1/* Parser for C and Objective-C.
2 Copyright (C) 1987-2026 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/* Holds data for deferred lookup of base functions for OpenMP
290 "begin declare variant", which are permitted to be declared after
291 the variant. */
292struct GTY(()) omp_begin_declare_variant_map_entry {
293 tree variant; /* The variant decl. */
294 tree id; /* Name of base function. */
295 tree ctx; /* The context selector associated with the variant. */
296};
297vec<omp_begin_declare_variant_map_entry, va_gc> *omp_begin_declare_variant_map;
298
299static tree omp_start_variant_function (c_declarator *, tree);
300static void omp_finish_variant_function (tree, tree, tree);
301
302/* Return a pointer to the Nth token in PARSERs tokens_buf. */
303
304c_token *
305c_parser_tokens_buf (c_parser *parser, unsigned n)
306{
307 return &parser->tokens_buf[n];
308}
309
310/* Return the error state of PARSER. */
311
312bool
313c_parser_error (c_parser *parser)
314{
315 return parser->error;
316}
317
318/* Set the error state of PARSER to ERR. */
319
320void
321c_parser_set_error (c_parser *parser, bool err)
322{
323 parser->error = err;
324}
325
326
327/* The actual parser and external interface. ??? Does this need to be
328 garbage-collected? */
329
330static GTY (()) c_parser *the_parser;
331
332/* Read in and lex a single token, storing it in *TOKEN. If RAW,
333 context-sensitive postprocessing of the token is not done. */
334
335static void
336c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
337{
338 timevar_push (tv: TV_LEX);
339
340 if (raw || vec_safe_length (v: parser->raw_tokens) == 0)
341 {
342 token->type = c_lex_with_flags (&token->value, &token->location,
343 &token->flags,
344 (parser->lex_joined_string
345 ? 0 : C_LEX_STRING_NO_JOIN));
346 token->id_kind = C_ID_NONE;
347 token->keyword = RID_MAX;
348 token->pragma_kind = PRAGMA_NONE;
349 }
350 else
351 {
352 /* Use a token previously lexed as a raw look-ahead token, and
353 complete the processing on it. */
354 *token = (*parser->raw_tokens)[parser->raw_tokens_used];
355 ++parser->raw_tokens_used;
356 if (parser->raw_tokens_used == vec_safe_length (v: parser->raw_tokens))
357 {
358 vec_free (v&: parser->raw_tokens);
359 parser->raw_tokens_used = 0;
360 }
361 }
362
363 if (raw)
364 goto out;
365
366 switch (token->type)
367 {
368 case CPP_NAME:
369 {
370 tree decl;
371
372 bool objc_force_identifier = parser->objc_need_raw_identifier;
373 if (c_dialect_objc ())
374 parser->objc_need_raw_identifier = false;
375
376 if (C_IS_RESERVED_WORD (token->value))
377 {
378 enum rid rid_code = C_RID_CODE (token->value);
379
380 if (rid_code == RID_CXX_COMPAT_WARN)
381 {
382 warning_at (token->location,
383 OPT_Wc___compat,
384 "identifier %qE conflicts with C++ keyword",
385 token->value);
386 }
387 else if (rid_code >= RID_FIRST_ADDR_SPACE
388 && rid_code <= RID_LAST_ADDR_SPACE)
389 {
390 addr_space_t as;
391 as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
392 targetm.addr_space.diagnose_usage (as, token->location);
393 token->id_kind = C_ID_ADDRSPACE;
394 token->keyword = rid_code;
395 break;
396 }
397 else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
398 {
399 /* We found an Objective-C "pq" keyword (in, out,
400 inout, bycopy, byref, oneway). They need special
401 care because the interpretation depends on the
402 context. */
403 if (parser->objc_pq_context)
404 {
405 token->type = CPP_KEYWORD;
406 token->keyword = rid_code;
407 break;
408 }
409 else if (parser->objc_could_be_foreach_context
410 && rid_code == RID_IN)
411 {
412 /* We are in Objective-C, inside a (potential)
413 foreach context (which means after having
414 parsed 'for (', but before having parsed ';'),
415 and we found 'in'. We consider it the keyword
416 which terminates the declaration at the
417 beginning of a foreach-statement. Note that
418 this means you can't use 'in' for anything else
419 in that context; in particular, in Objective-C
420 you can't use 'in' as the name of the running
421 variable in a C for loop. We could potentially
422 try to add code here to disambiguate, but it
423 seems a reasonable limitation. */
424 token->type = CPP_KEYWORD;
425 token->keyword = rid_code;
426 break;
427 }
428 /* Else, "pq" keywords outside of the "pq" context are
429 not keywords, and we fall through to the code for
430 normal tokens. */
431 }
432 else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
433 {
434 /* We found an Objective-C "property attribute"
435 keyword (getter, setter, readonly, etc). These are
436 only valid in the property context. */
437 if (parser->objc_property_attr_context)
438 {
439 token->type = CPP_KEYWORD;
440 token->keyword = rid_code;
441 break;
442 }
443 /* Else they are not special keywords.
444 */
445 }
446 else if (c_dialect_objc ()
447 && (OBJC_IS_AT_KEYWORD (rid_code)
448 || OBJC_IS_CXX_KEYWORD (rid_code)))
449 {
450 /* We found one of the Objective-C "@" keywords (defs,
451 selector, synchronized, etc) or one of the
452 Objective-C "cxx" keywords (class, private,
453 protected, public, try, catch, throw) without a
454 preceding '@' sign. Do nothing and fall through to
455 the code for normal tokens (in C++ we would still
456 consider the CXX ones keywords, but not in C). */
457 ;
458 }
459 else
460 {
461 token->type = CPP_KEYWORD;
462 token->keyword = rid_code;
463 break;
464 }
465 }
466
467 decl = lookup_name (token->value);
468 if (decl)
469 {
470 if (TREE_CODE (decl) == TYPE_DECL)
471 {
472 token->id_kind = C_ID_TYPENAME;
473 break;
474 }
475 }
476 else if (c_dialect_objc ())
477 {
478 tree objc_interface_decl = objc_is_class_name (token->value);
479 /* Objective-C class names are in the same namespace as
480 variables and typedefs, and hence are shadowed by local
481 declarations. */
482 if (objc_interface_decl
483 && (!objc_force_identifier || global_bindings_p ()))
484 {
485 token->value = objc_interface_decl;
486 token->id_kind = C_ID_CLASSNAME;
487 break;
488 }
489 }
490 token->id_kind = C_ID_ID;
491 }
492 break;
493 case CPP_AT_NAME:
494 /* This only happens in Objective-C; it must be a keyword. */
495 token->type = CPP_KEYWORD;
496 switch (C_RID_CODE (token->value))
497 {
498 /* Replace 'class' with '@class', 'private' with '@private',
499 etc. This prevents confusion with the C++ keyword
500 'class', and makes the tokens consistent with other
501 Objective-C 'AT' keywords. For example '@class' is
502 reported as RID_AT_CLASS which is consistent with
503 '@synchronized', which is reported as
504 RID_AT_SYNCHRONIZED.
505 */
506 case RID_CLASS: token->keyword = RID_AT_CLASS; break;
507 case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
508 case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
509 case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
510 case RID_THROW: token->keyword = RID_AT_THROW; break;
511 case RID_TRY: token->keyword = RID_AT_TRY; break;
512 case RID_CATCH: token->keyword = RID_AT_CATCH; break;
513 case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
514 default: token->keyword = C_RID_CODE (token->value);
515 }
516 break;
517 case CPP_COLON:
518 case CPP_COMMA:
519 case CPP_CLOSE_PAREN:
520 case CPP_SEMICOLON:
521 /* These tokens may affect the interpretation of any identifiers
522 following, if doing Objective-C. */
523 if (c_dialect_objc ())
524 parser->objc_need_raw_identifier = false;
525 break;
526 case CPP_PRAGMA:
527 /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
528 token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
529 token->value = NULL;
530 break;
531 default:
532 break;
533 }
534 out:
535 timevar_pop (tv: TV_LEX);
536}
537
538/* Return a pointer to the next token from PARSER, reading it in if
539 necessary. */
540
541c_token *
542c_parser_peek_token (c_parser *parser)
543{
544 if (parser->tokens_avail == 0)
545 {
546 c_lex_one_token (parser, token: &parser->tokens[0]);
547 parser->tokens_avail = 1;
548 }
549 return &parser->tokens[0];
550}
551
552/* Return a pointer to the next-but-one token from PARSER, reading it
553 in if necessary. The next token is already read in. */
554
555c_token *
556c_parser_peek_2nd_token (c_parser *parser)
557{
558 if (parser->tokens_avail >= 2)
559 return &parser->tokens[1];
560 gcc_assert (parser->tokens_avail == 1);
561 gcc_assert (parser->tokens[0].type != CPP_EOF);
562 gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
563 c_lex_one_token (parser, token: &parser->tokens[1]);
564 parser->tokens_avail = 2;
565 return &parser->tokens[1];
566}
567
568/* Return a pointer to the Nth token from PARSER, reading it
569 in if necessary. The N-1th token is already read in. */
570
571c_token *
572c_parser_peek_nth_token (c_parser *parser, unsigned int n)
573{
574 /* N is 1-based, not zero-based. */
575 gcc_assert (n > 0);
576
577 if (parser->tokens_avail >= n)
578 return &parser->tokens[n - 1];
579 gcc_assert (parser->tokens_avail == n - 1);
580 c_lex_one_token (parser, token: &parser->tokens[n - 1]);
581 parser->tokens_avail = n;
582 return &parser->tokens[n - 1];
583}
584
585/* Return a pointer to the Nth token from PARSER, reading it in as a
586 raw look-ahead token if necessary. The N-1th token is already read
587 in. Raw look-ahead tokens remain available for when the non-raw
588 functions above are called. */
589
590c_token *
591c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
592{
593 /* N is 1-based, not zero-based. */
594 gcc_assert (n > 0);
595
596 if (parser->tokens_avail >= n)
597 return &parser->tokens[n - 1];
598 unsigned int raw_len = vec_safe_length (v: parser->raw_tokens);
599 unsigned int raw_avail
600 = parser->tokens_avail + raw_len - parser->raw_tokens_used;
601 gcc_assert (raw_avail >= n - 1);
602 if (raw_avail >= n)
603 return &(*parser->raw_tokens)[parser->raw_tokens_used
604 + n - 1 - parser->tokens_avail];
605 vec_safe_reserve (v&: parser->raw_tokens, nelems: 1);
606 parser->raw_tokens->quick_grow (len: raw_len + 1);
607 c_lex_one_token (parser, token: &(*parser->raw_tokens)[raw_len], raw: true);
608 return &(*parser->raw_tokens)[raw_len];
609}
610
611bool
612c_keyword_starts_typename (enum rid keyword)
613{
614 switch (keyword)
615 {
616 case RID_UNSIGNED:
617 case RID_LONG:
618 case RID_SHORT:
619 case RID_SIGNED:
620 case RID_COMPLEX:
621 case RID_INT:
622 case RID_CHAR:
623 case RID_FLOAT:
624 case RID_DOUBLE:
625 case RID_VOID:
626 case RID_DFLOAT32:
627 case RID_DFLOAT64:
628 case RID_DFLOAT128:
629 case RID_DFLOAT64X:
630 CASE_RID_FLOATN_NX:
631 case RID_BOOL:
632 case RID_BITINT:
633 case RID_ENUM:
634 case RID_STRUCT:
635 case RID_UNION:
636 case RID_TYPEOF:
637 case RID_TYPEOF_UNQUAL:
638 case RID_CONST:
639 case RID_ATOMIC:
640 case RID_VOLATILE:
641 case RID_RESTRICT:
642 case RID_ATTRIBUTE:
643 case RID_FRACT:
644 case RID_ACCUM:
645 case RID_SAT:
646 case RID_AUTO_TYPE:
647 case RID_ALIGNAS:
648 return true;
649 default:
650 if (keyword >= RID_FIRST_INT_N
651 && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
652 && int_n_enabled_p[keyword - RID_FIRST_INT_N])
653 return true;
654 return false;
655 }
656}
657
658/* Return true if TOKEN can start a type name,
659 false otherwise. */
660bool
661c_token_starts_typename (c_token *token)
662{
663 switch (token->type)
664 {
665 case CPP_NAME:
666 switch (token->id_kind)
667 {
668 case C_ID_ID:
669 return false;
670 case C_ID_ADDRSPACE:
671 return true;
672 case C_ID_TYPENAME:
673 return true;
674 case C_ID_CLASSNAME:
675 gcc_assert (c_dialect_objc ());
676 return true;
677 default:
678 gcc_unreachable ();
679 }
680 case CPP_KEYWORD:
681 return c_keyword_starts_typename (keyword: token->keyword);
682 case CPP_LESS:
683 if (c_dialect_objc ())
684 return true;
685 return false;
686 default:
687 return false;
688 }
689}
690
691/* Return true if the next token from PARSER, starting from token N, can start
692 a type name, false otherwise. LA specifies how to do lookahead in order to
693 detect unknown type names. If unsure, pick CLA_PREFER_ID. */
694
695static inline bool
696c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la,
697 unsigned int n = 1)
698{
699 c_token *token = c_parser_peek_nth_token (parser, n);
700 if (c_token_starts_typename (token))
701 return true;
702
703 /* Try a bit harder to detect an unknown typename. */
704 if (la != cla_prefer_id
705 && token->type == CPP_NAME
706 && token->id_kind == C_ID_ID
707
708 /* Do not try too hard when we could have "object in array". */
709 && !parser->objc_could_be_foreach_context
710
711 && (la == cla_prefer_type
712 || c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_NAME
713 || c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_MULT)
714
715 /* Only unknown identifiers. */
716 && !lookup_name (token->value))
717 return true;
718
719 return false;
720}
721
722/* Return true if TOKEN, after an open parenthesis, can start a
723 compound literal (either a storage class specifier allowed in that
724 context, or a type name), false otherwise. */
725static bool
726c_token_starts_compound_literal (c_token *token)
727{
728 switch (token->type)
729 {
730 case CPP_KEYWORD:
731 switch (token->keyword)
732 {
733 case RID_CONSTEXPR:
734 case RID_REGISTER:
735 case RID_STATIC:
736 case RID_THREAD:
737 return true;
738 default:
739 break;
740 }
741 /* Fall through. */
742 default:
743 return c_token_starts_typename (token);
744 }
745}
746
747/* Return true if TOKEN is a type qualifier, false otherwise. */
748static bool
749c_token_is_qualifier (c_token *token)
750{
751 switch (token->type)
752 {
753 case CPP_NAME:
754 switch (token->id_kind)
755 {
756 case C_ID_ADDRSPACE:
757 return true;
758 default:
759 return false;
760 }
761 case CPP_KEYWORD:
762 switch (token->keyword)
763 {
764 case RID_CONST:
765 case RID_VOLATILE:
766 case RID_RESTRICT:
767 case RID_ATTRIBUTE:
768 case RID_ATOMIC:
769 return true;
770 default:
771 return false;
772 }
773 case CPP_LESS:
774 return false;
775 default:
776 gcc_unreachable ();
777 }
778}
779
780/* Return true if the next token from PARSER is a type qualifier,
781 false otherwise. */
782static inline bool
783c_parser_next_token_is_qualifier (c_parser *parser)
784{
785 c_token *token = c_parser_peek_token (parser);
786 return c_token_is_qualifier (token);
787}
788
789/* Return true if TOKEN can start declaration specifiers (not
790 including standard attributes), false otherwise. */
791static bool
792c_token_starts_declspecs (c_token *token)
793{
794 switch (token->type)
795 {
796 case CPP_NAME:
797 switch (token->id_kind)
798 {
799 case C_ID_ID:
800 return false;
801 case C_ID_ADDRSPACE:
802 return true;
803 case C_ID_TYPENAME:
804 return true;
805 case C_ID_CLASSNAME:
806 gcc_assert (c_dialect_objc ());
807 return true;
808 default:
809 gcc_unreachable ();
810 }
811 case CPP_KEYWORD:
812 switch (token->keyword)
813 {
814 case RID_STATIC:
815 case RID_EXTERN:
816 case RID_REGISTER:
817 case RID_TYPEDEF:
818 case RID_INLINE:
819 case RID_NORETURN:
820 case RID_AUTO:
821 case RID_THREAD:
822 case RID_UNSIGNED:
823 case RID_LONG:
824 case RID_SHORT:
825 case RID_SIGNED:
826 case RID_COMPLEX:
827 case RID_INT:
828 case RID_CHAR:
829 case RID_FLOAT:
830 case RID_DOUBLE:
831 case RID_VOID:
832 case RID_DFLOAT32:
833 case RID_DFLOAT64:
834 case RID_DFLOAT128:
835 case RID_DFLOAT64X:
836 CASE_RID_FLOATN_NX:
837 case RID_BOOL:
838 case RID_BITINT:
839 case RID_ENUM:
840 case RID_STRUCT:
841 case RID_UNION:
842 case RID_TYPEOF:
843 case RID_TYPEOF_UNQUAL:
844 case RID_CONST:
845 case RID_VOLATILE:
846 case RID_RESTRICT:
847 case RID_ATTRIBUTE:
848 case RID_FRACT:
849 case RID_ACCUM:
850 case RID_SAT:
851 case RID_ALIGNAS:
852 case RID_ATOMIC:
853 case RID_AUTO_TYPE:
854 case RID_CONSTEXPR:
855 return true;
856 default:
857 if (token->keyword >= RID_FIRST_INT_N
858 && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
859 && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
860 return true;
861 return false;
862 }
863 case CPP_LESS:
864 if (c_dialect_objc ())
865 return true;
866 return false;
867 default:
868 return false;
869 }
870}
871
872
873/* Return true if TOKEN can start declaration specifiers (not
874 including standard attributes) or a static assertion, false
875 otherwise. */
876static bool
877c_token_starts_declaration (c_token *token)
878{
879 if (c_token_starts_declspecs (token)
880 || token->keyword == RID_STATIC_ASSERT)
881 return true;
882 else
883 return false;
884}
885
886/* Return true if the next token from PARSER can start declaration
887 specifiers (not including standard attributes), false
888 otherwise. */
889bool
890c_parser_next_token_starts_declspecs (c_parser *parser)
891{
892 c_token *token = c_parser_peek_token (parser);
893
894 /* In Objective-C, a classname normally starts a declspecs unless it
895 is immediately followed by a dot. In that case, it is the
896 Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
897 setter/getter on the class. c_token_starts_declspecs() can't
898 differentiate between the two cases because it only checks the
899 current token, so we have a special check here. */
900 if (c_dialect_objc ()
901 && token->type == CPP_NAME
902 && token->id_kind == C_ID_CLASSNAME
903 && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
904 return false;
905
906 return c_token_starts_declspecs (token);
907}
908
909static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
910 unsigned int *);
911
912/* Return true if the next tokens from PARSER (starting with token N, 1-based)
913 can start declaration specifiers (not including standard attributes) or a
914 static assertion, false otherwise. */
915bool
916c_parser_next_tokens_start_declaration (c_parser *parser, unsigned int n)
917{
918 c_token *token = c_parser_peek_nth_token (parser, n);
919
920 /* Same as above. */
921 if (c_dialect_objc ()
922 && token->type == CPP_NAME
923 && token->id_kind == C_ID_CLASSNAME
924 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_DOT)
925 return false;
926
927 /* Labels do not start declarations. */
928 if (token->type == CPP_NAME
929 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_COLON)
930 return false;
931
932 /* A static assertion is only a declaration if followed by a semicolon;
933 otherwise, it may be an expression in C2Y. */
934 if (token->keyword == RID_STATIC_ASSERT
935 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_OPEN_PAREN)
936 {
937 n += 2;
938 if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
939 || c_parser_peek_nth_token_raw (parser, n)->type != CPP_CLOSE_PAREN)
940 /* Invalid static assertion syntax; treat as a declaration and report a
941 syntax error there. */
942 return true;
943 return c_parser_peek_nth_token_raw (parser, n: n + 1)->type == CPP_SEMICOLON;
944 }
945
946 if (c_token_starts_declaration (token))
947 return true;
948
949 if (c_parser_next_tokens_start_typename (parser, la: cla_nonabstract_decl, n))
950 return true;
951
952 return false;
953}
954
955/* Consume the next token from PARSER. */
956
957void
958c_parser_consume_token (c_parser *parser)
959{
960 gcc_assert (parser->tokens_avail >= 1);
961 gcc_assert (parser->tokens[0].type != CPP_EOF);
962 gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
963 gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
964 parser->last_token_location = parser->tokens[0].location;
965 if (parser->tokens != &parser->tokens_buf[0])
966 parser->tokens++;
967 else if (parser->tokens_avail >= 2)
968 {
969 parser->tokens[0] = parser->tokens[1];
970 if (parser->tokens_avail >= 3)
971 {
972 parser->tokens[1] = parser->tokens[2];
973 if (parser->tokens_avail >= 4)
974 parser->tokens[2] = parser->tokens[3];
975 }
976 }
977 parser->tokens_avail--;
978 parser->seen_string_literal = false;
979}
980
981/* Expect the current token to be a #pragma. Consume it and remember
982 that we've begun parsing a pragma. */
983
984static void
985c_parser_consume_pragma (c_parser *parser)
986{
987 gcc_assert (!parser->in_pragma);
988 gcc_assert (parser->tokens_avail >= 1);
989 gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
990 if (parser->tokens != &parser->tokens_buf[0])
991 parser->tokens++;
992 else if (parser->tokens_avail >= 2)
993 {
994 parser->tokens[0] = parser->tokens[1];
995 if (parser->tokens_avail >= 3)
996 parser->tokens[1] = parser->tokens[2];
997 }
998 parser->tokens_avail--;
999 parser->in_pragma = true;
1000}
1001
1002/* Update the global input_location from TOKEN. */
1003static inline void
1004c_parser_set_source_position_from_token (c_token *token)
1005{
1006 if (token->type != CPP_EOF)
1007 {
1008 input_location = token->location;
1009 }
1010}
1011
1012/* Helper function for c_parser_error.
1013 Having peeked a token of kind TOK1_KIND that might signify
1014 a conflict marker, peek successor tokens to determine
1015 if we actually do have a conflict marker.
1016 Specifically, we consider a run of 7 '<', '=' or '>' characters
1017 at the start of a line as a conflict marker.
1018 These come through the lexer as three pairs and a single,
1019 e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
1020 If it returns true, *OUT_LOC is written to with the location/range
1021 of the marker. */
1022
1023static bool
1024c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
1025 location_t *out_loc)
1026{
1027 c_token *token2 = c_parser_peek_2nd_token (parser);
1028 if (token2->type != tok1_kind)
1029 return false;
1030 c_token *token3 = c_parser_peek_nth_token (parser, n: 3);
1031 if (token3->type != tok1_kind)
1032 return false;
1033 c_token *token4 = c_parser_peek_nth_token (parser, n: 4);
1034 if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
1035 return false;
1036
1037 /* It must be at the start of the line. */
1038 location_t start_loc = c_parser_peek_token (parser)->location;
1039 if (LOCATION_COLUMN (start_loc) != 1)
1040 return false;
1041
1042 /* We have a conflict marker. Construct a location of the form:
1043 <<<<<<<
1044 ^~~~~~~
1045 with start == caret, finishing at the end of the marker. */
1046 location_t finish_loc = get_finish (loc: token4->location);
1047 *out_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc);
1048
1049 return true;
1050}
1051
1052/* Issue a diagnostic of the form
1053 FILE:LINE: MESSAGE before TOKEN
1054 where TOKEN is the next token in the input stream of PARSER.
1055 MESSAGE (specified by the caller) is usually of the form "expected
1056 OTHER-TOKEN".
1057
1058 Use RICHLOC as the location of the diagnostic.
1059
1060 Do not issue a diagnostic if still recovering from an error.
1061
1062 Return true iff an error was actually emitted.
1063
1064 ??? This is taken from the C++ parser, but building up messages in
1065 this way is not i18n-friendly and some other approach should be
1066 used. */
1067
1068static bool
1069c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1070 rich_location *richloc)
1071{
1072 c_token *token = c_parser_peek_token (parser);
1073 if (parser->error)
1074 return false;
1075 parser->error = true;
1076 if (!gmsgid)
1077 return false;
1078
1079 /* If this is actually a conflict marker, report it as such. */
1080 if (token->type == CPP_LSHIFT
1081 || token->type == CPP_RSHIFT
1082 || token->type == CPP_EQ_EQ)
1083 {
1084 location_t loc;
1085 if (c_parser_peek_conflict_marker (parser, tok1_kind: token->type, out_loc: &loc))
1086 {
1087 error_at (loc, "version control conflict marker in file");
1088 return true;
1089 }
1090 }
1091
1092 /* If we were parsing a string-literal and there is an unknown name
1093 token right after, then check to see if that could also have been
1094 a literal string by checking the name against a list of known
1095 standard string literal constants defined in header files. If
1096 there is one, then add that as an hint to the error message. */
1097 auto_diagnostic_group d;
1098 name_hint h;
1099 if (parser->seen_string_literal && token->type == CPP_NAME)
1100 {
1101 tree name = token->value;
1102 const char *token_name = IDENTIFIER_POINTER (name);
1103 const char *header_hint
1104 = get_c_stdlib_header_for_string_macro_name (n: token_name);
1105 if (header_hint != NULL)
1106 h = name_hint (nullptr,
1107 std::make_unique<suggest_missing_header>
1108 (args&: token->location,
1109 args&: token_name,
1110 args&: header_hint));
1111 }
1112
1113 c_parse_error (gmsgid,
1114 /* Because c_parse_error does not understand
1115 CPP_KEYWORD, keywords are treated like
1116 identifiers. */
1117 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
1118 /* ??? The C parser does not save the cpp flags of a
1119 token, we need to pass 0 here and we will not get
1120 the source spelling of some tokens but rather the
1121 canonical spelling. */
1122 token->value, /*flags=*/0, richloc);
1123 return true;
1124}
1125
1126/* As c_parser_error_richloc, but issue the message at the
1127 location of PARSER's next token, or at input_location
1128 if the next token is EOF. */
1129
1130bool
1131c_parser_error (c_parser *parser, const char *gmsgid)
1132{
1133 c_token *token = c_parser_peek_token (parser);
1134 c_parser_set_source_position_from_token (token);
1135 rich_location richloc (line_table, input_location);
1136 return c_parser_error_richloc (parser, gmsgid, richloc: &richloc);
1137}
1138
1139/* Some tokens naturally come in pairs e.g.'(' and ')'.
1140 This class is for tracking such a matching pair of symbols.
1141 In particular, it tracks the location of the first token,
1142 so that if the second token is missing, we can highlight the
1143 location of the first token when notifying the user about the
1144 problem. */
1145
1146template <typename traits_t>
1147class token_pair
1148{
1149 public:
1150 /* token_pair's ctor. */
1151 token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
1152
1153 /* If the next token is the opening symbol for this pair, consume it and
1154 return true.
1155 Otherwise, issue an error and return false.
1156 In either case, record the location of the opening token. */
1157
1158 bool require_open (c_parser *parser)
1159 {
1160 c_token *token = c_parser_peek_token (parser);
1161 if (token)
1162 m_open_loc = token->location;
1163
1164 return c_parser_require (parser, traits_t::open_token_type,
1165 traits_t::open_gmsgid);
1166 }
1167
1168 /* Consume the next token from PARSER, recording its location as
1169 that of the opening token within the pair. */
1170
1171 void consume_open (c_parser *parser)
1172 {
1173 c_token *token = c_parser_peek_token (parser);
1174 gcc_assert (token->type == traits_t::open_token_type);
1175 m_open_loc = token->location;
1176 c_parser_consume_token (parser);
1177 }
1178
1179 /* If the next token is the closing symbol for this pair, consume it
1180 and return true.
1181 Otherwise, issue an error, highlighting the location of the
1182 corresponding opening token, and return false. */
1183
1184 bool require_close (c_parser *parser) const
1185 {
1186 return c_parser_require (parser, traits_t::close_token_type,
1187 traits_t::close_gmsgid, m_open_loc);
1188 }
1189
1190 /* Like token_pair::require_close, except that tokens will be skipped
1191 until the desired token is found. An error message is still produced
1192 if the next token is not as expected. */
1193
1194 void skip_until_found_close (c_parser *parser) const
1195 {
1196 c_parser_skip_until_found (parser, traits_t::close_token_type,
1197 traits_t::close_gmsgid, m_open_loc);
1198 }
1199
1200 private:
1201 location_t m_open_loc;
1202};
1203
1204/* Traits for token_pair<T> for tracking matching pairs of parentheses. */
1205
1206struct matching_paren_traits
1207{
1208 static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
1209 static const char * const open_gmsgid;
1210 static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
1211 static const char * const close_gmsgid;
1212};
1213
1214const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
1215const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
1216
1217/* "matching_parens" is a token_pair<T> class for tracking matching
1218 pairs of parentheses. */
1219
1220typedef token_pair<matching_paren_traits> matching_parens;
1221
1222/* Traits for token_pair<T> for tracking matching pairs of braces. */
1223
1224struct matching_brace_traits
1225{
1226 static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
1227 static const char * const open_gmsgid;
1228 static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
1229 static const char * const close_gmsgid;
1230};
1231
1232const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
1233const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
1234
1235/* "matching_braces" is a token_pair<T> class for tracking matching
1236 pairs of braces. */
1237
1238typedef token_pair<matching_brace_traits> matching_braces;
1239
1240/* Get a description of the matching symbol to TYPE e.g. "(" for
1241 CPP_CLOSE_PAREN. */
1242
1243static const char *
1244get_matching_symbol (enum cpp_ttype type)
1245{
1246 switch (type)
1247 {
1248 default:
1249 gcc_unreachable ();
1250 case CPP_CLOSE_PAREN:
1251 return "(";
1252 case CPP_CLOSE_BRACE:
1253 return "{";
1254 }
1255}
1256
1257/* If the next token is of the indicated TYPE, consume it. Otherwise,
1258 issue the error MSGID. If MSGID is NULL then a message has already
1259 been produced and no message will be produced this time. Returns
1260 true if found, false otherwise.
1261
1262 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1263 within any error as the location of an "opening" token matching
1264 the close token TYPE (e.g. the location of the '(' when TYPE is
1265 CPP_CLOSE_PAREN).
1266
1267 If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
1268 one type (e.g. "expected %<)%>") and thus it may be reasonable to
1269 attempt to generate a fix-it hint for the problem.
1270 Otherwise msgid describes multiple token types (e.g.
1271 "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
1272 generate a fix-it hint. */
1273
1274bool
1275c_parser_require (c_parser *parser,
1276 enum cpp_ttype type,
1277 const char *msgid,
1278 location_t matching_location,
1279 bool type_is_unique)
1280{
1281 if (c_parser_next_token_is (parser, type))
1282 {
1283 c_parser_consume_token (parser);
1284 return true;
1285 }
1286 else
1287 {
1288 location_t next_token_loc = c_parser_peek_token (parser)->location;
1289 gcc_rich_location richloc (next_token_loc);
1290
1291 /* Potentially supply a fix-it hint, suggesting to add the
1292 missing token immediately after the *previous* token.
1293 This may move the primary location within richloc. */
1294 if (!parser->error && type_is_unique)
1295 maybe_suggest_missing_token_insertion (richloc: &richloc, token_type: type,
1296 prev_token_loc: parser->last_token_location);
1297
1298 /* If matching_location != UNKNOWN_LOCATION, highlight it.
1299 Attempt to consolidate diagnostics by printing it as a
1300 secondary range within the main diagnostic. */
1301 bool added_matching_location = false;
1302 if (matching_location != UNKNOWN_LOCATION)
1303 added_matching_location
1304 = richloc.add_location_if_nearby (dc: *global_dc, loc: matching_location);
1305
1306 if (c_parser_error_richloc (parser, gmsgid: msgid, richloc: &richloc))
1307 /* If we weren't able to consolidate matching_location, then
1308 print it as a secondary diagnostic. */
1309 if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1310 inform (matching_location, "to match this %qs",
1311 get_matching_symbol (type));
1312
1313 return false;
1314 }
1315}
1316
1317/* If the next token is the indicated keyword, consume it. Otherwise,
1318 issue the error MSGID. Returns true if found, false otherwise. */
1319
1320static bool
1321c_parser_require_keyword (c_parser *parser,
1322 enum rid keyword,
1323 const char *msgid)
1324{
1325 if (c_parser_next_token_is_keyword (parser, keyword))
1326 {
1327 c_parser_consume_token (parser);
1328 return true;
1329 }
1330 else
1331 {
1332 c_parser_error (parser, gmsgid: msgid);
1333 return false;
1334 }
1335}
1336
1337/* Like c_parser_require, except that tokens will be skipped until the
1338 desired token is found. An error message is still produced if the
1339 next token is not as expected. If MSGID is NULL then a message has
1340 already been produced and no message will be produced this
1341 time.
1342
1343 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1344 within any error as the location of an "opening" token matching
1345 the close token TYPE (e.g. the location of the '(' when TYPE is
1346 CPP_CLOSE_PAREN). */
1347
1348void
1349c_parser_skip_until_found (c_parser *parser,
1350 enum cpp_ttype type,
1351 const char *msgid,
1352 location_t matching_location)
1353{
1354 unsigned nesting_depth = 0;
1355
1356 if (c_parser_require (parser, type, msgid, matching_location))
1357 {
1358 if (UNLIKELY (type == CPP_PRAGMA_EOL) && parser->in_omp_attribute_pragma)
1359 {
1360 c_token *token = c_parser_peek_token (parser);
1361 if (token->type == CPP_EOF)
1362 {
1363 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1364 parser->tokens_avail
1365 = parser->in_omp_attribute_pragma->save_tokens_avail;
1366 parser->in_omp_attribute_pragma = NULL;
1367 }
1368 }
1369 return;
1370 }
1371
1372 /* Skip tokens until the desired token is found. */
1373 while (true)
1374 {
1375 /* Peek at the next token. */
1376 c_token *token = c_parser_peek_token (parser);
1377 /* If we've reached the token we want, consume it and stop. */
1378 if (token->type == type && !nesting_depth)
1379 {
1380 c_parser_consume_token (parser);
1381 if (UNLIKELY (type == CPP_PRAGMA_EOL)
1382 && parser->in_omp_attribute_pragma)
1383 {
1384 c_token *token = c_parser_peek_token (parser);
1385 if (token->type == CPP_EOF)
1386 {
1387 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1388 parser->tokens_avail
1389 = parser->in_omp_attribute_pragma->save_tokens_avail;
1390 parser->in_omp_attribute_pragma = NULL;
1391 }
1392 }
1393 break;
1394 }
1395
1396 /* If we've run out of tokens, stop. */
1397 if (token->type == CPP_EOF)
1398 return;
1399 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1400 return;
1401 if (token->type == CPP_OPEN_BRACE
1402 || token->type == CPP_OPEN_PAREN
1403 || token->type == CPP_OPEN_SQUARE)
1404 ++nesting_depth;
1405 else if (token->type == CPP_CLOSE_BRACE
1406 || token->type == CPP_CLOSE_PAREN
1407 || token->type == CPP_CLOSE_SQUARE)
1408 {
1409 if (nesting_depth-- == 0)
1410 break;
1411 }
1412 /* Consume this token. */
1413 c_parser_consume_token (parser);
1414 }
1415 parser->error = false;
1416}
1417
1418/* Skip tokens until the end of a parameter is found, but do not
1419 consume the comma, semicolon or closing delimiter. */
1420
1421static void
1422c_parser_skip_to_end_of_parameter (c_parser *parser)
1423{
1424 unsigned nesting_depth = 0;
1425
1426 while (true)
1427 {
1428 c_token *token = c_parser_peek_token (parser);
1429 if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1430 && !nesting_depth)
1431 break;
1432 /* If we've run out of tokens, stop. */
1433 if (token->type == CPP_EOF)
1434 return;
1435 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1436 return;
1437 if (token->type == CPP_OPEN_BRACE
1438 || token->type == CPP_OPEN_PAREN
1439 || token->type == CPP_OPEN_SQUARE)
1440 ++nesting_depth;
1441 else if (token->type == CPP_CLOSE_BRACE
1442 || token->type == CPP_CLOSE_PAREN
1443 || token->type == CPP_CLOSE_SQUARE)
1444 {
1445 if (nesting_depth-- == 0)
1446 break;
1447 }
1448 /* Consume this token. */
1449 c_parser_consume_token (parser);
1450 }
1451 parser->error = false;
1452}
1453
1454/* Skip tokens until a non-nested closing curly brace is the next
1455 token, or there are no more tokens. Return true in the first case,
1456 false otherwise. */
1457
1458static bool
1459c_parser_skip_to_closing_brace (c_parser *parser)
1460{
1461 unsigned nesting_depth = 0;
1462
1463 while (true)
1464 {
1465 c_token *token = c_parser_peek_token (parser);
1466
1467 switch (token->type)
1468 {
1469 case CPP_PRAGMA_EOL:
1470 if (!parser->in_pragma)
1471 break;
1472 /* FALLTHRU */
1473 case CPP_EOF:
1474 /* If we've run out of tokens, stop. */
1475 return false;
1476
1477 case CPP_CLOSE_BRACE:
1478 /* If the next token is a non-nested `}', then we have reached
1479 the end of the current block. */
1480 if (nesting_depth-- == 0)
1481 return true;
1482 break;
1483
1484 case CPP_OPEN_BRACE:
1485 /* If it the next token is a `{', then we are entering a new
1486 block. Consume the entire block. */
1487 ++nesting_depth;
1488 break;
1489
1490 default:
1491 break;
1492 }
1493
1494 /* Consume the token. */
1495 c_parser_consume_token (parser);
1496 }
1497}
1498
1499/* Expect to be at the end of the pragma directive and consume an
1500 end of line marker. */
1501
1502static void
1503c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1504{
1505 gcc_assert (parser->in_pragma);
1506 parser->in_pragma = false;
1507
1508 if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
1509 c_parser_error (parser, gmsgid: "expected end of line");
1510
1511 cpp_ttype token_type;
1512 do
1513 {
1514 c_token *token = c_parser_peek_token (parser);
1515 token_type = token->type;
1516 if (token_type == CPP_EOF)
1517 break;
1518 c_parser_consume_token (parser);
1519 }
1520 while (token_type != CPP_PRAGMA_EOL);
1521
1522 if (parser->in_omp_attribute_pragma)
1523 {
1524 c_token *token = c_parser_peek_token (parser);
1525 if (token->type == CPP_EOF)
1526 {
1527 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1528 parser->tokens_avail
1529 = parser->in_omp_attribute_pragma->save_tokens_avail;
1530 parser->in_omp_attribute_pragma = NULL;
1531 }
1532 }
1533
1534 parser->error = false;
1535}
1536
1537/* Skip tokens up to and including "#pragma omp end declare variant".
1538 Properly handle nested "#pragma omp begin declare variant" pragmas. */
1539static void
1540c_parser_skip_to_pragma_omp_end_declare_variant (c_parser *parser)
1541{
1542 for (int depth = 0; depth >= 0; )
1543 {
1544 c_token *token = c_parser_peek_token (parser);
1545
1546 switch (token->type)
1547 {
1548 case CPP_PRAGMA_EOL:
1549 if (!parser->in_pragma)
1550 break;
1551 /* FALLTHRU */
1552 case CPP_EOF:
1553 /* If we've run out of tokens, stop. */
1554 return;
1555
1556 case CPP_PRAGMA:
1557 if ((token->pragma_kind == PRAGMA_OMP_BEGIN
1558 || token->pragma_kind == PRAGMA_OMP_END)
1559 && c_parser_peek_nth_token (parser, n: 2)->type == CPP_NAME
1560 && c_parser_peek_nth_token (parser, n: 3)->type == CPP_NAME)
1561 {
1562 tree id1 = c_parser_peek_nth_token (parser, n: 2)->value;
1563 tree id2 = c_parser_peek_nth_token (parser, n: 3)->value;
1564 if (strcmp (IDENTIFIER_POINTER (id1), s2: "declare") == 0
1565 && strcmp (IDENTIFIER_POINTER (id2), s2: "variant") == 0)
1566 {
1567 if (token->pragma_kind == PRAGMA_OMP_BEGIN)
1568 depth++;
1569 else
1570 depth--;
1571 }
1572 }
1573 c_parser_consume_pragma (parser);
1574 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
1575 continue;
1576
1577 default:
1578 break;
1579 }
1580
1581 /* Consume the token. */
1582 c_parser_consume_token (parser);
1583 }
1584}
1585
1586/* Skip tokens until we have consumed an entire block, or until we
1587 have consumed a non-nested ';'. */
1588
1589static void
1590c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
1591 bool metadirective_p = false)
1592{
1593 unsigned nesting_depth = 0;
1594 int bracket_depth = 0;
1595 bool save_error = parser->error;
1596
1597 while (true)
1598 {
1599 c_token *token;
1600
1601 /* Peek at the next token. */
1602 token = c_parser_peek_token (parser);
1603
1604 switch (token->type)
1605 {
1606 case CPP_EOF:
1607 return;
1608
1609 case CPP_PRAGMA_EOL:
1610 if (parser->in_pragma)
1611 return;
1612 break;
1613
1614 case CPP_SEMICOLON:
1615 /* If the next token is a ';', we have reached the
1616 end of the statement. */
1617 if (!nesting_depth && (!metadirective_p || bracket_depth <= 0))
1618 {
1619 /* Consume the ';'. */
1620 c_parser_consume_token (parser);
1621 goto finished;
1622 }
1623 break;
1624
1625 case CPP_CLOSE_BRACE:
1626 /* If the next token is a non-nested '}', then we have
1627 reached the end of the current block. */
1628 if ((nesting_depth == 0 || --nesting_depth == 0)
1629 && (!metadirective_p || bracket_depth <= 0))
1630 {
1631 c_parser_consume_token (parser);
1632 goto finished;
1633 }
1634 break;
1635
1636 case CPP_OPEN_BRACE:
1637 /* If it the next token is a '{', then we are entering a new
1638 block. Consume the entire block. */
1639 ++nesting_depth;
1640 break;
1641
1642 case CPP_OPEN_PAREN:
1643 /* Track parentheses in case the statement is a standalone 'for'
1644 statement - we want to skip over the semicolons separating the
1645 operands. */
1646 if (metadirective_p && nesting_depth == 0)
1647 ++bracket_depth;
1648 break;
1649
1650 case CPP_CLOSE_PAREN:
1651 if (metadirective_p && nesting_depth == 0)
1652 --bracket_depth;
1653 break;
1654
1655 case CPP_PRAGMA:
1656 /* If we see a pragma, consume the whole thing at once. We
1657 have some safeguards against consuming pragmas willy-nilly.
1658 Normally, we'd expect to be here with parser->error set,
1659 which disables these safeguards. But it's possible to get
1660 here for secondary error recovery, after parser->error has
1661 been cleared. */
1662 c_parser_consume_pragma (parser);
1663 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
1664 parser->error = save_error;
1665 continue;
1666
1667 default:
1668 break;
1669 }
1670
1671 c_parser_consume_token (parser);
1672 }
1673
1674 finished:
1675 parser->error = false;
1676}
1677
1678/* CPP's options (initialized by c-opts.cc). */
1679extern cpp_options *cpp_opts;
1680
1681/* Save the warning flags which are controlled by __extension__. */
1682
1683static inline int
1684disable_extension_diagnostics (void)
1685{
1686 int ret = (pedantic
1687 | (warn_pointer_arith << 1)
1688 | (warn_traditional << 2)
1689 | (flag_iso << 3)
1690 | (warn_long_long << 4)
1691 | (warn_cxx_compat << 5)
1692 | (warn_overlength_strings << 6)
1693 /* warn_c90_c99_compat has three states: -1/0/1, so we must
1694 play tricks to properly restore it. */
1695 | ((warn_c90_c99_compat == 1) << 7)
1696 | ((warn_c90_c99_compat == -1) << 8)
1697 /* Similarly for warn_c99_c11_compat. */
1698 | ((warn_c99_c11_compat == 1) << 9)
1699 | ((warn_c99_c11_compat == -1) << 10)
1700 /* Similarly for warn_c11_c23_compat. */
1701 | ((warn_c11_c23_compat == 1) << 11)
1702 | ((warn_c11_c23_compat == -1) << 12)
1703 /* Similarly for warn_c23_c2y_compat. */
1704 | ((warn_c23_c2y_compat == 1) << 13)
1705 | ((warn_c23_c2y_compat == -1) << 14)
1706 );
1707 cpp_opts->cpp_pedantic = pedantic = 0;
1708 warn_pointer_arith = 0;
1709 cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1710 flag_iso = 0;
1711 cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1712 warn_cxx_compat = 0;
1713 warn_overlength_strings = 0;
1714 warn_c90_c99_compat = 0;
1715 warn_c99_c11_compat = 0;
1716 warn_c11_c23_compat = 0;
1717 warn_c23_c2y_compat = 0;
1718 return ret;
1719}
1720
1721/* Restore the warning flags which are controlled by __extension__.
1722 FLAGS is the return value from disable_extension_diagnostics. */
1723
1724static inline void
1725restore_extension_diagnostics (int flags)
1726{
1727 cpp_opts->cpp_pedantic = pedantic = flags & 1;
1728 warn_pointer_arith = (flags >> 1) & 1;
1729 cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1730 flag_iso = (flags >> 3) & 1;
1731 cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1732 warn_cxx_compat = (flags >> 5) & 1;
1733 warn_overlength_strings = (flags >> 6) & 1;
1734 /* See above for why is this needed. */
1735 warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1736 warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1737 warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1738 warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
1739}
1740
1741/* Helper data structure for parsing #pragma acc routine. */
1742struct oacc_routine_data {
1743 bool error_seen; /* Set if error has been reported. */
1744 bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
1745 tree clauses;
1746 location_t loc;
1747};
1748
1749/* Used for parsing objc foreach statements. */
1750static tree objc_foreach_break_label, objc_foreach_continue_label;
1751
1752/* Used for parsing OMP for loops.
1753
1754 Some notes on flags used for context:
1755 parser->omp_for_parse_state is non-null anywhere inside the OMP FOR
1756 construct, except for the final-loop-body.
1757 The want_nested_loop flag is true if inside a {} sequence where
1758 a loop-nest (or another {} sequence containing a loop-nest) is expected,
1759 but has not yet been seen. It's false when parsing intervening code
1760 statements or their substatements that cannot contain a loop-nest.
1761 The in_intervening_code flag is true when parsing any intervening code,
1762 including substatements, and whether or not want_nested_loop is true.
1763
1764 And, about error handling:
1765 The saw_intervening_code flag is set if the loop is not perfectly
1766 nested, even in the usual case where this is not an error.
1767 perfect_nesting_fail is set if an error has been diagnosed because an
1768 imperfectly-nested loop was found where a perfectly-nested one is
1769 required (we diagnose this only once).
1770 fail is set if any kind of structural error in the loop nest
1771 has been found and diagnosed.
1772 */
1773struct omp_for_parse_data {
1774 enum tree_code code;
1775 tree declv, condv, incrv, initv;
1776 tree pre_body;
1777 tree bindings;
1778 int count; /* Expected nesting depth. */
1779 int depth; /* Current nesting depth. */
1780 location_t for_loc;
1781 bool ordered : 1;
1782 bool inscan : 1;
1783 bool want_nested_loop : 1;
1784 bool in_intervening_code : 1;
1785 bool saw_intervening_code: 1;
1786 bool perfect_nesting_fail : 1;
1787 bool fail : 1;
1788};
1789
1790struct attr_state
1791{
1792 /* True if we parsed a musttail attribute for return. */
1793 bool musttail_p;
1794};
1795
1796static bool c_parser_nth_token_starts_std_attributes (c_parser *,
1797 unsigned int);
1798static tree c_parser_std_attribute_specifier_sequence (c_parser *);
1799static void c_parser_external_declaration (c_parser *);
1800static void c_parser_asm_definition (c_parser *);
1801static tree c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
1802 bool, bool, bool, tree * = NULL,
1803 vec<c_token> * = NULL,
1804 bool have_attrs = false,
1805 tree attrs = NULL,
1806 struct oacc_routine_data * = NULL,
1807 bool * = NULL);
1808static bool c_parser_handle_statement_omp_attributes (c_parser *, tree &,
1809 bool *);
1810static void c_parser_static_assert_declaration_no_semi (c_parser *);
1811static void c_parser_static_assert_declaration (c_parser *);
1812static struct c_typespec c_parser_enum_specifier (c_parser *);
1813static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
1814static tree c_parser_struct_declaration (c_parser *, tree *);
1815static struct c_typespec c_parser_typeof_specifier (c_parser *);
1816static tree c_parser_alignas_specifier (c_parser *);
1817static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
1818 c_dtr_syn, bool *);
1819static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
1820 bool,
1821 struct c_declarator *);
1822static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
1823 bool);
1824static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
1825 tree, bool);
1826static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
1827static tree c_parser_asm_string_literal (c_parser *);
1828static tree c_parser_simple_asm_expr (c_parser *);
1829static tree c_parser_gnu_attributes (c_parser *);
1830static struct c_expr c_parser_initializer (c_parser *, tree);
1831static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
1832 struct obstack *, bool);
1833static void c_parser_initelt (c_parser *, struct obstack *);
1834static void c_parser_initval (c_parser *, struct c_expr *,
1835 struct obstack *);
1836static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
1837static location_t c_parser_compound_statement_nostart (c_parser *);
1838static void c_parser_label (c_parser *, tree);
1839static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
1840static void c_parser_statement_after_labels (c_parser *, bool *, tree,
1841 vec<tree> * = NULL,
1842 attr_state = {});
1843static tree c_parser_c99_block_statement (c_parser *, bool *,
1844 location_t * = NULL);
1845static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
1846static void c_parser_switch_statement (c_parser *, bool *, tree);
1847static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
1848 bool *, tree);
1849static void c_parser_do_statement (c_parser *, bool, unsigned short, bool,
1850 tree);
1851static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
1852 bool *, tree);
1853static tree c_parser_asm_statement (c_parser *);
1854static tree c_parser_asm_operands (c_parser *);
1855static tree c_parser_asm_goto_operands (c_parser *);
1856static tree c_parser_asm_clobbers (c_parser *);
1857static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
1858 tree = NULL_TREE);
1859static struct c_expr c_parser_conditional_expression (c_parser *,
1860 struct c_expr *, tree);
1861static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
1862 tree);
1863static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
1864static struct c_expr c_parser_unary_expression (c_parser *);
1865static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
1866 enum rid);
1867static struct c_expr c_parser_alignof_expression (c_parser *);
1868static struct c_expr c_parser_maxof_or_minof_expression (c_parser *, enum rid);
1869static struct c_expr c_parser_postfix_expression (c_parser *);
1870static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
1871 struct c_declspecs *,
1872 struct c_type_name *,
1873 location_t);
1874static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
1875 location_t loc,
1876 struct c_expr);
1877static tree c_parser_transaction (c_parser *, enum rid);
1878static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
1879static tree c_parser_transaction_cancel (c_parser *);
1880static struct c_expr c_parser_expression (c_parser *);
1881static struct c_expr c_parser_expression_conv (c_parser *);
1882static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
1883 vec<tree, va_gc> **, location_t *,
1884 tree *, vec<location_t> *,
1885 unsigned int * = NULL);
1886static struct c_expr c_parser_has_attribute_expression (c_parser *);
1887
1888static void c_parser_oacc_declare (c_parser *);
1889static void c_parser_oacc_enter_exit_data (c_parser *, bool);
1890static void c_parser_oacc_update (c_parser *);
1891static void c_parser_omp_construct (c_parser *, bool *);
1892static void c_parser_omp_groupprivate (c_parser *);
1893static void c_parser_omp_threadprivate (c_parser *);
1894static void c_parser_omp_barrier (c_parser *);
1895static void c_parser_omp_depobj (c_parser *);
1896static void c_parser_omp_flush (c_parser *);
1897static bool c_parser_omp_next_tokens_can_be_canon_loop (c_parser *,
1898 enum tree_code, bool);
1899static tree c_parser_omp_loop_nest (c_parser *, bool *);
1900static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
1901 tree, tree *, bool *);
1902static void c_parser_omp_taskwait (c_parser *);
1903static void c_parser_omp_taskyield (c_parser *);
1904static void c_parser_omp_cancel (c_parser *);
1905static void c_parser_omp_nothing (c_parser *);
1906static void c_parser_omp_metadirective (c_parser *, bool *);
1907
1908enum pragma_context { pragma_external, pragma_struct, pragma_param,
1909 pragma_stmt, pragma_compound };
1910static bool c_parser_pragma (c_parser *, enum pragma_context, bool *, tree);
1911static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
1912static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
1913static void c_parser_omp_begin (c_parser *);
1914static void c_parser_omp_end (c_parser *);
1915static bool c_parser_omp_declare (c_parser *, enum pragma_context);
1916static void c_parser_omp_requires (c_parser *);
1917static bool c_parser_omp_error (c_parser *, enum pragma_context);
1918static void c_parser_omp_assumption_clauses (c_parser *, bool);
1919static void c_parser_omp_allocate (c_parser *);
1920static void c_parser_omp_assumes (c_parser *);
1921static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
1922static tree c_parser_omp_dispatch (location_t, c_parser *);
1923static void c_parser_omp_interop (c_parser *);
1924static void c_parser_oacc_routine (c_parser *, enum pragma_context);
1925
1926/* These Objective-C parser functions are only ever called when
1927 compiling Objective-C. */
1928static void c_parser_objc_class_definition (c_parser *, tree);
1929static void c_parser_objc_class_instance_variables (c_parser *);
1930static void c_parser_objc_class_declaration (c_parser *);
1931static void c_parser_objc_alias_declaration (c_parser *);
1932static void c_parser_objc_protocol_definition (c_parser *, tree);
1933static bool c_parser_objc_method_type (c_parser *);
1934static void c_parser_objc_method_definition (c_parser *);
1935static void c_parser_objc_methodprotolist (c_parser *);
1936static void c_parser_objc_methodproto (c_parser *);
1937static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
1938static tree c_parser_objc_type_name (c_parser *);
1939static tree c_parser_objc_protocol_refs (c_parser *);
1940static void c_parser_objc_try_catch_finally_statement (c_parser *);
1941static void c_parser_objc_synchronized_statement (c_parser *);
1942static tree c_parser_objc_selector (c_parser *);
1943static tree c_parser_objc_selector_arg (c_parser *);
1944static tree c_parser_objc_receiver (c_parser *);
1945static tree c_parser_objc_message_args (c_parser *);
1946static tree c_parser_objc_keywordexpr (c_parser *);
1947static void c_parser_objc_at_property_declaration (c_parser *);
1948static void c_parser_objc_at_synthesize_declaration (c_parser *);
1949static void c_parser_objc_at_dynamic_declaration (c_parser *);
1950static bool c_parser_objc_diagnose_bad_element_prefix
1951 (c_parser *, struct c_declspecs *);
1952static location_t c_parser_parse_rtl_body (c_parser *, char *);
1953static tree c_parser_handle_musttail (c_parser *, tree, attr_state &);
1954
1955#if ENABLE_ANALYZER
1956
1957namespace ana {
1958
1959/* Concrete implementation of ana::translation_unit for the C frontend. */
1960
1961class c_translation_unit : public translation_unit
1962{
1963public:
1964 /* Implementation of translation_unit::lookup_constant_by_id for use by the
1965 analyzer to look up named constants in the user's source code. */
1966 tree lookup_constant_by_id (tree id) const final override
1967 {
1968 /* Consider decls. */
1969 if (tree decl = lookup_name (id))
1970 if (TREE_CODE (decl) == CONST_DECL)
1971 if (tree value = DECL_INITIAL (decl))
1972 if (TREE_CODE (value) == INTEGER_CST)
1973 return value;
1974
1975 /* Consider macros. */
1976 cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1977 if (cpp_macro_p (node: hashnode))
1978 if (tree value = consider_macro (macro: hashnode->value.macro))
1979 return value;
1980
1981 return NULL_TREE;
1982 }
1983
1984 tree
1985 lookup_type_by_id (tree id) const final override
1986 {
1987 if (tree type_decl = lookup_name (id))
1988 if (TREE_CODE (type_decl) == TYPE_DECL)
1989 {
1990 tree record_type = TREE_TYPE (type_decl);
1991 if (TREE_CODE (record_type) == RECORD_TYPE)
1992 return record_type;
1993 }
1994
1995 return NULL_TREE;
1996 }
1997
1998 tree
1999 lookup_global_var_by_id (tree id) const final override
2000 {
2001 if (tree var_decl = lookup_name (id))
2002 if (TREE_CODE (var_decl) == VAR_DECL)
2003 return var_decl;
2004
2005 return NULL_TREE;
2006 }
2007
2008private:
2009 /* Attempt to get an INTEGER_CST from MACRO.
2010 Only handle the simplest cases: where MACRO's definition is a single
2011 token containing a number, by lexing the number again.
2012 This will handle e.g.
2013 #define NAME 42
2014 and other bases but not negative numbers, parentheses or e.g.
2015 #define NAME 1 << 7
2016 as doing so would require a parser. */
2017 tree consider_macro (cpp_macro *macro) const
2018 {
2019 if (macro->paramc > 0)
2020 return NULL_TREE;
2021 if (macro->kind != cmk_macro)
2022 return NULL_TREE;
2023 if (macro->count != 1)
2024 return NULL_TREE;
2025 const cpp_token &tok = macro->exp.tokens[0];
2026 if (tok.type != CPP_NUMBER)
2027 return NULL_TREE;
2028
2029 cpp_reader *old_parse_in = parse_in;
2030 parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
2031
2032 pretty_printer pp;
2033 pp_string (&pp, (const char *) tok.val.str.text);
2034 pp_newline (&pp);
2035 cpp_push_buffer (parse_in,
2036 (const unsigned char *) pp_formatted_text (&pp),
2037 strlen (s: pp_formatted_text (&pp)),
2038 0);
2039
2040 tree value;
2041 location_t loc;
2042 unsigned char cpp_flags;
2043 c_lex_with_flags (&value, &loc, &cpp_flags, 0);
2044
2045 cpp_destroy (parse_in);
2046 parse_in = old_parse_in;
2047
2048 if (value && TREE_CODE (value) == INTEGER_CST)
2049 return value;
2050
2051 return NULL_TREE;
2052 }
2053};
2054
2055} // namespace ana
2056
2057#endif /* #if ENABLE_ANALYZER */
2058
2059/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
2060
2061 translation-unit:
2062 external-declarations
2063
2064 external-declarations:
2065 external-declaration
2066 external-declarations external-declaration
2067
2068 GNU extensions:
2069
2070 translation-unit:
2071 empty
2072*/
2073
2074static void
2075c_parser_translation_unit (c_parser *parser)
2076{
2077 if (c_parser_next_token_is (parser, type: CPP_EOF))
2078 {
2079 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2080 "ISO C forbids an empty translation unit");
2081 }
2082 else
2083 {
2084 void *obstack_position = obstack_alloc (&parser_obstack, 0);
2085 mark_valid_location_for_stdc_pragma (false);
2086 do
2087 {
2088 ggc_collect ();
2089 c_parser_external_declaration (parser);
2090 obstack_free (&parser_obstack, obstack_position);
2091 }
2092 while (c_parser_next_token_is_not (parser, type: CPP_EOF));
2093 }
2094
2095 unsigned int i;
2096 tree decl;
2097 FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
2098 if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
2099 error ("storage size of %q+D isn%'t known", decl);
2100
2101 if (vec_safe_length (v: current_omp_declare_target_attribute))
2102 {
2103 c_omp_declare_target_attr
2104 a = current_omp_declare_target_attribute->pop ();
2105 if (!errorcount)
2106 error ("%qs without corresponding %qs",
2107 a.device_type >= 0 ? "#pragma omp begin declare target"
2108 : "#pragma omp declare target",
2109 "#pragma omp end declare target");
2110 vec_safe_truncate (v: current_omp_declare_target_attribute, size: 0);
2111 }
2112 if (vec_safe_length (v: current_omp_begin_assumes))
2113 {
2114 if (!errorcount)
2115 error ("%qs without corresponding %qs",
2116 "#pragma omp begin assumes", "#pragma omp end assumes");
2117 vec_safe_truncate (v: current_omp_begin_assumes, size: 0);
2118 }
2119 if (vec_safe_length (v: current_omp_declare_variant_attribute))
2120 {
2121 if (!errorcount)
2122 error ("%<omp begin declare variant%> without corresponding "
2123 "%<omp end declare variant%>");
2124 vec_safe_truncate (v: current_omp_declare_variant_attribute, size: 0);
2125 }
2126 if (vec_safe_length (v: omp_begin_declare_variant_map))
2127 {
2128 unsigned int i;
2129 omp_begin_declare_variant_map_entry *e;
2130 FOR_EACH_VEC_ELT (*omp_begin_declare_variant_map, i, e)
2131 omp_finish_variant_function (e->variant, e->id, e->ctx);
2132 vec_safe_truncate (v: omp_begin_declare_variant_map, size: 0);
2133 }
2134
2135#if ENABLE_ANALYZER
2136 if (flag_analyzer)
2137 {
2138 ana::c_translation_unit tu;
2139 ana::on_finish_translation_unit (tu);
2140 }
2141#endif
2142}
2143
2144/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
2145
2146 external-declaration:
2147 function-definition
2148 declaration
2149
2150 GNU extensions:
2151
2152 external-declaration:
2153 asm-definition
2154 ;
2155 __extension__ external-declaration
2156
2157 Objective-C:
2158
2159 external-declaration:
2160 objc-class-definition
2161 objc-class-declaration
2162 objc-alias-declaration
2163 objc-protocol-definition
2164 objc-method-definition
2165 @end
2166*/
2167
2168static void
2169c_parser_external_declaration (c_parser *parser)
2170{
2171 int ext;
2172 switch (c_parser_peek_token (parser)->type)
2173 {
2174 case CPP_KEYWORD:
2175 switch (c_parser_peek_token (parser)->keyword)
2176 {
2177 case RID_EXTENSION:
2178 ext = disable_extension_diagnostics ();
2179 c_parser_consume_token (parser);
2180 c_parser_external_declaration (parser);
2181 restore_extension_diagnostics (flags: ext);
2182 break;
2183 case RID_ASM:
2184 c_parser_asm_definition (parser);
2185 break;
2186 case RID_AT_INTERFACE:
2187 case RID_AT_IMPLEMENTATION:
2188 gcc_assert (c_dialect_objc ());
2189 c_parser_objc_class_definition (parser, NULL_TREE);
2190 break;
2191 case RID_AT_CLASS:
2192 gcc_assert (c_dialect_objc ());
2193 c_parser_objc_class_declaration (parser);
2194 break;
2195 case RID_AT_ALIAS:
2196 gcc_assert (c_dialect_objc ());
2197 c_parser_objc_alias_declaration (parser);
2198 break;
2199 case RID_AT_PROTOCOL:
2200 gcc_assert (c_dialect_objc ());
2201 c_parser_objc_protocol_definition (parser, NULL_TREE);
2202 break;
2203 case RID_AT_PROPERTY:
2204 gcc_assert (c_dialect_objc ());
2205 c_parser_objc_at_property_declaration (parser);
2206 break;
2207 case RID_AT_SYNTHESIZE:
2208 gcc_assert (c_dialect_objc ());
2209 c_parser_objc_at_synthesize_declaration (parser);
2210 break;
2211 case RID_AT_DYNAMIC:
2212 gcc_assert (c_dialect_objc ());
2213 c_parser_objc_at_dynamic_declaration (parser);
2214 break;
2215 case RID_AT_END:
2216 gcc_assert (c_dialect_objc ());
2217 c_parser_consume_token (parser);
2218 objc_finish_implementation ();
2219 break;
2220 default:
2221 goto decl_or_fndef;
2222 }
2223 break;
2224 case CPP_SEMICOLON:
2225 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2226 "ISO C does not allow extra %<;%> outside of a function");
2227 c_parser_consume_token (parser);
2228 break;
2229 case CPP_PRAGMA:
2230 mark_valid_location_for_stdc_pragma (true);
2231 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2232 mark_valid_location_for_stdc_pragma (false);
2233 break;
2234 case CPP_PLUS:
2235 case CPP_MINUS:
2236 if (c_dialect_objc ())
2237 {
2238 c_parser_objc_method_definition (parser);
2239 break;
2240 }
2241 /* Else fall through, and yield a syntax error trying to parse
2242 as a declaration or function definition. */
2243 /* FALLTHRU */
2244 default:
2245 decl_or_fndef:
2246 /* A declaration or a function definition (or, in Objective-C,
2247 an @interface or @protocol with prefix attributes). We can
2248 only tell which after parsing the declaration specifiers, if
2249 any, and the first declarator. */
2250 c_parser_declaration_or_fndef (parser, true, true, true, false, true,
2251 false);
2252 break;
2253 }
2254}
2255
2256static void c_parser_handle_directive_omp_attributes (tree &, vec<c_token> *&,
2257 vec<c_token> *);
2258static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
2259static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
2260
2261/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
2262
2263static void
2264add_debug_begin_stmt (location_t loc)
2265{
2266 /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2267 if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2268 return;
2269
2270 tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2271 SET_EXPR_LOCATION (stmt, loc);
2272 add_stmt (stmt);
2273}
2274
2275/* Helper function for c_parser_declaration_or_fndef and
2276 Handle assume attribute(s). */
2277
2278static tree
2279handle_assume_attribute (location_t here, tree attrs, bool nested)
2280{
2281 if (nested)
2282 for (tree attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: attrs); attr;
2283 attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", TREE_CHAIN (attr)))
2284 {
2285 tree args = TREE_VALUE (attr);
2286 int nargs = list_length (args);
2287 if (nargs != 1)
2288 {
2289 error_at (here, "wrong number of arguments specified "
2290 "for %qE attribute",
2291 get_attribute_name (attr));
2292 inform (here, "expected %i, found %i", 1, nargs);
2293 }
2294 else
2295 {
2296 tree arg = TREE_VALUE (args);
2297 arg = c_objc_common_truthvalue_conversion (here, arg);
2298 arg = c_fully_fold (arg, false, NULL);
2299 if (arg != error_mark_node)
2300 {
2301 tree fn = build_call_expr_internal_loc (here, IFN_ASSUME,
2302 void_type_node, 1,
2303 arg);
2304 add_stmt (fn);
2305 }
2306 }
2307 }
2308 else
2309 pedwarn (here, OPT_Wattributes,
2310 "%<assume%> attribute at top level");
2311
2312 return remove_attribute ("gnu", "assume", attrs);
2313}
2314
2315/* We might need to reclassify any previously-lexed identifier, e.g.
2316 when we've left a for loop with an if-statement without else in the
2317 body - we might have used a wrong scope for the token. See PR67784. */
2318
2319static void
2320c_parser_maybe_reclassify_token (c_parser *parser)
2321{
2322 if (c_parser_next_token_is (parser, type: CPP_NAME))
2323 {
2324 c_token *token = c_parser_peek_token (parser);
2325
2326 if (token->id_kind == C_ID_ID || token->id_kind == C_ID_TYPENAME)
2327 {
2328 tree decl = lookup_name (token->value);
2329
2330 token->id_kind = C_ID_ID;
2331 if (decl)
2332 {
2333 if (TREE_CODE (decl) == TYPE_DECL)
2334 token->id_kind = C_ID_TYPENAME;
2335 }
2336 else if (c_dialect_objc ())
2337 {
2338 tree objc_interface_decl = objc_is_class_name (token->value);
2339 /* Objective-C class names are in the same namespace as
2340 variables and typedefs, and hence are shadowed by local
2341 declarations. */
2342 if (objc_interface_decl)
2343 {
2344 token->value = objc_interface_decl;
2345 token->id_kind = C_ID_CLASSNAME;
2346 }
2347 }
2348 }
2349 }
2350}
2351
2352/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
2353 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
2354 is accepted; otherwise (old-style parameter declarations) only other
2355 declarations are accepted. If STATIC_ASSERT_OK is true, a static
2356 assertion is accepted; otherwise (old-style parameter declarations)
2357 it is not. If NESTED is true, we are inside a function or parsing
2358 old-style parameter declarations; any functions encountered are
2359 nested functions and declaration specifiers are required; otherwise
2360 we are at top level and functions are normal functions and
2361 declaration specifiers may be optional. If EMPTY_OK is true, empty
2362 declarations are OK (subject to all other constraints); otherwise
2363 (old-style parameter declarations) they are diagnosed. If
2364 START_ATTR_OK is true, the declaration specifiers may start with
2365 attributes (GNU or standard); otherwise they may not.
2366 OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
2367 declaration when parsing an Objective-C foreach statement.
2368 FALLTHRU_ATTR_P is used to signal whether this function parsed
2369 "__attribute__((fallthrough));". ATTRS are any standard attributes
2370 parsed in the caller (in contexts where such attributes had to be
2371 parsed to determine whether what follows is a declaration or a
2372 statement); HAVE_ATTRS says whether there were any such attributes
2373 (even empty). If SIMPLE_OK, the construct can be a simple-declaration;
2374 in that case, the ';' is not consumed (left to the caller so that it
2375 can figure out if there was a simple-declaration or not), there must
2376 be an initializer, and only one object may be declared. When SIMPLE_OK
2377 is true we are called from c_parser_selection_header.
2378
2379 Returns the resulting declaration, if there was any with an initializer.
2380
2381 declaration:
2382 declaration-specifiers init-declarator-list[opt] ;
2383 static_assert-declaration
2384
2385 function-definition:
2386 declaration-specifiers[opt] declarator declaration-list[opt]
2387 compound-statement
2388
2389 declaration-list:
2390 declaration
2391 declaration-list declaration
2392
2393 init-declarator-list:
2394 init-declarator
2395 init-declarator-list , init-declarator
2396
2397 init-declarator:
2398 declarator simple-asm-expr[opt] gnu-attributes[opt]
2399 declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
2400
2401 simple-declaration:
2402 attribute-specifier-sequence[opt] declaration-specifiers declarator
2403 = initializer
2404
2405 GNU extensions:
2406
2407 nested-function-definition:
2408 declaration-specifiers declarator declaration-list[opt]
2409 compound-statement
2410
2411 attribute ;
2412
2413 Objective-C:
2414 gnu-attributes objc-class-definition
2415 gnu-attributes objc-category-definition
2416 gnu-attributes objc-protocol-definition
2417
2418 The simple-asm-expr and gnu-attributes are GNU extensions.
2419
2420 This function does not handle __extension__; that is handled in its
2421 callers. ??? Following the old parser, __extension__ may start
2422 external declarations, declarations in functions and declarations
2423 at the start of "for" loops, but not old-style parameter
2424 declarations.
2425
2426 C99 requires declaration specifiers in a function definition; the
2427 absence is diagnosed through the diagnosis of implicit int. In GNU
2428 C we also allow but diagnose declarations without declaration
2429 specifiers, but only at top level (elsewhere they conflict with
2430 other syntax).
2431
2432 In Objective-C, declarations of the looping variable in a foreach
2433 statement are exceptionally terminated by 'in' (for example, 'for
2434 (NSObject *object in array) { ... }').
2435
2436 OpenMP:
2437
2438 declaration:
2439 threadprivate-directive
2440
2441 GIMPLE:
2442
2443 gimple-function-definition:
2444 declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
2445 declaration-list[opt] compound-statement
2446
2447 rtl-function-definition:
2448 declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
2449 declaration-list[opt] compound-statement */
2450
2451static tree
2452c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
2453 bool static_assert_ok, bool empty_ok,
2454 bool nested, bool start_attr_ok,
2455 bool simple_ok,
2456 tree *objc_foreach_object_declaration
2457 /* = NULL */,
2458 vec<c_token> *omp_declare_simd_clauses
2459 /* = NULL */,
2460 bool have_attrs /* = false */,
2461 tree attrs /* = NULL_TREE */,
2462 struct oacc_routine_data *oacc_routine_data
2463 /* = NULL */,
2464 bool *fallthru_attr_p /* = NULL */)
2465{
2466 struct c_declspecs *specs;
2467 tree prefix_attrs;
2468 tree all_prefix_attrs;
2469 bool diagnosed_no_specs = false;
2470 location_t here = c_parser_peek_token (parser)->location;
2471 tree result = NULL_TREE;
2472
2473 add_debug_begin_stmt (loc: c_parser_peek_token (parser)->location);
2474
2475 if (static_assert_ok
2476 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
2477 {
2478 c_parser_static_assert_declaration (parser);
2479 return result;
2480 }
2481 specs = build_null_declspecs ();
2482
2483 /* Handle any standard attributes parsed in the caller. */
2484 if (have_attrs)
2485 {
2486 declspecs_add_attrs (here, specs, attrs);
2487 specs->non_std_attrs_seen_p = false;
2488 }
2489
2490 /* Try to detect an unknown type name when we have "A B" or "A *B". */
2491 if (c_parser_peek_token (parser)->type == CPP_NAME
2492 && c_parser_peek_token (parser)->id_kind == C_ID_ID
2493 && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2494 || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2495 && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2496 {
2497 tree name = c_parser_peek_token (parser)->value;
2498
2499 /* Issue a warning about NAME being an unknown type name, perhaps
2500 with some kind of hint.
2501 If the user forgot a "struct" etc, suggest inserting
2502 it. Otherwise, attempt to look for misspellings. */
2503 gcc_rich_location richloc (here);
2504 if (tag_exists_p (RECORD_TYPE, name))
2505 {
2506 /* This is not C++ with its implicit typedef. */
2507 richloc.add_fixit_insert_before (new_content: "struct ");
2508 error_at (&richloc,
2509 "unknown type name %qE;"
2510 " use %<struct%> keyword to refer to the type",
2511 name);
2512 }
2513 else if (tag_exists_p (UNION_TYPE, name))
2514 {
2515 richloc.add_fixit_insert_before (new_content: "union ");
2516 error_at (&richloc,
2517 "unknown type name %qE;"
2518 " use %<union%> keyword to refer to the type",
2519 name);
2520 }
2521 else if (tag_exists_p (ENUMERAL_TYPE, name))
2522 {
2523 richloc.add_fixit_insert_before (new_content: "enum ");
2524 error_at (&richloc,
2525 "unknown type name %qE;"
2526 " use %<enum%> keyword to refer to the type",
2527 name);
2528 }
2529 else
2530 {
2531 auto_diagnostic_group d;
2532 name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2533 here);
2534 if (const char *suggestion = hint.suggestion ())
2535 {
2536 richloc.add_fixit_replace (new_content: suggestion);
2537 error_at (&richloc,
2538 "unknown type name %qE; did you mean %qs?",
2539 name, suggestion);
2540 }
2541 else
2542 error_at (here, "unknown type name %qE", name);
2543 }
2544
2545 /* Parse declspecs normally to get a correct pointer type, but avoid
2546 a further "fails to be a type name" error. Refuse nested functions
2547 since it is not how the user likely wants us to recover. */
2548 c_parser_peek_token (parser)->type = CPP_KEYWORD;
2549 c_parser_peek_token (parser)->keyword = RID_VOID;
2550 c_parser_peek_token (parser)->value = error_mark_node;
2551 fndef_ok = !nested;
2552 }
2553
2554 /* When there are standard attributes at the start of the
2555 declaration (to apply to the entity being declared), an
2556 init-declarator-list or function definition must be present. */
2557 if (c_parser_nth_token_starts_std_attributes (parser, 1))
2558 have_attrs = true;
2559
2560 c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2561 true, true, start_attr_ok, true, cla_nonabstract_decl);
2562 if (parser->error)
2563 {
2564 c_parser_skip_to_end_of_block_or_statement (parser);
2565 return result;
2566 }
2567 if (nested && !specs->declspecs_seen_p)
2568 {
2569 c_parser_error (parser, gmsgid: "expected declaration specifiers");
2570 c_parser_skip_to_end_of_block_or_statement (parser);
2571 return result;
2572 }
2573
2574 finish_declspecs (specs);
2575 /* When the decl is declared, its type is a top level type, we should
2576 call verify_counted_by_for_top_anonymous_type. */
2577 if (specs->typespec_kind == ctsk_tagdef)
2578 verify_counted_by_for_top_anonymous_type (specs->type);
2579
2580 bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2581 bool std_auto_type_p = specs->c23_auto_p;
2582 bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2583 gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2584 const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2585 if (specs->constexpr_p)
2586 {
2587 /* An underspecified declaration may not declare tags or members
2588 or structures or unions; it is undefined behavior to declare
2589 the members of an enumeration. Where the structure, union or
2590 enumeration type is declared within an initializer, this is
2591 diagnosed elsewhere. Diagnose here the case of declaring
2592 such a type in the type specifiers of a constexpr
2593 declaration. */
2594 switch (specs->typespec_kind)
2595 {
2596 case ctsk_tagfirstref:
2597 case ctsk_tagfirstref_attrs:
2598 error_at (here, "%qT declared in underspecified object declaration",
2599 specs->type);
2600 break;
2601
2602 case ctsk_tagdef:
2603 error_at (here, "%qT defined in underspecified object declaration",
2604 specs->type);
2605 break;
2606
2607 default:
2608 break;
2609 }
2610 }
2611
2612 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
2613 {
2614 bool handled_assume = false;
2615 if (specs->attrs
2616 && !nested
2617 && specs->typespec_kind == ctsk_none
2618 && c_parser_handle_statement_omp_attributes (parser, specs->attrs,
2619 NULL))
2620 {
2621 if (specs->attrs)
2622 c_warn_unused_attributes (specs->attrs);
2623 while (parser->in_omp_attribute_pragma)
2624 {
2625 gcc_assert (c_parser_next_token_is (parser, CPP_PRAGMA));
2626 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2627 }
2628 c_parser_consume_token (parser);
2629 return result;
2630 }
2631 if (specs->typespec_kind == ctsk_none
2632 && lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2633 {
2634 handled_assume = true;
2635 specs->attrs
2636 = handle_assume_attribute (here, attrs: specs->attrs, nested);
2637 }
2638 if (any_auto_type_p)
2639 error_at (here, "%qs in empty declaration", auto_type_keyword);
2640 else if (specs->typespec_kind == ctsk_none
2641 && attribute_fallthrough_p (specs->attrs))
2642 {
2643 if (fallthru_attr_p != NULL)
2644 *fallthru_attr_p = true;
2645 if (nested)
2646 {
2647 tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2648 void_type_node, 0);
2649 add_stmt (fn);
2650 }
2651 else
2652 pedwarn (here, OPT_Wattributes,
2653 "%<fallthrough%> attribute at top level");
2654 }
2655 else if (empty_ok
2656 && !(have_attrs && specs->non_std_attrs_seen_p)
2657 && !handled_assume)
2658 shadow_tag (specs);
2659 else
2660 {
2661 shadow_tag_warned (specs, 1);
2662 if (!handled_assume)
2663 pedwarn (here, 0, "empty declaration");
2664 }
2665 /* We still have to evaluate size expressions. */
2666 if (specs->expr)
2667 add_stmt (fold_convert (void_type_node, specs->expr));
2668 c_parser_consume_token (parser);
2669 if (oacc_routine_data)
2670 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2671 return result;
2672 }
2673 else if (specs->typespec_kind == ctsk_none
2674 && nested
2675 /* Only parse __attribute__((musttail)) when called from
2676 c_parser_compound_statement_nostart. This certainly isn't
2677 a declaration in that case, but we don't do tentative parsing
2678 of GNU attributes right now. */
2679 && fallthru_attr_p
2680 && c_parser_next_token_is_keyword (parser, keyword: RID_RETURN))
2681 {
2682 attr_state astate = {};
2683 specs->attrs = c_parser_handle_musttail (parser, specs->attrs, astate);
2684 if (astate.musttail_p)
2685 {
2686 if (specs->attrs)
2687 {
2688 auto_urlify_attributes sentinel;
2689 warning_at (c_parser_peek_token (parser)->location,
2690 OPT_Wattributes,
2691 "attribute %<musttail%> mixed with other attributes "
2692 "on %<return%> statement");
2693 }
2694 c_parser_statement_after_labels (parser, NULL, NULL_TREE, NULL,
2695 astate);
2696 return result;
2697 }
2698 }
2699
2700 /* Provide better error recovery. Note that a type name here is usually
2701 better diagnosed as a redeclaration. */
2702 if (empty_ok
2703 && specs->typespec_kind == ctsk_tagdef
2704 && c_parser_next_token_starts_declspecs (parser)
2705 && !c_parser_next_token_is (parser, type: CPP_NAME))
2706 {
2707 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
2708 parser->error = false;
2709 shadow_tag_warned (specs, 1);
2710 return result;
2711 }
2712 else if (c_dialect_objc () && !any_auto_type_p)
2713 {
2714 /* Prefix attributes are an error on method decls. */
2715 switch (c_parser_peek_token (parser)->type)
2716 {
2717 case CPP_PLUS:
2718 case CPP_MINUS:
2719 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2720 return result;
2721 if (specs->attrs)
2722 {
2723 warning_at (c_parser_peek_token (parser)->location,
2724 OPT_Wattributes,
2725 "prefix attributes are ignored for methods");
2726 specs->attrs = NULL_TREE;
2727 }
2728 if (fndef_ok)
2729 c_parser_objc_method_definition (parser);
2730 else
2731 c_parser_objc_methodproto (parser);
2732 return result;
2733 break;
2734 default:
2735 break;
2736 }
2737 /* This is where we parse 'attributes @interface ...',
2738 'attributes @implementation ...', 'attributes @protocol ...'
2739 (where attributes could be, for example, __attribute__
2740 ((deprecated)).
2741 */
2742 switch (c_parser_peek_token (parser)->keyword)
2743 {
2744 case RID_AT_INTERFACE:
2745 {
2746 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2747 return result;
2748 c_parser_objc_class_definition (parser, specs->attrs);
2749 return result;
2750 }
2751 break;
2752 case RID_AT_IMPLEMENTATION:
2753 {
2754 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2755 return result;
2756 if (specs->attrs)
2757 {
2758 warning_at (c_parser_peek_token (parser)->location,
2759 OPT_Wattributes,
2760 "prefix attributes are ignored for implementations");
2761 specs->attrs = NULL_TREE;
2762 }
2763 c_parser_objc_class_definition (parser, NULL_TREE);
2764 return result;
2765 }
2766 break;
2767 case RID_AT_PROTOCOL:
2768 {
2769 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2770 return result;
2771 c_parser_objc_protocol_definition (parser, specs->attrs);
2772 return result;
2773 }
2774 break;
2775 case RID_AT_ALIAS:
2776 case RID_AT_CLASS:
2777 case RID_AT_END:
2778 case RID_AT_PROPERTY:
2779 if (specs->attrs)
2780 {
2781 c_parser_error (parser, gmsgid: "unexpected attribute");
2782 specs->attrs = NULL;
2783 }
2784 break;
2785 default:
2786 break;
2787 }
2788 }
2789 else if (attribute_fallthrough_p (specs->attrs))
2790 warning_at (here, OPT_Wattributes,
2791 "%<fallthrough%> attribute not followed by %<;%>");
2792 else if (lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2793 warning_at (here, OPT_Wattributes,
2794 "%<assume%> attribute not followed by %<;%>");
2795
2796 auto_vec<c_token> omp_declare_simd_attr_clauses;
2797 c_parser_handle_directive_omp_attributes (specs->attrs,
2798 omp_declare_simd_clauses,
2799 &omp_declare_simd_attr_clauses);
2800 pending_xref_error ();
2801 prefix_attrs = specs->attrs;
2802 all_prefix_attrs = prefix_attrs;
2803 specs->attrs = NULL_TREE;
2804 bool more_than_one_decl = false;
2805 while (true)
2806 {
2807 struct c_declarator *declarator;
2808 bool dummy = false;
2809 timevar_id_t tv;
2810 tree fnbody = NULL_TREE;
2811 tree underspec_name = NULL_TREE;
2812 auto_vec<c_token> omp_dsimd_idattr_clauses;
2813 /* Declaring either one or more declarators (in which case we
2814 should diagnose if there were no declaration specifiers) or a
2815 function definition (in which case the diagnostic for
2816 implicit int suffices). */
2817 declarator = c_parser_declarator (parser,
2818 type_seen_p: specs->typespec_kind != ctsk_none,
2819 kind: C_DTR_NORMAL, seen_id: &dummy);
2820 if (declarator == NULL)
2821 {
2822 if (omp_declare_simd_clauses)
2823 c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2824 omp_declare_simd_clauses);
2825 if (oacc_routine_data)
2826 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2827 /* This check is here purely to improve the diagnostic. */
2828 if (!simple_ok)
2829 c_parser_skip_to_end_of_block_or_statement (parser);
2830 return result;
2831 }
2832 if (flag_openmp || flag_openmp_simd)
2833 {
2834 struct c_declarator *d = declarator;
2835 while (d->kind != cdk_id)
2836 d = d->declarator;
2837 vec<c_token> *dummy = NULL;
2838 c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2839 &omp_dsimd_idattr_clauses);
2840 }
2841 if (gnu_auto_type_p && declarator->kind != cdk_id)
2842 {
2843 error_at (here,
2844 "%<__auto_type%> requires a plain identifier"
2845 " as declarator");
2846 c_parser_skip_to_end_of_block_or_statement (parser);
2847 return result;
2848 }
2849 if (std_auto_type_p)
2850 {
2851 struct c_declarator *d = declarator;
2852 while (d->kind == cdk_attrs)
2853 d = d->declarator;
2854 if (d->kind != cdk_id)
2855 {
2856 error_at (here,
2857 "%<auto%> requires a plain identifier, possibly with"
2858 " attributes, as declarator");
2859 c_parser_skip_to_end_of_block_or_statement (parser);
2860 return result;
2861 }
2862 underspec_name = d->u.id.id;
2863 }
2864 else if (specs->constexpr_p)
2865 {
2866 struct c_declarator *d = declarator;
2867 while (d->kind != cdk_id)
2868 d = d->declarator;
2869 underspec_name = d->u.id.id;
2870 }
2871 if (c_parser_next_token_is (parser, type: CPP_EQ)
2872 || c_parser_next_token_is (parser, type: CPP_COMMA)
2873 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
2874 || c_parser_next_token_is_keyword (parser, keyword: RID_ASM)
2875 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE)
2876 || c_parser_next_token_is_keyword (parser, keyword: RID_IN))
2877 {
2878 tree asm_name = NULL_TREE;
2879 tree postfix_attrs = NULL_TREE;
2880 if (!diagnosed_no_specs && !specs->declspecs_seen_p)
2881 {
2882 diagnosed_no_specs = true;
2883 pedwarn (here, 0, "data definition has no type or storage class");
2884 }
2885 /* Having seen a data definition, there cannot now be a
2886 function definition. */
2887 fndef_ok = false;
2888 if (c_parser_next_token_is_keyword (parser, keyword: RID_ASM))
2889 asm_name = c_parser_simple_asm_expr (parser);
2890 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
2891 {
2892 postfix_attrs = c_parser_gnu_attributes (parser);
2893 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
2894 {
2895 /* This means there is an attribute specifier after
2896 the declarator in a function definition. Provide
2897 some more information for the user. */
2898 error_at (here, "attributes should be specified before the "
2899 "declarator in a function definition");
2900 c_parser_skip_to_end_of_block_or_statement (parser);
2901 return result;
2902 }
2903 }
2904 if (c_parser_next_token_is (parser, type: CPP_EQ))
2905 {
2906 tree d;
2907 struct c_expr init;
2908 location_t init_loc;
2909 c_parser_consume_token (parser);
2910 if (any_auto_type_p)
2911 {
2912 init_loc = c_parser_peek_token (parser)->location;
2913 rich_location richloc (line_table, init_loc);
2914 unsigned int underspec_state = 0;
2915 if (std_auto_type_p)
2916 underspec_state =
2917 start_underspecified_init (init_loc, underspec_name);
2918 start_init (NULL_TREE, asm_name,
2919 (global_bindings_p ()
2920 || specs->storage_class == csc_static
2921 || specs->constexpr_p),
2922 specs->constexpr_p, &richloc);
2923 /* A parameter is initialized, which is invalid. Don't
2924 attempt to instrument the initializer. */
2925 sanitize_code_type flag_sanitize_save = flag_sanitize;
2926 if (nested && !empty_ok)
2927 flag_sanitize = 0;
2928 init = c_parser_expr_no_commas (parser, NULL);
2929 if (std_auto_type_p)
2930 finish_underspecified_init (underspec_name,
2931 underspec_state);
2932 flag_sanitize = flag_sanitize_save;
2933 if (gnu_auto_type_p
2934 && TREE_CODE (init.value) == COMPONENT_REF
2935 && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
2936 error_at (here,
2937 "%<__auto_type%> used with a bit-field"
2938 " initializer");
2939 init = convert_lvalue_to_rvalue (init_loc, init, true, true,
2940 true);
2941 tree init_type = TREE_TYPE (init.value);
2942 bool vm_type = c_type_variably_modified_p (t: init_type);
2943 if (vm_type)
2944 init.value = save_expr (init.value);
2945 finish_init ();
2946 specs->typespec_kind = ctsk_typeof;
2947 specs->locations[cdw_typedef] = init_loc;
2948 specs->typedef_p = true;
2949 specs->type = init_type;
2950 if (specs->postfix_attrs)
2951 {
2952 /* Postfix [[]] attributes are valid with C23
2953 auto, although not with __auto_type, and
2954 modify the type given by the initializer. */
2955 specs->postfix_attrs
2956 = c_warn_type_attributes (specs->type,
2957 specs->postfix_attrs);
2958 decl_attributes (&specs->type, specs->postfix_attrs, 0);
2959 specs->postfix_attrs = NULL_TREE;
2960 }
2961 if (vm_type)
2962 {
2963 bool maybe_const = true;
2964 tree type_expr = c_fully_fold (init.value, false,
2965 &maybe_const);
2966 specs->expr_const_operands &= maybe_const;
2967 if (specs->expr)
2968 specs->expr = build2 (COMPOUND_EXPR,
2969 TREE_TYPE (type_expr),
2970 specs->expr, type_expr);
2971 else
2972 specs->expr = type_expr;
2973 }
2974 d = start_decl (declarator, specs, true,
2975 chainon (postfix_attrs, all_prefix_attrs));
2976 if (!d)
2977 d = error_mark_node;
2978 if (omp_declare_simd_clauses)
2979 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2980 omp_declare_simd_clauses);
2981 if (!omp_dsimd_idattr_clauses.is_empty ())
2982 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2983 &omp_dsimd_idattr_clauses);
2984 }
2985 else
2986 {
2987 /* The declaration of the variable is in effect while
2988 its initializer is parsed, except for a constexpr
2989 variable. */
2990 init_loc = c_parser_peek_token (parser)->location;
2991 rich_location richloc (line_table, init_loc);
2992 unsigned int underspec_state = 0;
2993 if (specs->constexpr_p)
2994 underspec_state =
2995 start_underspecified_init (init_loc, underspec_name);
2996 d = start_decl (declarator, specs, true,
2997 chainon (postfix_attrs,
2998 all_prefix_attrs),
2999 !specs->constexpr_p);
3000 if (!d)
3001 d = error_mark_node;
3002 if (!specs->constexpr_p && omp_declare_simd_clauses)
3003 c_finish_omp_declare_simd (parser, d, NULL_TREE,
3004 omp_declare_simd_clauses);
3005 if (!specs->constexpr_p
3006 && !omp_dsimd_idattr_clauses.is_empty ())
3007 c_finish_omp_declare_simd (parser, d, NULL_TREE,
3008 &omp_dsimd_idattr_clauses);
3009 start_init (d, asm_name,
3010 TREE_STATIC (d) || specs->constexpr_p,
3011 specs->constexpr_p, &richloc);
3012 /* A parameter is initialized, which is invalid. Don't
3013 attempt to instrument the initializer. */
3014 sanitize_code_type flag_sanitize_save = flag_sanitize;
3015 if (TREE_CODE (d) == PARM_DECL)
3016 flag_sanitize = 0;
3017 init = c_parser_initializer (parser, d);
3018 flag_sanitize = flag_sanitize_save;
3019 if (specs->constexpr_p)
3020 {
3021 finish_underspecified_init (underspec_name,
3022 underspec_state);
3023 d = pushdecl (d);
3024 if (omp_declare_simd_clauses)
3025 c_finish_omp_declare_simd (parser, d, NULL_TREE,
3026 omp_declare_simd_clauses);
3027 if (!specs->constexpr_p
3028 && !omp_dsimd_idattr_clauses.is_empty ())
3029 c_finish_omp_declare_simd (parser, d, NULL_TREE,
3030 &omp_dsimd_idattr_clauses);
3031 }
3032 finish_init ();
3033 }
3034 if (oacc_routine_data)
3035 c_finish_oacc_routine (oacc_routine_data, d, false);
3036 if (d != error_mark_node)
3037 {
3038 maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
3039 finish_decl (d, init_loc, init.value,
3040 init.original_type, asm_name);
3041 result = d;
3042 }
3043 }
3044 else
3045 {
3046 if (any_auto_type_p || specs->constexpr_p)
3047 {
3048 error_at (here,
3049 "%qs requires an initialized data declaration",
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
3055 location_t lastloc = UNKNOWN_LOCATION;
3056 tree attrs = chainon (postfix_attrs, all_prefix_attrs);
3057 tree d = start_decl (declarator, specs, false, attrs, true,
3058 &lastloc);
3059 if (d && TREE_CODE (d) == FUNCTION_DECL)
3060 {
3061 /* Find the innermost declarator that is neither cdk_id
3062 nor cdk_attrs. */
3063 const struct c_declarator *decl = declarator;
3064 const struct c_declarator *last_non_id_attrs = NULL;
3065
3066 while (decl)
3067 switch (decl->kind)
3068 {
3069 case cdk_array:
3070 case cdk_function:
3071 case cdk_pointer:
3072 last_non_id_attrs = decl;
3073 decl = decl->declarator;
3074 break;
3075
3076 case cdk_attrs:
3077 decl = decl->declarator;
3078 break;
3079
3080 case cdk_id:
3081 decl = 0;
3082 break;
3083
3084 default:
3085 gcc_unreachable ();
3086 }
3087
3088 /* If it exists and is cdk_function declaration whose
3089 arguments have not been set yet, use its arguments. */
3090 if (last_non_id_attrs
3091 && last_non_id_attrs->kind == cdk_function)
3092 {
3093 tree parms = last_non_id_attrs->u.arg_info->parms;
3094 if (DECL_ARGUMENTS (d) == NULL_TREE
3095 && DECL_INITIAL (d) == NULL_TREE)
3096 DECL_ARGUMENTS (d) = parms;
3097
3098 warn_parms_array_mismatch (lastloc, d, parms);
3099 }
3100 }
3101 if (omp_declare_simd_clauses
3102 || !omp_dsimd_idattr_clauses.is_empty ())
3103 {
3104 tree parms = NULL_TREE;
3105 if (d && TREE_CODE (d) == FUNCTION_DECL)
3106 {
3107 struct c_declarator *ce = declarator;
3108 while (ce != NULL)
3109 if (ce->kind == cdk_function)
3110 {
3111 parms = ce->u.arg_info->parms;
3112 break;
3113 }
3114 else
3115 ce = ce->declarator;
3116 }
3117 if (parms)
3118 temp_store_parm_decls (d, parms);
3119 if (omp_declare_simd_clauses)
3120 c_finish_omp_declare_simd (parser, d, parms,
3121 omp_declare_simd_clauses);
3122 if (!specs->constexpr_p
3123 && !omp_dsimd_idattr_clauses.is_empty ())
3124 c_finish_omp_declare_simd (parser, d, parms,
3125 &omp_dsimd_idattr_clauses);
3126 if (parms)
3127 temp_pop_parm_decls ();
3128 }
3129 if (oacc_routine_data)
3130 c_finish_oacc_routine (oacc_routine_data, d, false);
3131 if (d)
3132 finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
3133 NULL_TREE, asm_name);
3134
3135 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
3136 {
3137 if (d)
3138 *objc_foreach_object_declaration = d;
3139 else
3140 *objc_foreach_object_declaration = error_mark_node;
3141 }
3142 }
3143 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3144 {
3145 more_than_one_decl = true;
3146 if (any_auto_type_p || specs->constexpr_p)
3147 {
3148 error_at (here,
3149 "%qs may only be used with a single declarator",
3150 any_auto_type_p ? auto_type_keyword : "constexpr");
3151 c_parser_skip_to_end_of_block_or_statement (parser);
3152 return result;
3153 }
3154 c_parser_consume_token (parser);
3155 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
3156 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
3157 prefix_attrs);
3158 else
3159 all_prefix_attrs = prefix_attrs;
3160 continue;
3161 }
3162 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
3163 {
3164 if (!simple_ok)
3165 c_parser_consume_token (parser);
3166 return result;
3167 }
3168 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
3169 {
3170 /* This can only happen in Objective-C: we found the
3171 'in' that terminates the declaration inside an
3172 Objective-C foreach statement. Do not consume the
3173 token, so that the caller can use it to determine
3174 that this indeed is a foreach context. */
3175 return result;
3176 }
3177 else
3178 {
3179 if (!simple_ok)
3180 {
3181 c_parser_error (parser, gmsgid: "expected %<,%> or %<;%>");
3182 c_parser_skip_to_end_of_block_or_statement (parser);
3183 }
3184 /* It's not valid to use if (int i = 2, j = 3). */
3185 else if (more_than_one_decl)
3186 error_at (here, "declaration in condition can only declare "
3187 "a single object");
3188 return result;
3189 }
3190 }
3191 else if (any_auto_type_p || specs->constexpr_p)
3192 {
3193 error_at (here,
3194 "%qs requires an initialized data declaration",
3195 any_auto_type_p ? auto_type_keyword : "constexpr");
3196 c_parser_skip_to_end_of_block_or_statement (parser);
3197 return result;
3198 }
3199 else if (!fndef_ok)
3200 {
3201 if (simple_ok && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3202 /* Let c_parser_selection_header emit the error. */;
3203 else
3204 {
3205 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, "
3206 "%<asm%> or %<__attribute__%>");
3207 c_parser_skip_to_end_of_block_or_statement (parser);
3208 }
3209 return result;
3210 }
3211 /* Function definition (nested or otherwise). */
3212 if (nested)
3213 {
3214 pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
3215 c_push_function_context ();
3216 }
3217
3218 /* If we're in an OpenMP "begin declare variant" block, the
3219 name in the declarator refers to the base function. We need
3220 to save that and modify the declarator to have the mangled
3221 name for the variant function instead. */
3222 tree dv_base = NULL_TREE;
3223 tree dv_ctx = NULL_TREE;
3224 if (!vec_safe_is_empty (v: current_omp_declare_variant_attribute))
3225 {
3226 c_omp_declare_variant_attr a
3227 = current_omp_declare_variant_attribute->last ();
3228 dv_ctx = copy_list (a.selector);
3229 dv_base = omp_start_variant_function (declarator, dv_ctx);
3230 }
3231
3232 if (!start_function (specs, declarator, all_prefix_attrs))
3233 {
3234 /* At this point we've consumed:
3235 declaration-specifiers declarator
3236 and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
3237 RID_ASM, RID_ATTRIBUTE, or RID_IN,
3238 but the
3239 declaration-specifiers declarator
3240 aren't grokkable as a function definition, so we have
3241 an error. */
3242 gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
3243 if (c_parser_next_token_starts_declspecs (parser))
3244 {
3245 /* If we have
3246 declaration-specifiers declarator decl-specs
3247 then assume we have a missing semicolon, which would
3248 give us:
3249 declaration-specifiers declarator decl-specs
3250 ^
3251 ;
3252 <~~~~~~~~~ declaration ~~~~~~~~~~>
3253 Use c_parser_require to get an error with a fix-it hint. */
3254 c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
3255 parser->error = false;
3256 }
3257 else
3258 {
3259 /* This can appear in many cases looking nothing like a
3260 function definition, so we don't give a more specific
3261 error suggesting there was one. */
3262 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, %<asm%> "
3263 "or %<__attribute__%>");
3264 }
3265 if (nested)
3266 c_pop_function_context ();
3267 break;
3268 }
3269
3270 if (DECL_DECLARED_INLINE_P (current_function_decl))
3271 tv = TV_PARSE_INLINE;
3272 else
3273 tv = TV_PARSE_FUNC;
3274 auto_timevar at (g_timer, tv);
3275
3276 /* Parse old-style parameter declarations. ??? Attributes are
3277 not allowed to start declaration specifiers here because of a
3278 syntax conflict between a function declaration with attribute
3279 suffix and a function definition with an attribute prefix on
3280 first old-style parameter declaration. Following the old
3281 parser, they are not accepted on subsequent old-style
3282 parameter declarations either. However, there is no
3283 ambiguity after the first declaration, nor indeed on the
3284 first as long as we don't allow postfix attributes after a
3285 declarator with a nonempty identifier list in a definition;
3286 and postfix attributes have never been accepted here in
3287 function definitions either. */
3288 int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
3289 debug_nonbind_markers_p = 0;
3290 c_parser_maybe_reclassify_token (parser);
3291 while (c_parser_next_token_is_not (parser, type: CPP_EOF)
3292 && c_parser_next_token_is_not (parser, type: CPP_OPEN_BRACE))
3293 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: false,
3294 nested: true, start_attr_ok: false, simple_ok: false);
3295 debug_nonbind_markers_p = save_debug_nonbind_markers_p;
3296 store_parm_decls ();
3297 if (omp_declare_simd_clauses)
3298 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3299 omp_declare_simd_clauses);
3300 if (!omp_dsimd_idattr_clauses.is_empty ())
3301 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3302 &omp_dsimd_idattr_clauses);
3303 if (oacc_routine_data)
3304 c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
3305 location_t startloc = c_parser_peek_token (parser)->location;
3306 DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
3307 = startloc;
3308 location_t endloc = startloc;
3309 /* If this function was in a "begin declare variant" block,
3310 remember it. We will associate it with the base function at
3311 the end of processing the translation unit, since it is permitted
3312 for the variant definition to appear before the base declaration. */
3313 if (dv_base && current_function_decl != error_mark_node)
3314 {
3315 omp_begin_declare_variant_map_entry e
3316 = { .variant: current_function_decl, .id: dv_base, .ctx: dv_ctx };
3317 vec_safe_push (v&: omp_begin_declare_variant_map, obj: e);
3318 }
3319
3320 /* If the definition was marked with __RTL, use the RTL parser now,
3321 consuming the function body. */
3322 if (specs->declspec_il == cdil_rtl)
3323 {
3324 endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
3325
3326 /* Normally, store_parm_decls sets next_is_function_body,
3327 anticipating a function body. We need a push_scope/pop_scope
3328 pair to flush out this state, or subsequent function parsing
3329 will go wrong. */
3330 push_scope ();
3331 pop_scope ();
3332
3333 finish_function (endloc);
3334 return result;
3335 }
3336 /* If the definition was marked with __GIMPLE then parse the
3337 function body as GIMPLE. */
3338 else if (specs->declspec_il != cdil_none)
3339 {
3340 bool saved = in_late_binary_op;
3341 in_late_binary_op = true;
3342 c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3343 specs->declspec_il,
3344 specs->entry_bb_count);
3345 in_late_binary_op = saved;
3346 }
3347 else
3348 fnbody = c_parser_compound_statement (parser, &endloc);
3349 tree fndecl = current_function_decl;
3350 if (nested && specs->declspec_il == cdil_none)
3351 {
3352 tree decl = current_function_decl;
3353 /* Mark nested functions as needing static-chain initially.
3354 lower_nested_functions will recompute it but the
3355 DECL_STATIC_CHAIN flag is also used before that happens,
3356 by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
3357 DECL_STATIC_CHAIN (decl) = 1;
3358 add_stmt (fnbody);
3359 finish_function (endloc);
3360 c_pop_function_context ();
3361 add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
3362 }
3363 else if (nested)
3364 {
3365 if (specs->declspec_il == cdil_rtl)
3366 error ("%<__RTL%> function cannot be a nested function");
3367 else
3368 error ("%<__GIMPLE%> function cannot be a nested function");
3369 finish_function (endloc);
3370 c_pop_function_context ();
3371 }
3372 else
3373 {
3374 if (fnbody)
3375 add_stmt (fnbody);
3376 finish_function (endloc);
3377 }
3378 /* Get rid of the empty stmt list for GIMPLE/RTL. */
3379 if (specs->declspec_il != cdil_none)
3380 DECL_SAVED_TREE (fndecl) = NULL_TREE;
3381
3382 break;
3383 }
3384
3385 return result;
3386}
3387
3388/* Parse an asm-definition (asm() outside a function body). This is a
3389 GNU extension.
3390
3391 asm-definition:
3392 simple-asm-expr ;
3393 asm ( toplevel-asm-argument ) ;
3394
3395 toplevel-asm-argument:
3396 asm-string-literal
3397 asm-string-literal : asm-operands[opt]
3398 asm-string-literal : asm-operands[opt] : asm-operands[opt]
3399
3400 The :: token is considered equivalent to two consecutive : tokens. */
3401
3402static void
3403c_parser_asm_definition (c_parser *parser)
3404{
3405 location_t asm_loc = c_parser_peek_token (parser)->location;
3406 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
3407 c_parser_consume_token (parser);
3408 matching_parens parens;
3409 tree asm_str = NULL_TREE;
3410 tree outputs = NULL_TREE, inputs = NULL_TREE;
3411 if (!parens.require_open (parser))
3412 goto done;
3413 asm_str = c_parser_asm_string_literal (parser);
3414 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3415 {
3416 parens.require_close (parser);
3417 goto done;
3418 }
3419 for (int section = 0; section < 2; ++section)
3420 {
3421 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
3422 {
3423 ++section;
3424 if (section == 2)
3425 {
3426 c_parser_error (parser, gmsgid: "expected %<)%>");
3427 error_close_paren:
3428 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
3429 asm_str = NULL_TREE;
3430 goto done;
3431 }
3432 c_parser_consume_token (parser);
3433 }
3434 else if (!c_parser_require (parser, type: CPP_COLON,
3435 msgid: "expected %<:%> or %<)%>",
3436 UNKNOWN_LOCATION, type_is_unique: false))
3437 goto error_close_paren;
3438 if (!c_parser_next_token_is (parser, type: CPP_COLON)
3439 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
3440 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3441 {
3442 if (section)
3443 inputs = c_parser_asm_operands (parser);
3444 else
3445 outputs = c_parser_asm_operands (parser);
3446 }
3447 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3448 break;
3449 }
3450
3451 if (!parens.require_close (parser))
3452 {
3453 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
3454 asm_str = NULL_TREE;
3455 }
3456
3457 if (asm_str)
3458 asm_str = build_asm_expr (asm_loc, asm_str, outputs, inputs,
3459 NULL_TREE, NULL_TREE, false, false);
3460done:
3461 if (asm_str)
3462 symtab->finalize_toplevel_asm (asm_str);
3463 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
3464}
3465
3466/* Parse a static assertion (C11 6.7.10).
3467
3468 static_assert-declaration:
3469 static_assert-declaration-no-semi ;
3470*/
3471
3472static void
3473c_parser_static_assert_declaration (c_parser *parser)
3474{
3475 c_parser_static_assert_declaration_no_semi (parser);
3476 if (parser->error
3477 || !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
3478 c_parser_skip_to_end_of_block_or_statement (parser);
3479}
3480
3481/* Parse a static assertion (C11 6.7.10), without the trailing
3482 semicolon.
3483
3484 static_assert-declaration-no-semi:
3485 _Static_assert ( constant-expression , string-literal )
3486
3487 C23:
3488 static_assert-declaration-no-semi:
3489 _Static_assert ( constant-expression )
3490*/
3491
3492static void
3493c_parser_static_assert_declaration_no_semi (c_parser *parser)
3494{
3495 location_t assert_loc, value_loc;
3496 tree value;
3497 tree string = NULL_TREE;
3498
3499 gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3500 tree spelling = c_parser_peek_token (parser)->value;
3501 assert_loc = c_parser_peek_token (parser)->location;
3502 if (flag_isoc99)
3503 pedwarn_c99 (assert_loc, OPT_Wpedantic,
3504 "ISO C99 does not support %qE", spelling);
3505 else
3506 pedwarn_c99 (assert_loc, OPT_Wpedantic,
3507 "ISO C90 does not support %qE", spelling);
3508 c_parser_consume_token (parser);
3509 matching_parens parens;
3510 if (!parens.require_open (parser))
3511 return;
3512 location_t value_tok_loc = c_parser_peek_token (parser)->location;
3513 value = convert_lvalue_to_rvalue (value_tok_loc,
3514 c_parser_expr_no_commas (parser, NULL),
3515 true, true).value;
3516 value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3517 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3518 {
3519 c_parser_consume_token (parser);
3520 switch (c_parser_peek_token (parser)->type)
3521 {
3522 case CPP_STRING:
3523 case CPP_STRING16:
3524 case CPP_STRING32:
3525 case CPP_WSTRING:
3526 case CPP_UTF8STRING:
3527 string = c_parser_string_literal (parser, false, true).value;
3528 break;
3529 default:
3530 c_parser_error (parser, gmsgid: "expected string literal");
3531 return;
3532 }
3533 }
3534 else if (flag_isoc11)
3535 /* If pedantic for pre-C11, the use of _Static_assert itself will
3536 have been diagnosed, so do not also diagnose the use of this
3537 new C23 feature of _Static_assert. */
3538 pedwarn_c11 (assert_loc, OPT_Wpedantic,
3539 "ISO C11 does not support omitting the string in "
3540 "%qE", spelling);
3541 parens.require_close (parser);
3542
3543 if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
3544 {
3545 error_at (value_loc, "expression in static assertion is not an integer");
3546 return;
3547 }
3548 if (TREE_CODE (value) != INTEGER_CST)
3549 {
3550 value = c_fully_fold (value, false, NULL);
3551 /* Strip no-op conversions. */
3552 STRIP_TYPE_NOPS (value);
3553 if (TREE_CODE (value) == INTEGER_CST)
3554 pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
3555 "is not an integer constant expression");
3556 }
3557 if (TREE_CODE (value) != INTEGER_CST)
3558 {
3559 error_at (value_loc, "expression in static assertion is not constant");
3560 return;
3561 }
3562 constant_expression_warning (value);
3563 if (integer_zerop (value))
3564 {
3565 if (string)
3566 error_at (assert_loc, "static assertion failed: %E", string);
3567 else
3568 error_at (assert_loc, "static assertion failed");
3569 }
3570}
3571
3572/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
3573 6.7, C11 6.7), adding them to SPECS (which may already include some).
3574 Storage class specifiers are accepted iff SCSPEC_OK; type
3575 specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
3576 accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
3577 iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
3578 addition to the syntax shown, standard attributes are accepted at
3579 the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
3580 unlike gnu-attributes, they are not accepted in the middle of the
3581 list. (This combines various different syntax productions in the C
3582 standard, and in some cases gnu-attributes and standard attributes
3583 at the start may already have been parsed before this function is
3584 called.)
3585
3586 declaration-specifiers:
3587 storage-class-specifier declaration-specifiers[opt]
3588 type-specifier declaration-specifiers[opt]
3589 type-qualifier declaration-specifiers[opt]
3590 function-specifier declaration-specifiers[opt]
3591 alignment-specifier declaration-specifiers[opt]
3592
3593 Function specifiers (inline) are from C99, and are currently
3594 handled as storage class specifiers, as is __thread. Alignment
3595 specifiers are from C11.
3596
3597 C90 6.5.1, C99 6.7.1, C11 6.7.1:
3598 storage-class-specifier:
3599 typedef
3600 extern
3601 static
3602 auto
3603 register
3604 _Thread_local
3605
3606 (_Thread_local is new in C11.)
3607
3608 C99 6.7.4, C11 6.7.4:
3609 function-specifier:
3610 inline
3611 _Noreturn
3612
3613 (_Noreturn is new in C11.)
3614
3615 C90 6.5.2, C99 6.7.2, C11 6.7.2:
3616 type-specifier:
3617 void
3618 char
3619 short
3620 int
3621 long
3622 float
3623 double
3624 signed
3625 unsigned
3626 _Bool
3627 _Complex
3628 [_Imaginary removed in C99 TC2]
3629 _BitInt ( constant-expression )
3630 struct-or-union-specifier
3631 enum-specifier
3632 typedef-name
3633 atomic-type-specifier
3634
3635 (_Bool and _Complex are new in C99.)
3636 (atomic-type-specifier is new in C11.)
3637 (_BitInt is new in C23.)
3638
3639 C90 6.5.3, C99 6.7.3, C11 6.7.3:
3640
3641 type-qualifier:
3642 const
3643 restrict
3644 volatile
3645 address-space-qualifier
3646 _Atomic
3647
3648 (restrict is new in C99.)
3649 (_Atomic is new in C11.)
3650
3651 GNU extensions:
3652
3653 declaration-specifiers:
3654 gnu-attributes declaration-specifiers[opt]
3655
3656 type-qualifier:
3657 address-space
3658
3659 address-space:
3660 identifier recognized by the target
3661
3662 storage-class-specifier:
3663 __thread
3664
3665 type-specifier:
3666 typeof-specifier
3667 __auto_type
3668 __intN
3669 _Decimal32
3670 _Decimal64
3671 _Decimal128
3672 _Fract
3673 _Accum
3674 _Sat
3675
3676 (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
3677 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
3678
3679 atomic-type-specifier
3680 _Atomic ( type-name )
3681
3682 Objective-C:
3683
3684 type-specifier:
3685 class-name objc-protocol-refs[opt]
3686 typedef-name objc-protocol-refs
3687 objc-protocol-refs
3688*/
3689
3690void
3691c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
3692 bool scspec_ok, bool typespec_ok, bool start_attr_ok,
3693 bool alignspec_ok, bool auto_type_ok,
3694 bool start_std_attr_ok, bool end_std_attr_ok,
3695 enum c_lookahead_kind la)
3696{
3697 bool attrs_ok = start_attr_ok;
3698 bool seen_type = specs->typespec_kind != ctsk_none;
3699
3700 if (!typespec_ok)
3701 gcc_assert (la == cla_prefer_id);
3702
3703 if (start_std_attr_ok
3704 && c_parser_nth_token_starts_std_attributes (parser, 1))
3705 {
3706 gcc_assert (!specs->non_std_attrs_seen_p);
3707 location_t loc = c_parser_peek_token (parser)->location;
3708 tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3709 declspecs_add_attrs (loc, specs, attrs);
3710 specs->non_std_attrs_seen_p = false;
3711 }
3712
3713 while (c_parser_next_token_is (parser, type: CPP_NAME)
3714 || c_parser_next_token_is (parser, type: CPP_KEYWORD)
3715 || (c_dialect_objc () && c_parser_next_token_is (parser, type: CPP_LESS)))
3716 {
3717 struct c_typespec t;
3718 tree attrs;
3719 tree align;
3720 location_t loc = c_parser_peek_token (parser)->location;
3721
3722 /* If we cannot accept a type, exit if the next token must start
3723 one. Also, if we already have seen a tagged definition,
3724 a typename would be an error anyway and likely the user
3725 has simply forgotten a semicolon, so we exit. */
3726 if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3727 && c_parser_next_tokens_start_typename (parser, la)
3728 && !c_parser_next_token_is_qualifier (parser)
3729 && !c_parser_next_token_is_keyword (parser, keyword: RID_ALIGNAS))
3730 break;
3731
3732 if (c_parser_next_token_is (parser, type: CPP_NAME))
3733 {
3734 c_token *name_token = c_parser_peek_token (parser);
3735 tree value = name_token->value;
3736 c_id_kind kind = name_token->id_kind;
3737
3738 if (kind == C_ID_ADDRSPACE)
3739 {
3740 addr_space_t as
3741 = name_token->keyword - RID_FIRST_ADDR_SPACE;
3742 declspecs_add_addrspace (name_token->location, specs, as);
3743 c_parser_consume_token (parser);
3744 attrs_ok = true;
3745 continue;
3746 }
3747
3748 gcc_assert (!c_parser_next_token_is_qualifier (parser));
3749
3750 /* If we cannot accept a type, and the next token must start one,
3751 exit. Do the same if we already have seen a tagged definition,
3752 since it would be an error anyway and likely the user has simply
3753 forgotten a semicolon. */
3754 if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
3755 break;
3756
3757 /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
3758 a C_ID_CLASSNAME. */
3759 c_parser_consume_token (parser);
3760 seen_type = true;
3761 attrs_ok = true;
3762 if (kind == C_ID_ID)
3763 {
3764 auto_diagnostic_group d;
3765 name_hint hint = lookup_name_fuzzy (value, FUZZY_LOOKUP_TYPENAME,
3766 loc);
3767 if (const char *suggestion = hint.suggestion ())
3768 {
3769 gcc_rich_location richloc (loc);
3770 richloc.add_fixit_replace (new_content: suggestion);
3771 error_at (&richloc,
3772 "unknown type name %qE; did you mean %qs?",
3773 value, suggestion);
3774 }
3775 else
3776 error_at (loc, "unknown type name %qE", value);
3777 t.kind = ctsk_typedef;
3778 t.spec = error_mark_node;
3779 }
3780 else if (kind == C_ID_TYPENAME
3781 && (!c_dialect_objc ()
3782 || c_parser_next_token_is_not (parser, type: CPP_LESS)))
3783 {
3784 t.kind = ctsk_typedef;
3785 /* For a typedef name, record the meaning, not the name.
3786 In case of 'foo foo, bar;'. */
3787 t.spec = lookup_name (value);
3788 }
3789 else
3790 {
3791 tree proto = NULL_TREE;
3792 gcc_assert (c_dialect_objc ());
3793 t.kind = ctsk_objc;
3794 if (c_parser_next_token_is (parser, type: CPP_LESS))
3795 proto = c_parser_objc_protocol_refs (parser);
3796 t.spec = objc_get_protocol_qualified_type (value, proto);
3797 }
3798 t.expr = NULL_TREE;
3799 t.expr_const_operands = true;
3800 t.has_enum_type_specifier = false;
3801 declspecs_add_type (name_token->location, specs, t);
3802 continue;
3803 }
3804 if (c_parser_next_token_is (parser, type: CPP_LESS))
3805 {
3806 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
3807 nisse@lysator.liu.se. */
3808 tree proto;
3809 gcc_assert (c_dialect_objc ());
3810 if (!typespec_ok || seen_type)
3811 break;
3812 proto = c_parser_objc_protocol_refs (parser);
3813 t.kind = ctsk_objc;
3814 t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
3815 t.expr = NULL_TREE;
3816 t.expr_const_operands = true;
3817 t.has_enum_type_specifier = false;
3818 declspecs_add_type (loc, specs, t);
3819 continue;
3820 }
3821 gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3822 switch (c_parser_peek_token (parser)->keyword)
3823 {
3824 case RID_STATIC:
3825 case RID_EXTERN:
3826 case RID_REGISTER:
3827 case RID_TYPEDEF:
3828 case RID_INLINE:
3829 case RID_NORETURN:
3830 case RID_AUTO:
3831 case RID_THREAD:
3832 case RID_CONSTEXPR:
3833 if (!scspec_ok)
3834 goto out;
3835 attrs_ok = true;
3836 /* TODO: Distinguish between function specifiers (inline, noreturn)
3837 and storage class specifiers, either here or in
3838 declspecs_add_scspec. */
3839 declspecs_add_scspec (loc, specs,
3840 c_parser_peek_token (parser)->value);
3841 c_parser_consume_token (parser);
3842 break;
3843 case RID_AUTO_TYPE:
3844 if (!auto_type_ok)
3845 goto out;
3846 /* Fall through. */
3847 case RID_UNSIGNED:
3848 case RID_LONG:
3849 case RID_SHORT:
3850 case RID_SIGNED:
3851 case RID_COMPLEX:
3852 case RID_INT:
3853 case RID_CHAR:
3854 case RID_FLOAT:
3855 case RID_DOUBLE:
3856 case RID_VOID:
3857 case RID_DFLOAT32:
3858 case RID_DFLOAT64:
3859 case RID_DFLOAT128:
3860 case RID_DFLOAT64X:
3861 CASE_RID_FLOATN_NX:
3862 case RID_BOOL:
3863 case RID_FRACT:
3864 case RID_ACCUM:
3865 case RID_SAT:
3866 case RID_INT_N_0:
3867 case RID_INT_N_1:
3868 case RID_INT_N_2:
3869 case RID_INT_N_3:
3870 if (!typespec_ok)
3871 goto out;
3872 attrs_ok = true;
3873 seen_type = true;
3874 if (c_dialect_objc ())
3875 parser->objc_need_raw_identifier = true;
3876 t.kind = ctsk_resword;
3877 t.spec = c_parser_peek_token (parser)->value;
3878 t.expr = NULL_TREE;
3879 t.expr_const_operands = true;
3880 t.has_enum_type_specifier = false;
3881 declspecs_add_type (loc, specs, t);
3882 c_parser_consume_token (parser);
3883 break;
3884 case RID_ENUM:
3885 if (!typespec_ok)
3886 goto out;
3887 attrs_ok = true;
3888 seen_type = true;
3889 t = c_parser_enum_specifier (parser);
3890 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3891 declspecs_add_type (loc, specs, t);
3892 break;
3893 case RID_STRUCT:
3894 case RID_UNION:
3895 if (!typespec_ok)
3896 goto out;
3897 attrs_ok = true;
3898 seen_type = true;
3899 t = c_parser_struct_or_union_specifier (parser);
3900 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3901 declspecs_add_type (loc, specs, t);
3902 break;
3903 case RID_TYPEOF:
3904 case RID_TYPEOF_UNQUAL:
3905 /* ??? The old parser rejected typeof after other type
3906 specifiers, but is a syntax error the best way of
3907 handling this? */
3908 if (!typespec_ok || seen_type)
3909 goto out;
3910 attrs_ok = true;
3911 seen_type = true;
3912 t = c_parser_typeof_specifier (parser);
3913 declspecs_add_type (loc, specs, t);
3914 break;
3915 case RID_BITINT:
3916 if (!typespec_ok)
3917 goto out;
3918 else
3919 {
3920 attrs_ok = true;
3921 seen_type = true;
3922 t.kind = ctsk_resword;
3923 t.spec = c_parser_peek_token (parser)->value;
3924 t.expr = error_mark_node;
3925 t.expr_const_operands = true;
3926 t.has_enum_type_specifier = false;
3927 c_parser_consume_token (parser);
3928 matching_parens parens;
3929 if (parens.require_open (parser))
3930 {
3931 c_expr expr = c_parser_expr_no_commas (parser, NULL);
3932 t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3933 true).value;
3934 parens.skip_until_found_close (parser);
3935 }
3936 declspecs_add_type (loc, specs, t);
3937 }
3938 break;
3939 case RID_ATOMIC:
3940 /* C parser handling of Objective-C constructs needs
3941 checking for correct lvalue-to-rvalue conversions, and
3942 the code in build_modify_expr handling various
3943 Objective-C cases, and that in build_unary_op handling
3944 Objective-C cases for increment / decrement, also needs
3945 updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
3946 and objc_types_are_equivalent may also need updates. */
3947 if (c_dialect_objc ())
3948 sorry ("%<_Atomic%> in Objective-C");
3949 if (flag_isoc99)
3950 pedwarn_c99 (loc, OPT_Wpedantic,
3951 "ISO C99 does not support the %<_Atomic%> qualifier");
3952 else
3953 pedwarn_c99 (loc, OPT_Wpedantic,
3954 "ISO C90 does not support the %<_Atomic%> qualifier");
3955 attrs_ok = true;
3956 tree value;
3957 value = c_parser_peek_token (parser)->value;
3958 c_parser_consume_token (parser);
3959 if (typespec_ok && c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
3960 {
3961 /* _Atomic ( type-name ). */
3962 seen_type = true;
3963 c_parser_consume_token (parser);
3964 struct c_type_name *type = c_parser_type_name (parser);
3965 t.kind = ctsk_typeof;
3966 t.spec = error_mark_node;
3967 t.expr = NULL_TREE;
3968 t.expr_const_operands = true;
3969 t.has_enum_type_specifier = false;
3970 if (type != NULL)
3971 t.spec = groktypename (type, &t.expr,
3972 &t.expr_const_operands);
3973 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
3974 msgid: "expected %<)%>");
3975 if (t.spec != error_mark_node)
3976 {
3977 if (TREE_CODE (t.spec) == ARRAY_TYPE)
3978 error_at (loc, "%<_Atomic%>-qualified array type");
3979 else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
3980 error_at (loc, "%<_Atomic%>-qualified function type");
3981 else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
3982 error_at (loc, "%<_Atomic%> applied to a qualified type");
3983 else
3984 t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
3985 }
3986 declspecs_add_type (loc, specs, t);
3987 }
3988 else
3989 declspecs_add_qual (loc, specs, value);
3990 break;
3991 case RID_CONST:
3992 case RID_VOLATILE:
3993 case RID_RESTRICT:
3994 attrs_ok = true;
3995 declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3996 c_parser_consume_token (parser);
3997 break;
3998 case RID_ATTRIBUTE:
3999 if (!attrs_ok)
4000 goto out;
4001 attrs = c_parser_gnu_attributes (parser);
4002 declspecs_add_attrs (loc, specs, attrs);
4003 break;
4004 case RID_ALIGNAS:
4005 if (!alignspec_ok)
4006 goto out;
4007 align = c_parser_alignas_specifier (parser);
4008 declspecs_add_alignas (loc, specs, align);
4009 break;
4010 case RID_GIMPLE:
4011 if (! flag_gimple)
4012 error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
4013 c_parser_consume_token (parser);
4014 specs->declspec_il = cdil_gimple;
4015 specs->locations[cdw_gimple] = loc;
4016 c_parser_gimple_or_rtl_pass_list (parser, specs);
4017 break;
4018 case RID_RTL:
4019 c_parser_consume_token (parser);
4020 specs->declspec_il = cdil_rtl;
4021 specs->locations[cdw_rtl] = loc;
4022 c_parser_gimple_or_rtl_pass_list (parser, specs);
4023 break;
4024 default:
4025 goto out;
4026 }
4027 }
4028 out:
4029 if (end_std_attr_ok
4030 && c_parser_nth_token_starts_std_attributes (parser, 1))
4031 specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
4032}
4033
4034/* Complain about a non-CPP_NAME within an enumerator list. */
4035
4036static void
4037report_bad_enum_name (c_parser *parser)
4038{
4039 if (!parser->error)
4040 {
4041 c_token *token = c_parser_peek_token (parser);
4042 switch (token->type)
4043 {
4044 default:
4045 break;
4046 case CPP_CLOSE_BRACE:
4047 /* Give a nicer error for "enum {}". */
4048 error_at (token->location,
4049 "empty enum is invalid");
4050 parser->error = true;
4051 return;
4052 case CPP_KEYWORD:
4053 /* Give a nicer error for attempts to use "true" and "false"
4054 in enums with C23 onwards. */
4055 if (token->keyword == RID_FALSE
4056 || token->keyword == RID_TRUE)
4057 {
4058 auto_diagnostic_group d;
4059 error_at (token->location,
4060 "cannot use keyword %qs as enumeration constant",
4061 IDENTIFIER_POINTER (token->value));
4062 add_note_about_new_keyword (loc: token->location,
4063 keyword_id: token->value);
4064 parser->error = true;
4065 return;
4066 }
4067 break;
4068 }
4069 }
4070
4071 /* Otherwise, a more generic error message. */
4072 c_parser_error (parser, gmsgid: "expected identifier");
4073}
4074
4075/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
4076
4077 enum-specifier:
4078 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
4079 { enumerator-list } gnu-attributes[opt]
4080 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
4081 { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
4082 enum gnu-attributes[opt] identifier
4083
4084 The form with trailing comma is new in C99; enum-type-specifiers
4085 are new in C23. The forms with gnu-attributes are GNU extensions.
4086 In GNU C, we accept any expression without commas in the syntax
4087 (assignment expressions, not just conditional expressions);
4088 assignment expressions will be diagnosed as non-constant.
4089
4090 enum-type-specifier:
4091 : specifier-qualifier-list
4092
4093 enumerator-list:
4094 enumerator
4095 enumerator-list , enumerator
4096
4097 enumerator:
4098 enumeration-constant attribute-specifier-sequence[opt]
4099 enumeration-constant attribute-specifier-sequence[opt]
4100 = constant-expression
4101
4102 GNU Extensions:
4103
4104 enumerator:
4105 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
4106 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
4107 = constant-expression
4108
4109*/
4110
4111static struct c_typespec
4112c_parser_enum_specifier (c_parser *parser)
4113{
4114 struct c_typespec ret;
4115 bool have_std_attrs;
4116 bool potential_nesting_p = false;
4117 tree std_attrs = NULL_TREE;
4118 tree attrs;
4119 tree ident = NULL_TREE;
4120 tree fixed_underlying_type = NULL_TREE;
4121 location_t enum_loc;
4122 location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4123 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
4124 c_parser_consume_token (parser);
4125 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4126 if (have_std_attrs)
4127 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4128 attrs = c_parser_gnu_attributes (parser);
4129 enum_loc = c_parser_peek_token (parser)->location;
4130 /* Set the location in case we create a decl now. */
4131 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
4132 if (c_parser_next_token_is (parser, type: CPP_NAME))
4133 {
4134 ident = c_parser_peek_token (parser)->value;
4135 ident_loc = c_parser_peek_token (parser)->location;
4136 enum_loc = ident_loc;
4137 c_parser_consume_token (parser);
4138 }
4139 if (c_parser_next_token_is (parser, type: CPP_COLON)
4140 /* Distinguish an enum-type-specifier from a bit-field
4141 declaration of the form "enum e : constant-expression;". */
4142 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
4143 {
4144 pedwarn_c11 (enum_loc, OPT_Wpedantic,
4145 "ISO C does not support specifying %<enum%> underlying "
4146 "types before C23");
4147 if (ident)
4148 {
4149 /* The tag is in scope during the enum-type-specifier (which
4150 may refer to the tag inside typeof). */
4151 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
4152 have_std_attrs, std_attrs, true);
4153 if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
4154 error_at (enum_loc, "%<enum%> declared both with and without "
4155 "fixed underlying type");
4156 potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
4157 }
4158 else
4159 {
4160 /* There must be an enum definition, so this initialization
4161 (to avoid possible warnings about uninitialized data)
4162 will be replaced later (either with the results of that
4163 definition, or with the results of error handling for the
4164 case of no tag and no definition). */
4165 ret.spec = NULL_TREE;
4166 ret.kind = ctsk_tagdef;
4167 ret.expr = NULL_TREE;
4168 ret.expr_const_operands = true;
4169 ret.has_enum_type_specifier = true;
4170 }
4171 c_parser_consume_token (parser);
4172 struct c_declspecs *specs = build_null_declspecs ();
4173 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: false, alignspec_ok: false, auto_type_ok: false,
4174 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_id);
4175 finish_declspecs (specs);
4176 if (specs->default_int_p)
4177 error_at (enum_loc, "no %<enum%> underlying type specified");
4178 else if (TREE_CODE (specs->type) != INTEGER_TYPE
4179 && TREE_CODE (specs->type) != BOOLEAN_TYPE)
4180 {
4181 error_at (enum_loc, "invalid %<enum%> underlying type");
4182 specs->type = integer_type_node;
4183 }
4184 else if (specs->restrict_p)
4185 error_at (enum_loc, "invalid use of %<restrict%>");
4186 fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
4187 if (ident)
4188 {
4189 /* The type specified must be consistent with any previously
4190 specified underlying type. If this is a newly declared
4191 type, it is now a complete type. */
4192 if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4193 && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
4194 {
4195 TYPE_MIN_VALUE (ret.spec) =
4196 TYPE_MIN_VALUE (fixed_underlying_type);
4197 TYPE_MAX_VALUE (ret.spec) =
4198 TYPE_MAX_VALUE (fixed_underlying_type);
4199 TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
4200 SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
4201 TYPE_SIZE (ret.spec) = NULL_TREE;
4202 TYPE_PRECISION (ret.spec) =
4203 TYPE_PRECISION (fixed_underlying_type);
4204 ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
4205 layout_type (ret.spec);
4206 }
4207 else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4208 && !comptypes (fixed_underlying_type,
4209 ENUM_UNDERLYING_TYPE (ret.spec)))
4210 {
4211 error_at (enum_loc, "%<enum%> underlying type incompatible with "
4212 "previous declaration");
4213 fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
4214 }
4215 }
4216 }
4217 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
4218 {
4219 /* Parse an enum definition. */
4220 struct c_enum_contents the_enum;
4221 tree type;
4222 tree postfix_attrs;
4223 /* We chain the enumerators in reverse order, then put them in
4224 forward order at the end. */
4225 tree values;
4226 timevar_push (tv: TV_PARSE_ENUM);
4227 type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
4228 potential_nesting_p);
4229 values = NULL_TREE;
4230 c_parser_consume_token (parser);
4231 while (true)
4232 {
4233 tree enum_id;
4234 tree enum_value;
4235 tree enum_decl;
4236 bool seen_comma;
4237 c_token *token;
4238 location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4239 location_t decl_loc, value_loc;
4240 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
4241 {
4242 report_bad_enum_name (parser);
4243 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4244 values = error_mark_node;
4245 break;
4246 }
4247 token = c_parser_peek_token (parser);
4248 enum_id = token->value;
4249 /* Set the location in case we create a decl now. */
4250 c_parser_set_source_position_from_token (token);
4251 decl_loc = value_loc = token->location;
4252 c_parser_consume_token (parser);
4253 /* Parse any specified attributes. */
4254 tree std_attrs = NULL_TREE;
4255 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4256 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4257 tree enum_attrs = chainon (std_attrs,
4258 c_parser_gnu_attributes (parser));
4259 if (c_parser_next_token_is (parser, type: CPP_EQ))
4260 {
4261 c_parser_consume_token (parser);
4262 value_loc = c_parser_peek_token (parser)->location;
4263 enum_value = convert_lvalue_to_rvalue (value_loc,
4264 (c_parser_expr_no_commas
4265 (parser, NULL)),
4266 true, true).value;
4267 }
4268 else
4269 enum_value = NULL_TREE;
4270 enum_decl = build_enumerator (decl_loc, value_loc,
4271 &the_enum, enum_id, enum_value);
4272 if (enum_attrs)
4273 decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
4274 TREE_CHAIN (enum_decl) = values;
4275 values = enum_decl;
4276 seen_comma = false;
4277 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4278 {
4279 comma_loc = c_parser_peek_token (parser)->location;
4280 seen_comma = true;
4281 c_parser_consume_token (parser);
4282 }
4283 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4284 {
4285 if (seen_comma)
4286 pedwarn_c90 (comma_loc, OPT_Wpedantic,
4287 "comma at end of enumerator list");
4288 c_parser_consume_token (parser);
4289 break;
4290 }
4291 if (!seen_comma)
4292 {
4293 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
4294 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4295 values = error_mark_node;
4296 break;
4297 }
4298 }
4299 postfix_attrs = c_parser_gnu_attributes (parser);
4300 ret.spec = finish_enum (type, nreverse (values),
4301 chainon (std_attrs,
4302 chainon (attrs, postfix_attrs)));
4303 ret.kind = ctsk_tagdef;
4304 ret.expr = NULL_TREE;
4305 ret.expr_const_operands = true;
4306 ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
4307 timevar_pop (tv: TV_PARSE_ENUM);
4308 return ret;
4309 }
4310 else if (!ident)
4311 {
4312 c_parser_error (parser, gmsgid: "expected %<{%>");
4313 ret.spec = error_mark_node;
4314 ret.kind = ctsk_tagref;
4315 ret.expr = NULL_TREE;
4316 ret.expr_const_operands = true;
4317 ret.has_enum_type_specifier = false;
4318 return ret;
4319 }
4320 /* Attributes may only appear when the members are defined or in
4321 certain forward declarations (treat enum forward declarations in
4322 GNU C analogously to struct and union forward declarations in
4323 standard C). */
4324 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4325 c_parser_error (parser, gmsgid: "expected %<;%>");
4326 if (fixed_underlying_type == NULL_TREE)
4327 {
4328 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
4329 std_attrs, false);
4330 /* In ISO C, enumerated types without a fixed underlying type
4331 can be referred to only if already defined. */
4332 if (pedantic && !COMPLETE_TYPE_P (ret.spec))
4333 {
4334 gcc_assert (ident);
4335 pedwarn (enum_loc, OPT_Wpedantic,
4336 "ISO C forbids forward references to %<enum%> types");
4337 }
4338 }
4339 return ret;
4340}
4341
4342/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
4343
4344 struct-or-union-specifier:
4345 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4346 identifier[opt] { struct-contents } gnu-attributes[opt]
4347 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4348 identifier
4349
4350 struct-contents:
4351 struct-declaration-list
4352
4353 struct-declaration-list:
4354 struct-declaration ;
4355 struct-declaration-list struct-declaration ;
4356
4357 GNU extensions:
4358
4359 struct-contents:
4360 empty
4361 struct-declaration
4362 struct-declaration-list struct-declaration
4363
4364 struct-declaration-list:
4365 struct-declaration-list ;
4366 ;
4367
4368 (Note that in the syntax here, unlike that in ISO C, the semicolons
4369 are included here rather than in struct-declaration, in order to
4370 describe the syntax with extra semicolons and missing semicolon at
4371 end.)
4372
4373 Objective-C:
4374
4375 struct-declaration-list:
4376 @defs ( class-name )
4377
4378 (Note this does not include a trailing semicolon, but can be
4379 followed by further declarations, and gets a pedwarn-if-pedantic
4380 when followed by a semicolon.) */
4381
4382static struct c_typespec
4383c_parser_struct_or_union_specifier (c_parser *parser)
4384{
4385 struct c_typespec ret;
4386 bool have_std_attrs;
4387 tree std_attrs = NULL_TREE;
4388 tree attrs;
4389 tree ident = NULL_TREE;
4390 location_t struct_loc;
4391 location_t ident_loc = UNKNOWN_LOCATION;
4392 enum tree_code code;
4393 switch (c_parser_peek_token (parser)->keyword)
4394 {
4395 case RID_STRUCT:
4396 code = RECORD_TYPE;
4397 break;
4398 case RID_UNION:
4399 code = UNION_TYPE;
4400 break;
4401 default:
4402 gcc_unreachable ();
4403 }
4404 struct_loc = c_parser_peek_token (parser)->location;
4405 c_parser_consume_token (parser);
4406 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4407 if (have_std_attrs)
4408 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4409 attrs = c_parser_gnu_attributes (parser);
4410
4411 /* Set the location in case we create a decl now. */
4412 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
4413
4414 if (c_parser_next_token_is (parser, type: CPP_NAME))
4415 {
4416 ident = c_parser_peek_token (parser)->value;
4417 ident_loc = c_parser_peek_token (parser)->location;
4418 struct_loc = ident_loc;
4419 c_parser_consume_token (parser);
4420 }
4421 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
4422 {
4423 /* Parse a struct or union definition. Start the scope of the
4424 tag before parsing components. */
4425 class c_struct_parse_info *struct_info;
4426 tree type = start_struct (struct_loc, code, ident, &struct_info);
4427 tree postfix_attrs;
4428 /* We chain the components in reverse order, then put them in
4429 forward order at the end. Each struct-declaration may
4430 declare multiple components (comma-separated), so we must use
4431 chainon to join them, although when parsing each
4432 struct-declaration we can use TREE_CHAIN directly.
4433
4434 The theory behind all this is that there will be more
4435 semicolon separated fields than comma separated fields, and
4436 so we'll be minimizing the number of node traversals required
4437 by chainon. */
4438 tree contents;
4439 tree expr = NULL;
4440 timevar_push (tv: TV_PARSE_STRUCT);
4441 contents = NULL_TREE;
4442 c_parser_consume_token (parser);
4443 /* Handle the Objective-C @defs construct,
4444 e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4445 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_DEFS))
4446 {
4447 tree name;
4448 gcc_assert (c_dialect_objc ());
4449 c_parser_consume_token (parser);
4450 matching_parens parens;
4451 if (!parens.require_open (parser))
4452 goto end_at_defs;
4453 if (c_parser_next_token_is (parser, type: CPP_NAME)
4454 && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4455 {
4456 name = c_parser_peek_token (parser)->value;
4457 c_parser_consume_token (parser);
4458 }
4459 else
4460 {
4461 c_parser_error (parser, gmsgid: "expected class name");
4462 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4463 goto end_at_defs;
4464 }
4465 parens.skip_until_found_close (parser);
4466 contents = nreverse (objc_get_class_ivars (name));
4467 }
4468 end_at_defs:
4469 /* Parse the struct-declarations and semicolons. Problems with
4470 semicolons are diagnosed here; empty structures are diagnosed
4471 elsewhere. */
4472 while (true)
4473 {
4474 tree decls;
4475 /* Parse any stray semicolon. */
4476 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4477 {
4478 location_t semicolon_loc
4479 = c_parser_peek_token (parser)->location;
4480 gcc_rich_location richloc (semicolon_loc);
4481 richloc.add_fixit_remove ();
4482 pedwarn (&richloc, OPT_Wpedantic,
4483 "extra semicolon in struct or union specified");
4484 c_parser_consume_token (parser);
4485 continue;
4486 }
4487 /* Stop if at the end of the struct or union contents. */
4488 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4489 {
4490 c_parser_consume_token (parser);
4491 break;
4492 }
4493 /* Accept #pragmas at struct scope. */
4494 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
4495 {
4496 c_parser_pragma (parser, pragma_struct, NULL, NULL_TREE);
4497 continue;
4498 }
4499 /* Parse some comma-separated declarations, but not the
4500 trailing semicolon if any. */
4501 decls = c_parser_struct_declaration (parser, &expr);
4502 contents = chainon (decls, contents);
4503 /* If no semicolon follows, either we have a parse error or
4504 are at the end of the struct or union and should
4505 pedwarn. */
4506 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4507 c_parser_consume_token (parser);
4508 else
4509 {
4510 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4511 pedwarn (c_parser_peek_token (parser)->location, 0,
4512 "no semicolon at end of struct or union");
4513 else if (parser->error
4514 || !c_parser_next_token_starts_declspecs (parser))
4515 {
4516 c_parser_error (parser, gmsgid: "expected %<;%>");
4517 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4518 break;
4519 }
4520
4521 /* If we come here, we have already emitted an error
4522 for an expected `;', identifier or `(', and we also
4523 recovered already. Go on with the next field. */
4524 }
4525 }
4526 postfix_attrs = c_parser_gnu_attributes (parser);
4527 ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4528 chainon (std_attrs,
4529 chainon (attrs, postfix_attrs)),
4530 struct_info, expr: &expr);
4531 ret.kind = ctsk_tagdef;
4532 ret.expr = expr;
4533 ret.expr_const_operands = true;
4534 ret.has_enum_type_specifier = false;
4535 timevar_pop (tv: TV_PARSE_STRUCT);
4536 return ret;
4537 }
4538 else if (!ident)
4539 {
4540 c_parser_error (parser, gmsgid: "expected %<{%>");
4541 ret.spec = error_mark_node;
4542 ret.kind = ctsk_tagref;
4543 ret.expr = NULL_TREE;
4544 ret.expr_const_operands = true;
4545 ret.has_enum_type_specifier = false;
4546 return ret;
4547 }
4548 /* Attributes may only appear when the members are defined or in
4549 certain forward declarations. */
4550 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4551 c_parser_error (parser, gmsgid: "expected %<;%>");
4552 /* ??? Existing practice is that GNU attributes are ignored after
4553 the struct or union keyword when not defining the members. */
4554 ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4555 false);
4556 return ret;
4557}
4558
4559/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4560 *without* the trailing semicolon.
4561
4562 struct-declaration:
4563 attribute-specifier-sequence[opt] specifier-qualifier-list
4564 attribute-specifier-sequence[opt] struct-declarator-list
4565 static_assert-declaration-no-semi
4566
4567 specifier-qualifier-list:
4568 type-specifier specifier-qualifier-list[opt]
4569 type-qualifier specifier-qualifier-list[opt]
4570 alignment-specifier specifier-qualifier-list[opt]
4571 gnu-attributes specifier-qualifier-list[opt]
4572
4573 struct-declarator-list:
4574 struct-declarator
4575 struct-declarator-list , gnu-attributes[opt] struct-declarator
4576
4577 struct-declarator:
4578 declarator gnu-attributes[opt]
4579 declarator[opt] : constant-expression gnu-attributes[opt]
4580
4581 GNU extensions:
4582
4583 struct-declaration:
4584 __extension__ struct-declaration
4585 specifier-qualifier-list
4586
4587 Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4588 of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4589 any expression without commas in the syntax (assignment
4590 expressions, not just conditional expressions); assignment
4591 expressions will be diagnosed as non-constant. */
4592
4593static tree
4594c_parser_struct_declaration (c_parser *parser, tree *expr)
4595{
4596 struct c_declspecs *specs;
4597 tree prefix_attrs;
4598 tree all_prefix_attrs;
4599 tree decls;
4600 location_t decl_loc;
4601 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
4602 {
4603 int ext;
4604 tree decl;
4605 ext = disable_extension_diagnostics ();
4606 c_parser_consume_token (parser);
4607 decl = c_parser_struct_declaration (parser, expr);
4608 restore_extension_diagnostics (flags: ext);
4609 return decl;
4610 }
4611 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
4612 {
4613 c_parser_static_assert_declaration_no_semi (parser);
4614 return NULL_TREE;
4615 }
4616 specs = build_null_declspecs ();
4617 decl_loc = c_parser_peek_token (parser)->location;
4618 /* Strictly by the standard, we shouldn't allow _Alignas here,
4619 but it appears to have been intended to allow it there, so
4620 we're keeping it as it is until WG14 reaches a conclusion
4621 of N1731.
4622 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4623 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true,
4624 alignspec_ok: true, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: true, la: cla_nonabstract_decl);
4625 if (parser->error)
4626 return NULL_TREE;
4627 if (!specs->declspecs_seen_p)
4628 {
4629 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
4630 return NULL_TREE;
4631 }
4632 finish_declspecs (specs);
4633 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4634 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4635 {
4636 tree ret;
4637 if (specs->typespec_kind == ctsk_none)
4638 {
4639 pedwarn (decl_loc, OPT_Wpedantic,
4640 "ISO C forbids member declarations with no members");
4641 shadow_tag_warned (specs, pedantic);
4642 ret = NULL_TREE;
4643 }
4644 else
4645 {
4646 /* Support for unnamed structs or unions as members of
4647 structs or unions (which is [a] useful and [b] supports
4648 MS P-SDK). */
4649 tree attrs = NULL;
4650
4651 ret = grokfield (c_parser_peek_token (parser)->location,
4652 build_id_declarator (NULL_TREE), specs,
4653 NULL_TREE, &attrs, expr);
4654 if (ret)
4655 decl_attributes (&ret, attrs, 0);
4656 }
4657 return ret;
4658 }
4659
4660 /* Provide better error recovery. Note that a type name here is valid,
4661 and will be treated as a field name. */
4662 if (specs->typespec_kind == ctsk_tagdef
4663 && TREE_CODE (specs->type) != ENUMERAL_TYPE
4664 && c_parser_next_token_starts_declspecs (parser)
4665 && !c_parser_next_token_is (parser, type: CPP_NAME))
4666 {
4667 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
4668 parser->error = false;
4669 return NULL_TREE;
4670 }
4671
4672 pending_xref_error ();
4673 prefix_attrs = specs->attrs;
4674 all_prefix_attrs = prefix_attrs;
4675 specs->attrs = NULL_TREE;
4676 decls = NULL_TREE;
4677 while (true)
4678 {
4679 /* Declaring one or more declarators or un-named bit-fields. */
4680 struct c_declarator *declarator;
4681 bool dummy = false;
4682 if (c_parser_next_token_is (parser, type: CPP_COLON))
4683 declarator = build_id_declarator (NULL_TREE);
4684 else
4685 declarator = c_parser_declarator (parser,
4686 type_seen_p: specs->typespec_kind != ctsk_none,
4687 kind: C_DTR_NORMAL, seen_id: &dummy);
4688 if (declarator == NULL)
4689 {
4690 c_parser_skip_to_end_of_block_or_statement (parser);
4691 break;
4692 }
4693 if (c_parser_next_token_is (parser, type: CPP_COLON)
4694 || c_parser_next_token_is (parser, type: CPP_COMMA)
4695 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4696 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
4697 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4698 {
4699 tree postfix_attrs = NULL_TREE;
4700 tree width = NULL_TREE;
4701 tree d;
4702 if (c_parser_next_token_is (parser, type: CPP_COLON))
4703 {
4704 c_parser_consume_token (parser);
4705 location_t loc = c_parser_peek_token (parser)->location;
4706 width = convert_lvalue_to_rvalue (loc,
4707 (c_parser_expr_no_commas
4708 (parser, NULL)),
4709 true, true).value;
4710 }
4711 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4712 postfix_attrs = c_parser_gnu_attributes (parser);
4713 d = grokfield (c_parser_peek_token (parser)->location,
4714 declarator, specs, width, &all_prefix_attrs, expr);
4715 decl_attributes (&d, chainon (postfix_attrs,
4716 all_prefix_attrs), 0);
4717 DECL_CHAIN (d) = decls;
4718 decls = d;
4719 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4720 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4721 prefix_attrs);
4722 else
4723 all_prefix_attrs = prefix_attrs;
4724 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4725 c_parser_consume_token (parser);
4726 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4727 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4728 {
4729 /* Semicolon consumed in caller. */
4730 break;
4731 }
4732 else
4733 {
4734 c_parser_error (parser, gmsgid: "expected %<,%>, %<;%> or %<}%>");
4735 break;
4736 }
4737 }
4738 else
4739 {
4740 c_parser_error (parser,
4741 gmsgid: "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4742 "%<__attribute__%>");
4743 break;
4744 }
4745 }
4746 return decls;
4747}
4748
4749/* Parse a typeof specifier (a GNU extension adopted in C23).
4750
4751 typeof-specifier:
4752 typeof ( expression )
4753 typeof ( type-name )
4754 typeof_unqual ( expression )
4755 typeof_unqual ( type-name )
4756*/
4757
4758static struct c_typespec
4759c_parser_typeof_specifier (c_parser *parser)
4760{
4761 bool is_unqual;
4762 bool is_std;
4763 struct c_typespec ret;
4764 ret.kind = ctsk_typeof;
4765 ret.spec = error_mark_node;
4766 ret.expr = NULL_TREE;
4767 ret.expr_const_operands = true;
4768 ret.has_enum_type_specifier = false;
4769 if (c_parser_next_token_is_keyword (parser, keyword: RID_TYPEOF))
4770 {
4771 is_unqual = false;
4772 tree spelling = c_parser_peek_token (parser)->value;
4773 is_std = (flag_isoc23
4774 && strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof") == 0);
4775 }
4776 else
4777 {
4778 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4779 is_unqual = true;
4780 tree spelling = c_parser_peek_token (parser)->value;
4781 is_std = strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof_unqual") == 0;
4782 }
4783 c_parser_consume_token (parser);
4784 c_inhibit_evaluation_warnings++;
4785 in_typeof++;
4786 matching_parens parens;
4787 if (!parens.require_open (parser))
4788 {
4789 c_inhibit_evaluation_warnings--;
4790 in_typeof--;
4791 return ret;
4792 }
4793 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4794 {
4795 struct c_type_name *type = c_parser_type_name (parser);
4796 c_inhibit_evaluation_warnings--;
4797 in_typeof--;
4798 if (type != NULL)
4799 {
4800 ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4801 pop_maybe_used (c_type_variably_modified_p (t: ret.spec));
4802 }
4803 }
4804 else
4805 {
4806 bool was_vm;
4807 location_t here = c_parser_peek_token (parser)->location;
4808 struct c_expr expr = c_parser_expression (parser);
4809 c_inhibit_evaluation_warnings--;
4810 in_typeof--;
4811 if (TREE_CODE (expr.value) == COMPONENT_REF
4812 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4813 error_at (here, "%<typeof%> applied to a bit-field");
4814 mark_exp_read (expr.value);
4815 ret.spec = TREE_TYPE (expr.value);
4816 was_vm = c_type_variably_modified_p (t: ret.spec);
4817 /* This is returned with the type so that when the type is
4818 evaluated, this can be evaluated. */
4819 if (was_vm)
4820 ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4821 pop_maybe_used (was_vm);
4822 }
4823 parens.skip_until_found_close (parser);
4824 if (ret.spec != error_mark_node)
4825 {
4826 if (is_unqual)
4827 {
4828 bool is_array = TREE_CODE (ret.spec) == ARRAY_TYPE;
4829 int quals = TYPE_QUALS (strip_array_types (ret.spec));
4830 if ((is_array ? quals & ~TYPE_QUAL_ATOMIC : quals)
4831 != TYPE_UNQUALIFIED)
4832 {
4833 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4834 if (quals & TYPE_QUAL_ATOMIC && is_array)
4835 ret.spec = c_build_qualified_type (ret.spec,
4836 TYPE_QUAL_ATOMIC);
4837 }
4838 }
4839 if (is_std)
4840 {
4841 /* In ISO C terms, _Noreturn is not part of the type of
4842 expressions such as &abort, but in GCC it is represented
4843 internally as a type qualifier. */
4844 if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4845 && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4846 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4847 else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4848 && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4849 ret.spec
4850 = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4851 }
4852 }
4853 return ret;
4854}
4855
4856/* Parse an alignment-specifier.
4857
4858 C11 6.7.5:
4859
4860 alignment-specifier:
4861 _Alignas ( type-name )
4862 _Alignas ( constant-expression )
4863*/
4864
4865static tree
4866c_parser_alignas_specifier (c_parser * parser)
4867{
4868 tree ret = error_mark_node;
4869 location_t loc = c_parser_peek_token (parser)->location;
4870 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4871 tree spelling = c_parser_peek_token (parser)->value;
4872 c_parser_consume_token (parser);
4873 if (flag_isoc99)
4874 pedwarn_c99 (loc, OPT_Wpedantic,
4875 "ISO C99 does not support %qE", spelling);
4876 else
4877 pedwarn_c99 (loc, OPT_Wpedantic,
4878 "ISO C90 does not support %qE", spelling);
4879 matching_parens parens;
4880 if (!parens.require_open (parser))
4881 return ret;
4882 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4883 {
4884 struct c_type_name *type = c_parser_type_name (parser);
4885 if (type != NULL)
4886 ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4887 false, true, 1);
4888 }
4889 else
4890 ret = convert_lvalue_to_rvalue (loc,
4891 c_parser_expr_no_commas (parser, NULL),
4892 true, true).value;
4893 parens.skip_until_found_close (parser);
4894 return ret;
4895}
4896
4897/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4898 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4899 a typedef name may be redeclared; otherwise it may not. KIND
4900 indicates which kind of declarator is wanted. Returns a valid
4901 declarator except in the case of a syntax error in which case NULL is
4902 returned. *SEEN_ID is set to true if an identifier being declared is
4903 seen; this is used to diagnose bad forms of abstract array declarators
4904 and to determine whether an identifier list is syntactically permitted.
4905
4906 declarator:
4907 pointer[opt] direct-declarator
4908
4909 direct-declarator:
4910 identifier
4911 ( gnu-attributes[opt] declarator )
4912 direct-declarator array-declarator
4913 direct-declarator ( parameter-type-list )
4914 direct-declarator ( identifier-list[opt] )
4915
4916 pointer:
4917 * type-qualifier-list[opt]
4918 * type-qualifier-list[opt] pointer
4919
4920 type-qualifier-list:
4921 type-qualifier
4922 gnu-attributes
4923 type-qualifier-list type-qualifier
4924 type-qualifier-list gnu-attributes
4925
4926 array-declarator:
4927 [ type-qualifier-list[opt] assignment-expression[opt] ]
4928 [ static type-qualifier-list[opt] assignment-expression ]
4929 [ type-qualifier-list static assignment-expression ]
4930 [ type-qualifier-list[opt] * ]
4931
4932 parameter-type-list:
4933 parameter-list
4934 parameter-list , ...
4935
4936 parameter-list:
4937 parameter-declaration
4938 parameter-list , parameter-declaration
4939
4940 parameter-declaration:
4941 declaration-specifiers declarator gnu-attributes[opt]
4942 declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4943
4944 identifier-list:
4945 identifier
4946 identifier-list , identifier
4947
4948 abstract-declarator:
4949 pointer
4950 pointer[opt] direct-abstract-declarator
4951
4952 direct-abstract-declarator:
4953 ( gnu-attributes[opt] abstract-declarator )
4954 direct-abstract-declarator[opt] array-declarator
4955 direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4956
4957 GNU extensions:
4958
4959 direct-declarator:
4960 direct-declarator ( parameter-forward-declarations
4961 parameter-type-list[opt] )
4962
4963 direct-abstract-declarator:
4964 direct-abstract-declarator[opt] ( parameter-forward-declarations
4965 parameter-type-list[opt] )
4966
4967 parameter-forward-declarations:
4968 parameter-list ;
4969 parameter-forward-declarations parameter-list ;
4970
4971 The uses of gnu-attributes shown above are GNU extensions.
4972
4973 Some forms of array declarator are not included in C99 in the
4974 syntax for abstract declarators; these are disallowed elsewhere.
4975 This may be a defect (DR#289).
4976
4977 This function also accepts an omitted abstract declarator as being
4978 an abstract declarator, although not part of the formal syntax. */
4979
4980struct c_declarator *
4981c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4982 bool *seen_id)
4983{
4984 /* Parse any initial pointer part. */
4985 if (c_parser_next_token_is (parser, type: CPP_MULT))
4986 {
4987 struct c_declspecs *quals_attrs = build_null_declspecs ();
4988 struct c_declarator *inner;
4989 c_parser_consume_token (parser);
4990 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4991 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: false, la: cla_prefer_id);
4992 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4993 if (inner == NULL)
4994 return NULL;
4995 else
4996 return make_pointer_declarator (quals_attrs, inner);
4997 }
4998 /* Now we have a direct declarator, direct abstract declarator or
4999 nothing (which counts as a direct abstract declarator here). */
5000 return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
5001}
5002
5003/* Parse a direct declarator or direct abstract declarator; arguments
5004 as c_parser_declarator. */
5005
5006static struct c_declarator *
5007c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
5008 bool *seen_id)
5009{
5010 /* The direct declarator must start with an identifier (possibly
5011 omitted) or a parenthesized declarator (possibly abstract). In
5012 an ordinary declarator, initial parentheses must start a
5013 parenthesized declarator. In an abstract declarator or parameter
5014 declarator, they could start a parenthesized declarator or a
5015 parameter list. To tell which, the open parenthesis and any
5016 following gnu-attributes must be read. If a declaration
5017 specifier or standard attributes follow, then it is a parameter
5018 list; if the specifier is a typedef name, there might be an
5019 ambiguity about redeclaring it, which is resolved in the
5020 direction of treating it as a typedef name. If a close
5021 parenthesis follows, it is also an empty parameter list, as the
5022 syntax does not permit empty abstract declarators. Otherwise, it
5023 is a parenthesized declarator (in which case the analysis may be
5024 repeated inside it, recursively).
5025
5026 ??? There is an ambiguity in a parameter declaration "int
5027 (__attribute__((foo)) x)", where x is not a typedef name: it
5028 could be an abstract declarator for a function, or declare x with
5029 parentheses. The proper resolution of this ambiguity needs
5030 documenting. At present we follow an accident of the old
5031 parser's implementation, whereby the first parameter must have
5032 some declaration specifiers other than just gnu-attributes. Thus as
5033 a parameter declaration it is treated as a parenthesized
5034 parameter named x, and as an abstract declarator it is
5035 rejected.
5036
5037 ??? Also following the old parser, gnu-attributes inside an empty
5038 parameter list are ignored, making it a list not yielding a
5039 prototype, rather than giving an error or making it have one
5040 parameter with implicit type int.
5041
5042 ??? Also following the old parser, typedef names may be
5043 redeclared in declarators, but not Objective-C class names. */
5044
5045 if (kind != C_DTR_ABSTRACT
5046 && c_parser_next_token_is (parser, type: CPP_NAME)
5047 && ((type_seen_p
5048 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
5049 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
5050 || c_parser_peek_token (parser)->id_kind == C_ID_ID))
5051 {
5052 struct c_declarator *inner
5053 = build_id_declarator (c_parser_peek_token (parser)->value);
5054 *seen_id = true;
5055 inner->id_loc = c_parser_peek_token (parser)->location;
5056 c_parser_consume_token (parser);
5057 if (c_parser_nth_token_starts_std_attributes (parser, 1))
5058 inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
5059 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5060 }
5061
5062 if (kind != C_DTR_NORMAL
5063 && c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
5064 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5065 {
5066 struct c_declarator *inner = build_id_declarator (NULL_TREE);
5067 inner->id_loc = c_parser_peek_token (parser)->location;
5068 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5069 }
5070
5071 /* Either we are at the end of an abstract declarator, or we have
5072 parentheses. */
5073
5074 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
5075 {
5076 tree attrs;
5077 struct c_declarator *inner;
5078 c_parser_consume_token (parser);
5079 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5080 keyword: RID_ATTRIBUTE);
5081 attrs = c_parser_gnu_attributes (parser);
5082 if (kind != C_DTR_NORMAL
5083 && (c_parser_next_token_starts_declspecs (parser)
5084 || (!have_gnu_attrs
5085 && (c_parser_nth_token_starts_std_attributes (parser, 1)
5086 || c_parser_next_token_is (parser, type: CPP_ELLIPSIS)))
5087 || c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN)))
5088 {
5089 struct c_arg_info *args
5090 = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
5091 attrs, have_gnu_attrs);
5092 if (args == NULL)
5093 return NULL;
5094 else
5095 {
5096 inner = build_id_declarator (NULL_TREE);
5097 if (!(args->types
5098 && args->types != error_mark_node
5099 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5100 && c_parser_nth_token_starts_std_attributes (parser, 1))
5101 {
5102 tree std_attrs
5103 = c_parser_std_attribute_specifier_sequence (parser);
5104 if (std_attrs)
5105 inner = build_attrs_declarator (std_attrs, inner);
5106 }
5107 inner = build_function_declarator (args, inner);
5108 return c_parser_direct_declarator_inner (parser, *seen_id,
5109 inner);
5110 }
5111 }
5112 /* A parenthesized declarator. */
5113 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
5114 if (inner != NULL && attrs != NULL)
5115 inner = build_attrs_declarator (attrs, inner);
5116 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5117 {
5118 c_parser_consume_token (parser);
5119 if (inner == NULL)
5120 return NULL;
5121 else
5122 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5123 }
5124 else
5125 {
5126 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5127 msgid: "expected %<)%>");
5128 return NULL;
5129 }
5130 }
5131 else
5132 {
5133 if (kind == C_DTR_NORMAL)
5134 {
5135 c_parser_error (parser, gmsgid: "expected identifier or %<(%>");
5136 return NULL;
5137 }
5138 else
5139 return build_id_declarator (NULL_TREE);
5140 }
5141}
5142
5143/* Parse part of a direct declarator or direct abstract declarator,
5144 given that some (in INNER) has already been parsed; ID_PRESENT is
5145 true if an identifier is present, false for an abstract
5146 declarator. */
5147
5148static struct c_declarator *
5149c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
5150 struct c_declarator *inner)
5151{
5152 /* Parse a sequence of array declarators and parameter lists. */
5153 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
5154 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5155 {
5156 location_t brace_loc = c_parser_peek_token (parser)->location;
5157 struct c_declarator *declarator;
5158 struct c_declspecs *quals_attrs = build_null_declspecs ();
5159 struct c_expr dimen;
5160 dimen.value = NULL_TREE;
5161 dimen.original_code = ERROR_MARK;
5162 dimen.original_type = NULL_TREE;
5163 c_parser_consume_token (parser);
5164 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
5165 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
5166
5167 location_t static_loc = UNKNOWN_LOCATION;
5168 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
5169 {
5170 static_loc = c_parser_peek_token (parser)->location;
5171 c_parser_consume_token (parser);
5172 if (!quals_attrs->declspecs_seen_p)
5173 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
5174 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
5175 }
5176 if (!quals_attrs->declspecs_seen_p)
5177 quals_attrs = NULL;
5178 /* If "static" is present, there must be an array dimension.
5179 Otherwise, there may be a dimension, "*", or no
5180 dimension. */
5181 const bool static_seen = (static_loc != UNKNOWN_LOCATION);
5182 bool star_seen = false;
5183 if (c_parser_next_token_is (parser, type: CPP_MULT)
5184 && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
5185 {
5186 star_seen = true;
5187 c_parser_consume_token (parser);
5188 }
5189 else if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
5190 dimen = c_parser_expr_no_commas (parser, NULL);
5191
5192 if (static_seen)
5193 {
5194 if (star_seen)
5195 {
5196 error_at (static_loc,
5197 "%<static%> may not be used with an unspecified "
5198 "variable length array size");
5199 /* Prevent further errors. */
5200 star_seen = false;
5201 dimen.value = error_mark_node;
5202 }
5203 else if (!dimen.value)
5204 error_at (static_loc,
5205 "%<static%> may not be used without an array size");
5206 }
5207
5208 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
5209 c_parser_consume_token (parser);
5210 else
5211 {
5212 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
5213 msgid: "expected %<]%>");
5214 return NULL;
5215 }
5216 if (dimen.value)
5217 dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
5218 declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
5219 static_seen, star_seen);
5220 if (declarator == NULL)
5221 return NULL;
5222 if (c_parser_nth_token_starts_std_attributes (parser, 1))
5223 {
5224 tree std_attrs
5225 = c_parser_std_attribute_specifier_sequence (parser);
5226 if (std_attrs)
5227 inner = build_attrs_declarator (std_attrs, inner);
5228 }
5229 inner = set_array_declarator_inner (declarator, inner);
5230 return c_parser_direct_declarator_inner (parser, id_present, inner);
5231 }
5232 else if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
5233 {
5234 tree attrs;
5235 struct c_arg_info *args;
5236 c_parser_consume_token (parser);
5237 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5238 keyword: RID_ATTRIBUTE);
5239 attrs = c_parser_gnu_attributes (parser);
5240 args = c_parser_parms_declarator (parser, id_present, attrs,
5241 have_gnu_attrs);
5242 if (args == NULL)
5243 return NULL;
5244 else
5245 {
5246 if (!(args->types
5247 && args->types != error_mark_node
5248 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5249 && c_parser_nth_token_starts_std_attributes (parser, 1))
5250 {
5251 tree std_attrs
5252 = c_parser_std_attribute_specifier_sequence (parser);
5253 if (std_attrs)
5254 inner = build_attrs_declarator (std_attrs, inner);
5255 }
5256 inner = build_function_declarator (args, inner);
5257 return c_parser_direct_declarator_inner (parser, id_present, inner);
5258 }
5259 }
5260 return inner;
5261}
5262
5263/* Parse a parameter list or identifier list, including the closing
5264 parenthesis but not the opening one. ATTRS are the gnu-attributes
5265 at the start of the list. ID_LIST_OK is true if an identifier list
5266 is acceptable; such a list must not have attributes at the start.
5267 HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
5268 attributes) were present (in which case standard attributes cannot
5269 occur). */
5270
5271static struct c_arg_info *
5272c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
5273 bool have_gnu_attrs)
5274{
5275 push_scope ();
5276 declare_parm_level ();
5277 /* If the list starts with an identifier, it is an identifier list.
5278 Otherwise, it is either a prototype list or an empty list. */
5279 if (id_list_ok
5280 && !attrs
5281 && c_parser_next_token_is (parser, type: CPP_NAME)
5282 && c_parser_peek_token (parser)->id_kind == C_ID_ID
5283
5284 /* Look ahead to detect typos in type names. */
5285 && c_parser_peek_2nd_token (parser)->type != CPP_NAME
5286 && c_parser_peek_2nd_token (parser)->type != CPP_MULT
5287 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
5288 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
5289 && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
5290 {
5291 tree list = NULL_TREE, *nextp = &list;
5292 while (c_parser_next_token_is (parser, type: CPP_NAME)
5293 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
5294 {
5295 *nextp = build_tree_list (NULL_TREE,
5296 c_parser_peek_token (parser)->value);
5297 nextp = & TREE_CHAIN (*nextp);
5298 c_parser_consume_token (parser);
5299 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5300 break;
5301 c_parser_consume_token (parser);
5302 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5303 {
5304 c_parser_error (parser, gmsgid: "expected identifier");
5305 break;
5306 }
5307 }
5308 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5309 {
5310 struct c_arg_info *ret = build_arg_info ();
5311 ret->types = list;
5312 c_parser_consume_token (parser);
5313 pop_scope ();
5314 return ret;
5315 }
5316 else
5317 {
5318 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5319 msgid: "expected %<)%>");
5320 pop_scope ();
5321 return NULL;
5322 }
5323 }
5324 else
5325 {
5326 struct c_arg_info *ret
5327 = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
5328 pop_scope ();
5329 return ret;
5330 }
5331}
5332
5333/* Parse a parameter list (possibly empty), including the closing
5334 parenthesis but not the opening one. ATTRS are the gnu-attributes
5335 at the start of the list; if HAVE_GNU_ATTRS, there were some such
5336 attributes (possibly empty, in which case ATTRS is NULL_TREE),
5337 which means standard attributes cannot start the list. EXPR is
5338 NULL or an expression that needs to be evaluated for the side
5339 effects of array size expressions in the parameters. */
5340
5341static struct c_arg_info *
5342c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
5343 bool have_gnu_attrs)
5344{
5345 bool bad_parm = false;
5346
5347 /* ??? Following the old parser, forward parameter declarations may
5348 use abstract declarators, and if no real parameter declarations
5349 follow the forward declarations then this is not diagnosed. Also
5350 note as above that gnu-attributes are ignored as the only contents of
5351 the parentheses, or as the only contents after forward
5352 declarations. */
5353 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5354 {
5355 struct c_arg_info *ret = build_arg_info ();
5356 c_parser_consume_token (parser);
5357 return ret;
5358 }
5359 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS) && !have_gnu_attrs)
5360 {
5361 struct c_arg_info *ret = build_arg_info ();
5362
5363 ret->types = NULL_TREE;
5364 pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
5365 "ISO C requires a named argument before %<...%> "
5366 "before C23");
5367 c_parser_consume_token (parser);
5368 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5369 {
5370 ret->no_named_args_stdarg_p = true;
5371 c_parser_consume_token (parser);
5372 return ret;
5373 }
5374 else
5375 {
5376 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5377 msgid: "expected %<)%>");
5378 return NULL;
5379 }
5380 }
5381 /* Nonempty list of parameters, either terminated with semicolon
5382 (forward declarations; recurse) or with close parenthesis (normal
5383 function) or with ", ... )" (variadic function). */
5384 while (true)
5385 {
5386 /* Parse a parameter. */
5387 struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
5388 have_gnu_attrs);
5389 attrs = NULL_TREE;
5390 have_gnu_attrs = false;
5391 if (parm == NULL)
5392 bad_parm = true;
5393 else
5394 push_parm_decl (parm, &expr);
5395 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
5396 {
5397 tree new_attrs;
5398 c_parser_consume_token (parser);
5399 mark_forward_parm_decls ();
5400 bool new_have_gnu_attrs
5401 = c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE);
5402 new_attrs = c_parser_gnu_attributes (parser);
5403 return c_parser_parms_list_declarator (parser, attrs: new_attrs, expr,
5404 have_gnu_attrs: new_have_gnu_attrs);
5405 }
5406 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5407 {
5408 c_parser_consume_token (parser);
5409 if (bad_parm)
5410 return NULL;
5411 else
5412 return get_parm_info (false, expr);
5413 }
5414 if (!c_parser_require (parser, type: CPP_COMMA,
5415 msgid: "expected %<;%>, %<,%> or %<)%>",
5416 UNKNOWN_LOCATION, type_is_unique: false))
5417 {
5418 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5419 return NULL;
5420 }
5421 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
5422 {
5423 c_parser_consume_token (parser);
5424 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5425 {
5426 c_parser_consume_token (parser);
5427 if (bad_parm)
5428 return NULL;
5429 else
5430 return get_parm_info (true, expr);
5431 }
5432 else
5433 {
5434 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5435 msgid: "expected %<)%>");
5436 return NULL;
5437 }
5438 }
5439 }
5440}
5441
5442/* Parse a parameter declaration. ATTRS are the gnu-attributes at the
5443 start of the declaration if it is the first parameter;
5444 HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
5445 empty) there. */
5446
5447static struct c_parm *
5448c_parser_parameter_declaration (c_parser *parser, tree attrs,
5449 bool have_gnu_attrs)
5450{
5451 struct c_declspecs *specs;
5452 struct c_declarator *declarator;
5453 tree prefix_attrs;
5454 tree postfix_attrs = NULL_TREE;
5455 bool dummy = false;
5456
5457 /* Accept #pragmas between parameter declarations. */
5458 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
5459 c_parser_pragma (parser, pragma_param, NULL, NULL_TREE);
5460
5461 if (!c_parser_next_token_starts_declspecs (parser)
5462 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5463 {
5464 c_token *token = c_parser_peek_token (parser);
5465 if (parser->error)
5466 return NULL;
5467 c_parser_set_source_position_from_token (token);
5468 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
5469 {
5470 auto_diagnostic_group d;
5471 name_hint hint = lookup_name_fuzzy (token->value,
5472 FUZZY_LOOKUP_TYPENAME,
5473 token->location);
5474 if (const char *suggestion = hint.suggestion ())
5475 {
5476 gcc_rich_location richloc (token->location);
5477 richloc.add_fixit_replace (new_content: suggestion);
5478 error_at (&richloc,
5479 "unknown type name %qE; did you mean %qs?",
5480 token->value, suggestion);
5481 }
5482 else
5483 error_at (token->location, "unknown type name %qE", token->value);
5484 parser->error = true;
5485 }
5486 /* ??? In some Objective-C cases '...' isn't applicable so there
5487 should be a different message. */
5488 else
5489 c_parser_error (parser,
5490 gmsgid: "expected declaration specifiers or %<...%>");
5491 c_parser_skip_to_end_of_parameter (parser);
5492 return NULL;
5493 }
5494
5495 location_t start_loc = c_parser_peek_token (parser)->location;
5496
5497 specs = build_null_declspecs ();
5498 if (attrs)
5499 {
5500 declspecs_add_attrs (input_location, specs, attrs);
5501 attrs = NULL_TREE;
5502 }
5503 c_parser_declspecs (parser, specs, scspec_ok: true, typespec_ok: true, start_attr_ok: true, alignspec_ok: true, auto_type_ok: false,
5504 start_std_attr_ok: !have_gnu_attrs, end_std_attr_ok: true, la: cla_nonabstract_decl);
5505 finish_declspecs (specs);
5506 /* When the param is declared, its type is a top level type, we should
5507 call verify_counted_by_for_top_anonymous_type. */
5508 if (specs->typespec_kind == ctsk_tagdef)
5509 verify_counted_by_for_top_anonymous_type (specs->type);
5510
5511 pending_xref_error ();
5512 prefix_attrs = specs->attrs;
5513 specs->attrs = NULL_TREE;
5514 declarator = c_parser_declarator (parser,
5515 type_seen_p: specs->typespec_kind != ctsk_none,
5516 kind: C_DTR_PARM, seen_id: &dummy);
5517 if (declarator == NULL)
5518 {
5519 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
5520 return NULL;
5521 }
5522 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5523 postfix_attrs = c_parser_gnu_attributes (parser);
5524
5525 /* Generate a location for the parameter, ranging from the start of the
5526 initial token to the end of the final token.
5527
5528 If we have a identifier, then use it for the caret location, e.g.
5529
5530 extern int callee (int one, int (*two)(int, int), float three);
5531 ~~~~~~^~~~~~~~~~~~~~
5532
5533 otherwise, reuse the start location for the caret location e.g.:
5534
5535 extern int callee (int one, int (*)(int, int), float three);
5536 ^~~~~~~~~~~~~~~~~
5537 */
5538 location_t end_loc = parser->last_token_location;
5539
5540 /* Find any cdk_id declarator; determine if we have an identifier. */
5541 c_declarator *id_declarator = declarator;
5542 while (id_declarator && id_declarator->kind != cdk_id)
5543 id_declarator = id_declarator->declarator;
5544 location_t caret_loc = (id_declarator->u.id.id
5545 ? id_declarator->id_loc
5546 : start_loc);
5547 location_t param_loc = make_location (caret: caret_loc, start: start_loc, finish: end_loc);
5548
5549 return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5550 declarator, param_loc);
5551}
5552
5553/* Parse a string literal in an asm expression. It should not be
5554 translated, and wide string literals are an error although
5555 permitted by the syntax. This is a GNU extension.
5556
5557 asm-string-literal:
5558 string-literal
5559*/
5560
5561static tree
5562c_parser_asm_string_literal (c_parser *parser)
5563{
5564 tree str;
5565 int save_flag = warn_overlength_strings;
5566 warn_overlength_strings = 0;
5567 str = c_parser_string_literal (parser, false, false).value;
5568 warn_overlength_strings = save_flag;
5569 return str;
5570}
5571
5572/* Parse a simple asm expression. This is used in restricted
5573 contexts, where a full expression with inputs and outputs does not
5574 make sense. This is a GNU extension.
5575
5576 simple-asm-expr:
5577 asm ( asm-string-literal )
5578*/
5579
5580static tree
5581c_parser_simple_asm_expr (c_parser *parser)
5582{
5583 tree str;
5584 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5585 c_parser_consume_token (parser);
5586 matching_parens parens;
5587 if (!parens.require_open (parser))
5588 return NULL_TREE;
5589 str = c_parser_asm_string_literal (parser);
5590 if (!parens.require_close (parser))
5591 {
5592 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5593 return NULL_TREE;
5594 }
5595 return str;
5596}
5597
5598static tree
5599c_parser_gnu_attribute_any_word (c_parser *parser)
5600{
5601 tree attr_name = NULL_TREE;
5602
5603 if (c_parser_next_token_is (parser, type: CPP_KEYWORD))
5604 {
5605 /* ??? See comment above about what keywords are accepted here. */
5606 bool ok;
5607 switch (c_parser_peek_token (parser)->keyword)
5608 {
5609 case RID_STATIC:
5610 case RID_UNSIGNED:
5611 case RID_LONG:
5612 case RID_CONST:
5613 case RID_EXTERN:
5614 case RID_REGISTER:
5615 case RID_TYPEDEF:
5616 case RID_SHORT:
5617 case RID_INLINE:
5618 case RID_NORETURN:
5619 case RID_VOLATILE:
5620 case RID_SIGNED:
5621 case RID_AUTO:
5622 case RID_RESTRICT:
5623 case RID_COMPLEX:
5624 case RID_THREAD:
5625 case RID_INT:
5626 case RID_CHAR:
5627 case RID_FLOAT:
5628 case RID_DOUBLE:
5629 case RID_VOID:
5630 case RID_DFLOAT32:
5631 case RID_DFLOAT64:
5632 case RID_DFLOAT128:
5633 case RID_DFLOAT64X:
5634 CASE_RID_FLOATN_NX:
5635 case RID_BOOL:
5636 case RID_BITINT:
5637 case RID_FRACT:
5638 case RID_ACCUM:
5639 case RID_SAT:
5640 case RID_TRANSACTION_ATOMIC:
5641 case RID_TRANSACTION_CANCEL:
5642 case RID_ATOMIC:
5643 case RID_AUTO_TYPE:
5644 case RID_CONSTEXPR:
5645 case RID_INT_N_0:
5646 case RID_INT_N_1:
5647 case RID_INT_N_2:
5648 case RID_INT_N_3:
5649 ok = true;
5650 break;
5651 default:
5652 ok = false;
5653 break;
5654 }
5655 if (!ok)
5656 return NULL_TREE;
5657
5658 /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5659 attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5660 }
5661 else if (c_parser_next_token_is (parser, type: CPP_NAME))
5662 attr_name = c_parser_peek_token (parser)->value;
5663
5664 return attr_name;
5665}
5666
5667/* Parse attribute arguments. This is a common form of syntax
5668 covering all currently valid GNU and standard attributes.
5669
5670 gnu-attribute-arguments:
5671 identifier
5672 identifier , nonempty-expr-list
5673 expr-list
5674
5675 where the "identifier" must not be declared as a type. ??? Why not
5676 allow identifiers declared as types to start the arguments? */
5677
5678static tree
5679c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5680 bool require_string, bool assume_attr,
5681 bool allow_empty_args)
5682{
5683 vec<tree, va_gc> *expr_list;
5684 tree attr_args;
5685 /* Parse the attribute contents. If they start with an
5686 identifier which is followed by a comma or close
5687 parenthesis, then the arguments start with that
5688 identifier; otherwise they are an expression list.
5689 In objective-c the identifier may be a classname. */
5690 if (c_parser_next_token_is (parser, type: CPP_NAME)
5691 && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5692 || (c_dialect_objc ()
5693 && c_parser_peek_token (parser)->id_kind
5694 == C_ID_CLASSNAME))
5695 && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5696 || (c_parser_peek_2nd_token (parser)->type
5697 == CPP_CLOSE_PAREN))
5698 && (takes_identifier
5699 || (c_dialect_objc ()
5700 && !assume_attr
5701 && c_parser_peek_token (parser)->id_kind
5702 == C_ID_CLASSNAME)))
5703 {
5704 tree arg1 = c_parser_peek_token (parser)->value;
5705 c_parser_consume_token (parser);
5706 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5707 attr_args = build_tree_list (NULL_TREE, arg1);
5708 else
5709 {
5710 tree tree_list;
5711 c_parser_consume_token (parser);
5712 expr_list = c_parser_expr_list (parser, false, true,
5713 NULL, NULL, NULL, NULL);
5714 tree_list = build_tree_list_vec (expr_list);
5715 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5716 release_tree_vector (expr_list);
5717 }
5718 }
5719 else
5720 {
5721 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5722 {
5723 if (!allow_empty_args)
5724 error_at (c_parser_peek_token (parser)->location,
5725 "parentheses must be omitted if "
5726 "attribute argument list is empty");
5727 attr_args = NULL_TREE;
5728 }
5729 else if (require_string)
5730 {
5731 /* The only valid argument for this attribute is a string
5732 literal. Handle this specially here to avoid accepting
5733 string literals with excess parentheses. */
5734 tree string = c_parser_string_literal (parser, false, true).value;
5735 attr_args = build_tree_list (NULL_TREE, string);
5736 }
5737 else if (assume_attr)
5738 {
5739 tree cond
5740 = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5741 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
5742 attr_args = build_tree_list (NULL_TREE, cond);
5743 else
5744 {
5745 tree tree_list;
5746 c_parser_consume_token (parser);
5747 expr_list = c_parser_expr_list (parser, false, true,
5748 NULL, NULL, NULL, NULL);
5749 tree_list = build_tree_list_vec (expr_list);
5750 attr_args = tree_cons (NULL_TREE, cond, tree_list);
5751 release_tree_vector (expr_list);
5752 }
5753 }
5754 else
5755 {
5756 expr_list = c_parser_expr_list (parser, false, true,
5757 NULL, NULL, NULL, NULL);
5758 attr_args = build_tree_list_vec (expr_list);
5759 release_tree_vector (expr_list);
5760 }
5761 }
5762 return attr_args;
5763}
5764
5765/* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5766
5767 gnu-attributes:
5768 empty
5769 gnu-attributes gnu-attribute
5770
5771 gnu-attribute:
5772 __attribute__ ( ( gnu-attribute-list ) )
5773
5774 gnu-attribute-list:
5775 gnu-attrib
5776 gnu-attribute_list , gnu-attrib
5777
5778 gnu-attrib:
5779 empty
5780 any-word
5781 any-word ( gnu-attribute-arguments )
5782
5783 where "any-word" may be any identifier (including one declared as a
5784 type), a reserved word storage class specifier, type specifier or
5785 type qualifier. ??? This still leaves out most reserved keywords
5786 (following the old parser), shouldn't we include them?
5787 When EXPECT_COMMA is true, expect the attribute to be preceded
5788 by a comma and fail if it isn't.
5789 When EMPTY_OK is true, allow and consume any number of consecutive
5790 commas with no attributes in between. */
5791
5792static tree
5793c_parser_gnu_attribute (c_parser *parser, tree attrs,
5794 bool expect_comma = false, bool empty_ok = true)
5795{
5796 bool comma_first = c_parser_next_token_is (parser, type: CPP_COMMA);
5797 if (!comma_first
5798 && !c_parser_next_token_is (parser, type: CPP_NAME)
5799 && !c_parser_next_token_is (parser, type: CPP_KEYWORD))
5800 return NULL_TREE;
5801
5802 while (c_parser_next_token_is (parser, type: CPP_COMMA))
5803 {
5804 c_parser_consume_token (parser);
5805 if (!empty_ok)
5806 return attrs;
5807 }
5808
5809 tree attr_name = c_parser_gnu_attribute_any_word (parser);
5810 if (attr_name == NULL_TREE)
5811 return NULL_TREE;
5812
5813 attr_name = canonicalize_attr_name (attr_name);
5814 c_parser_consume_token (parser);
5815
5816 tree attr;
5817 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5818 {
5819 if (expect_comma && !comma_first)
5820 {
5821 /* A comma is missing between the last attribute on the chain
5822 and this one. */
5823 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5824 msgid: "expected %<)%>");
5825 return error_mark_node;
5826 }
5827 attr = build_tree_list (attr_name, NULL_TREE);
5828 /* Add this attribute to the list. */
5829 attrs = chainon (attrs, attr);
5830 return attrs;
5831 }
5832 c_parser_consume_token (parser);
5833
5834 tree attr_args
5835 = c_parser_attribute_arguments (parser,
5836 takes_identifier: attribute_takes_identifier_p (attr_name),
5837 require_string: false,
5838 assume_attr: is_attribute_p (attr_name: "assume", ident: attr_name),
5839 allow_empty_args: true);
5840
5841 attr = build_tree_list (attr_name, attr_args);
5842 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5843 c_parser_consume_token (parser);
5844 else
5845 {
5846 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5847 msgid: "expected %<)%>");
5848 return error_mark_node;
5849 }
5850
5851 if (expect_comma && !comma_first)
5852 {
5853 /* A comma is missing between the last attribute on the chain
5854 and this one. */
5855 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5856 msgid: "expected %<)%>");
5857 return error_mark_node;
5858 }
5859
5860 /* Add this attribute to the list. */
5861 attrs = chainon (attrs, attr);
5862 return attrs;
5863}
5864
5865static tree
5866c_parser_gnu_attributes (c_parser *parser)
5867{
5868 tree attrs = NULL_TREE;
5869 while (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5870 {
5871 bool save_translate_strings_p = parser->translate_strings_p;
5872 parser->translate_strings_p = false;
5873 /* Consume the `__attribute__' keyword. */
5874 c_parser_consume_token (parser);
5875 /* Look for the two `(' tokens. */
5876 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5877 {
5878 parser->translate_strings_p = save_translate_strings_p;
5879 return attrs;
5880 }
5881 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5882 {
5883 parser->translate_strings_p = save_translate_strings_p;
5884 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5885 return attrs;
5886 }
5887 /* Parse the attribute list. Require a comma between successive
5888 (possibly empty) attributes. */
5889 for (bool expect_comma = false; ; expect_comma = true)
5890 {
5891 /* Parse a single attribute. */
5892 tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5893 if (attr == error_mark_node)
5894 return attrs;
5895 if (!attr)
5896 break;
5897 attrs = attr;
5898 }
5899
5900 /* Look for the two `)' tokens. */
5901 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5902 c_parser_consume_token (parser);
5903 else
5904 {
5905 parser->translate_strings_p = save_translate_strings_p;
5906 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5907 msgid: "expected %<)%>");
5908 return attrs;
5909 }
5910 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5911 c_parser_consume_token (parser);
5912 else
5913 {
5914 parser->translate_strings_p = save_translate_strings_p;
5915 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5916 msgid: "expected %<)%>");
5917 return attrs;
5918 }
5919 parser->translate_strings_p = save_translate_strings_p;
5920 }
5921
5922 return attrs;
5923}
5924
5925/* Parse an optional balanced token sequence.
5926
5927 balanced-token-sequence:
5928 balanced-token
5929 balanced-token-sequence balanced-token
5930
5931 balanced-token:
5932 ( balanced-token-sequence[opt] )
5933 [ balanced-token-sequence[opt] ]
5934 { balanced-token-sequence[opt] }
5935 any token other than ()[]{}
5936*/
5937
5938static void
5939c_parser_balanced_token_sequence (c_parser *parser)
5940{
5941 while (true)
5942 {
5943 c_token *token = c_parser_peek_token (parser);
5944 switch (token->type)
5945 {
5946 case CPP_OPEN_BRACE:
5947 {
5948 matching_braces braces;
5949 braces.consume_open (parser);
5950 c_parser_balanced_token_sequence (parser);
5951 braces.require_close (parser);
5952 break;
5953 }
5954
5955 case CPP_OPEN_PAREN:
5956 {
5957 matching_parens parens;
5958 parens.consume_open (parser);
5959 c_parser_balanced_token_sequence (parser);
5960 parens.require_close (parser);
5961 break;
5962 }
5963
5964 case CPP_OPEN_SQUARE:
5965 c_parser_consume_token (parser);
5966 c_parser_balanced_token_sequence (parser);
5967 c_parser_require (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5968 break;
5969
5970 case CPP_CLOSE_BRACE:
5971 case CPP_CLOSE_PAREN:
5972 case CPP_CLOSE_SQUARE:
5973 case CPP_EOF:
5974 return;
5975
5976 case CPP_PRAGMA:
5977 c_parser_consume_pragma (parser);
5978 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
5979 break;
5980
5981 default:
5982 c_parser_consume_token (parser);
5983 break;
5984 }
5985 }
5986}
5987
5988/* Parse arguments of omp::directive or omp::decl attribute.
5989
5990 directive-name ,[opt] clause-list[opt]
5991
5992 For directive just remember the tokens in a vector for subsequent
5993 parsing. */
5994
5995static void
5996c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5997{
5998 unsigned int n = 1;
5999 c_token *first = c_parser_peek_token (parser);
6000 if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
6001 || (c_parser_peek_nth_token_raw (parser, n)->type
6002 != CPP_CLOSE_PAREN))
6003 {
6004 c_parser_balanced_token_sequence (parser);
6005 TREE_VALUE (attribute) = NULL_TREE;
6006 return;
6007 }
6008 if (n == 1)
6009 {
6010 error_at (first->location, "expected OpenMP directive name");
6011 TREE_VALUE (attribute) = NULL_TREE;
6012 return;
6013 }
6014 vec<c_token, va_gc> *v;
6015 vec_alloc (v, nelems: n - 1);
6016 for (--n; n; --n)
6017 {
6018 c_token *tok = c_parser_peek_token (parser);
6019 v->quick_push (obj: *tok);
6020 c_parser_consume_token (parser);
6021 }
6022 tree arg = make_node (C_TOKEN_VEC);
6023 C_TOKEN_VEC_TOKENS (arg) = v;
6024 if (decl_p)
6025 TREE_PUBLIC (arg) = 1;
6026 TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
6027}
6028
6029/* Parse arguments of omp::sequence attribute.
6030
6031 omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
6032
6033static void
6034c_parser_omp_sequence_args (c_parser *parser, tree attribute)
6035{
6036 do
6037 {
6038 c_token *token = c_parser_peek_token (parser);
6039 if (token->type == CPP_NAME
6040 && strcmp (IDENTIFIER_POINTER (token->value), s2: "omp") == 0
6041 && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
6042 {
6043 c_parser_consume_token (parser);
6044 c_parser_consume_token (parser);
6045 token = c_parser_peek_token (parser);
6046 }
6047 bool directive = false;
6048 const char *p;
6049 if (token->type != CPP_NAME)
6050 p = "";
6051 else
6052 p = IDENTIFIER_POINTER (token->value);
6053 if (strcmp (s1: p, s2: "directive") == 0)
6054 directive = true;
6055 else if (strcmp (s1: p, s2: "sequence") != 0)
6056 {
6057 error_at (token->location, "expected %<directive%> or %<sequence%>");
6058 unsigned nesting_depth = 0;
6059
6060 while (true)
6061 {
6062 /* Peek at the next token. */
6063 token = c_parser_peek_token (parser);
6064 /* If we've reached the token we want, consume it and stop. */
6065 if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
6066 && !nesting_depth)
6067 break;
6068 /* If we've run out of tokens, stop. */
6069 if (token->type == CPP_EOF)
6070 break;
6071 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
6072 break;
6073 if (token->type == CPP_OPEN_BRACE
6074 || token->type == CPP_OPEN_PAREN
6075 || token->type == CPP_OPEN_SQUARE)
6076 ++nesting_depth;
6077 else if (token->type == CPP_CLOSE_BRACE
6078 || token->type == CPP_CLOSE_PAREN
6079 || token->type == CPP_CLOSE_SQUARE)
6080 {
6081 if (nesting_depth-- == 0)
6082 break;
6083 }
6084 /* Consume this token. */
6085 c_parser_consume_token (parser);
6086 }
6087 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
6088 break;
6089 c_parser_consume_token (parser);
6090 continue;
6091 }
6092 c_parser_consume_token (parser);
6093 matching_parens parens;
6094 if (parens.require_open (parser))
6095 {
6096 if (directive)
6097 c_parser_omp_directive_args (parser, attribute, decl_p: false);
6098 else
6099 c_parser_omp_sequence_args (parser, attribute);
6100 parens.skip_until_found_close (parser);
6101 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
6102 break;
6103 c_parser_consume_token (parser);
6104 }
6105 else if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
6106 break;
6107 else
6108 c_parser_consume_token (parser);
6109 }
6110 while (1);
6111}
6112
6113/* Parse standard (C23) attributes (including GNU attributes in the
6114 gnu:: namespace).
6115
6116 attribute-specifier-sequence:
6117 attribute-specifier-sequence[opt] attribute-specifier
6118
6119 attribute-specifier:
6120 [ [ attribute-list ] ]
6121
6122 attribute-list:
6123 attribute[opt]
6124 attribute-list, attribute[opt]
6125
6126 attribute:
6127 attribute-token attribute-argument-clause[opt]
6128
6129 attribute-token:
6130 standard-attribute
6131 attribute-prefixed-token
6132
6133 standard-attribute:
6134 identifier
6135
6136 attribute-prefixed-token:
6137 attribute-prefix :: identifier
6138
6139 attribute-prefix:
6140 identifier
6141
6142 attribute-argument-clause:
6143 ( balanced-token-sequence[opt] )
6144
6145 Keywords are accepted as identifiers for this purpose.
6146
6147 As an extension, we permit an attribute-specifier to be:
6148
6149 [ [ __extension__ attribute-list ] ]
6150
6151 Two colons are then accepted as a synonym for ::. No attempt is made
6152 to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
6153 indicates whether this relaxation is in effect. */
6154
6155static tree
6156c_parser_std_attribute (c_parser *parser, bool for_tm)
6157{
6158 c_token *token = c_parser_peek_token (parser);
6159 tree ns, name, attribute;
6160
6161 /* Parse the attribute-token. */
6162 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6163 {
6164 c_parser_error (parser, gmsgid: "expected identifier");
6165 return error_mark_node;
6166 }
6167 name = canonicalize_attr_name (attr_name: token->value);
6168 c_parser_consume_token (parser);
6169 if (c_parser_next_token_is (parser, type: CPP_SCOPE)
6170 || (c_parser_next_token_is (parser, type: CPP_COLON)
6171 && (c_parser_peek_token (parser)->flags & COLON_SCOPE) != 0
6172 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
6173 {
6174 ns = name;
6175 if (c_parser_next_token_is (parser, type: CPP_COLON))
6176 c_parser_consume_token (parser);
6177 c_parser_consume_token (parser);
6178 token = c_parser_peek_token (parser);
6179 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6180 {
6181 c_parser_error (parser, gmsgid: "expected identifier");
6182 return error_mark_node;
6183 }
6184 name = canonicalize_attr_name (attr_name: token->value);
6185 c_parser_consume_token (parser);
6186 }
6187 else
6188 ns = NULL_TREE;
6189 attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
6190
6191 /* Parse the arguments, if any. */
6192 const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
6193 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
6194 {
6195 if ((flag_openmp || flag_openmp_simd)
6196 && ns
6197 && is_attribute_p (attr_name: "omp", ident: ns)
6198 && (is_attribute_p (attr_name: "directive", ident: name)
6199 || is_attribute_p (attr_name: "sequence", ident: name)
6200 || is_attribute_p (attr_name: "decl", ident: name)))
6201 {
6202 error ("%<omp::%E%> attribute requires argument", name);
6203 return error_mark_node;
6204 }
6205 goto out;
6206 }
6207 {
6208 location_t open_loc = c_parser_peek_token (parser)->location;
6209 matching_parens parens;
6210 parens.consume_open (parser);
6211 if ((as && as->max_length == 0)
6212 /* Special-case the transactional-memory attribute "outer",
6213 which is specially handled but not registered as an
6214 attribute, to avoid allowing arbitrary balanced token
6215 sequences as arguments. */
6216 || is_attribute_p (attr_name: "outer", ident: name))
6217 {
6218 error_at (open_loc, "%qE attribute does not take any arguments", name);
6219 parens.skip_until_found_close (parser);
6220 return error_mark_node;
6221 }
6222 /* If this is a fake attribute created to handle -Wno-attributes,
6223 we must skip parsing the arguments. */
6224 if (as && !attribute_ignored_p (as))
6225 {
6226 bool takes_identifier
6227 = (ns != NULL_TREE
6228 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
6229 && attribute_takes_identifier_p (name));
6230 bool require_string
6231 = (ns == NULL_TREE
6232 && (strcmp (IDENTIFIER_POINTER (name), s2: "deprecated") == 0
6233 || strcmp (IDENTIFIER_POINTER (name), s2: "nodiscard") == 0));
6234 bool assume_attr
6235 = (ns != NULL_TREE
6236 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
6237 && strcmp (IDENTIFIER_POINTER (name), s2: "assume") == 0);
6238 TREE_VALUE (attribute)
6239 = c_parser_attribute_arguments (parser, takes_identifier,
6240 require_string, assume_attr, allow_empty_args: false);
6241 }
6242 else
6243 {
6244 if ((flag_openmp || flag_openmp_simd)
6245 && ns
6246 && is_attribute_p (attr_name: "omp", ident: ns))
6247 {
6248 if (is_attribute_p (attr_name: "directive", ident: name))
6249 {
6250 c_parser_omp_directive_args (parser, attribute, decl_p: false);
6251 parens.skip_until_found_close (parser);
6252 return attribute;
6253 }
6254 else if (is_attribute_p (attr_name: "decl", ident: name))
6255 {
6256 TREE_VALUE (TREE_PURPOSE (attribute))
6257 = get_identifier ("directive");
6258 c_parser_omp_directive_args (parser, attribute, decl_p: true);
6259 parens.skip_until_found_close (parser);
6260 return attribute;
6261 }
6262 else if (is_attribute_p (attr_name: "sequence", ident: name))
6263 {
6264 TREE_VALUE (TREE_PURPOSE (attribute))
6265 = get_identifier ("directive");
6266 c_parser_omp_sequence_args (parser, attribute);
6267 parens.skip_until_found_close (parser);
6268 TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
6269 return attribute;
6270 }
6271 }
6272 c_parser_balanced_token_sequence (parser);
6273 }
6274 parens.require_close (parser);
6275 }
6276 out:
6277 if (ns == NULL_TREE && !for_tm && !as)
6278 {
6279 /* An attribute with standard syntax and no namespace specified
6280 is a constraint violation if it is not one of the known
6281 standard attributes. Diagnose it here with a pedwarn and
6282 then discard it to prevent a duplicate warning later. */
6283 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
6284 name);
6285 return error_mark_node;
6286 }
6287 return attribute;
6288}
6289
6290static tree
6291c_parser_std_attribute_list (c_parser *parser, bool for_tm)
6292{
6293 tree attributes = NULL_TREE;
6294 while (true)
6295 {
6296 c_token *token = c_parser_peek_token (parser);
6297 if (token->type == CPP_CLOSE_SQUARE)
6298 break;
6299 if (token->type == CPP_COMMA)
6300 {
6301 c_parser_consume_token (parser);
6302 continue;
6303 }
6304 tree attribute = c_parser_std_attribute (parser, for_tm);
6305 if (attribute != error_mark_node)
6306 {
6307 TREE_CHAIN (attribute) = attributes;
6308 attributes = attribute;
6309 }
6310 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
6311 break;
6312 }
6313 return attributes;
6314}
6315
6316static tree
6317c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
6318{
6319 location_t loc = c_parser_peek_token (parser)->location;
6320 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
6321 return NULL_TREE;
6322 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
6323 {
6324 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6325 return NULL_TREE;
6326 }
6327 tree attributes;
6328 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
6329 {
6330 auto ext = disable_extension_diagnostics ();
6331 c_parser_consume_token (parser);
6332 attributes = c_parser_std_attribute_list (parser, for_tm);
6333 restore_extension_diagnostics (flags: ext);
6334 }
6335 else
6336 {
6337 if (!for_tm)
6338 pedwarn_c11 (loc, OPT_Wpedantic,
6339 "ISO C does not support %<[[]]%> attributes before C23");
6340 attributes = c_parser_std_attribute_list (parser, for_tm);
6341 }
6342 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6343 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6344 return nreverse (attributes);
6345}
6346
6347/* Look past an optional balanced token sequence of raw look-ahead
6348 tokens starting with the *Nth token. *N is updated to point to the
6349 following token. Return true if such a sequence was found, false
6350 if the tokens parsed were not balanced. */
6351
6352static bool
6353c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
6354{
6355 while (true)
6356 {
6357 c_token *token = c_parser_peek_nth_token_raw (parser, n: *n);
6358 switch (token->type)
6359 {
6360 case CPP_OPEN_BRACE:
6361 {
6362 ++*n;
6363 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6364 {
6365 token = c_parser_peek_nth_token_raw (parser, n: *n);
6366 if (token->type == CPP_CLOSE_BRACE)
6367 ++*n;
6368 else
6369 return false;
6370 }
6371 else
6372 return false;
6373 break;
6374 }
6375
6376 case CPP_OPEN_PAREN:
6377 {
6378 ++*n;
6379 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6380 {
6381 token = c_parser_peek_nth_token_raw (parser, n: *n);
6382 if (token->type == CPP_CLOSE_PAREN)
6383 ++*n;
6384 else
6385 return false;
6386 }
6387 else
6388 return false;
6389 break;
6390 }
6391
6392 case CPP_OPEN_SQUARE:
6393 {
6394 ++*n;
6395 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6396 {
6397 token = c_parser_peek_nth_token_raw (parser, n: *n);
6398 if (token->type == CPP_CLOSE_SQUARE)
6399 ++*n;
6400 else
6401 return false;
6402 }
6403 else
6404 return false;
6405 break;
6406 }
6407
6408 case CPP_CLOSE_BRACE:
6409 case CPP_CLOSE_PAREN:
6410 case CPP_CLOSE_SQUARE:
6411 case CPP_EOF:
6412 return true;
6413
6414 default:
6415 ++*n;
6416 break;
6417 }
6418 }
6419}
6420
6421/* Return whether standard attributes start with the Nth token. */
6422
6423static bool
6424c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
6425{
6426 if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
6427 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_OPEN_SQUARE))
6428 return false;
6429 /* In C, '[[' must start attributes. In Objective-C, we need to
6430 check whether '[[' is matched by ']]'. */
6431 if (!c_dialect_objc ())
6432 return true;
6433 n += 2;
6434 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
6435 return false;
6436 c_token *token = c_parser_peek_nth_token_raw (parser, n);
6437 if (token->type != CPP_CLOSE_SQUARE)
6438 return false;
6439 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
6440 return token->type == CPP_CLOSE_SQUARE;
6441}
6442
6443/* Skip standard attribute tokens starting at Nth token (with 1 as the
6444 next token), return index of the first token after the standard
6445 attribute tokens, or N on failure. */
6446
6447static size_t
6448c_parser_skip_std_attribute_spec_seq (c_parser *parser, size_t n)
6449{
6450 size_t orig_n = n;
6451 while (true)
6452 {
6453 if (c_parser_peek_nth_token_raw (parser, n)->type == CPP_OPEN_SQUARE
6454 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
6455 == CPP_OPEN_SQUARE))
6456 {
6457 unsigned int m = n + 2;
6458 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &m))
6459 return orig_n;
6460 c_token *token = c_parser_peek_nth_token_raw (parser, n: m);
6461 if (token->type != CPP_CLOSE_SQUARE)
6462 return orig_n;
6463 token = c_parser_peek_nth_token_raw (parser, n: m + 1);
6464 if (token->type != CPP_CLOSE_SQUARE)
6465 return orig_n;
6466 n = m + 2;
6467 }
6468 else
6469 break;
6470 }
6471 return n;
6472}
6473
6474static tree
6475c_parser_std_attribute_specifier_sequence (c_parser *parser)
6476{
6477 tree attributes = NULL_TREE;
6478 do
6479 {
6480 tree attrs = c_parser_std_attribute_specifier (parser, for_tm: false);
6481 attributes = chainon (attributes, attrs);
6482 }
6483 while (c_parser_nth_token_starts_std_attributes (parser, n: 1));
6484 return attributes;
6485}
6486
6487/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6488 says whether alignment specifiers are OK (only in cases that might
6489 be the type name of a compound literal).
6490
6491 type-name:
6492 specifier-qualifier-list abstract-declarator[opt]
6493*/
6494
6495struct c_type_name *
6496c_parser_type_name (c_parser *parser, bool alignas_ok)
6497{
6498 struct c_declspecs *specs = build_null_declspecs ();
6499 struct c_declarator *declarator;
6500 struct c_type_name *ret;
6501 bool dummy = false;
6502 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true, alignspec_ok: alignas_ok, auto_type_ok: false,
6503 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_type);
6504 if (!specs->declspecs_seen_p)
6505 {
6506 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
6507 return NULL;
6508 }
6509 if (specs->type != error_mark_node)
6510 {
6511 pending_xref_error ();
6512 finish_declspecs (specs);
6513 /* When the typename is declared, its type is a top level type, we should
6514 call verify_counted_by_for_top_anonymous_type. */
6515 if (specs->typespec_kind == ctsk_tagdef)
6516 verify_counted_by_for_top_anonymous_type (specs->type);
6517 }
6518 declarator = c_parser_declarator (parser,
6519 type_seen_p: specs->typespec_kind != ctsk_none,
6520 kind: C_DTR_ABSTRACT, seen_id: &dummy);
6521 if (declarator == NULL)
6522 return NULL;
6523 ret = XOBNEW (&parser_obstack, struct c_type_name);
6524 ret->specs = specs;
6525 ret->declarator = declarator;
6526 return ret;
6527}
6528
6529/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6530
6531 initializer:
6532 assignment-expression
6533 { initializer-list }
6534 { initializer-list , }
6535
6536 initializer-list:
6537 designation[opt] initializer
6538 initializer-list , designation[opt] initializer
6539
6540 designation:
6541 designator-list =
6542
6543 designator-list:
6544 designator
6545 designator-list designator
6546
6547 designator:
6548 array-designator
6549 . identifier
6550
6551 array-designator:
6552 [ constant-expression ]
6553
6554 GNU extensions:
6555
6556 initializer:
6557 { }
6558
6559 designation:
6560 array-designator
6561 identifier :
6562
6563 array-designator:
6564 [ constant-expression ... constant-expression ]
6565
6566 Any expression without commas is accepted in the syntax for the
6567 constant-expressions, with non-constant expressions rejected later.
6568
6569 DECL is the declaration we're parsing this initializer for.
6570
6571 This function is only used for top-level initializers; for nested
6572 ones, see c_parser_initval. */
6573
6574static struct c_expr
6575c_parser_initializer (c_parser *parser, tree decl)
6576{
6577 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
6578 return c_parser_braced_init (parser, NULL_TREE, false, NULL,
6579 decl != error_mark_node
6580 && C_DECL_VARIABLE_SIZE (decl));
6581 else
6582 {
6583 struct c_expr ret;
6584 location_t loc = c_parser_peek_token (parser)->location;
6585 ret = c_parser_expr_no_commas (parser, NULL);
6586 if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6587 {
6588 error_at (loc,
6589 "variable-sized object may not be initialized except "
6590 "with an empty initializer");
6591 ret.set_error ();
6592 }
6593 /* This is handled mostly by gimplify.cc, but we have to deal with
6594 not warning about int x = x; as it is a GCC extension to turn off
6595 this warning but only if warn_init_self is zero. */
6596 if (VAR_P (decl)
6597 && !DECL_EXTERNAL (decl)
6598 && !TREE_STATIC (decl)
6599 && ret.value == decl
6600 && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), opt_id: OPT_Winit_self))
6601 suppress_warning (decl, OPT_Winit_self);
6602 if (TREE_CODE (ret.value) != STRING_CST
6603 && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6604 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6605 (ret.value))))
6606 ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6607 return ret;
6608 }
6609}
6610
6611/* The location of the last comma within the current initializer list,
6612 or UNKNOWN_LOCATION if not within one. */
6613
6614location_t last_init_list_comma;
6615
6616/* Parse a braced initializer list. TYPE is the type specified for a
6617 compound literal, and NULL_TREE for other initializers and for
6618 nested braced lists. NESTED_P is true for nested braced lists,
6619 false for the list of a compound literal or the list that is the
6620 top-level initializer in a declaration. VARSIZE_P indicates
6621 wether the object to be initialized has a variable size. */
6622
6623static struct c_expr
6624c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6625 struct obstack *outer_obstack, bool varsize_p)
6626{
6627 struct c_expr ret;
6628 struct obstack braced_init_obstack;
6629 location_t brace_loc = c_parser_peek_token (parser)->location;
6630 gcc_obstack_init (&braced_init_obstack);
6631 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6632 bool save_c_omp_array_section_p = c_omp_array_section_p;
6633 c_omp_array_section_p = false;
6634 bool zero_init_padding_bits = false;
6635 matching_braces braces;
6636 braces.consume_open (parser);
6637 if (nested_p)
6638 {
6639 finish_implicit_inits (brace_loc, outer_obstack);
6640 push_init_level (brace_loc, 0, &braced_init_obstack);
6641 }
6642 else
6643 really_start_incremental_init (type);
6644 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6645 {
6646 pedwarn_c11 (brace_loc, OPT_Wpedantic,
6647 "ISO C forbids empty initializer braces before C23");
6648 if (flag_isoc23)
6649 zero_init_padding_bits = true;
6650 }
6651 else
6652 {
6653 if (varsize_p)
6654 error_at (brace_loc,
6655 "variable-sized object may not be initialized except "
6656 "with an empty initializer");
6657 /* Parse a non-empty initializer list, possibly with a trailing
6658 comma. */
6659 while (true)
6660 {
6661 c_parser_initelt (parser, &braced_init_obstack);
6662 if (parser->error)
6663 break;
6664 if (c_parser_next_token_is (parser, type: CPP_COMMA))
6665 {
6666 last_init_list_comma = c_parser_peek_token (parser)->location;
6667 c_parser_consume_token (parser);
6668 /* CPP_EMBED should be always in between two CPP_COMMA
6669 tokens. */
6670 while (c_parser_next_token_is (parser, type: CPP_EMBED))
6671 {
6672 c_token *embed = c_parser_peek_token (parser);
6673 c_parser_consume_token (parser);
6674 c_expr embed_val;
6675 embed_val.value = embed->value;
6676 embed_val.original_code = RAW_DATA_CST;
6677 embed_val.original_type = integer_type_node;
6678 set_c_expr_source_range (expr: &embed_val, src_range: embed->get_range ());
6679 embed_val.m_decimal = 0;
6680 process_init_element (embed->location, embed_val, false,
6681 &braced_init_obstack);
6682 gcc_checking_assert (c_parser_next_token_is (parser,
6683 CPP_COMMA));
6684 last_init_list_comma = c_parser_peek_token (parser)->location;
6685 c_parser_consume_token (parser);
6686 }
6687 }
6688 else
6689 break;
6690 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6691 break;
6692 }
6693 }
6694 c_omp_array_section_p = save_c_omp_array_section_p;
6695 c_token *next_tok = c_parser_peek_token (parser);
6696 if (next_tok->type != CPP_CLOSE_BRACE)
6697 {
6698 ret.set_error ();
6699 ret.original_code = ERROR_MARK;
6700 ret.original_type = NULL;
6701 braces.skip_until_found_close (parser);
6702 pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6703 obstack_free (&braced_init_obstack, NULL);
6704 return ret;
6705 }
6706 location_t close_loc = next_tok->location;
6707 c_parser_consume_token (parser);
6708 ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6709 if (zero_init_padding_bits
6710 && ret.value
6711 && TREE_CODE (ret.value) == CONSTRUCTOR)
6712 CONSTRUCTOR_ZERO_PADDING_BITS (ret.value) = 1;
6713 obstack_free (&braced_init_obstack, NULL);
6714 set_c_expr_source_range (expr: &ret, start: brace_loc, finish: close_loc);
6715 return ret;
6716}
6717
6718/* Parse a nested initializer, including designators. */
6719
6720static void
6721c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6722{
6723 /* Parse any designator or designator list. A single array
6724 designator may have the subsequent "=" omitted in GNU C, but a
6725 longer list or a structure member designator may not. */
6726 if (c_parser_next_token_is (parser, type: CPP_NAME)
6727 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6728 {
6729 /* Old-style structure member designator. */
6730 set_init_label (c_parser_peek_token (parser)->location,
6731 c_parser_peek_token (parser)->value,
6732 c_parser_peek_token (parser)->location,
6733 braced_init_obstack);
6734 /* Use the colon as the error location. */
6735 pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6736 "obsolete use of designated initializer with %<:%>");
6737 c_parser_consume_token (parser);
6738 c_parser_consume_token (parser);
6739 }
6740 else
6741 {
6742 /* des_seen is 0 if there have been no designators, 1 if there
6743 has been a single array designator and 2 otherwise. */
6744 int des_seen = 0;
6745 /* Location of a designator. */
6746 location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6747 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
6748 || c_parser_next_token_is (parser, type: CPP_DOT))
6749 {
6750 int des_prev = des_seen;
6751 if (!des_seen)
6752 des_loc = c_parser_peek_token (parser)->location;
6753 if (des_seen < 2)
6754 des_seen++;
6755 if (c_parser_next_token_is (parser, type: CPP_DOT))
6756 {
6757 des_seen = 2;
6758 c_parser_consume_token (parser);
6759 if (c_parser_next_token_is (parser, type: CPP_NAME))
6760 {
6761 set_init_label (des_loc, c_parser_peek_token (parser)->value,
6762 c_parser_peek_token (parser)->location,
6763 braced_init_obstack);
6764 c_parser_consume_token (parser);
6765 }
6766 else
6767 {
6768 struct c_expr init;
6769 init.set_error ();
6770 init.original_code = ERROR_MARK;
6771 init.original_type = NULL;
6772 c_parser_error (parser, gmsgid: "expected identifier");
6773 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6774 process_init_element (input_location, init, false,
6775 braced_init_obstack);
6776 return;
6777 }
6778 }
6779 else
6780 {
6781 struct c_expr first_expr;
6782 tree first, second;
6783 location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6784 location_t array_index_loc = UNKNOWN_LOCATION;
6785 /* ??? Following the old parser, [ objc-receiver
6786 objc-message-args ] is accepted as an initializer,
6787 being distinguished from a designator by what follows
6788 the first assignment expression inside the square
6789 brackets, but after a first array designator a
6790 subsequent square bracket is for Objective-C taken to
6791 start an expression, using the obsolete form of
6792 designated initializer without '=', rather than
6793 possibly being a second level of designation: in LALR
6794 terms, the '[' is shifted rather than reducing
6795 designator to designator-list. */
6796 if (des_prev == 1 && c_dialect_objc ())
6797 {
6798 des_seen = des_prev;
6799 break;
6800 }
6801 if (des_prev == 0 && c_dialect_objc ())
6802 {
6803 /* This might be an array designator or an
6804 Objective-C message expression. If the former,
6805 continue parsing here; if the latter, parse the
6806 remainder of the initializer given the starting
6807 primary-expression. ??? It might make sense to
6808 distinguish when des_prev == 1 as well; see
6809 previous comment. */
6810 tree rec, args;
6811 struct c_expr mexpr;
6812 c_parser_consume_token (parser);
6813 if (c_parser_peek_token (parser)->type == CPP_NAME
6814 && ((c_parser_peek_token (parser)->id_kind
6815 == C_ID_TYPENAME)
6816 || (c_parser_peek_token (parser)->id_kind
6817 == C_ID_CLASSNAME)))
6818 {
6819 /* Type name receiver. */
6820 tree id = c_parser_peek_token (parser)->value;
6821 c_parser_consume_token (parser);
6822 rec = objc_get_class_reference (id);
6823 goto parse_message_args;
6824 }
6825 array_index_loc = c_parser_peek_token (parser)->location;
6826 first_expr = c_parser_expr_no_commas (parser, NULL);
6827 mark_exp_read (first_expr.value);
6828 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS)
6829 || c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6830 goto array_desig_after_first;
6831 first = first_expr.value;
6832 /* Expression receiver. So far only one part
6833 without commas has been parsed; there might be
6834 more of the expression. */
6835 rec = first;
6836 while (c_parser_next_token_is (parser, type: CPP_COMMA))
6837 {
6838 struct c_expr next;
6839 location_t comma_loc, exp_loc;
6840 comma_loc = c_parser_peek_token (parser)->location;
6841 c_parser_consume_token (parser);
6842 exp_loc = c_parser_peek_token (parser)->location;
6843 next = c_parser_expr_no_commas (parser, NULL);
6844 next = convert_lvalue_to_rvalue (exp_loc, next,
6845 true, true);
6846 rec = build_compound_expr (comma_loc, rec, next.value);
6847 }
6848 parse_message_args:
6849 /* Now parse the objc-message-args. */
6850 args = c_parser_objc_message_args (parser);
6851 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6852 msgid: "expected %<]%>");
6853 mexpr.value
6854 = objc_build_message_expr (rec, args);
6855 mexpr.original_code = ERROR_MARK;
6856 mexpr.original_type = NULL;
6857 mexpr.m_decimal = 0;
6858 /* Now parse and process the remainder of the
6859 initializer, starting with this message
6860 expression as a primary-expression. */
6861 c_parser_initval (parser, &mexpr, braced_init_obstack);
6862 return;
6863 }
6864 c_parser_consume_token (parser);
6865 array_index_loc = c_parser_peek_token (parser)->location;
6866 first_expr = c_parser_expr_no_commas (parser, NULL);
6867 mark_exp_read (first_expr.value);
6868 array_desig_after_first:
6869 first_expr = convert_lvalue_to_rvalue (array_index_loc,
6870 first_expr,
6871 true, true);
6872 first = first_expr.value;
6873 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
6874 {
6875 ellipsis_loc = c_parser_peek_token (parser)->location;
6876 c_parser_consume_token (parser);
6877 second = convert_lvalue_to_rvalue (ellipsis_loc,
6878 (c_parser_expr_no_commas
6879 (parser, NULL)),
6880 true, true).value;
6881 mark_exp_read (second);
6882 }
6883 else
6884 second = NULL_TREE;
6885 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6886 {
6887 c_parser_consume_token (parser);
6888 set_init_index (array_index_loc, first, second,
6889 braced_init_obstack);
6890 if (second)
6891 pedwarn (ellipsis_loc, OPT_Wpedantic,
6892 "ISO C forbids specifying range of elements to initialize");
6893 }
6894 else
6895 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6896 msgid: "expected %<]%>");
6897 }
6898 }
6899 if (des_seen >= 1)
6900 {
6901 if (c_parser_next_token_is (parser, type: CPP_EQ))
6902 {
6903 pedwarn_c90 (des_loc, OPT_Wpedantic,
6904 "ISO C90 forbids specifying subobject "
6905 "to initialize");
6906 c_parser_consume_token (parser);
6907 }
6908 else
6909 {
6910 if (des_seen == 1)
6911 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6912 "obsolete use of designated initializer without %<=%>");
6913 else
6914 {
6915 struct c_expr init;
6916 init.set_error ();
6917 init.original_code = ERROR_MARK;
6918 init.original_type = NULL;
6919 c_parser_error (parser, gmsgid: "expected %<=%>");
6920 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6921 process_init_element (input_location, init, false,
6922 braced_init_obstack);
6923 return;
6924 }
6925 }
6926 }
6927 }
6928 c_parser_initval (parser, NULL, braced_init_obstack);
6929}
6930
6931/* Parse a nested initializer; as c_parser_initializer but parses
6932 initializers within braced lists, after any designators have been
6933 applied. If AFTER is not NULL then it is an Objective-C message
6934 expression which is the primary-expression starting the
6935 initializer. */
6936
6937static void
6938c_parser_initval (c_parser *parser, struct c_expr *after,
6939 struct obstack * braced_init_obstack)
6940{
6941 struct c_expr init;
6942 gcc_assert (!after || c_dialect_objc ());
6943 location_t loc = c_parser_peek_token (parser)->location;
6944
6945 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE) && !after)
6946 init = c_parser_braced_init (parser, NULL_TREE, nested_p: true,
6947 outer_obstack: braced_init_obstack, varsize_p: false);
6948 else
6949 {
6950 init = c_parser_expr_no_commas (parser, after);
6951 if (init.value != NULL_TREE
6952 && TREE_CODE (init.value) != STRING_CST
6953 && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6954 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6955 (init.value))))
6956 init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6957 }
6958 tree val = init.value;
6959 process_init_element (loc, init, false, braced_init_obstack);
6960
6961 /* Attempt to optimize large char array initializers into RAW_DATA_CST
6962 to save compile time and memory even when not using #embed. */
6963 static unsigned vals_to_ignore;
6964 if (vals_to_ignore)
6965 /* If earlier call determined there is certain number of CPP_COMMA
6966 CPP_NUMBER tokens with 0-255 int values, but not enough for
6967 RAW_DATA_CST to be beneficial, don't try to check it again until
6968 they are all parsed. */
6969 --vals_to_ignore;
6970 else if (val
6971 && TREE_CODE (val) == INTEGER_CST
6972 && TREE_TYPE (val) == integer_type_node
6973 && c_parser_next_token_is (parser, type: CPP_COMMA))
6974 if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
6975 {
6976 char buf1[64];
6977 unsigned int i;
6978 gcc_checking_assert (len >= 64);
6979 location_t last_loc = UNKNOWN_LOCATION;
6980 for (i = 0; i < 64; ++i)
6981 {
6982 c_token *tok = c_parser_peek_nth_token_raw (parser, n: 1 + 2 * i);
6983 if (tok->type != CPP_COMMA)
6984 break;
6985 tok = c_parser_peek_nth_token_raw (parser, n: 2 + 2 * i);
6986 if (tok->type != CPP_NUMBER
6987 || TREE_CODE (tok->value) != INTEGER_CST
6988 || TREE_TYPE (tok->value) != integer_type_node
6989 || wi::neg_p (x: wi::to_wide (t: tok->value))
6990 || wi::to_widest (t: tok->value) > UCHAR_MAX)
6991 break;
6992 buf1[i] = (char) tree_to_uhwi (tok->value);
6993 if (i == 0)
6994 loc = tok->location;
6995 last_loc = tok->location;
6996 }
6997 if (i < 64)
6998 {
6999 vals_to_ignore = i;
7000 return;
7001 }
7002 c_token *tok = c_parser_peek_nth_token_raw (parser, n: 1 + 2 * i);
7003 /* If 64 CPP_COMMA CPP_NUMBER pairs are followed by CPP_CLOSE_BRACE,
7004 punt if len is INT_MAX as that can mean this is a flexible array
7005 member and in that case we need one CPP_NUMBER afterwards
7006 (as guaranteed for CPP_EMBED). */
7007 if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
7008 len = i;
7009 else if (tok->type != CPP_COMMA
7010 || (c_parser_peek_nth_token_raw (parser, n: 2 + 2 * i)->type
7011 != CPP_NUMBER))
7012 {
7013 vals_to_ignore = i;
7014 return;
7015 }
7016 /* Ensure the STRING_CST fits into 128K. */
7017 unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
7018 unsigned int orig_len = len;
7019 unsigned int off = 0, last = 0;
7020 if (!wi::neg_p (x: wi::to_wide (t: val)) && wi::to_widest (t: val) <= UCHAR_MAX)
7021 off = 1;
7022 len = MIN (len, max_len - off);
7023 char *buf2 = XNEWVEC (char, len + off);
7024 if (off)
7025 buf2[0] = (char) tree_to_uhwi (val);
7026 memcpy (dest: buf2 + off, src: buf1, n: i);
7027 for (unsigned int j = 0; j < i; ++j)
7028 {
7029 c_parser_peek_token (parser);
7030 c_parser_consume_token (parser);
7031 c_parser_peek_token (parser);
7032 c_parser_consume_token (parser);
7033 }
7034 for (; i < len; ++i)
7035 {
7036 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
7037 break;
7038 tok = c_parser_peek_2nd_token (parser);
7039 if (tok->type != CPP_NUMBER
7040 || TREE_CODE (tok->value) != INTEGER_CST
7041 || TREE_TYPE (tok->value) != integer_type_node
7042 || wi::neg_p (x: wi::to_wide (t: tok->value))
7043 || wi::to_widest (t: tok->value) > UCHAR_MAX)
7044 break;
7045 c_token *tok2 = c_parser_peek_nth_token (parser, n: 3);
7046 if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
7047 break;
7048 buf2[i + off] = (char) tree_to_uhwi (tok->value);
7049 /* If orig_len is INT_MAX, this can be flexible array member and
7050 in that case we need to ensure another element which
7051 for CPP_EMBED is normally guaranteed after it. Include
7052 that byte in the RAW_DATA_OWNER though, so it can be optimized
7053 later. */
7054 if (orig_len == INT_MAX
7055 && (tok2->type == CPP_CLOSE_BRACE
7056 || (c_parser_peek_nth_token (parser, n: 4)->type
7057 != CPP_NUMBER)))
7058 {
7059 last = 1;
7060 break;
7061 }
7062 last_loc = tok->location;
7063 c_parser_consume_token (parser);
7064 c_parser_consume_token (parser);
7065 }
7066 val = make_node (RAW_DATA_CST);
7067 TREE_TYPE (val) = integer_type_node;
7068 RAW_DATA_LENGTH (val) = i;
7069 tree owner = build_string (i + off + last, buf2);
7070 XDELETEVEC (buf2);
7071 TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
7072 i + off + last);
7073 RAW_DATA_OWNER (val) = owner;
7074 RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
7075 init.value = val;
7076 set_c_expr_source_range (expr: &init, start: loc, finish: last_loc);
7077 init.original_code = RAW_DATA_CST;
7078 init.original_type = integer_type_node;
7079 init.m_decimal = 0;
7080 process_init_element (loc, init, false, braced_init_obstack);
7081 }
7082}
7083
7084/* Parse a compound statement (possibly a function body) (C90 6.6.2,
7085 C99 6.8.2, C11 6.8.2, C23 6.8.2).
7086
7087 compound-statement:
7088 { block-item-list[opt] }
7089 { label-declarations block-item-list }
7090
7091 block-item-list:
7092 block-item
7093 block-item-list block-item
7094
7095 block-item:
7096 label
7097 nested-declaration
7098 statement
7099
7100 nested-declaration:
7101 declaration
7102
7103 GNU extensions:
7104
7105 compound-statement:
7106 { label-declarations block-item-list }
7107
7108 nested-declaration:
7109 __extension__ nested-declaration
7110 nested-function-definition
7111
7112 label-declarations:
7113 label-declaration
7114 label-declarations label-declaration
7115
7116 label-declaration:
7117 __label__ identifier-list ;
7118
7119 Allowing the mixing of declarations and code is new in C99. The
7120 GNU syntax also permits (not shown above) labels at the end of
7121 compound statements, which yield an error. We don't allow labels
7122 on declarations; this might seem like a natural extension, but
7123 there would be a conflict between gnu-attributes on the label and
7124 prefix gnu-attributes on the declaration. ??? The syntax follows the
7125 old parser in requiring something after label declarations.
7126 Although they are erroneous if the labels declared aren't defined,
7127 is it useful for the syntax to be this way?
7128
7129 OpenACC:
7130
7131 block-item:
7132 openacc-directive
7133
7134 openacc-directive:
7135 update-directive
7136
7137 OpenMP:
7138
7139 block-item:
7140 openmp-directive
7141
7142 openmp-directive:
7143 barrier-directive
7144 flush-directive
7145 taskwait-directive
7146 taskyield-directive
7147 cancel-directive
7148 cancellation-point-directive */
7149
7150static tree
7151c_parser_compound_statement (c_parser *parser, location_t *endlocp)
7152{
7153 tree stmt;
7154 location_t brace_loc;
7155 brace_loc = c_parser_peek_token (parser)->location;
7156 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
7157 {
7158 /* Ensure a scope is entered and left anyway to avoid confusion
7159 if we have just prepared to enter a function body. */
7160 stmt = c_begin_compound_stmt (true);
7161 c_end_compound_stmt (brace_loc, stmt, true);
7162 return error_mark_node;
7163 }
7164 stmt = c_begin_compound_stmt (true);
7165 location_t end_loc = c_parser_compound_statement_nostart (parser);
7166 if (endlocp)
7167 *endlocp = end_loc;
7168
7169 return c_end_compound_stmt (brace_loc, stmt, true);
7170}
7171
7172/* Diagnose errors related to imperfectly nested loops in an OMP
7173 loop construct. This function is called when such code is seen.
7174 Only issue one such diagnostic no matter how much invalid
7175 intervening code there is in the loop.
7176 FIXME: maybe the location associated with the diagnostic should
7177 be the current parser token instead of the location of the outer loop
7178 nest. */
7179
7180static void
7181check_omp_intervening_code (c_parser *parser)
7182{
7183 struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
7184 gcc_assert (omp_for_parse_state);
7185
7186 if (!omp_for_parse_state->in_intervening_code)
7187 return;
7188 omp_for_parse_state->saw_intervening_code = true;
7189
7190 /* Only diagnose errors related to perfect nesting once. */
7191 if (!omp_for_parse_state->perfect_nesting_fail)
7192 {
7193
7194 /* OpenACC does not (yet) permit intervening code, in
7195 addition to situations forbidden by the OpenMP spec. */
7196 if (omp_for_parse_state->code == OACC_LOOP)
7197 {
7198 error_at (omp_for_parse_state->for_loc,
7199 "inner loops must be perfectly nested in "
7200 "%<#pragma acc loop%>");
7201 omp_for_parse_state->perfect_nesting_fail = true;
7202 }
7203 else if (omp_for_parse_state->ordered)
7204 {
7205 error_at (omp_for_parse_state->for_loc,
7206 "inner loops must be perfectly nested with "
7207 "%<ordered%> clause");
7208 omp_for_parse_state->perfect_nesting_fail = true;
7209 }
7210 else if (omp_for_parse_state->inscan)
7211 {
7212 error_at (omp_for_parse_state->for_loc,
7213 "inner loops must be perfectly nested with "
7214 "%<reduction%> %<inscan%> clause");
7215 omp_for_parse_state->perfect_nesting_fail = true;
7216 }
7217 else if (omp_for_parse_state->code == OMP_TILE)
7218 {
7219 error_at (omp_for_parse_state->for_loc,
7220 "inner loops must be perfectly nested in "
7221 "%<pragma omp tile%>");
7222 omp_for_parse_state->perfect_nesting_fail = true;
7223 }
7224 if (omp_for_parse_state->perfect_nesting_fail)
7225 omp_for_parse_state->fail = true;
7226 }
7227}
7228
7229/* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
7230 and add the statement to the current list. If SL is an empty statement
7231 list, do nothing. */
7232static void
7233add_structured_block_stmt (tree sl)
7234{
7235 if (TREE_CODE (sl) != STATEMENT_LIST
7236 || !tsi_end_p (i: tsi_start (t: sl)))
7237 add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
7238}
7239
7240struct c_omp_attribute_data
7241{
7242 vec<c_token, va_gc> *tokens;
7243 const c_omp_directive *dir;
7244 c_omp_directive_kind kind;
7245};
7246
7247/* Handle omp::directive and omp::sequence attributes in ATTRS
7248 (if any) at the start of a statement or in attribute-declaration. */
7249
7250static bool
7251c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
7252 bool *have_std_attrs)
7253{
7254 if (!flag_openmp && !flag_openmp_simd)
7255 return false;
7256
7257 auto_vec<c_omp_attribute_data, 16> vd;
7258 int cnt = 0;
7259 int tokens = 0;
7260 bool bad = false;
7261 for (tree *pa = &attrs; *pa; )
7262 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7263 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
7264 {
7265 cnt++;
7266 for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
7267 {
7268 tree d = TREE_VALUE (a);
7269 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7270 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7271 c_token *first = toks->address ();
7272 c_token *last = first + toks->length ();
7273 if (parser->omp_attrs_forbidden_p)
7274 {
7275 error_at (first->location,
7276 "mixing OpenMP directives with attribute and pragma "
7277 "syntax on the same statement");
7278 parser->omp_attrs_forbidden_p = false;
7279 bad = true;
7280 }
7281 else if (TREE_PUBLIC (d))
7282 {
7283 error_at (first->location,
7284 "OpenMP %<omp::decl%> attribute on a statement");
7285 bad = true;
7286 }
7287 const char *directive[3] = {};
7288 for (int i = 0; i < 3; i++)
7289 {
7290 tree id = NULL_TREE;
7291 if (first + i == last)
7292 break;
7293 if (first[i].type == CPP_NAME)
7294 id = first[i].value;
7295 else if (first[i].type == CPP_KEYWORD)
7296 id = ridpointers[(int) first[i].keyword];
7297 else
7298 break;
7299 directive[i] = IDENTIFIER_POINTER (id);
7300 }
7301 const c_omp_directive *dir = NULL;
7302 if (directive[0])
7303 dir = c_omp_categorize_directive (directive[0], directive[1],
7304 directive[2]);
7305 if (dir == NULL)
7306 {
7307 error_at (first->location,
7308 "unknown OpenMP directive name in %qs attribute "
7309 "argument",
7310 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7311 continue;
7312 }
7313 c_omp_directive_kind kind = dir->kind;
7314 if (dir->id == PRAGMA_OMP_ORDERED)
7315 {
7316 /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
7317 depend/doacross clause. */
7318 if (directive[1]
7319 && (strcmp (s1: directive[1], s2: "depend") == 0
7320 || strcmp (s1: directive[1], s2: "doacross") == 0))
7321 kind = C_OMP_DIR_STANDALONE;
7322 else if (first + 2 < last
7323 && first[1].type == CPP_COMMA
7324 && first[2].type == CPP_NAME
7325 && (strcmp (IDENTIFIER_POINTER (first[2].value),
7326 s2: "depend") == 0
7327 || strcmp (IDENTIFIER_POINTER (first[2].value),
7328 s2: "doacross") == 0))
7329 kind = C_OMP_DIR_STANDALONE;
7330 }
7331 else if (dir->id == PRAGMA_OMP_ERROR)
7332 {
7333 /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
7334 int paren_depth = 0;
7335 for (int i = 1; first + i < last; i++)
7336 if (first[i].type == CPP_OPEN_PAREN)
7337 paren_depth++;
7338 else if (first[i].type == CPP_CLOSE_PAREN)
7339 paren_depth--;
7340 else if (paren_depth == 0
7341 && first + i + 2 < last
7342 && first[i].type == CPP_NAME
7343 && first[i + 1].type == CPP_OPEN_PAREN
7344 && first[i + 2].type == CPP_NAME
7345 && !strcmp (IDENTIFIER_POINTER (first[i].value),
7346 s2: "at")
7347 && !strcmp (IDENTIFIER_POINTER (first[i
7348 + 2].value),
7349 s2: "execution"))
7350 {
7351 kind = C_OMP_DIR_STANDALONE;
7352 break;
7353 }
7354 }
7355 c_omp_attribute_data v = { .tokens: toks, .dir: dir, .kind: kind };
7356 vd.safe_push (obj: v);
7357 if (flag_openmp || dir->simd)
7358 tokens += (last - first) + 1;
7359 }
7360 c_omp_attribute_data v = {};
7361 vd.safe_push (obj: v);
7362 *pa = TREE_CHAIN (*pa);
7363 }
7364 else
7365 pa = &TREE_CHAIN (*pa);
7366
7367 if (bad)
7368 {
7369 fail:
7370 if (have_std_attrs && attrs == NULL)
7371 *have_std_attrs = false;
7372 return false;
7373 }
7374
7375 unsigned int i;
7376 c_omp_attribute_data *v;
7377 c_omp_attribute_data *construct_seen = nullptr;
7378 c_omp_attribute_data *standalone_seen = nullptr;
7379 c_omp_attribute_data *prev_standalone_seen = nullptr;
7380 FOR_EACH_VEC_ELT (vd, i, v)
7381 if (v->tokens)
7382 {
7383 if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
7384 construct_seen = v;
7385 else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
7386 standalone_seen = v;
7387 }
7388 else
7389 {
7390 if (standalone_seen && !prev_standalone_seen)
7391 {
7392 prev_standalone_seen = standalone_seen;
7393 standalone_seen = nullptr;
7394 }
7395 }
7396
7397 if (cnt > 1 && construct_seen)
7398 {
7399 error_at ((*construct_seen->tokens)[0].location,
7400 "OpenMP construct among %<omp::directive%> attributes"
7401 " requires all %<omp::directive%> attributes on the"
7402 " same statement to be in the same %<omp::sequence%>");
7403 goto fail;
7404 }
7405 if (cnt > 1 && standalone_seen && prev_standalone_seen)
7406 {
7407 error_at ((*standalone_seen->tokens)[0].location,
7408 "multiple OpenMP standalone directives among"
7409 " %<omp::directive%> attributes must be all within the"
7410 " same %<omp::sequence%>");
7411 goto fail;
7412 }
7413
7414 if (prev_standalone_seen)
7415 standalone_seen = prev_standalone_seen;
7416 if (standalone_seen
7417 && !c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7418 {
7419 error_at (standalone_seen->tokens->address ()->location,
7420 "standalone OpenMP directives in %<omp::directive%> attribute"
7421 " can only appear on an empty statement");
7422 goto fail;
7423 }
7424 if (cnt && c_parser_next_token_is (parser, type: CPP_PRAGMA))
7425 {
7426 c_token *token = c_parser_peek_token (parser);
7427 enum pragma_kind kind = token->pragma_kind;
7428 if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
7429 {
7430 error_at (token->location,
7431 "mixing OpenMP directives with attribute and pragma "
7432 "syntax on the same statement");
7433 goto fail;
7434 }
7435 }
7436
7437 if (!tokens)
7438 return false;
7439
7440 unsigned int tokens_avail = parser->tokens_avail;
7441
7442 tokens++;
7443 vec<c_token, va_gc> *toks = NULL;
7444 vec_safe_reserve (v&: toks, nelems: tokens, exact: true);
7445 FOR_EACH_VEC_ELT (vd, i, v)
7446 {
7447 if (!v->tokens)
7448 continue;
7449 if (!flag_openmp && !v->dir->simd)
7450 continue;
7451 c_token *first = v->tokens->address ();
7452 c_token *last = first + v->tokens->length ();
7453 c_token tok = {};
7454 tok.type = CPP_PRAGMA;
7455 tok.keyword = RID_MAX;
7456 tok.pragma_kind = pragma_kind (v->dir->id);
7457 tok.location = first->location;
7458 toks->quick_push (obj: tok);
7459 while (++first < last)
7460 toks->quick_push (obj: *first);
7461 tok = {};
7462 tok.type = CPP_PRAGMA_EOL;
7463 tok.keyword = RID_MAX;
7464 tok.location = last[-1].location;
7465 toks->quick_push (obj: tok);
7466 }
7467
7468 c_token tok = {};
7469 tok.type = CPP_EOF;
7470 tok.keyword = RID_MAX;
7471 tok.location = toks->last ().location;
7472 toks->quick_push (obj: tok);
7473
7474 gcc_assert (!parser->in_omp_attribute_pragma);
7475 parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
7476 parser->in_omp_attribute_pragma->token_vec = toks;
7477 parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
7478 parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
7479 parser->tokens = toks->address ();
7480 parser->tokens_avail = tokens;
7481 return true;
7482}
7483
7484/* Handle omp::directive and omp::sequence attributes in ATTRS
7485 (if any) at the start or after declaration-id of a declaration. */
7486
7487static void
7488c_parser_handle_directive_omp_attributes (tree &attrs,
7489 vec<c_token> *&pragma_clauses,
7490 vec<c_token> *attr_clauses)
7491{
7492 if (!flag_openmp && !flag_openmp_simd)
7493 return;
7494
7495 for (tree *pa = &attrs; *pa; )
7496 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7497 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
7498 {
7499 int cnt = 0;
7500 for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
7501 {
7502 tree a = *pa2;
7503 tree d = TREE_VALUE (a);
7504 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7505 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7506 c_token *first = toks->address ();
7507 c_token *last = first + toks->length ();
7508 const char *directive[3] = {};
7509 for (int i = 0; i < 3; i++)
7510 {
7511 tree id = NULL_TREE;
7512 if (first + i == last)
7513 break;
7514 if (first[i].type == CPP_NAME)
7515 id = first[i].value;
7516 else if (first[i].type == CPP_KEYWORD)
7517 id = ridpointers[(int) first[i].keyword];
7518 else
7519 break;
7520 directive[i] = IDENTIFIER_POINTER (id);
7521 }
7522 const c_omp_directive *dir = NULL;
7523 if (directive[0])
7524 dir = c_omp_categorize_directive (directive[0], directive[1],
7525 directive[2]);
7526 if (dir == NULL)
7527 {
7528 error_at (first->location,
7529 "unknown OpenMP directive name in "
7530 "%qs attribute argument",
7531 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7532 *pa2 = TREE_CHAIN (a);
7533 }
7534 else if (dir->id == PRAGMA_OMP_DECLARE
7535 && (strcmp (s1: directive[1], s2: "simd") == 0
7536 || strcmp (s1: directive[1], s2: "variant") == 0))
7537 {
7538 if (pragma_clauses)
7539 {
7540 error_at (first->location,
7541 "mixing OpenMP directives with attribute and "
7542 "pragma syntax on the same declaration");
7543 for (pa = &attrs; *pa; )
7544 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7545 && is_attribute_p (attr_name: "directive",
7546 ident: get_attribute_name (*pa)))
7547 *pa = TREE_CHAIN (*pa);
7548 else
7549 pa = &TREE_CHAIN (*pa);
7550 return;
7551 }
7552 ++cnt;
7553 attr_clauses->reserve (nelems: attr_clauses->length ()
7554 + toks->length () + 2);
7555 for (++first; first < last; ++first)
7556 attr_clauses->quick_push (obj: *first);
7557 c_token tok = {};
7558 tok.type = CPP_PRAGMA_EOL;
7559 tok.keyword = RID_MAX;
7560 tok.location = last[-1].location;
7561 attr_clauses->quick_push (obj: tok);
7562 *pa2 = TREE_CHAIN (a);
7563 }
7564 else
7565 pa2 = &TREE_CHAIN (a);
7566 }
7567 if (cnt && TREE_VALUE (*pa) == NULL_TREE)
7568 *pa = TREE_CHAIN (*pa);
7569 else
7570 pa = &TREE_CHAIN (*pa);
7571 }
7572 else
7573 pa = &TREE_CHAIN (*pa);
7574 if (attr_clauses->length ())
7575 {
7576 c_token tok = {};
7577 tok.type = CPP_EOF;
7578 tok.keyword = RID_MAX;
7579 tok.location = attr_clauses->last ().location;
7580 attr_clauses->quick_push (obj: tok);
7581 attr_clauses->quick_push (obj: tok);
7582 pragma_clauses = attr_clauses;
7583 }
7584}
7585
7586/* Check if STD_ATTR contains a musttail attribute and remove if it
7587 precedes a return. PARSER is the parser and ATTR is the output
7588 attr_state. */
7589
7590static tree
7591c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
7592{
7593 if (c_parser_next_token_is_keyword (parser, keyword: RID_RETURN))
7594 {
7595 if (tree a = lookup_attribute (attr_ns: "gnu", attr_name: "musttail", list: std_attrs))
7596 {
7597 for (; a; a = lookup_attribute (attr_ns: "gnu", attr_name: "musttail", TREE_CHAIN (a)))
7598 if (TREE_VALUE (a))
7599 error ("%qs attribute does not take any arguments",
7600 "musttail");
7601 std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
7602 attr.musttail_p = true;
7603 }
7604 if (lookup_attribute (attr_ns: "clang", attr_name: "musttail", list: std_attrs))
7605 {
7606 std_attrs = remove_attribute ("clang", "musttail", std_attrs);
7607 attr.musttail_p = true;
7608 }
7609 }
7610 return std_attrs;
7611}
7612
7613/* Return a statement before optional series of LABEL_EXPR/CASE_LABEL_EXPRs.
7614 Instead of collecting vectors of labels before each stmt just in case
7615 the statement would be iteration or switch statement for named loops,
7616 we just remember last emitted statement and let the iteration/switch
7617 statement search backwards in cur_stmt_list until that stmt for loop
7618 names if any. */
7619
7620static tree
7621get_before_labels ()
7622{
7623 if (!building_stmt_list_p ())
7624 return NULL_TREE;
7625 tree_stmt_iterator tsi = tsi_last (cur_stmt_list);
7626 if (tsi_end_p (i: tsi))
7627 return NULL_TREE;
7628 return tsi_stmt (i: tsi);
7629}
7630
7631/* Parse a compound statement except for the opening brace. This is
7632 used for parsing both compound statements and statement expressions
7633 (which follow different paths to handling the opening). */
7634
7635static location_t
7636c_parser_compound_statement_nostart (c_parser *parser)
7637{
7638 bool last_stmt = false;
7639 bool last_label = false;
7640 bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
7641 location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
7642 struct omp_for_parse_data *omp_for_parse_state
7643 = parser->omp_for_parse_state;
7644 bool in_omp_loop_block
7645 = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
7646 tree sl = NULL_TREE;
7647 attr_state a = {};
7648
7649 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7650 {
7651 location_t endloc = c_parser_peek_token (parser)->location;
7652 add_debug_begin_stmt (loc: endloc);
7653 c_parser_consume_token (parser);
7654 return endloc;
7655 }
7656
7657 /* If we're parsing a {} sequence in an OMP_FOR body, start a
7658 statement list for intervening code. */
7659 if (in_omp_loop_block)
7660 sl = push_stmt_list ();
7661
7662 mark_valid_location_for_stdc_pragma (true);
7663 if (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
7664 {
7665 /* Read zero or more forward-declarations for labels that nested
7666 functions can jump to. */
7667 mark_valid_location_for_stdc_pragma (false);
7668 if (in_omp_loop_block)
7669 check_omp_intervening_code (parser);
7670 while (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
7671 {
7672 label_loc = c_parser_peek_token (parser)->location;
7673 c_parser_consume_token (parser);
7674 /* Any identifiers, including those declared as type names,
7675 are OK here. */
7676 while (true)
7677 {
7678 tree label;
7679 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
7680 {
7681 c_parser_error (parser, gmsgid: "expected identifier");
7682 break;
7683 }
7684 label
7685 = declare_label (c_parser_peek_token (parser)->value);
7686 C_DECLARED_LABEL_FLAG (label) = 1;
7687 add_stmt (build_stmt (label_loc, DECL_EXPR, label));
7688 c_parser_consume_token (parser);
7689 if (c_parser_next_token_is (parser, type: CPP_COMMA))
7690 c_parser_consume_token (parser);
7691 else
7692 break;
7693 }
7694 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7695 }
7696 pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7697 }
7698 /* We must now have at least one statement, label or declaration. */
7699 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7700 {
7701 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7702 c_parser_error (parser, gmsgid: "expected declaration or statement");
7703 location_t endloc = c_parser_peek_token (parser)->location;
7704 c_parser_consume_token (parser);
7705 return endloc;
7706 }
7707 tree before_labels = get_before_labels ();
7708 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_BRACE))
7709 {
7710 location_t loc = c_parser_peek_token (parser)->location;
7711 loc = expansion_point_location_if_in_system_header (loc);
7712
7713 bool want_nested_loop = (omp_for_parse_state
7714 ? omp_for_parse_state->want_nested_loop
7715 : false);
7716
7717 /* First take care of special cases for OpenMP "canonical loop
7718 nest form", that do not allow standard attributes, labels, or
7719 __extension__ before the nested statement. */
7720 if (in_omp_loop_block && !last_label)
7721 {
7722 tree_code code = omp_for_parse_state->code;
7723 if (want_nested_loop
7724 && c_parser_omp_next_tokens_can_be_canon_loop (parser, code,
7725 false))
7726 {
7727 /* Found the next nested loop. If there were intervening
7728 code statements collected before now, wrap them in an
7729 OMP_STRUCTURED_BLOCK node, and start a new structured
7730 block to hold statements that may come after the FOR. */
7731 gcc_assert (sl);
7732 add_structured_block_stmt (sl: pop_stmt_list (sl));
7733 omp_for_parse_state->depth++;
7734 add_stmt (c_parser_omp_loop_nest (parser, NULL));
7735 omp_for_parse_state->depth--;
7736 sl = push_stmt_list ();
7737 parser->error = false;
7738 before_labels = get_before_labels ();
7739 continue;
7740 }
7741 else if (want_nested_loop
7742 && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7743 {
7744 /* If this nested compound statement contains the nested loop,
7745 we need to separate the other statements in the current
7746 statement into separate blocks of intervening code. If
7747 there's no nested loop, it's all part of the same
7748 chunk of intervening code. */
7749 tree pre_sl = pop_stmt_list (sl);
7750 tree nested_sl = push_stmt_list ();
7751 mark_valid_location_for_stdc_pragma (false);
7752 c_parser_statement_after_labels (parser, NULL, NULL_TREE);
7753 nested_sl = pop_stmt_list (nested_sl);
7754 if (omp_for_parse_state->want_nested_loop)
7755 {
7756 /* This block didn't contain a loop-nest, so it's
7757 all part of the same chunk of intervening code. */
7758 check_omp_intervening_code (parser);
7759 sl = push_stmt_list ();
7760 add_stmt (pre_sl);
7761 add_stmt (nested_sl);
7762 }
7763 else
7764 {
7765 /* It contains the nested loop. */
7766 add_structured_block_stmt (sl: pre_sl);
7767 add_stmt (nested_sl);
7768 sl = push_stmt_list ();
7769 }
7770 parser->error = false;
7771 before_labels = get_before_labels ();
7772 continue;
7773 }
7774 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7775 {
7776 /* Prior to implementing the OpenMP 5.1 syntax for canonical
7777 loop form, GCC used to accept an empty statements that
7778 would now be flagged as intervening code. Continue to
7779 do that, as an extension. */
7780 /* FIXME: Maybe issue a warning or something here? */
7781 c_parser_consume_token (parser);
7782 before_labels = get_before_labels ();
7783 continue;
7784 }
7785 }
7786
7787 /* Standard attributes may start a label, statement or declaration. */
7788 bool have_std_attrs
7789 = c_parser_nth_token_starts_std_attributes (parser, n: 1);
7790 tree std_attrs = NULL_TREE;
7791 if (have_std_attrs)
7792 {
7793 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7794 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr&: a);
7795 }
7796 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7797 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7798 || (c_parser_next_token_is (parser, type: CPP_NAME)
7799 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7800 {
7801 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7802 label_loc = c_parser_peek_2nd_token (parser)->location;
7803 else
7804 label_loc = c_parser_peek_token (parser)->location;
7805 last_label = true;
7806 last_stmt = false;
7807 mark_valid_location_for_stdc_pragma (false);
7808 if (in_omp_loop_block)
7809 check_omp_intervening_code (parser);
7810 c_parser_label (parser, std_attrs);
7811 }
7812 else if (c_parser_next_tokens_start_declaration (parser)
7813 || (have_std_attrs
7814 && !c_parser_handle_statement_omp_attributes
7815 (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7816 && c_parser_next_token_is (parser, type: CPP_SEMICOLON)
7817 && (have_std_attrs = true)))
7818 {
7819 if (last_label)
7820 pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wfree_labels,
7821 "a label can only be part of a statement and "
7822 "a declaration is not a statement");
7823 /* It's unlikely we'll see a nested loop in a declaration in
7824 intervening code in an OMP loop, but disallow it anyway. */
7825 if (in_omp_loop_block)
7826 {
7827 check_omp_intervening_code (parser);
7828 omp_for_parse_state->want_nested_loop = false;
7829 }
7830 mark_valid_location_for_stdc_pragma (false);
7831 bool fallthru_attr_p = false;
7832 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: !have_std_attrs,
7833 empty_ok: true, nested: true, start_attr_ok: true, simple_ok: false, NULL,
7834 NULL, have_attrs: have_std_attrs, attrs: std_attrs,
7835 NULL, fallthru_attr_p: &fallthru_attr_p);
7836
7837 if (in_omp_loop_block)
7838 omp_for_parse_state->want_nested_loop = want_nested_loop;
7839 if (last_stmt && !fallthru_attr_p)
7840 pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7841 "ISO C90 forbids mixed declarations and code");
7842 last_stmt = fallthru_attr_p;
7843 last_label = false;
7844 before_labels = get_before_labels ();
7845 }
7846 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
7847 {
7848 /* __extension__ can start a declaration, but is also an
7849 unary operator that can start an expression. Consume all
7850 but the last of a possible series of __extension__ to
7851 determine which. If standard attributes have already
7852 been seen, it must start a statement, not a declaration,
7853 but standard attributes starting a declaration may appear
7854 after __extension__. */
7855 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7856 && (c_parser_peek_2nd_token (parser)->keyword
7857 == RID_EXTENSION))
7858 c_parser_consume_token (parser);
7859 if (!have_std_attrs
7860 && (c_parser_next_tokens_start_declaration (parser, n: 2)
7861 || c_parser_nth_token_starts_std_attributes (parser, n: 2)))
7862 {
7863 int ext;
7864 ext = disable_extension_diagnostics ();
7865 c_parser_consume_token (parser);
7866 last_label = false;
7867 /* It's unlikely we'll see a nested loop in a declaration in
7868 intervening code in an OMP loop, but disallow it anyway. */
7869 if (in_omp_loop_block)
7870 {
7871 check_omp_intervening_code (parser);
7872 omp_for_parse_state->want_nested_loop = false;
7873 }
7874 mark_valid_location_for_stdc_pragma (false);
7875 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
7876 start_attr_ok: true, simple_ok: false);
7877 if (in_omp_loop_block)
7878 omp_for_parse_state->want_nested_loop = want_nested_loop;
7879 /* Following the old parser, __extension__ does not
7880 disable this diagnostic. */
7881 restore_extension_diagnostics (flags: ext);
7882 if (last_stmt)
7883 pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7884 "ISO C90 forbids mixed declarations and code");
7885 last_stmt = false;
7886 before_labels = get_before_labels ();
7887 }
7888 else
7889 goto statement;
7890 }
7891 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
7892 {
7893 if (have_std_attrs && !parser->in_omp_attribute_pragma)
7894 c_parser_error (parser, gmsgid: "expected declaration or statement");
7895 else if (std_attrs)
7896 c_warn_unused_attributes (std_attrs);
7897 /* External pragmas, and some omp pragmas, are not associated
7898 with regular c code, and so are not to be considered statements
7899 syntactically. This ensures that the user doesn't put them
7900 places that would turn into syntax errors if the directive
7901 were ignored. */
7902 if (omp_for_parse_state)
7903 omp_for_parse_state->want_nested_loop = false;
7904 if (c_parser_pragma (parser,
7905 last_label ? pragma_stmt : pragma_compound,
7906 NULL, before_labels))
7907 {
7908 last_label = false;
7909 last_stmt = true;
7910 if (omp_for_parse_state)
7911 check_omp_intervening_code (parser);
7912 }
7913 if (omp_for_parse_state)
7914 omp_for_parse_state->want_nested_loop = want_nested_loop;
7915 before_labels = get_before_labels ();
7916 }
7917 else if (c_parser_next_token_is (parser, type: CPP_EOF))
7918 {
7919 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7920 c_parser_error (parser, gmsgid: "expected declaration or statement");
7921 return c_parser_peek_token (parser)->location;
7922 }
7923 else if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7924 {
7925 if (parser->in_if_block)
7926 {
7927 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7928 error_at (loc, "expected %<}%> before %<else%>");
7929 return c_parser_peek_token (parser)->location;
7930 }
7931 else
7932 {
7933 error_at (loc, "%<else%> without a previous %<if%>");
7934 c_parser_consume_token (parser);
7935 before_labels = get_before_labels ();
7936 continue;
7937 }
7938 }
7939 else
7940 {
7941 statement:
7942 c_warn_unused_attributes (std_attrs);
7943 last_label = false;
7944 last_stmt = true;
7945 mark_valid_location_for_stdc_pragma (false);
7946 if (!omp_for_parse_state)
7947 c_parser_statement_after_labels (parser, NULL, before_labels,
7948 NULL, a);
7949 else
7950 {
7951 /* In canonical loop nest form, nested loops can only appear
7952 directly, or in a directly nested compound statement. We
7953 already took care of those cases above, so now we have
7954 something else. This statement and everything inside
7955 it must be intervening code. */
7956 omp_for_parse_state->want_nested_loop = false;
7957 check_omp_intervening_code (parser);
7958 c_parser_statement_after_labels (parser, NULL, before_labels);
7959 omp_for_parse_state->want_nested_loop = want_nested_loop;
7960 }
7961 before_labels = get_before_labels ();
7962 }
7963
7964 parser->error = false;
7965 }
7966 if (last_label)
7967 pedwarn_c11 (label_loc, OPT_Wfree_labels,
7968 "label at end of compound statement");
7969 location_t endloc = c_parser_peek_token (parser)->location;
7970 c_parser_consume_token (parser);
7971
7972 /* Restore the value we started with. */
7973 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7974
7975 /* Package leftover intervening code, or the whole contents of the
7976 compound statement if we were looking for a nested loop in an OMP_FOR
7977 construct and didn't find one. */
7978 if (sl)
7979 {
7980 sl = pop_stmt_list (sl);
7981 if (omp_for_parse_state->want_nested_loop)
7982 add_stmt (sl);
7983 else
7984 add_structured_block_stmt (sl);
7985 }
7986 return endloc;
7987}
7988
7989/* Parse all consecutive labels, possibly preceded by standard
7990 attributes. In this context, a statement is required, not a
7991 declaration, so attributes must be followed by a statement that is
7992 not just a semicolon. Returns an attr_state. */
7993
7994static attr_state
7995c_parser_all_labels (c_parser *parser)
7996{
7997 attr_state attr = {};
7998 bool have_std_attrs;
7999 tree std_attrs = NULL;
8000 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1)))
8001 {
8002 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8003 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
8004 }
8005
8006 while (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
8007 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
8008 || (c_parser_next_token_is (parser, type: CPP_NAME)
8009 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
8010 {
8011 c_parser_label (parser, std_attrs);
8012 std_attrs = NULL;
8013 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
8014 n: 1)))
8015 {
8016 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8017 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
8018 }
8019 }
8020 if (std_attrs
8021 && (!c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
8022 || std_attrs))
8023 {
8024 if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8025 c_parser_error (parser, gmsgid: "expected statement");
8026 c_warn_unused_attributes (std_attrs);
8027 }
8028 else if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8029 c_parser_error (parser, gmsgid: "expected statement");
8030 return attr;
8031}
8032
8033
8034/* Information used while parsing an OpenMP metadirective. */
8035struct omp_metadirective_parse_data {
8036 /* These fields are used to unique-ify labels when reparsing the
8037 code in a metadirective alternative. */
8038 vec<tree> * GTY((skip)) body_labels;
8039 unsigned int region_num;
8040};
8041
8042/* Helper function for c_parser_label: mangle a metadirective region
8043 label NAME. */
8044static tree
8045mangle_metadirective_region_label (c_parser *parser, tree name)
8046{
8047 if (parser->omp_metadirective_state->body_labels->contains (search: name))
8048 {
8049 const char *old_name = IDENTIFIER_POINTER (name);
8050 char *new_name = (char *) XALLOCAVEC (char, strlen (old_name) + 32);
8051 sprintf (s: new_name, format: "%s_MDR%u", old_name,
8052 parser->omp_metadirective_state->region_num);
8053 return get_identifier (new_name);
8054 }
8055 return name;
8056}
8057
8058/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
8059
8060 label:
8061 identifier : gnu-attributes[opt]
8062 case constant-expression :
8063 default :
8064
8065 GNU extensions:
8066
8067 label:
8068 case constant-expression ... constant-expression :
8069
8070 The use of gnu-attributes on labels is a GNU extension. The syntax in
8071 GNU C accepts any expressions without commas, non-constant
8072 expressions being rejected later. Any standard
8073 attribute-specifier-sequence before the first label has been parsed
8074 in the caller, to distinguish statements from declarations. Any
8075 attribute-specifier-sequence after the label is parsed in this
8076 function. */
8077static void
8078c_parser_label (c_parser *parser, tree std_attrs)
8079{
8080 location_t loc1 = c_parser_peek_token (parser)->location;
8081 tree label = NULL_TREE;
8082
8083 /* Remember whether this case or a user-defined label is allowed to fall
8084 through to. */
8085 bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
8086
8087 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
8088 {
8089 tree exp1, exp2;
8090 c_parser_consume_token (parser);
8091 exp1 = convert_lvalue_to_rvalue (loc1,
8092 c_parser_expr_no_commas (parser, NULL),
8093 true, true).value;
8094 if (c_parser_next_token_is (parser, type: CPP_COLON))
8095 {
8096 c_parser_consume_token (parser);
8097 label = do_case (loc1, exp1, NULL_TREE, std_attrs);
8098 }
8099 else if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
8100 {
8101 c_parser_consume_token (parser);
8102 exp2 = convert_lvalue_to_rvalue (loc1,
8103 c_parser_expr_no_commas (parser,
8104 NULL),
8105 true, true).value;
8106 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
8107 label = do_case (loc1, exp1, exp2, std_attrs);
8108 }
8109 else
8110 c_parser_error (parser, gmsgid: "expected %<:%> or %<...%>");
8111 }
8112 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
8113 {
8114 c_parser_consume_token (parser);
8115 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
8116 label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
8117 }
8118 else
8119 {
8120 tree name = c_parser_peek_token (parser)->value;
8121 tree tlab;
8122 tree attrs;
8123 location_t loc2 = c_parser_peek_token (parser)->location;
8124 gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
8125 c_parser_consume_token (parser);
8126 gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
8127 c_parser_consume_token (parser);
8128 attrs = c_parser_gnu_attributes (parser);
8129 if (parser->omp_metadirective_state)
8130 name = mangle_metadirective_region_label (parser, name);
8131 tlab = define_label (loc2, name);
8132 if (tlab)
8133 {
8134 decl_attributes (&tlab, attrs, 0);
8135 decl_attributes (&tlab, std_attrs, 0);
8136 label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
8137 }
8138 if (attrs
8139 && c_parser_next_tokens_start_declaration (parser))
8140 warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
8141 " label and declaration appertains to the label");
8142 }
8143 if (label)
8144 {
8145 if (TREE_CODE (label) == LABEL_EXPR)
8146 FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
8147 else
8148 FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
8149 }
8150}
8151
8152/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
8153
8154 statement:
8155 labeled-statement
8156 attribute-specifier-sequence[opt] compound-statement
8157 expression-statement
8158 attribute-specifier-sequence[opt] selection-statement
8159 attribute-specifier-sequence[opt] iteration-statement
8160 attribute-specifier-sequence[opt] jump-statement
8161
8162 labeled-statement:
8163 attribute-specifier-sequence[opt] label statement
8164
8165 expression-statement:
8166 expression[opt] ;
8167 attribute-specifier-sequence expression ;
8168
8169 selection-statement:
8170 if-statement
8171 switch-statement
8172
8173 iteration-statement:
8174 while-statement
8175 do-statement
8176 for-statement
8177
8178 jump-statement:
8179 goto identifier ;
8180 continue ;
8181 break ;
8182 return expression[opt] ;
8183
8184 GNU extensions:
8185
8186 statement:
8187 attribute-specifier-sequence[opt] asm-statement
8188
8189 jump-statement:
8190 goto * expression ;
8191
8192 expression-statement:
8193 gnu-attributes ;
8194
8195 Objective-C:
8196
8197 statement:
8198 attribute-specifier-sequence[opt] objc-throw-statement
8199 attribute-specifier-sequence[opt] objc-try-catch-statement
8200 attribute-specifier-sequence[opt] objc-synchronized-statement
8201
8202 objc-throw-statement:
8203 @throw expression ;
8204 @throw ;
8205
8206 OpenACC:
8207
8208 statement:
8209 attribute-specifier-sequence[opt] openacc-construct
8210
8211 openacc-construct:
8212 parallel-construct
8213 kernels-construct
8214 data-construct
8215 loop-construct
8216
8217 parallel-construct:
8218 parallel-directive structured-block
8219
8220 kernels-construct:
8221 kernels-directive structured-block
8222
8223 data-construct:
8224 data-directive structured-block
8225
8226 loop-construct:
8227 loop-directive structured-block
8228
8229 OpenMP:
8230
8231 statement:
8232 attribute-specifier-sequence[opt] openmp-construct
8233
8234 openmp-construct:
8235 parallel-construct
8236 for-construct
8237 simd-construct
8238 for-simd-construct
8239 sections-construct
8240 single-construct
8241 parallel-for-construct
8242 parallel-for-simd-construct
8243 parallel-sections-construct
8244 master-construct
8245 critical-construct
8246 atomic-construct
8247 ordered-construct
8248
8249 parallel-construct:
8250 parallel-directive structured-block
8251
8252 for-construct:
8253 for-directive iteration-statement
8254
8255 simd-construct:
8256 simd-directive iteration-statements
8257
8258 for-simd-construct:
8259 for-simd-directive iteration-statements
8260
8261 sections-construct:
8262 sections-directive section-scope
8263
8264 single-construct:
8265 single-directive structured-block
8266
8267 parallel-for-construct:
8268 parallel-for-directive iteration-statement
8269
8270 parallel-for-simd-construct:
8271 parallel-for-simd-directive iteration-statement
8272
8273 parallel-sections-construct:
8274 parallel-sections-directive section-scope
8275
8276 master-construct:
8277 master-directive structured-block
8278
8279 critical-construct:
8280 critical-directive structured-block
8281
8282 atomic-construct:
8283 atomic-directive expression-statement
8284
8285 ordered-construct:
8286 ordered-directive structured-block
8287
8288 Transactional Memory:
8289
8290 statement:
8291 attribute-specifier-sequence[opt] transaction-statement
8292 attribute-specifier-sequence[opt] transaction-cancel-statement
8293
8294 IF_P is used to track whether there's a (possibly labeled) if statement
8295 which is not enclosed in braces and has an else clause. This is used to
8296 implement -Wparentheses. */
8297
8298static void
8299c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
8300{
8301 tree before_labels = get_before_labels ();
8302 attr_state a = c_parser_all_labels (parser);
8303 if (loc_after_labels)
8304 *loc_after_labels = c_parser_peek_token (parser)->location;
8305 parser->omp_attrs_forbidden_p = false;
8306 c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8307}
8308
8309/* Parse and handle optional identifier after break or continue keywords. */
8310
8311static tree
8312c_parser_bc_name (c_parser *parser, bool is_break)
8313{
8314 if (!c_parser_next_token_is (parser, type: CPP_NAME))
8315 return NULL_TREE;
8316
8317 c_token *tok = c_parser_peek_token (parser);
8318 tree label = c_finish_bc_name (tok->location, tok->value, is_break);
8319 c_parser_consume_token (parser);
8320 return label;
8321}
8322
8323/* Parse a statement, other than a labeled statement. CHAIN is a vector
8324 of if-else-if conditions. All labels and standard attributes have
8325 been parsed in the caller.
8326
8327 IF_P is used to track whether there's a (possibly labeled) if statement
8328 which is not enclosed in braces and has an else clause. This is used to
8329 implement -Wparentheses. ASTATE is an earlier parsed attribute state.
8330
8331 BEFORE_LABELS is last statement before possible labels, see
8332 get_before_labels description for details. */
8333
8334static void
8335c_parser_statement_after_labels (c_parser *parser, bool *if_p,
8336 tree before_labels,
8337 vec<tree> *chain, attr_state astate)
8338{
8339 location_t loc = c_parser_peek_token (parser)->location;
8340 tree stmt = NULL_TREE;
8341 bool in_if_block = parser->in_if_block;
8342 parser->in_if_block = false;
8343 if (if_p != NULL)
8344 *if_p = false;
8345
8346 if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
8347 add_debug_begin_stmt (loc);
8348
8349 restart:
8350 switch (c_parser_peek_token (parser)->type)
8351 {
8352 case CPP_OPEN_BRACE:
8353 add_stmt (c_parser_compound_statement (parser));
8354 break;
8355 case CPP_KEYWORD:
8356 switch (c_parser_peek_token (parser)->keyword)
8357 {
8358 case RID_IF:
8359 c_parser_if_statement (parser, if_p, chain);
8360 break;
8361 case RID_SWITCH:
8362 c_parser_switch_statement (parser, if_p, before_labels);
8363 break;
8364 case RID_WHILE:
8365 c_parser_while_statement (parser, false, 0, false, if_p, before_labels);
8366 break;
8367 case RID_DO:
8368 c_parser_do_statement (parser, false, 0, false, before_labels);
8369 break;
8370 case RID_FOR:
8371 c_parser_for_statement (parser, false, 0, false, if_p, before_labels);
8372 break;
8373 case RID_GOTO:
8374 c_parser_consume_token (parser);
8375 if (c_parser_next_token_is (parser, type: CPP_NAME))
8376 {
8377 tree name = c_parser_peek_token (parser)->value;
8378 if (parser->omp_metadirective_state)
8379 name = mangle_metadirective_region_label (parser, name);
8380 stmt = c_finish_goto_label (loc, name);
8381 c_parser_consume_token (parser);
8382 }
8383 else if (c_parser_next_token_is (parser, type: CPP_MULT))
8384 {
8385 struct c_expr val;
8386
8387 c_parser_consume_token (parser);
8388 val = c_parser_expression (parser);
8389 val = convert_lvalue_to_rvalue (loc, val, false, true);
8390 stmt = c_finish_goto_ptr (loc, val);
8391 }
8392 else
8393 c_parser_error (parser, gmsgid: "expected identifier or %<*%>");
8394 goto expect_semicolon;
8395 case RID_CONTINUE:
8396 c_parser_consume_token (parser);
8397 stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false,
8398 c_parser_bc_name (parser, is_break: false));
8399 goto expect_semicolon;
8400 case RID_BREAK:
8401 c_parser_consume_token (parser);
8402 stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true,
8403 c_parser_bc_name (parser, is_break: true));
8404 goto expect_semicolon;
8405 case RID_RETURN:
8406 c_parser_consume_token (parser);
8407 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8408 {
8409 stmt = c_finish_return (loc, NULL_TREE, NULL_TREE,
8410 astate.musttail_p);
8411 c_parser_consume_token (parser);
8412 }
8413 else
8414 {
8415 location_t xloc = c_parser_peek_token (parser)->location;
8416 struct c_expr expr = c_parser_expression_conv (parser);
8417 mark_exp_read (expr.value);
8418 stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
8419 expr.value, expr.original_type,
8420 astate.musttail_p);
8421 goto expect_semicolon;
8422 }
8423 break;
8424 case RID_ASM:
8425 stmt = c_parser_asm_statement (parser);
8426 break;
8427 case RID_TRANSACTION_ATOMIC:
8428 case RID_TRANSACTION_RELAXED:
8429 stmt = c_parser_transaction (parser,
8430 c_parser_peek_token (parser)->keyword);
8431 break;
8432 case RID_TRANSACTION_CANCEL:
8433 stmt = c_parser_transaction_cancel (parser);
8434 goto expect_semicolon;
8435 case RID_AT_THROW:
8436 gcc_assert (c_dialect_objc ());
8437 c_parser_consume_token (parser);
8438 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8439 {
8440 stmt = objc_build_throw_stmt (loc, NULL_TREE);
8441 c_parser_consume_token (parser);
8442 }
8443 else
8444 {
8445 struct c_expr expr = c_parser_expression (parser);
8446 expr = convert_lvalue_to_rvalue (loc, expr, false, false);
8447 expr.value = c_fully_fold (expr.value, false, NULL);
8448 stmt = objc_build_throw_stmt (loc, expr.value);
8449 goto expect_semicolon;
8450 }
8451 break;
8452 case RID_AT_TRY:
8453 gcc_assert (c_dialect_objc ());
8454 c_parser_objc_try_catch_finally_statement (parser);
8455 break;
8456 case RID_AT_SYNCHRONIZED:
8457 gcc_assert (c_dialect_objc ());
8458 c_parser_objc_synchronized_statement (parser);
8459 break;
8460 case RID_ATTRIBUTE:
8461 {
8462 /* Allow '__attribute__((fallthrough));' or
8463 '__attribute__((assume(cond)));' or
8464 '__attribute__((musttail))) return'. */
8465 tree attrs = c_parser_gnu_attributes (parser);
8466 bool has_assume = lookup_attribute (attr_name: "assume", list: attrs);
8467 if (has_assume)
8468 {
8469 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8470 attrs = handle_assume_attribute (here: loc, attrs, nested: true);
8471 else
8472 {
8473 auto_urlify_attributes sentinel;
8474 warning_at (loc, OPT_Wattributes,
8475 "%<assume%> attribute not followed by %<;%>");
8476 has_assume = false;
8477 }
8478 }
8479 gcc_assert (!astate.musttail_p);
8480 attrs = c_parser_handle_musttail (parser, std_attrs: attrs, attr&: astate);
8481 if (astate.musttail_p)
8482 {
8483 if (attrs)
8484 {
8485 auto_urlify_attributes sentinel;
8486 warning_at (c_parser_peek_token (parser)->location,
8487 OPT_Wattributes,
8488 "attribute %<musttail%> mixed with other "
8489 "attributes on %<return%> statement");
8490 }
8491 goto restart;
8492 }
8493 if (attribute_fallthrough_p (attrs))
8494 {
8495 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8496 {
8497 tree fn = build_call_expr_internal_loc (loc,
8498 IFN_FALLTHROUGH,
8499 void_type_node, 0);
8500 add_stmt (fn);
8501 /* Eat the ';'. */
8502 c_parser_consume_token (parser);
8503 }
8504 else
8505 {
8506 auto_urlify_attributes sentinel;
8507 warning_at (loc, OPT_Wattributes,
8508 "%<fallthrough%> attribute not followed "
8509 "by %<;%>");
8510 }
8511 }
8512 else if (has_assume)
8513 /* Eat the ';'. */
8514 c_parser_consume_token (parser);
8515 else if (attrs != NULL_TREE)
8516 {
8517 auto_urlify_attributes sentinel;
8518 warning_at (loc, OPT_Wattributes,
8519 "only attribute %<fallthrough%> or %<assume%> can "
8520 "be applied to a null statement");
8521 }
8522 break;
8523 }
8524 default:
8525 goto expr_stmt;
8526 }
8527 break;
8528 case CPP_SEMICOLON:
8529 c_parser_consume_token (parser);
8530 break;
8531 case CPP_CLOSE_PAREN:
8532 case CPP_CLOSE_SQUARE:
8533 /* Avoid infinite loop in error recovery:
8534 c_parser_skip_until_found stops at a closing nesting
8535 delimiter without consuming it, but here we need to consume
8536 it to proceed further. */
8537 c_parser_error (parser, gmsgid: "expected statement");
8538 c_parser_consume_token (parser);
8539 break;
8540 case CPP_PRAGMA:
8541 if (!c_parser_pragma (parser, pragma_stmt, if_p, before_labels))
8542 goto restart;
8543 break;
8544 default:
8545 expr_stmt:
8546 stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
8547 expect_semicolon:
8548 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
8549 break;
8550 }
8551 /* Two cases cannot and do not have line numbers associated: If stmt
8552 is degenerate, such as "2;", then stmt is an INTEGER_CST, which
8553 cannot hold line numbers. But that's OK because the statement
8554 will either be changed to a MODIFY_EXPR during gimplification of
8555 the statement expr, or discarded. If stmt was compound, but
8556 without new variables, we will have skipped the creation of a
8557 BIND and will have a bare STATEMENT_LIST. But that's OK because
8558 (recursively) all of the component statements should already have
8559 line numbers assigned. ??? Can we discard no-op statements
8560 earlier? */
8561 if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
8562 protected_set_expr_location (stmt, loc);
8563
8564 parser->in_if_block = in_if_block;
8565}
8566
8567/* Parse the condition from an if, do, while or for statements. */
8568
8569static tree
8570c_parser_condition (c_parser *parser)
8571{
8572 location_t loc = c_parser_peek_token (parser)->location;
8573 tree cond;
8574 cond = c_parser_expression_conv (parser).value;
8575 cond = c_objc_common_truthvalue_conversion (loc, cond);
8576 cond = c_fully_fold (cond, false, NULL);
8577 if (warn_sequence_point)
8578 verify_sequence_points (cond);
8579 return cond;
8580}
8581
8582/* Parse a parenthesized condition from a do or while statement.
8583
8584 condition:
8585 ( expression )
8586*/
8587
8588static tree
8589c_parser_paren_condition (c_parser *parser)
8590{
8591 tree cond;
8592 matching_parens parens;
8593 if (!parens.require_open (parser))
8594 return error_mark_node;
8595 cond = c_parser_condition (parser);
8596 parens.skip_until_found_close (parser);
8597 return cond;
8598}
8599
8600/* Parse a selection-header:
8601
8602 selection-header:
8603 expression
8604 declaration expression
8605 simple-declaration
8606
8607 simple-declaration:
8608 attribute-specifier-sequence[opt] declaration-specifiers declarator
8609 = initializer
8610
8611 SWITCH_P is true if we are called from c_parser_switch_statement; in
8612 that case, don't perform the truthvalue conversion. */
8613
8614static c_expr
8615c_parser_selection_header (c_parser *parser, bool switch_p)
8616{
8617 location_t loc = c_parser_peek_token (parser)->location;
8618 c_expr expr;
8619 bool parse_expr = true;
8620 tree std_attrs;
8621 bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
8622 if (have_std_attrs)
8623 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8624 else
8625 std_attrs = NULL_TREE;
8626 if (c_parser_next_tokens_start_declaration (parser))
8627 {
8628 pedwarn_c23 (loc, OPT_Wpedantic,
8629 "ISO C does not support if declarations before C2Y");
8630 expr.value
8631 = c_parser_declaration_or_fndef (parser,
8632 /*fndef_ok=*/false,
8633 /*static_assert_ok=*/false,
8634 /*empty_ok=*/false,
8635 /*nested=*/true,
8636 /*start_attr_ok=*/true,
8637 /*simple_ok=*/true,
8638 /*objc_foreach_object_decl=*/objc_foreach_object_declaration: nullptr,
8639 /*omp_declare_simd_clauses=*/nullptr,
8640 have_attrs: have_std_attrs,
8641 attrs: std_attrs);
8642 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8643 c_parser_consume_token (parser);
8644 else
8645 {
8646 /* A simple-declaration is a declaration that can appear in
8647 place of the controlling expression of a selection statement.
8648 In that case, there shall be an initializer. */
8649 if (!expr.value)
8650 {
8651 error_at (loc, "declaration in the controlling expression must "
8652 "have an initializer");
8653 expr.original_type = error_mark_node;
8654 expr.set_error ();
8655 return expr;
8656 }
8657 parse_expr = false;
8658 }
8659 if (expr.value)
8660 {
8661 expr.original_type = TREE_TYPE (expr.value);
8662 expr = convert_lvalue_to_rvalue (loc, expr, /*convert_p=*/true,
8663 /*read_p=*/true);
8664 }
8665 }
8666 else if (have_std_attrs)
8667 {
8668 c_parser_error (parser, gmsgid: "expected declaration");
8669 expr.original_type = error_mark_node;
8670 expr.set_error ();
8671 return expr;
8672 }
8673
8674 if (parse_expr)
8675 expr = c_parser_expression_conv (parser);
8676 if (!switch_p)
8677 {
8678 expr.value = c_objc_common_truthvalue_conversion (loc, expr.value);
8679 expr.value = c_fully_fold (expr.value, false, NULL);
8680 if (warn_sequence_point)
8681 verify_sequence_points (expr.value);
8682 }
8683 return expr;
8684}
8685
8686/* Parse a selection-header enclosed in parentheses:
8687
8688 ( selection-header )
8689*/
8690
8691static tree
8692c_parser_paren_selection_header (c_parser *parser)
8693{
8694 matching_parens parens;
8695 if (!parens.require_open (parser))
8696 return error_mark_node;
8697 tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value;
8698 parens.skip_until_found_close (parser);
8699 return cond;
8700}
8701
8702/* Parse a statement which is a block in C99.
8703
8704 IF_P is used to track whether there's a (possibly labeled) if statement
8705 which is not enclosed in braces and has an else clause. This is used to
8706 implement -Wparentheses. */
8707
8708static tree
8709c_parser_c99_block_statement (c_parser *parser, bool *if_p,
8710 location_t *loc_after_labels)
8711{
8712 tree block = c_begin_compound_stmt (flag_isoc99);
8713 location_t loc = c_parser_peek_token (parser)->location;
8714 c_parser_statement (parser, if_p, loc_after_labels);
8715 return c_end_compound_stmt (loc, block, flag_isoc99);
8716}
8717
8718/* Parse the body of an if statement. This is just parsing a
8719 statement but (a) it is a block in C99, (b) we track whether the
8720 body is an if statement for the sake of -Wparentheses warnings, (c)
8721 we handle an empty body specially for the sake of -Wempty-body
8722 warnings, and (d) we call parser_compound_statement directly
8723 because c_parser_statement_after_labels resets
8724 parser->in_if_block.
8725
8726 IF_P is used to track whether there's a (possibly labeled) if statement
8727 which is not enclosed in braces and has an else clause. This is used to
8728 implement -Wparentheses. */
8729
8730static tree
8731c_parser_if_body (c_parser *parser, bool *if_p,
8732 const token_indent_info &if_tinfo)
8733{
8734 tree block = c_begin_compound_stmt (flag_isoc99);
8735 location_t body_loc = c_parser_peek_token (parser)->location;
8736 location_t body_loc_after_labels = UNKNOWN_LOCATION;
8737 token_indent_info body_tinfo
8738 = get_token_indent_info (token: c_parser_peek_token (parser));
8739 tree before_labels = get_before_labels ();
8740 attr_state a = c_parser_all_labels (parser);
8741
8742 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8743 {
8744 location_t loc = c_parser_peek_token (parser)->location;
8745 add_stmt (build_empty_stmt (loc));
8746 c_parser_consume_token (parser);
8747 if (!c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
8748 warning_at (loc, OPT_Wempty_body,
8749 "suggest braces around empty body in an %<if%> statement");
8750 }
8751 else if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
8752 add_stmt (c_parser_compound_statement (parser));
8753 else
8754 {
8755 body_loc_after_labels = c_parser_peek_token (parser)->location;
8756 c_parser_statement_after_labels (parser, if_p, before_labels, NULL, astate: a);
8757 }
8758
8759 token_indent_info next_tinfo
8760 = get_token_indent_info (token: c_parser_peek_token (parser));
8761 warn_for_misleading_indentation (guard_tinfo: if_tinfo, body_tinfo, next_tinfo);
8762 if (body_loc_after_labels != UNKNOWN_LOCATION
8763 && next_tinfo.type != CPP_SEMICOLON)
8764 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8765 if_tinfo.location, RID_IF);
8766
8767 return c_end_compound_stmt (body_loc, block, flag_isoc99);
8768}
8769
8770/* Parse the else body of an if statement. This is just parsing a
8771 statement but (a) it is a block in C99, (b) we handle an empty body
8772 specially for the sake of -Wempty-body warnings. CHAIN is a vector
8773 of if-else-if conditions. */
8774
8775static tree
8776c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
8777 vec<tree> *chain)
8778{
8779 location_t body_loc = c_parser_peek_token (parser)->location;
8780 tree block = c_begin_compound_stmt (flag_isoc99);
8781 token_indent_info body_tinfo
8782 = get_token_indent_info (token: c_parser_peek_token (parser));
8783 location_t body_loc_after_labels = UNKNOWN_LOCATION;
8784 tree before_labels = get_before_labels ();
8785 attr_state a = c_parser_all_labels (parser);
8786
8787 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8788 {
8789 location_t loc = c_parser_peek_token (parser)->location;
8790 warning_at (loc,
8791 OPT_Wempty_body,
8792 "suggest braces around empty body in an %<else%> statement");
8793 add_stmt (build_empty_stmt (loc));
8794 c_parser_consume_token (parser);
8795 }
8796 else
8797 {
8798 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
8799 body_loc_after_labels = c_parser_peek_token (parser)->location;
8800 c_parser_statement_after_labels (parser, NULL, before_labels, chain, astate: a);
8801 }
8802
8803 token_indent_info next_tinfo
8804 = get_token_indent_info (token: c_parser_peek_token (parser));
8805 warn_for_misleading_indentation (guard_tinfo: else_tinfo, body_tinfo, next_tinfo);
8806 if (body_loc_after_labels != UNKNOWN_LOCATION
8807 && next_tinfo.type != CPP_SEMICOLON)
8808 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8809 else_tinfo.location, RID_ELSE);
8810
8811 return c_end_compound_stmt (body_loc, block, flag_isoc99);
8812}
8813
8814/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8815
8816 if-statement:
8817 if ( selection-header ) statement
8818 if ( selection-header ) statement else statement
8819
8820 CHAIN is a vector of if-else-if conditions.
8821 IF_P is used to track whether there's a (possibly labeled) if statement
8822 which is not enclosed in braces and has an else clause. This is used to
8823 implement -Wparentheses. */
8824
8825static void
8826c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
8827{
8828 tree block;
8829 location_t loc;
8830 tree cond;
8831 bool nested_if = false;
8832 tree first_body, second_body;
8833 bool in_if_block;
8834
8835 gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
8836 token_indent_info if_tinfo
8837 = get_token_indent_info (token: c_parser_peek_token (parser));
8838 c_parser_consume_token (parser);
8839 block = c_begin_compound_stmt (flag_isoc99);
8840 loc = c_parser_peek_token (parser)->location;
8841 cond = c_parser_paren_selection_header (parser);
8842 in_if_block = parser->in_if_block;
8843 parser->in_if_block = true;
8844 first_body = c_parser_if_body (parser, if_p: &nested_if, if_tinfo);
8845 parser->in_if_block = in_if_block;
8846
8847 if (warn_duplicated_cond)
8848 warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
8849
8850 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
8851 {
8852 token_indent_info else_tinfo
8853 = get_token_indent_info (token: c_parser_peek_token (parser));
8854 c_parser_consume_token (parser);
8855 if (warn_duplicated_cond)
8856 {
8857 if (c_parser_next_token_is_keyword (parser, keyword: RID_IF)
8858 && chain == NULL)
8859 {
8860 /* We've got "if (COND) else if (COND2)". Start the
8861 condition chain and add COND as the first element. */
8862 chain = new vec<tree> ();
8863 if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8864 chain->safe_push (obj: cond);
8865 }
8866 else if (!c_parser_next_token_is_keyword (parser, keyword: RID_IF))
8867 /* This is if-else without subsequent if. Zap the condition
8868 chain; we would have already warned at this point. */
8869 vec_free (v&: chain);
8870 }
8871 second_body = c_parser_else_body (parser, else_tinfo, chain);
8872 /* Set IF_P to true to indicate that this if statement has an
8873 else clause. This may trigger the Wparentheses warning
8874 below when we get back up to the parent if statement. */
8875 if (if_p != NULL)
8876 *if_p = true;
8877 }
8878 else
8879 {
8880 second_body = NULL_TREE;
8881
8882 /* Diagnose an ambiguous else if if-then-else is nested inside
8883 if-then. */
8884 if (nested_if)
8885 warning_at (loc, OPT_Wdangling_else,
8886 "suggest explicit braces to avoid ambiguous %<else%>");
8887
8888 if (warn_duplicated_cond)
8889 /* This if statement does not have an else clause. We don't
8890 need the condition chain anymore. */
8891 vec_free (v&: chain);
8892 }
8893 c_finish_if_stmt (loc, cond, first_body, second_body);
8894 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8895
8896 c_parser_maybe_reclassify_token (parser);
8897}
8898
8899/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8900
8901 switch-statement:
8902 switch (expression) statement
8903
8904 BEFORE_LABELS is last statement before possible labels, see
8905 get_before_labels description for details. */
8906
8907static void
8908c_parser_switch_statement (c_parser *parser, bool *if_p, tree before_labels)
8909{
8910 struct c_expr ce;
8911 tree block, expr, body;
8912 unsigned char save_in_statement;
8913 location_t switch_loc = c_parser_peek_token (parser)->location;
8914 location_t switch_cond_loc;
8915 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8916 c_parser_consume_token (parser);
8917 tree switch_name;
8918 int num_names = c_get_loop_names (before_labels, true, &switch_name);
8919 block = c_begin_compound_stmt (flag_isoc99);
8920 bool explicit_cast_p = false;
8921 matching_parens parens;
8922 if (parens.require_open (parser))
8923 {
8924 switch_cond_loc = c_parser_peek_token (parser)->location;
8925 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
8926 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
8927 explicit_cast_p = true;
8928 ce = c_parser_selection_header (parser, /*switch_p=*/true);
8929 /* The call above already performed convert_lvalue_to_rvalue, but
8930 if it parsed an expression, read_p was false. Make sure we mark
8931 the expression as read. */
8932 ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8933 expr = ce.value;
8934 /* ??? expr has no valid location? */
8935 parens.skip_until_found_close (parser);
8936 }
8937 else
8938 {
8939 switch_cond_loc = UNKNOWN_LOCATION;
8940 expr = error_mark_node;
8941 ce.original_type = error_mark_node;
8942 }
8943 tree stmt
8944 = c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p,
8945 switch_name);
8946 save_in_statement = in_statement;
8947 in_statement |= IN_SWITCH_STMT;
8948 if (switch_name)
8949 {
8950 C_DECL_LOOP_SWITCH_NAME_VALID (switch_name) = 1;
8951 in_statement |= IN_NAMED_STMT;
8952 }
8953 else
8954 in_statement &= ~IN_NAMED_STMT;
8955 location_t loc_after_labels;
8956 bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8957 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8958 location_t next_loc = c_parser_peek_token (parser)->location;
8959 if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8960 warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8961 RID_SWITCH);
8962 c_finish_switch (body, ce.original_type);
8963 in_statement = save_in_statement;
8964 if (num_names)
8965 {
8966 if (!C_DECL_LOOP_SWITCH_NAME_USED (switch_name))
8967 SWITCH_STMT_NAME (stmt) = NULL_TREE;
8968 else
8969 SWITCH_STMT_NO_BREAK_P (stmt) = 0;
8970 c_release_loop_names (num_names);
8971 }
8972 add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8973 c_parser_maybe_reclassify_token (parser);
8974}
8975
8976/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8977
8978 while-statement:
8979 while (expression) statement
8980
8981 IF_P is used to track whether there's a (possibly labeled) if statement
8982 which is not enclosed in braces and has an else clause. This is used to
8983 implement -Wparentheses.
8984
8985 BEFORE_LABELS is last statement before possible labels, see
8986 get_before_labels description for details. */
8987
8988static void
8989c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8990 bool novector, bool *if_p, tree before_labels)
8991{
8992 tree block, cond, body;
8993 unsigned char save_in_statement;
8994 location_t loc;
8995 gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8996 token_indent_info while_tinfo
8997 = get_token_indent_info (token: c_parser_peek_token (parser));
8998 tree loop_name;
8999 int num_names = c_get_loop_names (before_labels, false, &loop_name);
9000
9001 if (parser->omp_for_parse_state)
9002 {
9003 error_at (c_parser_peek_token (parser)->location,
9004 "loop not permitted in intervening code in OpenMP loop body");
9005 parser->omp_for_parse_state->fail = true;
9006 }
9007
9008 c_parser_consume_token (parser);
9009 block = c_begin_compound_stmt (flag_isoc99);
9010 loc = c_parser_peek_token (parser)->location;
9011 cond = c_parser_paren_condition (parser);
9012 if (ivdep && cond != error_mark_node)
9013 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9014 build_int_cst (integer_type_node,
9015 annot_expr_ivdep_kind),
9016 integer_zero_node);
9017 if (unroll && cond != error_mark_node)
9018 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9019 build_int_cst (integer_type_node,
9020 annot_expr_unroll_kind),
9021 build_int_cst (integer_type_node, unroll));
9022 if (novector && cond != error_mark_node)
9023 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9024 build_int_cst (integer_type_node,
9025 annot_expr_no_vector_kind),
9026 integer_zero_node);
9027 save_in_statement = in_statement;
9028 in_statement = IN_ITERATION_STMT;
9029 if (loop_name)
9030 {
9031 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9032 in_statement |= IN_NAMED_STMT;
9033 }
9034
9035 token_indent_info body_tinfo
9036 = get_token_indent_info (token: c_parser_peek_token (parser));
9037
9038 location_t loc_after_labels;
9039 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
9040 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
9041 if (loop_name && !C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
9042 loop_name = NULL_TREE;
9043 add_stmt (build_stmt (loc, WHILE_STMT, cond, body, loop_name, NULL_TREE,
9044 NULL_TREE));
9045 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
9046 c_parser_maybe_reclassify_token (parser);
9047 if (num_names)
9048 c_release_loop_names (num_names);
9049
9050 token_indent_info next_tinfo
9051 = get_token_indent_info (token: c_parser_peek_token (parser));
9052 warn_for_misleading_indentation (guard_tinfo: while_tinfo, body_tinfo, next_tinfo);
9053
9054 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9055 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9056 while_tinfo.location, RID_WHILE);
9057
9058 in_statement = save_in_statement;
9059}
9060
9061/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
9062
9063 do-statement:
9064 do statement while ( expression ) ;
9065
9066 BEFORE_LABELS is last statement before possible labels, see
9067 get_before_labels description for details. */
9068
9069static void
9070c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9071 bool novector, tree before_labels)
9072{
9073 tree block, cond, body;
9074 unsigned char save_in_statement;
9075 location_t loc;
9076 gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
9077 tree loop_name;
9078 int num_names = c_get_loop_names (before_labels, false, &loop_name);
9079
9080 if (parser->omp_for_parse_state)
9081 {
9082 error_at (c_parser_peek_token (parser)->location,
9083 "loop not permitted in intervening code in OpenMP loop body");
9084 parser->omp_for_parse_state->fail = true;
9085 }
9086
9087 c_parser_consume_token (parser);
9088 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
9089 warning_at (c_parser_peek_token (parser)->location,
9090 OPT_Wempty_body,
9091 "suggest braces around empty body in %<do%> statement");
9092 block = c_begin_compound_stmt (flag_isoc99);
9093 loc = c_parser_peek_token (parser)->location;
9094 save_in_statement = in_statement;
9095 in_statement = IN_ITERATION_STMT;
9096 if (loop_name)
9097 {
9098 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9099 in_statement |= IN_NAMED_STMT;
9100 }
9101 body = c_parser_c99_block_statement (parser, NULL);
9102 c_parser_require_keyword (parser, keyword: RID_WHILE, msgid: "expected %<while%>");
9103 in_statement = save_in_statement;
9104 if (num_names)
9105 {
9106 if (!C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
9107 loop_name = NULL_TREE;
9108 c_release_loop_names (num_names);
9109 }
9110 cond = c_parser_paren_condition (parser);
9111 if (ivdep && cond != error_mark_node)
9112 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9113 build_int_cst (integer_type_node,
9114 annot_expr_ivdep_kind),
9115 integer_zero_node);
9116 if (unroll && cond != error_mark_node)
9117 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9118 build_int_cst (integer_type_node,
9119 annot_expr_unroll_kind),
9120 build_int_cst (integer_type_node, unroll));
9121 if (novector && cond != error_mark_node)
9122 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9123 build_int_cst (integer_type_node,
9124 annot_expr_no_vector_kind),
9125 integer_zero_node);
9126 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
9127 c_parser_skip_to_end_of_block_or_statement (parser);
9128
9129 add_stmt (build_stmt (loc, DO_STMT, cond, body, loop_name));
9130 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
9131}
9132
9133/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
9134
9135 for-statement:
9136 for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
9137 for ( nested-declaration expression[opt] ; expression[opt] ) statement
9138
9139 The form with a declaration is new in C99.
9140
9141 ??? In accordance with the old parser, the declaration may be a
9142 nested function, which is then rejected in check_for_loop_decls,
9143 but does it make any sense for this to be included in the grammar?
9144 Note in particular that the nested function does not include a
9145 trailing ';', whereas the "declaration" production includes one.
9146 Also, can we reject bad declarations earlier and cheaper than
9147 check_for_loop_decls?
9148
9149 In Objective-C, there are two additional variants:
9150
9151 foreach-statement:
9152 for ( expression in expresssion ) statement
9153 for ( declaration in expression ) statement
9154
9155 This is inconsistent with C, because the second variant is allowed
9156 even if c99 is not enabled.
9157
9158 The rest of the comment documents these Objective-C foreach-statement.
9159
9160 Here is the canonical example of the first variant:
9161 for (object in array) { do something with object }
9162 we call the first expression ("object") the "object_expression" and
9163 the second expression ("array") the "collection_expression".
9164 object_expression must be an lvalue of type "id" (a generic Objective-C
9165 object) because the loop works by assigning to object_expression the
9166 various objects from the collection_expression. collection_expression
9167 must evaluate to something of type "id" which responds to the method
9168 countByEnumeratingWithState:objects:count:.
9169
9170 The canonical example of the second variant is:
9171 for (id object in array) { do something with object }
9172 which is completely equivalent to
9173 {
9174 id object;
9175 for (object in array) { do something with object }
9176 }
9177 Note that initizializing 'object' in some way (eg, "for ((object =
9178 xxx) in array) { do something with object }") is possibly
9179 technically valid, but completely pointless as 'object' will be
9180 assigned to something else as soon as the loop starts. We should
9181 most likely reject it (TODO).
9182
9183 The beginning of the Objective-C foreach-statement looks exactly
9184 like the beginning of the for-statement, and we can tell it is a
9185 foreach-statement only because the initial declaration or
9186 expression is terminated by 'in' instead of ';'.
9187
9188 IF_P is used to track whether there's a (possibly labeled) if statement
9189 which is not enclosed in braces and has an else clause. This is used to
9190 implement -Wparentheses.
9191
9192 BEFORE_LABELS is last statement before possible labels, see
9193 get_before_labels description for details. */
9194
9195static void
9196c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9197 bool novector, bool *if_p, tree before_labels)
9198{
9199 tree block, cond, incr, body;
9200 unsigned char save_in_statement;
9201 tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
9202 /* The following are only used when parsing an ObjC foreach statement. */
9203 tree object_expression;
9204 /* Silence the bogus uninitialized warning. */
9205 tree collection_expression = NULL;
9206 location_t loc = c_parser_peek_token (parser)->location;
9207 location_t for_loc = loc;
9208 bool is_foreach_statement = false;
9209 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
9210 token_indent_info for_tinfo
9211 = get_token_indent_info (token: c_parser_peek_token (parser));
9212 tree loop_name;
9213 int num_names = c_get_loop_names (before_labels, false, &loop_name);
9214
9215 if (parser->omp_for_parse_state)
9216 {
9217 error_at (for_loc,
9218 "loop not permitted in intervening code in OpenMP loop body");
9219 parser->omp_for_parse_state->fail = true;
9220 }
9221
9222 c_parser_consume_token (parser);
9223 /* Open a compound statement in Objective-C as well, just in case this is
9224 as foreach expression. */
9225 block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
9226 cond = error_mark_node;
9227 incr = error_mark_node;
9228 matching_parens parens;
9229 if (parens.require_open (parser))
9230 {
9231 /* Parse the initialization declaration or expression. */
9232 object_expression = error_mark_node;
9233 parser->objc_could_be_foreach_context = c_dialect_objc ();
9234 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
9235 {
9236 parser->objc_could_be_foreach_context = false;
9237 c_parser_consume_token (parser);
9238 c_finish_expr_stmt (loc, NULL_TREE);
9239 }
9240 else if (c_parser_next_tokens_start_declaration (parser)
9241 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
9242 {
9243 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
9244 simple_ok: false, objc_foreach_object_declaration: &object_expression);
9245 parser->objc_could_be_foreach_context = false;
9246
9247 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9248 {
9249 c_parser_consume_token (parser);
9250 is_foreach_statement = true;
9251 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9252 c_parser_error (parser, gmsgid: "multiple iterating variables in "
9253 "fast enumeration");
9254 }
9255 else
9256 check_for_loop_decls (for_loc, flag_isoc99);
9257 }
9258 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
9259 {
9260 /* __extension__ can start a declaration, but is also an
9261 unary operator that can start an expression. Consume all
9262 but the last of a possible series of __extension__ to
9263 determine which. */
9264 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
9265 && (c_parser_peek_2nd_token (parser)->keyword
9266 == RID_EXTENSION))
9267 c_parser_consume_token (parser);
9268 if (c_parser_next_tokens_start_declaration (parser, n: 2)
9269 || c_parser_nth_token_starts_std_attributes (parser, n: 2))
9270 {
9271 int ext;
9272 ext = disable_extension_diagnostics ();
9273 c_parser_consume_token (parser);
9274 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
9275 start_attr_ok: true, simple_ok: false, objc_foreach_object_declaration: &object_expression);
9276 parser->objc_could_be_foreach_context = false;
9277
9278 restore_extension_diagnostics (flags: ext);
9279 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9280 {
9281 c_parser_consume_token (parser);
9282 is_foreach_statement = true;
9283 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9284 c_parser_error (parser, gmsgid: "multiple iterating variables in "
9285 "fast enumeration");
9286 }
9287 else
9288 check_for_loop_decls (for_loc, flag_isoc99);
9289 }
9290 else
9291 goto init_expr;
9292 }
9293 else
9294 {
9295 init_expr:
9296 {
9297 struct c_expr ce;
9298 tree init_expression;
9299 ce = c_parser_expression (parser);
9300 init_expression = ce.value;
9301 parser->objc_could_be_foreach_context = false;
9302 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9303 {
9304 c_parser_consume_token (parser);
9305 is_foreach_statement = true;
9306 if (! lvalue_p (init_expression))
9307 c_parser_error (parser, gmsgid: "invalid iterating variable in "
9308 "fast enumeration");
9309 object_expression
9310 = c_fully_fold (init_expression, false, NULL);
9311 }
9312 else
9313 {
9314 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9315 init_expression = ce.value;
9316 c_finish_expr_stmt (loc, init_expression);
9317 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
9318 msgid: "expected %<;%>");
9319 }
9320 }
9321 }
9322 /* Parse the loop condition. In the case of a foreach
9323 statement, there is no loop condition. */
9324 gcc_assert (!parser->objc_could_be_foreach_context);
9325 if (!is_foreach_statement)
9326 {
9327 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
9328 {
9329 if (ivdep)
9330 {
9331 c_parser_error (parser, gmsgid: "missing loop condition in loop "
9332 "with %<GCC ivdep%> pragma");
9333 cond = error_mark_node;
9334 }
9335 else if (unroll)
9336 {
9337 c_parser_error (parser, gmsgid: "missing loop condition in loop "
9338 "with %<GCC unroll%> pragma");
9339 cond = error_mark_node;
9340 }
9341 else
9342 {
9343 c_parser_consume_token (parser);
9344 cond = NULL_TREE;
9345 }
9346 }
9347 else
9348 {
9349 cond = c_parser_condition (parser);
9350 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
9351 msgid: "expected %<;%>");
9352 }
9353 if (ivdep && cond != error_mark_node)
9354 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9355 build_int_cst (integer_type_node,
9356 annot_expr_ivdep_kind),
9357 integer_zero_node);
9358 if (unroll && cond != error_mark_node)
9359 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9360 build_int_cst (integer_type_node,
9361 annot_expr_unroll_kind),
9362 build_int_cst (integer_type_node, unroll));
9363 if (novector && cond && cond != error_mark_node)
9364 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9365 build_int_cst (integer_type_node,
9366 annot_expr_no_vector_kind),
9367 integer_zero_node);
9368 }
9369 /* Parse the increment expression (the third expression in a
9370 for-statement). In the case of a foreach-statement, this is
9371 the expression that follows the 'in'. */
9372 loc = c_parser_peek_token (parser)->location;
9373 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
9374 {
9375 if (is_foreach_statement)
9376 {
9377 c_parser_error (parser,
9378 gmsgid: "missing collection in fast enumeration");
9379 collection_expression = error_mark_node;
9380 }
9381 else
9382 incr = c_process_expr_stmt (loc, NULL_TREE);
9383 }
9384 else
9385 {
9386 if (is_foreach_statement)
9387 collection_expression
9388 = c_fully_fold (c_parser_expression (parser).value, false, NULL);
9389 else
9390 {
9391 struct c_expr ce = c_parser_expression (parser);
9392 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9393 incr = c_process_expr_stmt (loc, ce.value);
9394 }
9395 }
9396 parens.skip_until_found_close (parser);
9397 }
9398 save_in_statement = in_statement;
9399 if (is_foreach_statement)
9400 {
9401 in_statement = IN_OBJC_FOREACH;
9402 save_objc_foreach_break_label = objc_foreach_break_label;
9403 save_objc_foreach_continue_label = objc_foreach_continue_label;
9404 objc_foreach_break_label = create_artificial_label (loc);
9405 objc_foreach_continue_label = create_artificial_label (loc);
9406 if (loop_name)
9407 {
9408 gcc_checking_assert (!DECL_CHAIN (loop_name)
9409 && !DECL_CHAIN (objc_foreach_break_label));
9410 C_DECL_SWITCH_NAME (loop_name) = 1;
9411 DECL_CHAIN (loop_name) = objc_foreach_break_label;
9412 DECL_CHAIN (objc_foreach_break_label) = objc_foreach_continue_label;
9413 }
9414 }
9415 else
9416 in_statement = IN_ITERATION_STMT;
9417 if (loop_name)
9418 {
9419 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9420 in_statement |= IN_NAMED_STMT;
9421 }
9422
9423 token_indent_info body_tinfo
9424 = get_token_indent_info (token: c_parser_peek_token (parser));
9425
9426 location_t loc_after_labels;
9427 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
9428 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
9429
9430 if (loop_name && is_foreach_statement)
9431 {
9432 gcc_checking_assert (DECL_CHAIN (loop_name) == objc_foreach_break_label
9433 && (DECL_CHAIN (objc_foreach_break_label)
9434 == objc_foreach_continue_label));
9435 C_DECL_SWITCH_NAME (loop_name) = 0;
9436 DECL_CHAIN (loop_name) = NULL_TREE;
9437 DECL_CHAIN (objc_foreach_break_label) = NULL_TREE;
9438 }
9439
9440 if (is_foreach_statement)
9441 objc_finish_foreach_loop (for_loc, object_expression,
9442 collection_expression, body,
9443 objc_foreach_break_label,
9444 objc_foreach_continue_label);
9445 else
9446 add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
9447 body, NULL_TREE,
9448 loop_name && C_DECL_LOOP_SWITCH_NAME_USED (loop_name)
9449 ? loop_name : NULL_TREE, NULL_TREE, NULL_TREE));
9450 add_stmt (c_end_compound_stmt (for_loc, block,
9451 flag_isoc99 || c_dialect_objc ()));
9452 c_parser_maybe_reclassify_token (parser);
9453
9454 token_indent_info next_tinfo
9455 = get_token_indent_info (token: c_parser_peek_token (parser));
9456 warn_for_misleading_indentation (guard_tinfo: for_tinfo, body_tinfo, next_tinfo);
9457
9458 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9459 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9460 for_tinfo.location, RID_FOR);
9461
9462 in_statement = save_in_statement;
9463 if (num_names)
9464 c_release_loop_names (num_names);
9465 if (is_foreach_statement)
9466 {
9467 objc_foreach_break_label = save_objc_foreach_break_label;
9468 objc_foreach_continue_label = save_objc_foreach_continue_label;
9469 }
9470}
9471
9472/* Parse an asm statement, a GNU extension. This is a full-blown asm
9473 statement with inputs, outputs, clobbers, and volatile, inline, and goto
9474 tags allowed.
9475
9476 asm-qualifier:
9477 volatile
9478 inline
9479 goto
9480
9481 asm-qualifier-list:
9482 asm-qualifier-list asm-qualifier
9483 asm-qualifier
9484
9485 asm-statement:
9486 asm asm-qualifier-list[opt] ( asm-argument ) ;
9487
9488 asm-argument:
9489 asm-string-literal
9490 asm-string-literal : asm-operands[opt]
9491 asm-string-literal : asm-operands[opt] : asm-operands[opt]
9492 asm-string-literal : asm-operands[opt] : asm-operands[opt] \
9493 : asm-clobbers[opt]
9494 asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
9495 : asm-goto-operands
9496
9497 The form with asm-goto-operands is valid if and only if the
9498 asm-qualifier-list contains goto, and is the only allowed form in that case.
9499 Duplicate asm-qualifiers are not allowed.
9500
9501 The :: token is considered equivalent to two consecutive : tokens. */
9502
9503static tree
9504c_parser_asm_statement (c_parser *parser)
9505{
9506 tree str, outputs, inputs, clobbers, labels, ret;
9507 bool simple;
9508 location_t asm_loc = c_parser_peek_token (parser)->location;
9509 int section, nsections;
9510
9511 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
9512 c_parser_consume_token (parser);
9513
9514 /* Handle the asm-qualifier-list. */
9515 location_t volatile_loc = UNKNOWN_LOCATION;
9516 location_t inline_loc = UNKNOWN_LOCATION;
9517 location_t goto_loc = UNKNOWN_LOCATION;
9518 for (;;)
9519 {
9520 c_token *token = c_parser_peek_token (parser);
9521 location_t loc = token->location;
9522 switch (token->keyword)
9523 {
9524 case RID_VOLATILE:
9525 if (volatile_loc)
9526 {
9527 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9528 inform (volatile_loc, "first seen here");
9529 }
9530 else
9531 volatile_loc = loc;
9532 c_parser_consume_token (parser);
9533 continue;
9534
9535 case RID_INLINE:
9536 if (inline_loc)
9537 {
9538 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9539 inform (inline_loc, "first seen here");
9540 }
9541 else
9542 inline_loc = loc;
9543 c_parser_consume_token (parser);
9544 continue;
9545
9546 case RID_GOTO:
9547 if (goto_loc)
9548 {
9549 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9550 inform (goto_loc, "first seen here");
9551 }
9552 else
9553 goto_loc = loc;
9554 c_parser_consume_token (parser);
9555 continue;
9556
9557 case RID_CONST:
9558 case RID_RESTRICT:
9559 error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
9560 c_parser_consume_token (parser);
9561 continue;
9562
9563 default:
9564 break;
9565 }
9566 break;
9567 }
9568
9569 bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
9570 bool is_inline = (inline_loc != UNKNOWN_LOCATION);
9571 bool is_goto = (goto_loc != UNKNOWN_LOCATION);
9572
9573 ret = NULL;
9574
9575 matching_parens parens;
9576 if (!parens.require_open (parser))
9577 goto error;
9578
9579 str = c_parser_asm_string_literal (parser);
9580 if (str == NULL_TREE)
9581 goto error_close_paren;
9582
9583 simple = true;
9584 outputs = NULL_TREE;
9585 inputs = NULL_TREE;
9586 clobbers = NULL_TREE;
9587 labels = NULL_TREE;
9588
9589 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
9590 goto done_asm;
9591
9592 /* Parse each colon-delimited section of operands. */
9593 nsections = 3 + is_goto;
9594 for (section = 0; section < nsections; ++section)
9595 {
9596 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
9597 {
9598 ++section;
9599 if (section == nsections)
9600 {
9601 c_parser_error (parser, gmsgid: "expected %<)%>");
9602 goto error_close_paren;
9603 }
9604 c_parser_consume_token (parser);
9605 }
9606 else if (!c_parser_require (parser, type: CPP_COLON,
9607 msgid: is_goto
9608 ? G_("expected %<:%>")
9609 : G_("expected %<:%> or %<)%>"),
9610 UNKNOWN_LOCATION, type_is_unique: is_goto))
9611 goto error_close_paren;
9612
9613 /* Once past any colon, we're no longer a simple asm. */
9614 simple = false;
9615
9616 if ((!c_parser_next_token_is (parser, type: CPP_COLON)
9617 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
9618 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
9619 || section == 3)
9620 switch (section)
9621 {
9622 case 0:
9623 outputs = c_parser_asm_operands (parser);
9624 break;
9625 case 1:
9626 inputs = c_parser_asm_operands (parser);
9627 break;
9628 case 2:
9629 clobbers = c_parser_asm_clobbers (parser);
9630 break;
9631 case 3:
9632 labels = c_parser_asm_goto_operands (parser);
9633 break;
9634 default:
9635 gcc_unreachable ();
9636 }
9637
9638 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
9639 goto done_asm;
9640 }
9641
9642 done_asm:
9643 if (!parens.require_close (parser))
9644 {
9645 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9646 goto error;
9647 }
9648
9649 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
9650 c_parser_skip_to_end_of_block_or_statement (parser);
9651
9652 ret = build_asm_stmt (is_volatile,
9653 build_asm_expr (asm_loc, str, outputs, inputs,
9654 clobbers, labels, simple, is_inline));
9655
9656 error:
9657 return ret;
9658
9659 error_close_paren:
9660 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9661 goto error;
9662}
9663
9664/* Parse asm operands, a GNU extension.
9665
9666 asm-operands:
9667 asm-operand
9668 asm-operands , asm-operand
9669
9670 asm-operand:
9671 asm-string-literal ( expression )
9672 [ identifier ] asm-string-literal ( expression )
9673*/
9674
9675static tree
9676c_parser_asm_operands (c_parser *parser)
9677{
9678 tree list = NULL_TREE;
9679 while (true)
9680 {
9681 tree name, str;
9682 struct c_expr expr;
9683 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
9684 {
9685 c_parser_consume_token (parser);
9686 if (c_parser_next_token_is (parser, type: CPP_NAME))
9687 {
9688 tree id = c_parser_peek_token (parser)->value;
9689 c_parser_consume_token (parser);
9690 name = build_string (IDENTIFIER_LENGTH (id),
9691 IDENTIFIER_POINTER (id));
9692 }
9693 else
9694 {
9695 c_parser_error (parser, gmsgid: "expected identifier");
9696 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, NULL);
9697 return NULL_TREE;
9698 }
9699 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
9700 msgid: "expected %<]%>");
9701 }
9702 else
9703 name = NULL_TREE;
9704 str = c_parser_asm_string_literal (parser);
9705 if (str == NULL_TREE)
9706 return NULL_TREE;
9707 matching_parens parens;
9708 if (!parens.require_open (parser))
9709 return NULL_TREE;
9710 expr = c_parser_expression (parser);
9711 mark_exp_read (expr.value);
9712 if (!parens.require_close (parser))
9713 {
9714 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9715 return NULL_TREE;
9716 }
9717 list = chainon (list, build_tree_list (build_tree_list (name, str),
9718 expr.value));
9719 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9720 c_parser_consume_token (parser);
9721 else
9722 break;
9723 }
9724 return list;
9725}
9726
9727/* Parse asm clobbers, a GNU extension.
9728
9729 asm-clobbers:
9730 asm-string-literal
9731 asm-clobbers , asm-string-literal
9732*/
9733
9734static tree
9735c_parser_asm_clobbers (c_parser *parser)
9736{
9737 tree list = NULL_TREE;
9738 while (true)
9739 {
9740 tree str = c_parser_asm_string_literal (parser);
9741 if (str)
9742 list = tree_cons (NULL_TREE, str, list);
9743 else
9744 return NULL_TREE;
9745 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9746 c_parser_consume_token (parser);
9747 else
9748 break;
9749 }
9750 return list;
9751}
9752
9753/* Parse asm goto labels, a GNU extension.
9754
9755 asm-goto-operands:
9756 identifier
9757 asm-goto-operands , identifier
9758*/
9759
9760static tree
9761c_parser_asm_goto_operands (c_parser *parser)
9762{
9763 tree list = NULL_TREE;
9764 while (true)
9765 {
9766 tree name, label;
9767
9768 if (c_parser_next_token_is (parser, type: CPP_NAME))
9769 {
9770 c_token *tok = c_parser_peek_token (parser);
9771 name = tok->value;
9772 label = lookup_label_for_goto (tok->location, name);
9773 c_parser_consume_token (parser);
9774 TREE_USED (label) = 1;
9775 }
9776 else
9777 {
9778 c_parser_error (parser, gmsgid: "expected identifier");
9779 return NULL_TREE;
9780 }
9781
9782 name = build_string (IDENTIFIER_LENGTH (name),
9783 IDENTIFIER_POINTER (name));
9784 list = tree_cons (name, label, list);
9785 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9786 c_parser_consume_token (parser);
9787 else
9788 return nreverse (list);
9789 }
9790}
9791
9792/* Parse a possibly concatenated sequence of string literals.
9793 TRANSLATE says whether to translate them to the execution character
9794 set; WIDE_OK says whether any kind of prefixed string literal is
9795 permitted in this context. This code is based on that in
9796 lex_string. */
9797
9798struct c_expr
9799c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
9800{
9801 struct c_expr ret;
9802 size_t count;
9803 struct obstack str_ob;
9804 struct obstack loc_ob;
9805 cpp_string str, istr, *strs;
9806 c_token *tok;
9807 location_t loc, last_tok_loc;
9808 enum cpp_ttype type;
9809 tree value, string_tree;
9810
9811 tok = c_parser_peek_token (parser);
9812 loc = tok->location;
9813 last_tok_loc = linemap_resolve_location (line_table, loc,
9814 lrk: LRK_MACRO_DEFINITION_LOCATION,
9815 NULL);
9816 type = tok->type;
9817 switch (type)
9818 {
9819 case CPP_STRING:
9820 case CPP_WSTRING:
9821 case CPP_STRING16:
9822 case CPP_STRING32:
9823 case CPP_UTF8STRING:
9824 string_tree = tok->value;
9825 break;
9826
9827 default:
9828 c_parser_error (parser, gmsgid: "expected string literal");
9829 ret.set_error ();
9830 ret.value = NULL_TREE;
9831 ret.original_code = ERROR_MARK;
9832 ret.original_type = NULL_TREE;
9833 return ret;
9834 }
9835
9836 /* Try to avoid the overhead of creating and destroying an obstack
9837 for the common case of just one string. */
9838 switch (c_parser_peek_2nd_token (parser)->type)
9839 {
9840 default:
9841 c_parser_consume_token (parser);
9842 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9843 str.len = TREE_STRING_LENGTH (string_tree);
9844 count = 1;
9845 strs = &str;
9846 break;
9847
9848 case CPP_STRING:
9849 case CPP_WSTRING:
9850 case CPP_STRING16:
9851 case CPP_STRING32:
9852 case CPP_UTF8STRING:
9853 gcc_obstack_init (&str_ob);
9854 gcc_obstack_init (&loc_ob);
9855 count = 0;
9856 do
9857 {
9858 c_parser_consume_token (parser);
9859 count++;
9860 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9861 str.len = TREE_STRING_LENGTH (string_tree);
9862 if (type != tok->type)
9863 {
9864 if (type == CPP_STRING)
9865 type = tok->type;
9866 else if (tok->type != CPP_STRING)
9867 error ("unsupported non-standard concatenation "
9868 "of string literals");
9869 }
9870 obstack_grow (&str_ob, &str, sizeof (cpp_string));
9871 obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
9872 tok = c_parser_peek_token (parser);
9873 string_tree = tok->value;
9874 last_tok_loc
9875 = linemap_resolve_location (line_table, loc: tok->location,
9876 lrk: LRK_MACRO_DEFINITION_LOCATION, NULL);
9877 }
9878 while (tok->type == CPP_STRING
9879 || tok->type == CPP_WSTRING
9880 || tok->type == CPP_STRING16
9881 || tok->type == CPP_STRING32
9882 || tok->type == CPP_UTF8STRING);
9883 strs = (cpp_string *) obstack_finish (&str_ob);
9884 }
9885
9886 if (count > 1 && !in_system_header_at (loc: input_location))
9887 warning (OPT_Wtraditional,
9888 "traditional C rejects string constant concatenation");
9889
9890 if ((type == CPP_STRING || wide_ok)
9891 && ((translate
9892 ? cpp_interpret_string : cpp_interpret_string_notranslate)
9893 (parse_in, strs, count, &istr, type)))
9894 {
9895 value = build_string (istr.len, (const char *) istr.text);
9896 free (ptr: const_cast<unsigned char *> (istr.text));
9897 if (count > 1)
9898 {
9899 location_t *locs = (location_t *) obstack_finish (&loc_ob);
9900 gcc_assert (g_string_concat_db);
9901 g_string_concat_db->record_string_concatenation (num: count, locs);
9902 }
9903 }
9904 else
9905 {
9906 if (type != CPP_STRING && !wide_ok)
9907 {
9908 error_at (loc, "a wide string is invalid in this context");
9909 type = CPP_STRING;
9910 }
9911 /* Callers cannot generally handle error_mark_node in this
9912 context, so return the empty string instead. An error has
9913 been issued, either above or from cpp_interpret_string. */
9914 switch (type)
9915 {
9916 default:
9917 case CPP_STRING:
9918 case CPP_UTF8STRING:
9919 if (type == CPP_UTF8STRING && flag_char8_t)
9920 {
9921 value = build_string (TYPE_PRECISION (char8_type_node)
9922 / TYPE_PRECISION (char_type_node),
9923 ""); /* char8_t is 8 bits */
9924 }
9925 else
9926 value = build_string (1, "");
9927 break;
9928 case CPP_STRING16:
9929 value = build_string (TYPE_PRECISION (char16_type_node)
9930 / TYPE_PRECISION (char_type_node),
9931 "\0"); /* char16_t is 16 bits */
9932 break;
9933 case CPP_STRING32:
9934 value = build_string (TYPE_PRECISION (char32_type_node)
9935 / TYPE_PRECISION (char_type_node),
9936 "\0\0\0"); /* char32_t is 32 bits */
9937 break;
9938 case CPP_WSTRING:
9939 value = build_string (TYPE_PRECISION (wchar_type_node)
9940 / TYPE_PRECISION (char_type_node),
9941 "\0\0\0"); /* widest supported wchar_t
9942 is 32 bits */
9943 break;
9944 }
9945 }
9946
9947 switch (type)
9948 {
9949 default:
9950 case CPP_STRING:
9951 TREE_TYPE (value) = char_array_type_node;
9952 break;
9953 case CPP_UTF8STRING:
9954 if (flag_char8_t)
9955 TREE_TYPE (value) = char8_array_type_node;
9956 else
9957 TREE_TYPE (value) = char_array_type_node;
9958 break;
9959 case CPP_STRING16:
9960 TREE_TYPE (value) = char16_array_type_node;
9961 break;
9962 case CPP_STRING32:
9963 TREE_TYPE (value) = char32_array_type_node;
9964 break;
9965 case CPP_WSTRING:
9966 TREE_TYPE (value) = wchar_array_type_node;
9967 }
9968 value = fix_string_type (value);
9969
9970 if (count > 1)
9971 {
9972 obstack_free (&str_ob, 0);
9973 obstack_free (&loc_ob, 0);
9974 }
9975
9976 ret.value = value;
9977 ret.original_code = STRING_CST;
9978 ret.original_type = NULL_TREE;
9979 set_c_expr_source_range (expr: &ret, src_range: get_range_from_loc (set: line_table, loc));
9980 ret.m_decimal = 0;
9981 parser->seen_string_literal = true;
9982 return ret;
9983}
9984
9985/* Parse an expression other than a compound expression; that is, an
9986 assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9987 AFTER is not NULL then it is an Objective-C message expression which
9988 is the primary-expression starting the expression as an initializer.
9989
9990 assignment-expression:
9991 conditional-expression
9992 unary-expression assignment-operator assignment-expression
9993
9994 assignment-operator: one of
9995 = *= /= %= += -= <<= >>= &= ^= |=
9996
9997 In GNU C we accept any conditional expression on the LHS and
9998 diagnose the invalid lvalue rather than producing a syntax
9999 error. */
10000
10001static struct c_expr
10002c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
10003 tree omp_atomic_lhs)
10004{
10005 struct c_expr lhs, rhs, ret;
10006 enum tree_code code;
10007 location_t op_location, exp_location;
10008 bool save_in_omp_for = c_in_omp_for;
10009 c_in_omp_for = false;
10010 gcc_assert (!after || c_dialect_objc ());
10011 lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
10012 op_location = c_parser_peek_token (parser)->location;
10013 switch (c_parser_peek_token (parser)->type)
10014 {
10015 case CPP_EQ:
10016 code = NOP_EXPR;
10017 break;
10018 case CPP_MULT_EQ:
10019 code = MULT_EXPR;
10020 break;
10021 case CPP_DIV_EQ:
10022 code = TRUNC_DIV_EXPR;
10023 break;
10024 case CPP_MOD_EQ:
10025 code = TRUNC_MOD_EXPR;
10026 break;
10027 case CPP_PLUS_EQ:
10028 code = PLUS_EXPR;
10029 break;
10030 case CPP_MINUS_EQ:
10031 code = MINUS_EXPR;
10032 break;
10033 case CPP_LSHIFT_EQ:
10034 code = LSHIFT_EXPR;
10035 break;
10036 case CPP_RSHIFT_EQ:
10037 code = RSHIFT_EXPR;
10038 break;
10039 case CPP_AND_EQ:
10040 code = BIT_AND_EXPR;
10041 break;
10042 case CPP_XOR_EQ:
10043 code = BIT_XOR_EXPR;
10044 break;
10045 case CPP_OR_EQ:
10046 code = BIT_IOR_EXPR;
10047 break;
10048 default:
10049 c_in_omp_for = save_in_omp_for;
10050 return lhs;
10051 }
10052 c_parser_consume_token (parser);
10053 exp_location = c_parser_peek_token (parser)->location;
10054 rhs = c_parser_expr_no_commas (parser, NULL);
10055 rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
10056
10057 ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
10058 code, exp_location, rhs.value,
10059 rhs.original_type);
10060 ret.m_decimal = 0;
10061 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
10062 if (code == NOP_EXPR)
10063 ret.original_code = MODIFY_EXPR;
10064 else
10065 {
10066 suppress_warning (ret.value, OPT_Wparentheses);
10067 ret.original_code = ERROR_MARK;
10068 }
10069 ret.original_type = NULL;
10070 c_in_omp_for = save_in_omp_for;
10071 return ret;
10072}
10073
10074/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
10075 AFTER is not NULL then it is an Objective-C message expression which is
10076 the primary-expression starting the expression as an initializer.
10077
10078 conditional-expression:
10079 logical-OR-expression
10080 logical-OR-expression ? expression : conditional-expression
10081
10082 GNU extensions:
10083
10084 conditional-expression:
10085 logical-OR-expression ? : conditional-expression
10086*/
10087
10088static struct c_expr
10089c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
10090 tree omp_atomic_lhs)
10091{
10092 struct c_expr cond, exp1, exp2, ret;
10093 location_t start, cond_loc, colon_loc;
10094 bool save_c_omp_array_section_p = c_omp_array_section_p;
10095
10096 gcc_assert (!after || c_dialect_objc ());
10097
10098 cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
10099
10100 if (c_parser_next_token_is_not (parser, type: CPP_QUERY))
10101 return cond;
10102 c_omp_array_section_p = false;
10103 if (cond.value != error_mark_node)
10104 start = cond.get_start ();
10105 else
10106 start = UNKNOWN_LOCATION;
10107 cond_loc = c_parser_peek_token (parser)->location;
10108 cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
10109 c_parser_consume_token (parser);
10110 if (c_parser_next_token_is (parser, type: CPP_COLON))
10111 {
10112 tree eptype = NULL_TREE;
10113
10114 location_t middle_loc = c_parser_peek_token (parser)->location;
10115 pedwarn (middle_loc, OPT_Wpedantic,
10116 "ISO C forbids omitting the middle term of a %<?:%> expression");
10117 if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
10118 {
10119 eptype = TREE_TYPE (cond.value);
10120 cond.value = TREE_OPERAND (cond.value, 0);
10121 }
10122 tree e = cond.value;
10123 while (TREE_CODE (e) == COMPOUND_EXPR)
10124 e = TREE_OPERAND (e, 1);
10125 warn_for_omitted_condop (middle_loc, e);
10126 /* Make sure first operand is calculated only once. */
10127 exp1.value = save_expr (default_conversion (cond.value));
10128 if (eptype)
10129 exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
10130 exp1.original_type = NULL;
10131 exp1.src_range = cond.src_range;
10132 cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
10133 c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
10134 }
10135 else
10136 {
10137 cond.value
10138 = c_objc_common_truthvalue_conversion
10139 (cond_loc, default_conversion (cond.value));
10140 c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
10141 exp1 = c_parser_expression_conv (parser);
10142 mark_exp_read (exp1.value);
10143 c_inhibit_evaluation_warnings +=
10144 ((cond.value == truthvalue_true_node)
10145 - (cond.value == truthvalue_false_node));
10146 }
10147
10148 colon_loc = c_parser_peek_token (parser)->location;
10149 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
10150 {
10151 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10152 ret.set_error ();
10153 ret.original_code = ERROR_MARK;
10154 ret.original_type = NULL;
10155 c_omp_array_section_p = save_c_omp_array_section_p;
10156 return ret;
10157 }
10158 {
10159 location_t exp2_loc = c_parser_peek_token (parser)->location;
10160 exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
10161 exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
10162 }
10163 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10164 location_t loc1 = make_location (caret: exp1.get_start (), src_range: exp1.src_range);
10165 location_t loc2 = make_location (caret: exp2.get_start (), src_range: exp2.src_range);
10166 if (UNLIKELY (omp_atomic_lhs != NULL)
10167 && (TREE_CODE (cond.value) == GT_EXPR
10168 || TREE_CODE (cond.value) == LT_EXPR
10169 || TREE_CODE (cond.value) == EQ_EXPR)
10170 && c_tree_equal (exp2.value, omp_atomic_lhs)
10171 && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
10172 || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
10173 ret.value = build3_loc (loc: colon_loc, code: COND_EXPR, TREE_TYPE (omp_atomic_lhs),
10174 arg0: cond.value, arg1: exp1.value, arg2: exp2.value);
10175 else
10176 ret.value
10177 = build_conditional_expr (colon_loc, cond.value,
10178 cond.original_code == C_MAYBE_CONST_EXPR,
10179 exp1.value, exp1.original_type, loc1,
10180 exp2.value, exp2.original_type, loc2);
10181 ret.original_code = ERROR_MARK;
10182 if (exp1.value == error_mark_node || exp2.value == error_mark_node)
10183 ret.original_type = NULL;
10184 else
10185 {
10186 tree t1, t2;
10187
10188 /* If both sides are enum type, the default conversion will have
10189 made the type of the result be an integer type. We want to
10190 remember the enum types we started with. */
10191 t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
10192 t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
10193 ret.original_type = ((t1 != error_mark_node
10194 && t2 != error_mark_node
10195 && (TYPE_MAIN_VARIANT (t1)
10196 == TYPE_MAIN_VARIANT (t2)))
10197 ? t1
10198 : NULL);
10199 }
10200 set_c_expr_source_range (expr: &ret, start, finish: exp2.get_finish ());
10201 ret.m_decimal = 0;
10202 c_omp_array_section_p = save_c_omp_array_section_p;
10203 return ret;
10204}
10205
10206/* Parse a binary expression; that is, a logical-OR-expression (C90
10207 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
10208 NULL then it is an Objective-C message expression which is the
10209 primary-expression starting the expression as an initializer.
10210
10211 OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
10212 when it should be the unfolded lhs. In a valid OpenMP source,
10213 one of the operands of the toplevel binary expression must be equal
10214 to it. In that case, just return a build2 created binary operation
10215 rather than result of parser_build_binary_op.
10216
10217 multiplicative-expression:
10218 cast-expression
10219 multiplicative-expression * cast-expression
10220 multiplicative-expression / cast-expression
10221 multiplicative-expression % cast-expression
10222
10223 additive-expression:
10224 multiplicative-expression
10225 additive-expression + multiplicative-expression
10226 additive-expression - multiplicative-expression
10227
10228 shift-expression:
10229 additive-expression
10230 shift-expression << additive-expression
10231 shift-expression >> additive-expression
10232
10233 relational-expression:
10234 shift-expression
10235 relational-expression < shift-expression
10236 relational-expression > shift-expression
10237 relational-expression <= shift-expression
10238 relational-expression >= shift-expression
10239
10240 equality-expression:
10241 relational-expression
10242 equality-expression == relational-expression
10243 equality-expression != relational-expression
10244
10245 AND-expression:
10246 equality-expression
10247 AND-expression & equality-expression
10248
10249 exclusive-OR-expression:
10250 AND-expression
10251 exclusive-OR-expression ^ AND-expression
10252
10253 inclusive-OR-expression:
10254 exclusive-OR-expression
10255 inclusive-OR-expression | exclusive-OR-expression
10256
10257 logical-AND-expression:
10258 inclusive-OR-expression
10259 logical-AND-expression && inclusive-OR-expression
10260
10261 logical-OR-expression:
10262 logical-AND-expression
10263 logical-OR-expression || logical-AND-expression
10264*/
10265
10266static struct c_expr
10267c_parser_binary_expression (c_parser *parser, struct c_expr *after,
10268 tree omp_atomic_lhs)
10269{
10270 /* A binary expression is parsed using operator-precedence parsing,
10271 with the operands being cast expressions. All the binary
10272 operators are left-associative. Thus a binary expression is of
10273 form:
10274
10275 E0 op1 E1 op2 E2 ...
10276
10277 which we represent on a stack. On the stack, the precedence
10278 levels are strictly increasing. When a new operator is
10279 encountered of higher precedence than that at the top of the
10280 stack, it is pushed; its LHS is the top expression, and its RHS
10281 is everything parsed until it is popped. When a new operator is
10282 encountered with precedence less than or equal to that at the top
10283 of the stack, triples E[i-1] op[i] E[i] are popped and replaced
10284 by the result of the operation until the operator at the top of
10285 the stack has lower precedence than the new operator or there is
10286 only one element on the stack; then the top expression is the LHS
10287 of the new operator. In the case of logical AND and OR
10288 expressions, we also need to adjust c_inhibit_evaluation_warnings
10289 as appropriate when the operators are pushed and popped. */
10290
10291 struct {
10292 /* The expression at this stack level. */
10293 struct c_expr expr;
10294 /* The precedence of the operator on its left, PREC_NONE at the
10295 bottom of the stack. */
10296 enum c_parser_prec prec;
10297 /* The operation on its left. */
10298 enum tree_code op;
10299 /* The source location of this operation. */
10300 location_t loc;
10301 /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
10302 tree sizeof_arg;
10303 } stack[NUM_PRECS];
10304 int sp;
10305 /* Location of the binary operator. */
10306 location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
10307#define POP \
10308 do { \
10309 switch (stack[sp].op) \
10310 { \
10311 case TRUTH_ANDIF_EXPR: \
10312 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10313 == truthvalue_false_node); \
10314 break; \
10315 case TRUTH_ORIF_EXPR: \
10316 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10317 == truthvalue_true_node); \
10318 break; \
10319 case TRUNC_DIV_EXPR: \
10320 if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
10321 || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
10322 && (stack[sp].expr.original_code == SIZEOF_EXPR \
10323 || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
10324 { \
10325 tree type0 = stack[sp - 1].sizeof_arg; \
10326 tree type1 = stack[sp].sizeof_arg; \
10327 tree first_arg = type0; \
10328 if (!TYPE_P (type0)) \
10329 type0 = TREE_TYPE (type0); \
10330 if (!TYPE_P (type1)) \
10331 type1 = TREE_TYPE (type1); \
10332 if (POINTER_TYPE_P (type0) \
10333 && comptypes (TREE_TYPE (type0), type1) \
10334 && !(TREE_CODE (first_arg) == PARM_DECL \
10335 && C_ARRAY_PARAMETER (first_arg) \
10336 && warn_sizeof_array_argument)) \
10337 { \
10338 auto_diagnostic_group d; \
10339 if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
10340 "division %<sizeof (%T) / sizeof (%T)%> " \
10341 "does not compute the number of array " \
10342 "elements", \
10343 type0, type1)) \
10344 if (DECL_P (first_arg)) \
10345 inform (DECL_SOURCE_LOCATION (first_arg), \
10346 "first %<sizeof%> operand was declared here"); \
10347 } \
10348 else if (TREE_CODE (type0) == ARRAY_TYPE \
10349 && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
10350 && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
10351 maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
10352 stack[sp].sizeof_arg, type1); \
10353 } \
10354 break; \
10355 default: \
10356 break; \
10357 } \
10358 stack[sp - 1].expr \
10359 = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
10360 stack[sp - 1].expr, true, true); \
10361 stack[sp].expr \
10362 = convert_lvalue_to_rvalue (stack[sp].loc, \
10363 stack[sp].expr, true, true); \
10364 if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
10365 && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
10366 && ((1 << stack[sp].prec) \
10367 & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
10368 | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
10369 | (1 << PREC_ADD) | (1 << PREC_MULT) \
10370 | (1 << PREC_EQ)))) \
10371 || ((c_parser_next_token_is (parser, CPP_QUERY) \
10372 || (omp_atomic_lhs == void_list_node \
10373 && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
10374 && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
10375 && stack[sp].op != TRUNC_MOD_EXPR \
10376 && stack[sp].op != GE_EXPR \
10377 && stack[sp].op != LE_EXPR \
10378 && stack[sp].op != NE_EXPR \
10379 && stack[0].expr.value != error_mark_node \
10380 && stack[1].expr.value != error_mark_node \
10381 && (omp_atomic_lhs == void_list_node \
10382 || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
10383 || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
10384 || (stack[sp].op == EQ_EXPR \
10385 && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
10386 { \
10387 tree t = make_node (stack[1].op); \
10388 TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
10389 TREE_OPERAND (t, 0) = stack[0].expr.value; \
10390 TREE_OPERAND (t, 1) = stack[1].expr.value; \
10391 stack[0].expr.value = t; \
10392 stack[0].expr.m_decimal = 0; \
10393 } \
10394 else \
10395 stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
10396 stack[sp].op, \
10397 stack[sp - 1].expr, \
10398 stack[sp].expr); \
10399 sp--; \
10400 } while (0)
10401 gcc_assert (!after || c_dialect_objc ());
10402 stack[0].loc = c_parser_peek_token (parser)->location;
10403 stack[0].expr = c_parser_cast_expression (parser, after);
10404 stack[0].prec = PREC_NONE;
10405 stack[0].sizeof_arg = c_last_sizeof_arg;
10406 sp = 0;
10407 while (true)
10408 {
10409 enum c_parser_prec oprec;
10410 enum tree_code ocode;
10411 source_range src_range;
10412 if (parser->error)
10413 goto out;
10414 switch (c_parser_peek_token (parser)->type)
10415 {
10416 case CPP_MULT:
10417 oprec = PREC_MULT;
10418 ocode = MULT_EXPR;
10419 break;
10420 case CPP_DIV:
10421 oprec = PREC_MULT;
10422 ocode = TRUNC_DIV_EXPR;
10423 break;
10424 case CPP_MOD:
10425 oprec = PREC_MULT;
10426 ocode = TRUNC_MOD_EXPR;
10427 break;
10428 case CPP_PLUS:
10429 oprec = PREC_ADD;
10430 ocode = PLUS_EXPR;
10431 break;
10432 case CPP_MINUS:
10433 oprec = PREC_ADD;
10434 ocode = MINUS_EXPR;
10435 break;
10436 case CPP_LSHIFT:
10437 oprec = PREC_SHIFT;
10438 ocode = LSHIFT_EXPR;
10439 break;
10440 case CPP_RSHIFT:
10441 oprec = PREC_SHIFT;
10442 ocode = RSHIFT_EXPR;
10443 break;
10444 case CPP_LESS:
10445 oprec = PREC_REL;
10446 ocode = LT_EXPR;
10447 break;
10448 case CPP_GREATER:
10449 oprec = PREC_REL;
10450 ocode = GT_EXPR;
10451 break;
10452 case CPP_LESS_EQ:
10453 oprec = PREC_REL;
10454 ocode = LE_EXPR;
10455 break;
10456 case CPP_GREATER_EQ:
10457 oprec = PREC_REL;
10458 ocode = GE_EXPR;
10459 break;
10460 case CPP_EQ_EQ:
10461 oprec = PREC_EQ;
10462 ocode = EQ_EXPR;
10463 break;
10464 case CPP_NOT_EQ:
10465 oprec = PREC_EQ;
10466 ocode = NE_EXPR;
10467 break;
10468 case CPP_AND:
10469 oprec = PREC_BITAND;
10470 ocode = BIT_AND_EXPR;
10471 break;
10472 case CPP_XOR:
10473 oprec = PREC_BITXOR;
10474 ocode = BIT_XOR_EXPR;
10475 break;
10476 case CPP_OR:
10477 oprec = PREC_BITOR;
10478 ocode = BIT_IOR_EXPR;
10479 break;
10480 case CPP_AND_AND:
10481 oprec = PREC_LOGAND;
10482 ocode = TRUTH_ANDIF_EXPR;
10483 break;
10484 case CPP_OR_OR:
10485 oprec = PREC_LOGOR;
10486 ocode = TRUTH_ORIF_EXPR;
10487 break;
10488 default:
10489 /* Not a binary operator, so end of the binary
10490 expression. */
10491 goto out;
10492 }
10493 binary_loc = c_parser_peek_token (parser)->location;
10494 while (oprec <= stack[sp].prec)
10495 POP;
10496 c_parser_consume_token (parser);
10497 switch (ocode)
10498 {
10499 case TRUTH_ANDIF_EXPR:
10500 src_range = stack[sp].expr.src_range;
10501 stack[sp].expr
10502 = convert_lvalue_to_rvalue (stack[sp].loc,
10503 stack[sp].expr, true, true);
10504 stack[sp].expr.value = c_objc_common_truthvalue_conversion
10505 (stack[sp].loc, default_conversion (stack[sp].expr.value));
10506 c_inhibit_evaluation_warnings += (stack[sp].expr.value
10507 == truthvalue_false_node);
10508 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
10509 break;
10510 case TRUTH_ORIF_EXPR:
10511 src_range = stack[sp].expr.src_range;
10512 stack[sp].expr
10513 = convert_lvalue_to_rvalue (stack[sp].loc,
10514 stack[sp].expr, true, true);
10515 stack[sp].expr.value = c_objc_common_truthvalue_conversion
10516 (stack[sp].loc, default_conversion (stack[sp].expr.value));
10517 c_inhibit_evaluation_warnings += (stack[sp].expr.value
10518 == truthvalue_true_node);
10519 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
10520 break;
10521 default:
10522 break;
10523 }
10524 sp++;
10525 stack[sp].loc = binary_loc;
10526 stack[sp].expr = c_parser_cast_expression (parser, NULL);
10527 stack[sp].prec = oprec;
10528 stack[sp].op = ocode;
10529 stack[sp].sizeof_arg = c_last_sizeof_arg;
10530 }
10531 out:
10532 while (sp > 0)
10533 POP;
10534 return stack[0].expr;
10535#undef POP
10536}
10537
10538/* Parse any storage class specifiers after an open parenthesis in a
10539 context where a compound literal is permitted. */
10540
10541static struct c_declspecs *
10542c_parser_compound_literal_scspecs (c_parser *parser)
10543{
10544 bool seen_scspec = false;
10545 struct c_declspecs *specs = build_null_declspecs ();
10546 while (c_parser_next_token_is (parser, type: CPP_KEYWORD))
10547 {
10548 switch (c_parser_peek_token (parser)->keyword)
10549 {
10550 case RID_CONSTEXPR:
10551 case RID_REGISTER:
10552 case RID_STATIC:
10553 case RID_THREAD:
10554 seen_scspec = true;
10555 declspecs_add_scspec (c_parser_peek_token (parser)->location,
10556 specs, c_parser_peek_token (parser)->value);
10557 c_parser_consume_token (parser);
10558 break;
10559 default:
10560 goto out;
10561 }
10562 }
10563 out:
10564 return seen_scspec ? specs : NULL;
10565}
10566
10567/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
10568 is not NULL then it is an Objective-C message expression which is the
10569 primary-expression starting the expression as an initializer.
10570
10571 cast-expression:
10572 unary-expression
10573 ( type-name ) unary-expression
10574*/
10575
10576static struct c_expr
10577c_parser_cast_expression (c_parser *parser, struct c_expr *after)
10578{
10579 location_t cast_loc = c_parser_peek_token (parser)->location;
10580 gcc_assert (!after || c_dialect_objc ());
10581 if (after)
10582 return c_parser_postfix_expression_after_primary (parser,
10583 loc: cast_loc, *after);
10584 /* If the expression begins with a parenthesized type name, it may
10585 be either a cast or a compound literal; we need to see whether
10586 the next character is '{' to tell the difference. If not, it is
10587 an unary expression. Full detection of unknown typenames here
10588 would require a 3-token lookahead. */
10589 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10590 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10591 {
10592 struct c_declspecs *scspecs;
10593 struct c_type_name *type_name;
10594 struct c_expr ret;
10595 struct c_expr expr;
10596 matching_parens parens;
10597 parens.consume_open (parser);
10598 scspecs = c_parser_compound_literal_scspecs (parser);
10599 type_name = c_parser_type_name (parser, alignas_ok: true);
10600 parens.skip_until_found_close (parser);
10601 if (type_name == NULL)
10602 {
10603 ret.set_error ();
10604 ret.original_code = ERROR_MARK;
10605 ret.original_type = NULL;
10606 return ret;
10607 }
10608
10609 /* Save casted types in the function's used types hash table. */
10610 used_types_insert (type_name->specs->type);
10611
10612 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10613 return c_parser_postfix_expression_after_paren_type (parser, scspecs,
10614 type_name,
10615 cast_loc);
10616 if (scspecs)
10617 error_at (cast_loc, "storage class specifier in cast");
10618 if (type_name->specs->alignas_p)
10619 error_at (type_name->specs->locations[cdw_alignas],
10620 "alignment specified for type name in cast");
10621 {
10622 location_t expr_loc = c_parser_peek_token (parser)->location;
10623 expr = c_parser_cast_expression (parser, NULL);
10624 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
10625 }
10626 ret.value = c_cast_expr (cast_loc, type_name, expr.value);
10627 if (ret.value && expr.value)
10628 set_c_expr_source_range (expr: &ret, start: cast_loc, finish: expr.get_finish ());
10629 ret.original_code = ERROR_MARK;
10630 ret.original_type = NULL;
10631 ret.m_decimal = 0;
10632 return ret;
10633 }
10634 else
10635 return c_parser_unary_expression (parser);
10636}
10637
10638/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
10639
10640 unary-expression:
10641 postfix-expression
10642 ++ unary-expression
10643 -- unary-expression
10644 unary-operator cast-expression
10645 _Countof unary-expression
10646 _Countof ( type-name )
10647 sizeof unary-expression
10648 sizeof ( type-name )
10649 static-assert-declaration-no-semi
10650
10651 (_Countof and the use of static assertions in expressions are new in C2y.)
10652
10653 unary-operator: one of
10654 & * + - ~ !
10655
10656 GNU extensions:
10657
10658 unary-expression:
10659 __alignof__ unary-expression
10660 __alignof__ ( type-name )
10661 _Maxof ( type-name )
10662 _Minof ( type-name )
10663 && identifier
10664
10665 (C11 permits _Alignof with type names only.)
10666
10667 unary-operator: one of
10668 __extension__ __real__ __imag__
10669
10670 Transactional Memory:
10671
10672 unary-expression:
10673 transaction-expression
10674
10675 In addition, the GNU syntax treats ++ and -- as unary operators, so
10676 they may be applied to cast expressions with errors for non-lvalues
10677 given later. */
10678
10679static struct c_expr
10680c_parser_unary_expression (c_parser *parser)
10681{
10682 int ext;
10683 struct c_expr ret, op;
10684 location_t op_loc = c_parser_peek_token (parser)->location;
10685 location_t exp_loc;
10686 location_t finish;
10687 ret.original_code = ERROR_MARK;
10688 ret.original_type = NULL;
10689 switch (c_parser_peek_token (parser)->type)
10690 {
10691 case CPP_PLUS_PLUS:
10692 c_parser_consume_token (parser);
10693 exp_loc = c_parser_peek_token (parser)->location;
10694 op = c_parser_cast_expression (parser, NULL);
10695 if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10696 && !DECL_READ_P (op.value)
10697 && (VAR_P (op.value) ? warn_unused_but_set_variable
10698 : warn_unused_but_set_parameter) > 1)
10699 {
10700 op = default_function_array_read_conversion (exp_loc, op);
10701 DECL_READ_P (op.value) = 0;
10702 }
10703 else
10704 op = default_function_array_read_conversion (exp_loc, op);
10705 return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
10706 case CPP_MINUS_MINUS:
10707 c_parser_consume_token (parser);
10708 exp_loc = c_parser_peek_token (parser)->location;
10709 op = c_parser_cast_expression (parser, NULL);
10710 if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10711 && !DECL_READ_P (op.value)
10712 && (VAR_P (op.value) ? warn_unused_but_set_variable
10713 : warn_unused_but_set_parameter) > 1)
10714 {
10715 op = default_function_array_read_conversion (exp_loc, op);
10716 DECL_READ_P (op.value) = 0;
10717 }
10718 else
10719 op = default_function_array_read_conversion (exp_loc, op);
10720 return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
10721 case CPP_AND:
10722 c_parser_consume_token (parser);
10723 op = c_parser_cast_expression (parser, NULL);
10724 mark_exp_read (op.value);
10725 return parser_build_unary_op (op_loc, ADDR_EXPR, op);
10726 case CPP_MULT:
10727 {
10728 c_parser_consume_token (parser);
10729 exp_loc = c_parser_peek_token (parser)->location;
10730 op = c_parser_cast_expression (parser, NULL);
10731 finish = op.get_finish ();
10732 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10733 location_t combined_loc = make_location (caret: op_loc, start: op_loc, finish);
10734 ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
10735 ret.src_range.m_start = op_loc;
10736 ret.src_range.m_finish = finish;
10737 ret.m_decimal = 0;
10738 return ret;
10739 }
10740 case CPP_PLUS:
10741 if (!c_dialect_objc () && !in_system_header_at (loc: input_location))
10742 warning_at (op_loc,
10743 OPT_Wtraditional,
10744 "traditional C rejects the unary plus operator");
10745 c_parser_consume_token (parser);
10746 exp_loc = c_parser_peek_token (parser)->location;
10747 op = c_parser_cast_expression (parser, NULL);
10748 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10749 return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
10750 case CPP_MINUS:
10751 c_parser_consume_token (parser);
10752 exp_loc = c_parser_peek_token (parser)->location;
10753 op = c_parser_cast_expression (parser, NULL);
10754 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10755 return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
10756 case CPP_COMPL:
10757 c_parser_consume_token (parser);
10758 exp_loc = c_parser_peek_token (parser)->location;
10759 op = c_parser_cast_expression (parser, NULL);
10760 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10761 return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
10762 case CPP_NOT:
10763 c_parser_consume_token (parser);
10764 exp_loc = c_parser_peek_token (parser)->location;
10765 op = c_parser_cast_expression (parser, NULL);
10766 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10767 return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
10768 case CPP_AND_AND:
10769 /* Refer to the address of a label as a pointer. */
10770 c_parser_consume_token (parser);
10771 if (c_parser_next_token_is (parser, type: CPP_NAME))
10772 {
10773 ret.value = finish_label_address_expr
10774 (c_parser_peek_token (parser)->value, op_loc);
10775 set_c_expr_source_range (expr: &ret, start: op_loc,
10776 finish: c_parser_peek_token (parser)->get_finish ());
10777 c_parser_consume_token (parser);
10778 }
10779 else
10780 {
10781 c_parser_error (parser, gmsgid: "expected identifier");
10782 ret.set_error ();
10783 }
10784 return ret;
10785 case CPP_KEYWORD:
10786 {
10787 enum rid rid = c_parser_peek_token (parser)->keyword;
10788 switch (rid)
10789 {
10790 case RID_COUNTOF:
10791 case RID_SIZEOF:
10792 return c_parser_sizeof_or_countof_expression (parser, rid);
10793 case RID_ALIGNOF:
10794 return c_parser_alignof_expression (parser);
10795 case RID_MAXOF:
10796 case RID_MINOF:
10797 return c_parser_maxof_or_minof_expression (parser, rid);
10798 case RID_BUILTIN_HAS_ATTRIBUTE:
10799 return c_parser_has_attribute_expression (parser);
10800 case RID_EXTENSION:
10801 c_parser_consume_token (parser);
10802 ext = disable_extension_diagnostics ();
10803 ret = c_parser_cast_expression (parser, NULL);
10804 restore_extension_diagnostics (flags: ext);
10805 return ret;
10806 case RID_REALPART:
10807 c_parser_consume_token (parser);
10808 exp_loc = c_parser_peek_token (parser)->location;
10809 op = c_parser_cast_expression (parser, NULL);
10810 op = default_function_array_conversion (exp_loc, op);
10811 return parser_build_unary_op (op_loc, REALPART_EXPR, op);
10812 case RID_IMAGPART:
10813 c_parser_consume_token (parser);
10814 exp_loc = c_parser_peek_token (parser)->location;
10815 op = c_parser_cast_expression (parser, NULL);
10816 op = default_function_array_conversion (exp_loc, op);
10817 return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
10818 case RID_TRANSACTION_ATOMIC:
10819 case RID_TRANSACTION_RELAXED:
10820 return c_parser_transaction_expression (parser, rid);
10821 case RID_STATIC_ASSERT:
10822 c_parser_static_assert_declaration_no_semi (parser);
10823 pedwarn_c23 (op_loc, OPT_Wpedantic,
10824 "ISO C does not support static assertions in "
10825 "expressions before C2Y");
10826 ret.value = void_node;
10827 set_c_expr_source_range (expr: &ret, start: op_loc, finish: op_loc);
10828 ret.m_decimal = 0;
10829 return ret;
10830 default:
10831 return c_parser_postfix_expression (parser);
10832 }
10833 }
10834 default:
10835 return c_parser_postfix_expression (parser);
10836 }
10837}
10838
10839/* Parse a sizeof or _Countof expression. */
10840
10841static struct c_expr
10842c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
10843{
10844 const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
10845 struct c_expr expr;
10846 struct c_expr result;
10847 location_t expr_loc;
10848 gcc_assert (c_parser_next_token_is_keyword (parser, rid));
10849
10850 location_t start;
10851 location_t finish = UNKNOWN_LOCATION;
10852
10853 start = c_parser_peek_token (parser)->location;
10854
10855 if (rid == RID_COUNTOF)
10856 pedwarn_c23 (start, OPT_Wpedantic,
10857 "ISO C does not support %qs before C2Y", op_name);
10858
10859 c_parser_consume_token (parser);
10860 c_inhibit_evaluation_warnings++;
10861 if (rid == RID_COUNTOF)
10862 in_countof++;
10863 else
10864 in_sizeof++;
10865 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10866 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10867 {
10868 /* Either sizeof ( type-name ) or sizeof unary-expression
10869 starting with a compound literal. */
10870 struct c_declspecs *scspecs;
10871 struct c_type_name *type_name;
10872 matching_parens parens;
10873 parens.consume_open (parser);
10874 expr_loc = c_parser_peek_token (parser)->location;
10875 scspecs = c_parser_compound_literal_scspecs (parser);
10876 type_name = c_parser_type_name (parser, alignas_ok: true);
10877 parens.skip_until_found_close (parser);
10878 finish = parser->tokens_buf[0].location;
10879 if (type_name == NULL)
10880 {
10881 /* Let c_expr_sizeof_expr call pop_maybe_used and fill in c_expr
10882 for parsing error; the parsing of the expression could have
10883 called record_maybe_used_decl. */
10884 expr.set_error ();
10885 goto Xof_expr;
10886 }
10887 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10888 {
10889 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10890 type_name,
10891 expr_loc);
10892 finish = expr.get_finish ();
10893 goto Xof_expr;
10894 }
10895 /* sizeof ( type-name ). */
10896 if (scspecs)
10897 error_at (expr_loc, "storage class specifier in %qs", op_name);
10898 if (type_name->specs->alignas_p)
10899 error_at (type_name->specs->locations[cdw_alignas],
10900 "alignment specified for type name in %qs", op_name);
10901 c_inhibit_evaluation_warnings--;
10902 if (rid == RID_COUNTOF)
10903 {
10904 in_countof--;
10905 result = c_expr_countof_type (loc: expr_loc, type_name);
10906 }
10907 else
10908 {
10909 in_sizeof--;
10910 result = c_expr_sizeof_type (expr_loc, type_name);
10911 }
10912 }
10913 else
10914 {
10915 expr_loc = c_parser_peek_token (parser)->location;
10916 expr = c_parser_unary_expression (parser);
10917 finish = expr.get_finish ();
10918 Xof_expr:
10919 c_inhibit_evaluation_warnings--;
10920 if (rid == RID_COUNTOF)
10921 in_countof--;
10922 else
10923 in_sizeof--;
10924 mark_exp_read (expr.value);
10925 if (TREE_CODE (expr.value) == COMPONENT_REF
10926 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
10927 error_at (expr_loc, "%qs applied to a bit-field", op_name);
10928 if (rid == RID_COUNTOF)
10929 result = c_expr_countof_expr (expr_loc, expr);
10930 else
10931 result = c_expr_sizeof_expr (expr_loc, expr);
10932 }
10933 if (finish == UNKNOWN_LOCATION)
10934 finish = start;
10935 set_c_expr_source_range (expr: &result, start, finish);
10936 return result;
10937}
10938
10939/* Parse an alignof expression. */
10940
10941static struct c_expr
10942c_parser_alignof_expression (c_parser *parser)
10943{
10944 struct c_expr expr;
10945 location_t start_loc = c_parser_peek_token (parser)->location;
10946 location_t end_loc;
10947 tree alignof_spelling = c_parser_peek_token (parser)->value;
10948 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
10949 bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
10950 s2: "_Alignof") == 0
10951 || strcmp (IDENTIFIER_POINTER (alignof_spelling),
10952 s2: "alignof") == 0);
10953 /* A diagnostic is not required for the use of this identifier in
10954 the implementation namespace; only diagnose it for the C11 or C23
10955 spelling because of existing code using the other spellings. */
10956 if (is_c11_alignof)
10957 {
10958 if (flag_isoc99)
10959 pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
10960 alignof_spelling);
10961 else
10962 pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
10963 alignof_spelling);
10964 }
10965 c_parser_consume_token (parser);
10966 c_inhibit_evaluation_warnings++;
10967 in_alignof++;
10968 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10969 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10970 {
10971 /* Either __alignof__ ( type-name ) or __alignof__
10972 unary-expression starting with a compound literal. */
10973 location_t loc;
10974 struct c_declspecs *scspecs;
10975 struct c_type_name *type_name;
10976 struct c_expr ret;
10977 matching_parens parens;
10978 parens.consume_open (parser);
10979 loc = c_parser_peek_token (parser)->location;
10980 scspecs = c_parser_compound_literal_scspecs (parser);
10981 type_name = c_parser_type_name (parser, alignas_ok: true);
10982 end_loc = c_parser_peek_token (parser)->location;
10983 parens.skip_until_found_close (parser);
10984 if (type_name == NULL)
10985 {
10986 struct c_expr ret;
10987 c_inhibit_evaluation_warnings--;
10988 in_alignof--;
10989 ret.set_error ();
10990 ret.original_code = ERROR_MARK;
10991 ret.original_type = NULL;
10992 return ret;
10993 }
10994 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10995 {
10996 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10997 type_name,
10998 loc);
10999 goto alignof_expr;
11000 }
11001 /* alignof ( type-name ). */
11002 if (scspecs)
11003 error_at (loc, "storage class specifier in %qE", alignof_spelling);
11004 if (type_name->specs->alignas_p)
11005 error_at (type_name->specs->locations[cdw_alignas],
11006 "alignment specified for type name in %qE",
11007 alignof_spelling);
11008 c_inhibit_evaluation_warnings--;
11009 in_alignof--;
11010 ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
11011 NULL, NULL),
11012 false, is_c11_alignof, 1);
11013 ret.original_code = ERROR_MARK;
11014 ret.original_type = NULL;
11015 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
11016 ret.m_decimal = 0;
11017 return ret;
11018 }
11019 else
11020 {
11021 struct c_expr ret;
11022 expr = c_parser_unary_expression (parser);
11023 end_loc = expr.src_range.m_finish;
11024 alignof_expr:
11025 mark_exp_read (expr.value);
11026 c_inhibit_evaluation_warnings--;
11027 in_alignof--;
11028 if (is_c11_alignof)
11029 pedwarn (start_loc,
11030 OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
11031 alignof_spelling);
11032 ret.value = c_alignof_expr (start_loc, expr.value);
11033 ret.original_code = ERROR_MARK;
11034 ret.original_type = NULL;
11035 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
11036 ret.m_decimal = 0;
11037 return ret;
11038 }
11039}
11040
11041/* Parse a _Maxof or _Minof expression. */
11042
11043static struct c_expr
11044c_parser_maxof_or_minof_expression (c_parser *parser, enum rid rid)
11045{
11046 const char *op_name = (rid == RID_MAXOF) ? "_Maxof" : "_Minof";
11047 struct c_expr result;
11048 location_t expr_loc;
11049 struct c_type_name *type_name;
11050 matching_parens parens;
11051 gcc_assert (c_parser_next_token_is_keyword (parser, rid));
11052
11053 location_t start;
11054 location_t finish = UNKNOWN_LOCATION;
11055
11056 start = c_parser_peek_token (parser)->location;
11057
11058 pedwarn (start, OPT_Wpedantic, "ISO C does not support %qs", op_name);
11059
11060 c_parser_consume_token (parser);
11061 c_inhibit_evaluation_warnings++;
11062 if (!c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
11063 {
11064 c_parser_error (parser, gmsgid: "expected %<(%>");
11065 goto fail;
11066 }
11067 parens.consume_open (parser);
11068 expr_loc = c_parser_peek_token (parser)->location;
11069 if (!c_token_starts_typename (token: c_parser_peek_token (parser)))
11070 {
11071 error_at (expr_loc, "invalid application of %qs to something not a type", op_name);
11072 parens.skip_until_found_close (parser);
11073 goto fail;
11074 }
11075 type_name = c_parser_type_name (parser, alignas_ok: true);
11076 if (type_name == NULL)
11077 {
11078 // c_parser_type_name() has already diagnosed the error.
11079 parens.skip_until_found_close (parser);
11080 goto fail;
11081 }
11082 parens.skip_until_found_close (parser);
11083 finish = parser->tokens_buf[0].location;
11084 if (type_name->specs->alignas_p)
11085 error_at (type_name->specs->locations[cdw_alignas],
11086 "alignment specified for type name in %qs", op_name);
11087 c_inhibit_evaluation_warnings--;
11088 if (rid == RID_MAXOF)
11089 result = c_expr_maxof_type (loc: expr_loc, type_name);
11090 else
11091 result = c_expr_minof_type (loc: expr_loc, type_name);
11092 set_c_expr_source_range (expr: &result, start, finish);
11093 return result;
11094fail:
11095 c_inhibit_evaluation_warnings--;
11096 result.set_error ();
11097 result.original_code = ERROR_MARK;
11098 result.original_type = NULL;
11099 return result;
11100}
11101
11102/* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
11103 expression. */
11104
11105static struct c_expr
11106c_parser_has_attribute_expression (c_parser *parser)
11107{
11108 gcc_assert (c_parser_next_token_is_keyword (parser,
11109 RID_BUILTIN_HAS_ATTRIBUTE));
11110 location_t start = c_parser_peek_token (parser)->location;
11111 c_parser_consume_token (parser);
11112
11113 c_inhibit_evaluation_warnings++;
11114
11115 matching_parens parens;
11116 if (!parens.require_open (parser))
11117 {
11118 c_inhibit_evaluation_warnings--;
11119 in_typeof--;
11120
11121 struct c_expr result;
11122 result.set_error ();
11123 result.original_code = ERROR_MARK;
11124 result.original_type = NULL;
11125 return result;
11126 }
11127
11128 /* Treat the type argument the same way as in typeof for the purposes
11129 of warnings. FIXME: Generalize this so the warning refers to
11130 __builtin_has_attribute rather than typeof. */
11131 in_typeof++;
11132
11133 /* The first operand: one of DECL, EXPR, or TYPE. */
11134 tree oper = NULL_TREE;
11135 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
11136 {
11137 struct c_type_name *tname = c_parser_type_name (parser);
11138 in_typeof--;
11139 if (tname)
11140 {
11141 oper = groktypename (tname, NULL, NULL);
11142 pop_maybe_used (c_type_variably_modified_p (t: oper));
11143 }
11144 }
11145 else
11146 {
11147 struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
11148 c_inhibit_evaluation_warnings--;
11149 in_typeof--;
11150 if (cexpr.value != error_mark_node)
11151 {
11152 mark_exp_read (cexpr.value);
11153 oper = cexpr.value;
11154 tree etype = TREE_TYPE (oper);
11155 bool was_vm = c_type_variably_modified_p (t: etype);
11156 /* This is returned with the type so that when the type is
11157 evaluated, this can be evaluated. */
11158 if (was_vm)
11159 oper = c_fully_fold (oper, false, NULL);
11160 pop_maybe_used (was_vm);
11161 }
11162 }
11163
11164 struct c_expr result;
11165 result.original_code = ERROR_MARK;
11166 result.original_type = NULL;
11167
11168 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11169 {
11170 /* Consume the closing parenthesis if that's the next token
11171 in the likely case the built-in was invoked with fewer
11172 than two arguments. */
11173 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11174 c_parser_consume_token (parser);
11175 c_inhibit_evaluation_warnings--;
11176 result.set_error ();
11177 return result;
11178 }
11179
11180 bool save_translate_strings_p = parser->translate_strings_p;
11181
11182 location_t atloc = c_parser_peek_token (parser)->location;
11183 /* Parse a single attribute. Require no leading comma and do not
11184 allow empty attributes. */
11185 tree attr = c_parser_gnu_attribute (parser, NULL_TREE, expect_comma: false, empty_ok: false);
11186
11187 parser->translate_strings_p = save_translate_strings_p;
11188
11189 location_t finish = c_parser_peek_token (parser)->location;
11190 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11191 c_parser_consume_token (parser);
11192 else
11193 {
11194 c_parser_error (parser, gmsgid: "expected identifier");
11195 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11196
11197 result.set_error ();
11198 return result;
11199 }
11200
11201 if (!attr)
11202 {
11203 error_at (atloc, "expected identifier");
11204 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11205 msgid: "expected %<)%>");
11206 result.set_error ();
11207 return result;
11208 }
11209
11210 result.original_code = INTEGER_CST;
11211 result.original_type = boolean_type_node;
11212
11213 if (has_attribute (atloc, oper, attr, default_conversion))
11214 result.value = boolean_true_node;
11215 else
11216 result.value = boolean_false_node;
11217
11218 set_c_expr_source_range (expr: &result, start, finish);
11219 result.m_decimal = 0;
11220 return result;
11221}
11222
11223/* Helper function to read arguments of builtins which are interfaces
11224 for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
11225 others. The name of the builtin is passed using BNAME parameter.
11226 Function returns true if there were no errors while parsing and
11227 stores the arguments in CEXPR_LIST. If it returns true,
11228 *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
11229 parenthesis. */
11230static bool
11231c_parser_get_builtin_args (c_parser *parser, const char *bname,
11232 vec<c_expr_t, va_gc> **ret_cexpr_list,
11233 bool choose_expr_p,
11234 location_t *out_close_paren_loc)
11235{
11236 location_t loc = c_parser_peek_token (parser)->location;
11237 vec<c_expr_t, va_gc> *cexpr_list;
11238 c_expr_t expr;
11239 bool saved_force_folding_builtin_constant_p;
11240
11241 *ret_cexpr_list = NULL;
11242 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
11243 {
11244 error_at (loc, "cannot take address of %qs", bname);
11245 return false;
11246 }
11247
11248 c_parser_consume_token (parser);
11249
11250 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11251 {
11252 *out_close_paren_loc = c_parser_peek_token (parser)->location;
11253 c_parser_consume_token (parser);
11254 return true;
11255 }
11256
11257 saved_force_folding_builtin_constant_p
11258 = force_folding_builtin_constant_p;
11259 force_folding_builtin_constant_p |= choose_expr_p;
11260 expr = c_parser_expr_no_commas (parser, NULL);
11261 force_folding_builtin_constant_p
11262 = saved_force_folding_builtin_constant_p;
11263 vec_alloc (v&: cexpr_list, nelems: 1);
11264 vec_safe_push (v&: cexpr_list, obj: expr);
11265 while (c_parser_next_token_is (parser, type: CPP_COMMA))
11266 {
11267 c_parser_consume_token (parser);
11268 if (c_parser_next_token_is (parser, type: CPP_EMBED))
11269 {
11270 c_token *embed = c_parser_peek_token (parser);
11271 tree value = embed->value;
11272 expr.original_code = INTEGER_CST;
11273 expr.original_type = integer_type_node;
11274 expr.value = NULL_TREE;
11275 set_c_expr_source_range (expr: &expr, src_range: embed->get_range ());
11276 expr.m_decimal = 0;
11277 for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
11278 {
11279 expr.value = build_int_cst (integer_type_node,
11280 RAW_DATA_UCHAR_ELT (value, i));
11281 vec_safe_push (v&: cexpr_list, obj: expr);
11282 }
11283 c_parser_consume_token (parser);
11284 continue;
11285 }
11286 expr = c_parser_expr_no_commas (parser, NULL);
11287 vec_safe_push (v&: cexpr_list, obj: expr);
11288 }
11289
11290 *out_close_paren_loc = c_parser_peek_token (parser)->location;
11291 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
11292 return false;
11293
11294 *ret_cexpr_list = cexpr_list;
11295 return true;
11296}
11297
11298/* This represents a single generic-association. */
11299
11300struct c_generic_association
11301{
11302 /* The location of the starting token of the type. */
11303 location_t type_location;
11304 /* The association's type, or NULL_TREE for 'default'. */
11305 tree type;
11306 /* The association's expression. */
11307 struct c_expr expression;
11308};
11309
11310/* Parse a generic-selection. (C11 6.5.1.1).
11311
11312 generic-selection:
11313 _Generic ( generic-controlling-operand , generic-assoc-list )
11314
11315 generic-controlling-operand:
11316 assignment-expression
11317 type-name
11318
11319 (The use of a type-name is new in C2Y.)
11320
11321 generic-assoc-list:
11322 generic-association
11323 generic-assoc-list , generic-association
11324
11325 generic-association:
11326 type-name : assignment-expression
11327 default : assignment-expression
11328*/
11329
11330static struct c_expr
11331c_parser_generic_selection (c_parser *parser)
11332{
11333 struct c_expr selector, error_expr;
11334 tree selector_type;
11335 struct c_generic_association matched_assoc;
11336 int match_found = -1;
11337 location_t generic_loc, selector_loc;
11338
11339 error_expr.original_code = ERROR_MARK;
11340 error_expr.original_type = NULL;
11341 error_expr.set_error ();
11342 matched_assoc.type_location = UNKNOWN_LOCATION;
11343 matched_assoc.type = NULL_TREE;
11344 matched_assoc.expression = error_expr;
11345
11346 gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
11347 generic_loc = c_parser_peek_token (parser)->location;
11348 c_parser_consume_token (parser);
11349 if (flag_isoc99)
11350 pedwarn_c99 (generic_loc, OPT_Wpedantic,
11351 "ISO C99 does not support %<_Generic%>");
11352 else
11353 pedwarn_c99 (generic_loc, OPT_Wpedantic,
11354 "ISO C90 does not support %<_Generic%>");
11355
11356 matching_parens parens;
11357 if (!parens.require_open (parser))
11358 return error_expr;
11359
11360 selector_loc = c_parser_peek_token (parser)->location;
11361 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
11362 {
11363 c_inhibit_evaluation_warnings++;
11364 pedwarn_c23 (selector_loc, OPT_Wpedantic,
11365 "ISO C does not support use of type name as %<_Generic%> "
11366 "controlling operand before C2Y");
11367 struct c_type_name *type = c_parser_type_name (parser);
11368 if (type)
11369 selector_type = groktypename (type, NULL, NULL);
11370 c_inhibit_evaluation_warnings--;
11371 if (!type)
11372 {
11373 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11374 return error_expr;
11375 }
11376 }
11377 else
11378 {
11379 c_inhibit_evaluation_warnings++;
11380 in_generic++;
11381 selector = c_parser_expr_no_commas (parser, NULL);
11382 selector = default_function_array_conversion (selector_loc, selector);
11383 c_inhibit_evaluation_warnings--;
11384 in_generic--;
11385 pop_maybe_used (!flag_isoc23);
11386
11387 if (selector.value == error_mark_node)
11388 {
11389 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11390 return selector;
11391 }
11392 mark_exp_read (selector.value);
11393 selector_type = TREE_TYPE (selector.value);
11394 /* In ISO C terms, rvalues (including the controlling expression
11395 of _Generic) do not have qualified types. */
11396 if (TREE_CODE (selector_type) != ARRAY_TYPE)
11397 selector_type = TYPE_MAIN_VARIANT (selector_type);
11398 /* In ISO C terms, _Noreturn is not part of the type of expressions
11399 such as &abort, but in GCC it is represented internally as a type
11400 qualifier. */
11401 if (FUNCTION_POINTER_TYPE_P (selector_type)
11402 && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
11403 selector_type
11404 = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
11405 }
11406
11407 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11408 {
11409 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11410 return error_expr;
11411 }
11412
11413 auto_vec<c_generic_association> associations;
11414 struct maybe_used_decl *maybe_used_default = NULL;
11415 while (1)
11416 {
11417 struct c_generic_association assoc, *iter;
11418 unsigned int ix;
11419 c_token *token = c_parser_peek_token (parser);
11420
11421 assoc.type_location = token->location;
11422 if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
11423 {
11424 c_parser_consume_token (parser);
11425 assoc.type = NULL_TREE;
11426 }
11427 else
11428 {
11429 struct c_type_name *type_name;
11430
11431 type_name = c_parser_type_name (parser);
11432 if (type_name == NULL)
11433 {
11434 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11435 return error_expr;
11436 }
11437 assoc.type = grokgenassoc (type_name);
11438 if (assoc.type == error_mark_node)
11439 {
11440 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11441 return error_expr;
11442 }
11443
11444 if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
11445 pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11446 "ISO C does not support %<_Generic%> association with "
11447 "function type before C2Y");
11448 else if (!COMPLETE_TYPE_P (assoc.type))
11449 pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11450 "ISO C does not support %<_Generic%> association with "
11451 "incomplete type before C2Y");
11452
11453 if (c_type_variably_modified_p (t: assoc.type))
11454 pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11455 "ISO C does not support %<_Generic%> association with "
11456 "variably-modified type before C2Y");
11457 }
11458
11459 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
11460 {
11461 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11462 return error_expr;
11463 }
11464
11465 bool match = assoc.type == NULL_TREE
11466 || comptypes (assoc.type, selector_type);
11467
11468 if (!match)
11469 c_inhibit_evaluation_warnings++;
11470 in_generic++;
11471
11472 assoc.expression = c_parser_expr_no_commas (parser, NULL);
11473
11474 if (!match)
11475 c_inhibit_evaluation_warnings--;
11476 in_generic--;
11477 if (!match)
11478 pop_maybe_used (!flag_isoc23);
11479 else if (assoc.type == NULL_TREE)
11480 maybe_used_default = save_maybe_used ();
11481 else
11482 pop_maybe_used (true);
11483
11484 if (assoc.expression.value == error_mark_node)
11485 {
11486 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11487 return error_expr;
11488 }
11489
11490 for (ix = 0; associations.iterate (ix, ptr: &iter); ++ix)
11491 {
11492 if (assoc.type == NULL_TREE)
11493 {
11494 if (iter->type == NULL_TREE)
11495 {
11496 error_at (assoc.type_location,
11497 "duplicate %<default%> case in %<_Generic%>");
11498 inform (iter->type_location, "original %<default%> is here");
11499 }
11500 }
11501 else if (iter->type != NULL_TREE)
11502 {
11503 if (comptypes (assoc.type, iter->type))
11504 {
11505 error_at (assoc.type_location,
11506 "%<_Generic%> specifies two compatible types");
11507 inform (iter->type_location, "compatible type is here");
11508 }
11509 }
11510 }
11511
11512 if (assoc.type == NULL_TREE)
11513 {
11514 if (match_found < 0)
11515 {
11516 matched_assoc = assoc;
11517 match_found = associations.length ();
11518 }
11519 }
11520 else if (match)
11521 {
11522 if (match_found < 0 || matched_assoc.type == NULL_TREE)
11523 {
11524 matched_assoc = assoc;
11525 match_found = associations.length ();
11526 }
11527 else
11528 {
11529 error_at (assoc.type_location,
11530 "%<_Generic%> selector matches multiple associations");
11531 inform (matched_assoc.type_location,
11532 "other match is here");
11533 }
11534 }
11535
11536 associations.safe_push (obj: assoc);
11537
11538 if (c_parser_peek_token (parser)->type != CPP_COMMA)
11539 break;
11540 c_parser_consume_token (parser);
11541 }
11542
11543 if (match_found >= 0 && matched_assoc.type == NULL_TREE)
11544 {
11545 /* Declarations referenced in the default association are used. */
11546 restore_maybe_used (maybe_used_default);
11547 pop_maybe_used (true);
11548 }
11549 else if (maybe_used_default)
11550 {
11551 /* Declarations referenced in the default association are not used, but
11552 are treated as used before C23. */
11553 restore_maybe_used (maybe_used_default);
11554 pop_maybe_used (!flag_isoc23);
11555 }
11556
11557 unsigned int ix;
11558 struct c_generic_association *iter;
11559 FOR_EACH_VEC_ELT (associations, ix, iter)
11560 if (ix != (unsigned) match_found)
11561 mark_exp_read (iter->expression.value);
11562
11563 if (!parens.require_close (parser))
11564 {
11565 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11566 return error_expr;
11567 }
11568
11569 if (match_found < 0)
11570 {
11571 error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
11572 "compatible with any association",
11573 selector_type);
11574 return error_expr;
11575 }
11576
11577 return matched_assoc.expression;
11578}
11579
11580/* Check the validity of a function pointer argument *EXPR (argument
11581 position POS) to __builtin_tgmath. Return the number of function
11582 arguments if possibly valid; return 0 having reported an error if
11583 not valid. */
11584
11585static unsigned int
11586check_tgmath_function (c_expr *expr, unsigned int pos)
11587{
11588 tree type = TREE_TYPE (expr->value);
11589 if (!FUNCTION_POINTER_TYPE_P (type))
11590 {
11591 error_at (expr->get_location (),
11592 "argument %u of %<__builtin_tgmath%> is not a function pointer",
11593 pos);
11594 return 0;
11595 }
11596 type = TREE_TYPE (type);
11597 if (!prototype_p (type))
11598 {
11599 error_at (expr->get_location (),
11600 "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
11601 return 0;
11602 }
11603 if (stdarg_p (type))
11604 {
11605 error_at (expr->get_location (),
11606 "argument %u of %<__builtin_tgmath%> has variable arguments",
11607 pos);
11608 return 0;
11609 }
11610 unsigned int nargs = 0;
11611 function_args_iterator iter;
11612 tree t;
11613 FOREACH_FUNCTION_ARGS (type, t, iter)
11614 {
11615 if (t == void_type_node)
11616 break;
11617 nargs++;
11618 }
11619 if (nargs == 0)
11620 {
11621 error_at (expr->get_location (),
11622 "argument %u of %<__builtin_tgmath%> has no arguments", pos);
11623 return 0;
11624 }
11625 return nargs;
11626}
11627
11628/* Ways in which a parameter or return value of a type-generic macro
11629 may vary between the different functions the macro may call. */
11630enum tgmath_parm_kind
11631 {
11632 tgmath_fixed, tgmath_real, tgmath_complex
11633 };
11634
11635/* Helper function for c_parser_postfix_expression. Parse predefined
11636 identifiers. */
11637
11638static struct c_expr
11639c_parser_predefined_identifier (c_parser *parser)
11640{
11641 location_t loc = c_parser_peek_token (parser)->location;
11642 switch (c_parser_peek_token (parser)->keyword)
11643 {
11644 case RID_FUNCTION_NAME:
11645 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11646 "identifier", "__FUNCTION__");
11647 break;
11648 case RID_PRETTY_FUNCTION_NAME:
11649 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11650 "identifier", "__PRETTY_FUNCTION__");
11651 break;
11652 case RID_C99_FUNCTION_NAME:
11653 pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
11654 "%<__func__%> predefined identifier");
11655 break;
11656 default:
11657 gcc_unreachable ();
11658 }
11659
11660 struct c_expr expr;
11661 expr.original_code = ERROR_MARK;
11662 expr.original_type = NULL;
11663 expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
11664 c_parser_peek_token (parser)->value);
11665 set_c_expr_source_range (expr: &expr, start: loc, finish: loc);
11666 expr.m_decimal = 0;
11667 c_parser_consume_token (parser);
11668 return expr;
11669}
11670
11671/* Check whether the REF has an counted-by object associated with it
11672 through the "counted_by" attribute. */
11673
11674static bool
11675has_counted_by_object (tree ref)
11676{
11677 /* Currently, there are two cases are valid:
11678 A. when the ref is an indirect_ref to a call to the
11679 .ACCESS_WITH_SIZE, return true. (this is for FAM)
11680 B. when the ref is a call to .ACCESS_WITH_SIZE, return true.
11681 (this is for pointer field inside a structure)
11682 More cases can be included later when the counted_by attribute is
11683 extended to other situations. */
11684 if ((TREE_CODE (ref) == INDIRECT_REF
11685 && is_access_with_size_p (TREE_OPERAND (ref, 0)))
11686 || is_access_with_size_p (ref))
11687 return true;
11688 return false;
11689}
11690
11691/* Get the reference to the counted-by object associated with the REF. */
11692
11693static tree
11694get_counted_by_ref (tree ref)
11695{
11696 /* Currently, there are two cases are valid:
11697 A. when the ref is an indirect_ref to a call to the
11698 .ACCESS_WITH_SIZE, return true. (this is for FAM)
11699 B. when the ref is a call to .ACCESS_WITH_SIZE, return true.
11700 (this is for pointer field inside a structure)
11701 More cases can be included later when the counted_by attribute is
11702 extended to other situations. */
11703 if (TREE_CODE (ref) == INDIRECT_REF
11704 && is_access_with_size_p (TREE_OPERAND (ref, 0)))
11705 return CALL_EXPR_ARG (TREE_OPERAND (ref, 0), 1);
11706 else if (is_access_with_size_p (ref))
11707 return CALL_EXPR_ARG (ref, 1);
11708
11709 return NULL_TREE;
11710}
11711
11712/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
11713 C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
11714 call c_parser_postfix_expression_after_paren_type on encountering them.
11715
11716 postfix-expression:
11717 primary-expression
11718 postfix-expression [ expression ]
11719 postfix-expression ( argument-expression-list[opt] )
11720 postfix-expression . identifier
11721 postfix-expression -> identifier
11722 postfix-expression ++
11723 postfix-expression --
11724 ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
11725 ( storage-class-specifiers[opt] type-name ) { initializer-list , }
11726
11727 argument-expression-list:
11728 argument-expression
11729 argument-expression-list , argument-expression
11730
11731 primary-expression:
11732 identifier
11733 constant
11734 string-literal
11735 ( expression )
11736 generic-selection
11737
11738 GNU extensions:
11739
11740 primary-expression:
11741 __func__
11742 (treated as a keyword in GNU C)
11743 __FUNCTION__
11744 __PRETTY_FUNCTION__
11745 ( compound-statement )
11746 __builtin_va_arg ( assignment-expression , type-name )
11747 __builtin_offsetof ( type-name , offsetof-member-designator )
11748 __builtin_choose_expr ( assignment-expression ,
11749 assignment-expression ,
11750 assignment-expression )
11751 __builtin_types_compatible_p ( type-name , type-name )
11752 __builtin_tgmath ( expr-list )
11753 __builtin_complex ( assignment-expression , assignment-expression )
11754 __builtin_shuffle ( assignment-expression , assignment-expression )
11755 __builtin_shuffle ( assignment-expression ,
11756 assignment-expression ,
11757 assignment-expression, )
11758 __builtin_convertvector ( assignment-expression , type-name )
11759 __builtin_assoc_barrier ( assignment-expression )
11760
11761 offsetof-member-designator:
11762 identifier
11763 offsetof-member-designator . identifier
11764 offsetof-member-designator [ expression ]
11765
11766 Objective-C:
11767
11768 primary-expression:
11769 [ objc-receiver objc-message-args ]
11770 @selector ( objc-selector-arg )
11771 @protocol ( identifier )
11772 @encode ( type-name )
11773 objc-string-literal
11774 Classname . identifier
11775*/
11776
11777static struct c_expr
11778c_parser_postfix_expression (c_parser *parser)
11779{
11780 struct c_expr expr, e1;
11781 struct c_type_name *t1, *t2;
11782 location_t loc = c_parser_peek_token (parser)->location;
11783 source_range tok_range = c_parser_peek_token (parser)->get_range ();
11784 expr.original_code = ERROR_MARK;
11785 expr.original_type = NULL;
11786 expr.m_decimal = 0;
11787 switch (c_parser_peek_token (parser)->type)
11788 {
11789 case CPP_NUMBER:
11790 expr.value = c_parser_peek_token (parser)->value;
11791 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11792 loc = c_parser_peek_token (parser)->location;
11793 expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
11794 c_parser_consume_token (parser);
11795 if (TREE_CODE (expr.value) == FIXED_CST
11796 && !targetm.fixed_point_supported_p ())
11797 {
11798 error_at (loc, "fixed-point types not supported for this target");
11799 expr.set_error ();
11800 }
11801 break;
11802 case CPP_CHAR:
11803 case CPP_CHAR16:
11804 case CPP_CHAR32:
11805 case CPP_UTF8CHAR:
11806 case CPP_WCHAR:
11807 expr.value = c_parser_peek_token (parser)->value;
11808 /* For the purpose of warning when a pointer is compared with
11809 a zero character constant. */
11810 expr.original_type = char_type_node;
11811 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11812 c_parser_consume_token (parser);
11813 break;
11814 case CPP_STRING:
11815 case CPP_STRING16:
11816 case CPP_STRING32:
11817 case CPP_WSTRING:
11818 case CPP_UTF8STRING:
11819 expr = c_parser_string_literal (parser, translate: parser->translate_strings_p,
11820 wide_ok: true);
11821 break;
11822 case CPP_OBJC_STRING:
11823 gcc_assert (c_dialect_objc ());
11824 expr.value
11825 = objc_build_string_object (c_parser_peek_token (parser)->value);
11826 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11827 c_parser_consume_token (parser);
11828 break;
11829 case CPP_NAME:
11830 switch (c_parser_peek_token (parser)->id_kind)
11831 {
11832 case C_ID_ID:
11833 {
11834 tree id = c_parser_peek_token (parser)->value;
11835 c_parser_consume_token (parser);
11836 expr.value = build_external_ref (loc, id,
11837 (c_parser_peek_token (parser)->type
11838 == CPP_OPEN_PAREN),
11839 &expr.original_type);
11840 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11841 break;
11842 }
11843 case C_ID_CLASSNAME:
11844 {
11845 /* Here we parse the Objective-C 2.0 Class.name dot
11846 syntax. */
11847 tree class_name = c_parser_peek_token (parser)->value;
11848 tree component;
11849 c_parser_consume_token (parser);
11850 gcc_assert (c_dialect_objc ());
11851 if (!c_parser_require (parser, type: CPP_DOT, msgid: "expected %<.%>"))
11852 {
11853 expr.set_error ();
11854 break;
11855 }
11856 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
11857 {
11858 c_parser_error (parser, gmsgid: "expected identifier");
11859 expr.set_error ();
11860 break;
11861 }
11862 c_token *component_tok = c_parser_peek_token (parser);
11863 component = component_tok->value;
11864 location_t end_loc = component_tok->get_finish ();
11865 c_parser_consume_token (parser);
11866 expr.value = objc_build_class_component_ref (class_name,
11867 component);
11868 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
11869 break;
11870 }
11871 default:
11872 c_parser_error (parser, gmsgid: "expected expression");
11873 expr.set_error ();
11874 break;
11875 }
11876 break;
11877 case CPP_OPEN_PAREN:
11878 /* A parenthesized expression, statement expression or compound
11879 literal. */
11880 if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
11881 {
11882 /* A statement expression. */
11883 tree stmt;
11884 location_t brace_loc;
11885 bool save_c_omp_array_section_p = c_omp_array_section_p;
11886 c_parser_consume_token (parser);
11887 brace_loc = c_parser_peek_token (parser)->location;
11888 c_parser_consume_token (parser);
11889 /* If we've not yet started the current function's statement list,
11890 or we're in the parameter scope of an old-style function
11891 declaration, statement expressions are not allowed. */
11892 if (!building_stmt_list_p () || old_style_parameter_scope ())
11893 {
11894 error_at (loc, "braced-group within expression allowed "
11895 "only inside a function");
11896 parser->error = true;
11897 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
11898 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11899 expr.set_error ();
11900 break;
11901 }
11902 c_omp_array_section_p = false;
11903 stmt = c_begin_stmt_expr ();
11904 c_parser_compound_statement_nostart (parser);
11905 location_t close_loc = c_parser_peek_token (parser)->location;
11906 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11907 msgid: "expected %<)%>");
11908 pedwarn (loc, OPT_Wpedantic,
11909 "ISO C forbids braced-groups within expressions");
11910 expr.value = c_finish_stmt_expr (brace_loc, stmt);
11911 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11912 mark_exp_read (expr.value);
11913 c_omp_array_section_p = save_c_omp_array_section_p;
11914 }
11915 else
11916 {
11917 /* A parenthesized expression. */
11918 location_t loc_open_paren = c_parser_peek_token (parser)->location;
11919 c_parser_consume_token (parser);
11920 expr = c_parser_expression (parser);
11921 if (TREE_CODE (expr.value) == MODIFY_EXPR)
11922 suppress_warning (expr.value, OPT_Wparentheses);
11923 if (expr.original_code != C_MAYBE_CONST_EXPR
11924 && expr.original_code != SIZEOF_EXPR)
11925 expr.original_code = ERROR_MARK;
11926 /* Remember that we saw ( ) around the sizeof. */
11927 if (expr.original_code == SIZEOF_EXPR)
11928 expr.original_code = PAREN_SIZEOF_EXPR;
11929 /* Don't change EXPR.ORIGINAL_TYPE. */
11930 location_t loc_close_paren = c_parser_peek_token (parser)->location;
11931 set_c_expr_source_range (expr: &expr, start: loc_open_paren, finish: loc_close_paren);
11932 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11933 msgid: "expected %<)%>", matching_location: loc_open_paren);
11934 }
11935 break;
11936 case CPP_KEYWORD:
11937 switch (c_parser_peek_token (parser)->keyword)
11938 {
11939 case RID_FUNCTION_NAME:
11940 case RID_PRETTY_FUNCTION_NAME:
11941 case RID_C99_FUNCTION_NAME:
11942 expr = c_parser_predefined_identifier (parser);
11943 break;
11944 case RID_VA_ARG:
11945 {
11946 location_t start_loc = loc;
11947 c_parser_consume_token (parser);
11948 matching_parens parens;
11949 if (!parens.require_open (parser))
11950 {
11951 expr.set_error ();
11952 break;
11953 }
11954 e1 = c_parser_expr_no_commas (parser, NULL);
11955 mark_exp_read (e1.value);
11956 e1.value = c_fully_fold (e1.value, false, NULL);
11957 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11958 {
11959 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11960 expr.set_error ();
11961 break;
11962 }
11963 loc = c_parser_peek_token (parser)->location;
11964 t1 = c_parser_type_name (parser);
11965 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11966 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11967 msgid: "expected %<)%>");
11968 if (t1 == NULL)
11969 {
11970 expr.set_error ();
11971 }
11972 else
11973 {
11974 tree type_expr = NULL_TREE;
11975 tree type = groktypename (t1, &type_expr, NULL);
11976 expr.value = c_build_va_arg (start_loc, e1.value, loc,
11977 type, type_expr);
11978 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11979 }
11980 }
11981 break;
11982 case RID_C23_VA_START:
11983 {
11984 c_parser_consume_token (parser);
11985 matching_parens parens;
11986 if (!parens.require_open (parser))
11987 {
11988 expr.set_error ();
11989 break;
11990 }
11991 e1 = c_parser_expr_no_commas (parser, NULL);
11992 e1 = convert_lvalue_to_rvalue (e1.get_location (), e1, true, true);
11993 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11994 {
11995 location_t cloc = c_parser_peek_token (parser)->location;
11996 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11997 {
11998 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11999 expr.set_error ();
12000 break;
12001 }
12002 if (c_parser_next_token_is (parser, type: CPP_NAME)
12003 && c_parser_peek_token (parser)->id_kind == C_ID_ID
12004 && (c_parser_peek_2nd_token (parser)->type
12005 == CPP_CLOSE_PAREN))
12006 {
12007 tree name = c_parser_peek_token (parser)->value;
12008 location_t nloc = c_parser_peek_token (parser)->location;
12009 tree decl = lookup_name (name);
12010 tree last_parm
12011 = tree_last (DECL_ARGUMENTS (current_function_decl));
12012 if (!last_parm || decl != last_parm)
12013 warning_at (nloc, OPT_Wvarargs,
12014 "optional second parameter of %<va_start%> "
12015 "not last named argument");
12016 else if (DECL_REGISTER (decl))
12017 warning_at (nloc, OPT_Wvarargs,
12018 "undefined behavior when second parameter "
12019 "of %<va_start%> is declared with "
12020 "%<register%> storage");
12021 c_parser_consume_token (parser);
12022 }
12023 else
12024 {
12025 unsigned nesting_depth = 0;
12026 location_t sloc = c_parser_peek_token (parser)->location;
12027 location_t eloc = sloc;
12028
12029 /* For va_start (ap,) the ) comes from stdarg.h.
12030 Use location of , in that case, otherwise without
12031 -Wsystem-headers nothing is reported. After all,
12032 the problematic token is the comma in that case. */
12033 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
12034 sloc = eloc = cloc;
12035 while (true)
12036 {
12037 c_token *token = c_parser_peek_token (parser);
12038 if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
12039 break;
12040
12041 if (token->type == CPP_EOF)
12042 break;
12043 if (token->type == CPP_OPEN_PAREN)
12044 ++nesting_depth;
12045 else if (token->type == CPP_CLOSE_PAREN)
12046 --nesting_depth;
12047 eloc = token->location;
12048 c_parser_consume_token (parser);
12049 }
12050 if (sloc != eloc)
12051 sloc = make_location (caret: sloc, start: sloc, finish: eloc);
12052 warning_at (sloc, OPT_Wvarargs,
12053 "%<va_start%> macro used with additional "
12054 "arguments other than identifier of the "
12055 "last named argument");
12056 }
12057 }
12058 parens.skip_until_found_close (parser);
12059 tree fndecl = builtin_decl_explicit (fncode: BUILT_IN_VA_START);
12060 vec<tree, va_gc> *params;
12061 vec_alloc (v&: params, nelems: 2);
12062 params->quick_push (obj: e1.value);
12063 params->quick_push (integer_zero_node);
12064 auto_vec<location_t> arg_loc (2);
12065 arg_loc.quick_push (obj: e1.get_location ());
12066 arg_loc.quick_push (UNKNOWN_LOCATION);
12067 expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
12068 params, NULL);
12069 set_c_expr_source_range (expr: &expr, start: loc,
12070 finish: parser->tokens_buf[0].get_finish ());
12071 expr.m_decimal = 0;
12072 expr.original_code = ERROR_MARK;
12073 expr.original_type = NULL;
12074 release_tree_vector (params);
12075 break;
12076 }
12077 case RID_OFFSETOF:
12078 {
12079 c_parser_consume_token (parser);
12080 matching_parens parens;
12081 if (!parens.require_open (parser))
12082 {
12083 expr.set_error ();
12084 break;
12085 }
12086 t1 = c_parser_type_name (parser);
12087 if (t1 == NULL)
12088 parser->error = true;
12089 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
12090 gcc_assert (parser->error);
12091 if (parser->error)
12092 {
12093 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12094 expr.set_error ();
12095 break;
12096 }
12097 tree type = groktypename (t1, NULL, NULL);
12098 tree offsetof_ref;
12099 if (type == error_mark_node)
12100 offsetof_ref = error_mark_node;
12101 else
12102 {
12103 offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
12104 SET_EXPR_LOCATION (offsetof_ref, loc);
12105 }
12106 /* Parse the second argument to __builtin_offsetof. We
12107 must have one identifier, and beyond that we want to
12108 accept sub structure and sub array references. */
12109 if (c_parser_next_token_is (parser, type: CPP_NAME))
12110 {
12111 c_token *comp_tok = c_parser_peek_token (parser);
12112 offsetof_ref
12113 = build_component_ref (loc, offsetof_ref, comp_tok->value,
12114 comp_tok->location, UNKNOWN_LOCATION);
12115 c_parser_consume_token (parser);
12116 while (c_parser_next_token_is (parser, type: CPP_DOT)
12117 || c_parser_next_token_is (parser,
12118 type: CPP_OPEN_SQUARE)
12119 || c_parser_next_token_is (parser,
12120 type: CPP_DEREF))
12121 {
12122 if (c_parser_next_token_is (parser, type: CPP_DEREF))
12123 {
12124 loc = c_parser_peek_token (parser)->location;
12125 offsetof_ref = build_array_ref (loc,
12126 offsetof_ref,
12127 integer_zero_node);
12128 goto do_dot;
12129 }
12130 else if (c_parser_next_token_is (parser, type: CPP_DOT))
12131 {
12132 do_dot:
12133 c_parser_consume_token (parser);
12134 if (c_parser_next_token_is_not (parser,
12135 type: CPP_NAME))
12136 {
12137 c_parser_error (parser, gmsgid: "expected identifier");
12138 break;
12139 }
12140 c_token *comp_tok = c_parser_peek_token (parser);
12141 offsetof_ref
12142 = build_component_ref (loc, offsetof_ref,
12143 comp_tok->value,
12144 comp_tok->location,
12145 UNKNOWN_LOCATION);
12146 c_parser_consume_token (parser);
12147 }
12148 else
12149 {
12150 struct c_expr ce;
12151 tree idx;
12152 loc = c_parser_peek_token (parser)->location;
12153 c_parser_consume_token (parser);
12154 ce = c_parser_expression (parser);
12155 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
12156 idx = ce.value;
12157 idx = c_fully_fold (idx, false, NULL);
12158 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
12159 msgid: "expected %<]%>");
12160 offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
12161 }
12162 }
12163 }
12164 else
12165 c_parser_error (parser, gmsgid: "expected identifier");
12166 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12167 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
12168 msgid: "expected %<)%>");
12169 expr.value = fold_offsetof (offsetof_ref);
12170 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
12171 }
12172 break;
12173 case RID_CHOOSE_EXPR:
12174 {
12175 vec<c_expr_t, va_gc> *cexpr_list;
12176 c_expr_t *e1_p, *e2_p, *e3_p;
12177 tree c;
12178 location_t close_paren_loc;
12179
12180 c_parser_consume_token (parser);
12181 if (!c_parser_get_builtin_args (parser,
12182 bname: "__builtin_choose_expr",
12183 ret_cexpr_list: &cexpr_list, choose_expr_p: true,
12184 out_close_paren_loc: &close_paren_loc))
12185 {
12186 expr.set_error ();
12187 break;
12188 }
12189
12190 if (vec_safe_length (v: cexpr_list) != 3)
12191 {
12192 error_at (loc, "wrong number of arguments to "
12193 "%<__builtin_choose_expr%>");
12194 expr.set_error ();
12195 break;
12196 }
12197
12198 e1_p = &(*cexpr_list)[0];
12199 e2_p = &(*cexpr_list)[1];
12200 e3_p = &(*cexpr_list)[2];
12201
12202 c = e1_p->value;
12203 mark_exp_read (e2_p->value);
12204 mark_exp_read (e3_p->value);
12205 if (TREE_CODE (c) != INTEGER_CST
12206 || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
12207 error_at (loc,
12208 "first argument to %<__builtin_choose_expr%> not"
12209 " a constant");
12210 constant_expression_warning (c);
12211 expr = integer_zerop (c) ? *e3_p : *e2_p;
12212 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12213 break;
12214 }
12215 case RID_TYPES_COMPATIBLE_P:
12216 {
12217 c_parser_consume_token (parser);
12218 matching_parens parens;
12219 if (!parens.require_open (parser))
12220 {
12221 expr.set_error ();
12222 break;
12223 }
12224 t1 = c_parser_type_name (parser);
12225 if (t1 == NULL)
12226 {
12227 expr.set_error ();
12228 break;
12229 }
12230 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
12231 {
12232 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12233 expr.set_error ();
12234 break;
12235 }
12236 t2 = c_parser_type_name (parser);
12237 if (t2 == NULL)
12238 {
12239 expr.set_error ();
12240 break;
12241 }
12242 location_t close_paren_loc = c_parser_peek_token (parser)->location;
12243 parens.skip_until_found_close (parser);
12244 tree e1, e2;
12245 e1 = groktypename (t1, NULL, NULL);
12246 e2 = groktypename (t2, NULL, NULL);
12247 if (e1 == error_mark_node || e2 == error_mark_node)
12248 {
12249 expr.set_error ();
12250 break;
12251 }
12252
12253 e1 = TYPE_MAIN_VARIANT (e1);
12254 e2 = TYPE_MAIN_VARIANT (e2);
12255
12256 expr.value
12257 = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
12258 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12259 }
12260 break;
12261 case RID_BUILTIN_TGMATH:
12262 {
12263 vec<c_expr_t, va_gc> *cexpr_list;
12264 location_t close_paren_loc;
12265
12266 c_parser_consume_token (parser);
12267 if (!c_parser_get_builtin_args (parser,
12268 bname: "__builtin_tgmath",
12269 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12270 out_close_paren_loc: &close_paren_loc))
12271 {
12272 expr.set_error ();
12273 break;
12274 }
12275
12276 if (vec_safe_length (v: cexpr_list) < 3)
12277 {
12278 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12279 expr.set_error ();
12280 break;
12281 }
12282
12283 unsigned int i;
12284 c_expr_t *p;
12285 FOR_EACH_VEC_ELT (*cexpr_list, i, p)
12286 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12287 unsigned int nargs = check_tgmath_function (expr: &(*cexpr_list)[0], pos: 1);
12288 if (nargs == 0)
12289 {
12290 expr.set_error ();
12291 break;
12292 }
12293 if (vec_safe_length (v: cexpr_list) < nargs)
12294 {
12295 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12296 expr.set_error ();
12297 break;
12298 }
12299 unsigned int num_functions = vec_safe_length (v: cexpr_list) - nargs;
12300 if (num_functions < 2)
12301 {
12302 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12303 expr.set_error ();
12304 break;
12305 }
12306
12307 /* The first NUM_FUNCTIONS expressions are the function
12308 pointers. The remaining NARGS expressions are the
12309 arguments that are to be passed to one of those
12310 functions, chosen following <tgmath.h> rules. */
12311 for (unsigned int j = 1; j < num_functions; j++)
12312 {
12313 unsigned int this_nargs
12314 = check_tgmath_function (expr: &(*cexpr_list)[j], pos: j + 1);
12315 if (this_nargs == 0)
12316 {
12317 expr.set_error ();
12318 goto out;
12319 }
12320 if (this_nargs != nargs)
12321 {
12322 error_at ((*cexpr_list)[j].get_location (),
12323 "argument %u of %<__builtin_tgmath%> has "
12324 "wrong number of arguments", j + 1);
12325 expr.set_error ();
12326 goto out;
12327 }
12328 }
12329
12330 /* The functions all have the same number of arguments.
12331 Determine whether arguments and return types vary in
12332 ways permitted for <tgmath.h> functions. */
12333 /* The first entry in each of these vectors is for the
12334 return type, subsequent entries for parameter
12335 types. */
12336 auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
12337 auto_vec<tree> parm_first (nargs + 1);
12338 auto_vec<bool> parm_complex (nargs + 1);
12339 auto_vec<bool> parm_varies (nargs + 1);
12340 tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
12341 tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
12342 parm_first.quick_push (obj: first_ret);
12343 parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
12344 parm_varies.quick_push (obj: false);
12345 function_args_iterator iter;
12346 tree t;
12347 unsigned int argpos;
12348 FOREACH_FUNCTION_ARGS (first_type, t, iter)
12349 {
12350 if (t == void_type_node)
12351 break;
12352 parm_first.quick_push (TYPE_MAIN_VARIANT (t));
12353 parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
12354 parm_varies.quick_push (obj: false);
12355 }
12356 for (unsigned int j = 1; j < num_functions; j++)
12357 {
12358 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12359 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12360 if (ret != parm_first[0])
12361 {
12362 parm_varies[0] = true;
12363 if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
12364 && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
12365 {
12366 error_at ((*cexpr_list)[0].get_location (),
12367 "invalid type-generic return type for "
12368 "argument %u of %<__builtin_tgmath%>",
12369 1);
12370 expr.set_error ();
12371 goto out;
12372 }
12373 if (!SCALAR_FLOAT_TYPE_P (ret)
12374 && !COMPLEX_FLOAT_TYPE_P (ret))
12375 {
12376 error_at ((*cexpr_list)[j].get_location (),
12377 "invalid type-generic return type for "
12378 "argument %u of %<__builtin_tgmath%>",
12379 j + 1);
12380 expr.set_error ();
12381 goto out;
12382 }
12383 }
12384 if (TREE_CODE (ret) == COMPLEX_TYPE)
12385 parm_complex[0] = true;
12386 argpos = 1;
12387 FOREACH_FUNCTION_ARGS (type, t, iter)
12388 {
12389 if (t == void_type_node)
12390 break;
12391 t = TYPE_MAIN_VARIANT (t);
12392 if (t != parm_first[argpos])
12393 {
12394 parm_varies[argpos] = true;
12395 if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
12396 && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
12397 {
12398 error_at ((*cexpr_list)[0].get_location (),
12399 "invalid type-generic type for "
12400 "argument %u of argument %u of "
12401 "%<__builtin_tgmath%>", argpos, 1);
12402 expr.set_error ();
12403 goto out;
12404 }
12405 if (!SCALAR_FLOAT_TYPE_P (t)
12406 && !COMPLEX_FLOAT_TYPE_P (t))
12407 {
12408 error_at ((*cexpr_list)[j].get_location (),
12409 "invalid type-generic type for "
12410 "argument %u of argument %u of "
12411 "%<__builtin_tgmath%>", argpos, j + 1);
12412 expr.set_error ();
12413 goto out;
12414 }
12415 }
12416 if (TREE_CODE (t) == COMPLEX_TYPE)
12417 parm_complex[argpos] = true;
12418 argpos++;
12419 }
12420 }
12421 enum tgmath_parm_kind max_variation = tgmath_fixed;
12422 for (unsigned int j = 0; j <= nargs; j++)
12423 {
12424 enum tgmath_parm_kind this_kind;
12425 if (parm_varies[j])
12426 {
12427 if (parm_complex[j])
12428 max_variation = this_kind = tgmath_complex;
12429 else
12430 {
12431 this_kind = tgmath_real;
12432 if (max_variation != tgmath_complex)
12433 max_variation = tgmath_real;
12434 }
12435 }
12436 else
12437 this_kind = tgmath_fixed;
12438 parm_kind.quick_push (obj: this_kind);
12439 }
12440 if (max_variation == tgmath_fixed)
12441 {
12442 error_at (loc, "function arguments of %<__builtin_tgmath%> "
12443 "all have the same type");
12444 expr.set_error ();
12445 break;
12446 }
12447
12448 /* Identify a parameter (not the return type) that varies,
12449 including with complex types if any variation includes
12450 complex types; there must be at least one such
12451 parameter. */
12452 unsigned int tgarg = 0;
12453 for (unsigned int j = 1; j <= nargs; j++)
12454 if (parm_kind[j] == max_variation)
12455 {
12456 tgarg = j;
12457 break;
12458 }
12459 if (tgarg == 0)
12460 {
12461 error_at (loc, "function arguments of %<__builtin_tgmath%> "
12462 "lack type-generic parameter");
12463 expr.set_error ();
12464 break;
12465 }
12466
12467 /* Determine the type of the relevant parameter for each
12468 function. */
12469 auto_vec<tree> tg_type (num_functions);
12470 for (unsigned int j = 0; j < num_functions; j++)
12471 {
12472 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12473 argpos = 1;
12474 FOREACH_FUNCTION_ARGS (type, t, iter)
12475 {
12476 if (argpos == tgarg)
12477 {
12478 tg_type.quick_push (TYPE_MAIN_VARIANT (t));
12479 break;
12480 }
12481 argpos++;
12482 }
12483 }
12484
12485 /* Verify that the corresponding types are different for
12486 all the listed functions. Also determine whether all
12487 the types are complex, whether all the types are
12488 standard or binary, and whether all the types are
12489 decimal. */
12490 bool all_complex = true;
12491 bool all_binary = true;
12492 bool all_decimal = true;
12493 hash_set<tree> tg_types;
12494 FOR_EACH_VEC_ELT (tg_type, i, t)
12495 {
12496 if (TREE_CODE (t) == COMPLEX_TYPE)
12497 all_decimal = false;
12498 else
12499 {
12500 all_complex = false;
12501 if (DECIMAL_FLOAT_TYPE_P (t))
12502 all_binary = false;
12503 else
12504 all_decimal = false;
12505 }
12506 if (tg_types.add (k: t))
12507 {
12508 error_at ((*cexpr_list)[i].get_location (),
12509 "duplicate type-generic parameter type for "
12510 "function argument %u of %<__builtin_tgmath%>",
12511 i + 1);
12512 expr.set_error ();
12513 goto out;
12514 }
12515 }
12516
12517 /* Verify that other parameters and the return type whose
12518 types vary have their types varying in the correct
12519 way. */
12520 for (unsigned int j = 0; j < num_functions; j++)
12521 {
12522 tree exp_type = tg_type[j];
12523 tree exp_real_type = exp_type;
12524 if (TREE_CODE (exp_type) == COMPLEX_TYPE)
12525 exp_real_type = TREE_TYPE (exp_type);
12526 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12527 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12528 if ((parm_kind[0] == tgmath_complex && ret != exp_type)
12529 || (parm_kind[0] == tgmath_real && ret != exp_real_type))
12530 {
12531 error_at ((*cexpr_list)[j].get_location (),
12532 "bad return type for function argument %u "
12533 "of %<__builtin_tgmath%>", j + 1);
12534 expr.set_error ();
12535 goto out;
12536 }
12537 argpos = 1;
12538 FOREACH_FUNCTION_ARGS (type, t, iter)
12539 {
12540 if (t == void_type_node)
12541 break;
12542 t = TYPE_MAIN_VARIANT (t);
12543 if ((parm_kind[argpos] == tgmath_complex
12544 && t != exp_type)
12545 || (parm_kind[argpos] == tgmath_real
12546 && t != exp_real_type))
12547 {
12548 error_at ((*cexpr_list)[j].get_location (),
12549 "bad type for argument %u of "
12550 "function argument %u of "
12551 "%<__builtin_tgmath%>", argpos, j + 1);
12552 expr.set_error ();
12553 goto out;
12554 }
12555 argpos++;
12556 }
12557 }
12558
12559 /* The functions listed are a valid set of functions for a
12560 <tgmath.h> macro to select between. Identify the
12561 matching function, if any. First, the argument types
12562 must be combined following <tgmath.h> rules. Integer
12563 types are treated as _Decimal64 if any type-generic
12564 argument is decimal, or if the only alternatives for
12565 type-generic arguments are of decimal types, and are
12566 otherwise treated as _Float32x (or _Complex _Float32x
12567 for complex integer types) if any type-generic argument
12568 has _FloatNx type, otherwise as double (or _Complex
12569 double for complex integer types). After that
12570 adjustment, types are combined following the usual
12571 arithmetic conversions. If the function only accepts
12572 complex arguments, a complex type is produced. */
12573 bool arg_complex = all_complex;
12574 bool arg_binary = all_binary;
12575 bool arg_int_decimal = all_decimal;
12576 bool arg_int_floatnx = false;
12577 bool arg_int_decimalx = false;
12578 for (unsigned int j = 1; j <= nargs; j++)
12579 {
12580 if (parm_kind[j] == tgmath_fixed)
12581 continue;
12582 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12583 tree type = TREE_TYPE (ce->value);
12584 if (!INTEGRAL_TYPE_P (type)
12585 && !SCALAR_FLOAT_TYPE_P (type)
12586 && TREE_CODE (type) != COMPLEX_TYPE)
12587 {
12588 error_at (ce->get_location (),
12589 "invalid type of argument %u of type-generic "
12590 "function", j);
12591 expr.set_error ();
12592 goto out;
12593 }
12594 if (DECIMAL_FLOAT_TYPE_P (type))
12595 {
12596 arg_int_decimal = true;
12597 if (all_complex)
12598 {
12599 error_at (ce->get_location (),
12600 "decimal floating-point argument %u to "
12601 "complex-only type-generic function", j);
12602 expr.set_error ();
12603 goto out;
12604 }
12605 else if (all_binary)
12606 {
12607 error_at (ce->get_location (),
12608 "decimal floating-point argument %u to "
12609 "binary-only type-generic function", j);
12610 expr.set_error ();
12611 goto out;
12612 }
12613 else if (arg_complex)
12614 {
12615 error_at (ce->get_location (),
12616 "both complex and decimal floating-point "
12617 "arguments to type-generic function");
12618 expr.set_error ();
12619 goto out;
12620 }
12621 else if (arg_binary)
12622 {
12623 error_at (ce->get_location (),
12624 "both binary and decimal floating-point "
12625 "arguments to type-generic function");
12626 expr.set_error ();
12627 goto out;
12628 }
12629 }
12630 else if (TREE_CODE (type) == COMPLEX_TYPE)
12631 {
12632 arg_complex = true;
12633 if (COMPLEX_FLOAT_TYPE_P (type))
12634 arg_binary = true;
12635 if (all_decimal)
12636 {
12637 error_at (ce->get_location (),
12638 "complex argument %u to "
12639 "decimal-only type-generic function", j);
12640 expr.set_error ();
12641 goto out;
12642 }
12643 else if (arg_int_decimal)
12644 {
12645 error_at (ce->get_location (),
12646 "both complex and decimal floating-point "
12647 "arguments to type-generic function");
12648 expr.set_error ();
12649 goto out;
12650 }
12651 }
12652 else if (SCALAR_FLOAT_TYPE_P (type))
12653 {
12654 arg_binary = true;
12655 if (all_decimal)
12656 {
12657 error_at (ce->get_location (),
12658 "binary argument %u to "
12659 "decimal-only type-generic function", j);
12660 expr.set_error ();
12661 goto out;
12662 }
12663 else if (arg_int_decimal)
12664 {
12665 error_at (ce->get_location (),
12666 "both binary and decimal floating-point "
12667 "arguments to type-generic function");
12668 expr.set_error ();
12669 goto out;
12670 }
12671 }
12672 tree rtype = TYPE_MAIN_VARIANT (type);
12673 if (TREE_CODE (rtype) == COMPLEX_TYPE)
12674 rtype = TREE_TYPE (rtype);
12675 if (SCALAR_FLOAT_TYPE_P (rtype))
12676 for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
12677 if (rtype == FLOATNX_TYPE_NODE (j))
12678 {
12679 arg_int_floatnx = true;
12680 break;
12681 }
12682 if (rtype == dfloat64x_type_node)
12683 arg_int_decimalx = true;
12684 }
12685 tree arg_real = NULL_TREE;
12686 for (unsigned int j = 1; j <= nargs; j++)
12687 {
12688 if (parm_kind[j] == tgmath_fixed)
12689 continue;
12690 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12691 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
12692 if (TREE_CODE (type) == COMPLEX_TYPE)
12693 type = TREE_TYPE (type);
12694 if (INTEGRAL_TYPE_P (type))
12695 type = (arg_int_decimalx
12696 ? dfloat64x_type_node
12697 : arg_int_floatnx
12698 ? float32x_type_node
12699 : arg_int_decimal
12700 ? dfloat64_type_node
12701 : double_type_node);
12702 if (arg_real == NULL_TREE)
12703 arg_real = type;
12704 else
12705 arg_real = common_type (arg_real, type);
12706 if (arg_real == error_mark_node)
12707 {
12708 expr.set_error ();
12709 goto out;
12710 }
12711 }
12712 tree arg_type = (arg_complex
12713 ? build_complex_type (arg_real)
12714 : arg_real);
12715
12716 /* Look for a function to call with type-generic parameter
12717 type ARG_TYPE. */
12718 c_expr_t *fn = NULL;
12719 for (unsigned int j = 0; j < num_functions; j++)
12720 {
12721 if (tg_type[j] == arg_type)
12722 {
12723 fn = &(*cexpr_list)[j];
12724 break;
12725 }
12726 }
12727 if (fn == NULL
12728 && parm_kind[0] == tgmath_fixed
12729 && SCALAR_FLOAT_TYPE_P (parm_first[0]))
12730 {
12731 /* Presume this is a macro that rounds its result to a
12732 narrower type, and look for the first function with
12733 at least the range and precision of the argument
12734 type. */
12735 for (unsigned int j = 0; j < num_functions; j++)
12736 {
12737 if (arg_complex
12738 != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
12739 continue;
12740 tree real_tg_type = (arg_complex
12741 ? TREE_TYPE (tg_type[j])
12742 : tg_type[j]);
12743 if (DECIMAL_FLOAT_TYPE_P (arg_real)
12744 != DECIMAL_FLOAT_TYPE_P (real_tg_type))
12745 continue;
12746 scalar_float_mode arg_mode
12747 = SCALAR_FLOAT_TYPE_MODE (arg_real);
12748 scalar_float_mode tg_mode
12749 = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
12750 const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
12751 const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
12752 if (arg_fmt->b == tg_fmt->b
12753 && arg_fmt->p <= tg_fmt->p
12754 && arg_fmt->emax <= tg_fmt->emax
12755 && (arg_fmt->emin - arg_fmt->p
12756 >= tg_fmt->emin - tg_fmt->p))
12757 {
12758 fn = &(*cexpr_list)[j];
12759 break;
12760 }
12761 }
12762 }
12763 if (fn == NULL)
12764 {
12765 error_at (loc, "no matching function for type-generic call");
12766 expr.set_error ();
12767 break;
12768 }
12769
12770 /* Construct a call to FN. */
12771 vec<tree, va_gc> *args;
12772 vec_alloc (v&: args, nelems: nargs);
12773 vec<tree, va_gc> *origtypes;
12774 vec_alloc (v&: origtypes, nelems: nargs);
12775 auto_vec<location_t> arg_loc (nargs);
12776 for (unsigned int j = 0; j < nargs; j++)
12777 {
12778 c_expr_t *ce = &(*cexpr_list)[num_functions + j];
12779 args->quick_push (obj: ce->value);
12780 arg_loc.quick_push (obj: ce->get_location ());
12781 origtypes->quick_push (obj: ce->original_type);
12782 }
12783 expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
12784 args, origtypes);
12785 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12786 break;
12787 }
12788 case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
12789 {
12790 vec<c_expr_t, va_gc> *cexpr_list;
12791 c_expr_t *e2_p;
12792 tree chain_value;
12793 location_t close_paren_loc;
12794
12795 c_parser_consume_token (parser);
12796 if (!c_parser_get_builtin_args (parser,
12797 bname: "__builtin_call_with_static_chain",
12798 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12799 out_close_paren_loc: &close_paren_loc))
12800 {
12801 expr.set_error ();
12802 break;
12803 }
12804 if (vec_safe_length (v: cexpr_list) != 2)
12805 {
12806 error_at (loc, "wrong number of arguments to "
12807 "%<__builtin_call_with_static_chain%>");
12808 expr.set_error ();
12809 break;
12810 }
12811
12812 expr = (*cexpr_list)[0];
12813 e2_p = &(*cexpr_list)[1];
12814 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12815 chain_value = e2_p->value;
12816 mark_exp_read (chain_value);
12817
12818 if (TREE_CODE (expr.value) != CALL_EXPR)
12819 error_at (loc, "first argument to "
12820 "%<__builtin_call_with_static_chain%> "
12821 "must be a call expression");
12822 else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
12823 error_at (loc, "second argument to "
12824 "%<__builtin_call_with_static_chain%> "
12825 "must be a pointer type");
12826 else
12827 CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
12828 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12829 break;
12830 }
12831 case RID_BUILTIN_COMPLEX:
12832 {
12833 vec<c_expr_t, va_gc> *cexpr_list;
12834 c_expr_t *e1_p, *e2_p;
12835 location_t close_paren_loc;
12836
12837 c_parser_consume_token (parser);
12838 if (!c_parser_get_builtin_args (parser,
12839 bname: "__builtin_complex",
12840 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12841 out_close_paren_loc: &close_paren_loc))
12842 {
12843 expr.set_error ();
12844 break;
12845 }
12846
12847 if (vec_safe_length (v: cexpr_list) != 2)
12848 {
12849 error_at (loc, "wrong number of arguments to "
12850 "%<__builtin_complex%>");
12851 expr.set_error ();
12852 break;
12853 }
12854
12855 e1_p = &(*cexpr_list)[0];
12856 e2_p = &(*cexpr_list)[1];
12857
12858 *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
12859 if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
12860 e1_p->value = convert (TREE_TYPE (e1_p->value),
12861 TREE_OPERAND (e1_p->value, 0));
12862 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12863 if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
12864 e2_p->value = convert (TREE_TYPE (e2_p->value),
12865 TREE_OPERAND (e2_p->value, 0));
12866 if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12867 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12868 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
12869 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
12870 {
12871 error_at (loc, "%<__builtin_complex%> operand "
12872 "not of real binary floating-point type");
12873 expr.set_error ();
12874 break;
12875 }
12876 if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
12877 != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
12878 {
12879 error_at (loc,
12880 "%<__builtin_complex%> operands of different types");
12881 expr.set_error ();
12882 break;
12883 }
12884 pedwarn_c90 (loc, OPT_Wpedantic,
12885 "ISO C90 does not support complex types");
12886 expr.value = build2_loc (loc, code: COMPLEX_EXPR,
12887 type: build_complex_type
12888 (TYPE_MAIN_VARIANT
12889 (TREE_TYPE (e1_p->value))),
12890 arg0: e1_p->value, arg1: e2_p->value);
12891 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12892 break;
12893 }
12894 case RID_BUILTIN_COUNTED_BY_REF:
12895 {
12896 vec<c_expr_t, va_gc> *cexpr_list;
12897 c_expr_t *e_p;
12898 location_t close_paren_loc;
12899
12900 c_parser_consume_token (parser);
12901 if (!c_parser_get_builtin_args (parser,
12902 bname: "__builtin_counted_by_ref",
12903 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12904 out_close_paren_loc: &close_paren_loc))
12905 {
12906 expr.set_error ();
12907 break;
12908 }
12909 if (vec_safe_length (v: cexpr_list) != 1)
12910 {
12911 error_at (loc, "wrong number of arguments to "
12912 "%<__builtin_counted_by_ref%>");
12913 expr.set_error ();
12914 break;
12915 }
12916
12917 e_p = &(*cexpr_list)[0];
12918 tree ref = e_p->value;
12919
12920 if (TREE_CODE (TREE_TYPE (ref)) != ARRAY_TYPE
12921 && TREE_CODE (TREE_TYPE (ref)) != POINTER_TYPE)
12922 {
12923 error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12924 " must be an array or pointer");
12925 expr.set_error ();
12926 break;
12927 }
12928
12929 if (TREE_CODE (ref) != COMPONENT_REF)
12930 {
12931 error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12932 " must be a field of a structure");
12933 expr.set_error ();
12934 break;
12935 }
12936
12937 /* If the ref is inside TYPEOF or ALIGNOF, the call to
12938 .ACCESS_WITH_SIZE was not generated by the routine
12939 build_component_ref by default, we should generate it here. */
12940 if (TREE_CODE (ref) == COMPONENT_REF)
12941 ref = handle_counted_by_for_component_ref (loc, ref);
12942
12943 if (has_counted_by_object (ref))
12944 expr.value = get_counted_by_ref (ref);
12945 else
12946 expr.value = null_pointer_node;
12947
12948 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12949 break;
12950 }
12951 case RID_BUILTIN_SHUFFLE:
12952 {
12953 vec<c_expr_t, va_gc> *cexpr_list;
12954 unsigned int i;
12955 c_expr_t *p;
12956 location_t close_paren_loc;
12957
12958 c_parser_consume_token (parser);
12959 if (!c_parser_get_builtin_args (parser,
12960 bname: "__builtin_shuffle",
12961 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12962 out_close_paren_loc: &close_paren_loc))
12963 {
12964 expr.set_error ();
12965 break;
12966 }
12967
12968 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12969 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12970
12971 if (vec_safe_length (v: cexpr_list) == 2)
12972 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12973 NULL_TREE,
12974 (*cexpr_list)[1].value);
12975
12976 else if (vec_safe_length (v: cexpr_list) == 3)
12977 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12978 (*cexpr_list)[1].value,
12979 (*cexpr_list)[2].value);
12980 else
12981 {
12982 error_at (loc, "wrong number of arguments to "
12983 "%<__builtin_shuffle%>");
12984 expr.set_error ();
12985 }
12986 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12987 break;
12988 }
12989 case RID_BUILTIN_SHUFFLEVECTOR:
12990 {
12991 vec<c_expr_t, va_gc> *cexpr_list;
12992 unsigned int i;
12993 c_expr_t *p;
12994 location_t close_paren_loc;
12995
12996 c_parser_consume_token (parser);
12997 if (!c_parser_get_builtin_args (parser,
12998 bname: "__builtin_shufflevector",
12999 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
13000 out_close_paren_loc: &close_paren_loc))
13001 {
13002 expr.set_error ();
13003 break;
13004 }
13005
13006 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
13007 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
13008
13009 if (vec_safe_length (v: cexpr_list) < 3)
13010 {
13011 error_at (loc, "wrong number of arguments to "
13012 "%<__builtin_shuffle%>");
13013 expr.set_error ();
13014 }
13015 else
13016 {
13017 auto_vec<tree, 16> mask;
13018 for (i = 2; i < cexpr_list->length (); ++i)
13019 mask.safe_push (obj: (*cexpr_list)[i].value);
13020 expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
13021 (*cexpr_list)[1].value,
13022 mask);
13023 }
13024 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
13025 break;
13026 }
13027 case RID_BUILTIN_CONVERTVECTOR:
13028 {
13029 location_t start_loc = loc;
13030 c_parser_consume_token (parser);
13031 matching_parens parens;
13032 if (!parens.require_open (parser))
13033 {
13034 expr.set_error ();
13035 break;
13036 }
13037 e1 = c_parser_expr_no_commas (parser, NULL);
13038 mark_exp_read (e1.value);
13039 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
13040 {
13041 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13042 expr.set_error ();
13043 break;
13044 }
13045 loc = c_parser_peek_token (parser)->location;
13046 t1 = c_parser_type_name (parser);
13047 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
13048 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
13049 msgid: "expected %<)%>");
13050 if (t1 == NULL)
13051 expr.set_error ();
13052 else
13053 {
13054 tree type_expr = NULL_TREE;
13055 expr.value = c_build_vec_convert (start_loc, e1.value, loc,
13056 groktypename (t1, &type_expr,
13057 NULL));
13058 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
13059 }
13060 }
13061 break;
13062 case RID_BUILTIN_ASSOC_BARRIER:
13063 {
13064 location_t start_loc = loc;
13065 c_parser_consume_token (parser);
13066 matching_parens parens;
13067 if (!parens.require_open (parser))
13068 {
13069 expr.set_error ();
13070 break;
13071 }
13072 e1 = c_parser_expr_no_commas (parser, NULL);
13073 mark_exp_read (e1.value);
13074 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
13075 parens.skip_until_found_close (parser);
13076 expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
13077 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
13078 }
13079 break;
13080 case RID_BUILTIN_STDC:
13081 {
13082 vec<c_expr_t, va_gc> *cexpr_list;
13083 c_expr_t *arg_p;
13084 location_t close_paren_loc;
13085 enum c_builtin_stdc {
13086 C_BUILTIN_STDC_BIT_CEIL,
13087 C_BUILTIN_STDC_BIT_FLOOR,
13088 C_BUILTIN_STDC_BIT_WIDTH,
13089 C_BUILTIN_STDC_COUNT_ONES,
13090 C_BUILTIN_STDC_COUNT_ZEROS,
13091 C_BUILTIN_STDC_FIRST_LEADING_ONE,
13092 C_BUILTIN_STDC_FIRST_LEADING_ZERO,
13093 C_BUILTIN_STDC_FIRST_TRAILING_ONE,
13094 C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
13095 C_BUILTIN_STDC_HAS_SINGLE_BIT,
13096 C_BUILTIN_STDC_LEADING_ONES,
13097 C_BUILTIN_STDC_LEADING_ZEROS,
13098 C_BUILTIN_STDC_ROTATE_LEFT,
13099 C_BUILTIN_STDC_ROTATE_RIGHT,
13100 C_BUILTIN_STDC_TRAILING_ONES,
13101 C_BUILTIN_STDC_TRAILING_ZEROS,
13102 C_BUILTIN_STDC_MAX
13103 } stdc_rid = C_BUILTIN_STDC_MAX;
13104 const char *name
13105 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
13106 unsigned num_args = 1;
13107 switch (name[sizeof ("__builtin_stdc_") - 1])
13108 {
13109 case 'b':
13110 switch (name[sizeof ("__builtin_stdc_bit_") - 1])
13111 {
13112 case 'c':
13113 stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
13114 break;
13115 case 'f':
13116 stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
13117 break;
13118 default:
13119 stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
13120 break;
13121 }
13122 break;
13123 case 'c':
13124 if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
13125 stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
13126 else
13127 stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
13128 break;
13129 case 'f':
13130 switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
13131 {
13132 case 'n':
13133 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
13134 break;
13135 case 'e':
13136 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
13137 break;
13138 case 'o':
13139 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
13140 break;
13141 default:
13142 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
13143 break;
13144 }
13145 break;
13146 case 'h':
13147 stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
13148 break;
13149 case 'l':
13150 if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
13151 stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
13152 else
13153 stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
13154 break;
13155 case 'r':
13156 if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l')
13157 stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT;
13158 else
13159 stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT;
13160 num_args = 2;
13161 break;
13162 case 't':
13163 if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
13164 stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
13165 else
13166 stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
13167 break;
13168 }
13169 gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
13170
13171 c_parser_consume_token (parser);
13172 if (!c_parser_get_builtin_args (parser, bname: name,
13173 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
13174 out_close_paren_loc: &close_paren_loc))
13175 {
13176 expr.set_error ();
13177 break;
13178 }
13179
13180 if (vec_safe_length (v: cexpr_list) != num_args)
13181 {
13182 error_at (loc, "wrong number of arguments to %qs", name);
13183 expr.set_error ();
13184 break;
13185 }
13186
13187 arg_p = &(*cexpr_list)[0];
13188 *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13189 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13190 {
13191 error_at (loc, "%qs operand not an integral type", name);
13192 expr.set_error ();
13193 break;
13194 }
13195 if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13196 {
13197 error_at (loc, "argument %u in call to function "
13198 "%qs has enumerated type", 1, name);
13199 expr.set_error ();
13200 break;
13201 }
13202 if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
13203 {
13204 error_at (loc, "argument %u in call to function "
13205 "%qs has boolean type", 1, name);
13206 expr.set_error ();
13207 break;
13208 }
13209 if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
13210 {
13211 error_at (loc, "argument 1 in call to function "
13212 "%qs has signed type", name);
13213 expr.set_error ();
13214 break;
13215 }
13216 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
13217 == char_type_node)
13218 {
13219 error_at (loc, "argument 1 in call to function "
13220 "%qs has %<char%> type", name);
13221 expr.set_error ();
13222 break;
13223 }
13224 tree arg = arg_p->value;
13225 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
13226 /* Expand:
13227 __builtin_stdc_leading_zeros (arg) as
13228 (unsigned int) __builtin_clzg (arg, prec)
13229 __builtin_stdc_leading_ones (arg) as
13230 (unsigned int) __builtin_clzg ((type) ~arg, prec)
13231 __builtin_stdc_trailing_zeros (arg) as
13232 (unsigned int) __builtin_ctzg (arg, prec)
13233 __builtin_stdc_trailing_ones (arg) as
13234 (unsigned int) __builtin_ctzg ((type) ~arg, prec)
13235 __builtin_stdc_first_leading_zero (arg) as
13236 __builtin_clzg ((type) ~arg, -1) + 1U
13237 __builtin_stdc_first_leading_one (arg) as
13238 __builtin_clzg (arg, -1) + 1U
13239 __builtin_stdc_first_trailing_zero (arg) as
13240 __builtin_ctzg ((type) ~arg, -1) + 1U
13241 __builtin_stdc_first_trailing_one (arg) as
13242 __builtin_ctzg (arg, -1) + 1U
13243 __builtin_stdc_count_zeros (arg) as
13244 (unsigned int) __builtin_popcountg ((type) ~arg)
13245 __builtin_stdc_count_ones (arg) as
13246 (unsigned int) __builtin_popcountg (arg)
13247 __builtin_stdc_has_single_bit (arg) as
13248 (_Bool) (__builtin_popcountg (arg) == 1)
13249 __builtin_stdc_bit_width (arg) as
13250 (unsigned int) (prec - __builtin_clzg (arg, prec))
13251 __builtin_stdc_bit_floor (arg) as
13252 arg == 0 ? (type) 0
13253 : (type) 1 << (prec - 1 - __builtin_clzg (arg))
13254 __builtin_stdc_bit_ceil (arg) as
13255 arg <= 1 ? (type) 1
13256 : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
13257 without evaluating arg multiple times, type being
13258 __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
13259 int prec = TYPE_PRECISION (type);
13260 if (num_args == 2)
13261 {
13262 /* Expand:
13263 __builtin_stdc_rotate_left (arg1, arg2) as
13264 arg1 r<< (arg2 % prec)
13265 __builtin_stdc_rotate_right (arg1, arg2) as
13266 arg1 r>> (arg2 % prec). */
13267 arg_p = &(*cexpr_list)[1];
13268 *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13269 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13270 {
13271 error_at (loc, "%qs operand not an integral type", name);
13272 expr.set_error ();
13273 break;
13274 }
13275 if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13276 {
13277 error_at (loc, "argument %u in call to function "
13278 "%qs has enumerated type", 2, name);
13279 expr.set_error ();
13280 break;
13281 }
13282 tree arg1 = save_expr (arg);
13283 tree arg2 = save_expr (arg_p->value);
13284 tree_code code;
13285 if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT)
13286 code = LROTATE_EXPR;
13287 else
13288 code = RROTATE_EXPR;
13289
13290 if (TREE_CODE (arg2) == INTEGER_CST
13291 && tree_int_cst_sgn (arg2) < 0)
13292 warning_at (loc, OPT_Wshift_count_negative,
13293 "rotate count is negative");
13294
13295 tree instrument_expr = NULL_TREE;
13296 if (sanitize_flags_p (flag: SANITIZE_SHIFT))
13297 instrument_expr = ubsan_instrument_shift (loc, code,
13298 arg1, arg2);
13299
13300 /* Promote arg2 to unsigned just so that we don't
13301 need to deal with arg2 type not being able to represent
13302 prec. In the end gimplification uses unsigned int
13303 for all shifts/rotates anyway. */
13304 if (TYPE_PRECISION (TREE_TYPE (arg2))
13305 < TYPE_PRECISION (integer_type_node))
13306 arg2 = fold_convert (unsigned_type_node, arg2);
13307
13308 if (TYPE_UNSIGNED (TREE_TYPE (arg2)))
13309 arg2 = build2_loc (loc, code: TRUNC_MOD_EXPR, TREE_TYPE (arg2),
13310 arg0: arg2, arg1: build_int_cst (TREE_TYPE (arg2),
13311 prec));
13312 else
13313 {
13314 /* When second argument is signed, just do the modulo in
13315 unsigned type, that results in better generated code
13316 (for power of 2 precisions bitwise AND). */
13317 tree utype = c_common_unsigned_type (TREE_TYPE (arg2));
13318 arg2 = build2_loc (loc, code: TRUNC_MOD_EXPR, type: utype,
13319 fold_convert (utype, arg2),
13320 arg1: build_int_cst (utype, prec));
13321 }
13322
13323 /* The middle-end isn't prepared to handle {L,R}ROTATE_EXPR
13324 on types without mode precision, except for large/huge
13325 _BitInt types. */
13326 if (type_has_mode_precision_p (TREE_TYPE (arg1))
13327 || (TREE_CODE (TREE_TYPE (arg1)) == BITINT_TYPE
13328 && prec > MAX_FIXED_MODE_SIZE))
13329 expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg0: arg1,
13330 arg1: arg2);
13331 else
13332 {
13333 arg2 = save_expr (arg2);
13334 tree t1 = build2_loc (loc, code: (code == LROTATE_EXPR
13335 ? LSHIFT_EXPR : RSHIFT_EXPR),
13336 TREE_TYPE (arg1), arg0: arg1, arg1: arg2);
13337 tree t2 = build2_loc (loc, code: MINUS_EXPR,
13338 TREE_TYPE (arg2),
13339 arg0: build_int_cst (TREE_TYPE (arg2),
13340 prec), arg1: arg2);
13341 t2 = build2_loc (loc, code: (code == LROTATE_EXPR
13342 ? RSHIFT_EXPR : LSHIFT_EXPR),
13343 TREE_TYPE (arg1), arg0: arg1, arg1: t2);
13344 suppress_warning (t2, OPT_Wshift_count_overflow);
13345 tree t3 = build2_loc (loc, code: BIT_IOR_EXPR,
13346 TREE_TYPE (arg1), arg0: t1, arg1: t2);
13347 tree t4 = build2_loc (loc, code: NE_EXPR, boolean_type_node,
13348 arg0: arg2,
13349 arg1: build_zero_cst (TREE_TYPE (arg2)));
13350 t4 = build2_loc (loc, code: COMPOUND_EXPR, boolean_type_node,
13351 arg0: arg1, arg1: t4);
13352 expr.value = build3_loc (loc, code: COND_EXPR,
13353 TREE_TYPE (arg1), arg0: t4, arg1: t3, arg2: arg1);
13354 }
13355 if (instrument_expr)
13356 expr.value = build2_loc (loc, code: COMPOUND_EXPR,
13357 TREE_TYPE (expr.value),
13358 arg0: instrument_expr, arg1: expr.value);
13359 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
13360 break;
13361 }
13362 tree barg1 = arg;
13363 switch (stdc_rid)
13364 {
13365 case C_BUILTIN_STDC_BIT_CEIL:
13366 arg = save_expr (arg);
13367 barg1 = build2_loc (loc, code: PLUS_EXPR, type, arg0: arg,
13368 arg1: build_int_cst (type, -1));
13369 break;
13370 case C_BUILTIN_STDC_BIT_FLOOR:
13371 barg1 = arg = save_expr (arg);
13372 break;
13373 case C_BUILTIN_STDC_COUNT_ZEROS:
13374 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13375 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13376 case C_BUILTIN_STDC_LEADING_ONES:
13377 case C_BUILTIN_STDC_TRAILING_ONES:
13378 barg1 = build1_loc (loc, code: BIT_NOT_EXPR, type, arg1: arg);
13379 break;
13380 default:
13381 break;
13382 }
13383 tree barg2 = NULL_TREE;
13384 switch (stdc_rid)
13385 {
13386 case C_BUILTIN_STDC_BIT_WIDTH:
13387 case C_BUILTIN_STDC_LEADING_ONES:
13388 case C_BUILTIN_STDC_LEADING_ZEROS:
13389 case C_BUILTIN_STDC_TRAILING_ONES:
13390 case C_BUILTIN_STDC_TRAILING_ZEROS:
13391 barg2 = build_int_cst (integer_type_node, prec);
13392 break;
13393 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13394 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13395 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13396 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13397 barg2 = integer_minus_one_node;
13398 break;
13399 default:
13400 break;
13401 }
13402 tree fndecl = NULL_TREE;
13403 switch (stdc_rid)
13404 {
13405 case C_BUILTIN_STDC_BIT_CEIL:
13406 case C_BUILTIN_STDC_BIT_FLOOR:
13407 case C_BUILTIN_STDC_BIT_WIDTH:
13408 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13409 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13410 case C_BUILTIN_STDC_LEADING_ONES:
13411 case C_BUILTIN_STDC_LEADING_ZEROS:
13412 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CLZG);
13413 break;
13414 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13415 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13416 case C_BUILTIN_STDC_TRAILING_ONES:
13417 case C_BUILTIN_STDC_TRAILING_ZEROS:
13418 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CTZG);
13419 break;
13420 case C_BUILTIN_STDC_COUNT_ONES:
13421 case C_BUILTIN_STDC_COUNT_ZEROS:
13422 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13423 fndecl = builtin_decl_explicit (fncode: BUILT_IN_POPCOUNTG);
13424 break;
13425 default:
13426 gcc_unreachable ();
13427 }
13428 /* Construct a call to __builtin_{clz,ctz,popcount}g. */
13429 int nargs = barg2 != NULL_TREE ? 2 : 1;
13430 vec<tree, va_gc> *args;
13431 vec_alloc (v&: args, nelems: nargs);
13432 vec<tree, va_gc> *origtypes;
13433 vec_alloc (v&: origtypes, nelems: nargs);
13434 auto_vec<location_t> arg_loc (nargs);
13435 args->quick_push (obj: barg1);
13436 arg_loc.quick_push (obj: arg_p->get_location ());
13437 origtypes->quick_push (obj: arg_p->original_type);
13438 if (nargs == 2)
13439 {
13440 args->quick_push (obj: barg2);
13441 arg_loc.quick_push (obj: loc);
13442 origtypes->quick_push (integer_type_node);
13443 }
13444 expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
13445 args, origtypes);
13446 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
13447 if (expr.value == error_mark_node)
13448 break;
13449 switch (stdc_rid)
13450 {
13451 case C_BUILTIN_STDC_BIT_CEIL:
13452 case C_BUILTIN_STDC_BIT_FLOOR:
13453 --prec;
13454 /* FALLTHRU */
13455 case C_BUILTIN_STDC_BIT_WIDTH:
13456 expr.value = build2_loc (loc, code: MINUS_EXPR, integer_type_node,
13457 arg0: build_int_cst (integer_type_node,
13458 prec), arg1: expr.value);
13459 break;
13460 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13461 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13462 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13463 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13464 expr.value = build2_loc (loc, code: PLUS_EXPR, integer_type_node,
13465 arg0: expr.value, integer_one_node);
13466 break;
13467 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13468 expr.value = build2_loc (loc, code: EQ_EXPR, boolean_type_node,
13469 arg0: expr.value, integer_one_node);
13470 break;
13471 default:
13472 break;
13473 }
13474
13475 if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
13476 && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
13477 {
13478 if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
13479 expr.value = fold_convert_loc (loc, unsigned_type_node,
13480 expr.value);
13481 break;
13482 }
13483 /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
13484 or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
13485 warnings. The LSHIFT_EXPR is in dead code in that case. */
13486 if (integer_zerop (arg)
13487 || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
13488 expr.value = build_int_cst (type, 0);
13489 else
13490 expr.value
13491 = build2_loc (loc, code: LSHIFT_EXPR, type,
13492 arg0: build_int_cst (type,
13493 (stdc_rid
13494 == C_BUILTIN_STDC_BIT_CEIL
13495 ? 2 : 1)), arg1: expr.value);
13496 if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
13497 expr.value = build3_loc (loc, code: COND_EXPR, type,
13498 arg0: build2_loc (loc, code: LE_EXPR,
13499 boolean_type_node, arg0: arg,
13500 arg1: build_int_cst (type, 1)),
13501 arg1: build_int_cst (type, 1),
13502 arg2: expr.value);
13503 else
13504 expr.value = build3_loc (loc, code: COND_EXPR, type,
13505 arg0: build2_loc (loc, code: EQ_EXPR,
13506 boolean_type_node, arg0: arg,
13507 arg1: build_int_cst (type, 0)),
13508 arg1: build_int_cst (type, 0),
13509 arg2: expr.value);
13510 break;
13511 }
13512 case RID_AT_SELECTOR:
13513 {
13514 gcc_assert (c_dialect_objc ());
13515 c_parser_consume_token (parser);
13516 matching_parens parens;
13517 if (!parens.require_open (parser))
13518 {
13519 expr.set_error ();
13520 break;
13521 }
13522 tree sel = c_parser_objc_selector_arg (parser);
13523 location_t close_loc = c_parser_peek_token (parser)->location;
13524 parens.skip_until_found_close (parser);
13525 expr.value = objc_build_selector_expr (loc, sel);
13526 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13527 }
13528 break;
13529 case RID_AT_PROTOCOL:
13530 {
13531 gcc_assert (c_dialect_objc ());
13532 c_parser_consume_token (parser);
13533 matching_parens parens;
13534 if (!parens.require_open (parser))
13535 {
13536 expr.set_error ();
13537 break;
13538 }
13539 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13540 {
13541 c_parser_error (parser, gmsgid: "expected identifier");
13542 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13543 expr.set_error ();
13544 break;
13545 }
13546 tree id = c_parser_peek_token (parser)->value;
13547 c_parser_consume_token (parser);
13548 location_t close_loc = c_parser_peek_token (parser)->location;
13549 parens.skip_until_found_close (parser);
13550 expr.value = objc_build_protocol_expr (id);
13551 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13552 }
13553 break;
13554 case RID_AT_ENCODE:
13555 {
13556 /* Extension to support C-structures in the archiver. */
13557 gcc_assert (c_dialect_objc ());
13558 c_parser_consume_token (parser);
13559 matching_parens parens;
13560 if (!parens.require_open (parser))
13561 {
13562 expr.set_error ();
13563 break;
13564 }
13565 t1 = c_parser_type_name (parser);
13566 if (t1 == NULL)
13567 {
13568 expr.set_error ();
13569 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13570 break;
13571 }
13572 location_t close_loc = c_parser_peek_token (parser)->location;
13573 parens.skip_until_found_close (parser);
13574 tree type = groktypename (t1, NULL, NULL);
13575 expr.value = objc_build_encode_expr (type);
13576 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13577 }
13578 break;
13579 case RID_GENERIC:
13580 expr = c_parser_generic_selection (parser);
13581 break;
13582 case RID_OMP_ALL_MEMORY:
13583 gcc_assert (flag_openmp);
13584 c_parser_consume_token (parser);
13585 error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
13586 "%<depend%> clause");
13587 expr.set_error ();
13588 break;
13589 /* C23 'nullptr' literal. */
13590 case RID_NULLPTR:
13591 c_parser_consume_token (parser);
13592 expr.value = nullptr_node;
13593 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13594 pedwarn_c11 (loc, OPT_Wpedantic,
13595 "ISO C does not support %qs before C23", "nullptr");
13596 break;
13597 case RID_TRUE:
13598 c_parser_consume_token (parser);
13599 expr.value = boolean_true_node;
13600 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13601 break;
13602 case RID_FALSE:
13603 c_parser_consume_token (parser);
13604 expr.value = boolean_false_node;
13605 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13606 break;
13607 default:
13608 c_parser_error (parser, gmsgid: "expected expression");
13609 expr.set_error ();
13610 break;
13611 }
13612 break;
13613 case CPP_OPEN_SQUARE:
13614 if (c_dialect_objc ())
13615 {
13616 tree receiver, args;
13617 c_parser_consume_token (parser);
13618 receiver = c_parser_objc_receiver (parser);
13619 args = c_parser_objc_message_args (parser);
13620 location_t close_loc = c_parser_peek_token (parser)->location;
13621 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
13622 msgid: "expected %<]%>");
13623 expr.value = objc_build_message_expr (receiver, args);
13624 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13625 break;
13626 }
13627 /* Else fall through to report error. */
13628 /* FALLTHRU */
13629 default:
13630 c_parser_error (parser, gmsgid: "expected expression");
13631 expr.set_error ();
13632 break;
13633 }
13634 out:
13635 return c_parser_postfix_expression_after_primary
13636 (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
13637}
13638
13639/* Parse a postfix expression after a parenthesized type name: the
13640 brace-enclosed initializer of a compound literal, possibly followed
13641 by some postfix operators. This is separate because it is not
13642 possible to tell until after the type name whether a cast
13643 expression has a cast or a compound literal, or whether the operand
13644 of sizeof is a parenthesized type name or starts with a compound
13645 literal. TYPE_LOC is the location where TYPE_NAME starts--the
13646 location of the first token after the parentheses around the type
13647 name. */
13648
13649static struct c_expr
13650c_parser_postfix_expression_after_paren_type (c_parser *parser,
13651 struct c_declspecs *scspecs,
13652 struct c_type_name *type_name,
13653 location_t type_loc)
13654{
13655 tree type;
13656 struct c_expr init;
13657 bool non_const;
13658 struct c_expr expr;
13659 location_t start_loc;
13660 tree type_expr = NULL_TREE;
13661 bool type_expr_const = true;
13662 bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
13663 unsigned int underspec_state = 0;
13664 check_compound_literal_type (type_loc, type_name);
13665 rich_location richloc (line_table, type_loc);
13666 start_loc = c_parser_peek_token (parser)->location;
13667 if (constexpr_p)
13668 {
13669 underspec_state = start_underspecified_init (start_loc, NULL_TREE);
13670 /* A constexpr compound literal is subject to the constraints on
13671 underspecified declarations, which may not declare tags or
13672 members or structures or unions; it is undefined behavior to
13673 declare the members of an enumeration. Where the structure,
13674 union or enumeration type is declared within the compound
13675 literal initializer, this is diagnosed elsewhere as a result
13676 of the above call to start_underspecified_init. Diagnose
13677 here the case of declaring such a type in the type specifiers
13678 of the compound literal. */
13679 switch (type_name->specs->typespec_kind)
13680 {
13681 case ctsk_tagfirstref:
13682 case ctsk_tagfirstref_attrs:
13683 error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
13684 type_name->specs->type);
13685 break;
13686
13687 case ctsk_tagdef:
13688 error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
13689 type_name->specs->type);
13690 break;
13691
13692 default:
13693 break;
13694 }
13695 }
13696 start_init (NULL_TREE, NULL,
13697 (global_bindings_p ()
13698 || (scspecs && scspecs->storage_class == csc_static)
13699 || constexpr_p), constexpr_p, &richloc);
13700 type = groktypename (type_name, &type_expr, &type_expr_const);
13701 bool varsize_p = false;
13702 if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
13703 {
13704 pedwarn (type_loc, OPT_Wpedantic, "compound literal has variable size");
13705 varsize_p = true;
13706 }
13707 else if (TREE_CODE (type) == FUNCTION_TYPE)
13708 {
13709 error_at (type_loc, "compound literal has function type");
13710 type = error_mark_node;
13711 }
13712 if (constexpr_p && type != error_mark_node)
13713 {
13714 tree type_no_array = strip_array_types (type);
13715 /* The type of a constexpr object must not be variably modified
13716 (which applies to all compound literals), volatile, atomic or
13717 restrict qualified or have a member with such a qualifier.
13718 const qualification is implicitly added. */
13719 if (TYPE_QUALS (type_no_array)
13720 & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
13721 error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
13722 else if (RECORD_OR_UNION_TYPE_P (type_no_array)
13723 && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
13724 error_at (type_loc, "invalid qualifiers for field of "
13725 "%<constexpr%> object");
13726 type = c_build_qualified_type (type,
13727 (TYPE_QUALS (type_no_array)
13728 | TYPE_QUAL_CONST));
13729 }
13730 init = c_parser_braced_init (parser, type, nested_p: false, NULL, varsize_p);
13731 if (constexpr_p)
13732 finish_underspecified_init (NULL_TREE, underspec_state);
13733 finish_init ();
13734 maybe_warn_string_init (type_loc, type, init);
13735
13736 if (type != error_mark_node
13737 && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
13738 && current_function_decl)
13739 {
13740 error ("compound literal qualified by address-space qualifier");
13741 type = error_mark_node;
13742 }
13743
13744 if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
13745 "ISO C90 forbids compound literals") && scspecs)
13746 pedwarn_c11 (start_loc, OPT_Wpedantic,
13747 "ISO C forbids storage class specifiers in compound literals "
13748 "before C23");
13749 non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
13750 ? CONSTRUCTOR_NON_CONST (init.value)
13751 : init.original_code == C_MAYBE_CONST_EXPR);
13752 non_const |= !type_expr_const;
13753 unsigned int alignas_align = 0;
13754 if (type != error_mark_node
13755 && type_name->specs->align_log != -1)
13756 {
13757 alignas_align = 1U << type_name->specs->align_log;
13758 if (alignas_align < min_align_of_type (type))
13759 {
13760 error_at (type_name->specs->locations[cdw_alignas],
13761 "%<_Alignas%> specifiers cannot reduce "
13762 "alignment of compound literal");
13763 alignas_align = 0;
13764 }
13765 }
13766 expr.value = build_compound_literal (start_loc, type, init.value, non_const,
13767 alignas_align, scspecs);
13768 set_c_expr_source_range (expr: &expr, src_range: init.src_range);
13769 expr.m_decimal = 0;
13770 expr.original_code = ERROR_MARK;
13771 expr.original_type = NULL;
13772 if (type != error_mark_node
13773 && expr.value != error_mark_node
13774 && type_expr)
13775 {
13776 if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
13777 {
13778 gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
13779 C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
13780 }
13781 else
13782 {
13783 gcc_assert (!non_const);
13784 expr.value = build2 (C_MAYBE_CONST_EXPR, type,
13785 type_expr, expr.value);
13786 }
13787 }
13788 return c_parser_postfix_expression_after_primary (parser, loc: start_loc, expr);
13789}
13790
13791/* Callback function for sizeof_pointer_memaccess_warning to compare
13792 types. */
13793
13794static bool
13795sizeof_ptr_memacc_comptypes (tree type1, tree type2)
13796{
13797 return comptypes (type1, type2) == 1;
13798}
13799
13800/* Warn for patterns where abs-like function appears to be used incorrectly,
13801 gracefully ignore any non-abs-like function. The warning location should
13802 be LOC. FNDECL is the declaration of called function, it must be a
13803 BUILT_IN_NORMAL function. ARG is the first and only argument of the
13804 call. */
13805
13806static void
13807warn_for_abs (location_t loc, tree fndecl, tree arg)
13808{
13809 /* Avoid warning in unreachable subexpressions. */
13810 if (c_inhibit_evaluation_warnings)
13811 return;
13812
13813 tree atype = TREE_TYPE (arg);
13814
13815 /* Casts from pointers (and thus arrays and fndecls) will generate
13816 -Wint-conversion warnings. Most other wrong types hopefully lead to type
13817 mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
13818 types and possibly other exotic types. */
13819 if (!INTEGRAL_TYPE_P (atype)
13820 && !SCALAR_FLOAT_TYPE_P (atype)
13821 && TREE_CODE (atype) != COMPLEX_TYPE)
13822 return;
13823
13824 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
13825
13826 switch (fcode)
13827 {
13828 case BUILT_IN_ABS:
13829 case BUILT_IN_LABS:
13830 case BUILT_IN_LLABS:
13831 case BUILT_IN_IMAXABS:
13832 if (!INTEGRAL_TYPE_P (atype))
13833 {
13834 if (SCALAR_FLOAT_TYPE_P (atype))
13835 warning_at (loc, OPT_Wabsolute_value,
13836 "using integer absolute value function %qD when "
13837 "argument is of floating-point type %qT",
13838 fndecl, atype);
13839 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13840 warning_at (loc, OPT_Wabsolute_value,
13841 "using integer absolute value function %qD when "
13842 "argument is of complex type %qT", fndecl, atype);
13843 else
13844 gcc_unreachable ();
13845 return;
13846 }
13847 if (TYPE_UNSIGNED (atype))
13848 warning_at (loc, OPT_Wabsolute_value,
13849 "taking the absolute value of unsigned type %qT "
13850 "has no effect", atype);
13851 break;
13852
13853 CASE_FLT_FN (BUILT_IN_FABS):
13854 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
13855 if (!SCALAR_FLOAT_TYPE_P (atype)
13856 || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
13857 {
13858 if (INTEGRAL_TYPE_P (atype))
13859 warning_at (loc, OPT_Wabsolute_value,
13860 "using floating-point absolute value function %qD "
13861 "when argument is of integer type %qT", fndecl, atype);
13862 else if (DECIMAL_FLOAT_TYPE_P (atype))
13863 warning_at (loc, OPT_Wabsolute_value,
13864 "using floating-point absolute value function %qD "
13865 "when argument is of decimal floating-point type %qT",
13866 fndecl, atype);
13867 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13868 warning_at (loc, OPT_Wabsolute_value,
13869 "using floating-point absolute value function %qD when "
13870 "argument is of complex type %qT", fndecl, atype);
13871 else
13872 gcc_unreachable ();
13873 return;
13874 }
13875 break;
13876
13877 CASE_FLT_FN (BUILT_IN_CABS):
13878 if (TREE_CODE (atype) != COMPLEX_TYPE)
13879 {
13880 if (INTEGRAL_TYPE_P (atype))
13881 warning_at (loc, OPT_Wabsolute_value,
13882 "using complex absolute value function %qD when "
13883 "argument is of integer type %qT", fndecl, atype);
13884 else if (SCALAR_FLOAT_TYPE_P (atype))
13885 warning_at (loc, OPT_Wabsolute_value,
13886 "using complex absolute value function %qD when "
13887 "argument is of floating-point type %qT",
13888 fndecl, atype);
13889 else
13890 gcc_unreachable ();
13891
13892 return;
13893 }
13894 break;
13895
13896 case BUILT_IN_FABSD32:
13897 case BUILT_IN_FABSD64:
13898 case BUILT_IN_FABSD128:
13899 case BUILT_IN_FABSD64X:
13900 if (!DECIMAL_FLOAT_TYPE_P (atype))
13901 {
13902 if (INTEGRAL_TYPE_P (atype))
13903 warning_at (loc, OPT_Wabsolute_value,
13904 "using decimal floating-point absolute value "
13905 "function %qD when argument is of integer type %qT",
13906 fndecl, atype);
13907 else if (SCALAR_FLOAT_TYPE_P (atype))
13908 warning_at (loc, OPT_Wabsolute_value,
13909 "using decimal floating-point absolute value "
13910 "function %qD when argument is of floating-point "
13911 "type %qT", fndecl, atype);
13912 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13913 warning_at (loc, OPT_Wabsolute_value,
13914 "using decimal floating-point absolute value "
13915 "function %qD when argument is of complex type %qT",
13916 fndecl, atype);
13917 else
13918 gcc_unreachable ();
13919 return;
13920 }
13921 break;
13922
13923 default:
13924 return;
13925 }
13926
13927 if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13928 return;
13929
13930 tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13931 if (TREE_CODE (atype) == COMPLEX_TYPE)
13932 {
13933 gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
13934 atype = TREE_TYPE (atype);
13935 ftype = TREE_TYPE (ftype);
13936 }
13937
13938 if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
13939 warning_at (loc, OPT_Wabsolute_value,
13940 "absolute value function %qD given an argument of type %qT "
13941 "but has parameter of type %qT which may cause truncation "
13942 "of value", fndecl, atype, ftype);
13943}
13944
13945
13946/* Parse a postfix expression after the initial primary or compound
13947 literal; that is, parse a series of postfix operators.
13948
13949 EXPR_LOC is the location of the primary expression. */
13950
13951static struct c_expr
13952c_parser_postfix_expression_after_primary (c_parser *parser,
13953 location_t expr_loc,
13954 struct c_expr expr)
13955{
13956 struct c_expr orig_expr;
13957 tree ident, idx, len;
13958 location_t sizeof_arg_loc[6], comp_loc;
13959 tree sizeof_arg[6];
13960 unsigned int literal_zero_mask;
13961 unsigned int i;
13962 vec<tree, va_gc> *exprlist;
13963 vec<tree, va_gc> *origtypes = NULL;
13964 vec<location_t> arg_loc = vNULL;
13965 location_t start;
13966 location_t finish;
13967
13968 while (true)
13969 {
13970 location_t op_loc = c_parser_peek_token (parser)->location;
13971 switch (c_parser_peek_token (parser)->type)
13972 {
13973 case CPP_OPEN_SQUARE:
13974 /* Array reference. */
13975 c_parser_consume_token (parser);
13976 idx = len = NULL_TREE;
13977 if (!c_omp_array_section_p
13978 || c_parser_next_token_is_not (parser, type: CPP_COLON))
13979 idx = c_parser_expression (parser).value;
13980
13981 if (c_omp_array_section_p
13982 && c_parser_next_token_is (parser, type: CPP_COLON))
13983 {
13984 c_parser_consume_token (parser);
13985 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_SQUARE))
13986 len = c_parser_expression (parser).value;
13987
13988 expr.value = build_omp_array_section (op_loc, expr.value, idx,
13989 len);
13990 }
13991 else
13992 expr.value = build_array_ref (op_loc, expr.value, idx);
13993
13994 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
13995 msgid: "expected %<]%>");
13996
13997 start = expr.get_start ();
13998 finish = parser->tokens_buf[0].location;
13999 set_c_expr_source_range (expr: &expr, start, finish);
14000 expr.original_code = ERROR_MARK;
14001 expr.original_type = NULL;
14002 expr.m_decimal = 0;
14003 break;
14004 case CPP_OPEN_PAREN:
14005 /* Function call. */
14006 {
14007 matching_parens parens;
14008 parens.consume_open (parser);
14009 for (i = 0; i < 6; i++)
14010 {
14011 sizeof_arg[i] = NULL_TREE;
14012 sizeof_arg_loc[i] = UNKNOWN_LOCATION;
14013 }
14014 literal_zero_mask = 0;
14015 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
14016 exprlist = NULL;
14017 else if (TREE_CODE (expr.value) == FUNCTION_DECL
14018 && fndecl_built_in_p (node: expr.value, name1: BUILT_IN_CLASSIFY_TYPE)
14019 && c_parser_next_tokens_start_typename (parser,
14020 la: cla_prefer_id))
14021 {
14022 /* __builtin_classify_type (type) */
14023 c_inhibit_evaluation_warnings++;
14024 in_alignof++;
14025 struct c_type_name *type = c_parser_type_name (parser);
14026 c_inhibit_evaluation_warnings--;
14027 in_alignof--;
14028 struct c_typespec ret;
14029 ret.expr = NULL_TREE;
14030 ret.spec = error_mark_node;
14031 ret.expr_const_operands = false;
14032 if (type != NULL)
14033 ret.spec = groktypename (type, &ret.expr,
14034 &ret.expr_const_operands);
14035 parens.skip_until_found_close (parser);
14036 expr.value = build_int_cst (integer_type_node,
14037 type_to_class (ret.spec));
14038 break;
14039 }
14040 else
14041 exprlist = c_parser_expr_list (parser, true, false, &origtypes,
14042 sizeof_arg_loc, sizeof_arg,
14043 &arg_loc, &literal_zero_mask);
14044 parens.skip_until_found_close (parser);
14045 }
14046 orig_expr = expr;
14047 mark_exp_read (expr.value);
14048 if (warn_sizeof_pointer_memaccess)
14049 sizeof_pointer_memaccess_warning (sizeof_arg_loc,
14050 expr.value, exprlist,
14051 sizeof_arg,
14052 sizeof_ptr_memacc_comptypes);
14053 if (TREE_CODE (expr.value) == FUNCTION_DECL)
14054 {
14055 if (fndecl_built_in_p (node: expr.value, name1: BUILT_IN_MEMSET)
14056 && vec_safe_length (v: exprlist) == 3)
14057 {
14058 tree arg0 = (*exprlist)[0];
14059 tree arg2 = (*exprlist)[2];
14060 warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
14061 }
14062 if (warn_absolute_value
14063 && fndecl_built_in_p (node: expr.value, klass: BUILT_IN_NORMAL)
14064 && vec_safe_length (v: exprlist) == 1)
14065 warn_for_abs (loc: expr_loc, fndecl: expr.value, arg: (*exprlist)[0]);
14066 if (parser->omp_for_parse_state
14067 && parser->omp_for_parse_state->in_intervening_code
14068 && omp_runtime_api_call (fndecl: expr.value))
14069 {
14070 error_at (expr_loc, "calls to the OpenMP runtime API are "
14071 "not permitted in intervening code");
14072 parser->omp_for_parse_state->fail = true;
14073 }
14074 if (warn_calloc_transposed_args)
14075 if (tree attr = lookup_attribute (attr_name: "alloc_size",
14076 TYPE_ATTRIBUTES
14077 (TREE_TYPE (expr.value))))
14078 if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
14079 warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
14080 sizeof_arg, attr);
14081 }
14082
14083 start = expr.get_start ();
14084 finish = parser->tokens_buf[0].get_finish ();
14085 expr.value
14086 = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
14087 exprlist, origtypes);
14088 set_c_expr_source_range (expr: &expr, start, finish);
14089 expr.m_decimal = 0;
14090
14091 expr.original_code = ERROR_MARK;
14092 if (TREE_CODE (expr.value) == INTEGER_CST
14093 && TREE_CODE (orig_expr.value) == FUNCTION_DECL
14094 && fndecl_built_in_p (node: orig_expr.value, name1: BUILT_IN_CONSTANT_P))
14095 expr.original_code = C_MAYBE_CONST_EXPR;
14096 expr.original_type = NULL;
14097 if (exprlist)
14098 {
14099 release_tree_vector (exprlist);
14100 release_tree_vector (origtypes);
14101 }
14102 arg_loc.release ();
14103 break;
14104 case CPP_DOT:
14105 /* Structure element reference. */
14106 c_parser_consume_token (parser);
14107 expr = default_function_array_conversion (expr_loc, expr);
14108 if (c_parser_next_token_is (parser, type: CPP_NAME))
14109 {
14110 c_token *comp_tok = c_parser_peek_token (parser);
14111 ident = comp_tok->value;
14112 comp_loc = comp_tok->location;
14113 }
14114 else
14115 {
14116 c_parser_error (parser, gmsgid: "expected identifier");
14117 expr.set_error ();
14118 expr.original_code = ERROR_MARK;
14119 expr.original_type = NULL;
14120 return expr;
14121 }
14122 start = expr.get_start ();
14123 finish = c_parser_peek_token (parser)->get_finish ();
14124 c_parser_consume_token (parser);
14125 expr.value = build_component_ref (op_loc, expr.value, ident,
14126 comp_loc, UNKNOWN_LOCATION);
14127 set_c_expr_source_range (expr: &expr, start, finish);
14128 expr.original_code = ERROR_MARK;
14129 if (TREE_CODE (expr.value) != COMPONENT_REF)
14130 expr.original_type = NULL;
14131 else
14132 {
14133 /* Remember the original type of a bitfield. */
14134 tree field = TREE_OPERAND (expr.value, 1);
14135 if (TREE_CODE (field) != FIELD_DECL)
14136 expr.original_type = NULL;
14137 else
14138 expr.original_type = DECL_BIT_FIELD_TYPE (field);
14139 }
14140 expr.m_decimal = 0;
14141 break;
14142 case CPP_DEREF:
14143 /* Structure element reference. */
14144 c_parser_consume_token (parser);
14145 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
14146 if (c_parser_next_token_is (parser, type: CPP_NAME))
14147 {
14148 c_token *comp_tok = c_parser_peek_token (parser);
14149 ident = comp_tok->value;
14150 comp_loc = comp_tok->location;
14151 }
14152 else
14153 {
14154 c_parser_error (parser, gmsgid: "expected identifier");
14155 expr.set_error ();
14156 expr.original_code = ERROR_MARK;
14157 expr.original_type = NULL;
14158 return expr;
14159 }
14160 start = expr.get_start ();
14161 finish = c_parser_peek_token (parser)->get_finish ();
14162 c_parser_consume_token (parser);
14163 expr.value = build_component_ref (op_loc,
14164 build_indirect_ref (op_loc,
14165 expr.value,
14166 RO_ARROW),
14167 ident, comp_loc,
14168 expr.get_location ());
14169 set_c_expr_source_range (expr: &expr, start, finish);
14170 expr.original_code = ERROR_MARK;
14171 if (TREE_CODE (expr.value) != COMPONENT_REF)
14172 expr.original_type = NULL;
14173 else
14174 {
14175 /* Remember the original type of a bitfield. */
14176 tree field = TREE_OPERAND (expr.value, 1);
14177 if (TREE_CODE (field) != FIELD_DECL)
14178 expr.original_type = NULL;
14179 else
14180 expr.original_type = DECL_BIT_FIELD_TYPE (field);
14181 }
14182 expr.m_decimal = 0;
14183 break;
14184 case CPP_PLUS_PLUS:
14185 /* Postincrement. */
14186 start = expr.get_start ();
14187 finish = c_parser_peek_token (parser)->get_finish ();
14188 c_parser_consume_token (parser);
14189 if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
14190 && !DECL_READ_P (expr.value)
14191 && (VAR_P (expr.value) ? warn_unused_but_set_variable
14192 : warn_unused_but_set_parameter) > 1
14193 && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
14194 {
14195 expr = default_function_array_read_conversion (expr_loc, expr);
14196 DECL_READ_P (expr.value) = 0;
14197 }
14198 else
14199 expr = default_function_array_read_conversion (expr_loc, expr);
14200 expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
14201 expr.value, false);
14202 set_c_expr_source_range (expr: &expr, start, finish);
14203 expr.original_code = ERROR_MARK;
14204 expr.original_type = NULL;
14205 break;
14206 case CPP_MINUS_MINUS:
14207 /* Postdecrement. */
14208 start = expr.get_start ();
14209 finish = c_parser_peek_token (parser)->get_finish ();
14210 c_parser_consume_token (parser);
14211 if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
14212 && !DECL_READ_P (expr.value)
14213 && (VAR_P (expr.value) ? warn_unused_but_set_variable
14214 : warn_unused_but_set_parameter) > 1
14215 && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
14216 {
14217 expr = default_function_array_read_conversion (expr_loc, expr);
14218 DECL_READ_P (expr.value) = 0;
14219 }
14220 else
14221 expr = default_function_array_read_conversion (expr_loc, expr);
14222 expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
14223 expr.value, false);
14224 set_c_expr_source_range (expr: &expr, start, finish);
14225 expr.original_code = ERROR_MARK;
14226 expr.original_type = NULL;
14227 break;
14228 default:
14229 return expr;
14230 }
14231 }
14232}
14233
14234/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
14235
14236 expression:
14237 assignment-expression
14238 expression , assignment-expression
14239*/
14240
14241static struct c_expr
14242c_parser_expression (c_parser *parser)
14243{
14244 location_t tloc = c_parser_peek_token (parser)->location;
14245 struct c_expr expr;
14246 expr = c_parser_expr_no_commas (parser, NULL);
14247 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14248 expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
14249 while (c_parser_next_token_is (parser, type: CPP_COMMA))
14250 {
14251 struct c_expr next;
14252 tree lhsval;
14253 location_t loc = c_parser_peek_token (parser)->location;
14254 location_t expr_loc;
14255 c_parser_consume_token (parser);
14256 expr_loc = c_parser_peek_token (parser)->location;
14257 lhsval = expr.value;
14258 while (TREE_CODE (lhsval) == COMPOUND_EXPR
14259 || TREE_CODE (lhsval) == NOP_EXPR)
14260 {
14261 if (TREE_CODE (lhsval) == COMPOUND_EXPR)
14262 lhsval = TREE_OPERAND (lhsval, 1);
14263 else
14264 lhsval = TREE_OPERAND (lhsval, 0);
14265 }
14266 if (DECL_P (lhsval) || handled_component_p (t: lhsval))
14267 mark_exp_read (lhsval);
14268 if (c_parser_next_token_is (parser, type: CPP_EMBED))
14269 {
14270 /* Users aren't interested in milions of -Wunused-value
14271 warnings when using #embed inside of a comma expression,
14272 and one CPP_NUMBER plus CPP_COMMA before it and one
14273 CPP_COMMA plus CPP_NUMBER after it is guaranteed by
14274 the preprocessor. Thus, parse the whole CPP_EMBED just
14275 as a single INTEGER_CST, the last byte in it. */
14276 c_token *embed = c_parser_peek_token (parser);
14277 tree val = embed->value;
14278 unsigned last = RAW_DATA_LENGTH (val) - 1;
14279 next.value = build_int_cst (TREE_TYPE (val),
14280 RAW_DATA_UCHAR_ELT (val, last));
14281 next.original_type = integer_type_node;
14282 c_parser_consume_token (parser);
14283 }
14284 else
14285 {
14286 next = c_parser_expr_no_commas (parser, NULL);
14287 next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
14288 }
14289 expr.value = build_compound_expr (loc, expr.value, next.value);
14290 expr.original_code = COMPOUND_EXPR;
14291 expr.original_type = next.original_type;
14292 expr.m_decimal = 0;
14293 }
14294 return expr;
14295}
14296
14297/* Parse an expression and convert functions or arrays to pointers and
14298 lvalues to rvalues. */
14299
14300static struct c_expr
14301c_parser_expression_conv (c_parser *parser)
14302{
14303 struct c_expr expr;
14304 location_t loc = c_parser_peek_token (parser)->location;
14305 expr = c_parser_expression (parser);
14306 expr = convert_lvalue_to_rvalue (loc, expr, true, false);
14307 return expr;
14308}
14309
14310/* Helper function of c_parser_expr_list. Check if IDXth (0 based)
14311 argument is a literal zero alone and if so, set it in literal_zero_mask. */
14312
14313static inline void
14314c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
14315 unsigned int idx)
14316{
14317 if (idx >= HOST_BITS_PER_INT)
14318 return;
14319
14320 c_token *tok = c_parser_peek_token (parser);
14321 switch (tok->type)
14322 {
14323 case CPP_NUMBER:
14324 case CPP_CHAR:
14325 case CPP_WCHAR:
14326 case CPP_CHAR16:
14327 case CPP_CHAR32:
14328 case CPP_UTF8CHAR:
14329 /* If a parameter is literal zero alone, remember it
14330 for -Wmemset-transposed-args warning. */
14331 if (integer_zerop (tok->value)
14332 && !TREE_OVERFLOW (tok->value)
14333 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14334 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
14335 *literal_zero_mask |= 1U << idx;
14336 default:
14337 break;
14338 }
14339}
14340
14341/* Parse a non-empty list of expressions. If CONVERT_P, convert
14342 functions and arrays to pointers and lvalues to rvalues. If
14343 FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
14344 locations of function arguments into this vector.
14345
14346 nonempty-expr-list:
14347 assignment-expression
14348 nonempty-expr-list , assignment-expression
14349*/
14350
14351static vec<tree, va_gc> *
14352c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
14353 vec<tree, va_gc> **p_orig_types,
14354 location_t *sizeof_arg_loc, tree *sizeof_arg,
14355 vec<location_t> *locations,
14356 unsigned int *literal_zero_mask)
14357{
14358 vec<tree, va_gc> *ret;
14359 vec<tree, va_gc> *orig_types;
14360 struct c_expr expr;
14361 unsigned int idx = 0;
14362 bool save_c_omp_array_section_p = c_omp_array_section_p;
14363 c_omp_array_section_p = false;
14364
14365 ret = make_tree_vector ();
14366 if (p_orig_types == NULL)
14367 orig_types = NULL;
14368 else
14369 orig_types = make_tree_vector ();
14370
14371 if (literal_zero_mask)
14372 c_parser_check_literal_zero (parser, literal_zero_mask, idx: 0);
14373 expr = c_parser_expr_no_commas (parser, NULL);
14374 if (convert_p)
14375 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
14376 if (fold_p)
14377 expr.value = c_fully_fold (expr.value, false, NULL);
14378 ret->quick_push (obj: expr.value);
14379 if (orig_types)
14380 orig_types->quick_push (obj: expr.original_type);
14381 if (locations)
14382 locations->safe_push (obj: expr.get_location ());
14383 if (sizeof_arg != NULL
14384 && (expr.original_code == SIZEOF_EXPR
14385 || expr.original_code == PAREN_SIZEOF_EXPR))
14386 {
14387 sizeof_arg[0] = c_last_sizeof_arg;
14388 sizeof_arg_loc[0] = c_last_sizeof_loc;
14389 }
14390 while (c_parser_next_token_is (parser, type: CPP_COMMA))
14391 {
14392 c_parser_consume_token (parser);
14393 if (c_parser_next_token_is (parser, type: CPP_EMBED))
14394 {
14395 c_token *embed = c_parser_peek_token (parser);
14396 tree value = embed->value;
14397 expr.original_code = INTEGER_CST;
14398 expr.original_type = integer_type_node;
14399 expr.value = NULL_TREE;
14400 set_c_expr_source_range (expr: &expr, src_range: embed->get_range ());
14401 expr.m_decimal = 0;
14402 for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
14403 {
14404 if (literal_zero_mask
14405 && idx + 1 < HOST_BITS_PER_INT
14406 && RAW_DATA_POINTER (value)[i] == 0)
14407 *literal_zero_mask |= 1U << (idx + 1);
14408 expr.value = build_int_cst (integer_type_node,
14409 RAW_DATA_UCHAR_ELT (value, i));
14410 vec_safe_push (v&: ret, obj: expr.value);
14411 if (orig_types)
14412 vec_safe_push (v&: orig_types, obj: expr.original_type);
14413 if (locations)
14414 locations->safe_push (obj: expr.get_location ());
14415 ++idx;
14416 }
14417 c_parser_consume_token (parser);
14418 continue;
14419 }
14420 if (literal_zero_mask)
14421 c_parser_check_literal_zero (parser, literal_zero_mask, idx: idx + 1);
14422 expr = c_parser_expr_no_commas (parser, NULL);
14423 if (convert_p)
14424 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
14425 true);
14426 if (fold_p)
14427 expr.value = c_fully_fold (expr.value, false, NULL);
14428 vec_safe_push (v&: ret, obj: expr.value);
14429 if (orig_types)
14430 vec_safe_push (v&: orig_types, obj: expr.original_type);
14431 if (locations)
14432 locations->safe_push (obj: expr.get_location ());
14433 if (++idx < 6
14434 && sizeof_arg != NULL
14435 && (expr.original_code == SIZEOF_EXPR
14436 || expr.original_code == PAREN_SIZEOF_EXPR))
14437 {
14438 sizeof_arg[idx] = c_last_sizeof_arg;
14439 sizeof_arg_loc[idx] = c_last_sizeof_loc;
14440 }
14441 }
14442 if (orig_types)
14443 *p_orig_types = orig_types;
14444 c_omp_array_section_p = save_c_omp_array_section_p;
14445 return ret;
14446}
14447
14448/* Parse Objective-C-specific constructs. */
14449
14450/* Parse an objc-class-definition.
14451
14452 objc-class-definition:
14453 @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
14454 objc-class-instance-variables[opt] objc-methodprotolist @end
14455 @implementation identifier objc-superclass[opt]
14456 objc-class-instance-variables[opt]
14457 @interface identifier ( identifier ) objc-protocol-refs[opt]
14458 objc-methodprotolist @end
14459 @interface identifier ( ) objc-protocol-refs[opt]
14460 objc-methodprotolist @end
14461 @implementation identifier ( identifier )
14462
14463 objc-superclass:
14464 : identifier
14465
14466 "@interface identifier (" must start "@interface identifier (
14467 identifier ) ...": objc-methodprotolist in the first production may
14468 not start with a parenthesized identifier as a declarator of a data
14469 definition with no declaration specifiers if the objc-superclass,
14470 objc-protocol-refs and objc-class-instance-variables are omitted. */
14471
14472static void
14473c_parser_objc_class_definition (c_parser *parser, tree attributes)
14474{
14475 bool iface_p;
14476 tree id1;
14477 tree superclass;
14478 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_INTERFACE))
14479 iface_p = true;
14480 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_IMPLEMENTATION))
14481 iface_p = false;
14482 else
14483 gcc_unreachable ();
14484
14485 c_parser_consume_token (parser);
14486 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14487 {
14488 c_parser_error (parser, gmsgid: "expected identifier");
14489 return;
14490 }
14491 id1 = c_parser_peek_token (parser)->value;
14492 location_t loc1 = c_parser_peek_token (parser)->location;
14493 c_parser_consume_token (parser);
14494 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
14495 {
14496 /* We have a category or class extension. */
14497 tree id2;
14498 tree proto = NULL_TREE;
14499 matching_parens parens;
14500 parens.consume_open (parser);
14501 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14502 {
14503 if (iface_p && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
14504 {
14505 /* We have a class extension. */
14506 id2 = NULL_TREE;
14507 }
14508 else
14509 {
14510 c_parser_error (parser, gmsgid: "expected identifier or %<)%>");
14511 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
14512 return;
14513 }
14514 }
14515 else
14516 {
14517 id2 = c_parser_peek_token (parser)->value;
14518 c_parser_consume_token (parser);
14519 }
14520 parens.skip_until_found_close (parser);
14521 if (!iface_p)
14522 {
14523 objc_start_category_implementation (id1, id2);
14524 return;
14525 }
14526 if (c_parser_next_token_is (parser, type: CPP_LESS))
14527 proto = c_parser_objc_protocol_refs (parser);
14528 objc_start_category_interface (id1, id2, proto, attributes);
14529 c_parser_objc_methodprotolist (parser);
14530 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14531 objc_finish_interface ();
14532 return;
14533 }
14534 if (c_parser_next_token_is (parser, type: CPP_COLON))
14535 {
14536 c_parser_consume_token (parser);
14537 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14538 {
14539 c_parser_error (parser, gmsgid: "expected identifier");
14540 return;
14541 }
14542 superclass = c_parser_peek_token (parser)->value;
14543 c_parser_consume_token (parser);
14544 }
14545 else
14546 superclass = NULL_TREE;
14547 if (iface_p)
14548 {
14549 tree proto = NULL_TREE;
14550 if (c_parser_next_token_is (parser, type: CPP_LESS))
14551 proto = c_parser_objc_protocol_refs (parser);
14552 objc_start_class_interface (id1, loc1, superclass, proto, attributes);
14553 }
14554 else
14555 objc_start_class_implementation (id1, superclass);
14556 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
14557 c_parser_objc_class_instance_variables (parser);
14558 if (iface_p)
14559 {
14560 objc_continue_interface ();
14561 c_parser_objc_methodprotolist (parser);
14562 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14563 objc_finish_interface ();
14564 }
14565 else
14566 {
14567 objc_continue_implementation ();
14568 return;
14569 }
14570}
14571
14572/* Parse objc-class-instance-variables.
14573
14574 objc-class-instance-variables:
14575 { objc-instance-variable-decl-list[opt] }
14576
14577 objc-instance-variable-decl-list:
14578 objc-visibility-spec
14579 objc-instance-variable-decl ;
14580 ;
14581 objc-instance-variable-decl-list objc-visibility-spec
14582 objc-instance-variable-decl-list objc-instance-variable-decl ;
14583 objc-instance-variable-decl-list ;
14584
14585 objc-visibility-spec:
14586 @private
14587 @protected
14588 @public
14589
14590 objc-instance-variable-decl:
14591 struct-declaration
14592*/
14593
14594static void
14595c_parser_objc_class_instance_variables (c_parser *parser)
14596{
14597 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
14598 c_parser_consume_token (parser);
14599 while (c_parser_next_token_is_not (parser, type: CPP_EOF))
14600 {
14601 tree decls;
14602 /* Parse any stray semicolon. */
14603 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14604 {
14605 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14606 "extra semicolon");
14607 c_parser_consume_token (parser);
14608 continue;
14609 }
14610 /* Stop if at the end of the instance variables. */
14611 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
14612 {
14613 c_parser_consume_token (parser);
14614 break;
14615 }
14616 /* Parse any objc-visibility-spec. */
14617 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PRIVATE))
14618 {
14619 c_parser_consume_token (parser);
14620 objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
14621 continue;
14622 }
14623 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROTECTED))
14624 {
14625 c_parser_consume_token (parser);
14626 objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
14627 continue;
14628 }
14629 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PUBLIC))
14630 {
14631 c_parser_consume_token (parser);
14632 objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
14633 continue;
14634 }
14635 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PACKAGE))
14636 {
14637 c_parser_consume_token (parser);
14638 objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
14639 continue;
14640 }
14641 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
14642 {
14643 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14644 continue;
14645 }
14646
14647 /* Parse some comma-separated declarations. */
14648 decls = c_parser_struct_declaration (parser, NULL);
14649 if (decls == NULL)
14650 {
14651 /* There is a syntax error. We want to skip the offending
14652 tokens up to the next ';' (included) or '}'
14653 (excluded). */
14654
14655 /* First, skip manually a ')' or ']'. This is because they
14656 reduce the nesting level, so c_parser_skip_until_found()
14657 wouldn't be able to skip past them. */
14658 c_token *token = c_parser_peek_token (parser);
14659 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
14660 c_parser_consume_token (parser);
14661
14662 /* Then, do the standard skipping. */
14663 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14664
14665 /* We hopefully recovered. Start normal parsing again. */
14666 parser->error = false;
14667 continue;
14668 }
14669 else
14670 {
14671 /* Comma-separated instance variables are chained together
14672 in reverse order; add them one by one. */
14673 tree ivar = nreverse (decls);
14674 for (; ivar; ivar = DECL_CHAIN (ivar))
14675 objc_add_instance_variable (copy_node (ivar));
14676 }
14677 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14678 }
14679}
14680
14681/* Parse an objc-class-declaration.
14682
14683 objc-class-declaration:
14684 @class identifier-list ;
14685*/
14686
14687static void
14688c_parser_objc_class_declaration (c_parser *parser)
14689{
14690 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
14691 c_parser_consume_token (parser);
14692 /* Any identifiers, including those declared as type names, are OK
14693 here. */
14694 while (true)
14695 {
14696 tree id;
14697 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14698 {
14699 c_parser_error (parser, gmsgid: "expected identifier");
14700 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14701 parser->error = false;
14702 return;
14703 }
14704 id = c_parser_peek_token (parser)->value;
14705 objc_declare_class (id);
14706 c_parser_consume_token (parser);
14707 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14708 c_parser_consume_token (parser);
14709 else
14710 break;
14711 }
14712 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14713}
14714
14715/* Parse an objc-alias-declaration.
14716
14717 objc-alias-declaration:
14718 @compatibility_alias identifier identifier ;
14719*/
14720
14721static void
14722c_parser_objc_alias_declaration (c_parser *parser)
14723{
14724 tree id1, id2;
14725 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
14726 c_parser_consume_token (parser);
14727 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14728 {
14729 c_parser_error (parser, gmsgid: "expected identifier");
14730 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14731 return;
14732 }
14733 id1 = c_parser_peek_token (parser)->value;
14734 c_parser_consume_token (parser);
14735 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14736 {
14737 c_parser_error (parser, gmsgid: "expected identifier");
14738 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14739 return;
14740 }
14741 id2 = c_parser_peek_token (parser)->value;
14742 c_parser_consume_token (parser);
14743 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14744 objc_declare_alias (id1, id2);
14745}
14746
14747/* Parse an objc-protocol-definition.
14748
14749 objc-protocol-definition:
14750 @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
14751 @protocol identifier-list ;
14752
14753 "@protocol identifier ;" should be resolved as "@protocol
14754 identifier-list ;": objc-methodprotolist may not start with a
14755 semicolon in the first alternative if objc-protocol-refs are
14756 omitted. */
14757
14758static void
14759c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
14760{
14761 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
14762
14763 c_parser_consume_token (parser);
14764 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14765 {
14766 c_parser_error (parser, gmsgid: "expected identifier");
14767 return;
14768 }
14769 if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14770 || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
14771 {
14772 /* Any identifiers, including those declared as type names, are
14773 OK here. */
14774 while (true)
14775 {
14776 tree id;
14777 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14778 {
14779 c_parser_error (parser, gmsgid: "expected identifier");
14780 break;
14781 }
14782 id = c_parser_peek_token (parser)->value;
14783 objc_declare_protocol (id, attributes);
14784 c_parser_consume_token (parser);
14785 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14786 c_parser_consume_token (parser);
14787 else
14788 break;
14789 }
14790 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14791 }
14792 else
14793 {
14794 tree id = c_parser_peek_token (parser)->value;
14795 tree proto = NULL_TREE;
14796 c_parser_consume_token (parser);
14797 if (c_parser_next_token_is (parser, type: CPP_LESS))
14798 proto = c_parser_objc_protocol_refs (parser);
14799 parser->objc_pq_context = true;
14800 objc_start_protocol (id, proto, attributes);
14801 c_parser_objc_methodprotolist (parser);
14802 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14803 parser->objc_pq_context = false;
14804 objc_finish_interface ();
14805 }
14806}
14807
14808/* Parse an objc-method-type.
14809
14810 objc-method-type:
14811 +
14812 -
14813
14814 Return true if it is a class method (+) and false if it is
14815 an instance method (-).
14816*/
14817static inline bool
14818c_parser_objc_method_type (c_parser *parser)
14819{
14820 switch (c_parser_peek_token (parser)->type)
14821 {
14822 case CPP_PLUS:
14823 c_parser_consume_token (parser);
14824 return true;
14825 case CPP_MINUS:
14826 c_parser_consume_token (parser);
14827 return false;
14828 default:
14829 gcc_unreachable ();
14830 }
14831}
14832
14833/* Parse an objc-method-definition.
14834
14835 objc-method-definition:
14836 objc-method-type objc-method-decl ;[opt] compound-statement
14837*/
14838
14839static void
14840c_parser_objc_method_definition (c_parser *parser)
14841{
14842 bool is_class_method = c_parser_objc_method_type (parser);
14843 tree decl, attributes = NULL_TREE, expr = NULL_TREE;
14844 parser->objc_pq_context = true;
14845 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14846 &expr);
14847 if (decl == error_mark_node)
14848 return; /* Bail here. */
14849
14850 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14851 {
14852 c_parser_consume_token (parser);
14853 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14854 "extra semicolon in method definition specified");
14855 }
14856
14857 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
14858 {
14859 c_parser_error (parser, gmsgid: "expected %<{%>");
14860 return;
14861 }
14862
14863 parser->objc_pq_context = false;
14864 if (objc_start_method_definition (is_class_method, decl, attributes, expr))
14865 {
14866 add_stmt (c_parser_compound_statement (parser));
14867 objc_finish_method_definition (current_function_decl);
14868 }
14869 else
14870 {
14871 /* This code is executed when we find a method definition
14872 outside of an @implementation context (or invalid for other
14873 reasons). Parse the method (to keep going) but do not emit
14874 any code.
14875 */
14876 c_parser_compound_statement (parser);
14877 }
14878}
14879
14880/* Parse an objc-methodprotolist.
14881
14882 objc-methodprotolist:
14883 empty
14884 objc-methodprotolist objc-methodproto
14885 objc-methodprotolist declaration
14886 objc-methodprotolist ;
14887 @optional
14888 @required
14889
14890 The declaration is a data definition, which may be missing
14891 declaration specifiers under the same rules and diagnostics as
14892 other data definitions outside functions, and the stray semicolon
14893 is diagnosed the same way as a stray semicolon outside a
14894 function. */
14895
14896static void
14897c_parser_objc_methodprotolist (c_parser *parser)
14898{
14899 while (true)
14900 {
14901 /* The list is terminated by @end. */
14902 switch (c_parser_peek_token (parser)->type)
14903 {
14904 case CPP_SEMICOLON:
14905 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14906 "ISO C does not allow extra %<;%> outside of a function");
14907 c_parser_consume_token (parser);
14908 break;
14909 case CPP_PLUS:
14910 case CPP_MINUS:
14911 c_parser_objc_methodproto (parser);
14912 break;
14913 case CPP_PRAGMA:
14914 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14915 break;
14916 case CPP_EOF:
14917 return;
14918 default:
14919 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_END))
14920 return;
14921 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROPERTY))
14922 c_parser_objc_at_property_declaration (parser);
14923 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_OPTIONAL))
14924 {
14925 objc_set_method_opt (true);
14926 c_parser_consume_token (parser);
14927 }
14928 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_REQUIRED))
14929 {
14930 objc_set_method_opt (false);
14931 c_parser_consume_token (parser);
14932 }
14933 else
14934 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: true,
14935 nested: false, start_attr_ok: true, simple_ok: false);
14936 break;
14937 }
14938 }
14939}
14940
14941/* Parse an objc-methodproto.
14942
14943 objc-methodproto:
14944 objc-method-type objc-method-decl ;
14945*/
14946
14947static void
14948c_parser_objc_methodproto (c_parser *parser)
14949{
14950 bool is_class_method = c_parser_objc_method_type (parser);
14951 tree decl, attributes = NULL_TREE;
14952
14953 /* Remember protocol qualifiers in prototypes. */
14954 parser->objc_pq_context = true;
14955 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14956 NULL);
14957 /* Forget protocol qualifiers now. */
14958 parser->objc_pq_context = false;
14959
14960 /* Do not allow the presence of attributes to hide an erroneous
14961 method implementation in the interface section. */
14962 if (!c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14963 {
14964 c_parser_error (parser, gmsgid: "expected %<;%>");
14965 return;
14966 }
14967
14968 if (decl != error_mark_node)
14969 objc_add_method_declaration (is_class_method, decl, attributes);
14970
14971 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14972}
14973
14974/* If we are at a position that method attributes may be present, check that
14975 there are not any parsed already (a syntax error) and then collect any
14976 specified at the current location. Finally, if new attributes were present,
14977 check that the next token is legal ( ';' for decls and '{' for defs). */
14978
14979static bool
14980c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
14981{
14982 bool bad = false;
14983 if (*attributes)
14984 {
14985 c_parser_error (parser,
14986 gmsgid: "method attributes must be specified at the end only");
14987 *attributes = NULL_TREE;
14988 bad = true;
14989 }
14990
14991 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
14992 *attributes = c_parser_gnu_attributes (parser);
14993
14994 /* If there were no attributes here, just report any earlier error. */
14995 if (*attributes == NULL_TREE || bad)
14996 return bad;
14997
14998 /* If the attributes are followed by a ; or {, then just report any earlier
14999 error. */
15000 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
15001 || c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
15002 return bad;
15003
15004 /* We've got attributes, but not at the end. */
15005 c_parser_error (parser,
15006 gmsgid: "expected %<;%> or %<{%> after method attribute definition");
15007 return true;
15008}
15009
15010/* Parse an objc-method-decl.
15011
15012 objc-method-decl:
15013 ( objc-type-name ) objc-selector
15014 objc-selector
15015 ( objc-type-name ) objc-keyword-selector objc-optparmlist
15016 objc-keyword-selector objc-optparmlist
15017 gnu-attributes
15018
15019 objc-keyword-selector:
15020 objc-keyword-decl
15021 objc-keyword-selector objc-keyword-decl
15022
15023 objc-keyword-decl:
15024 objc-selector : ( objc-type-name ) identifier
15025 objc-selector : identifier
15026 : ( objc-type-name ) identifier
15027 : identifier
15028
15029 objc-optparmlist:
15030 objc-optparms objc-optellipsis
15031
15032 objc-optparms:
15033 empty
15034 objc-opt-parms , parameter-declaration
15035
15036 objc-optellipsis:
15037 empty
15038 , ...
15039*/
15040
15041static tree
15042c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
15043 tree *attributes, tree *expr)
15044{
15045 tree type = NULL_TREE;
15046 tree sel;
15047 tree parms = NULL_TREE;
15048 bool ellipsis = false;
15049 bool attr_err = false;
15050
15051 *attributes = NULL_TREE;
15052 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15053 {
15054 matching_parens parens;
15055 parens.consume_open (parser);
15056 type = c_parser_objc_type_name (parser);
15057 parens.skip_until_found_close (parser);
15058 }
15059 sel = c_parser_objc_selector (parser);
15060 /* If there is no selector, or a colon follows, we have an
15061 objc-keyword-selector. If there is a selector, and a colon does
15062 not follow, that selector ends the objc-method-decl. */
15063 if (!sel || c_parser_next_token_is (parser, type: CPP_COLON))
15064 {
15065 tree tsel = sel;
15066 tree list = NULL_TREE;
15067 while (true)
15068 {
15069 tree atype = NULL_TREE, id, keyworddecl;
15070 tree param_attr = NULL_TREE;
15071 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
15072 break;
15073 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15074 {
15075 c_parser_consume_token (parser);
15076 atype = c_parser_objc_type_name (parser);
15077 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
15078 msgid: "expected %<)%>");
15079 }
15080 /* New ObjC allows attributes on method parameters. */
15081 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
15082 param_attr = c_parser_gnu_attributes (parser);
15083 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15084 {
15085 c_parser_error (parser, gmsgid: "expected identifier");
15086 return error_mark_node;
15087 }
15088 id = c_parser_peek_token (parser)->value;
15089 c_parser_consume_token (parser);
15090 keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
15091 list = chainon (list, keyworddecl);
15092 tsel = c_parser_objc_selector (parser);
15093 if (!tsel && c_parser_next_token_is_not (parser, type: CPP_COLON))
15094 break;
15095 }
15096
15097 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
15098
15099 /* Parse the optional parameter list. Optional Objective-C
15100 method parameters follow the C syntax, and may include '...'
15101 to denote a variable number of arguments. */
15102 parms = make_node (TREE_LIST);
15103 while (c_parser_next_token_is (parser, type: CPP_COMMA))
15104 {
15105 struct c_parm *parm;
15106 c_parser_consume_token (parser);
15107 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
15108 {
15109 ellipsis = true;
15110 c_parser_consume_token (parser);
15111 attr_err |= c_parser_objc_maybe_method_attributes
15112 (parser, attributes) ;
15113 break;
15114 }
15115 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
15116 if (parm == NULL)
15117 break;
15118 parms = chainon (parms,
15119 build_tree_list (NULL_TREE, grokparm (parm, expr)));
15120 }
15121 sel = list;
15122 }
15123 else
15124 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
15125
15126 if (sel == NULL)
15127 {
15128 c_parser_error (parser, gmsgid: "objective-c method declaration is expected");
15129 return error_mark_node;
15130 }
15131
15132 if (attr_err)
15133 return error_mark_node;
15134
15135 return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
15136}
15137
15138/* Parse an objc-type-name.
15139
15140 objc-type-name:
15141 objc-type-qualifiers[opt] type-name
15142 objc-type-qualifiers[opt]
15143
15144 objc-type-qualifiers:
15145 objc-type-qualifier
15146 objc-type-qualifiers objc-type-qualifier
15147
15148 objc-type-qualifier: one of
15149 in out inout bycopy byref oneway
15150*/
15151
15152static tree
15153c_parser_objc_type_name (c_parser *parser)
15154{
15155 tree quals = NULL_TREE;
15156 struct c_type_name *type_name = NULL;
15157 tree type = NULL_TREE;
15158 while (true)
15159 {
15160 c_token *token = c_parser_peek_token (parser);
15161 if (token->type == CPP_KEYWORD
15162 && (token->keyword == RID_IN
15163 || token->keyword == RID_OUT
15164 || token->keyword == RID_INOUT
15165 || token->keyword == RID_BYCOPY
15166 || token->keyword == RID_BYREF
15167 || token->keyword == RID_ONEWAY))
15168 {
15169 quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
15170 c_parser_consume_token (parser);
15171 }
15172 else
15173 break;
15174 }
15175 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
15176 type_name = c_parser_type_name (parser);
15177 if (type_name)
15178 type = groktypename (type_name, NULL, NULL);
15179
15180 /* If the type is unknown, and error has already been produced and
15181 we need to recover from the error. In that case, use NULL_TREE
15182 for the type, as if no type had been specified; this will use the
15183 default type ('id') which is good for error recovery. */
15184 if (type == error_mark_node)
15185 type = NULL_TREE;
15186
15187 return build_tree_list (quals, type);
15188}
15189
15190/* Parse objc-protocol-refs.
15191
15192 objc-protocol-refs:
15193 < identifier-list >
15194*/
15195
15196static tree
15197c_parser_objc_protocol_refs (c_parser *parser)
15198{
15199 tree list = NULL_TREE;
15200 gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
15201 c_parser_consume_token (parser);
15202 /* Any identifiers, including those declared as type names, are OK
15203 here. */
15204 while (true)
15205 {
15206 tree id;
15207 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15208 {
15209 c_parser_error (parser, gmsgid: "expected identifier");
15210 break;
15211 }
15212 id = c_parser_peek_token (parser)->value;
15213 list = chainon (list, build_tree_list (NULL_TREE, id));
15214 c_parser_consume_token (parser);
15215 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15216 c_parser_consume_token (parser);
15217 else
15218 break;
15219 }
15220 c_parser_require (parser, type: CPP_GREATER, msgid: "expected %<>%>");
15221 return list;
15222}
15223
15224/* Parse an objc-try-catch-finally-statement.
15225
15226 objc-try-catch-finally-statement:
15227 @try compound-statement objc-catch-list[opt]
15228 @try compound-statement objc-catch-list[opt] @finally compound-statement
15229
15230 objc-catch-list:
15231 @catch ( objc-catch-parameter-declaration ) compound-statement
15232 objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
15233
15234 objc-catch-parameter-declaration:
15235 parameter-declaration
15236 '...'
15237
15238 where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
15239
15240 PS: This function is identical to cp_parser_objc_try_catch_finally_statement
15241 for C++. Keep them in sync. */
15242
15243static void
15244c_parser_objc_try_catch_finally_statement (c_parser *parser)
15245{
15246 location_t location;
15247 tree stmt;
15248
15249 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
15250 c_parser_consume_token (parser);
15251 location = c_parser_peek_token (parser)->location;
15252 objc_maybe_warn_exceptions (location);
15253 stmt = c_parser_compound_statement (parser);
15254 objc_begin_try_stmt (location, stmt);
15255
15256 while (c_parser_next_token_is_keyword (parser, keyword: RID_AT_CATCH))
15257 {
15258 struct c_parm *parm;
15259 tree parameter_declaration = error_mark_node;
15260 bool seen_open_paren = false;
15261
15262 c_parser_consume_token (parser);
15263 matching_parens parens;
15264 if (!parens.require_open (parser))
15265 seen_open_paren = true;
15266 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
15267 {
15268 /* We have "@catch (...)" (where the '...' are literally
15269 what is in the code). Skip the '...'.
15270 parameter_declaration is set to NULL_TREE, and
15271 objc_being_catch_clauses() knows that that means
15272 '...'. */
15273 c_parser_consume_token (parser);
15274 parameter_declaration = NULL_TREE;
15275 }
15276 else
15277 {
15278 /* We have "@catch (NSException *exception)" or something
15279 like that. Parse the parameter declaration. */
15280 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
15281 if (parm == NULL)
15282 parameter_declaration = error_mark_node;
15283 else
15284 parameter_declaration = grokparm (parm, NULL);
15285 }
15286 if (seen_open_paren)
15287 parens.require_close (parser);
15288 else
15289 {
15290 /* If there was no open parenthesis, we are recovering from
15291 an error, and we are trying to figure out what mistake
15292 the user has made. */
15293
15294 /* If there is an immediate closing parenthesis, the user
15295 probably forgot the opening one (ie, they typed "@catch
15296 NSException *e)". Parse the closing parenthesis and keep
15297 going. */
15298 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
15299 c_parser_consume_token (parser);
15300
15301 /* If these is no immediate closing parenthesis, the user
15302 probably doesn't know that parenthesis are required at
15303 all (ie, they typed "@catch NSException *e"). So, just
15304 forget about the closing parenthesis and keep going. */
15305 }
15306 objc_begin_catch_clause (parameter_declaration);
15307 if (c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
15308 c_parser_compound_statement_nostart (parser);
15309 objc_finish_catch_clause ();
15310 }
15311 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_FINALLY))
15312 {
15313 c_parser_consume_token (parser);
15314 location = c_parser_peek_token (parser)->location;
15315 stmt = c_parser_compound_statement (parser);
15316 objc_build_finally_clause (location, stmt);
15317 }
15318 objc_finish_try_stmt ();
15319}
15320
15321/* Parse an objc-synchronized-statement.
15322
15323 objc-synchronized-statement:
15324 @synchronized ( expression ) compound-statement
15325*/
15326
15327static void
15328c_parser_objc_synchronized_statement (c_parser *parser)
15329{
15330 location_t loc;
15331 tree expr, stmt;
15332 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
15333 c_parser_consume_token (parser);
15334 loc = c_parser_peek_token (parser)->location;
15335 objc_maybe_warn_exceptions (loc);
15336 matching_parens parens;
15337 if (parens.require_open (parser))
15338 {
15339 struct c_expr ce = c_parser_expression (parser);
15340 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15341 expr = ce.value;
15342 expr = c_fully_fold (expr, false, NULL);
15343 parens.skip_until_found_close (parser);
15344 }
15345 else
15346 expr = error_mark_node;
15347 stmt = c_parser_compound_statement (parser);
15348 objc_build_synchronized (loc, expr, stmt);
15349}
15350
15351/* Parse an objc-selector; return NULL_TREE without an error if the
15352 next token is not an objc-selector.
15353
15354 objc-selector:
15355 identifier
15356 one of
15357 enum struct union if else while do for switch case default
15358 break continue return goto asm sizeof typeof typeof_unqual __alignof
15359 unsigned long const short volatile signed restrict _Complex
15360 in out inout bycopy byref oneway int char float double void _Bool
15361 _Atomic
15362
15363 ??? Why this selection of keywords but not, for example, storage
15364 class specifiers? */
15365
15366static tree
15367c_parser_objc_selector (c_parser *parser)
15368{
15369 c_token *token = c_parser_peek_token (parser);
15370 tree value = token->value;
15371 if (token->type == CPP_NAME)
15372 {
15373 c_parser_consume_token (parser);
15374 return value;
15375 }
15376 if (token->type != CPP_KEYWORD)
15377 return NULL_TREE;
15378 switch (token->keyword)
15379 {
15380 case RID_ENUM:
15381 case RID_STRUCT:
15382 case RID_UNION:
15383 case RID_IF:
15384 case RID_ELSE:
15385 case RID_WHILE:
15386 case RID_DO:
15387 case RID_FOR:
15388 case RID_SWITCH:
15389 case RID_CASE:
15390 case RID_DEFAULT:
15391 case RID_BREAK:
15392 case RID_CONTINUE:
15393 case RID_RETURN:
15394 case RID_GOTO:
15395 case RID_ASM:
15396 case RID_SIZEOF:
15397 case RID_TYPEOF:
15398 case RID_TYPEOF_UNQUAL:
15399 case RID_ALIGNOF:
15400 case RID_UNSIGNED:
15401 case RID_LONG:
15402 case RID_CONST:
15403 case RID_SHORT:
15404 case RID_VOLATILE:
15405 case RID_SIGNED:
15406 case RID_RESTRICT:
15407 case RID_COMPLEX:
15408 case RID_IN:
15409 case RID_OUT:
15410 case RID_INOUT:
15411 case RID_BYCOPY:
15412 case RID_BYREF:
15413 case RID_ONEWAY:
15414 case RID_INT:
15415 case RID_CHAR:
15416 case RID_FLOAT:
15417 case RID_DOUBLE:
15418 CASE_RID_FLOATN_NX:
15419 case RID_VOID:
15420 case RID_BOOL:
15421 case RID_ATOMIC:
15422 case RID_AUTO_TYPE:
15423 case RID_INT_N_0:
15424 case RID_INT_N_1:
15425 case RID_INT_N_2:
15426 case RID_INT_N_3:
15427 c_parser_consume_token (parser);
15428 return value;
15429 default:
15430 return NULL_TREE;
15431 }
15432}
15433
15434/* Parse an objc-selector-arg.
15435
15436 objc-selector-arg:
15437 objc-selector
15438 objc-keywordname-list
15439
15440 objc-keywordname-list:
15441 objc-keywordname
15442 objc-keywordname-list objc-keywordname
15443
15444 objc-keywordname:
15445 objc-selector :
15446 :
15447*/
15448
15449static tree
15450c_parser_objc_selector_arg (c_parser *parser)
15451{
15452 tree sel = c_parser_objc_selector (parser);
15453 tree list = NULL_TREE;
15454 if (sel
15455 && c_parser_next_token_is_not (parser, type: CPP_COLON)
15456 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
15457 return sel;
15458 while (true)
15459 {
15460 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
15461 {
15462 c_parser_consume_token (parser);
15463 list = chainon (list, build_tree_list (sel, NULL_TREE));
15464 list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
15465 }
15466 else
15467 {
15468 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
15469 return list;
15470 list = chainon (list, build_tree_list (sel, NULL_TREE));
15471 }
15472 sel = c_parser_objc_selector (parser);
15473 if (!sel
15474 && c_parser_next_token_is_not (parser, type: CPP_COLON)
15475 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
15476 break;
15477 }
15478 return list;
15479}
15480
15481/* Parse an objc-receiver.
15482
15483 objc-receiver:
15484 expression
15485 class-name
15486 type-name
15487*/
15488
15489static tree
15490c_parser_objc_receiver (c_parser *parser)
15491{
15492 location_t loc = c_parser_peek_token (parser)->location;
15493
15494 if (c_parser_peek_token (parser)->type == CPP_NAME
15495 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
15496 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
15497 {
15498 tree id = c_parser_peek_token (parser)->value;
15499 c_parser_consume_token (parser);
15500 return objc_get_class_reference (id);
15501 }
15502 struct c_expr ce = c_parser_expression (parser);
15503 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15504 return c_fully_fold (ce.value, false, NULL);
15505}
15506
15507/* Parse objc-message-args.
15508
15509 objc-message-args:
15510 objc-selector
15511 objc-keywordarg-list
15512
15513 objc-keywordarg-list:
15514 objc-keywordarg
15515 objc-keywordarg-list objc-keywordarg
15516
15517 objc-keywordarg:
15518 objc-selector : objc-keywordexpr
15519 : objc-keywordexpr
15520*/
15521
15522static tree
15523c_parser_objc_message_args (c_parser *parser)
15524{
15525 tree sel = c_parser_objc_selector (parser);
15526 tree list = NULL_TREE;
15527 if (sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
15528 return sel;
15529 while (true)
15530 {
15531 tree keywordexpr;
15532 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
15533 return error_mark_node;
15534 keywordexpr = c_parser_objc_keywordexpr (parser);
15535 list = chainon (list, build_tree_list (sel, keywordexpr));
15536 sel = c_parser_objc_selector (parser);
15537 if (!sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
15538 break;
15539 }
15540 return list;
15541}
15542
15543/* Parse an objc-keywordexpr.
15544
15545 objc-keywordexpr:
15546 nonempty-expr-list
15547*/
15548
15549static tree
15550c_parser_objc_keywordexpr (c_parser *parser)
15551{
15552 tree ret;
15553 vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, convert_p: true, fold_p: true,
15554 NULL, NULL, NULL, NULL);
15555 if (vec_safe_length (v: expr_list) == 1)
15556 {
15557 /* Just return the expression, remove a level of
15558 indirection. */
15559 ret = (*expr_list)[0];
15560 }
15561 else
15562 {
15563 /* We have a comma expression, we will collapse later. */
15564 ret = build_tree_list_vec (expr_list);
15565 }
15566 release_tree_vector (expr_list);
15567 return ret;
15568}
15569
15570/* A check, needed in several places, that ObjC interface, implementation or
15571 method definitions are not prefixed by incorrect items. */
15572static bool
15573c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
15574 struct c_declspecs *specs)
15575{
15576 if (!specs->declspecs_seen_p || specs->non_sc_seen_p
15577 || specs->typespec_kind != ctsk_none)
15578 {
15579 c_parser_error (parser,
15580 gmsgid: "no type or storage class may be specified here,");
15581 c_parser_skip_to_end_of_block_or_statement (parser);
15582 return true;
15583 }
15584 return false;
15585}
15586
15587/* Parse an Objective-C @property declaration. The syntax is:
15588
15589 objc-property-declaration:
15590 '@property' objc-property-attributes[opt] struct-declaration ;
15591
15592 objc-property-attributes:
15593 '(' objc-property-attribute-list ')'
15594
15595 objc-property-attribute-list:
15596 objc-property-attribute
15597 objc-property-attribute-list, objc-property-attribute
15598
15599 objc-property-attribute
15600 'getter' = identifier
15601 'setter' = identifier
15602 'readonly'
15603 'readwrite'
15604 'assign'
15605 'retain'
15606 'copy'
15607 'nonatomic'
15608
15609 For example:
15610 @property NSString *name;
15611 @property (readonly) id object;
15612 @property (retain, nonatomic, getter=getTheName) id name;
15613 @property int a, b, c;
15614
15615 PS: This function is identical to cp_parser_objc_at_propery_declaration
15616 for C++. Keep them in sync. */
15617static void
15618c_parser_objc_at_property_declaration (c_parser *parser)
15619{
15620 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
15621 location_t loc = c_parser_peek_token (parser)->location;
15622 c_parser_consume_token (parser); /* Eat '@property'. */
15623
15624 /* Parse the optional attribute list.
15625
15626 A list of parsed, but not verified, attributes. */
15627 vec<property_attribute_info *> prop_attr_list = vNULL;
15628
15629 bool syntax_error = false;
15630 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15631 {
15632 matching_parens parens;
15633
15634 location_t attr_start = c_parser_peek_token (parser)->location;
15635 /* Eat the '(' */
15636 parens.consume_open (parser);
15637
15638 /* Property attribute keywords are valid now. */
15639 parser->objc_property_attr_context = true;
15640
15641 /* Allow @property (), with a warning. */
15642 location_t attr_end = c_parser_peek_token (parser)->location;
15643
15644 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
15645 {
15646 location_t attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15647 warning_at (attr_comb, OPT_Wattributes,
15648 "empty property attribute list");
15649 }
15650 else
15651 while (true)
15652 {
15653 c_token *token = c_parser_peek_token (parser);
15654 attr_start = token->location;
15655 attr_end = get_finish (loc: token->location);
15656 location_t attr_comb = make_location (caret: attr_start, start: attr_start,
15657 finish: attr_end);
15658
15659 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
15660 {
15661 warning_at (attr_comb, OPT_Wattributes,
15662 "missing property attribute");
15663 if (token->type == CPP_CLOSE_PAREN)
15664 break;
15665 c_parser_consume_token (parser);
15666 continue;
15667 }
15668
15669 tree attr_name = NULL_TREE;
15670 enum rid keyword = RID_MAX; /* Not a valid property attribute. */
15671 bool add_at = false;
15672 if (token->type == CPP_KEYWORD)
15673 {
15674 keyword = token->keyword;
15675 if (OBJC_IS_AT_KEYWORD (keyword))
15676 {
15677 /* For '@' keywords the token value has the keyword,
15678 prepend the '@' for diagnostics. */
15679 attr_name = token->value;
15680 add_at = true;
15681 }
15682 else
15683 attr_name = ridpointers[(int)keyword];
15684 }
15685 else if (token->type == CPP_NAME)
15686 attr_name = token->value;
15687 c_parser_consume_token (parser);
15688
15689 enum objc_property_attribute_kind prop_kind
15690 = objc_prop_attr_kind_for_rid (keyword);
15691 property_attribute_info *prop
15692 = new property_attribute_info (attr_name, attr_comb, prop_kind);
15693 prop_attr_list.safe_push (obj: prop);
15694
15695 tree meth_name;
15696 switch (prop->prop_kind)
15697 {
15698 default: break;
15699 case OBJC_PROPERTY_ATTR_UNKNOWN:
15700 if (attr_name)
15701 error_at (attr_comb, "unknown property attribute %<%s%s%>",
15702 add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
15703 else
15704 error_at (attr_comb, "unknown property attribute");
15705 prop->parse_error = syntax_error = true;
15706 break;
15707
15708 case OBJC_PROPERTY_ATTR_GETTER:
15709 case OBJC_PROPERTY_ATTR_SETTER:
15710 if (c_parser_next_token_is_not (parser, type: CPP_EQ))
15711 {
15712 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15713 error_at (attr_comb, "expected %<=%> after Objective-C %qE",
15714 attr_name);
15715 prop->parse_error = syntax_error = true;
15716 break;
15717 }
15718 token = c_parser_peek_token (parser);
15719 attr_end = token->location;
15720 c_parser_consume_token (parser); /* eat the = */
15721 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15722 {
15723 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15724 error_at (attr_comb, "expected %qE selector name",
15725 attr_name);
15726 prop->parse_error = syntax_error = true;
15727 break;
15728 }
15729 /* Get the end of the method name, and consume the name. */
15730 token = c_parser_peek_token (parser);
15731 attr_end = get_finish (loc: token->location);
15732 meth_name = token->value;
15733 c_parser_consume_token (parser);
15734 if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
15735 {
15736 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
15737 {
15738 attr_comb = make_location (caret: attr_end, start: attr_start,
15739 finish: attr_end);
15740 error_at (attr_comb, "setter method names must"
15741 " terminate with %<:%>");
15742 prop->parse_error = syntax_error = true;
15743 }
15744 else
15745 {
15746 attr_end = get_finish (loc: c_parser_peek_token
15747 (parser)->location);
15748 c_parser_consume_token (parser);
15749 }
15750 attr_comb = make_location (caret: attr_start, start: attr_start,
15751 finish: attr_end);
15752 }
15753 else
15754 attr_comb = make_location (caret: attr_start, start: attr_start,
15755 finish: attr_end);
15756 prop->ident = meth_name;
15757 /* Updated location including all that was successfully
15758 parsed. */
15759 prop->prop_loc = attr_comb;
15760 break;
15761 }
15762
15763 /* If we see a comma here, then keep going - even if we already
15764 saw a syntax error. For simple mistakes e.g. (asign, getter=x)
15765 this makes a more useful output and avoid spurious warnings about
15766 missing attributes that are, in fact, specified after the one with
15767 the syntax error. */
15768 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15769 c_parser_consume_token (parser);
15770 else
15771 break;
15772 }
15773 parser->objc_property_attr_context = false;
15774
15775 if (syntax_error && c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
15776 /* We don't really want to chew the whole of the file looking for a
15777 matching closing parenthesis, so we will try to read the decl and
15778 let the error handling for that close out the statement. */
15779 ;
15780 else
15781 syntax_error = false, parens.skip_until_found_close (parser);
15782 }
15783
15784 /* 'properties' is the list of properties that we read. Usually a
15785 single one, but maybe more (eg, in "@property int a, b, c;" there
15786 are three). */
15787 tree properties = c_parser_struct_declaration (parser, NULL);
15788
15789 if (properties == error_mark_node)
15790 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15791 else
15792 {
15793 if (properties == NULL_TREE)
15794 c_parser_error (parser, gmsgid: "expected identifier");
15795 else
15796 {
15797 /* Comma-separated properties are chained together in reverse order;
15798 add them one by one. */
15799 properties = nreverse (properties);
15800 for (; properties; properties = TREE_CHAIN (properties))
15801 objc_add_property_declaration (loc, copy_node (properties),
15802 prop_attr_list);
15803 }
15804 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15805 }
15806
15807 while (!prop_attr_list.is_empty())
15808 delete prop_attr_list.pop ();
15809 prop_attr_list.release ();
15810 parser->error = false;
15811}
15812
15813/* Parse an Objective-C @synthesize declaration. The syntax is:
15814
15815 objc-synthesize-declaration:
15816 @synthesize objc-synthesize-identifier-list ;
15817
15818 objc-synthesize-identifier-list:
15819 objc-synthesize-identifier
15820 objc-synthesize-identifier-list, objc-synthesize-identifier
15821
15822 objc-synthesize-identifier
15823 identifier
15824 identifier = identifier
15825
15826 For example:
15827 @synthesize MyProperty;
15828 @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
15829
15830 PS: This function is identical to cp_parser_objc_at_synthesize_declaration
15831 for C++. Keep them in sync.
15832*/
15833static void
15834c_parser_objc_at_synthesize_declaration (c_parser *parser)
15835{
15836 tree list = NULL_TREE;
15837 location_t loc;
15838 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
15839 loc = c_parser_peek_token (parser)->location;
15840
15841 c_parser_consume_token (parser);
15842 while (true)
15843 {
15844 tree property, ivar;
15845 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15846 {
15847 c_parser_error (parser, gmsgid: "expected identifier");
15848 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15849 /* Once we find the semicolon, we can resume normal parsing.
15850 We have to reset parser->error manually because
15851 c_parser_skip_until_found() won't reset it for us if the
15852 next token is precisely a semicolon. */
15853 parser->error = false;
15854 return;
15855 }
15856 property = c_parser_peek_token (parser)->value;
15857 c_parser_consume_token (parser);
15858 if (c_parser_next_token_is (parser, type: CPP_EQ))
15859 {
15860 c_parser_consume_token (parser);
15861 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15862 {
15863 c_parser_error (parser, gmsgid: "expected identifier");
15864 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15865 parser->error = false;
15866 return;
15867 }
15868 ivar = c_parser_peek_token (parser)->value;
15869 c_parser_consume_token (parser);
15870 }
15871 else
15872 ivar = NULL_TREE;
15873 list = chainon (list, build_tree_list (ivar, property));
15874 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15875 c_parser_consume_token (parser);
15876 else
15877 break;
15878 }
15879 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15880 objc_add_synthesize_declaration (loc, list);
15881}
15882
15883/* Parse an Objective-C @dynamic declaration. The syntax is:
15884
15885 objc-dynamic-declaration:
15886 @dynamic identifier-list ;
15887
15888 For example:
15889 @dynamic MyProperty;
15890 @dynamic MyProperty, AnotherProperty;
15891
15892 PS: This function is identical to cp_parser_objc_at_dynamic_declaration
15893 for C++. Keep them in sync.
15894*/
15895static void
15896c_parser_objc_at_dynamic_declaration (c_parser *parser)
15897{
15898 tree list = NULL_TREE;
15899 location_t loc;
15900 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
15901 loc = c_parser_peek_token (parser)->location;
15902
15903 c_parser_consume_token (parser);
15904 while (true)
15905 {
15906 tree property;
15907 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15908 {
15909 c_parser_error (parser, gmsgid: "expected identifier");
15910 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15911 parser->error = false;
15912 return;
15913 }
15914 property = c_parser_peek_token (parser)->value;
15915 list = chainon (list, build_tree_list (NULL_TREE, property));
15916 c_parser_consume_token (parser);
15917 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15918 c_parser_consume_token (parser);
15919 else
15920 break;
15921 }
15922 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15923 objc_add_dynamic_declaration (loc, list);
15924}
15925
15926
15927/* Parse a pragma GCC ivdep. */
15928
15929static bool
15930c_parse_pragma_ivdep (c_parser *parser)
15931{
15932 c_parser_consume_pragma (parser);
15933 c_parser_skip_to_pragma_eol (parser);
15934 return true;
15935}
15936
15937/* Parse a pragma GCC novector. */
15938
15939static bool
15940c_parse_pragma_novector (c_parser *parser)
15941{
15942 c_parser_consume_pragma (parser);
15943 c_parser_skip_to_pragma_eol (parser);
15944 return true;
15945}
15946
15947/* Parse a pragma GCC unroll. */
15948
15949static unsigned short
15950c_parser_pragma_unroll (c_parser *parser)
15951{
15952 unsigned short unroll;
15953 c_parser_consume_pragma (parser);
15954 location_t location = c_parser_peek_token (parser)->location;
15955 tree expr = c_parser_expr_no_commas (parser, NULL).value;
15956 mark_exp_read (expr);
15957 expr = c_fully_fold (expr, false, NULL);
15958 HOST_WIDE_INT lunroll = 0;
15959 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
15960 || TREE_CODE (expr) != INTEGER_CST
15961 || (lunroll = tree_to_shwi (expr)) < 0
15962 || lunroll >= USHRT_MAX)
15963 {
15964 error_at (location, "%<#pragma GCC unroll%> requires an"
15965 " assignment-expression that evaluates to a non-negative"
15966 " integral constant less than %u", USHRT_MAX);
15967 unroll = 0;
15968 }
15969 else
15970 {
15971 unroll = (unsigned short)lunroll;
15972 if (unroll == 0)
15973 unroll = 1;
15974 }
15975
15976 c_parser_skip_to_pragma_eol (parser);
15977 return unroll;
15978}
15979
15980/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
15981 should be considered, statements. ALLOW_STMT is true if we're within
15982 the context of a function and such pragmas are to be allowed. Returns
15983 true if we actually parsed such a pragma. BEFORE_LABELS is last statement
15984 before possible labels, see get_before_labels description for details. */
15985
15986static bool
15987c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
15988 tree before_labels)
15989{
15990 unsigned int id;
15991 const char *construct = NULL;
15992
15993 input_location = c_parser_peek_token (parser)->location;
15994 id = c_parser_peek_token (parser)->pragma_kind;
15995 gcc_assert (id != PRAGMA_NONE);
15996 if (parser->omp_for_parse_state
15997 && parser->omp_for_parse_state->in_intervening_code
15998 && id >= PRAGMA_OMP__START_ && id <= PRAGMA_OMP__LAST_
15999 /* Allow a safe subset of non-executable directives. See classification in
16000 array c_omp_directives. */
16001 && id != PRAGMA_OMP_METADIRECTIVE && id != PRAGMA_OMP_NOTHING
16002 && id != PRAGMA_OMP_ASSUME && id != PRAGMA_OMP_ERROR)
16003 {
16004 error_at (
16005 input_location,
16006 "intervening code must not contain executable OpenMP directives");
16007 parser->omp_for_parse_state->fail = true;
16008 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16009 return false;
16010 }
16011
16012 switch (id)
16013 {
16014 case PRAGMA_OACC_DECLARE:
16015 c_parser_oacc_declare (parser);
16016 return false;
16017
16018 case PRAGMA_OACC_ENTER_DATA:
16019 if (context != pragma_compound)
16020 {
16021 construct = "acc enter data";
16022 in_compound:
16023 if (context == pragma_stmt)
16024 {
16025 error_at (c_parser_peek_token (parser)->location,
16026 "%<#pragma %s%> may only be used in compound "
16027 "statements", construct);
16028 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16029 return true;
16030 }
16031 goto bad_stmt;
16032 }
16033 c_parser_oacc_enter_exit_data (parser, true);
16034 return false;
16035
16036 case PRAGMA_OACC_EXIT_DATA:
16037 if (context != pragma_compound)
16038 {
16039 construct = "acc exit data";
16040 goto in_compound;
16041 }
16042 c_parser_oacc_enter_exit_data (parser, false);
16043 return false;
16044
16045 case PRAGMA_OACC_ROUTINE:
16046 if (context != pragma_external)
16047 {
16048 error_at (c_parser_peek_token (parser)->location,
16049 "%<#pragma acc routine%> must be at file scope");
16050 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16051 return false;
16052 }
16053 c_parser_oacc_routine (parser, context);
16054 return false;
16055
16056 case PRAGMA_OACC_UPDATE:
16057 if (context != pragma_compound)
16058 {
16059 construct = "acc update";
16060 goto in_compound;
16061 }
16062 c_parser_oacc_update (parser);
16063 return false;
16064
16065 case PRAGMA_OMP_BARRIER:
16066 if (context != pragma_compound)
16067 {
16068 construct = "omp barrier";
16069 goto in_compound;
16070 }
16071 c_parser_omp_barrier (parser);
16072 return false;
16073
16074 case PRAGMA_OMP_DEPOBJ:
16075 if (context != pragma_compound)
16076 {
16077 construct = "omp depobj";
16078 goto in_compound;
16079 }
16080 c_parser_omp_depobj (parser);
16081 return false;
16082
16083 case PRAGMA_OMP_FLUSH:
16084 if (context != pragma_compound)
16085 {
16086 construct = "omp flush";
16087 goto in_compound;
16088 }
16089 c_parser_omp_flush (parser);
16090 return false;
16091
16092 case PRAGMA_OMP_INTEROP:
16093 if (context != pragma_compound)
16094 {
16095 construct = "omp interop";
16096 goto in_compound;
16097 }
16098 c_parser_omp_interop (parser);
16099 return false;
16100
16101 case PRAGMA_OMP_TASKWAIT:
16102 if (context != pragma_compound)
16103 {
16104 construct = "omp taskwait";
16105 goto in_compound;
16106 }
16107 c_parser_omp_taskwait (parser);
16108 return false;
16109
16110 case PRAGMA_OMP_TASKYIELD:
16111 if (context != pragma_compound)
16112 {
16113 construct = "omp taskyield";
16114 goto in_compound;
16115 }
16116 c_parser_omp_taskyield (parser);
16117 return false;
16118
16119 case PRAGMA_OMP_CANCEL:
16120 if (context != pragma_compound)
16121 {
16122 construct = "omp cancel";
16123 goto in_compound;
16124 }
16125 c_parser_omp_cancel (parser);
16126 return false;
16127
16128 case PRAGMA_OMP_CANCELLATION_POINT:
16129 return c_parser_omp_cancellation_point (parser, context);
16130
16131 case PRAGMA_OMP_GROUPPRIVATE:
16132 c_parser_omp_groupprivate (parser);
16133 return false;
16134
16135 case PRAGMA_OMP_THREADPRIVATE:
16136 c_parser_omp_threadprivate (parser);
16137 return false;
16138
16139 case PRAGMA_OMP_TARGET:
16140 return c_parser_omp_target (parser, context, if_p);
16141
16142 case PRAGMA_OMP_BEGIN:
16143 c_parser_omp_begin (parser);
16144 return false;
16145
16146 case PRAGMA_OMP_END:
16147 c_parser_omp_end (parser);
16148 return false;
16149
16150 case PRAGMA_OMP_SCAN:
16151 error_at (c_parser_peek_token (parser)->location,
16152 "%<#pragma omp scan%> may only be used in "
16153 "a loop construct with %<inscan%> %<reduction%> clause");
16154 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16155 return false;
16156
16157 case PRAGMA_OMP_SECTION:
16158 error_at (c_parser_peek_token (parser)->location,
16159 "%<#pragma omp section%> may only be used in "
16160 "%<#pragma omp sections%> construct");
16161 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16162 return false;
16163
16164 case PRAGMA_OMP_DECLARE:
16165 return c_parser_omp_declare (parser, context);
16166
16167 case PRAGMA_OMP_REQUIRES:
16168 if (context != pragma_external)
16169 {
16170 error_at (c_parser_peek_token (parser)->location,
16171 "%<#pragma %s%> may only be used at file scope",
16172 "omp requires");
16173 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16174 return false;
16175 }
16176 c_parser_omp_requires (parser);
16177 return false;
16178
16179 case PRAGMA_OMP_ALLOCATE:
16180 c_parser_omp_allocate (parser);
16181 return false;
16182
16183 case PRAGMA_OMP_ASSUMES:
16184 if (context != pragma_external)
16185 {
16186 error_at (c_parser_peek_token (parser)->location,
16187 "%<#pragma %s%> may only be used at file scope",
16188 "omp assumes");
16189 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16190 return false;
16191 }
16192 c_parser_omp_assumes (parser);
16193 return false;
16194
16195 case PRAGMA_OMP_NOTHING:
16196 c_parser_omp_nothing (parser);
16197 return false;
16198
16199 case PRAGMA_OMP_METADIRECTIVE:
16200 c_parser_omp_metadirective (parser, if_p);
16201 return true;
16202
16203 case PRAGMA_OMP_ERROR:
16204 return c_parser_omp_error (parser, context);
16205
16206 case PRAGMA_OMP_ORDERED:
16207 return c_parser_omp_ordered (parser, context, if_p);
16208
16209 case PRAGMA_NOVECTOR:
16210 case PRAGMA_UNROLL:
16211 case PRAGMA_IVDEP:
16212 {
16213 bool novector = false;
16214 unsigned short unroll = 0;
16215 bool ivdep = false;
16216
16217 switch (id)
16218 {
16219 case PRAGMA_NOVECTOR:
16220 novector = c_parse_pragma_novector (parser);
16221 break;
16222 case PRAGMA_UNROLL:
16223 unroll = c_parser_pragma_unroll (parser);
16224 break;
16225 case PRAGMA_IVDEP:
16226 ivdep = c_parse_pragma_ivdep (parser);
16227 break;
16228 default:
16229 gcc_unreachable ();
16230 }
16231
16232 c_token *tok = c_parser_peek_token (parser);
16233 bool has_more = tok->type == CPP_PRAGMA;
16234 while (has_more)
16235 {
16236 switch (tok->pragma_kind)
16237 {
16238 case PRAGMA_IVDEP:
16239 ivdep = c_parse_pragma_ivdep (parser);
16240 break;
16241 case PRAGMA_UNROLL:
16242 unroll = c_parser_pragma_unroll (parser);
16243 break;
16244 case PRAGMA_NOVECTOR:
16245 novector = c_parse_pragma_novector (parser);
16246 break;
16247 default:
16248 has_more = false;
16249 break;
16250 }
16251 tok = c_parser_peek_token (parser);
16252 has_more = has_more && tok->type == CPP_PRAGMA;
16253 }
16254 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR)
16255 && !c_parser_next_token_is_keyword (parser, keyword: RID_WHILE)
16256 && !c_parser_next_token_is_keyword (parser, keyword: RID_DO))
16257 {
16258 c_parser_error (parser, gmsgid: "for, while or do statement expected");
16259 return false;
16260 }
16261 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
16262 c_parser_for_statement (parser, ivdep, unroll, novector, if_p,
16263 before_labels);
16264 else if (c_parser_next_token_is_keyword (parser, keyword: RID_WHILE))
16265 c_parser_while_statement (parser, ivdep, unroll, novector, if_p,
16266 before_labels);
16267 else
16268 c_parser_do_statement (parser, ivdep, unroll, novector,
16269 before_labels);
16270 }
16271 return true;
16272
16273 case PRAGMA_GCC_PCH_PREPROCESS:
16274 c_parser_error (parser, gmsgid: "%<#pragma GCC pch_preprocess%> must be first");
16275 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16276 return false;
16277
16278 case PRAGMA_OACC_WAIT:
16279 if (context != pragma_compound)
16280 {
16281 construct = "acc wait";
16282 goto in_compound;
16283 }
16284 /* FALL THROUGH. */
16285
16286 default:
16287 if (id < PRAGMA_FIRST_EXTERNAL)
16288 {
16289 if (context != pragma_stmt && context != pragma_compound)
16290 {
16291 bad_stmt:
16292 c_parser_error (parser, gmsgid: "expected declaration specifiers");
16293 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16294 return false;
16295 }
16296 c_parser_omp_construct (parser, if_p);
16297 return true;
16298 }
16299 break;
16300 }
16301
16302 c_parser_consume_pragma (parser);
16303 c_invoke_pragma_handler (id);
16304
16305 /* Skip to EOL, but suppress any error message. Those will have been
16306 generated by the handler routine through calling error, as opposed
16307 to calling c_parser_error. */
16308 parser->error = true;
16309 c_parser_skip_to_pragma_eol (parser);
16310
16311 return false;
16312}
16313
16314/* The interface the pragma parsers have to the lexer. */
16315
16316enum cpp_ttype
16317pragma_lex (tree *value, location_t *loc)
16318{
16319 c_token *tok = c_parser_peek_token (parser: the_parser);
16320 enum cpp_ttype ret = tok->type;
16321
16322 *value = tok->value;
16323 if (loc)
16324 *loc = tok->location;
16325
16326 if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
16327 ret = CPP_EOF;
16328 else if (ret == CPP_STRING)
16329 *value = c_parser_string_literal (parser: the_parser, translate: false, wide_ok: false).value;
16330 else
16331 {
16332 if (ret == CPP_KEYWORD)
16333 ret = CPP_NAME;
16334 c_parser_consume_token (parser: the_parser);
16335 }
16336
16337 return ret;
16338}
16339
16340void
16341pragma_lex_discard_to_eol ()
16342{
16343 cpp_ttype type;
16344 do
16345 {
16346 type = c_parser_peek_token (parser: the_parser)->type;
16347 gcc_assert (type != CPP_EOF);
16348 c_parser_consume_token (parser: the_parser);
16349 } while (type != CPP_PRAGMA_EOL);
16350}
16351
16352static void
16353c_parser_pragma_pch_preprocess (c_parser *parser)
16354{
16355 tree name = NULL;
16356
16357 parser->lex_joined_string = true;
16358 c_parser_consume_pragma (parser);
16359 if (c_parser_next_token_is (parser, type: CPP_STRING))
16360 {
16361 name = c_parser_peek_token (parser)->value;
16362 c_parser_consume_token (parser);
16363 }
16364 else
16365 c_parser_error (parser, gmsgid: "expected string literal");
16366 c_parser_skip_to_pragma_eol (parser);
16367 parser->lex_joined_string = false;
16368
16369 if (name)
16370 c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name));
16371}
16372
16373/* OpenACC and OpenMP parsing routines. */
16374
16375/* Returns name of the next clause.
16376 If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
16377 the token is not consumed. Otherwise appropriate pragma_omp_clause is
16378 returned and the token is consumed. */
16379
16380static pragma_omp_clause
16381c_parser_omp_clause_name (c_parser *parser)
16382{
16383 pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
16384
16385 if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
16386 result = PRAGMA_OACC_CLAUSE_AUTO;
16387 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IF))
16388 result = PRAGMA_OMP_CLAUSE_IF;
16389 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
16390 result = PRAGMA_OMP_CLAUSE_DEFAULT;
16391 else if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
16392 result = PRAGMA_OMP_CLAUSE_FOR;
16393 else if (c_parser_next_token_is (parser, type: CPP_NAME))
16394 {
16395 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16396
16397 switch (p[0])
16398 {
16399 case 'a':
16400 if (!strcmp (s1: "affinity", s2: p))
16401 result = PRAGMA_OMP_CLAUSE_AFFINITY;
16402 else if (!strcmp (s1: "aligned", s2: p))
16403 result = PRAGMA_OMP_CLAUSE_ALIGNED;
16404 else if (!strcmp (s1: "allocate", s2: p))
16405 result = PRAGMA_OMP_CLAUSE_ALLOCATE;
16406 else if (!strcmp (s1: "async", s2: p))
16407 result = PRAGMA_OACC_CLAUSE_ASYNC;
16408 else if (!strcmp (s1: "attach", s2: p))
16409 result = PRAGMA_OACC_CLAUSE_ATTACH;
16410 break;
16411 case 'b':
16412 if (!strcmp (s1: "bind", s2: p))
16413 result = PRAGMA_OMP_CLAUSE_BIND;
16414 break;
16415 case 'c':
16416 if (!strcmp (s1: "collapse", s2: p))
16417 result = PRAGMA_OMP_CLAUSE_COLLAPSE;
16418 else if (!strcmp (s1: "copy", s2: p))
16419 result = PRAGMA_OACC_CLAUSE_COPY;
16420 else if (!strcmp (s1: "copyin", s2: p))
16421 result = PRAGMA_OMP_CLAUSE_COPYIN;
16422 else if (!strcmp (s1: "copyout", s2: p))
16423 result = PRAGMA_OACC_CLAUSE_COPYOUT;
16424 else if (!strcmp (s1: "copyprivate", s2: p))
16425 result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
16426 else if (!strcmp (s1: "create", s2: p))
16427 result = PRAGMA_OACC_CLAUSE_CREATE;
16428 break;
16429 case 'd':
16430 if (!strcmp (s1: "defaultmap", s2: p))
16431 result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
16432 else if (!strcmp (s1: "delete", s2: p))
16433 result = PRAGMA_OACC_CLAUSE_DELETE;
16434 else if (!strcmp (s1: "depend", s2: p))
16435 result = PRAGMA_OMP_CLAUSE_DEPEND;
16436 else if (!strcmp (s1: "destroy", s2: p))
16437 result = PRAGMA_OMP_CLAUSE_DESTROY;
16438 else if (!strcmp (s1: "detach", s2: p))
16439 result = PRAGMA_OACC_CLAUSE_DETACH;
16440 else if (!strcmp (s1: "device", s2: p))
16441 result = PRAGMA_OMP_CLAUSE_DEVICE;
16442 else if (!strcmp (s1: "deviceptr", s2: p))
16443 result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
16444 else if (!strcmp (s1: "device_resident", s2: p))
16445 result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
16446 else if (!strcmp (s1: "device_type", s2: p))
16447 result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
16448 else if (!strcmp (s1: "dist_schedule", s2: p))
16449 result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
16450 else if (!strcmp (s1: "doacross", s2: p))
16451 result = PRAGMA_OMP_CLAUSE_DOACROSS;
16452 else if (!strcmp (s1: "dyn_groupprivate", s2: p))
16453 result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
16454 break;
16455 case 'e':
16456 if (!strcmp (s1: "enter", s2: p))
16457 result = PRAGMA_OMP_CLAUSE_ENTER;
16458 break;
16459 case 'f':
16460 if (!strcmp (s1: "filter", s2: p))
16461 result = PRAGMA_OMP_CLAUSE_FILTER;
16462 else if (!strcmp (s1: "final", s2: p))
16463 result = PRAGMA_OMP_CLAUSE_FINAL;
16464 else if (!strcmp (s1: "finalize", s2: p))
16465 result = PRAGMA_OACC_CLAUSE_FINALIZE;
16466 else if (!strcmp (s1: "firstprivate", s2: p))
16467 result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
16468 else if (!strcmp (s1: "from", s2: p))
16469 result = PRAGMA_OMP_CLAUSE_FROM;
16470 else if (!strcmp (s1: "full", s2: p))
16471 result = PRAGMA_OMP_CLAUSE_FULL;
16472 break;
16473 case 'g':
16474 if (!strcmp (s1: "gang", s2: p))
16475 result = PRAGMA_OACC_CLAUSE_GANG;
16476 else if (!strcmp (s1: "grainsize", s2: p))
16477 result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
16478 break;
16479 case 'h':
16480 if (!strcmp (s1: "has_device_addr", s2: p))
16481 result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
16482 else if (!strcmp (s1: "hint", s2: p))
16483 result = PRAGMA_OMP_CLAUSE_HINT;
16484 else if (!strcmp (s1: "host", s2: p))
16485 result = PRAGMA_OACC_CLAUSE_HOST;
16486 break;
16487 case 'i':
16488 if (!strcmp (s1: "if_present", s2: p))
16489 result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
16490 else if (!strcmp (s1: "in_reduction", s2: p))
16491 result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
16492 else if (!strcmp (s1: "inbranch", s2: p))
16493 result = PRAGMA_OMP_CLAUSE_INBRANCH;
16494 else if (!strcmp (s1: "independent", s2: p))
16495 result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
16496 else if (!strcmp (s1: "indirect", s2: p))
16497 result = PRAGMA_OMP_CLAUSE_INDIRECT;
16498 else if (!strcmp (s1: "init", s2: p))
16499 result = PRAGMA_OMP_CLAUSE_INIT;
16500 else if (!strcmp (s1: "is_device_ptr", s2: p))
16501 result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
16502 else if (!strcmp (s1: "interop", s2: p))
16503 result = PRAGMA_OMP_CLAUSE_INTEROP;
16504 break;
16505 case 'l':
16506 if (!strcmp (s1: "lastprivate", s2: p))
16507 result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
16508 else if (!strcmp (s1: "linear", s2: p))
16509 result = PRAGMA_OMP_CLAUSE_LINEAR;
16510 else if (!strcmp (s1: "link", s2: p))
16511 result = PRAGMA_OMP_CLAUSE_LINK;
16512 break;
16513 case 'm':
16514 if (!strcmp (s1: "map", s2: p))
16515 result = PRAGMA_OMP_CLAUSE_MAP;
16516 else if (!strcmp (s1: "mergeable", s2: p))
16517 result = PRAGMA_OMP_CLAUSE_MERGEABLE;
16518 break;
16519 case 'n':
16520 if (!strcmp (s1: "no_create", s2: p))
16521 result = PRAGMA_OACC_CLAUSE_NO_CREATE;
16522 else if (!strcmp (s1: "nocontext", s2: p))
16523 result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
16524 else if (!strcmp (s1: "nogroup", s2: p))
16525 result = PRAGMA_OMP_CLAUSE_NOGROUP;
16526 else if (!strcmp (s1: "nohost", s2: p))
16527 result = PRAGMA_OACC_CLAUSE_NOHOST;
16528 else if (!strcmp (s1: "nontemporal", s2: p))
16529 result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
16530 else if (!strcmp (s1: "notinbranch", s2: p))
16531 result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
16532 else if (!strcmp (s1: "novariants", s2: p))
16533 result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
16534 else if (!strcmp (s1: "nowait", s2: p))
16535 result = PRAGMA_OMP_CLAUSE_NOWAIT;
16536 else if (!strcmp (s1: "num_gangs", s2: p))
16537 result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
16538 else if (!strcmp (s1: "num_tasks", s2: p))
16539 result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
16540 else if (!strcmp (s1: "num_teams", s2: p))
16541 result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
16542 else if (!strcmp (s1: "num_threads", s2: p))
16543 result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
16544 else if (!strcmp (s1: "num_workers", s2: p))
16545 result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
16546 break;
16547 case 'o':
16548 if (!strcmp (s1: "ordered", s2: p))
16549 result = PRAGMA_OMP_CLAUSE_ORDERED;
16550 else if (!strcmp (s1: "order", s2: p))
16551 result = PRAGMA_OMP_CLAUSE_ORDER;
16552 break;
16553 case 'p':
16554 if (!strcmp (s1: "parallel", s2: p))
16555 result = PRAGMA_OMP_CLAUSE_PARALLEL;
16556 else if (!strcmp (s1: "partial", s2: p))
16557 result = PRAGMA_OMP_CLAUSE_PARTIAL;
16558 else if (!strcmp (s1: "present", s2: p))
16559 result = PRAGMA_OACC_CLAUSE_PRESENT;
16560 /* As of OpenACC 2.5, these are now aliases of the non-present_or
16561 clauses. */
16562 else if (!strcmp (s1: "present_or_copy", s2: p)
16563 || !strcmp (s1: "pcopy", s2: p))
16564 result = PRAGMA_OACC_CLAUSE_COPY;
16565 else if (!strcmp (s1: "present_or_copyin", s2: p)
16566 || !strcmp (s1: "pcopyin", s2: p))
16567 result = PRAGMA_OACC_CLAUSE_COPYIN;
16568 else if (!strcmp (s1: "present_or_copyout", s2: p)
16569 || !strcmp (s1: "pcopyout", s2: p))
16570 result = PRAGMA_OACC_CLAUSE_COPYOUT;
16571 else if (!strcmp (s1: "present_or_create", s2: p)
16572 || !strcmp (s1: "pcreate", s2: p))
16573 result = PRAGMA_OACC_CLAUSE_CREATE;
16574 else if (!strcmp (s1: "priority", s2: p))
16575 result = PRAGMA_OMP_CLAUSE_PRIORITY;
16576 else if (!strcmp (s1: "private", s2: p))
16577 result = PRAGMA_OMP_CLAUSE_PRIVATE;
16578 else if (!strcmp (s1: "proc_bind", s2: p))
16579 result = PRAGMA_OMP_CLAUSE_PROC_BIND;
16580 break;
16581 case 'r':
16582 if (!strcmp (s1: "reduction", s2: p))
16583 result = PRAGMA_OMP_CLAUSE_REDUCTION;
16584 break;
16585 case 's':
16586 if (!strcmp (s1: "safelen", s2: p))
16587 result = PRAGMA_OMP_CLAUSE_SAFELEN;
16588 else if (!strcmp (s1: "schedule", s2: p))
16589 result = PRAGMA_OMP_CLAUSE_SCHEDULE;
16590 else if (!strcmp (s1: "sections", s2: p))
16591 result = PRAGMA_OMP_CLAUSE_SECTIONS;
16592 else if (!strcmp (s1: "self", s2: p))
16593 result = PRAGMA_OACC_CLAUSE_SELF;
16594 else if (!strcmp (s1: "seq", s2: p))
16595 result = PRAGMA_OACC_CLAUSE_SEQ;
16596 else if (!strcmp (s1: "shared", s2: p))
16597 result = PRAGMA_OMP_CLAUSE_SHARED;
16598 else if (!strcmp (s1: "simd", s2: p))
16599 result = PRAGMA_OMP_CLAUSE_SIMD;
16600 else if (!strcmp (s1: "simdlen", s2: p))
16601 result = PRAGMA_OMP_CLAUSE_SIMDLEN;
16602 break;
16603 case 't':
16604 if (!strcmp (s1: "task_reduction", s2: p))
16605 result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
16606 else if (!strcmp (s1: "taskgroup", s2: p))
16607 result = PRAGMA_OMP_CLAUSE_TASKGROUP;
16608 else if (!strcmp (s1: "thread_limit", s2: p))
16609 result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
16610 else if (!strcmp (s1: "threads", s2: p))
16611 result = PRAGMA_OMP_CLAUSE_THREADS;
16612 else if (!strcmp (s1: "tile", s2: p))
16613 result = PRAGMA_OACC_CLAUSE_TILE;
16614 else if (!strcmp (s1: "to", s2: p))
16615 result = PRAGMA_OMP_CLAUSE_TO;
16616 break;
16617 case 'u':
16618 if (!strcmp (s1: "uniform", s2: p))
16619 result = PRAGMA_OMP_CLAUSE_UNIFORM;
16620 else if (!strcmp (s1: "untied", s2: p))
16621 result = PRAGMA_OMP_CLAUSE_UNTIED;
16622 else if (!strcmp (s1: "use", s2: p))
16623 result = PRAGMA_OMP_CLAUSE_USE;
16624 else if (!strcmp (s1: "use_device", s2: p))
16625 result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
16626 else if (!strcmp (s1: "use_device_addr", s2: p))
16627 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
16628 else if (!strcmp (s1: "use_device_ptr", s2: p))
16629 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
16630 else if (!strcmp (s1: "uses_allocators", s2: p))
16631 result = PRAGMA_OMP_CLAUSE_USES_ALLOCATORS;
16632 break;
16633 case 'v':
16634 if (!strcmp (s1: "vector", s2: p))
16635 result = PRAGMA_OACC_CLAUSE_VECTOR;
16636 else if (!strcmp (s1: "vector_length", s2: p))
16637 result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
16638 break;
16639 case 'w':
16640 if (!strcmp (s1: "wait", s2: p))
16641 result = PRAGMA_OACC_CLAUSE_WAIT;
16642 else if (!strcmp (s1: "worker", s2: p))
16643 result = PRAGMA_OACC_CLAUSE_WORKER;
16644 break;
16645 }
16646 }
16647
16648 if (result != PRAGMA_OMP_CLAUSE_NONE)
16649 c_parser_consume_token (parser);
16650
16651 return result;
16652}
16653
16654/* Validate that a clause of the given type does not already exist. */
16655
16656static void
16657check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
16658 const char *name)
16659{
16660 if (tree c = omp_find_clause (clauses, kind: code))
16661 error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
16662}
16663
16664/* OpenACC 2.0
16665 Parse wait clause or wait directive parameters. */
16666
16667static tree
16668c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
16669{
16670 vec<tree, va_gc> *args;
16671 tree t, args_tree;
16672
16673 matching_parens parens;
16674 if (!parens.require_open (parser))
16675 return list;
16676
16677 args = c_parser_expr_list (parser, convert_p: false, fold_p: true, NULL, NULL, NULL, NULL);
16678 args_tree = build_tree_list_vec (args);
16679
16680 for (t = args_tree; t; t = TREE_CHAIN (t))
16681 {
16682 tree targ = TREE_VALUE (t);
16683
16684 if (targ != error_mark_node)
16685 {
16686 if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
16687 {
16688 c_parser_error (parser, gmsgid: "expression must be integral");
16689 targ = error_mark_node;
16690 }
16691 else
16692 {
16693 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16694
16695 OMP_CLAUSE_DECL (c) = targ;
16696 OMP_CLAUSE_CHAIN (c) = list;
16697 list = c;
16698 }
16699 }
16700 }
16701
16702 release_tree_vector (args);
16703 parens.require_close (parser);
16704 return list;
16705}
16706
16707/* OpenACC 2.0, OpenMP 2.5:
16708 variable-list:
16709 identifier
16710 variable-list , identifier
16711
16712 If KIND is nonzero, create the appropriate node and install the
16713 decl in OMP_CLAUSE_DECL and add the node to the head of the list.
16714 If KIND is nonzero, CLAUSE_LOC is the location of the clause.
16715
16716 If KIND is zero (= OMP_CLAUSE_ERROR), create a TREE_LIST with the decl
16717 in TREE_PURPOSE and the location in TREE_VALUE (accessible using
16718 EXPR_LOCATION); return the list created.
16719
16720 The optional ALLOW_DEREF argument is true if list items can use the deref
16721 (->) operator. */
16722
16723struct omp_dim
16724{
16725 tree low_bound, length;
16726 location_t loc;
16727 bool no_colon;
16728 omp_dim (tree lb, tree len, location_t lo, bool nc)
16729 : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
16730};
16731
16732static tree
16733c_parser_omp_variable_list (c_parser *parser,
16734 location_t clause_loc,
16735 enum omp_clause_code kind, tree list,
16736 bool map_lvalue = false)
16737{
16738 auto_vec<omp_dim> dims;
16739 bool array_section_p;
16740 auto_vec<c_token> tokens;
16741 unsigned int tokens_avail = 0;
16742 c_token *saved_tokens = NULL;
16743
16744 while (1)
16745 {
16746 tree t = NULL_TREE;
16747 location_t tloc = c_parser_peek_token (parser)->location;
16748
16749 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16750 {
16751 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
16752 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
16753 {
16754 struct c_expr expr;
16755 if (kind == OMP_CLAUSE_DEPEND
16756 && c_parser_next_token_is_keyword (parser,
16757 keyword: RID_OMP_ALL_MEMORY)
16758 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16759 || (c_parser_peek_2nd_token (parser)->type
16760 == CPP_CLOSE_PAREN)))
16761 {
16762 expr.value = ridpointers[RID_OMP_ALL_MEMORY];
16763 c_parser_consume_token (parser);
16764 }
16765 else
16766 expr = c_parser_expr_no_commas (parser, NULL);
16767 if (expr.value != error_mark_node)
16768 {
16769 tree u = build_omp_clause (clause_loc, kind);
16770 OMP_CLAUSE_DECL (u) = expr.value;
16771 OMP_CLAUSE_CHAIN (u) = list;
16772 list = u;
16773 }
16774
16775 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
16776 break;
16777
16778 c_parser_consume_token (parser);
16779 continue;
16780 }
16781
16782 tokens.truncate (size: 0);
16783 unsigned int nesting_depth = 0;
16784 while (1)
16785 {
16786 c_token *token = c_parser_peek_token (parser);
16787 switch (token->type)
16788 {
16789 case CPP_EOF:
16790 case CPP_PRAGMA_EOL:
16791 break;
16792 case CPP_OPEN_BRACE:
16793 case CPP_OPEN_PAREN:
16794 case CPP_OPEN_SQUARE:
16795 ++nesting_depth;
16796 goto add;
16797 case CPP_CLOSE_BRACE:
16798 case CPP_CLOSE_PAREN:
16799 case CPP_CLOSE_SQUARE:
16800 if (nesting_depth-- == 0)
16801 break;
16802 goto add;
16803 case CPP_COMMA:
16804 if (nesting_depth == 0)
16805 break;
16806 goto add;
16807 default:
16808 add:
16809 tokens.safe_push (obj: *token);
16810 c_parser_consume_token (parser);
16811 continue;
16812 }
16813 break;
16814 }
16815
16816 /* Make sure nothing tries to read past the end of the tokens. */
16817 c_token eof_token;
16818 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
16819 eof_token.type = CPP_EOF;
16820 tokens.safe_push (obj: eof_token);
16821 tokens.safe_push (obj: eof_token);
16822
16823 saved_tokens = parser->tokens;
16824 tokens_avail = parser->tokens_avail;
16825 parser->tokens = tokens.address ();
16826 parser->tokens_avail = tokens.length ();
16827 }
16828 else if (map_lvalue
16829 && (kind == OMP_CLAUSE_MAP
16830 || kind == OMP_CLAUSE_TO
16831 || kind == OMP_CLAUSE_FROM))
16832 {
16833 location_t loc = c_parser_peek_token (parser)->location;
16834 bool save_c_omp_array_section_p = c_omp_array_section_p;
16835 c_omp_array_section_p = true;
16836 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16837 if (expr.value != error_mark_node)
16838 mark_exp_read (expr.value);
16839 c_omp_array_section_p = save_c_omp_array_section_p;
16840 tree decl = expr.value;
16841
16842 /* This code rewrites a parsed expression containing various tree
16843 codes used to represent array accesses into a more uniform nest of
16844 OMP_ARRAY_SECTION nodes before it is processed by
16845 c-typeck.cc:handle_omp_array_sections_1. It might be more
16846 efficient to move this logic to that function instead, analysing
16847 the parsed expression directly rather than this preprocessed
16848 form. (See also equivalent code in cp/parser.cc,
16849 cp/semantics.cc). */
16850 dims.truncate (size: 0);
16851 if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16852 {
16853 while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16854 {
16855 tree low_bound = TREE_OPERAND (decl, 1);
16856 tree length = TREE_OPERAND (decl, 2);
16857 dims.safe_push (obj: omp_dim (low_bound, length, loc, false));
16858 decl = TREE_OPERAND (decl, 0);
16859 }
16860
16861 while (TREE_CODE (decl) == ARRAY_REF
16862 || TREE_CODE (decl) == INDIRECT_REF
16863 || TREE_CODE (decl) == COMPOUND_EXPR)
16864 {
16865 if (TREE_CODE (decl) == COMPOUND_EXPR)
16866 {
16867 decl = TREE_OPERAND (decl, 1);
16868 STRIP_NOPS (decl);
16869 }
16870 else if (TREE_CODE (decl) == INDIRECT_REF)
16871 {
16872 dims.safe_push (obj: omp_dim (integer_zero_node,
16873 integer_one_node, loc, true));
16874 decl = TREE_OPERAND (decl, 0);
16875 }
16876 else /* ARRAY_REF. */
16877 {
16878 tree index = TREE_OPERAND (decl, 1);
16879 dims.safe_push (obj: omp_dim (index, integer_one_node, loc,
16880 true));
16881 decl = TREE_OPERAND (decl, 0);
16882 }
16883 }
16884
16885 for (int i = dims.length () - 1; i >= 0; i--)
16886 decl = build_omp_array_section (loc, decl, dims[i].low_bound,
16887 dims[i].length);
16888 }
16889 else if (TREE_CODE (decl) == INDIRECT_REF)
16890 {
16891 /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
16892 decl = TREE_OPERAND (decl, 0);
16893 STRIP_NOPS (decl);
16894
16895 decl = build_omp_array_section (loc, decl, integer_zero_node,
16896 integer_one_node);
16897 }
16898 else if (TREE_CODE (decl) == ARRAY_REF)
16899 {
16900 tree idx = TREE_OPERAND (decl, 1);
16901
16902 decl = TREE_OPERAND (decl, 0);
16903 STRIP_NOPS (decl);
16904
16905 decl = build_omp_array_section (loc, decl, idx, integer_one_node);
16906 }
16907 else if (TREE_CODE (decl) == NON_LVALUE_EXPR
16908 || CONVERT_EXPR_P (decl))
16909 decl = TREE_OPERAND (decl, 0);
16910
16911 tree u = build_omp_clause (loc, kind);
16912 OMP_CLAUSE_DECL (u) = decl;
16913 OMP_CLAUSE_CHAIN (u) = list;
16914 list = u;
16915
16916 goto next_item;
16917 }
16918
16919 if (c_parser_next_token_is (parser, type: CPP_NAME)
16920 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
16921 {
16922 t = lookup_name (c_parser_peek_token (parser)->value);
16923
16924 if (t == NULL_TREE)
16925 {
16926 undeclared_variable (c_parser_peek_token (parser)->location,
16927 c_parser_peek_token (parser)->value);
16928 t = error_mark_node;
16929 }
16930
16931 c_parser_consume_token (parser);
16932 }
16933 else if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
16934 && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
16935 || (c_parser_peek_token (parser)->keyword
16936 == RID_PRETTY_FUNCTION_NAME)
16937 || (c_parser_peek_token (parser)->keyword
16938 == RID_C99_FUNCTION_NAME)))
16939 t = c_parser_predefined_identifier (parser).value;
16940 else
16941 {
16942 c_parser_error (parser, gmsgid: "expected identifier");
16943 break;
16944 }
16945
16946 if (t == error_mark_node)
16947 ;
16948 else if (kind != 0) /* kind != OMP_CLAUSE_ERROR */
16949 {
16950 switch (kind)
16951 {
16952 case OMP_CLAUSE__CACHE_:
16953 /* The OpenACC cache directive explicitly only allows "array
16954 elements or subarrays". */
16955 if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
16956 {
16957 c_parser_error (parser, gmsgid: "expected %<[%>");
16958 t = error_mark_node;
16959 break;
16960 }
16961 /* FALLTHROUGH */
16962 case OMP_CLAUSE_MAP:
16963 case OMP_CLAUSE_FROM:
16964 case OMP_CLAUSE_TO:
16965 start_component_ref:
16966 while (c_parser_next_token_is (parser, type: CPP_DOT)
16967 || c_parser_next_token_is (parser, type: CPP_DEREF))
16968 {
16969 location_t op_loc = c_parser_peek_token (parser)->location;
16970 location_t arrow_loc = UNKNOWN_LOCATION;
16971 if (c_parser_next_token_is (parser, type: CPP_DEREF))
16972 {
16973 c_expr t_expr;
16974 t_expr.value = t;
16975 t_expr.original_code = ERROR_MARK;
16976 t_expr.original_type = NULL;
16977 set_c_expr_source_range (expr: &t_expr, start: op_loc, finish: op_loc);
16978 t_expr.m_decimal = 0;
16979 t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
16980 true, false);
16981 t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
16982 arrow_loc = t_expr.get_location ();
16983 }
16984 c_parser_consume_token (parser);
16985 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16986 {
16987 c_parser_error (parser, gmsgid: "expected identifier");
16988 t = error_mark_node;
16989 break;
16990 }
16991
16992 c_token *comp_tok = c_parser_peek_token (parser);
16993 tree ident = comp_tok->value;
16994 location_t comp_loc = comp_tok->location;
16995 c_parser_consume_token (parser);
16996 t = build_component_ref (op_loc, t, ident, comp_loc,
16997 arrow_loc);
16998 }
16999 /* FALLTHROUGH */
17000 case OMP_CLAUSE_AFFINITY:
17001 case OMP_CLAUSE_DEPEND:
17002 case OMP_CLAUSE_REDUCTION:
17003 case OMP_CLAUSE_IN_REDUCTION:
17004 case OMP_CLAUSE_TASK_REDUCTION:
17005 case OMP_CLAUSE_HAS_DEVICE_ADDR:
17006 array_section_p = false;
17007 dims.truncate (size: 0);
17008 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
17009 {
17010 location_t loc = UNKNOWN_LOCATION;
17011 tree low_bound = NULL_TREE, length = NULL_TREE;
17012 bool no_colon = false;
17013
17014 c_parser_consume_token (parser);
17015 if (!c_parser_next_token_is (parser, type: CPP_COLON))
17016 {
17017 location_t expr_loc
17018 = c_parser_peek_token (parser)->location;
17019 c_expr expr = c_parser_expression (parser);
17020 expr = convert_lvalue_to_rvalue (expr_loc, expr,
17021 false, true);
17022 low_bound = expr.value;
17023 loc = expr_loc;
17024 }
17025 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
17026 {
17027 length = integer_one_node;
17028 no_colon = true;
17029 }
17030 else
17031 {
17032 /* Look for `:'. */
17033 if (!c_parser_require (parser, type: CPP_COLON,
17034 msgid: "expected %<:%>"))
17035 {
17036 t = error_mark_node;
17037 break;
17038 }
17039 array_section_p = true;
17040 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
17041 {
17042 location_t expr_loc
17043 = c_parser_peek_token (parser)->location;
17044 c_expr expr = c_parser_expression (parser);
17045 expr = convert_lvalue_to_rvalue (expr_loc, expr,
17046 false, true);
17047 length = expr.value;
17048 }
17049 }
17050 /* Look for the closing `]'. */
17051 if (!c_parser_require (parser, type: CPP_CLOSE_SQUARE,
17052 msgid: "expected %<]%>"))
17053 {
17054 t = error_mark_node;
17055 break;
17056 }
17057
17058 dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon));
17059 }
17060
17061 if (t != error_mark_node)
17062 {
17063 if ((kind == OMP_CLAUSE_MAP
17064 || kind == OMP_CLAUSE_FROM
17065 || kind == OMP_CLAUSE_TO)
17066 && !array_section_p
17067 && (c_parser_next_token_is (parser, type: CPP_DOT)
17068 || c_parser_next_token_is (parser, type: CPP_DEREF)))
17069 {
17070 for (unsigned i = 0; i < dims.length (); i++)
17071 {
17072 gcc_assert (dims[i].length == integer_one_node);
17073 t = build_array_ref (dims[i].loc,
17074 t, dims[i].low_bound);
17075 }
17076 goto start_component_ref;
17077 }
17078 else
17079 for (unsigned i = 0; i < dims.length (); i++)
17080 t = build_omp_array_section (clause_loc, t,
17081 dims[i].low_bound,
17082 dims[i].length);
17083 }
17084
17085 if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
17086 && t != error_mark_node
17087 && parser->tokens_avail != 2)
17088 {
17089 if (array_section_p)
17090 {
17091 error_at (c_parser_peek_token (parser)->location,
17092 "expected %<)%> or %<,%>");
17093 t = error_mark_node;
17094 }
17095 else
17096 {
17097 parser->tokens = tokens.address ();
17098 parser->tokens_avail = tokens.length ();
17099
17100 t = c_parser_expr_no_commas (parser, NULL).value;
17101 if (t != error_mark_node && parser->tokens_avail != 2)
17102 {
17103 error_at (c_parser_peek_token (parser)->location,
17104 "expected %<)%> or %<,%>");
17105 t = error_mark_node;
17106 }
17107 }
17108 }
17109 break;
17110 default:
17111 break;
17112 }
17113
17114 if (t != error_mark_node)
17115 {
17116 tree u = build_omp_clause (clause_loc, kind);
17117 OMP_CLAUSE_DECL (u) = t;
17118 OMP_CLAUSE_CHAIN (u) = list;
17119 list = u;
17120 }
17121 }
17122 else /* kind == OMP_CLAUSE_ERROR */
17123 list = tree_cons (t, build_empty_stmt (tloc), list);
17124
17125 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
17126 {
17127 parser->tokens = saved_tokens;
17128 parser->tokens_avail = tokens_avail;
17129 }
17130
17131 next_item:
17132 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
17133 break;
17134
17135 c_parser_consume_token (parser);
17136 }
17137
17138 return list;
17139}
17140
17141/* Similarly, but expect leading and trailing parenthesis. This is a very
17142 common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
17143 argument is true if list items can use the deref (->) operator. */
17144
17145static tree
17146c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
17147 tree list, bool map_lvalue = false)
17148{
17149 /* The clauses location. */
17150 location_t loc = c_parser_peek_token (parser)->location;
17151
17152 if (parser->in_omp_decl_attribute)
17153 {
17154 if (kind)
17155 {
17156 tree u = build_omp_clause (loc, kind);
17157 OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
17158 OMP_CLAUSE_CHAIN (u) = list;
17159 return u;
17160 }
17161 else
17162 return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
17163 }
17164
17165 matching_parens parens;
17166 if (parens.require_open (parser))
17167 {
17168 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list, map_lvalue);
17169 parens.skip_until_found_close (parser);
17170 }
17171 return list;
17172}
17173
17174/* OpenACC 2.0:
17175 copy ( variable-list )
17176 copyin ( variable-list )
17177 copyout ( variable-list )
17178 create ( variable-list )
17179 delete ( variable-list )
17180 present ( variable-list )
17181
17182 OpenACC 2.6:
17183 no_create ( variable-list )
17184 attach ( variable-list )
17185 detach ( variable-list )
17186
17187 OpenACC 2.7:
17188 copyin (readonly : variable-list )
17189 */
17190
17191static tree
17192c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
17193 tree list)
17194{
17195 enum gomp_map_kind kind;
17196 switch (c_kind)
17197 {
17198 case PRAGMA_OACC_CLAUSE_ATTACH:
17199 kind = GOMP_MAP_ATTACH;
17200 break;
17201 case PRAGMA_OACC_CLAUSE_COPY:
17202 kind = GOMP_MAP_TOFROM;
17203 break;
17204 case PRAGMA_OACC_CLAUSE_COPYIN:
17205 kind = GOMP_MAP_TO;
17206 break;
17207 case PRAGMA_OACC_CLAUSE_COPYOUT:
17208 kind = GOMP_MAP_FROM;
17209 break;
17210 case PRAGMA_OACC_CLAUSE_CREATE:
17211 kind = GOMP_MAP_ALLOC;
17212 break;
17213 case PRAGMA_OACC_CLAUSE_DELETE:
17214 kind = GOMP_MAP_RELEASE;
17215 break;
17216 case PRAGMA_OACC_CLAUSE_DETACH:
17217 kind = GOMP_MAP_DETACH;
17218 break;
17219 case PRAGMA_OACC_CLAUSE_DEVICE:
17220 kind = GOMP_MAP_FORCE_TO;
17221 break;
17222 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
17223 kind = GOMP_MAP_DEVICE_RESIDENT;
17224 break;
17225 case PRAGMA_OACC_CLAUSE_LINK:
17226 kind = GOMP_MAP_LINK;
17227 break;
17228 case PRAGMA_OACC_CLAUSE_NO_CREATE:
17229 kind = GOMP_MAP_IF_PRESENT;
17230 break;
17231 case PRAGMA_OACC_CLAUSE_PRESENT:
17232 kind = GOMP_MAP_FORCE_PRESENT;
17233 break;
17234 case PRAGMA_OACC_CLAUSE_SELF:
17235 /* "The 'host' clause is a synonym for the 'self' clause." */
17236 case PRAGMA_OACC_CLAUSE_HOST:
17237 kind = GOMP_MAP_FORCE_FROM;
17238 break;
17239 default:
17240 gcc_unreachable ();
17241 }
17242
17243 tree nl = list;
17244 bool readonly = false;
17245 location_t open_loc = c_parser_peek_token (parser)->location;
17246 matching_parens parens;
17247 if (parens.require_open (parser))
17248 {
17249 /* Turn on readonly modifier parsing for copyin clause. */
17250 if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
17251 {
17252 c_token *token = c_parser_peek_token (parser);
17253 if (token->type == CPP_NAME
17254 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
17255 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17256 {
17257 c_parser_consume_token (parser);
17258 c_parser_consume_token (parser);
17259 readonly = true;
17260 }
17261 }
17262 nl = c_parser_omp_variable_list (parser, clause_loc: open_loc, kind: OMP_CLAUSE_MAP, list,
17263 map_lvalue: false);
17264 parens.skip_until_found_close (parser);
17265 }
17266
17267 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17268 {
17269 OMP_CLAUSE_SET_MAP_KIND (c, kind);
17270 if (readonly)
17271 OMP_CLAUSE_MAP_READONLY (c) = 1;
17272 }
17273
17274 return nl;
17275}
17276
17277/* OpenACC 2.0:
17278 deviceptr ( variable-list ) */
17279
17280static tree
17281c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
17282{
17283 tree vars, t;
17284
17285 /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
17286 c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
17287 variable-list must only allow for pointer variables. */
17288 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
17289 for (t = vars; t && t; t = TREE_CHAIN (t))
17290 {
17291 tree v = TREE_PURPOSE (t);
17292 location_t loc = EXPR_LOCATION (TREE_VALUE (t));
17293
17294 if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
17295 error_at (loc, "%qD is not a variable", v);
17296 else if (TREE_TYPE (v) == error_mark_node)
17297 ;
17298 else if (!POINTER_TYPE_P (TREE_TYPE (v)))
17299 error_at (loc, "%qD is not a pointer variable", v);
17300
17301 tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
17302 OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
17303 OMP_CLAUSE_DECL (u) = v;
17304 OMP_CLAUSE_CHAIN (u) = list;
17305 list = u;
17306 }
17307
17308 return list;
17309}
17310
17311/* OpenACC 2.0, OpenMP 3.0:
17312 collapse ( constant-expression ) */
17313
17314static tree
17315c_parser_omp_clause_collapse (c_parser *parser, tree list)
17316{
17317 tree c, num = error_mark_node;
17318 HOST_WIDE_INT n;
17319 location_t loc;
17320
17321 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
17322 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
17323
17324 loc = c_parser_peek_token (parser)->location;
17325 matching_parens parens;
17326 if (parens.require_open (parser))
17327 {
17328 num = c_parser_expr_no_commas (parser, NULL).value;
17329 parens.skip_until_found_close (parser);
17330 }
17331 if (num == error_mark_node)
17332 return list;
17333 mark_exp_read (num);
17334 num = c_fully_fold (num, false, NULL);
17335 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17336 || !tree_fits_shwi_p (num)
17337 || (n = tree_to_shwi (num)) <= 0
17338 || (int) n != n)
17339 {
17340 error_at (loc,
17341 "collapse argument needs positive constant integer expression");
17342 return list;
17343 }
17344 c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
17345 OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
17346 OMP_CLAUSE_CHAIN (c) = list;
17347 return c;
17348}
17349
17350/* OpenMP 2.5:
17351 copyin ( variable-list ) */
17352
17353static tree
17354c_parser_omp_clause_copyin (c_parser *parser, tree list)
17355{
17356 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYIN, list);
17357}
17358
17359/* OpenMP 2.5:
17360 copyprivate ( variable-list ) */
17361
17362static tree
17363c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
17364{
17365 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYPRIVATE, list);
17366}
17367
17368/* OpenMP 2.5:
17369 default ( none | shared )
17370
17371 OpenMP 5.1:
17372 default ( private | firstprivate )
17373
17374 OpenACC:
17375 default ( none | present ) */
17376
17377static tree
17378c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
17379{
17380 enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
17381 location_t loc = c_parser_peek_token (parser)->location;
17382 tree c;
17383
17384 matching_parens parens;
17385 if (!parens.require_open (parser))
17386 return list;
17387 if (c_parser_next_token_is (parser, type: CPP_NAME))
17388 {
17389 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17390
17391 switch (p[0])
17392 {
17393 case 'n':
17394 if (strcmp (s1: "none", s2: p) != 0)
17395 goto invalid_kind;
17396 kind = OMP_CLAUSE_DEFAULT_NONE;
17397 break;
17398
17399 case 'p':
17400 if (is_oacc)
17401 {
17402 if (strcmp (s1: "present", s2: p) != 0)
17403 goto invalid_kind;
17404 kind = OMP_CLAUSE_DEFAULT_PRESENT;
17405 }
17406 else
17407 {
17408 if (strcmp (s1: "private", s2: p) != 0)
17409 goto invalid_kind;
17410 kind = OMP_CLAUSE_DEFAULT_PRIVATE;
17411 }
17412 break;
17413
17414 case 'f':
17415 if (strcmp (s1: "firstprivate", s2: p) != 0 || is_oacc)
17416 goto invalid_kind;
17417 kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
17418 break;
17419
17420 case 's':
17421 if (strcmp (s1: "shared", s2: p) != 0 || is_oacc)
17422 goto invalid_kind;
17423 kind = OMP_CLAUSE_DEFAULT_SHARED;
17424 break;
17425
17426 default:
17427 goto invalid_kind;
17428 }
17429
17430 c_parser_consume_token (parser);
17431 }
17432 else
17433 {
17434 invalid_kind:
17435 if (is_oacc)
17436 c_parser_error (parser, gmsgid: "expected %<none%> or %<present%>");
17437 else
17438 c_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, "
17439 "%<private%> or %<firstprivate%>");
17440 }
17441 parens.skip_until_found_close (parser);
17442
17443 if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
17444 return list;
17445
17446 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default");
17447 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
17448 OMP_CLAUSE_CHAIN (c) = list;
17449 OMP_CLAUSE_DEFAULT_KIND (c) = kind;
17450
17451 return c;
17452}
17453
17454/* OpenMP 2.5:
17455 firstprivate ( variable-list ) */
17456
17457static tree
17458c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
17459{
17460 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, list);
17461}
17462
17463/* OpenMP 3.1:
17464 final ( expression ) */
17465
17466static tree
17467c_parser_omp_clause_final (c_parser *parser, tree list)
17468{
17469 location_t loc = c_parser_peek_token (parser)->location;
17470 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
17471 {
17472 matching_parens parens;
17473 tree t, c;
17474 if (!parens.require_open (parser))
17475 t = error_mark_node;
17476 else
17477 {
17478 location_t eloc = c_parser_peek_token (parser)->location;
17479 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17480 t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
17481 t = c_objc_common_truthvalue_conversion (eloc, t);
17482 t = c_fully_fold (t, false, NULL);
17483 parens.skip_until_found_close (parser);
17484 }
17485
17486 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final");
17487
17488 c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
17489 OMP_CLAUSE_FINAL_EXPR (c) = t;
17490 OMP_CLAUSE_CHAIN (c) = list;
17491 list = c;
17492 }
17493 else
17494 c_parser_error (parser, gmsgid: "expected %<(%>");
17495
17496 return list;
17497}
17498
17499/* OpenMP 5.1:
17500 indirect [( expression )]
17501*/
17502
17503static tree
17504c_parser_omp_clause_indirect (c_parser *parser, tree list)
17505{
17506 location_t location = c_parser_peek_token (parser)->location;
17507 tree t;
17508
17509 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17510 {
17511 matching_parens parens;
17512 if (!parens.require_open (parser))
17513 return list;
17514
17515 location_t loc = c_parser_peek_token (parser)->location;
17516 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17517 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17518 t = c_objc_common_truthvalue_conversion (loc, expr.value);
17519 t = c_fully_fold (t, false, NULL);
17520 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17521 || TREE_CODE (t) != INTEGER_CST)
17522 {
17523 c_parser_error (parser, gmsgid: "expected constant logical expression");
17524 return list;
17525 }
17526 parens.skip_until_found_close (parser);
17527 }
17528 else
17529 t = integer_one_node;
17530
17531 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect");
17532
17533 tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
17534 OMP_CLAUSE_INDIRECT_EXPR (c) = t;
17535 OMP_CLAUSE_CHAIN (c) = list;
17536
17537 return c;
17538}
17539
17540/* OpenACC, OpenMP 2.5:
17541 if ( expression )
17542
17543 OpenMP 4.5:
17544 if ( directive-name-modifier : expression )
17545
17546 directive-name-modifier:
17547 parallel | task | taskloop | target data | target | target update
17548 | target enter data | target exit data
17549
17550 OpenMP 5.0:
17551 directive-name-modifier:
17552 ... | simd | cancel */
17553
17554static tree
17555c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
17556{
17557 location_t location = c_parser_peek_token (parser)->location;
17558 enum tree_code if_modifier = ERROR_MARK;
17559
17560 matching_parens parens;
17561 if (!parens.require_open (parser))
17562 return list;
17563
17564 if (is_omp && c_parser_next_token_is (parser, type: CPP_NAME))
17565 {
17566 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17567 int n = 2;
17568 if (strcmp (s1: p, s2: "cancel") == 0)
17569 if_modifier = VOID_CST;
17570 else if (strcmp (s1: p, s2: "parallel") == 0)
17571 if_modifier = OMP_PARALLEL;
17572 else if (strcmp (s1: p, s2: "simd") == 0)
17573 if_modifier = OMP_SIMD;
17574 else if (strcmp (s1: p, s2: "task") == 0)
17575 if_modifier = OMP_TASK;
17576 else if (strcmp (s1: p, s2: "taskloop") == 0)
17577 if_modifier = OMP_TASKLOOP;
17578 else if (strcmp (s1: p, s2: "target") == 0)
17579 {
17580 if_modifier = OMP_TARGET;
17581 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17582 {
17583 p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
17584 if (strcmp (s1: "data", s2: p) == 0)
17585 if_modifier = OMP_TARGET_DATA;
17586 else if (strcmp (s1: "update", s2: p) == 0)
17587 if_modifier = OMP_TARGET_UPDATE;
17588 else if (strcmp (s1: "enter", s2: p) == 0)
17589 if_modifier = OMP_TARGET_ENTER_DATA;
17590 else if (strcmp (s1: "exit", s2: p) == 0)
17591 if_modifier = OMP_TARGET_EXIT_DATA;
17592 if (if_modifier != OMP_TARGET)
17593 {
17594 n = 3;
17595 c_parser_consume_token (parser);
17596 }
17597 else
17598 {
17599 location_t loc = c_parser_peek_2nd_token (parser)->location;
17600 error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
17601 "or %<exit%>");
17602 if_modifier = ERROR_MARK;
17603 }
17604 if (if_modifier == OMP_TARGET_ENTER_DATA
17605 || if_modifier == OMP_TARGET_EXIT_DATA)
17606 {
17607 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17608 {
17609 p = IDENTIFIER_POINTER
17610 (c_parser_peek_2nd_token (parser)->value);
17611 if (strcmp (s1: "data", s2: p) == 0)
17612 n = 4;
17613 }
17614 if (n == 4)
17615 c_parser_consume_token (parser);
17616 else
17617 {
17618 location_t loc
17619 = c_parser_peek_2nd_token (parser)->location;
17620 error_at (loc, "expected %<data%>");
17621 if_modifier = ERROR_MARK;
17622 }
17623 }
17624 }
17625 }
17626 if (if_modifier != ERROR_MARK)
17627 {
17628 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17629 {
17630 c_parser_consume_token (parser);
17631 c_parser_consume_token (parser);
17632 }
17633 else
17634 {
17635 if (n > 2)
17636 {
17637 location_t loc = c_parser_peek_2nd_token (parser)->location;
17638 error_at (loc, "expected %<:%>");
17639 }
17640 if_modifier = ERROR_MARK;
17641 }
17642 }
17643 }
17644
17645 location_t loc = c_parser_peek_token (parser)->location;
17646 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17647 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17648 tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
17649 t = c_fully_fold (t, false, NULL);
17650 parens.skip_until_found_close (parser);
17651
17652 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17653 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
17654 {
17655 if (if_modifier != ERROR_MARK
17656 && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17657 {
17658 const char *p = NULL;
17659 switch (if_modifier)
17660 {
17661 case VOID_CST: p = "cancel"; break;
17662 case OMP_PARALLEL: p = "parallel"; break;
17663 case OMP_SIMD: p = "simd"; break;
17664 case OMP_TASK: p = "task"; break;
17665 case OMP_TASKLOOP: p = "taskloop"; break;
17666 case OMP_TARGET_DATA: p = "target data"; break;
17667 case OMP_TARGET: p = "target"; break;
17668 case OMP_TARGET_UPDATE: p = "target update"; break;
17669 case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
17670 case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
17671 default: gcc_unreachable ();
17672 }
17673 error_at (location, "too many %<if%> clauses with %qs modifier",
17674 p);
17675 return list;
17676 }
17677 else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17678 {
17679 if (!is_omp)
17680 error_at (location, "too many %<if%> clauses");
17681 else
17682 error_at (location, "too many %<if%> clauses without modifier");
17683 return list;
17684 }
17685 else if (if_modifier == ERROR_MARK
17686 || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
17687 {
17688 error_at (location, "if any %<if%> clause has modifier, then all "
17689 "%<if%> clauses have to use modifier");
17690 return list;
17691 }
17692 }
17693
17694 c = build_omp_clause (location, OMP_CLAUSE_IF);
17695 OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
17696 OMP_CLAUSE_IF_EXPR (c) = t;
17697 OMP_CLAUSE_CHAIN (c) = list;
17698 return c;
17699}
17700
17701/* OpenMP 2.5:
17702 lastprivate ( variable-list )
17703
17704 OpenMP 5.0:
17705 lastprivate ( [ lastprivate-modifier : ] variable-list ) */
17706
17707static tree
17708c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
17709{
17710 /* The clauses location. */
17711 location_t loc = c_parser_peek_token (parser)->location;
17712
17713 if (c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
17714 {
17715 bool conditional = false;
17716 if (c_parser_next_token_is (parser, type: CPP_NAME)
17717 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17718 {
17719 const char *p
17720 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17721 if (strcmp (s1: p, s2: "conditional") == 0)
17722 {
17723 conditional = true;
17724 c_parser_consume_token (parser);
17725 c_parser_consume_token (parser);
17726 }
17727 }
17728 tree nlist = c_parser_omp_variable_list (parser, clause_loc: loc,
17729 kind: OMP_CLAUSE_LASTPRIVATE, list);
17730 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
17731 if (conditional)
17732 for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
17733 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
17734 return nlist;
17735 }
17736 return list;
17737}
17738
17739/* OpenMP 3.1:
17740 mergeable */
17741
17742static tree
17743c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17744{
17745 tree c;
17746
17747 /* FIXME: Should we allow duplicates? */
17748 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable");
17749
17750 c = build_omp_clause (c_parser_peek_token (parser)->location,
17751 OMP_CLAUSE_MERGEABLE);
17752 OMP_CLAUSE_CHAIN (c) = list;
17753
17754 return c;
17755}
17756
17757/* OpenMP 2.5:
17758 nowait */
17759
17760static tree
17761c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17762{
17763 tree c;
17764 location_t loc = c_parser_peek_token (parser)->location;
17765
17766 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait");
17767
17768 c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
17769 OMP_CLAUSE_CHAIN (c) = list;
17770 return c;
17771}
17772
17773/* OpenMP 2.5:
17774 num_threads ( expression ) */
17775
17776static tree
17777c_parser_omp_clause_num_threads (c_parser *parser, tree list)
17778{
17779 location_t num_threads_loc = c_parser_peek_token (parser)->location;
17780 matching_parens parens;
17781 if (parens.require_open (parser))
17782 {
17783 location_t expr_loc = c_parser_peek_token (parser)->location;
17784 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17785 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17786 tree c, t = expr.value;
17787 t = c_fully_fold (t, false, NULL);
17788
17789 parens.skip_until_found_close (parser);
17790
17791 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17792 {
17793 c_parser_error (parser, gmsgid: "expected integer expression");
17794 return list;
17795 }
17796
17797 /* Attempt to statically determine when the number isn't positive. */
17798 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17799 build_int_cst (TREE_TYPE (t), 0));
17800 protected_set_expr_location (c, expr_loc);
17801 if (c == boolean_true_node)
17802 {
17803 warning_at (expr_loc, OPT_Wopenmp,
17804 "%<num_threads%> value must be positive");
17805 t = integer_one_node;
17806 }
17807
17808 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, name: "num_threads");
17809
17810 c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
17811 OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
17812 OMP_CLAUSE_CHAIN (c) = list;
17813 list = c;
17814 }
17815
17816 return list;
17817}
17818
17819/* OpenMP 4.5:
17820 num_tasks ( expression )
17821
17822 OpenMP 5.1:
17823 num_tasks ( strict : expression ) */
17824
17825static tree
17826c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
17827{
17828 location_t num_tasks_loc = c_parser_peek_token (parser)->location;
17829 matching_parens parens;
17830 if (parens.require_open (parser))
17831 {
17832 bool strict = false;
17833 if (c_parser_next_token_is (parser, type: CPP_NAME)
17834 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17835 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17836 s2: "strict") == 0)
17837 {
17838 strict = true;
17839 c_parser_consume_token (parser);
17840 c_parser_consume_token (parser);
17841 }
17842
17843 location_t expr_loc = c_parser_peek_token (parser)->location;
17844 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17845 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17846 tree c, t = expr.value;
17847 t = c_fully_fold (t, false, NULL);
17848
17849 parens.skip_until_found_close (parser);
17850
17851 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17852 {
17853 c_parser_error (parser, gmsgid: "expected integer expression");
17854 return list;
17855 }
17856
17857 /* Attempt to statically determine when the number isn't positive. */
17858 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17859 build_int_cst (TREE_TYPE (t), 0));
17860 if (CAN_HAVE_LOCATION_P (c))
17861 SET_EXPR_LOCATION (c, expr_loc);
17862 if (c == boolean_true_node)
17863 {
17864 warning_at (expr_loc, OPT_Wopenmp,
17865 "%<num_tasks%> value must be positive");
17866 t = integer_one_node;
17867 }
17868
17869 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, name: "num_tasks");
17870
17871 c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
17872 OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
17873 OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
17874 OMP_CLAUSE_CHAIN (c) = list;
17875 list = c;
17876 }
17877
17878 return list;
17879}
17880
17881/* OpenMP 4.5:
17882 grainsize ( expression )
17883
17884 OpenMP 5.1:
17885 grainsize ( strict : expression ) */
17886
17887static tree
17888c_parser_omp_clause_grainsize (c_parser *parser, tree list)
17889{
17890 location_t grainsize_loc = c_parser_peek_token (parser)->location;
17891 matching_parens parens;
17892 if (parens.require_open (parser))
17893 {
17894 bool strict = false;
17895 if (c_parser_next_token_is (parser, type: CPP_NAME)
17896 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17897 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17898 s2: "strict") == 0)
17899 {
17900 strict = true;
17901 c_parser_consume_token (parser);
17902 c_parser_consume_token (parser);
17903 }
17904
17905 location_t expr_loc = c_parser_peek_token (parser)->location;
17906 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17907 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17908 tree c, t = expr.value;
17909 t = c_fully_fold (t, false, NULL);
17910
17911 parens.skip_until_found_close (parser);
17912
17913 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17914 {
17915 c_parser_error (parser, gmsgid: "expected integer expression");
17916 return list;
17917 }
17918
17919 /* Attempt to statically determine when the number isn't positive. */
17920 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17921 build_int_cst (TREE_TYPE (t), 0));
17922 if (CAN_HAVE_LOCATION_P (c))
17923 SET_EXPR_LOCATION (c, expr_loc);
17924 if (c == boolean_true_node)
17925 {
17926 warning_at (expr_loc, OPT_Wopenmp,
17927 "%<grainsize%> value must be positive");
17928 t = integer_one_node;
17929 }
17930
17931 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, name: "grainsize");
17932
17933 c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
17934 OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
17935 OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
17936 OMP_CLAUSE_CHAIN (c) = list;
17937 list = c;
17938 }
17939
17940 return list;
17941}
17942
17943/* OpenMP 4.5:
17944 priority ( expression ) */
17945
17946static tree
17947c_parser_omp_clause_priority (c_parser *parser, tree list)
17948{
17949 location_t priority_loc = c_parser_peek_token (parser)->location;
17950 matching_parens parens;
17951 if (parens.require_open (parser))
17952 {
17953 location_t expr_loc = c_parser_peek_token (parser)->location;
17954 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17955 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17956 tree c, t = expr.value;
17957 t = c_fully_fold (t, false, NULL);
17958
17959 parens.skip_until_found_close (parser);
17960
17961 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17962 {
17963 c_parser_error (parser, gmsgid: "expected integer expression");
17964 return list;
17965 }
17966
17967 /* Attempt to statically determine when the number isn't
17968 non-negative. */
17969 c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
17970 build_int_cst (TREE_TYPE (t), 0));
17971 if (CAN_HAVE_LOCATION_P (c))
17972 SET_EXPR_LOCATION (c, expr_loc);
17973 if (c == boolean_true_node)
17974 {
17975 warning_at (expr_loc, OPT_Wopenmp,
17976 "%<priority%> value must be non-negative");
17977 t = integer_one_node;
17978 }
17979
17980 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, name: "priority");
17981
17982 c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
17983 OMP_CLAUSE_PRIORITY_EXPR (c) = t;
17984 OMP_CLAUSE_CHAIN (c) = list;
17985 list = c;
17986 }
17987
17988 return list;
17989}
17990
17991/* OpenMP 4.5:
17992 hint ( expression ) */
17993
17994static tree
17995c_parser_omp_clause_hint (c_parser *parser, tree list)
17996{
17997 location_t hint_loc = c_parser_peek_token (parser)->location;
17998 matching_parens parens;
17999 if (parens.require_open (parser))
18000 {
18001 location_t expr_loc = c_parser_peek_token (parser)->location;
18002 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18003 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18004 tree c, t = expr.value;
18005 t = c_fully_fold (t, false, NULL);
18006 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
18007 || TREE_CODE (t) != INTEGER_CST
18008 || tree_int_cst_sgn (t) == -1)
18009 {
18010 c_parser_error (parser, gmsgid: "expected constant integer expression "
18011 "with valid sync-hint value");
18012 return list;
18013 }
18014 parens.skip_until_found_close (parser);
18015 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint");
18016
18017 c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
18018 OMP_CLAUSE_HINT_EXPR (c) = t;
18019 OMP_CLAUSE_CHAIN (c) = list;
18020 list = c;
18021 }
18022
18023 return list;
18024}
18025
18026/* OpenMP 5.1:
18027 filter ( integer-expression ) */
18028
18029static tree
18030c_parser_omp_clause_filter (c_parser *parser, tree list)
18031{
18032 location_t hint_loc = c_parser_peek_token (parser)->location;
18033 matching_parens parens;
18034 if (parens.require_open (parser))
18035 {
18036 location_t expr_loc = c_parser_peek_token (parser)->location;
18037 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18038 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18039 tree c, t = expr.value;
18040 t = c_fully_fold (t, false, NULL);
18041 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18042 {
18043 c_parser_error (parser, gmsgid: "expected integer expression");
18044 return list;
18045 }
18046 parens.skip_until_found_close (parser);
18047 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter");
18048
18049 c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
18050 OMP_CLAUSE_FILTER_EXPR (c) = t;
18051 OMP_CLAUSE_CHAIN (c) = list;
18052 list = c;
18053 }
18054
18055 return list;
18056}
18057
18058/* OpenMP 4.5:
18059 defaultmap ( tofrom : scalar )
18060
18061 OpenMP 5.0:
18062 defaultmap ( implicit-behavior [ : variable-category ] ) */
18063
18064static tree
18065c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
18066{
18067 location_t loc = c_parser_peek_token (parser)->location;
18068 tree c;
18069 const char *p;
18070 enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
18071 enum omp_clause_defaultmap_kind category
18072 = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
18073
18074 matching_parens parens;
18075 if (!parens.require_open (parser))
18076 return list;
18077 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
18078 p = "default";
18079 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
18080 {
18081 invalid_behavior:
18082 c_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, "
18083 "%<tofrom%>, %<firstprivate%>, %<none%> "
18084 "or %<default%>");
18085 goto out_err;
18086 }
18087 else
18088 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18089
18090 switch (p[0])
18091 {
18092 case 'a':
18093 if (strcmp (s1: "alloc", s2: p) == 0)
18094 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
18095 else
18096 goto invalid_behavior;
18097 break;
18098
18099 case 'd':
18100 if (strcmp (s1: "default", s2: p) == 0)
18101 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
18102 else
18103 goto invalid_behavior;
18104 break;
18105
18106 case 'f':
18107 if (strcmp (s1: "firstprivate", s2: p) == 0)
18108 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
18109 else if (strcmp (s1: "from", s2: p) == 0)
18110 behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
18111 else
18112 goto invalid_behavior;
18113 break;
18114
18115 case 'n':
18116 if (strcmp (s1: "none", s2: p) == 0)
18117 behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
18118 else
18119 goto invalid_behavior;
18120 break;
18121
18122 case 'p':
18123 if (strcmp (s1: "present", s2: p) == 0)
18124 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
18125 else
18126 goto invalid_behavior;
18127 break;
18128
18129 case 't':
18130 if (strcmp (s1: "tofrom", s2: p) == 0)
18131 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
18132 else if (strcmp (s1: "to", s2: p) == 0)
18133 behavior = OMP_CLAUSE_DEFAULTMAP_TO;
18134 else
18135 goto invalid_behavior;
18136 break;
18137
18138 default:
18139 goto invalid_behavior;
18140 }
18141 c_parser_consume_token (parser);
18142
18143 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
18144 {
18145 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18146 goto out_err;
18147 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18148 {
18149 invalid_category:
18150 c_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, "
18151 "%<pointer%> or %<all%>");
18152 goto out_err;
18153 }
18154 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18155 switch (p[0])
18156 {
18157 case 'a':
18158 if (strcmp (s1: "aggregate", s2: p) == 0)
18159 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
18160 else if (strcmp (s1: "all", s2: p) == 0)
18161 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
18162 else
18163 goto invalid_category;
18164 break;
18165
18166 case 'p':
18167 if (strcmp (s1: "pointer", s2: p) == 0)
18168 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
18169 else
18170 goto invalid_category;
18171 break;
18172
18173 case 's':
18174 if (strcmp (s1: "scalar", s2: p) == 0)
18175 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
18176 else
18177 goto invalid_category;
18178 break;
18179
18180 default:
18181 goto invalid_category;
18182 }
18183
18184 c_parser_consume_token (parser);
18185 }
18186 parens.skip_until_found_close (parser);
18187
18188 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
18189 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
18190 && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
18191 || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
18192 || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
18193 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18194 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
18195 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18196 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
18197 {
18198 enum omp_clause_defaultmap_kind cat = category;
18199 location_t loc = OMP_CLAUSE_LOCATION (c);
18200 if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
18201 || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
18202 && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18203 != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
18204 cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
18205 p = NULL;
18206 switch (cat)
18207 {
18208 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
18209 p = NULL;
18210 break;
18211 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
18212 p = "all";
18213 break;
18214 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
18215 p = "aggregate";
18216 break;
18217 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
18218 p = "pointer";
18219 break;
18220 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
18221 p = "scalar";
18222 break;
18223 default:
18224 gcc_unreachable ();
18225 }
18226 if (p)
18227 error_at (loc, "too many %<defaultmap%> clauses with %qs category",
18228 p);
18229 else
18230 error_at (loc, "too many %<defaultmap%> clauses with unspecified "
18231 "category");
18232 break;
18233 }
18234
18235 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
18236 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
18237 OMP_CLAUSE_CHAIN (c) = list;
18238 return c;
18239
18240 out_err:
18241 parens.skip_until_found_close (parser);
18242 return list;
18243}
18244
18245/* OpenACC 2.0:
18246 use_device ( variable-list )
18247
18248 OpenMP 4.5:
18249 use_device_ptr ( variable-list ) */
18250
18251static tree
18252c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
18253{
18254 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR,
18255 list);
18256}
18257
18258/* OpenMP 5.0:
18259 use_device_addr ( variable-list ) */
18260
18261static tree
18262c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
18263{
18264 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR,
18265 list);
18266}
18267
18268/* OpenMP 5.1:
18269 has_device_addr ( variable-list ) */
18270
18271static tree
18272c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
18273{
18274 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR,
18275 list);
18276}
18277
18278/* OpenMP 4.5:
18279 is_device_ptr ( variable-list ) */
18280
18281static tree
18282c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
18283{
18284 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, list);
18285}
18286
18287/* OpenACC:
18288 num_gangs ( expression )
18289 num_workers ( expression )
18290 vector_length ( expression ) */
18291
18292static tree
18293c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
18294 tree list)
18295{
18296 location_t loc = c_parser_peek_token (parser)->location;
18297
18298 matching_parens parens;
18299 if (!parens.require_open (parser))
18300 return list;
18301
18302 location_t expr_loc = c_parser_peek_token (parser)->location;
18303 c_expr expr = c_parser_expression (parser);
18304 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18305 tree c, t = expr.value;
18306 t = c_fully_fold (t, false, NULL);
18307
18308 parens.skip_until_found_close (parser);
18309
18310 if (t == error_mark_node)
18311 return list;
18312 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18313 {
18314 error_at (expr_loc, "%qs expression must be integral",
18315 omp_clause_code_name[code]);
18316 return list;
18317 }
18318
18319 /* Attempt to statically determine when the number isn't positive. */
18320 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
18321 build_int_cst (TREE_TYPE (t), 0));
18322 protected_set_expr_location (c, expr_loc);
18323 if (c == boolean_true_node)
18324 {
18325 warning_at (expr_loc, 0,
18326 "%qs value must be positive",
18327 omp_clause_code_name[code]);
18328 t = integer_one_node;
18329 }
18330
18331 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18332
18333 c = build_omp_clause (loc, code);
18334 OMP_CLAUSE_OPERAND (c, 0) = t;
18335 OMP_CLAUSE_CHAIN (c) = list;
18336 return c;
18337}
18338
18339/* OpenACC:
18340
18341 gang [( gang-arg-list )]
18342 worker [( [num:] int-expr )]
18343 vector [( [length:] int-expr )]
18344
18345 where gang-arg is one of:
18346
18347 [num:] int-expr
18348 static: size-expr
18349
18350 and size-expr may be:
18351
18352 *
18353 int-expr
18354*/
18355
18356static tree
18357c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
18358 omp_clause_code kind,
18359 const char *str, tree list)
18360{
18361 const char *id = "num";
18362 tree ops[2] = { NULL_TREE, NULL_TREE }, c;
18363
18364 if (kind == OMP_CLAUSE_VECTOR)
18365 id = "length";
18366
18367 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
18368 {
18369 c_parser_consume_token (parser);
18370
18371 do
18372 {
18373 c_token *next = c_parser_peek_token (parser);
18374 int idx = 0;
18375
18376 /* Gang static argument. */
18377 if (kind == OMP_CLAUSE_GANG
18378 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
18379 {
18380 c_parser_consume_token (parser);
18381
18382 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18383 goto cleanup_error;
18384
18385 idx = 1;
18386 if (ops[idx] != NULL_TREE)
18387 {
18388 c_parser_error (parser, gmsgid: "too many %<static%> arguments");
18389 goto cleanup_error;
18390 }
18391
18392 /* Check for the '*' argument. */
18393 if (c_parser_next_token_is (parser, type: CPP_MULT)
18394 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18395 || c_parser_peek_2nd_token (parser)->type
18396 == CPP_CLOSE_PAREN))
18397 {
18398 c_parser_consume_token (parser);
18399 ops[idx] = integer_minus_one_node;
18400
18401 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18402 {
18403 c_parser_consume_token (parser);
18404 continue;
18405 }
18406 else
18407 break;
18408 }
18409 }
18410 /* Worker num: argument and vector length: arguments. */
18411 else if (c_parser_next_token_is (parser, type: CPP_NAME)
18412 && strcmp (s1: id, IDENTIFIER_POINTER (next->value)) == 0
18413 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18414 {
18415 c_parser_consume_token (parser); /* id */
18416 c_parser_consume_token (parser); /* ':' */
18417 }
18418
18419 /* Now collect the actual argument. */
18420 if (ops[idx] != NULL_TREE)
18421 {
18422 c_parser_error (parser, gmsgid: "unexpected argument");
18423 goto cleanup_error;
18424 }
18425
18426 location_t expr_loc = c_parser_peek_token (parser)->location;
18427 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18428 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18429 tree expr = cexpr.value;
18430 if (expr == error_mark_node)
18431 goto cleanup_error;
18432
18433 expr = c_fully_fold (expr, false, NULL);
18434
18435 /* Attempt to statically determine when the number isn't a
18436 positive integer. */
18437
18438 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
18439 {
18440 c_parser_error (parser, gmsgid: "expected integer expression");
18441 return list;
18442 }
18443
18444 tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
18445 build_int_cst (TREE_TYPE (expr), 0));
18446 if (c == boolean_true_node)
18447 {
18448 warning_at (loc, 0,
18449 "%qs value must be positive", str);
18450 expr = integer_one_node;
18451 }
18452
18453 ops[idx] = expr;
18454
18455 if (kind == OMP_CLAUSE_GANG
18456 && c_parser_next_token_is (parser, type: CPP_COMMA))
18457 {
18458 c_parser_consume_token (parser);
18459 continue;
18460 }
18461 break;
18462 }
18463 while (1);
18464
18465 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
18466 goto cleanup_error;
18467 }
18468
18469 check_no_duplicate_clause (clauses: list, code: kind, name: str);
18470
18471 c = build_omp_clause (loc, kind);
18472
18473 if (ops[1])
18474 OMP_CLAUSE_OPERAND (c, 1) = ops[1];
18475
18476 OMP_CLAUSE_OPERAND (c, 0) = ops[0];
18477 OMP_CLAUSE_CHAIN (c) = list;
18478
18479 return c;
18480
18481 cleanup_error:
18482 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
18483 return list;
18484}
18485
18486/* OpenACC 2.5:
18487 auto
18488 finalize
18489 independent
18490 nohost
18491 seq */
18492
18493static tree
18494c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
18495 tree list)
18496{
18497 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18498
18499 tree c = build_omp_clause (loc, code);
18500 OMP_CLAUSE_CHAIN (c) = list;
18501
18502 return c;
18503}
18504
18505/* OpenACC:
18506 async [( int-expr )] */
18507
18508static tree
18509c_parser_oacc_clause_async (c_parser *parser, tree list)
18510{
18511 tree c, t;
18512 location_t loc = c_parser_peek_token (parser)->location;
18513
18514 t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18515
18516 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18517 {
18518 c_parser_consume_token (parser);
18519
18520 t = c_parser_expr_no_commas (parser, NULL).value;
18521 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18522 c_parser_error (parser, gmsgid: "expected integer expression");
18523 else if (t == error_mark_node
18524 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
18525 return list;
18526 }
18527 else
18528 t = c_fully_fold (t, false, NULL);
18529
18530 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async");
18531
18532 c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
18533 OMP_CLAUSE_ASYNC_EXPR (c) = t;
18534 OMP_CLAUSE_CHAIN (c) = list;
18535 list = c;
18536
18537 return list;
18538}
18539
18540/* OpenACC 2.0:
18541 tile ( size-expr-list ) */
18542
18543static tree
18544c_parser_oacc_clause_tile (c_parser *parser, tree list)
18545{
18546 tree c, expr = error_mark_node;
18547 location_t loc;
18548 tree tile = NULL_TREE;
18549
18550 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
18551 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
18552
18553 loc = c_parser_peek_token (parser)->location;
18554 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
18555 return list;
18556
18557 do
18558 {
18559 if (tile && !c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
18560 return list;
18561
18562 if (c_parser_next_token_is (parser, type: CPP_MULT)
18563 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18564 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
18565 {
18566 c_parser_consume_token (parser);
18567 expr = integer_zero_node;
18568 }
18569 else
18570 {
18571 location_t expr_loc = c_parser_peek_token (parser)->location;
18572 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18573 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18574 expr = cexpr.value;
18575
18576 if (expr == error_mark_node)
18577 {
18578 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18579 msgid: "expected %<)%>");
18580 return list;
18581 }
18582
18583 expr = c_fully_fold (expr, false, NULL);
18584
18585 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
18586 || !tree_fits_shwi_p (expr)
18587 || tree_to_shwi (expr) <= 0)
18588 {
18589 error_at (expr_loc, "%<tile%> argument needs positive"
18590 " integral constant");
18591 expr = integer_zero_node;
18592 }
18593 }
18594
18595 tile = tree_cons (NULL_TREE, expr, tile);
18596 }
18597 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN));
18598
18599 /* Consume the trailing ')'. */
18600 c_parser_consume_token (parser);
18601
18602 c = build_omp_clause (loc, OMP_CLAUSE_TILE);
18603 tile = nreverse (tile);
18604 OMP_CLAUSE_TILE_LIST (c) = tile;
18605 OMP_CLAUSE_CHAIN (c) = list;
18606 return c;
18607}
18608
18609/* OpenACC:
18610 wait [( int-expr-list )] */
18611
18612static tree
18613c_parser_oacc_clause_wait (c_parser *parser, tree list)
18614{
18615 location_t clause_loc = c_parser_peek_token (parser)->location;
18616
18617 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18618 list = c_parser_oacc_wait_list (parser, clause_loc, list);
18619 else
18620 {
18621 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
18622
18623 OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18624 OMP_CLAUSE_CHAIN (c) = list;
18625 list = c;
18626 }
18627
18628 return list;
18629}
18630
18631/* OpenACC 2.7:
18632 self [( expression )] */
18633
18634static tree
18635c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
18636{
18637 tree t;
18638 location_t location = c_parser_peek_token (parser)->location;
18639 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18640 {
18641 matching_parens parens;
18642 parens.consume_open (parser);
18643
18644 location_t loc = c_parser_peek_token (parser)->location;
18645 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18646 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
18647 t = c_objc_common_truthvalue_conversion (loc, expr.value);
18648 t = c_fully_fold (t, false, NULL);
18649 parens.skip_until_found_close (parser);
18650 }
18651 else
18652 t = truthvalue_true_node;
18653
18654 for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
18655 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
18656 {
18657 error_at (location, "too many %<self%> clauses");
18658 return list;
18659 }
18660
18661 tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
18662 OMP_CLAUSE_SELF_EXPR (c) = t;
18663 OMP_CLAUSE_CHAIN (c) = list;
18664 return c;
18665}
18666
18667/* OpenMP 5.0:
18668 order ( concurrent )
18669
18670 OpenMP 5.1:
18671 order ( order-modifier : concurrent )
18672
18673 order-modifier:
18674 reproducible
18675 unconstrained */
18676
18677static tree
18678c_parser_omp_clause_order (c_parser *parser, tree list)
18679{
18680 location_t loc = c_parser_peek_token (parser)->location;
18681 tree c;
18682 const char *p;
18683 bool unconstrained = false;
18684 bool reproducible = false;
18685
18686 matching_parens parens;
18687 if (!parens.require_open (parser))
18688 return list;
18689 if (c_parser_next_token_is (parser, type: CPP_NAME)
18690 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18691 {
18692 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18693 if (strcmp (s1: p, s2: "unconstrained") == 0)
18694 unconstrained = true;
18695 else if (strcmp (s1: p, s2: "reproducible") == 0)
18696 reproducible = true;
18697 else
18698 {
18699 c_parser_error (parser, gmsgid: "expected %<reproducible%> or "
18700 "%<unconstrained%>");
18701 goto out_err;
18702 }
18703 c_parser_consume_token (parser);
18704 c_parser_consume_token (parser);
18705 }
18706 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18707 {
18708 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
18709 goto out_err;
18710 }
18711 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18712 if (strcmp (s1: p, s2: "concurrent") != 0)
18713 {
18714 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
18715 goto out_err;
18716 }
18717 c_parser_consume_token (parser);
18718 parens.skip_until_found_close (parser);
18719 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order");
18720 c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
18721 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
18722 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
18723 OMP_CLAUSE_CHAIN (c) = list;
18724 return c;
18725
18726 out_err:
18727 parens.skip_until_found_close (parser);
18728 return list;
18729}
18730
18731
18732/* OpenMP 5.0:
18733 bind ( teams | parallel | thread ) */
18734
18735static tree
18736c_parser_omp_clause_bind (c_parser *parser, tree list)
18737{
18738 location_t loc = c_parser_peek_token (parser)->location;
18739 tree c;
18740 const char *p;
18741 enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18742
18743 matching_parens parens;
18744 if (!parens.require_open (parser))
18745 return list;
18746 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18747 {
18748 invalid:
18749 c_parser_error (parser,
18750 gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>");
18751 parens.skip_until_found_close (parser);
18752 return list;
18753 }
18754 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18755 if (strcmp (s1: p, s2: "teams") == 0)
18756 kind = OMP_CLAUSE_BIND_TEAMS;
18757 else if (strcmp (s1: p, s2: "parallel") == 0)
18758 kind = OMP_CLAUSE_BIND_PARALLEL;
18759 else if (strcmp (s1: p, s2: "thread") != 0)
18760 goto invalid;
18761 c_parser_consume_token (parser);
18762 parens.skip_until_found_close (parser);
18763 /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
18764 c = build_omp_clause (loc, OMP_CLAUSE_BIND);
18765 OMP_CLAUSE_BIND_KIND (c) = kind;
18766 OMP_CLAUSE_CHAIN (c) = list;
18767 return c;
18768}
18769
18770
18771/* OpenMP 2.5:
18772 ordered
18773
18774 OpenMP 4.5:
18775 ordered ( constant-expression ) */
18776
18777static tree
18778c_parser_omp_clause_ordered (c_parser *parser, tree list)
18779{
18780 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, name: "ordered");
18781
18782 tree c, num = NULL_TREE;
18783 HOST_WIDE_INT n;
18784 location_t loc = c_parser_peek_token (parser)->location;
18785 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
18786 {
18787 matching_parens parens;
18788 parens.consume_open (parser);
18789 num = c_parser_expr_no_commas (parser, NULL).value;
18790 parens.skip_until_found_close (parser);
18791 }
18792 if (num == error_mark_node)
18793 return list;
18794 if (num)
18795 {
18796 mark_exp_read (num);
18797 num = c_fully_fold (num, false, NULL);
18798 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
18799 || !tree_fits_shwi_p (num)
18800 || (n = tree_to_shwi (num)) <= 0
18801 || (int) n != n)
18802 {
18803 error_at (loc, "ordered argument needs positive "
18804 "constant integer expression");
18805 return list;
18806 }
18807 }
18808 c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
18809 OMP_CLAUSE_ORDERED_EXPR (c) = num;
18810 OMP_CLAUSE_CHAIN (c) = list;
18811 return c;
18812}
18813
18814/* OpenMP 2.5:
18815 private ( variable-list ) */
18816
18817static tree
18818c_parser_omp_clause_private (c_parser *parser, tree list)
18819{
18820 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_PRIVATE, list);
18821}
18822
18823/* OpenMP 2.5:
18824 reduction ( reduction-operator : variable-list )
18825
18826 reduction-operator:
18827 One of: + * - & ^ | && ||
18828
18829 OpenMP 3.1:
18830
18831 reduction-operator:
18832 One of: + * - & ^ | && || max min
18833
18834 OpenMP 4.0:
18835
18836 reduction-operator:
18837 One of: + * - & ^ | && ||
18838 identifier
18839
18840 OpenMP 5.0:
18841 reduction ( reduction-modifier, reduction-operator : variable-list )
18842 in_reduction ( reduction-operator : variable-list )
18843 task_reduction ( reduction-operator : variable-list ) */
18844
18845static tree
18846c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
18847 bool is_omp, tree list)
18848{
18849 location_t clause_loc = c_parser_peek_token (parser)->location;
18850 matching_parens parens;
18851 if (parens.require_open (parser))
18852 {
18853 bool task = false;
18854 bool inscan = false;
18855 enum tree_code code = ERROR_MARK;
18856 tree reduc_id = NULL_TREE;
18857
18858 if (kind == OMP_CLAUSE_REDUCTION && is_omp)
18859 {
18860 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
18861 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18862 {
18863 c_parser_consume_token (parser);
18864 c_parser_consume_token (parser);
18865 }
18866 else if (c_parser_next_token_is (parser, type: CPP_NAME)
18867 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18868 {
18869 const char *p
18870 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18871 if (strcmp (s1: p, s2: "task") == 0)
18872 task = true;
18873 else if (strcmp (s1: p, s2: "inscan") == 0)
18874 inscan = true;
18875 if (task || inscan)
18876 {
18877 c_parser_consume_token (parser);
18878 c_parser_consume_token (parser);
18879 }
18880 }
18881 }
18882
18883 switch (c_parser_peek_token (parser)->type)
18884 {
18885 case CPP_PLUS:
18886 code = PLUS_EXPR;
18887 break;
18888 case CPP_MULT:
18889 code = MULT_EXPR;
18890 break;
18891 case CPP_MINUS:
18892 if (is_omp)
18893 {
18894 location_t loc = c_parser_peek_token (parser)->location;
18895 gcc_rich_location richloc (loc);
18896 richloc.add_fixit_replace (new_content: "+");
18897 warning_at (&richloc, OPT_Wdeprecated_openmp,
18898 "%<-%> operator for reductions deprecated in "
18899 "OpenMP 5.2");
18900 }
18901 code = MINUS_EXPR;
18902 break;
18903 case CPP_AND:
18904 code = BIT_AND_EXPR;
18905 break;
18906 case CPP_XOR:
18907 code = BIT_XOR_EXPR;
18908 break;
18909 case CPP_OR:
18910 code = BIT_IOR_EXPR;
18911 break;
18912 case CPP_AND_AND:
18913 code = TRUTH_ANDIF_EXPR;
18914 break;
18915 case CPP_OR_OR:
18916 code = TRUTH_ORIF_EXPR;
18917 break;
18918 case CPP_NAME:
18919 {
18920 const char *p
18921 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18922 if (strcmp (s1: p, s2: "min") == 0)
18923 {
18924 code = MIN_EXPR;
18925 break;
18926 }
18927 if (strcmp (s1: p, s2: "max") == 0)
18928 {
18929 code = MAX_EXPR;
18930 break;
18931 }
18932 reduc_id = c_parser_peek_token (parser)->value;
18933 break;
18934 }
18935 default:
18936 c_parser_error (parser,
18937 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
18938 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
18939 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
18940 return list;
18941 }
18942 c_parser_consume_token (parser);
18943 reduc_id = c_omp_reduction_id (code, reduc_id);
18944 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18945 {
18946 tree nl, c;
18947
18948 nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
18949 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18950 {
18951 tree d = OMP_CLAUSE_DECL (c), type;
18952 if (TREE_CODE (d) != OMP_ARRAY_SECTION)
18953 type = TREE_TYPE (d);
18954 else
18955 {
18956 int cnt = 0;
18957 tree t;
18958 for (t = d;
18959 TREE_CODE (t) == OMP_ARRAY_SECTION;
18960 t = TREE_OPERAND (t, 0))
18961 cnt++;
18962 type = TREE_TYPE (t);
18963 while (cnt > 0)
18964 {
18965 if (TREE_CODE (type) != POINTER_TYPE
18966 && TREE_CODE (type) != ARRAY_TYPE)
18967 break;
18968 type = TREE_TYPE (type);
18969 cnt--;
18970 }
18971 }
18972 while (TREE_CODE (type) == ARRAY_TYPE)
18973 type = TREE_TYPE (type);
18974 OMP_CLAUSE_REDUCTION_CODE (c) = code;
18975 if (task)
18976 OMP_CLAUSE_REDUCTION_TASK (c) = 1;
18977 else if (inscan)
18978 OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
18979 if (code == ERROR_MARK
18980 || !(INTEGRAL_TYPE_P (type)
18981 || SCALAR_FLOAT_TYPE_P (type)
18982 || TREE_CODE (type) == COMPLEX_TYPE))
18983 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
18984 = c_omp_reduction_lookup (reduc_id,
18985 TYPE_MAIN_VARIANT (type));
18986 }
18987
18988 list = nl;
18989 }
18990 parens.skip_until_found_close (parser);
18991 }
18992 return list;
18993}
18994
18995/* OpenMP 2.5:
18996 schedule ( schedule-kind )
18997 schedule ( schedule-kind , expression )
18998
18999 schedule-kind:
19000 static | dynamic | guided | runtime | auto
19001
19002 OpenMP 4.5:
19003 schedule ( schedule-modifier : schedule-kind )
19004 schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
19005
19006 schedule-modifier:
19007 simd
19008 monotonic
19009 nonmonotonic */
19010
19011static tree
19012c_parser_omp_clause_schedule (c_parser *parser, tree list)
19013{
19014 tree c, t;
19015 location_t loc = c_parser_peek_token (parser)->location;
19016 int modifiers = 0, nmodifiers = 0;
19017
19018 matching_parens parens;
19019 if (!parens.require_open (parser))
19020 return list;
19021
19022 c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
19023
19024 location_t comma = UNKNOWN_LOCATION;
19025 while (c_parser_next_token_is (parser, type: CPP_NAME))
19026 {
19027 tree kind = c_parser_peek_token (parser)->value;
19028 const char *p = IDENTIFIER_POINTER (kind);
19029 if (strcmp (s1: "simd", s2: p) == 0)
19030 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
19031 else if (strcmp (s1: "monotonic", s2: p) == 0)
19032 modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
19033 else if (strcmp (s1: "nonmonotonic", s2: p) == 0)
19034 modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
19035 else
19036 break;
19037 comma = UNKNOWN_LOCATION;
19038 c_parser_consume_token (parser);
19039 if (nmodifiers++ == 0
19040 && c_parser_next_token_is (parser, type: CPP_COMMA))
19041 {
19042 comma = c_parser_peek_token (parser)->location;
19043 c_parser_consume_token (parser);
19044 }
19045 else
19046 {
19047 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
19048 break;
19049 }
19050 }
19051 if (comma != UNKNOWN_LOCATION)
19052 error_at (comma, "expected %<:%>");
19053
19054 if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
19055 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
19056 == (OMP_CLAUSE_SCHEDULE_MONOTONIC
19057 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
19058 {
19059 error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
19060 "specified");
19061 modifiers = 0;
19062 }
19063
19064 if (c_parser_next_token_is (parser, type: CPP_NAME))
19065 {
19066 tree kind = c_parser_peek_token (parser)->value;
19067 const char *p = IDENTIFIER_POINTER (kind);
19068
19069 switch (p[0])
19070 {
19071 case 'd':
19072 if (strcmp (s1: "dynamic", s2: p) != 0)
19073 goto invalid_kind;
19074 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
19075 break;
19076
19077 case 'g':
19078 if (strcmp (s1: "guided", s2: p) != 0)
19079 goto invalid_kind;
19080 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
19081 break;
19082
19083 case 'r':
19084 if (strcmp (s1: "runtime", s2: p) != 0)
19085 goto invalid_kind;
19086 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
19087 break;
19088
19089 default:
19090 goto invalid_kind;
19091 }
19092 }
19093 else if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
19094 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
19095 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
19096 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
19097 else
19098 goto invalid_kind;
19099
19100 c_parser_consume_token (parser);
19101 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19102 {
19103 location_t here;
19104 c_parser_consume_token (parser);
19105
19106 here = c_parser_peek_token (parser)->location;
19107 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19108 expr = convert_lvalue_to_rvalue (here, expr, false, true);
19109 t = expr.value;
19110 t = c_fully_fold (t, false, NULL);
19111
19112 if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
19113 error_at (here, "schedule %<runtime%> does not take "
19114 "a %<chunk_size%> parameter");
19115 else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
19116 error_at (here,
19117 "schedule %<auto%> does not take "
19118 "a %<chunk_size%> parameter");
19119 else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
19120 || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
19121 {
19122 /* Attempt to statically determine when the number isn't
19123 positive. */
19124 tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
19125 build_int_cst (TREE_TYPE (t), 0));
19126 protected_set_expr_location (s, loc);
19127 if (s == boolean_true_node)
19128 {
19129 warning_at (loc, OPT_Wopenmp,
19130 "chunk size value must be positive");
19131 t = integer_one_node;
19132 }
19133 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
19134 }
19135 else
19136 c_parser_error (parser, gmsgid: "expected integer expression");
19137
19138 parens.skip_until_found_close (parser);
19139 }
19140 else
19141 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
19142 msgid: "expected %<,%> or %<)%>");
19143
19144 OMP_CLAUSE_SCHEDULE_KIND (c)
19145 = (enum omp_clause_schedule_kind)
19146 (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
19147
19148 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule");
19149 OMP_CLAUSE_CHAIN (c) = list;
19150 return c;
19151
19152 invalid_kind:
19153 c_parser_error (parser, gmsgid: "invalid schedule kind");
19154 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
19155 return list;
19156}
19157
19158/* OpenMP 2.5:
19159 shared ( variable-list ) */
19160
19161static tree
19162c_parser_omp_clause_shared (c_parser *parser, tree list)
19163{
19164 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_SHARED, list);
19165}
19166
19167/* OpenMP 3.0:
19168 untied */
19169
19170static tree
19171c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
19172{
19173 tree c;
19174
19175 /* FIXME: Should we allow duplicates? */
19176 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied");
19177
19178 c = build_omp_clause (c_parser_peek_token (parser)->location,
19179 OMP_CLAUSE_UNTIED);
19180 OMP_CLAUSE_CHAIN (c) = list;
19181
19182 return c;
19183}
19184
19185/* OpenMP 4.0:
19186 inbranch
19187 notinbranch */
19188
19189static tree
19190c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
19191 enum omp_clause_code code, tree list)
19192{
19193 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
19194
19195 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19196 OMP_CLAUSE_CHAIN (c) = list;
19197
19198 return c;
19199}
19200
19201/* OpenMP 4.0:
19202 parallel
19203 for
19204 sections
19205 taskgroup */
19206
19207static tree
19208c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
19209 enum omp_clause_code code, tree list)
19210{
19211 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19212 OMP_CLAUSE_CHAIN (c) = list;
19213
19214 return c;
19215}
19216
19217/* OpenMP 4.5:
19218 nogroup */
19219
19220static tree
19221c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
19222{
19223 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup");
19224 tree c = build_omp_clause (c_parser_peek_token (parser)->location,
19225 OMP_CLAUSE_NOGROUP);
19226 OMP_CLAUSE_CHAIN (c) = list;
19227 return c;
19228}
19229
19230/* OpenMP 4.5:
19231 simd
19232 threads */
19233
19234static tree
19235c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
19236 enum omp_clause_code code, tree list)
19237{
19238 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
19239 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19240 OMP_CLAUSE_CHAIN (c) = list;
19241 return c;
19242}
19243
19244/* OpenMP 4.0:
19245 num_teams ( expression )
19246
19247 OpenMP 5.1:
19248 num_teams ( expression : expression ) */
19249
19250static tree
19251c_parser_omp_clause_num_teams (c_parser *parser, tree list)
19252{
19253 location_t num_teams_loc = c_parser_peek_token (parser)->location;
19254 matching_parens parens;
19255 if (parens.require_open (parser))
19256 {
19257 location_t upper_loc = c_parser_peek_token (parser)->location;
19258 location_t lower_loc = UNKNOWN_LOCATION;
19259 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19260 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
19261 tree c, upper = expr.value, lower = NULL_TREE;
19262 upper = c_fully_fold (upper, false, NULL);
19263
19264 if (c_parser_next_token_is (parser, type: CPP_COLON))
19265 {
19266 c_parser_consume_token (parser);
19267 lower_loc = upper_loc;
19268 lower = upper;
19269 upper_loc = c_parser_peek_token (parser)->location;
19270 expr = c_parser_expr_no_commas (parser, NULL);
19271 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
19272 upper = expr.value;
19273 upper = c_fully_fold (upper, false, NULL);
19274 }
19275
19276 parens.skip_until_found_close (parser);
19277
19278 if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
19279 || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
19280 {
19281 c_parser_error (parser, gmsgid: "expected integer expression");
19282 return list;
19283 }
19284
19285 /* Attempt to statically determine when the number isn't positive. */
19286 c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
19287 build_int_cst (TREE_TYPE (upper), 0));
19288 protected_set_expr_location (c, upper_loc);
19289 if (c == boolean_true_node)
19290 {
19291 warning_at (upper_loc, OPT_Wopenmp,
19292 "%<num_teams%> value must be positive");
19293 upper = integer_one_node;
19294 }
19295 if (lower)
19296 {
19297 c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
19298 build_int_cst (TREE_TYPE (lower), 0));
19299 protected_set_expr_location (c, lower_loc);
19300 if (c == boolean_true_node)
19301 {
19302 warning_at (lower_loc, OPT_Wopenmp,
19303 "%<num_teams%> value must be positive");
19304 lower = NULL_TREE;
19305 }
19306 else if (TREE_CODE (lower) == INTEGER_CST
19307 && TREE_CODE (upper) == INTEGER_CST
19308 && tree_int_cst_lt (t1: upper, t2: lower))
19309 {
19310 warning_at (lower_loc, OPT_Wopenmp,
19311 "%<num_teams%> lower bound %qE bigger than upper "
19312 "bound %qE", lower, upper);
19313 lower = NULL_TREE;
19314 }
19315 }
19316
19317 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, name: "num_teams");
19318
19319 c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
19320 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
19321 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
19322 OMP_CLAUSE_CHAIN (c) = list;
19323 list = c;
19324 }
19325
19326 return list;
19327}
19328
19329/* OpenMP 4.0:
19330 thread_limit ( expression ) */
19331
19332static tree
19333c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
19334{
19335 location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
19336 matching_parens parens;
19337 if (parens.require_open (parser))
19338 {
19339 location_t expr_loc = c_parser_peek_token (parser)->location;
19340 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19341 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19342 tree c, t = expr.value;
19343 t = c_fully_fold (t, false, NULL);
19344
19345 parens.skip_until_found_close (parser);
19346
19347 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
19348 {
19349 c_parser_error (parser, gmsgid: "expected integer expression");
19350 return list;
19351 }
19352
19353 /* Attempt to statically determine when the number isn't positive. */
19354 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
19355 build_int_cst (TREE_TYPE (t), 0));
19356 protected_set_expr_location (c, expr_loc);
19357 if (c == boolean_true_node)
19358 {
19359 warning_at (expr_loc, OPT_Wopenmp,
19360 "%<thread_limit%> value must be positive");
19361 t = integer_one_node;
19362 }
19363
19364 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT,
19365 name: "thread_limit");
19366
19367 c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
19368 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
19369 OMP_CLAUSE_CHAIN (c) = list;
19370 list = c;
19371 }
19372
19373 return list;
19374}
19375
19376/* OpenMP 4.0:
19377 aligned ( variable-list )
19378 aligned ( variable-list : constant-expression ) */
19379
19380static tree
19381c_parser_omp_clause_aligned (c_parser *parser, tree list)
19382{
19383 location_t clause_loc = c_parser_peek_token (parser)->location;
19384 tree nl, c;
19385
19386 matching_parens parens;
19387 if (!parens.require_open (parser))
19388 return list;
19389
19390 nl = c_parser_omp_variable_list (parser, clause_loc,
19391 kind: OMP_CLAUSE_ALIGNED, list);
19392
19393 if (c_parser_next_token_is (parser, type: CPP_COLON))
19394 {
19395 c_parser_consume_token (parser);
19396 location_t expr_loc = c_parser_peek_token (parser)->location;
19397 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19398 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19399 tree alignment = expr.value;
19400 alignment = c_fully_fold (alignment, false, NULL);
19401 if (TREE_CODE (alignment) != INTEGER_CST
19402 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
19403 || tree_int_cst_sgn (alignment) != 1)
19404 {
19405 error_at (clause_loc, "%<aligned%> clause alignment expression must "
19406 "be positive constant integer expression");
19407 alignment = NULL_TREE;
19408 }
19409
19410 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19411 OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
19412 }
19413
19414 parens.skip_until_found_close (parser);
19415 return nl;
19416}
19417
19418/* OpenMP 5.0:
19419 allocate ( variable-list )
19420 allocate ( expression : variable-list )
19421
19422 OpenMP 5.1:
19423 allocate ( allocator-modifier : variable-list )
19424 allocate ( allocator-modifier , allocator-modifier : variable-list )
19425
19426 allocator-modifier:
19427 allocator ( expression )
19428 align ( expression ) */
19429
19430static tree
19431c_parser_omp_clause_allocate (c_parser *parser, tree list)
19432{
19433 location_t clause_loc = c_parser_peek_token (parser)->location;
19434 tree nl, c;
19435 tree allocator = NULL_TREE;
19436 tree align = NULL_TREE;
19437
19438 matching_parens parens;
19439 if (!parens.require_open (parser))
19440 return list;
19441
19442 if ((c_parser_next_token_is_not (parser, type: CPP_NAME)
19443 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
19444 || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
19445 && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
19446 {
19447 bool has_modifiers = false;
19448 tree orig_type = NULL_TREE;
19449 if (c_parser_next_token_is (parser, type: CPP_NAME)
19450 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19451 {
19452 unsigned int n = 3;
19453 const char *p
19454 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19455 if ((strcmp (s1: p, s2: "allocator") == 0 || strcmp (s1: p, s2: "align") == 0)
19456 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
19457 && (c_parser_peek_nth_token_raw (parser, n)->type
19458 == CPP_CLOSE_PAREN))
19459 {
19460 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19461 == CPP_COLON)
19462 has_modifiers = true;
19463 else if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19464 == CPP_COMMA
19465 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
19466 == CPP_NAME)
19467 && (c_parser_peek_nth_token_raw (parser, n: n + 3)->type
19468 == CPP_OPEN_PAREN))
19469 {
19470 c_token *tok = c_parser_peek_nth_token_raw (parser, n: n + 2);
19471 const char *q = IDENTIFIER_POINTER (tok->value);
19472 n += 4;
19473 if ((strcmp (s1: q, s2: "allocator") == 0
19474 || strcmp (s1: q, s2: "align") == 0)
19475 && c_parser_check_balanced_raw_token_sequence (parser,
19476 n: &n)
19477 && (c_parser_peek_nth_token_raw (parser, n)->type
19478 == CPP_CLOSE_PAREN)
19479 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19480 == CPP_COLON))
19481 has_modifiers = true;
19482 }
19483 }
19484 if (has_modifiers)
19485 {
19486 c_parser_consume_token (parser);
19487 matching_parens parens2;
19488 parens2.require_open (parser);
19489 location_t expr_loc = c_parser_peek_token (parser)->location;
19490 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19491 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19492 if (expr.value == error_mark_node)
19493 ;
19494 else if (strcmp (s1: p, s2: "allocator") == 0)
19495 {
19496 allocator = expr.value;
19497 allocator = c_fully_fold (allocator, false, NULL);
19498 orig_type = expr.original_type
19499 ? expr.original_type : TREE_TYPE (allocator);
19500 orig_type = TYPE_MAIN_VARIANT (orig_type);
19501 }
19502 else
19503 {
19504 align = expr.value;
19505 align = c_fully_fold (align, false, NULL);
19506 }
19507 parens2.skip_until_found_close (parser);
19508 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19509 {
19510 c_parser_consume_token (parser);
19511 c_token *tok = c_parser_peek_token (parser);
19512 const char *q = "";
19513 if (c_parser_next_token_is (parser, type: CPP_NAME))
19514 q = IDENTIFIER_POINTER (tok->value);
19515 if (strcmp (s1: q, s2: "allocator") != 0 && strcmp (s1: q, s2: "align") != 0)
19516 {
19517 c_parser_error (parser, gmsgid: "expected %<allocator%> or "
19518 "%<align%>");
19519 parens.skip_until_found_close (parser);
19520 return list;
19521 }
19522 else if (strcmp (s1: p, s2: q) == 0)
19523 {
19524 error_at (tok->location, "duplicate %qs modifier", p);
19525 parens.skip_until_found_close (parser);
19526 return list;
19527 }
19528 c_parser_consume_token (parser);
19529 if (!parens2.require_open (parser))
19530 {
19531 parens.skip_until_found_close (parser);
19532 return list;
19533 }
19534 expr_loc = c_parser_peek_token (parser)->location;
19535 expr = c_parser_expr_no_commas (parser, NULL);
19536 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19537 true);
19538 if (strcmp (s1: q, s2: "allocator") == 0)
19539 {
19540 allocator = expr.value;
19541 allocator = c_fully_fold (allocator, false, NULL);
19542 orig_type = expr.original_type
19543 ? expr.original_type : TREE_TYPE (allocator);
19544 orig_type = TYPE_MAIN_VARIANT (orig_type);
19545 }
19546 else
19547 {
19548 align = expr.value;
19549 align = c_fully_fold (align, false, NULL);
19550 }
19551 parens2.skip_until_found_close (parser);
19552 }
19553 }
19554 }
19555 if (!has_modifiers)
19556 {
19557 location_t expr_loc = c_parser_peek_token (parser)->location;
19558 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19559 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19560 allocator = expr.value;
19561 allocator = c_fully_fold (allocator, false, NULL);
19562 orig_type = expr.original_type
19563 ? expr.original_type : TREE_TYPE (allocator);
19564 orig_type = TYPE_MAIN_VARIANT (orig_type);
19565 }
19566 if (allocator
19567 && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
19568 || TREE_CODE (orig_type) != ENUMERAL_TYPE
19569 || (TYPE_NAME (orig_type)
19570 != get_identifier ("omp_allocator_handle_t"))))
19571 {
19572 error_at (clause_loc, "%<allocate%> clause allocator expression "
19573 "has type %qT rather than "
19574 "%<omp_allocator_handle_t%>",
19575 TREE_TYPE (allocator));
19576 allocator = NULL_TREE;
19577 }
19578 if (align
19579 && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
19580 || !tree_fits_uhwi_p (align)
19581 || !integer_pow2p (align)))
19582 {
19583 error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
19584 "argument needs to be positive constant "
19585 "power of two integer expression");
19586 align = NULL_TREE;
19587 }
19588 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19589 {
19590 parens.skip_until_found_close (parser);
19591 return list;
19592 }
19593 }
19594
19595 nl = c_parser_omp_variable_list (parser, clause_loc,
19596 kind: OMP_CLAUSE_ALLOCATE, list);
19597
19598 if (allocator || align)
19599 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19600 {
19601 OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
19602 OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
19603 }
19604
19605 parens.skip_until_found_close (parser);
19606 return nl;
19607}
19608
19609/* OpenMP 5.0:
19610 uses_allocators ( allocator-list )
19611
19612 allocator-list:
19613 allocator
19614 allocator , allocator-list
19615 allocator ( traits-array )
19616 allocator ( traits-array ) , allocator-list
19617
19618 Deprecated in 5.2, removed in 6.0: 'allocator(trait-array)' syntax.
19619
19620 OpenMP 5.2:
19621
19622 uses_allocators ( modifier : allocator-list )
19623 uses_allocators ( modifier , modifier : allocator-list )
19624
19625 OpenMP 6.0:
19626 uses_allocators ( [modifier-list :] allocator-list [; ...] )
19627
19628 modifier:
19629 traits ( traits-array )
19630 memspace ( mem-space-handle ) */
19631
19632static tree
19633c_parser_omp_clause_uses_allocators (c_parser *parser, tree list)
19634{
19635 location_t clause_loc = c_parser_peek_token (parser)->location;
19636 tree nl = list;
19637 matching_parens parens;
19638 if (!parens.require_open (parser))
19639 return list;
19640
19641parse_next:
19642
19643 bool has_modifiers = false;
19644 bool seen_allocators = false;
19645 tree memspace_expr = NULL_TREE;
19646 tree traits_var = NULL_TREE;
19647
19648 if (c_parser_next_token_is (parser, type: CPP_NAME)
19649 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19650 {
19651 unsigned int n = 3;
19652 const char *p
19653 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19654 if ((strcmp (s1: p, s2: "traits") == 0 || strcmp (s1: p, s2: "memspace") == 0)
19655 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
19656 && (c_parser_peek_nth_token_raw (parser, n)->type
19657 == CPP_CLOSE_PAREN))
19658 {
19659 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19660 == CPP_COLON)
19661 has_modifiers = true;
19662 else if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19663 == CPP_COMMA
19664 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
19665 == CPP_NAME)
19666 && (c_parser_peek_nth_token_raw (parser, n: n + 3)->type
19667 == CPP_OPEN_PAREN))
19668 {
19669 c_token *tok = c_parser_peek_nth_token_raw (parser, n: n + 2);
19670 const char *q = IDENTIFIER_POINTER (tok->value);
19671 n += 4;
19672 if ((strcmp (s1: q, s2: "traits") == 0
19673 || strcmp (s1: q, s2: "memspace") == 0)
19674 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
19675 && (c_parser_peek_nth_token_raw (parser, n)->type
19676 == CPP_CLOSE_PAREN))
19677 {
19678 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19679 == CPP_COLON)
19680 has_modifiers = true;
19681 if ((c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19682 == CPP_COMMA)
19683 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
19684 == CPP_NAME))
19685 {
19686 c_token *tok
19687 = c_parser_peek_nth_token_raw (parser, n: n + 2);
19688 const char *m = IDENTIFIER_POINTER (tok->value);
19689 if (strcmp (s1: p, s2: m) == 0 || strcmp (s1: q, s2: m) == 0)
19690 {
19691 error_at (tok->location, "duplicate %qs modifier", m);
19692 goto end;
19693 }
19694 }
19695 }
19696 }
19697 }
19698 if (has_modifiers)
19699 {
19700 c_parser_consume_token (parser);
19701 matching_parens parens2;
19702 parens2.require_open (parser);
19703 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19704 if (expr.value == error_mark_node)
19705 ;
19706 else if (strcmp (s1: p, s2: "traits") == 0)
19707 {
19708 traits_var = expr.value;
19709 traits_var = c_fully_fold (traits_var, false, NULL);
19710 }
19711 else
19712 {
19713 memspace_expr = expr.value;
19714 memspace_expr = c_fully_fold (memspace_expr, false, NULL);
19715 }
19716 parens2.skip_until_found_close (parser);
19717 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19718 {
19719 c_parser_consume_token (parser);
19720 c_token *tok = c_parser_peek_token (parser);
19721 const char *q = "";
19722 if (c_parser_next_token_is (parser, type: CPP_NAME))
19723 q = IDENTIFIER_POINTER (tok->value);
19724 if (strcmp (s1: q, s2: "traits") != 0 && strcmp (s1: q, s2: "memspace") != 0)
19725 {
19726 c_parser_error (parser, gmsgid: "expected %<traits%> or "
19727 "%<memspace%>");
19728 parens.skip_until_found_close (parser);
19729 return list;
19730 }
19731 else if (strcmp (s1: p, s2: q) == 0)
19732 {
19733 error_at (tok->location, "duplicate %qs modifier", p);
19734 parens.skip_until_found_close (parser);
19735 return list;
19736 }
19737 c_parser_consume_token (parser);
19738 if (!parens2.require_open (parser))
19739 {
19740 parens.skip_until_found_close (parser);
19741 return list;
19742 }
19743 expr = c_parser_expr_no_commas (parser, NULL);
19744 if (strcmp (s1: q, s2: "traits") == 0)
19745 {
19746 traits_var = expr.value;
19747 traits_var = c_fully_fold (traits_var, false, NULL);
19748 }
19749 else
19750 {
19751 memspace_expr = expr.value;
19752 memspace_expr = c_fully_fold (memspace_expr, false, NULL);
19753 }
19754 parens2.skip_until_found_close (parser);
19755 }
19756 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19757 goto end;
19758 }
19759 }
19760
19761 while (c_parser_next_token_is (parser, type: CPP_NAME))
19762 {
19763 location_t alloc_loc = c_parser_peek_token (parser)->location;
19764 c_token *tok = c_parser_peek_token (parser);
19765 const char *tok_s = IDENTIFIER_POINTER (tok->value);
19766 tree t = lookup_name (tok->value);
19767 if (t == NULL_TREE)
19768 {
19769 undeclared_variable (tok->location, tok->value);
19770 t = error_mark_node;
19771 }
19772 c_parser_consume_token (parser);
19773
19774 /* Legacy traits syntax. */
19775 tree legacy_traits = NULL_TREE;
19776 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
19777 && c_parser_peek_2nd_token (parser)->type == CPP_NAME
19778 && c_parser_peek_nth_token_raw (parser, n: 3)->type == CPP_CLOSE_PAREN)
19779 {
19780 matching_parens parens2;
19781 parens2.require_open (parser);
19782 const char *tok_a
19783 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19784 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19785 location_t close_loc = c_parser_peek_token (parser)->location;
19786 parens2.skip_until_found_close (parser);
19787
19788 if (has_modifiers)
19789 {
19790 error_at (make_location (caret: alloc_loc, start: alloc_loc, finish: close_loc),
19791 "legacy %<%s(%s)%> traits syntax not allowed in "
19792 "%<uses_allocators%> clause when using modifiers",
19793 tok_s, tok_a);
19794 goto end;
19795 }
19796 legacy_traits = c_fully_fold (expr.value, false, NULL);
19797 if (legacy_traits == error_mark_node)
19798 goto end;
19799
19800 gcc_rich_location richloc (make_location (caret: alloc_loc, start: alloc_loc, finish: close_loc));
19801 if (nl == list)
19802 {
19803 /* Fixit only works well if it is the only first item. */
19804 richloc.add_fixit_replace (where: alloc_loc, new_content: "traits");
19805 richloc.add_fixit_insert_after (where: close_loc, new_content: ": ");
19806 richloc.add_fixit_insert_after (where: close_loc, new_content: tok_s);
19807 }
19808 warning_at (&richloc, OPT_Wdeprecated_openmp,
19809 "the specification of arguments to %<uses_allocators%> "
19810 "where each item is of the form %<allocator(traits)%> is "
19811 "deprecated since OpenMP 5.2");
19812 }
19813
19814 if (seen_allocators && has_modifiers)
19815 {
19816 error_at (c_parser_peek_token (parser)->location,
19817 "%<uses_allocators%> clause only accepts a single "
19818 "allocator when using modifiers");
19819 goto end;
19820 }
19821 seen_allocators = true;
19822
19823 tree c = build_omp_clause (clause_loc,
19824 OMP_CLAUSE_USES_ALLOCATORS);
19825 OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c) = t;
19826 OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (c) = memspace_expr;
19827 OMP_CLAUSE_USES_ALLOCATORS_TRAITS (c) = (legacy_traits
19828 ? legacy_traits : traits_var);
19829 OMP_CLAUSE_CHAIN (c) = nl;
19830 nl = c;
19831
19832 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19833 c_parser_consume_token (parser);
19834 else
19835 break;
19836 }
19837
19838 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
19839 {
19840 c_parser_consume_token (parser);
19841 goto parse_next;
19842 }
19843
19844 end:
19845 parens.skip_until_found_close (parser);
19846 return nl;
19847}
19848
19849/* OpenMP 4.0:
19850 linear ( variable-list )
19851 linear ( variable-list : expression )
19852
19853 OpenMP 4.5:
19854 linear ( modifier ( variable-list ) )
19855 linear ( modifier ( variable-list ) : expression )
19856
19857 modifier:
19858 val
19859
19860 OpenMP 5.2:
19861 linear ( variable-list : modifiers-list )
19862
19863 modifiers:
19864 val
19865 step ( expression ) */
19866
19867static tree
19868c_parser_omp_clause_linear (c_parser *parser, tree list)
19869{
19870 location_t clause_loc = c_parser_peek_token (parser)->location;
19871 location_t rm1_loc = UNKNOWN_LOCATION, rm2_loc = UNKNOWN_LOCATION;
19872 location_t after_colon_loc = UNKNOWN_LOCATION;
19873 tree nl, c, step;
19874 enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
19875 bool old_linear_modifier = false;
19876
19877 matching_parens parens;
19878 if (!parens.require_open (parser))
19879 return list;
19880
19881 if (c_parser_next_token_is (parser, type: CPP_NAME))
19882 {
19883 c_token *tok = c_parser_peek_token (parser);
19884 const char *p = IDENTIFIER_POINTER (tok->value);
19885 if (strcmp (s1: "val", s2: p) == 0)
19886 kind = OMP_CLAUSE_LINEAR_VAL;
19887 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
19888 kind = OMP_CLAUSE_LINEAR_DEFAULT;
19889 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19890 {
19891 old_linear_modifier = true;
19892 rm1_loc = make_location (caret: tok->location, start: tok->location,
19893 finish: c_parser_peek_2nd_token (parser)->location);
19894 c_parser_consume_token (parser);
19895 c_parser_consume_token (parser);
19896 }
19897 }
19898
19899 nl = c_parser_omp_variable_list (parser, clause_loc,
19900 kind: OMP_CLAUSE_LINEAR, list);
19901
19902 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19903 {
19904 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
19905 rm2_loc = c_parser_peek_token (parser)->location;
19906 parens.skip_until_found_close (parser);
19907 }
19908
19909 if (c_parser_next_token_is (parser, type: CPP_COLON))
19910 {
19911 c_parser_consume_token (parser);
19912 location_t expr_loc = c_parser_peek_token (parser)->location;
19913 after_colon_loc = expr_loc;
19914 bool has_modifiers = false;
19915 if (kind == OMP_CLAUSE_LINEAR_DEFAULT
19916 && c_parser_next_token_is (parser, type: CPP_NAME))
19917 {
19918 c_token *tok = c_parser_peek_token (parser);
19919 const char *p = IDENTIFIER_POINTER (tok->value);
19920 unsigned int pos = 0;
19921 if (strcmp (s1: "val", s2: p) == 0)
19922 pos = 2;
19923 else if (strcmp (s1: "step", s2: p) == 0
19924 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19925 {
19926 pos = 3;
19927 if (c_parser_check_balanced_raw_token_sequence (parser, n: &pos)
19928 && (c_parser_peek_nth_token_raw (parser, n: pos)->type
19929 == CPP_CLOSE_PAREN))
19930 ++pos;
19931 else
19932 pos = 0;
19933 }
19934 if (pos)
19935 {
19936 tok = c_parser_peek_nth_token_raw (parser, n: pos);
19937 if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
19938 has_modifiers = true;
19939 }
19940 }
19941 if (has_modifiers)
19942 {
19943 step = NULL_TREE;
19944 while (c_parser_next_token_is (parser, type: CPP_NAME))
19945 {
19946 c_token *tok = c_parser_peek_token (parser);
19947 const char *p = IDENTIFIER_POINTER (tok->value);
19948 if (strcmp (s1: "val", s2: p) == 0)
19949 {
19950 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19951 error_at (tok->location, "multiple linear modifiers");
19952 kind = OMP_CLAUSE_LINEAR_DEFAULT;
19953 c_parser_consume_token (parser);
19954 }
19955 else if (strcmp (s1: "step", s2: p) == 0)
19956 {
19957 c_parser_consume_token (parser);
19958 matching_parens parens2;
19959 if (parens2.require_open (parser))
19960 {
19961 if (step)
19962 error_at (tok->location,
19963 "multiple %<step%> modifiers");
19964 expr_loc = c_parser_peek_token (parser)->location;
19965 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19966 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19967 true);
19968 step = c_fully_fold (expr.value, false, NULL);
19969 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19970 {
19971 error_at (clause_loc, "%<linear%> clause step "
19972 "expression must be integral");
19973 step = integer_one_node;
19974 }
19975 parens2.skip_until_found_close (parser);
19976 }
19977 else
19978 break;
19979 }
19980 else
19981 break;
19982 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19983 {
19984 c_parser_consume_token (parser);
19985 continue;
19986 }
19987 break;
19988 }
19989 if (!step)
19990 step = integer_one_node;
19991 }
19992 else
19993 {
19994 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19995 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19996 step = c_fully_fold (expr.value, false, NULL);
19997 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19998 {
19999 error_at (clause_loc, "%<linear%> clause step expression must "
20000 "be integral");
20001 step = integer_one_node;
20002 }
20003 }
20004
20005 }
20006 else
20007 step = integer_one_node;
20008
20009 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20010 {
20011 OMP_CLAUSE_LINEAR_STEP (c) = step;
20012 OMP_CLAUSE_LINEAR_KIND (c) = kind;
20013 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
20014 }
20015
20016 if (old_linear_modifier)
20017 {
20018 gcc_rich_location richloc (clause_loc);
20019 if (rm2_loc != UNKNOWN_LOCATION)
20020 {
20021 richloc.add_fixit_remove (where: rm1_loc);
20022 if (after_colon_loc != UNKNOWN_LOCATION)
20023 {
20024 richloc.add_fixit_remove (where: rm2_loc);
20025 richloc.add_fixit_insert_before (where: after_colon_loc, new_content: "val, step (");
20026 location_t close_loc = c_parser_peek_token (parser)->location;
20027 richloc.add_fixit_insert_before (where: close_loc, new_content: ")");
20028 }
20029 else
20030 richloc.add_fixit_replace (where: rm2_loc, new_content: " : val");
20031 }
20032 warning_at (&richloc, OPT_Wdeprecated_openmp,
20033 "specifying the list items as arguments to the "
20034 "modifiers is deprecated since OpenMP 5.2");
20035 }
20036
20037 parens.skip_until_found_close (parser);
20038 return nl;
20039}
20040
20041/* OpenMP 5.0:
20042 nontemporal ( variable-list ) */
20043
20044static tree
20045c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
20046{
20047 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_NONTEMPORAL, list);
20048}
20049
20050/* OpenMP 4.0:
20051 safelen ( constant-expression ) */
20052
20053static tree
20054c_parser_omp_clause_safelen (c_parser *parser, tree list)
20055{
20056 location_t clause_loc = c_parser_peek_token (parser)->location;
20057 tree c, t;
20058
20059 matching_parens parens;
20060 if (!parens.require_open (parser))
20061 return list;
20062
20063 location_t expr_loc = c_parser_peek_token (parser)->location;
20064 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20065 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20066 t = expr.value;
20067 t = c_fully_fold (t, false, NULL);
20068 if (TREE_CODE (t) != INTEGER_CST
20069 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
20070 || tree_int_cst_sgn (t) != 1)
20071 {
20072 error_at (clause_loc, "%<safelen%> clause expression must "
20073 "be positive constant integer expression");
20074 t = NULL_TREE;
20075 }
20076
20077 parens.skip_until_found_close (parser);
20078 if (t == NULL_TREE || t == error_mark_node)
20079 return list;
20080
20081 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen");
20082
20083 c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
20084 OMP_CLAUSE_SAFELEN_EXPR (c) = t;
20085 OMP_CLAUSE_CHAIN (c) = list;
20086 return c;
20087}
20088
20089/* OpenMP 4.0:
20090 simdlen ( constant-expression ) */
20091
20092static tree
20093c_parser_omp_clause_simdlen (c_parser *parser, tree list)
20094{
20095 location_t clause_loc = c_parser_peek_token (parser)->location;
20096 tree c, t;
20097
20098 matching_parens parens;
20099 if (!parens.require_open (parser))
20100 return list;
20101
20102 location_t expr_loc = c_parser_peek_token (parser)->location;
20103 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20104 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20105 t = expr.value;
20106 t = c_fully_fold (t, false, NULL);
20107 if (TREE_CODE (t) != INTEGER_CST
20108 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
20109 || tree_int_cst_sgn (t) != 1)
20110 {
20111 error_at (clause_loc, "%<simdlen%> clause expression must "
20112 "be positive constant integer expression");
20113 t = NULL_TREE;
20114 }
20115
20116 parens.skip_until_found_close (parser);
20117 if (t == NULL_TREE || t == error_mark_node)
20118 return list;
20119
20120 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen");
20121
20122 c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
20123 OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
20124 OMP_CLAUSE_CHAIN (c) = list;
20125 return c;
20126}
20127
20128/* OpenMP 4.5:
20129 vec:
20130 identifier [+/- integer]
20131 vec , identifier [+/- integer]
20132*/
20133
20134static tree
20135c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
20136 tree list, bool depend_p)
20137{
20138 tree vec = NULL;
20139 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
20140 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
20141 {
20142 c_parser_error (parser, gmsgid: "expected identifier");
20143 return list;
20144 }
20145
20146 if (!depend_p)
20147 {
20148 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20149 if (strcmp (s1: p, s2: "omp_cur_iteration") == 0
20150 && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
20151 && c_parser_peek_nth_token (parser, n: 3)->type == CPP_NUMBER
20152 && c_parser_peek_nth_token (parser, n: 4)->type == CPP_CLOSE_PAREN)
20153 {
20154 tree val = c_parser_peek_nth_token (parser, n: 3)->value;
20155 if (integer_onep (val))
20156 {
20157 c_parser_consume_token (parser);
20158 c_parser_consume_token (parser);
20159 c_parser_consume_token (parser);
20160 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20161 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
20162 OMP_CLAUSE_CHAIN (u) = list;
20163 return u;
20164 }
20165 }
20166 }
20167
20168
20169
20170 while (c_parser_next_token_is (parser, type: CPP_NAME)
20171 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
20172 {
20173 tree t = lookup_name (c_parser_peek_token (parser)->value);
20174 tree addend = NULL;
20175
20176 if (t == NULL_TREE)
20177 {
20178 undeclared_variable (c_parser_peek_token (parser)->location,
20179 c_parser_peek_token (parser)->value);
20180 t = error_mark_node;
20181 }
20182
20183 c_parser_consume_token (parser);
20184
20185 bool neg = false;
20186 if (c_parser_next_token_is (parser, type: CPP_MINUS))
20187 neg = true;
20188 else if (!c_parser_next_token_is (parser, type: CPP_PLUS))
20189 {
20190 addend = integer_zero_node;
20191 neg = false;
20192 goto add_to_vector;
20193 }
20194 c_parser_consume_token (parser);
20195
20196 if (c_parser_next_token_is_not (parser, type: CPP_NUMBER))
20197 {
20198 c_parser_error (parser, gmsgid: "expected integer");
20199 return list;
20200 }
20201
20202 addend = c_parser_peek_token (parser)->value;
20203 if (TREE_CODE (addend) != INTEGER_CST)
20204 {
20205 c_parser_error (parser, gmsgid: "expected integer");
20206 return list;
20207 }
20208 c_parser_consume_token (parser);
20209
20210 add_to_vector:
20211 if (t != error_mark_node)
20212 {
20213 vec = tree_cons (addend, t, vec);
20214 if (neg)
20215 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
20216 }
20217
20218 if (c_parser_next_token_is_not (parser, type: CPP_COMMA)
20219 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
20220 || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
20221 break;
20222
20223 c_parser_consume_token (parser);
20224 }
20225
20226 if (vec == NULL_TREE)
20227 return list;
20228
20229 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20230 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
20231 OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
20232 OMP_CLAUSE_DECL (u) = nreverse (vec);
20233 OMP_CLAUSE_CHAIN (u) = list;
20234 return u;
20235}
20236
20237/* OpenMP 5.0:
20238 iterators ( iterators-definition )
20239
20240 iterators-definition:
20241 iterator-specifier
20242 iterator-specifier , iterators-definition
20243
20244 iterator-specifier:
20245 identifier = range-specification
20246 iterator-type identifier = range-specification
20247
20248 range-specification:
20249 begin : end
20250 begin : end : step */
20251
20252static tree
20253c_parser_omp_iterators (c_parser *parser)
20254{
20255 tree ret = NULL_TREE, *last = &ret;
20256 c_parser_consume_token (parser);
20257
20258 push_scope ();
20259
20260 matching_parens parens;
20261 if (!parens.require_open (parser))
20262 return error_mark_node;
20263
20264 do
20265 {
20266 tree iter_type = NULL_TREE, type_expr = NULL_TREE;
20267 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
20268 {
20269 struct c_type_name *type = c_parser_type_name (parser);
20270 if (type != NULL)
20271 iter_type = groktypename (type, &type_expr, NULL);
20272 }
20273 if (iter_type == NULL_TREE)
20274 iter_type = integer_type_node;
20275
20276 location_t loc = c_parser_peek_token (parser)->location;
20277 if (!c_parser_next_token_is (parser, type: CPP_NAME))
20278 {
20279 c_parser_error (parser, gmsgid: "expected identifier");
20280 break;
20281 }
20282
20283 tree id = c_parser_peek_token (parser)->value;
20284 c_parser_consume_token (parser);
20285
20286 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
20287 break;
20288
20289 location_t eloc = c_parser_peek_token (parser)->location;
20290 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20291 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20292 tree begin = expr.value;
20293
20294 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
20295 break;
20296
20297 eloc = c_parser_peek_token (parser)->location;
20298 expr = c_parser_expr_no_commas (parser, NULL);
20299 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20300 tree end = expr.value;
20301
20302 tree step = integer_one_node;
20303 if (c_parser_next_token_is (parser, type: CPP_COLON))
20304 {
20305 c_parser_consume_token (parser);
20306 eloc = c_parser_peek_token (parser)->location;
20307 expr = c_parser_expr_no_commas (parser, NULL);
20308 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20309 step = expr.value;
20310 }
20311
20312 tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
20313 DECL_ARTIFICIAL (iter_var) = 1;
20314 DECL_CONTEXT (iter_var) = current_function_decl;
20315 pushdecl (iter_var);
20316
20317 *last = make_tree_vec (6);
20318 TREE_VEC_ELT (*last, 0) = iter_var;
20319 TREE_VEC_ELT (*last, 1) = begin;
20320 TREE_VEC_ELT (*last, 2) = end;
20321 TREE_VEC_ELT (*last, 3) = step;
20322 last = &TREE_CHAIN (*last);
20323
20324 if (c_parser_next_token_is (parser, type: CPP_COMMA))
20325 {
20326 c_parser_consume_token (parser);
20327 continue;
20328 }
20329 break;
20330 }
20331 while (1);
20332
20333 parens.skip_until_found_close (parser);
20334 return ret ? ret : error_mark_node;
20335}
20336
20337/* OpenMP 5.0:
20338 affinity ( [aff-modifier :] variable-list )
20339 aff-modifier:
20340 iterator ( iterators-definition ) */
20341
20342static tree
20343c_parser_omp_clause_affinity (c_parser *parser, tree list)
20344{
20345 location_t clause_loc = c_parser_peek_token (parser)->location;
20346 tree nl, iterators = NULL_TREE;
20347
20348 matching_parens parens;
20349 if (!parens.require_open (parser))
20350 return list;
20351
20352 if (c_parser_next_token_is (parser, type: CPP_NAME))
20353 {
20354 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20355 bool parse_iter = ((strcmp (s1: "iterator", s2: p) == 0)
20356 && (c_parser_peek_2nd_token (parser)->type
20357 == CPP_OPEN_PAREN));
20358 if (parse_iter)
20359 {
20360 unsigned n = 3;
20361 parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, n: &n)
20362 && (c_parser_peek_nth_token_raw (parser, n)->type
20363 == CPP_CLOSE_PAREN)
20364 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
20365 == CPP_COLON));
20366 }
20367 if (parse_iter)
20368 {
20369 iterators = c_parser_omp_iterators (parser);
20370 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
20371 {
20372 if (iterators)
20373 pop_scope ();
20374 parens.skip_until_found_close (parser);
20375 return list;
20376 }
20377 }
20378 }
20379 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_AFFINITY,
20380 list);
20381 if (iterators)
20382 {
20383 tree block = pop_scope ();
20384 if (iterators != error_mark_node)
20385 {
20386 TREE_VEC_ELT (iterators, 5) = block;
20387 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20388 OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
20389 OMP_CLAUSE_DECL (c));
20390 }
20391 }
20392
20393 parens.skip_until_found_close (parser);
20394 return nl;
20395}
20396
20397
20398/* OpenMP 4.0:
20399 depend ( depend-kind: variable-list )
20400
20401 depend-kind:
20402 in | out | inout
20403
20404 OpenMP 4.5:
20405 depend ( source )
20406
20407 depend ( sink : vec )
20408
20409 OpenMP 5.0:
20410 depend ( depend-modifier , depend-kind: variable-list )
20411
20412 depend-kind:
20413 in | out | inout | mutexinoutset | depobj | inoutset
20414
20415 depend-modifier:
20416 iterator ( iterators-definition ) */
20417
20418static tree
20419c_parser_omp_clause_depend (c_parser *parser, tree list, location_t here)
20420{
20421 location_t clause_loc = c_parser_peek_token (parser)->location;
20422 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
20423 enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
20424 tree nl, c, iterators = NULL_TREE;
20425
20426 matching_parens parens;
20427 if (!parens.require_open (parser))
20428 return list;
20429
20430 do
20431 {
20432 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
20433 goto invalid_kind;
20434
20435 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20436 if (strcmp (s1: "iterator", s2: p) == 0 && iterators == NULL_TREE)
20437 {
20438 iterators = c_parser_omp_iterators (parser);
20439 c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>");
20440 continue;
20441 }
20442 if (strcmp (s1: "in", s2: p) == 0)
20443 kind = OMP_CLAUSE_DEPEND_IN;
20444 else if (strcmp (s1: "inout", s2: p) == 0)
20445 kind = OMP_CLAUSE_DEPEND_INOUT;
20446 else if (strcmp (s1: "inoutset", s2: p) == 0)
20447 kind = OMP_CLAUSE_DEPEND_INOUTSET;
20448 else if (strcmp (s1: "mutexinoutset", s2: p) == 0)
20449 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
20450 else if (strcmp (s1: "out", s2: p) == 0)
20451 kind = OMP_CLAUSE_DEPEND_OUT;
20452 else if (strcmp (s1: "depobj", s2: p) == 0)
20453 kind = OMP_CLAUSE_DEPEND_DEPOBJ;
20454 else if (strcmp (s1: "sink", s2: p) == 0)
20455 {
20456 gcc_rich_location richloc (clause_loc);
20457 richloc.add_fixit_replace (where: here, new_content: "doacross");
20458 warning_at (&richloc, OPT_Wdeprecated_openmp,
20459 "%<sink%> modifier with %<depend%> clause deprecated "
20460 "since OpenMP 5.2, use with %<doacross%>");
20461 dkind = OMP_CLAUSE_DOACROSS_SINK;
20462 }
20463 else if (strcmp (s1: "source", s2: p) == 0)
20464 {
20465 gcc_rich_location richloc (clause_loc);
20466 richloc.add_fixit_replace (where: here, new_content: "doacross");
20467 warning_at (&richloc, OPT_Wdeprecated_openmp,
20468 "%<source%> modifier with %<depend%> clause deprecated "
20469 "since OpenMP 5.2, use with %<doacross%>");
20470 dkind = OMP_CLAUSE_DOACROSS_SOURCE;
20471 }
20472 else
20473 goto invalid_kind;
20474 break;
20475 }
20476 while (1);
20477
20478 c_parser_consume_token (parser);
20479
20480 if (iterators
20481 && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
20482 || dkind == OMP_CLAUSE_DOACROSS_SINK))
20483 {
20484 pop_scope ();
20485 error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
20486 dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
20487 iterators = NULL_TREE;
20488 }
20489
20490 if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
20491 {
20492 c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20493 OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
20494 OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
20495 OMP_CLAUSE_DECL (c) = NULL_TREE;
20496 OMP_CLAUSE_CHAIN (c) = list;
20497 parens.skip_until_found_close (parser);
20498 return c;
20499 }
20500
20501 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
20502 goto resync_fail;
20503
20504 if (dkind == OMP_CLAUSE_DOACROSS_SINK)
20505 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: true);
20506 else
20507 {
20508 nl = c_parser_omp_variable_list (parser, clause_loc,
20509 kind: OMP_CLAUSE_DEPEND, list);
20510
20511 if (iterators)
20512 {
20513 tree block = pop_scope ();
20514 if (iterators == error_mark_node)
20515 iterators = NULL_TREE;
20516 else
20517 TREE_VEC_ELT (iterators, 5) = block;
20518 }
20519
20520 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20521 {
20522 OMP_CLAUSE_DEPEND_KIND (c) = kind;
20523 if (iterators)
20524 OMP_CLAUSE_DECL (c)
20525 = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
20526 }
20527 }
20528
20529 parens.skip_until_found_close (parser);
20530 return nl;
20531
20532 invalid_kind:
20533 c_parser_error (parser, gmsgid: "invalid depend kind");
20534 resync_fail:
20535 parens.skip_until_found_close (parser);
20536 if (iterators)
20537 pop_scope ();
20538 return list;
20539}
20540
20541/* OpenMP 5.2:
20542 doacross ( source : )
20543 doacross ( source : omp_cur_iteration )
20544
20545 doacross ( sink : vec )
20546 doacross ( sink : omp_cur_iteration - logical_iteration ) */
20547
20548static tree
20549c_parser_omp_clause_doacross (c_parser *parser, tree list)
20550{
20551 location_t clause_loc = c_parser_peek_token (parser)->location;
20552 enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
20553 tree nl;
20554 const char *p;
20555
20556 matching_parens parens;
20557 if (!parens.require_open (parser))
20558 return list;
20559
20560 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
20561 goto invalid_kind;
20562
20563 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20564 if (strcmp (s1: "sink", s2: p) == 0)
20565 kind = OMP_CLAUSE_DOACROSS_SINK;
20566 else if (strcmp (s1: "source", s2: p) == 0)
20567 kind = OMP_CLAUSE_DOACROSS_SOURCE;
20568 else
20569 goto invalid_kind;
20570
20571 c_parser_consume_token (parser);
20572
20573 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
20574 goto resync_fail;
20575
20576 if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
20577 {
20578 if (c_parser_next_token_is (parser, type: CPP_NAME)
20579 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
20580 s2: "omp_cur_iteration") == 0)
20581 c_parser_consume_token (parser);
20582 nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20583 OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
20584 OMP_CLAUSE_DECL (nl) = NULL_TREE;
20585 OMP_CLAUSE_CHAIN (nl) = list;
20586 }
20587 else
20588 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: false);
20589
20590 parens.skip_until_found_close (parser);
20591 return nl;
20592
20593 invalid_kind:
20594 c_parser_error (parser, gmsgid: "invalid doacross kind");
20595 resync_fail:
20596 parens.skip_until_found_close (parser);
20597 return list;
20598}
20599
20600/* OpenMP 6.1:
20601 dyn_groupprivate ( [fallback-modifier : ] integer-expression )
20602
20603 fallback-modifier
20604 fallback( abort | default_mem | null ) */
20605
20606static tree
20607c_parser_omp_clause_dyn_groupprivate (c_parser *parser, tree list)
20608{
20609 location_t clause_loc = c_parser_peek_token (parser)->location;
20610 matching_parens parens;
20611 if (!parens.require_open (parser))
20612 return list;
20613
20614 enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
20615
20616 unsigned n = 3;
20617 if (c_parser_next_token_is (parser, type: CPP_NAME)
20618 && (c_parser_peek_2nd_token (parser)->type == CPP_COLON
20619 || (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
20620 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
20621 && (c_parser_peek_nth_token_raw (parser, n)->type
20622 == CPP_CLOSE_PAREN)
20623 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
20624 == CPP_COLON))))
20625 {
20626 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20627 if (strcmp (s1: p, s2: "fallback") != 0)
20628 {
20629 c_parser_error (parser, gmsgid: "expected %<fallback%> modifier");
20630 return list;
20631 }
20632 c_parser_consume_token (parser);
20633 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
20634 return list;
20635 p = "";
20636 if (c_parser_next_token_is (parser, type: CPP_NAME))
20637 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20638 if (strcmp (s1: p, s2: "abort") == 0)
20639 kind = OMP_CLAUSE_FALLBACK_ABORT;
20640 else if (strcmp (s1: p, s2: "default_mem") == 0)
20641 kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
20642 else if (strcmp (s1: p, s2: "null") == 0)
20643 kind = OMP_CLAUSE_FALLBACK_NULL;
20644 else
20645 {
20646 c_parser_error (parser, gmsgid: "expected %<abort%>, %<default_mem%>, or "
20647 "%<null%> as fallback mode");
20648 return list;
20649 }
20650 c_parser_consume_token (parser);
20651 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
20652 return list;
20653 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
20654 return list;
20655 }
20656 location_t expr_loc = c_parser_peek_token (parser)->location;
20657 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20658 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20659 tree size = c_fully_fold (expr.value, false, NULL);
20660 parens.skip_until_found_close (parser);
20661
20662 if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
20663 {
20664 error_at (expr_loc, "expected integer expression");
20665 return list;
20666 }
20667
20668 /* Attempt to statically determine when the number is negative. */
20669 tree c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, size,
20670 build_int_cst (TREE_TYPE (size), 0));
20671 protected_set_expr_location (c, expr_loc);
20672 if (c == boolean_true_node)
20673 {
20674 warning_at (expr_loc, OPT_Wopenmp,
20675 "%<dyn_groupprivate%> value must be non-negative");
20676 size = integer_zero_node;
20677 }
20678 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DYN_GROUPPRIVATE,
20679 name: "dyn_groupprivate");
20680
20681 c = build_omp_clause (clause_loc, OMP_CLAUSE_DYN_GROUPPRIVATE);
20682 OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
20683 OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
20684 OMP_CLAUSE_CHAIN (c) = list;
20685 list = c;
20686
20687 return list;
20688}
20689
20690/* OpenMP 4.0:
20691 map ( map-kind: variable-list )
20692 map ( variable-list )
20693
20694 map-kind:
20695 alloc | to | from | tofrom
20696
20697 OpenMP 4.5:
20698 map-kind:
20699 alloc | to | from | tofrom | release | delete
20700
20701 map ( always [,] map-kind: variable-list )
20702
20703 OpenMP 5.0:
20704 map ( [map-type-modifier[,] ...] map-kind: variable-list )
20705
20706 map-type-modifier:
20707 always | close | present | iterator (iterators-definition) */
20708
20709static tree
20710c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
20711{
20712 location_t clause_loc = c_parser_peek_token (parser)->location;
20713 tree nl, c;
20714 enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
20715
20716 matching_parens parens;
20717 if (!parens.require_open (parser))
20718 return list;
20719
20720 int pos = 1;
20721 int map_kind_pos = 0;
20722 int iterator_length = 0;
20723 for (;;)
20724 {
20725 c_token *tok = c_parser_peek_nth_token_raw (parser, n: pos);
20726 if (tok->type != CPP_NAME)
20727 break;
20728
20729 const char *p = IDENTIFIER_POINTER (tok->value);
20730 c_token *next_tok = c_parser_peek_nth_token_raw (parser, n: pos + 1);
20731 if (strcmp (s1: p, s2: "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
20732 {
20733 unsigned n = pos + 2;
20734 if (c_parser_check_balanced_raw_token_sequence (parser, n: &n)
20735 && c_parser_peek_nth_token_raw (parser, n)->type
20736 == CPP_CLOSE_PAREN)
20737 {
20738 iterator_length = n - pos + 1;
20739 pos = n;
20740 next_tok = c_parser_peek_nth_token_raw (parser, n: pos + 1);
20741 }
20742 }
20743
20744 if (next_tok->type == CPP_COLON)
20745 {
20746 map_kind_pos = pos;
20747 break;
20748 }
20749
20750 if (next_tok->type == CPP_COMMA)
20751 pos++;
20752 else if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type
20753 == CPP_OPEN_PAREN)
20754 {
20755 unsigned int npos = pos + 2;
20756 if (c_parser_check_balanced_raw_token_sequence (parser, n: &npos)
20757 && (c_parser_peek_nth_token_raw (parser, n: npos)->type
20758 == CPP_CLOSE_PAREN)
20759 && (c_parser_peek_nth_token_raw (parser, n: npos + 1)->type
20760 == CPP_COMMA))
20761 pos = npos + 1;
20762 }
20763
20764 pos++;
20765 }
20766
20767 int always_modifier = 0;
20768 int close_modifier = 0;
20769 int present_modifier = 0;
20770 int mapper_modifier = 0;
20771 int num_commas = 0;
20772 int num_identifiers = 0;
20773 tree mapper_name = NULL_TREE;
20774 tree iterators = NULL_TREE;
20775 for (int pos = 1; pos < map_kind_pos; ++pos)
20776 {
20777 c_token *tok = c_parser_peek_token (parser);
20778
20779 if (tok->type == CPP_COMMA)
20780 {
20781 ++num_commas;
20782 if (num_commas > num_identifiers)
20783 c_parser_error (parser, gmsgid: "illegal comma");
20784 c_parser_consume_token (parser);
20785 continue;
20786 }
20787
20788 const char *p = IDENTIFIER_POINTER (tok->value);
20789 if (strcmp (s1: "always", s2: p) == 0)
20790 {
20791 if (always_modifier)
20792 {
20793 c_parser_error (parser, gmsgid: "too many %<always%> modifiers");
20794 parens.skip_until_found_close (parser);
20795 return list;
20796 }
20797 always_modifier++;
20798 c_parser_consume_token (parser);
20799 }
20800 else if (strcmp (s1: "close", s2: p) == 0)
20801 {
20802 if (close_modifier)
20803 {
20804 c_parser_error (parser, gmsgid: "too many %<close%> modifiers");
20805 parens.skip_until_found_close (parser);
20806 return list;
20807 }
20808 close_modifier++;
20809 c_parser_consume_token (parser);
20810 }
20811 else if (strcmp (s1: "iterator", s2: p) == 0)
20812 {
20813 if (iterators)
20814 {
20815 c_parser_error (parser, gmsgid: "too many %<iterator%> modifiers");
20816 parens.skip_until_found_close (parser);
20817 return list;
20818 }
20819 iterators = c_parser_omp_iterators (parser);
20820 pos += iterator_length - 1;
20821 }
20822 else if (strcmp (s1: "mapper", s2: p) == 0)
20823 {
20824 c_parser_consume_token (parser);
20825
20826 matching_parens mparens;
20827 if (mparens.require_open (parser))
20828 {
20829 if (mapper_modifier)
20830 {
20831 c_parser_error (parser, gmsgid: "too many %<mapper%> modifiers");
20832 /* Assume it's a well-formed mapper modifier, even if it
20833 seems to be in the wrong place. */
20834 c_parser_consume_token (parser);
20835 mparens.require_close (parser);
20836 parens.skip_until_found_close (parser);
20837 return list;
20838 }
20839
20840 tok = c_parser_peek_token (parser);
20841
20842 switch (tok->type)
20843 {
20844 case CPP_NAME:
20845 {
20846 mapper_name = tok->value;
20847 c_parser_consume_token (parser);
20848 if (declare_mapper_p)
20849 {
20850 error_at (tok->location,
20851 "in %<declare mapper%> directives, parameter "
20852 "to %<mapper%> modifier must be %<default%>");
20853 }
20854 }
20855 break;
20856
20857 case CPP_KEYWORD:
20858 if (tok->keyword == RID_DEFAULT)
20859 {
20860 c_parser_consume_token (parser);
20861 break;
20862 }
20863 /* Fallthrough. */
20864
20865 default:
20866 error_at (tok->location,
20867 "expected identifier or %<default%>");
20868 return list;
20869 }
20870
20871 if (!mparens.require_close (parser))
20872 {
20873 parens.skip_until_found_close (parser);
20874 return list;
20875 }
20876
20877 mapper_modifier++;
20878 pos += 3;
20879 }
20880 }
20881 else if (strcmp (s1: "present", s2: p) == 0)
20882 {
20883 if (present_modifier)
20884 {
20885 c_parser_error (parser, gmsgid: "too many %<present%> modifiers");
20886 parens.skip_until_found_close (parser);
20887 return list;
20888 }
20889 present_modifier++;
20890 c_parser_consume_token (parser);
20891 }
20892 else
20893 {
20894 c_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other "
20895 "than %<always%>, %<close%>, %<iterator%>, "
20896 "%<mapper%> or %<present%>");
20897 parens.skip_until_found_close (parser);
20898 return list;
20899 }
20900 ++num_identifiers;
20901 if (num_identifiers - 1 > num_commas)
20902 {
20903 gcc_rich_location richloc (clause_loc);
20904 richloc.add_fixit_insert_before (where: tok->location, new_content: ",");
20905 warning_at (&richloc, OPT_Wdeprecated_openmp,
20906 "%<map%> clause modifiers without comma separation is "
20907 "deprecated since OpenMP 5.2");
20908 }
20909 num_commas = num_identifiers - 1;
20910 }
20911
20912 if (c_parser_next_token_is (parser, type: CPP_NAME)
20913 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20914 {
20915 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20916 int always_present_modifier = always_modifier && present_modifier;
20917
20918 if (strcmp (s1: "alloc", s2: p) == 0)
20919 kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
20920 else if (strcmp (s1: "to", s2: p) == 0)
20921 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
20922 : present_modifier ? GOMP_MAP_PRESENT_TO
20923 : always_modifier ? GOMP_MAP_ALWAYS_TO
20924 : GOMP_MAP_TO);
20925 else if (strcmp (s1: "from", s2: p) == 0)
20926 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
20927 : present_modifier ? GOMP_MAP_PRESENT_FROM
20928 : always_modifier ? GOMP_MAP_ALWAYS_FROM
20929 : GOMP_MAP_FROM);
20930 else if (strcmp (s1: "tofrom", s2: p) == 0)
20931 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
20932 : present_modifier ? GOMP_MAP_PRESENT_TOFROM
20933 : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
20934 : GOMP_MAP_TOFROM);
20935 else if (strcmp (s1: "release", s2: p) == 0)
20936 kind = GOMP_MAP_RELEASE;
20937 else if (strcmp (s1: "delete", s2: p) == 0)
20938 kind = GOMP_MAP_DELETE;
20939 else
20940 {
20941 c_parser_error (parser, gmsgid: "invalid map kind");
20942 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
20943 msgid: "expected %<)%>");
20944 return list;
20945 }
20946 c_parser_consume_token (parser);
20947 c_parser_consume_token (parser);
20948 }
20949
20950 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_MAP, list,
20951 map_lvalue: true);
20952
20953 tree last_new = NULL_TREE;
20954
20955 if (iterators)
20956 {
20957 tree block = pop_scope ();
20958 if (iterators == error_mark_node)
20959 iterators = NULL_TREE;
20960 else
20961 TREE_VEC_ELT (iterators, 5) = block;
20962 }
20963
20964 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20965 {
20966 OMP_CLAUSE_SET_MAP_KIND (c, kind);
20967 OMP_CLAUSE_ITERATORS (c) = iterators;
20968 last_new = c;
20969 }
20970
20971 if (mapper_name)
20972 {
20973 tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20974 OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
20975 OMP_CLAUSE_DECL (name) = mapper_name;
20976 OMP_CLAUSE_CHAIN (name) = nl;
20977 nl = name;
20978
20979 gcc_assert (last_new);
20980
20981 name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20982 OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
20983 OMP_CLAUSE_DECL (name) = null_pointer_node;
20984 OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
20985 OMP_CLAUSE_CHAIN (last_new) = name;
20986 }
20987
20988 parens.skip_until_found_close (parser);
20989 return nl;
20990}
20991
20992/* OpenMP 4.0:
20993 device ( expression )
20994
20995 OpenMP 5.0:
20996 device ( [device-modifier :] integer-expression )
20997
20998 device-modifier:
20999 ancestor | device_num */
21000
21001static tree
21002c_parser_omp_clause_device (c_parser *parser, tree list)
21003{
21004 location_t clause_loc = c_parser_peek_token (parser)->location;
21005 location_t expr_loc;
21006 c_expr expr;
21007 tree c, t;
21008 bool ancestor = false;
21009
21010 matching_parens parens;
21011 if (!parens.require_open (parser))
21012 return list;
21013
21014 if (c_parser_next_token_is (parser, type: CPP_NAME)
21015 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
21016 {
21017 c_token *tok = c_parser_peek_token (parser);
21018 const char *p = IDENTIFIER_POINTER (tok->value);
21019 if (strcmp (s1: "ancestor", s2: p) == 0)
21020 {
21021 /* A requires directive with the reverse_offload clause must be
21022 specified. */
21023 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
21024 {
21025 error_at (tok->location, "%<ancestor%> device modifier not "
21026 "preceded by %<requires%> directive "
21027 "with %<reverse_offload%> clause");
21028 parens.skip_until_found_close (parser);
21029 return list;
21030 }
21031 ancestor = true;
21032 }
21033 else if (strcmp (s1: "device_num", s2: p) == 0)
21034 ;
21035 else
21036 {
21037 error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
21038 parens.skip_until_found_close (parser);
21039 return list;
21040 }
21041 c_parser_consume_token (parser);
21042 c_parser_consume_token (parser);
21043 }
21044
21045 expr_loc = c_parser_peek_token (parser)->location;
21046 expr = c_parser_expr_no_commas (parser, NULL);
21047 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
21048 t = expr.value;
21049 t = c_fully_fold (t, false, NULL);
21050
21051 parens.skip_until_found_close (parser);
21052
21053 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
21054 {
21055 c_parser_error (parser, gmsgid: "expected integer expression");
21056 return list;
21057 }
21058 if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
21059 {
21060 error_at (expr_loc, "the %<device%> clause expression must evaluate to "
21061 "%<1%>");
21062 return list;
21063 }
21064
21065 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, name: "device");
21066
21067 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
21068
21069 OMP_CLAUSE_DEVICE_ID (c) = t;
21070 OMP_CLAUSE_CHAIN (c) = list;
21071 OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
21072
21073 list = c;
21074 return list;
21075}
21076
21077/* OpenMP 4.0:
21078 dist_schedule ( static )
21079 dist_schedule ( static , expression ) */
21080
21081static tree
21082c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
21083{
21084 tree c, t = NULL_TREE;
21085 location_t loc = c_parser_peek_token (parser)->location;
21086
21087 matching_parens parens;
21088 if (!parens.require_open (parser))
21089 return list;
21090
21091 if (!c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
21092 {
21093 c_parser_error (parser, gmsgid: "invalid dist_schedule kind");
21094 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
21095 msgid: "expected %<)%>");
21096 return list;
21097 }
21098
21099 c_parser_consume_token (parser);
21100 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21101 {
21102 c_parser_consume_token (parser);
21103
21104 location_t expr_loc = c_parser_peek_token (parser)->location;
21105 c_expr expr = c_parser_expr_no_commas (parser, NULL);
21106 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
21107 t = expr.value;
21108 t = c_fully_fold (t, false, NULL);
21109 parens.skip_until_found_close (parser);
21110 }
21111 else
21112 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
21113 msgid: "expected %<,%> or %<)%>");
21114
21115 /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
21116 "dist_schedule"); */
21117 if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE))
21118 warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
21119 if (t == error_mark_node)
21120 return list;
21121
21122 c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
21123 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
21124 OMP_CLAUSE_CHAIN (c) = list;
21125 return c;
21126}
21127
21128/* OpenMP 4.0:
21129 proc_bind ( proc-bind-kind )
21130
21131 proc-bind-kind:
21132 primary | master | close | spread
21133 where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
21134
21135static tree
21136c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
21137{
21138 location_t clause_loc = c_parser_peek_token (parser)->location;
21139 enum omp_clause_proc_bind_kind kind;
21140 tree c;
21141
21142 matching_parens parens;
21143 if (!parens.require_open (parser))
21144 return list;
21145
21146 if (c_parser_next_token_is (parser, type: CPP_NAME))
21147 {
21148 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21149 if (strcmp (s1: "primary", s2: p) == 0)
21150 kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
21151 else if (strcmp (s1: "master", s2: p) == 0)
21152 {
21153 gcc_rich_location richloc (clause_loc);
21154 richloc.add_fixit_replace (where: c_parser_peek_token (parser)->location,
21155 new_content: "primary");
21156 warning_at (&richloc, OPT_Wdeprecated_openmp,
21157 "%<master%> affinity deprecated since OpenMP 5.1, "
21158 "use %<primary%>");
21159 kind = OMP_CLAUSE_PROC_BIND_MASTER;
21160 }
21161 else if (strcmp (s1: "close", s2: p) == 0)
21162 kind = OMP_CLAUSE_PROC_BIND_CLOSE;
21163 else if (strcmp (s1: "spread", s2: p) == 0)
21164 kind = OMP_CLAUSE_PROC_BIND_SPREAD;
21165 else
21166 goto invalid_kind;
21167 }
21168 else
21169 goto invalid_kind;
21170
21171 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind");
21172 c_parser_consume_token (parser);
21173 parens.skip_until_found_close (parser);
21174 c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
21175 OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
21176 OMP_CLAUSE_CHAIN (c) = list;
21177 return c;
21178
21179 invalid_kind:
21180 c_parser_error (parser, gmsgid: "invalid proc_bind kind");
21181 parens.skip_until_found_close (parser);
21182 return list;
21183}
21184
21185/* OpenMP 5.0:
21186 device_type ( host | nohost | any ) */
21187
21188static tree
21189c_parser_omp_clause_device_type (c_parser *parser, tree list)
21190{
21191 location_t clause_loc = c_parser_peek_token (parser)->location;
21192 enum omp_clause_device_type_kind kind;
21193 tree c;
21194
21195 matching_parens parens;
21196 if (!parens.require_open (parser))
21197 return list;
21198
21199 if (c_parser_next_token_is (parser, type: CPP_NAME))
21200 {
21201 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21202 if (strcmp (s1: "host", s2: p) == 0)
21203 kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
21204 else if (strcmp (s1: "nohost", s2: p) == 0)
21205 kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
21206 else if (strcmp (s1: "any", s2: p) == 0)
21207 kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
21208 else
21209 goto invalid_kind;
21210 }
21211 else
21212 goto invalid_kind;
21213
21214 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE,
21215 name: "device_type");
21216 c_parser_consume_token (parser);
21217 parens.skip_until_found_close (parser);
21218 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
21219 OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
21220 OMP_CLAUSE_CHAIN (c) = list;
21221 return c;
21222
21223 invalid_kind:
21224 c_parser_error (parser, gmsgid: "expected %<host%>, %<nohost%> or %<any%>");
21225 parens.skip_until_found_close (parser);
21226 return list;
21227}
21228
21229/* OpenMP 4.0:
21230 from ( variable-list )
21231 to ( variable-list )
21232
21233 OpenMP 5.1:
21234 from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
21235 to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
21236
21237 motion-modifier:
21238 present | iterator (iterators-definition) */
21239
21240static tree
21241c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
21242 tree list)
21243{
21244 location_t loc = c_parser_peek_token (parser)->location;
21245 matching_parens parens;
21246 if (!parens.require_open (parser))
21247 return list;
21248
21249 int pos = 1, colon_pos = 0;
21250 int iterator_length = 0;
21251
21252 while (c_parser_peek_nth_token_raw (parser, n: pos)->type == CPP_NAME)
21253 {
21254 const char *identifier =
21255 IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
21256 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type
21257 == CPP_OPEN_PAREN)
21258 {
21259 unsigned int npos = pos + 2;
21260 if (c_parser_check_balanced_raw_token_sequence (parser, n: &npos)
21261 && (c_parser_peek_nth_token_raw (parser, n: npos)->type
21262 == CPP_CLOSE_PAREN))
21263 {
21264 if (strcmp (s1: identifier, s2: "iterator") == 0)
21265 iterator_length = npos - pos + 1;
21266 pos = npos;
21267 }
21268 }
21269 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COMMA)
21270 pos += 2;
21271 else
21272 pos++;
21273 if (c_parser_peek_nth_token_raw (parser, n: pos)->type == CPP_COLON)
21274 {
21275 colon_pos = pos;
21276 break;
21277 }
21278 }
21279
21280 bool present = false;
21281 tree iterators = NULL_TREE;
21282
21283 for (int pos = 1; pos < colon_pos; ++pos)
21284 {
21285 c_token *token = c_parser_peek_token (parser);
21286 if (token->type == CPP_COMMA)
21287 {
21288 c_parser_consume_token (parser);
21289 continue;
21290 }
21291 const char *p = IDENTIFIER_POINTER (token->value);
21292 if (strcmp (s1: "present", s2: p) == 0)
21293 {
21294 if (present)
21295 {
21296 c_parser_error (parser, gmsgid: "too many %<present%> modifiers");
21297 parens.skip_until_found_close (parser);
21298 return list;
21299 }
21300 present = true;
21301 c_parser_consume_token (parser);
21302 }
21303 else if (strcmp (s1: "iterator", s2: p) == 0)
21304 {
21305 if (iterators)
21306 {
21307 c_parser_error (parser, gmsgid: "too many %<iterator%> modifiers");
21308 parens.skip_until_found_close (parser);
21309 return list;
21310 }
21311 iterators = c_parser_omp_iterators (parser);
21312 pos += iterator_length - 1;
21313 }
21314 else
21315 {
21316 error_at (token->location,
21317 "%qs clause with modifier other than %<iterator%> or "
21318 "%<present%>",
21319 kind == OMP_CLAUSE_TO ? "to" : "from");
21320 parens.skip_until_found_close (parser);
21321 return list;
21322 }
21323 }
21324
21325 if (colon_pos)
21326 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
21327
21328 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list);
21329 parens.skip_until_found_close (parser);
21330
21331 if (present)
21332 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21333 OMP_CLAUSE_MOTION_PRESENT (c) = 1;
21334
21335 if (iterators)
21336 {
21337 tree block = pop_scope ();
21338 if (iterators == error_mark_node)
21339 iterators = NULL_TREE;
21340 else
21341 TREE_VEC_ELT (iterators, 5) = block;
21342 }
21343
21344 if (iterators)
21345 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21346 OMP_CLAUSE_ITERATORS (c) = iterators;
21347
21348 return nl;
21349}
21350
21351/* OpenMP 4.0:
21352 uniform ( variable-list ) */
21353
21354static tree
21355c_parser_omp_clause_uniform (c_parser *parser, tree list)
21356{
21357 /* The clauses location. */
21358 location_t loc = c_parser_peek_token (parser)->location;
21359
21360 matching_parens parens;
21361 if (parens.require_open (parser))
21362 {
21363 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_UNIFORM,
21364 list);
21365 parens.skip_until_found_close (parser);
21366 }
21367 return list;
21368}
21369
21370/* OpenMP 5.1
21371 full */
21372
21373static tree
21374c_parser_omp_clause_full (c_parser *parser, tree list)
21375{
21376 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FULL, name: "full");
21377
21378 location_t loc = c_parser_peek_token (parser)->location;
21379 tree c = build_omp_clause (loc, OMP_CLAUSE_FULL);
21380 OMP_CLAUSE_CHAIN (c) = list;
21381 return c;
21382}
21383
21384/* OpenMP 5.1
21385 partial ( constant-expression ) */
21386
21387static tree
21388c_parser_omp_clause_partial (c_parser *parser, tree list)
21389{
21390 tree num = NULL_TREE;
21391 location_t loc = c_parser_peek_token (parser)->location;
21392
21393 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PARTIAL, name: "partial");
21394
21395 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
21396 {
21397 matching_parens parens;
21398 parens.consume_open (parser);
21399 num = c_parser_expr_no_commas (parser, NULL).value;
21400 parens.skip_until_found_close (parser);
21401
21402 if (num == error_mark_node)
21403 return list;
21404
21405 mark_exp_read (num);
21406 num = c_fully_fold (num, false, NULL);
21407 HOST_WIDE_INT n;
21408 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
21409 || !tree_fits_shwi_p (num)
21410 || (n = tree_to_shwi (num)) <= 0
21411 || (int) n != n)
21412 {
21413 error_at (loc, "%<partial%> argument needs positive constant "
21414 "integer expression");
21415 return list;
21416 }
21417 }
21418
21419 tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL);
21420 OMP_CLAUSE_PARTIAL_EXPR (c) = num;
21421 OMP_CLAUSE_CHAIN (c) = list;
21422 return c;
21423}
21424
21425/* OpenMP 5.1
21426 novariants ( scalar-expression ) */
21427
21428static tree
21429c_parser_omp_clause_novariants (c_parser *parser, tree list)
21430{
21431 matching_parens parens;
21432 if (!parens.require_open (parser))
21433 return list;
21434
21435 location_t loc = c_parser_peek_token (parser)->location;
21436 c_expr expr = c_parser_expr_no_commas (parser, NULL);
21437 tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
21438 t = c_objc_common_truthvalue_conversion (loc, t);
21439 t = c_fully_fold (t, false, NULL);
21440 parens.skip_until_found_close (parser);
21441
21442 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOVARIANTS, name: "novariants");
21443
21444 tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
21445 OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
21446 OMP_CLAUSE_CHAIN (c) = list;
21447 list = c;
21448
21449 return list;
21450}
21451
21452/* OpenMP 5.1
21453 nocontext ( scalar-expression ) */
21454
21455static tree
21456c_parser_omp_clause_nocontext (c_parser *parser, tree list)
21457{
21458 matching_parens parens;
21459 if (!parens.require_open (parser))
21460 return list;
21461
21462 location_t loc = c_parser_peek_token (parser)->location;
21463 c_expr expr = c_parser_expr_no_commas (parser, NULL);
21464 tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
21465 t = c_objc_common_truthvalue_conversion (loc, t);
21466 t = c_fully_fold (t, false, NULL);
21467 parens.skip_until_found_close (parser);
21468
21469 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOCONTEXT, name: "nocontext");
21470
21471 tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
21472 OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
21473 OMP_CLAUSE_CHAIN (c) = list;
21474 list = c;
21475
21476 return list;
21477}
21478
21479/* OpenMP 5.0:
21480 detach ( event-handle ) */
21481
21482static tree
21483c_parser_omp_clause_detach (c_parser *parser, tree list)
21484{
21485 matching_parens parens;
21486 location_t clause_loc = c_parser_peek_token (parser)->location;
21487
21488 if (!parens.require_open (parser))
21489 return list;
21490
21491 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
21492 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
21493 {
21494 c_parser_error (parser, gmsgid: "expected identifier");
21495 parens.skip_until_found_close (parser);
21496 return list;
21497 }
21498
21499 tree t = lookup_name (c_parser_peek_token (parser)->value);
21500 if (t == NULL_TREE)
21501 {
21502 undeclared_variable (c_parser_peek_token (parser)->location,
21503 c_parser_peek_token (parser)->value);
21504 parens.skip_until_found_close (parser);
21505 return list;
21506 }
21507 c_parser_consume_token (parser);
21508
21509 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
21510 if (!INTEGRAL_TYPE_P (type)
21511 || TREE_CODE (type) != ENUMERAL_TYPE
21512 || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
21513 {
21514 error_at (clause_loc, "%<detach%> clause event handle "
21515 "has type %qT rather than "
21516 "%<omp_event_handle_t%>",
21517 type);
21518 parens.skip_until_found_close (parser);
21519 return list;
21520 }
21521
21522 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
21523 OMP_CLAUSE_DECL (u) = t;
21524 OMP_CLAUSE_CHAIN (u) = list;
21525 parens.skip_until_found_close (parser);
21526 return u;
21527}
21528
21529/* OpenMP 5.0:
21530 destroy ( variable-list ) */
21531
21532static tree
21533c_parser_omp_clause_destroy (c_parser *parser, tree list)
21534{
21535 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_DESTROY, list);
21536 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21537 TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21538 return nl;
21539}
21540
21541/* OpenMP 5.1:
21542 prefer_type ( const-int-expr-or-string-literal-list )
21543
21544 OpenMP 6.0:
21545 prefer_type ( { preference-selector-list }, { ... } )
21546
21547 with preference-selector being:
21548 fr ( identifier-or-string-literal-list )
21549 attr ( string-list )
21550
21551 Data format:
21552 For the foreign runtime identifiers, string values are converted to
21553 their integer value; unknown string or integer values are set to
21554 GOMP_INTEROP_IFR_KNOWN.
21555
21556 Each item (a) GOMP_INTEROP_IFR_SEPARATOR
21557 (b) for any 'fr', its integer value.
21558 Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
21559 (c) GOMP_INTEROP_IFR_SEPARATOR
21560 (d) list of \0-terminated non-empty strings for 'attr'
21561 (e) '\0'
21562 Tailing '\0'. */
21563
21564static tree
21565c_parser_omp_modifier_prefer_type (c_parser *parser)
21566{
21567 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
21568 return error_mark_node;
21569
21570 std::string str;
21571
21572 /* Old Format: const-int-expr-or-string-literal-list */
21573 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
21574 while (true)
21575 {
21576 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21577 if (c_parser_next_token_is (parser, type: CPP_STRING))
21578 {
21579 c_expr cval = c_parser_string_literal (parser, translate: false, wide_ok: false);
21580 if (cval.value == error_mark_node)
21581 return error_mark_node;
21582 if ((size_t) TREE_STRING_LENGTH (cval.value)
21583 != strlen (TREE_STRING_POINTER (cval.value)) + 1)
21584 {
21585 error_at (cval.get_location (), "string literal must "
21586 "not contain %<\\0%>");
21587 parser->error = true;
21588 return error_mark_node;
21589 }
21590
21591 char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (cval.value));
21592 if (c == GOMP_INTEROP_IFR_UNKNOWN)
21593 warning_at (cval.get_location (), OPT_Wopenmp,
21594 "unknown foreign runtime identifier %qs",
21595 TREE_STRING_POINTER (cval.value));
21596 str += c;
21597 }
21598 else
21599 {
21600 c_expr cval = c_parser_expr_no_commas (parser, NULL);
21601 tree value = c_fully_fold (cval.value, false, NULL);
21602 if (INTEGRAL_TYPE_P (TREE_TYPE (value))
21603 && TREE_CODE (value) != INTEGER_CST)
21604 value = convert_lvalue_to_rvalue (cval.get_start (), cval,
21605 false, true).value;
21606 if (TREE_CODE (value) != INTEGER_CST
21607 || !tree_fits_shwi_p (value))
21608 {
21609 c_parser_error (parser, gmsgid: "expected string literal or constant "
21610 "integer expression");
21611 return error_mark_node;
21612 }
21613 HOST_WIDE_INT n = tree_to_shwi (value);
21614 if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
21615 {
21616 warning_at (cval.get_location (), OPT_Wopenmp,
21617 "unknown foreign runtime identifier %qwd", n);
21618 n = GOMP_INTEROP_IFR_UNKNOWN;
21619 }
21620 str += (char) n;
21621 }
21622 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21623 str += '\0';
21624 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21625 {
21626 c_parser_consume_token (parser);
21627 continue;
21628 }
21629 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN,
21630 msgid: "expected %<,%> or %<)%>"))
21631 return error_mark_node;
21632 str += '\0';
21633 tree res = build_string (str.length (), str.data ());
21634 TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
21635 str.length ());
21636 return res;
21637 }
21638
21639 /* New format. */
21640 std::string str2;
21641 while (true)
21642 {
21643 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
21644 return error_mark_node;
21645 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21646 str2.clear ();
21647 bool has_fr = false;
21648 while (true)
21649 {
21650 c_token *tok = c_parser_peek_token (parser);
21651 if (tok->type != CPP_NAME
21652 || (strcmp(s1: "fr", IDENTIFIER_POINTER (tok->value)) != 0
21653 && strcmp(s1: "attr", IDENTIFIER_POINTER (tok->value)) != 0))
21654 {
21655 c_parser_error (parser, gmsgid: "expected %<fr%> or %<attr%> preference "
21656 "selector");
21657 return error_mark_node;
21658 }
21659 c_parser_consume_token (parser);
21660 bool is_fr = IDENTIFIER_POINTER (tok->value)[0] == 'f';
21661 if (is_fr && has_fr)
21662 {
21663 c_parser_error (parser, gmsgid: "duplicated %<fr%> preference selector");
21664 return error_mark_node;
21665 }
21666 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
21667 return error_mark_node;
21668 while (true)
21669 {
21670 if (c_parser_next_token_is (parser, type: CPP_STRING))
21671 {
21672 c_expr cval = c_parser_string_literal (parser, translate: false, wide_ok: false);
21673 tree value = cval.value;
21674 if (value == error_mark_node)
21675 return error_mark_node;
21676 if ((size_t) TREE_STRING_LENGTH (value)
21677 != strlen (TREE_STRING_POINTER (value)) + 1)
21678 {
21679 error_at (cval.get_location (), "string literal must "
21680 "not contain %<\\0%>");
21681 parser->error = true;
21682 return error_mark_node;
21683 }
21684 if (!is_fr)
21685 {
21686 if (!startswith (TREE_STRING_POINTER (value), prefix: "ompx_"))
21687 {
21688 error_at (cval.get_location (),
21689 "%<attr%> string literal must start with "
21690 "%<ompx_%>");
21691 parser->error = true;
21692 return error_mark_node;
21693 }
21694 if (strchr (TREE_STRING_POINTER (value), c: ','))
21695 {
21696 error_at (cval.get_location (),
21697 "%<attr%> string literal must not contain "
21698 "a comma");
21699 parser->error = true;
21700 return error_mark_node;
21701 }
21702 str2 += TREE_STRING_POINTER (value);
21703 str2 += '\0';
21704 }
21705 else
21706 {
21707 if (*TREE_STRING_POINTER (value) == '\0')
21708 {
21709 c_parser_error (parser, gmsgid: "non-empty string literal expected");
21710 return error_mark_node;
21711 }
21712 char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (value));
21713 if (c == GOMP_INTEROP_IFR_UNKNOWN)
21714 warning_at (cval.get_location (), OPT_Wopenmp,
21715 "unknown foreign runtime identifier %qs",
21716 TREE_STRING_POINTER (value));
21717 str += c;
21718 has_fr = true;
21719 }
21720 }
21721 else if (!is_fr)
21722 {
21723 c_parser_error (parser, gmsgid: "expected string literal");
21724 return error_mark_node;
21725 }
21726 else
21727 {
21728 c_expr cval = c_parser_expr_no_commas (parser, NULL);
21729 tree value = c_fully_fold (cval.value, false, NULL);
21730 if (INTEGRAL_TYPE_P (TREE_TYPE (value))
21731 && TREE_CODE (value) != INTEGER_CST)
21732 value = convert_lvalue_to_rvalue (cval.get_start (), cval,
21733 false, true).value;
21734
21735 if (TREE_CODE (value) != INTEGER_CST
21736 || !tree_fits_shwi_p (value))
21737 {
21738 c_parser_error (parser, gmsgid: "expected string literal or "
21739 "constant integer expression");
21740 return error_mark_node;
21741 }
21742 HOST_WIDE_INT n = tree_to_shwi (value);
21743 if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
21744 {
21745 warning_at (cval.get_location (), OPT_Wopenmp,
21746 "unknown foreign runtime identifier %qwd", n);
21747 n = GOMP_INTEROP_IFR_UNKNOWN;
21748 }
21749 str += (char) n;
21750 has_fr = true;
21751 }
21752 if (!is_fr
21753 && c_parser_next_token_is (parser, type: CPP_COMMA))
21754 {
21755 c_parser_consume_token (parser);
21756 continue;
21757 }
21758 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN,
21759 msgid: is_fr ? G_("expected %<)%>")
21760 : G_("expected %<)%> or %<,%>")))
21761 return error_mark_node;
21762 break;
21763 }
21764 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21765 {
21766 c_parser_consume_token (parser);
21767 continue;
21768 }
21769 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21770 break;
21771 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
21772 return error_mark_node;
21773 }
21774 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21775 str += str2;
21776 str += '\0';
21777 c_parser_consume_token (parser);
21778 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
21779 break;
21780 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<)%> or %<,%>"))
21781 return error_mark_node;
21782 }
21783 c_parser_consume_token (parser);
21784 str += '\0';
21785 tree res = build_string (str.length (), str.data ());
21786 TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
21787 str.length ());
21788 return res;
21789}
21790
21791/* OpenMP 5.1
21792 modifiers of the 'init' clause, used by the 'init' and the
21793 'append_args' clauses.
21794
21795 Modifiers:
21796 target
21797 targetsync
21798 prefer_type (preference-specification)
21799
21800 Returns 'false' if an error has been issued. */
21801
21802static bool
21803c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target,
21804 bool *targetsync, tree *prefer_type_tree)
21805{
21806 *target = false;
21807 *targetsync = false;
21808 *prefer_type_tree = NULL_TREE;
21809
21810 do
21811 {
21812 c_token *tok = c_parser_peek_token (parser);
21813 if (tok->type != CPP_NAME)
21814 goto fail;
21815 const char *p = IDENTIFIER_POINTER (tok->value);
21816 if (strcmp (s1: "targetsync", s2: p) == 0)
21817 {
21818 if (*targetsync)
21819 error_at (tok->location, "duplicate %<targetsync%> modifier");
21820 *targetsync = true;
21821 c_parser_consume_token (parser);
21822 }
21823 else if (strcmp (s1: "target", s2: p) == 0)
21824 {
21825 if (*target)
21826 error_at (tok->location, "duplicate %<target%> modifier");
21827 *target = true;
21828 c_parser_consume_token (parser);
21829 }
21830 else if (strcmp (s1: "prefer_type", s2: p) == 0)
21831 {
21832 if (*prefer_type_tree != NULL_TREE)
21833 error_at (tok->location, "duplicate %<prefer_type%> modifier");
21834 c_parser_consume_token (parser);
21835 *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser);
21836 if (*prefer_type_tree == error_mark_node)
21837 return false;
21838 }
21839 else
21840 goto fail;
21841 tok = c_parser_peek_token (parser);
21842 if (tok->type == CPP_COMMA)
21843 {
21844 c_parser_consume_token (parser);
21845 continue;
21846 }
21847 /* Unknown token - either done or an error; handle it in the caller. */
21848 return true;
21849 }
21850 while (true);
21851
21852fail:
21853 c_parser_error (parser,
21854 gmsgid: "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
21855 return false;
21856}
21857
21858/* OpenMP 5.1:
21859 init ( [init-modifier-list : ] variable-list )
21860
21861 Modifiers:
21862 target
21863 targetsync
21864 prefer_type (preference-specification) */
21865
21866static tree
21867c_parser_omp_clause_init (c_parser *parser, tree list)
21868{
21869 location_t loc = c_parser_peek_token (parser)->location;
21870
21871 matching_parens parens;
21872 if (!parens.require_open (parser))
21873 return list;
21874
21875 bool target = false;
21876 bool targetsync = false;
21877 tree prefer_type_tree = NULL_TREE;
21878
21879 if (!c_parser_omp_clause_init_modifiers (parser, target: &target, targetsync: &targetsync,
21880 prefer_type_tree: &prefer_type_tree)
21881 || !c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
21882 {
21883 if (prefer_type_tree != error_mark_node)
21884 parens.skip_until_found_close (parser);
21885 return list;
21886 }
21887
21888 if (!target && !targetsync)
21889 error_at (loc,
21890 "missing required %<target%> and/or %<targetsync%> modifier");
21891
21892 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_INIT, list,
21893 map_lvalue: false);
21894 parens.skip_until_found_close (parser);
21895
21896 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21897 {
21898 TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21899 if (target)
21900 OMP_CLAUSE_INIT_TARGET (c) = 1;
21901 if (targetsync)
21902 OMP_CLAUSE_INIT_TARGETSYNC (c) = 1;
21903 if (prefer_type_tree)
21904 OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree;
21905 }
21906 return nl;
21907}
21908
21909/* OpenMP 5.0:
21910 use ( variable-list ) */
21911
21912static tree
21913c_parser_omp_clause_use (c_parser *parser, tree list)
21914{
21915 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE, list);
21916}
21917
21918/* OpenMP 6.0:
21919 interop ( variable-list ) */
21920
21921static tree
21922c_parser_omp_clause_interop (c_parser *parser, tree list)
21923{
21924 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INTEROP, name: "interop");
21925 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_INTEROP, list);
21926 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21927 {
21928 TREE_USED (OMP_CLAUSE_DECL (c)) = 1;
21929 DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1;
21930 }
21931 return nl;
21932}
21933
21934/* Parse all OpenACC clauses. The set clauses allowed by the directive
21935 is a bitmask in MASK. Return the list of clauses found. */
21936
21937static tree
21938c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
21939 const char *where, bool finish_p = true,
21940 bool target_p = false)
21941{
21942 tree clauses = NULL;
21943 bool first = true;
21944
21945 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
21946 {
21947 location_t here;
21948 pragma_omp_clause c_kind;
21949 const char *c_name;
21950 tree prev = clauses;
21951
21952 if (!first && c_parser_next_token_is (parser, type: CPP_COMMA))
21953 c_parser_consume_token (parser);
21954
21955 here = c_parser_peek_token (parser)->location;
21956 c_kind = c_parser_omp_clause_name (parser);
21957
21958 switch (c_kind)
21959 {
21960 case PRAGMA_OACC_CLAUSE_ASYNC:
21961 clauses = c_parser_oacc_clause_async (parser, list: clauses);
21962 c_name = "async";
21963 break;
21964 case PRAGMA_OACC_CLAUSE_AUTO:
21965 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO,
21966 list: clauses);
21967 c_name = "auto";
21968 break;
21969 case PRAGMA_OACC_CLAUSE_ATTACH:
21970 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21971 c_name = "attach";
21972 break;
21973 case PRAGMA_OACC_CLAUSE_COLLAPSE:
21974 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
21975 c_name = "collapse";
21976 break;
21977 case PRAGMA_OACC_CLAUSE_COPY:
21978 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21979 c_name = "copy";
21980 break;
21981 case PRAGMA_OACC_CLAUSE_COPYIN:
21982 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21983 c_name = "copyin";
21984 break;
21985 case PRAGMA_OACC_CLAUSE_COPYOUT:
21986 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21987 c_name = "copyout";
21988 break;
21989 case PRAGMA_OACC_CLAUSE_CREATE:
21990 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21991 c_name = "create";
21992 break;
21993 case PRAGMA_OACC_CLAUSE_DELETE:
21994 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21995 c_name = "delete";
21996 break;
21997 case PRAGMA_OMP_CLAUSE_DEFAULT:
21998 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: true);
21999 c_name = "default";
22000 break;
22001 case PRAGMA_OACC_CLAUSE_DETACH:
22002 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22003 c_name = "detach";
22004 break;
22005 case PRAGMA_OACC_CLAUSE_DEVICE:
22006 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22007 c_name = "device";
22008 break;
22009 case PRAGMA_OACC_CLAUSE_DEVICEPTR:
22010 clauses = c_parser_oacc_data_clause_deviceptr (parser, list: clauses);
22011 c_name = "deviceptr";
22012 break;
22013 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
22014 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22015 c_name = "device_resident";
22016 break;
22017 case PRAGMA_OACC_CLAUSE_FINALIZE:
22018 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE,
22019 list: clauses);
22020 c_name = "finalize";
22021 break;
22022 case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
22023 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
22024 c_name = "firstprivate";
22025 break;
22026 case PRAGMA_OACC_CLAUSE_GANG:
22027 c_name = "gang";
22028 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG,
22029 str: c_name, list: clauses);
22030 break;
22031 case PRAGMA_OACC_CLAUSE_HOST:
22032 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22033 c_name = "host";
22034 break;
22035 case PRAGMA_OACC_CLAUSE_IF:
22036 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: false);
22037 c_name = "if";
22038 break;
22039 case PRAGMA_OACC_CLAUSE_IF_PRESENT:
22040 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT,
22041 list: clauses);
22042 c_name = "if_present";
22043 break;
22044 case PRAGMA_OACC_CLAUSE_INDEPENDENT:
22045 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT,
22046 list: clauses);
22047 c_name = "independent";
22048 break;
22049 case PRAGMA_OACC_CLAUSE_LINK:
22050 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22051 c_name = "link";
22052 break;
22053 case PRAGMA_OACC_CLAUSE_NO_CREATE:
22054 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22055 c_name = "no_create";
22056 break;
22057 case PRAGMA_OACC_CLAUSE_NOHOST:
22058 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST,
22059 list: clauses);
22060 c_name = "nohost";
22061 break;
22062 case PRAGMA_OACC_CLAUSE_NUM_GANGS:
22063 clauses = c_parser_oacc_single_int_clause (parser,
22064 code: OMP_CLAUSE_NUM_GANGS,
22065 list: clauses);
22066 c_name = "num_gangs";
22067 break;
22068 case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
22069 clauses = c_parser_oacc_single_int_clause (parser,
22070 code: OMP_CLAUSE_NUM_WORKERS,
22071 list: clauses);
22072 c_name = "num_workers";
22073 break;
22074 case PRAGMA_OACC_CLAUSE_PRESENT:
22075 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22076 c_name = "present";
22077 break;
22078 case PRAGMA_OACC_CLAUSE_PRIVATE:
22079 clauses = c_parser_omp_clause_private (parser, list: clauses);
22080 c_name = "private";
22081 break;
22082 case PRAGMA_OACC_CLAUSE_REDUCTION:
22083 clauses
22084 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
22085 is_omp: false, list: clauses);
22086 c_name = "reduction";
22087 break;
22088 case PRAGMA_OACC_CLAUSE_SELF:
22089 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
22090 /* OpenACC compute construct */
22091 clauses = c_parser_oacc_compute_clause_self (parser, list: clauses);
22092 else
22093 /* OpenACC 'update' directive */
22094 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
22095 c_name = "self";
22096 break;
22097 case PRAGMA_OACC_CLAUSE_SEQ:
22098 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ,
22099 list: clauses);
22100 c_name = "seq";
22101 break;
22102 case PRAGMA_OACC_CLAUSE_TILE:
22103 clauses = c_parser_oacc_clause_tile (parser, list: clauses);
22104 c_name = "tile";
22105 break;
22106 case PRAGMA_OACC_CLAUSE_USE_DEVICE:
22107 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
22108 c_name = "use_device";
22109 break;
22110 case PRAGMA_OACC_CLAUSE_VECTOR:
22111 c_name = "vector";
22112 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_VECTOR,
22113 str: c_name, list: clauses);
22114 break;
22115 case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
22116 clauses = c_parser_oacc_single_int_clause (parser,
22117 code: OMP_CLAUSE_VECTOR_LENGTH,
22118 list: clauses);
22119 c_name = "vector_length";
22120 break;
22121 case PRAGMA_OACC_CLAUSE_WAIT:
22122 clauses = c_parser_oacc_clause_wait (parser, list: clauses);
22123 c_name = "wait";
22124 break;
22125 case PRAGMA_OACC_CLAUSE_WORKER:
22126 c_name = "worker";
22127 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_WORKER,
22128 str: c_name, list: clauses);
22129 break;
22130 default:
22131 c_parser_error (parser, gmsgid: "expected an OpenACC clause");
22132 goto saw_error;
22133 }
22134
22135 first = false;
22136
22137 if (((mask >> c_kind) & 1) == 0)
22138 {
22139 /* Remove the invalid clause(s) from the list to avoid
22140 confusing the rest of the compiler. */
22141 clauses = prev;
22142 error_at (here, "%qs is not valid for %qs", c_name, where);
22143 }
22144 }
22145
22146 saw_error:
22147 c_parser_skip_to_pragma_eol (parser);
22148
22149 if (finish_p)
22150 return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
22151 : C_ORT_ACC);
22152
22153 return clauses;
22154}
22155
22156/* Parse all OpenMP clauses. The set clauses allowed by the directive
22157 is a bitmask in MASK. Return the list of clauses found.
22158 FINISH_P set if c_finish_omp_clauses should be called.
22159 NESTED non-zero if clauses should be terminated by closing paren instead
22160 of end of pragma. If it is 2, additionally commas are required in between
22161 the clauses. */
22162
22163static tree
22164c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
22165 const char *where, bool finish_p = true,
22166 int nested = 0)
22167{
22168 tree clauses = NULL;
22169 bool first = true;
22170
22171 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
22172 {
22173 location_t here;
22174 pragma_omp_clause c_kind;
22175 const char *c_name;
22176 tree prev = clauses;
22177
22178 if (nested && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
22179 break;
22180
22181 if (!first || nested != 2)
22182 {
22183 if (c_parser_next_token_is (parser, type: CPP_COMMA))
22184 c_parser_consume_token (parser);
22185 else if (nested == 2)
22186 error_at (c_parser_peek_token (parser)->location,
22187 "clauses in %<simd%> trait should be separated "
22188 "by %<,%>");
22189 }
22190
22191 here = c_parser_peek_token (parser)->location;
22192 c_kind = c_parser_omp_clause_name (parser);
22193
22194 switch (c_kind)
22195 {
22196 case PRAGMA_OMP_CLAUSE_BIND:
22197 clauses = c_parser_omp_clause_bind (parser, list: clauses);
22198 c_name = "bind";
22199 break;
22200 case PRAGMA_OMP_CLAUSE_COLLAPSE:
22201 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
22202 c_name = "collapse";
22203 break;
22204 case PRAGMA_OMP_CLAUSE_COPYIN:
22205 clauses = c_parser_omp_clause_copyin (parser, list: clauses);
22206 c_name = "copyin";
22207 break;
22208 case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
22209 clauses = c_parser_omp_clause_copyprivate (parser, list: clauses);
22210 c_name = "copyprivate";
22211 break;
22212 case PRAGMA_OMP_CLAUSE_DEFAULT:
22213 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: false);
22214 c_name = "default";
22215 break;
22216 case PRAGMA_OMP_CLAUSE_DETACH:
22217 clauses = c_parser_omp_clause_detach (parser, list: clauses);
22218 c_name = "detach";
22219 break;
22220 case PRAGMA_OMP_CLAUSE_FILTER:
22221 clauses = c_parser_omp_clause_filter (parser, list: clauses);
22222 c_name = "filter";
22223 break;
22224 case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
22225 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
22226 c_name = "firstprivate";
22227 break;
22228 case PRAGMA_OMP_CLAUSE_FINAL:
22229 clauses = c_parser_omp_clause_final (parser, list: clauses);
22230 c_name = "final";
22231 break;
22232 case PRAGMA_OMP_CLAUSE_GRAINSIZE:
22233 clauses = c_parser_omp_clause_grainsize (parser, list: clauses);
22234 c_name = "grainsize";
22235 break;
22236 case PRAGMA_OMP_CLAUSE_HINT:
22237 clauses = c_parser_omp_clause_hint (parser, list: clauses);
22238 c_name = "hint";
22239 break;
22240 case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
22241 clauses = c_parser_omp_clause_defaultmap (parser, list: clauses);
22242 c_name = "defaultmap";
22243 break;
22244 case PRAGMA_OMP_CLAUSE_IF:
22245 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: true);
22246 c_name = "if";
22247 break;
22248 case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
22249 clauses
22250 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION,
22251 is_omp: true, list: clauses);
22252 c_name = "in_reduction";
22253 break;
22254 case PRAGMA_OMP_CLAUSE_INDIRECT:
22255 clauses = c_parser_omp_clause_indirect (parser, list: clauses);
22256 c_name = "indirect";
22257 break;
22258 case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
22259 clauses = c_parser_omp_clause_lastprivate (parser, list: clauses);
22260 c_name = "lastprivate";
22261 break;
22262 case PRAGMA_OMP_CLAUSE_MERGEABLE:
22263 clauses = c_parser_omp_clause_mergeable (parser, list: clauses);
22264 c_name = "mergeable";
22265 break;
22266 case PRAGMA_OMP_CLAUSE_NOWAIT:
22267 clauses = c_parser_omp_clause_nowait (parser, list: clauses);
22268 c_name = "nowait";
22269 break;
22270 case PRAGMA_OMP_CLAUSE_NUM_TASKS:
22271 clauses = c_parser_omp_clause_num_tasks (parser, list: clauses);
22272 c_name = "num_tasks";
22273 break;
22274 case PRAGMA_OMP_CLAUSE_NUM_THREADS:
22275 clauses = c_parser_omp_clause_num_threads (parser, list: clauses);
22276 c_name = "num_threads";
22277 break;
22278 case PRAGMA_OMP_CLAUSE_ORDER:
22279 clauses = c_parser_omp_clause_order (parser, list: clauses);
22280 c_name = "order";
22281 break;
22282 case PRAGMA_OMP_CLAUSE_ORDERED:
22283 clauses = c_parser_omp_clause_ordered (parser, list: clauses);
22284 c_name = "ordered";
22285 break;
22286 case PRAGMA_OMP_CLAUSE_PRIORITY:
22287 clauses = c_parser_omp_clause_priority (parser, list: clauses);
22288 c_name = "priority";
22289 break;
22290 case PRAGMA_OMP_CLAUSE_PRIVATE:
22291 clauses = c_parser_omp_clause_private (parser, list: clauses);
22292 c_name = "private";
22293 break;
22294 case PRAGMA_OMP_CLAUSE_REDUCTION:
22295 clauses
22296 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
22297 is_omp: true, list: clauses);
22298 c_name = "reduction";
22299 break;
22300 case PRAGMA_OMP_CLAUSE_SCHEDULE:
22301 clauses = c_parser_omp_clause_schedule (parser, list: clauses);
22302 c_name = "schedule";
22303 break;
22304 case PRAGMA_OMP_CLAUSE_SHARED:
22305 clauses = c_parser_omp_clause_shared (parser, list: clauses);
22306 c_name = "shared";
22307 break;
22308 case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
22309 clauses
22310 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_TASK_REDUCTION,
22311 is_omp: true, list: clauses);
22312 c_name = "task_reduction";
22313 break;
22314 case PRAGMA_OMP_CLAUSE_UNTIED:
22315 clauses = c_parser_omp_clause_untied (parser, list: clauses);
22316 c_name = "untied";
22317 break;
22318 case PRAGMA_OMP_CLAUSE_INBRANCH:
22319 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH,
22320 list: clauses);
22321 c_name = "inbranch";
22322 break;
22323 case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
22324 clauses = c_parser_omp_clause_nontemporal (parser, list: clauses);
22325 c_name = "nontemporal";
22326 break;
22327 case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
22328 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_NOTINBRANCH,
22329 list: clauses);
22330 c_name = "notinbranch";
22331 break;
22332 case PRAGMA_OMP_CLAUSE_PARALLEL:
22333 clauses
22334 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL,
22335 list: clauses);
22336 c_name = "parallel";
22337 if (!first)
22338 {
22339 clause_not_first:
22340 error_at (here, "%qs must be the first clause of %qs",
22341 c_name, where);
22342 clauses = prev;
22343 }
22344 break;
22345 case PRAGMA_OMP_CLAUSE_FOR:
22346 clauses
22347 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR,
22348 list: clauses);
22349 c_name = "for";
22350 if (!first)
22351 goto clause_not_first;
22352 break;
22353 case PRAGMA_OMP_CLAUSE_SECTIONS:
22354 clauses
22355 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS,
22356 list: clauses);
22357 c_name = "sections";
22358 if (!first)
22359 goto clause_not_first;
22360 break;
22361 case PRAGMA_OMP_CLAUSE_TASKGROUP:
22362 clauses
22363 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP,
22364 list: clauses);
22365 c_name = "taskgroup";
22366 if (!first)
22367 goto clause_not_first;
22368 break;
22369 case PRAGMA_OMP_CLAUSE_LINK:
22370 clauses
22371 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_LINK, list: clauses);
22372 c_name = "link";
22373 break;
22374 case PRAGMA_OMP_CLAUSE_TO:
22375 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
22376 {
22377 gcc_rich_location richloc (here);
22378 richloc.add_fixit_replace (new_content: "enter");
22379 warning_at (&richloc, OPT_Wdeprecated_openmp,
22380 "%<to%> clause with %<declare target%> deprecated "
22381 "since OpenMP 5.2, use %<enter%>");
22382 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
22383 list: clauses);
22384 for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
22385 OMP_CLAUSE_ENTER_TO (c) = 1;
22386 clauses = nl;
22387 }
22388 else
22389 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO,
22390 list: clauses);
22391 c_name = "to";
22392 break;
22393 case PRAGMA_OMP_CLAUSE_FROM:
22394 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM,
22395 list: clauses);
22396 c_name = "from";
22397 break;
22398 case PRAGMA_OMP_CLAUSE_UNIFORM:
22399 clauses = c_parser_omp_clause_uniform (parser, list: clauses);
22400 c_name = "uniform";
22401 break;
22402 case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
22403 clauses = c_parser_omp_clause_num_teams (parser, list: clauses);
22404 c_name = "num_teams";
22405 break;
22406 case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
22407 clauses = c_parser_omp_clause_thread_limit (parser, list: clauses);
22408 c_name = "thread_limit";
22409 break;
22410 case PRAGMA_OMP_CLAUSE_ALIGNED:
22411 clauses = c_parser_omp_clause_aligned (parser, list: clauses);
22412 c_name = "aligned";
22413 break;
22414 case PRAGMA_OMP_CLAUSE_ALLOCATE:
22415 clauses = c_parser_omp_clause_allocate (parser, list: clauses);
22416 c_name = "allocate";
22417 break;
22418 case PRAGMA_OMP_CLAUSE_LINEAR:
22419 clauses = c_parser_omp_clause_linear (parser, list: clauses);
22420 c_name = "linear";
22421 break;
22422 case PRAGMA_OMP_CLAUSE_USES_ALLOCATORS:
22423 clauses = c_parser_omp_clause_uses_allocators (parser, list: clauses);
22424 c_name = "uses_allocators";
22425 break;
22426 case PRAGMA_OMP_CLAUSE_AFFINITY:
22427 clauses = c_parser_omp_clause_affinity (parser, list: clauses);
22428 c_name = "affinity";
22429 break;
22430 case PRAGMA_OMP_CLAUSE_DEPEND:
22431 clauses = c_parser_omp_clause_depend (parser, list: clauses, here);
22432 c_name = "depend";
22433 break;
22434 case PRAGMA_OMP_CLAUSE_DOACROSS:
22435 clauses = c_parser_omp_clause_doacross (parser, list: clauses);
22436 c_name = "doacross";
22437 break;
22438 case PRAGMA_OMP_CLAUSE_DESTROY:
22439 clauses = c_parser_omp_clause_destroy (parser, list: clauses);
22440 c_name = "destroy";
22441 break;
22442 case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
22443 clauses = c_parser_omp_clause_dyn_groupprivate (parser, list: clauses);
22444 c_name = "dyn_groupprivate";
22445 break;
22446 case PRAGMA_OMP_CLAUSE_INIT:
22447 clauses = c_parser_omp_clause_init (parser, list: clauses);
22448 c_name = "init";
22449 break;
22450 case PRAGMA_OMP_CLAUSE_USE:
22451 clauses = c_parser_omp_clause_use (parser, list: clauses);
22452 c_name = "use";
22453 break;
22454 case PRAGMA_OMP_CLAUSE_INTEROP:
22455 clauses = c_parser_omp_clause_interop (parser, list: clauses);
22456 c_name = "interop";
22457 break;
22458 case PRAGMA_OMP_CLAUSE_MAP:
22459 clauses = c_parser_omp_clause_map (parser, list: clauses, declare_mapper_p: false);
22460 c_name = "map";
22461 break;
22462 case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
22463 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
22464 c_name = "use_device_ptr";
22465 break;
22466 case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
22467 clauses = c_parser_omp_clause_use_device_addr (parser, list: clauses);
22468 c_name = "use_device_addr";
22469 break;
22470 case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
22471 clauses = c_parser_omp_clause_has_device_addr (parser, list: clauses);
22472 c_name = "has_device_addr";
22473 break;
22474 case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
22475 clauses = c_parser_omp_clause_is_device_ptr (parser, list: clauses);
22476 c_name = "is_device_ptr";
22477 break;
22478 case PRAGMA_OMP_CLAUSE_DEVICE:
22479 clauses = c_parser_omp_clause_device (parser, list: clauses);
22480 c_name = "device";
22481 break;
22482 case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
22483 clauses = c_parser_omp_clause_dist_schedule (parser, list: clauses);
22484 c_name = "dist_schedule";
22485 break;
22486 case PRAGMA_OMP_CLAUSE_PROC_BIND:
22487 clauses = c_parser_omp_clause_proc_bind (parser, list: clauses);
22488 c_name = "proc_bind";
22489 break;
22490 case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
22491 clauses = c_parser_omp_clause_device_type (parser, list: clauses);
22492 c_name = "device_type";
22493 break;
22494 case PRAGMA_OMP_CLAUSE_SAFELEN:
22495 clauses = c_parser_omp_clause_safelen (parser, list: clauses);
22496 c_name = "safelen";
22497 break;
22498 case PRAGMA_OMP_CLAUSE_SIMDLEN:
22499 clauses = c_parser_omp_clause_simdlen (parser, list: clauses);
22500 c_name = "simdlen";
22501 break;
22502 case PRAGMA_OMP_CLAUSE_NOGROUP:
22503 clauses = c_parser_omp_clause_nogroup (parser, list: clauses);
22504 c_name = "nogroup";
22505 break;
22506 case PRAGMA_OMP_CLAUSE_THREADS:
22507 clauses
22508 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS,
22509 list: clauses);
22510 c_name = "threads";
22511 break;
22512 case PRAGMA_OMP_CLAUSE_SIMD:
22513 clauses
22514 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD,
22515 list: clauses);
22516 c_name = "simd";
22517 break;
22518 case PRAGMA_OMP_CLAUSE_ENTER:
22519 clauses
22520 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
22521 list: clauses);
22522 c_name = "enter";
22523 break;
22524 case PRAGMA_OMP_CLAUSE_FULL:
22525 c_name = "full";
22526 clauses = c_parser_omp_clause_full (parser, list: clauses);
22527 break;
22528 case PRAGMA_OMP_CLAUSE_PARTIAL:
22529 c_name = "partial";
22530 clauses = c_parser_omp_clause_partial (parser, list: clauses);
22531 break;
22532 case PRAGMA_OMP_CLAUSE_NOVARIANTS:
22533 c_name = "novariants";
22534 clauses = c_parser_omp_clause_novariants (parser, list: clauses);
22535 break;
22536 case PRAGMA_OMP_CLAUSE_NOCONTEXT:
22537 c_name = "nocontext";
22538 clauses = c_parser_omp_clause_nocontext (parser, list: clauses);
22539 break;
22540 default:
22541 c_parser_error (parser, gmsgid: "expected an OpenMP clause");
22542 goto saw_error;
22543 }
22544
22545 first = false;
22546
22547 if (((mask >> c_kind) & 1) == 0)
22548 {
22549 /* Remove the invalid clause(s) from the list to avoid
22550 confusing the rest of the compiler. */
22551 clauses = prev;
22552 error_at (here, "%qs is not valid for %qs", c_name, where);
22553 }
22554 }
22555
22556 saw_error:
22557 if (!nested)
22558 c_parser_skip_to_pragma_eol (parser);
22559
22560 if (finish_p)
22561 {
22562 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
22563 return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
22564 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE)) != 0)
22565 return c_finish_omp_clauses (clauses, C_ORT_OMP_INTEROP);
22566 return c_finish_omp_clauses (clauses, C_ORT_OMP);
22567 }
22568
22569 return clauses;
22570}
22571
22572/* OpenACC 2.0, OpenMP 2.5:
22573 structured-block:
22574 statement
22575
22576 In practice, we're also interested in adding the statement to an
22577 outer node. So it is convenient if we work around the fact that
22578 c_parser_statement calls add_stmt. */
22579
22580static tree
22581c_parser_omp_structured_block (c_parser *parser, bool *if_p)
22582{
22583 tree stmt = push_stmt_list ();
22584 parser->omp_attrs_forbidden_p = true;
22585 c_parser_statement (parser, if_p);
22586 return pop_stmt_list (stmt);
22587}
22588
22589/* OpenACC 2.0:
22590 # pragma acc cache (variable-list) new-line
22591
22592 OpenACC 2.7:
22593 # pragma acc cache (readonly: variable-list) new-line
22594
22595 LOC is the location of the #pragma token.
22596*/
22597
22598static tree
22599c_parser_oacc_cache (location_t loc, c_parser *parser)
22600{
22601 tree stmt, clauses = NULL_TREE;
22602 bool readonly = false;
22603 location_t open_loc = c_parser_peek_token (parser)->location;
22604 matching_parens parens;
22605 if (parens.require_open (parser))
22606 {
22607 c_token *token = c_parser_peek_token (parser);
22608 if (token->type == CPP_NAME
22609 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
22610 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
22611 {
22612 c_parser_consume_token (parser);
22613 c_parser_consume_token (parser);
22614 readonly = true;
22615 }
22616 clauses = c_parser_omp_variable_list (parser, clause_loc: open_loc,
22617 kind: OMP_CLAUSE__CACHE_, NULL_TREE);
22618 parens.skip_until_found_close (parser);
22619 }
22620
22621 if (readonly)
22622 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
22623 OMP_CLAUSE__CACHE__READONLY (c) = 1;
22624
22625 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22626
22627 c_parser_skip_to_pragma_eol (parser);
22628
22629 stmt = make_node (OACC_CACHE);
22630 TREE_TYPE (stmt) = void_type_node;
22631 OACC_CACHE_CLAUSES (stmt) = clauses;
22632 SET_EXPR_LOCATION (stmt, loc);
22633 add_stmt (stmt);
22634
22635 return stmt;
22636}
22637
22638/* OpenACC 2.0:
22639 # pragma acc data oacc-data-clause[optseq] new-line
22640 structured-block
22641
22642 LOC is the location of the #pragma token.
22643*/
22644
22645#define OACC_DATA_CLAUSE_MASK \
22646 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22647 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22648 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22649 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22650 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22651 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22652 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22653 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22654 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22655 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
22656
22657static tree
22658c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
22659{
22660 tree stmt, clauses, block;
22661
22662 clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
22663 where: "#pragma acc data");
22664
22665 block = c_begin_omp_parallel ();
22666 add_stmt (c_parser_omp_structured_block (parser, if_p));
22667
22668 stmt = c_finish_oacc_data (loc, clauses, block);
22669
22670 return stmt;
22671}
22672
22673/* OpenACC 2.0:
22674 # pragma acc declare oacc-data-clause[optseq] new-line
22675*/
22676
22677#define OACC_DECLARE_CLAUSE_MASK \
22678 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22679 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22680 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22681 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22682 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22683 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
22684 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
22685 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
22686
22687static void
22688c_parser_oacc_declare (c_parser *parser)
22689{
22690 location_t pragma_loc = c_parser_peek_token (parser)->location;
22691 tree clauses, stmt, t, decl;
22692
22693 bool error = false;
22694
22695 c_parser_consume_pragma (parser);
22696
22697 clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
22698 where: "#pragma acc declare");
22699 if (!clauses)
22700 {
22701 error_at (pragma_loc,
22702 "no valid clauses specified in %<#pragma acc declare%>");
22703 return;
22704 }
22705
22706 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
22707 {
22708 location_t loc = OMP_CLAUSE_LOCATION (t);
22709 decl = OMP_CLAUSE_DECL (t);
22710 if (!DECL_P (decl))
22711 {
22712 error_at (loc, "array section in %<#pragma acc declare%>");
22713 error = true;
22714 continue;
22715 }
22716
22717 switch (OMP_CLAUSE_MAP_KIND (t))
22718 {
22719 case GOMP_MAP_FIRSTPRIVATE_POINTER:
22720 case GOMP_MAP_ALLOC:
22721 case GOMP_MAP_TO:
22722 case GOMP_MAP_FORCE_DEVICEPTR:
22723 case GOMP_MAP_DEVICE_RESIDENT:
22724 break;
22725
22726 case GOMP_MAP_LINK:
22727 if (!global_bindings_p ()
22728 && (TREE_STATIC (decl)
22729 || !DECL_EXTERNAL (decl)))
22730 {
22731 error_at (loc,
22732 "%qD must be a global variable in "
22733 "%<#pragma acc declare link%>",
22734 decl);
22735 error = true;
22736 continue;
22737 }
22738 break;
22739
22740 default:
22741 if (global_bindings_p ())
22742 {
22743 error_at (loc, "invalid OpenACC clause at file scope");
22744 error = true;
22745 continue;
22746 }
22747 if (DECL_EXTERNAL (decl))
22748 {
22749 error_at (loc,
22750 "invalid use of %<extern%> variable %qD "
22751 "in %<#pragma acc declare%>", decl);
22752 error = true;
22753 continue;
22754 }
22755 else if (TREE_PUBLIC (decl))
22756 {
22757 error_at (loc,
22758 "invalid use of %<global%> variable %qD "
22759 "in %<#pragma acc declare%>", decl);
22760 error = true;
22761 continue;
22762 }
22763 break;
22764 }
22765
22766 if (!c_check_in_current_scope (decl))
22767 {
22768 error_at (loc,
22769 "%qD must be a variable declared in the same scope as "
22770 "%<#pragma acc declare%>", decl);
22771 error = true;
22772 continue;
22773 }
22774
22775 if (lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (decl))
22776 || lookup_attribute (attr_name: "omp declare target link",
22777 DECL_ATTRIBUTES (decl)))
22778 {
22779 error_at (loc, "variable %qD used more than once with "
22780 "%<#pragma acc declare%>", decl);
22781 error = true;
22782 continue;
22783 }
22784
22785 if (!error)
22786 {
22787 tree id;
22788
22789 if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
22790 id = get_identifier ("omp declare target link");
22791 else
22792 id = get_identifier ("omp declare target");
22793
22794 DECL_ATTRIBUTES (decl)
22795 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
22796
22797 if (global_bindings_p ())
22798 {
22799 symtab_node *node = symtab_node::get (decl);
22800 if (node != NULL)
22801 {
22802 node->offloadable = 1;
22803 if (ENABLE_OFFLOADING)
22804 {
22805 g->have_offload = true;
22806 if (is_a <varpool_node *> (p: node))
22807 vec_safe_push (v&: offload_vars, obj: decl);
22808 }
22809 }
22810 }
22811 }
22812 }
22813
22814 if (error || global_bindings_p ())
22815 return;
22816
22817 stmt = make_node (OACC_DECLARE);
22818 TREE_TYPE (stmt) = void_type_node;
22819 OACC_DECLARE_CLAUSES (stmt) = clauses;
22820 SET_EXPR_LOCATION (stmt, pragma_loc);
22821
22822 add_stmt (stmt);
22823
22824 return;
22825}
22826
22827/* OpenACC 2.0:
22828 # pragma acc enter data oacc-enter-data-clause[optseq] new-line
22829
22830 or
22831
22832 # pragma acc exit data oacc-exit-data-clause[optseq] new-line
22833
22834
22835 LOC is the location of the #pragma token.
22836*/
22837
22838#define OACC_ENTER_DATA_CLAUSE_MASK \
22839 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22840 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22841 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22842 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22843 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22844 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22845
22846#define OACC_EXIT_DATA_CLAUSE_MASK \
22847 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22848 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22849 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22850 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
22851 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
22852 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
22853 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22854
22855static void
22856c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
22857{
22858 location_t loc = c_parser_peek_token (parser)->location;
22859 tree clauses, stmt;
22860 const char *p = "";
22861
22862 c_parser_consume_pragma (parser);
22863
22864 if (c_parser_next_token_is (parser, type: CPP_NAME))
22865 {
22866 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22867 c_parser_consume_token (parser);
22868 }
22869
22870 if (strcmp (s1: p, s2: "data") != 0)
22871 {
22872 error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
22873 enter ? "enter" : "exit");
22874 parser->error = true;
22875 c_parser_skip_to_pragma_eol (parser);
22876 return;
22877 }
22878
22879 if (enter)
22880 clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
22881 where: "#pragma acc enter data");
22882 else
22883 clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
22884 where: "#pragma acc exit data");
22885
22886 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
22887 {
22888 error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
22889 enter ? "enter" : "exit");
22890 return;
22891 }
22892
22893 stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
22894 TREE_TYPE (stmt) = void_type_node;
22895 OMP_STANDALONE_CLAUSES (stmt) = clauses;
22896 SET_EXPR_LOCATION (stmt, loc);
22897 add_stmt (stmt);
22898}
22899
22900
22901/* OpenACC 2.0:
22902 # pragma acc host_data oacc-data-clause[optseq] new-line
22903 structured-block
22904*/
22905
22906#define OACC_HOST_DATA_CLAUSE_MASK \
22907 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
22908 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22909 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
22910
22911static tree
22912c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
22913{
22914 tree stmt, clauses, block;
22915
22916 clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
22917 where: "#pragma acc host_data", finish_p: false);
22918 if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR))
22919 {
22920 error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
22921 return error_mark_node;
22922 }
22923 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22924 block = c_begin_omp_parallel ();
22925 add_stmt (c_parser_omp_structured_block (parser, if_p));
22926 stmt = c_finish_oacc_host_data (loc, clauses, block);
22927 return stmt;
22928}
22929
22930
22931/* OpenACC 2.0:
22932
22933 # pragma acc loop oacc-loop-clause[optseq] new-line
22934 structured-block
22935
22936 LOC is the location of the #pragma token.
22937*/
22938
22939#define OACC_LOOP_CLAUSE_MASK \
22940 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
22941 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22942 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22943 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22944 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22945 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22946 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
22947 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
22948 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22949 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
22950static tree
22951c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
22952 omp_clause_mask mask, tree *cclauses, bool *if_p)
22953{
22954 bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
22955
22956 strcat (dest: p_name, src: " loop");
22957 mask |= OACC_LOOP_CLAUSE_MASK;
22958
22959 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
22960 /*finish_p=*/cclauses == NULL,
22961 /*target=*/target_p: is_parallel);
22962 if (cclauses)
22963 {
22964 clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
22965 if (*cclauses)
22966 *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
22967 if (clauses)
22968 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22969 }
22970
22971 tree block = c_begin_compound_stmt (true);
22972 tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
22973 if_p);
22974 block = c_end_compound_stmt (loc, block, true);
22975 add_stmt (block);
22976
22977 return stmt;
22978}
22979
22980/* OpenACC 2.0:
22981 # pragma acc kernels oacc-kernels-clause[optseq] new-line
22982 structured-block
22983
22984 or
22985
22986 # pragma acc parallel oacc-parallel-clause[optseq] new-line
22987 structured-block
22988
22989 OpenACC 2.6:
22990
22991 # pragma acc serial oacc-serial-clause[optseq] new-line
22992 structured-block
22993
22994 LOC is the location of the #pragma token.
22995*/
22996
22997#define OACC_KERNELS_CLAUSE_MASK \
22998 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22999 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23000 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23001 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23002 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23003 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23004 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23005 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23006 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23007 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23008 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
23009 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
23010 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23011 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23012 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
23013 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23014
23015#define OACC_PARALLEL_CLAUSE_MASK \
23016 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23017 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23018 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23019 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23020 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23021 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23022 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23023 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23024 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23025 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23026 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
23027 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
23028 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
23029 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
23030 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23031 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
23032 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23033 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
23034 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23035
23036#define OACC_SERIAL_CLAUSE_MASK \
23037 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23038 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23039 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23040 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23041 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23042 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23043 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23044 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23045 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23046 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23047 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
23048 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
23049 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23050 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
23051 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23052 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23053
23054static tree
23055c_parser_oacc_compute (location_t loc, c_parser *parser,
23056 enum pragma_kind p_kind, char *p_name, bool *if_p)
23057{
23058 omp_clause_mask mask;
23059 enum tree_code code;
23060 switch (p_kind)
23061 {
23062 case PRAGMA_OACC_KERNELS:
23063 strcat (dest: p_name, src: " kernels");
23064 mask = OACC_KERNELS_CLAUSE_MASK;
23065 code = OACC_KERNELS;
23066 break;
23067 case PRAGMA_OACC_PARALLEL:
23068 strcat (dest: p_name, src: " parallel");
23069 mask = OACC_PARALLEL_CLAUSE_MASK;
23070 code = OACC_PARALLEL;
23071 break;
23072 case PRAGMA_OACC_SERIAL:
23073 strcat (dest: p_name, src: " serial");
23074 mask = OACC_SERIAL_CLAUSE_MASK;
23075 code = OACC_SERIAL;
23076 break;
23077 default:
23078 gcc_unreachable ();
23079 }
23080
23081 if (c_parser_next_token_is (parser, type: CPP_NAME))
23082 {
23083 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23084 if (strcmp (s1: p, s2: "loop") == 0)
23085 {
23086 c_parser_consume_token (parser);
23087 tree block = c_begin_omp_parallel ();
23088 tree clauses;
23089 c_parser_oacc_loop (loc, parser, p_name, mask, cclauses: &clauses, if_p);
23090 return c_finish_omp_construct (loc, code, block, clauses);
23091 }
23092 }
23093
23094 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
23095 /*finish_p=*/true,
23096 /*target=*/target_p: true);
23097
23098 tree block = c_begin_omp_parallel ();
23099 add_stmt (c_parser_omp_structured_block (parser, if_p));
23100
23101 return c_finish_omp_construct (loc, code, block, clauses);
23102}
23103
23104/* OpenACC 2.0:
23105 # pragma acc routine oacc-routine-clause[optseq] new-line
23106 function-definition
23107
23108 # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
23109*/
23110
23111#define OACC_ROUTINE_CLAUSE_MASK \
23112 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
23113 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
23114 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
23115 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
23116 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
23117
23118/* Parse an OpenACC routine directive. For named directives, we apply
23119 immediately to the named function. For unnamed ones we then parse
23120 a declaration or definition, which must be for a function. */
23121
23122static void
23123c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
23124{
23125 gcc_checking_assert (context == pragma_external);
23126
23127 oacc_routine_data data;
23128 data.error_seen = false;
23129 data.fndecl_seen = false;
23130 data.loc = c_parser_peek_token (parser)->location;
23131
23132 c_parser_consume_pragma (parser);
23133
23134 /* Look for optional '( name )'. */
23135 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
23136 {
23137 c_parser_consume_token (parser); /* '(' */
23138
23139 tree decl = NULL_TREE;
23140 c_token *name_token = c_parser_peek_token (parser);
23141 location_t name_loc = name_token->location;
23142 if (name_token->type == CPP_NAME
23143 && (name_token->id_kind == C_ID_ID
23144 || name_token->id_kind == C_ID_TYPENAME))
23145 {
23146 decl = lookup_name (name_token->value);
23147 if (!decl)
23148 error_at (name_loc,
23149 "%qE has not been declared", name_token->value);
23150 c_parser_consume_token (parser);
23151 }
23152 else
23153 c_parser_error (parser, gmsgid: "expected function name");
23154
23155 if (!decl
23156 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
23157 {
23158 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23159 return;
23160 }
23161
23162 data.clauses
23163 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
23164 where: "#pragma acc routine");
23165 /* The clauses are in reverse order; fix that to make later diagnostic
23166 emission easier. */
23167 data.clauses = nreverse (data.clauses);
23168
23169 if (TREE_CODE (decl) != FUNCTION_DECL)
23170 {
23171 error_at (name_loc, "%qD does not refer to a function", decl);
23172 return;
23173 }
23174
23175 c_finish_oacc_routine (&data, decl, false);
23176 }
23177 else /* No optional '( name )'. */
23178 {
23179 data.clauses
23180 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
23181 where: "#pragma acc routine");
23182 /* The clauses are in reverse order; fix that to make later diagnostic
23183 emission easier. */
23184 data.clauses = nreverse (data.clauses);
23185
23186 /* Emit a helpful diagnostic if there's another pragma following this
23187 one. Also don't allow a static assertion declaration, as in the
23188 following we'll just parse a *single* "declaration or function
23189 definition", and the static assertion counts an one. */
23190 if (c_parser_next_token_is (parser, type: CPP_PRAGMA)
23191 || c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
23192 {
23193 error_at (data.loc,
23194 "%<#pragma acc routine%> not immediately followed by"
23195 " function declaration or definition");
23196 /* ..., and then just keep going. */
23197 return;
23198 }
23199
23200 /* We only have to consider the pragma_external case here. */
23201 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23202 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
23203 {
23204 int ext = disable_extension_diagnostics ();
23205 do
23206 c_parser_consume_token (parser);
23207 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23208 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
23209 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
23210 simple_ok: false, NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
23211 restore_extension_diagnostics (flags: ext);
23212 }
23213 else
23214 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
23215 simple_ok: false, NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
23216 }
23217}
23218
23219/* Finalize an OpenACC routine pragma, applying it to FNDECL.
23220 IS_DEFN is true if we're applying it to the definition. */
23221
23222static void
23223c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
23224 bool is_defn)
23225{
23226 /* Keep going if we're in error reporting mode. */
23227 if (data->error_seen
23228 || fndecl == error_mark_node)
23229 return;
23230
23231 if (data->fndecl_seen)
23232 {
23233 error_at (data->loc,
23234 "%<#pragma acc routine%> not immediately followed by"
23235 " a single function declaration or definition");
23236 data->error_seen = true;
23237 return;
23238 }
23239 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
23240 {
23241 error_at (data->loc,
23242 "%<#pragma acc routine%> not immediately followed by"
23243 " function declaration or definition");
23244 data->error_seen = true;
23245 return;
23246 }
23247
23248 int compatible
23249 = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
23250 "#pragma acc routine");
23251 if (compatible < 0)
23252 {
23253 data->error_seen = true;
23254 return;
23255 }
23256 if (compatible > 0)
23257 {
23258 }
23259 else
23260 {
23261 if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
23262 {
23263 error_at (data->loc,
23264 TREE_USED (fndecl)
23265 ? G_("%<#pragma acc routine%> must be applied before use")
23266 : G_("%<#pragma acc routine%> must be applied before"
23267 " definition"));
23268 data->error_seen = true;
23269 return;
23270 }
23271
23272 /* Set the routine's level of parallelism. */
23273 tree dims = oacc_build_routine_dims (clauses: data->clauses);
23274 oacc_replace_fn_attrib (fn: fndecl, dims);
23275
23276 /* Add an "omp declare target" attribute. */
23277 DECL_ATTRIBUTES (fndecl)
23278 = tree_cons (get_identifier ("omp declare target"),
23279 data->clauses, DECL_ATTRIBUTES (fndecl));
23280 }
23281
23282 /* Remember that we've used this "#pragma acc routine". */
23283 data->fndecl_seen = true;
23284}
23285
23286/* OpenACC 2.0:
23287 # pragma acc update oacc-update-clause[optseq] new-line
23288*/
23289
23290#define OACC_UPDATE_CLAUSE_MASK \
23291 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23292 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
23293 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
23294 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23295 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
23296 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23297 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23298
23299static void
23300c_parser_oacc_update (c_parser *parser)
23301{
23302 location_t loc = c_parser_peek_token (parser)->location;
23303
23304 c_parser_consume_pragma (parser);
23305
23306 tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
23307 where: "#pragma acc update");
23308 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
23309 {
23310 error_at (loc,
23311 "%<#pragma acc update%> must contain at least one "
23312 "%<device%> or %<host%> or %<self%> clause");
23313 return;
23314 }
23315
23316 if (parser->error)
23317 return;
23318
23319 tree stmt = make_node (OACC_UPDATE);
23320 TREE_TYPE (stmt) = void_type_node;
23321 OACC_UPDATE_CLAUSES (stmt) = clauses;
23322 SET_EXPR_LOCATION (stmt, loc);
23323 add_stmt (stmt);
23324}
23325
23326/* OpenACC 2.0:
23327 # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
23328
23329 LOC is the location of the #pragma token.
23330*/
23331
23332#define OACC_WAIT_CLAUSE_MASK \
23333 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23334 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) )
23335
23336static tree
23337c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
23338{
23339 tree clauses, list = NULL_TREE, stmt = NULL_TREE;
23340
23341 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
23342 list = c_parser_oacc_wait_list (parser, clause_loc: loc, list);
23343
23344 strcpy (dest: p_name, src: " wait");
23345 clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, where: p_name);
23346 stmt = c_finish_oacc_wait (loc, list, clauses);
23347 add_stmt (stmt);
23348
23349 return stmt;
23350}
23351
23352struct c_omp_loc_tree
23353{
23354 location_t loc;
23355 tree var;
23356};
23357
23358/* Check whether the expression used in the allocator clause is declared or
23359 modified between the variable declaration and its allocate directive. */
23360static tree
23361c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
23362{
23363 tree var = ((struct c_omp_loc_tree *) data)->var;
23364 location_t loc = ((struct c_omp_loc_tree *) data)->loc;
23365 if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
23366 {
23367 if (linemap_location_before_p (set: line_table, DECL_SOURCE_LOCATION (var),
23368 DECL_SOURCE_LOCATION (*tp)))
23369 {
23370 error_at (loc, "variable %qD used in the %<allocator%> clause must "
23371 "be declared before %qD", *tp, var);
23372 inform (DECL_SOURCE_LOCATION (*tp), "declared here");
23373 inform (DECL_SOURCE_LOCATION (var),
23374 "to be allocated variable declared here");
23375 return *tp;
23376 }
23377 else
23378 {
23379 gcc_assert (cur_stmt_list
23380 && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
23381
23382 tree_stmt_iterator l = tsi_last (cur_stmt_list);
23383 while (!tsi_end_p (i: l))
23384 {
23385 if (linemap_location_before_p (set: line_table, EXPR_LOCATION (*l),
23386 DECL_SOURCE_LOCATION (var)))
23387 break;
23388 if (TREE_CODE (*l) == MODIFY_EXPR
23389 && TREE_OPERAND (*l, 0) == *tp)
23390 {
23391 error_at (loc,
23392 "variable %qD used in the %<allocator%> clause "
23393 "must not be modified between declaration of %qD "
23394 "and its %<allocate%> directive", *tp, var);
23395 inform (EXPR_LOCATION (*l), "modified here");
23396 inform (DECL_SOURCE_LOCATION (var),
23397 "to be allocated variable declared here");
23398 return *tp;
23399 }
23400 --l;
23401 }
23402 }
23403 }
23404 return NULL_TREE;
23405}
23406
23407/* OpenMP 5.x:
23408 # pragma omp allocate (list) clauses
23409
23410 OpenMP 5.0 clause:
23411 allocator (omp_allocator_handle_t expression)
23412
23413 OpenMP 5.1 additional clause:
23414 align (constant-expression)] */
23415
23416static void
23417c_parser_omp_allocate (c_parser *parser)
23418{
23419 tree alignment = NULL_TREE;
23420 tree allocator = NULL_TREE;
23421 c_parser_consume_pragma (parser);
23422 location_t loc = c_parser_peek_token (parser)->location;
23423 location_t allocator_loc = UNKNOWN_LOCATION;
23424 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE);
23425 do
23426 {
23427 if (c_parser_next_token_is (parser, type: CPP_COMMA)
23428 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23429 c_parser_consume_token (parser);
23430 if (!c_parser_next_token_is (parser, type: CPP_NAME))
23431 break;
23432 matching_parens parens;
23433 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23434 c_parser_consume_token (parser);
23435 location_t expr_loc = c_parser_peek_token (parser)->location;
23436 if (strcmp (s1: "align", s2: p) != 0 && strcmp (s1: "allocator", s2: p) != 0)
23437 {
23438 error_at (c_parser_peek_token (parser)->location,
23439 "expected %<allocator%> or %<align%>");
23440 break;
23441 }
23442 if (!parens.require_open (parser))
23443 break;
23444
23445 c_expr expr = c_parser_expr_no_commas (parser, NULL);
23446 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
23447 expr_loc = c_parser_peek_token (parser)->location;
23448 if (expr.value == error_mark_node)
23449 ;
23450 else if (p[2] == 'i' && alignment)
23451 {
23452 error_at (expr_loc, "too many %qs clauses", "align");
23453 break;
23454 }
23455 else if (p[2] == 'i')
23456 {
23457 alignment = c_fully_fold (expr.value, false, NULL);
23458 if (TREE_CODE (alignment) != INTEGER_CST
23459 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
23460 || tree_int_cst_sgn (alignment) != 1
23461 || !integer_pow2p (alignment))
23462 {
23463 error_at (expr_loc, "%<align%> clause argument needs to be "
23464 "positive constant power of two integer "
23465 "expression");
23466 alignment = NULL_TREE;
23467 }
23468 }
23469 else if (allocator)
23470 {
23471 error_at (expr_loc, "too many %qs clauses", "allocator");
23472 break;
23473 }
23474 else
23475 {
23476 allocator = c_fully_fold (expr.value, false, NULL);
23477 allocator_loc = expr_loc;
23478 tree orig_type
23479 = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
23480 orig_type = TYPE_MAIN_VARIANT (orig_type);
23481 if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
23482 || TREE_CODE (orig_type) != ENUMERAL_TYPE
23483 || TYPE_NAME (orig_type)
23484 != get_identifier ("omp_allocator_handle_t"))
23485 {
23486 error_at (expr_loc,
23487 "%<allocator%> clause allocator expression has type "
23488 "%qT rather than %<omp_allocator_handle_t%>",
23489 TREE_TYPE (allocator));
23490 allocator = NULL_TREE;
23491 }
23492 }
23493 parens.skip_until_found_close (parser);
23494 } while (true);
23495 c_parser_skip_to_pragma_eol (parser);
23496
23497 c_mark_decl_jump_unsafe_in_current_scope ();
23498 for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
23499 {
23500 tree var = OMP_CLAUSE_DECL (c);
23501 if (TREE_CODE (var) == PARM_DECL)
23502 {
23503 error_at (OMP_CLAUSE_LOCATION (nl),
23504 "function parameter %qD may not appear as list item in an "
23505 "%<allocate%> directive", var);
23506 continue;
23507 }
23508 if (!parser->in_omp_decl_attribute && !c_check_in_current_scope (var))
23509 {
23510 error_at (OMP_CLAUSE_LOCATION (nl),
23511 "%<allocate%> directive must be in the same scope as %qD",
23512 var);
23513 inform (DECL_SOURCE_LOCATION (var), "declared here");
23514 continue;
23515 }
23516 if (lookup_attribute (attr_name: "omp allocate", DECL_ATTRIBUTES (var)))
23517 {
23518 error_at (OMP_CLAUSE_LOCATION (nl),
23519 "%qD already appeared as list item in an "
23520 "%<allocate%> directive", var);
23521 continue;
23522 }
23523 if (TREE_STATIC (var))
23524 {
23525 if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
23526 {
23527 error_at (loc,
23528 "%<allocator%> clause required for "
23529 "static variable %qD", var);
23530 continue;
23531 }
23532 else if (allocator
23533 && (wi::to_widest (t: allocator) < 1
23534 || wi::to_widest (t: allocator) > GOMP_OMP_PREDEF_ALLOC_MAX)
23535 && (wi::to_widest (t: allocator) < GOMP_OMPX_PREDEF_ALLOC_MIN
23536 || wi::to_widest (t: allocator) > GOMP_OMPX_PREDEF_ALLOC_MAX))
23537 {
23538 error_at (allocator_loc,
23539 "%<allocator%> clause requires a predefined allocator as "
23540 "%qD is static", var);
23541 }
23542 }
23543 if (allocator)
23544 {
23545 struct c_omp_loc_tree data
23546 = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), .var: var};
23547 walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
23548 }
23549 DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
23550 build_tree_list (allocator, alignment),
23551 DECL_ATTRIBUTES (var));
23552 }
23553}
23554
23555/* OpenMP 2.5:
23556 # pragma omp atomic new-line
23557 expression-stmt
23558
23559 expression-stmt:
23560 x binop= expr | x++ | ++x | x-- | --x
23561 binop:
23562 +, *, -, /, &, ^, |, <<, >>
23563
23564 where x is an lvalue expression with scalar type.
23565
23566 OpenMP 3.1:
23567 # pragma omp atomic new-line
23568 update-stmt
23569
23570 # pragma omp atomic read new-line
23571 read-stmt
23572
23573 # pragma omp atomic write new-line
23574 write-stmt
23575
23576 # pragma omp atomic update new-line
23577 update-stmt
23578
23579 # pragma omp atomic capture new-line
23580 capture-stmt
23581
23582 # pragma omp atomic capture new-line
23583 capture-block
23584
23585 read-stmt:
23586 v = x
23587 write-stmt:
23588 x = expr
23589 update-stmt:
23590 expression-stmt | x = x binop expr
23591 capture-stmt:
23592 v = expression-stmt
23593 capture-block:
23594 { v = x; update-stmt; } | { update-stmt; v = x; }
23595
23596 OpenMP 4.0:
23597 update-stmt:
23598 expression-stmt | x = x binop expr | x = expr binop x
23599 capture-stmt:
23600 v = update-stmt
23601 capture-block:
23602 { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
23603
23604 OpenMP 5.1:
23605 # pragma omp atomic compare new-line
23606 conditional-update-atomic
23607
23608 # pragma omp atomic compare capture new-line
23609 conditional-update-capture-atomic
23610
23611 conditional-update-atomic:
23612 cond-expr-stmt | cond-update-stmt
23613 cond-expr-stmt:
23614 x = expr ordop x ? expr : x;
23615 x = x ordop expr ? expr : x;
23616 x = x == e ? d : x;
23617 cond-update-stmt:
23618 if (expr ordop x) { x = expr; }
23619 if (x ordop expr) { x = expr; }
23620 if (x == e) { x = d; }
23621 ordop:
23622 <, >
23623 conditional-update-capture-atomic:
23624 v = cond-expr-stmt
23625 { v = x; cond-expr-stmt }
23626 { cond-expr-stmt v = x; }
23627 { v = x; cond-update-stmt }
23628 { cond-update-stmt v = x; }
23629 if (x == e) { x = d; } else { v = x; }
23630 { r = x == e; if (r) { x = d; } }
23631 { r = x == e; if (r) { x = d; } else { v = x; } }
23632
23633 where x, r and v are lvalue expressions with scalar type,
23634 expr, e and d are expressions with scalar type and e might be
23635 the same as v.
23636
23637 LOC is the location of the #pragma token. */
23638
23639static void
23640c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
23641{
23642 tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
23643 tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
23644 tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
23645 enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
23646 enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
23647 struct c_expr expr;
23648 location_t eloc;
23649 bool structured_block = false;
23650 bool swapped = false;
23651 bool non_lvalue_p;
23652 tree clauses = NULL_TREE;
23653 bool capture = false;
23654 bool compare = false;
23655 bool weak = false;
23656 enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23657 bool no_semicolon = false;
23658 bool extra_scope = false;
23659
23660 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
23661 {
23662 if (c_parser_next_token_is (parser, type: CPP_COMMA)
23663 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23664 c_parser_consume_token (parser);
23665
23666 if (c_parser_next_token_is (parser, type: CPP_NAME))
23667 {
23668 const char *p
23669 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23670 location_t cloc = c_parser_peek_token (parser)->location;
23671 enum tree_code new_code = ERROR_MARK;
23672 enum omp_memory_order new_memory_order
23673 = OMP_MEMORY_ORDER_UNSPECIFIED;
23674 bool new_capture = false;
23675 bool new_compare = false;
23676 bool new_weak = false;
23677 enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23678
23679 if (!strcmp (s1: p, s2: "read"))
23680 new_code = OMP_ATOMIC_READ;
23681 else if (!strcmp (s1: p, s2: "write"))
23682 new_code = NOP_EXPR;
23683 else if (!strcmp (s1: p, s2: "update"))
23684 new_code = OMP_ATOMIC;
23685 else if (openacc && !strcmp (s1: p, s2: "capture"))
23686 new_code = OMP_ATOMIC_CAPTURE_NEW;
23687 else if (openacc)
23688 {
23689 p = NULL;
23690 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23691 "or %<capture%> clause");
23692 }
23693 else if (!strcmp (s1: p, s2: "capture"))
23694 new_capture = true;
23695 else if (!strcmp (s1: p, s2: "compare"))
23696 new_compare = true;
23697 else if (!strcmp (s1: p, s2: "weak"))
23698 new_weak = true;
23699 else if (!strcmp (s1: p, s2: "fail"))
23700 {
23701 matching_parens parens;
23702
23703 c_parser_consume_token (parser);
23704 if (!parens.require_open (parser))
23705 continue;
23706
23707 if (c_parser_next_token_is (parser, type: CPP_NAME))
23708 {
23709 const char *q
23710 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23711
23712 if (!strcmp (s1: q, s2: "seq_cst"))
23713 new_fail = OMP_MEMORY_ORDER_SEQ_CST;
23714 else if (!strcmp (s1: q, s2: "acquire"))
23715 new_fail = OMP_MEMORY_ORDER_ACQUIRE;
23716 else if (!strcmp (s1: q, s2: "relaxed"))
23717 new_fail = OMP_MEMORY_ORDER_RELAXED;
23718 }
23719
23720 if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23721 {
23722 c_parser_consume_token (parser);
23723 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23724 error_at (cloc, "too many %qs clauses", "fail");
23725 else
23726 fail = new_fail;
23727 }
23728 else
23729 c_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> "
23730 "or %<relaxed%>");
23731 parens.skip_until_found_close (parser);
23732 continue;
23733 }
23734 else if (!strcmp (s1: p, s2: "seq_cst"))
23735 new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23736 else if (!strcmp (s1: p, s2: "acq_rel"))
23737 new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23738 else if (!strcmp (s1: p, s2: "release"))
23739 new_memory_order = OMP_MEMORY_ORDER_RELEASE;
23740 else if (!strcmp (s1: p, s2: "acquire"))
23741 new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23742 else if (!strcmp (s1: p, s2: "relaxed"))
23743 new_memory_order = OMP_MEMORY_ORDER_RELAXED;
23744 else if (!strcmp (s1: p, s2: "hint"))
23745 {
23746 c_parser_consume_token (parser);
23747 clauses = c_parser_omp_clause_hint (parser, list: clauses);
23748 continue;
23749 }
23750 else
23751 {
23752 p = NULL;
23753 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23754 "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
23755 "%<seq_cst%>, %<acq_rel%>, %<release%>, "
23756 "%<relaxed%> or %<hint%> clause");
23757 }
23758 if (p)
23759 {
23760 if (new_code != ERROR_MARK)
23761 {
23762 /* OpenACC permits 'update capture'. */
23763 if (openacc
23764 && code == OMP_ATOMIC
23765 && new_code == OMP_ATOMIC_CAPTURE_NEW)
23766 code = new_code;
23767 else if (code != ERROR_MARK)
23768 error_at (cloc, "too many atomic clauses");
23769 else
23770 code = new_code;
23771 }
23772 else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23773 {
23774 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23775 error_at (cloc, "too many memory order clauses");
23776 else
23777 memory_order = new_memory_order;
23778 }
23779 else if (new_capture)
23780 {
23781 if (capture)
23782 error_at (cloc, "too many %qs clauses", "capture");
23783 else
23784 capture = true;
23785 }
23786 else if (new_compare)
23787 {
23788 if (compare)
23789 error_at (cloc, "too many %qs clauses", "compare");
23790 else
23791 compare = true;
23792 }
23793 else if (new_weak)
23794 {
23795 if (weak)
23796 error_at (cloc, "too many %qs clauses", "weak");
23797 else
23798 weak = true;
23799 }
23800 c_parser_consume_token (parser);
23801 continue;
23802 }
23803 }
23804 break;
23805 }
23806 c_parser_skip_to_pragma_eol (parser);
23807
23808 if (code == ERROR_MARK)
23809 code = OMP_ATOMIC;
23810 if (capture)
23811 {
23812 if (code != OMP_ATOMIC)
23813 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23814 "clauses", "capture");
23815 else
23816 code = OMP_ATOMIC_CAPTURE_NEW;
23817 }
23818 if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
23819 {
23820 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23821 "clauses", "compare");
23822 compare = false;
23823 }
23824 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
23825 {
23826 error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
23827 fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23828 }
23829 if (weak && !compare)
23830 {
23831 error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
23832 weak = false;
23833 }
23834 if (openacc)
23835 memory_order = OMP_MEMORY_ORDER_RELAXED;
23836 else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
23837 {
23838 omp_requires_mask
23839 = (enum omp_requires) (omp_requires_mask
23840 | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
23841 switch ((enum omp_memory_order)
23842 (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
23843 {
23844 case OMP_MEMORY_ORDER_UNSPECIFIED:
23845 case OMP_MEMORY_ORDER_RELAXED:
23846 memory_order = OMP_MEMORY_ORDER_RELAXED;
23847 break;
23848 case OMP_MEMORY_ORDER_SEQ_CST:
23849 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23850 break;
23851 case OMP_MEMORY_ORDER_ACQUIRE:
23852 if (code == NOP_EXPR) /* atomic write */
23853 {
23854 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23855 "%<acquire%> clause implicitly provided by a "
23856 "%<requires%> directive");
23857 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23858 }
23859 else
23860 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23861 break;
23862 case OMP_MEMORY_ORDER_RELEASE:
23863 if (code == OMP_ATOMIC_READ)
23864 {
23865 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23866 "%<release%> clause implicitly provided by a "
23867 "%<requires%> directive");
23868 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23869 }
23870 else
23871 memory_order = OMP_MEMORY_ORDER_RELEASE;
23872 break;
23873 case OMP_MEMORY_ORDER_ACQ_REL:
23874 switch (code)
23875 {
23876 case OMP_ATOMIC_READ:
23877 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23878 break;
23879 case NOP_EXPR: /* atomic write */
23880 memory_order = OMP_MEMORY_ORDER_RELEASE;
23881 break;
23882 default:
23883 memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23884 break;
23885 }
23886 break;
23887 default:
23888 gcc_unreachable ();
23889 }
23890 }
23891 else
23892 switch (code)
23893 {
23894 case OMP_ATOMIC_READ:
23895 if (memory_order == OMP_MEMORY_ORDER_RELEASE)
23896 {
23897 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23898 "%<release%> clause");
23899 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23900 }
23901 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23902 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23903 break;
23904 case NOP_EXPR: /* atomic write */
23905 if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
23906 {
23907 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23908 "%<acquire%> clause");
23909 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23910 }
23911 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23912 memory_order = OMP_MEMORY_ORDER_RELEASE;
23913 break;
23914 default:
23915 break;
23916 }
23917 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23918 memory_order
23919 = (enum omp_memory_order) (memory_order
23920 | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
23921
23922 switch (code)
23923 {
23924 case OMP_ATOMIC_READ:
23925 case NOP_EXPR: /* atomic write */
23926 v = c_parser_cast_expression (parser, NULL).value;
23927 non_lvalue_p = !lvalue_p (v);
23928 v = c_fully_fold (v, false, NULL, true);
23929 if (v == error_mark_node)
23930 goto saw_error;
23931 if (non_lvalue_p)
23932 v = non_lvalue (v);
23933 loc = c_parser_peek_token (parser)->location;
23934 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23935 goto saw_error;
23936 if (code == NOP_EXPR)
23937 {
23938 eloc = c_parser_peek_token (parser)->location;
23939 expr = c_parser_expression (parser);
23940 expr = default_function_array_read_conversion (eloc, expr);
23941 /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
23942 opcode. */
23943 code = OMP_ATOMIC;
23944 lhs = v;
23945 v = NULL_TREE;
23946 rhs = c_fully_fold (expr.value, false, NULL);
23947 if (rhs == error_mark_node)
23948 goto saw_error;
23949 }
23950 else
23951 {
23952 lhs = c_parser_cast_expression (parser, NULL).value;
23953 non_lvalue_p = !lvalue_p (lhs);
23954 lhs = c_fully_fold (lhs, false, NULL, true);
23955 if (lhs == error_mark_node)
23956 goto saw_error;
23957 if (non_lvalue_p)
23958 lhs = non_lvalue (lhs);
23959 }
23960 goto done;
23961 case OMP_ATOMIC_CAPTURE_NEW:
23962 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
23963 {
23964 c_parser_consume_token (parser);
23965 structured_block = true;
23966 }
23967 else if (compare
23968 && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23969 break;
23970 else
23971 {
23972 v = c_parser_cast_expression (parser, NULL).value;
23973 non_lvalue_p = !lvalue_p (v);
23974 v = c_fully_fold (v, false, NULL, true);
23975 if (v == error_mark_node)
23976 goto saw_error;
23977 if (non_lvalue_p)
23978 v = non_lvalue (v);
23979 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23980 goto saw_error;
23981 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23982 {
23983 eloc = c_parser_peek_token (parser)->location;
23984 error_at (eloc, "expected expression");
23985 goto saw_error;
23986 }
23987 }
23988 break;
23989 default:
23990 break;
23991 }
23992
23993 /* For structured_block case we don't know yet whether
23994 old or new x should be captured. */
23995restart:
23996 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23997 {
23998 c_parser_consume_token (parser);
23999
24000 matching_parens parens;
24001 if (!parens.require_open (parser))
24002 goto saw_error;
24003 eloc = c_parser_peek_token (parser)->location;
24004 c_expr cmp_expr;
24005 if (r)
24006 {
24007 cmp_expr = c_parser_cast_expression (parser, NULL);
24008 cmp_expr = default_function_array_conversion (eloc, cmp_expr);
24009 }
24010 else
24011 cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
24012 parens.skip_until_found_close (parser);
24013 if (cmp_expr.value == error_mark_node)
24014 goto saw_error;
24015 if (r)
24016 {
24017 if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
24018 goto bad_if;
24019 cmp_expr.value = rhs1;
24020 rhs1 = NULL_TREE;
24021 gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
24022 }
24023 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24024 ;
24025 else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
24026 {
24027 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
24028 "expected %<==%> comparison in %<if%> condition");
24029 goto saw_error;
24030 }
24031 else if (TREE_CODE (cmp_expr.value) != GT_EXPR
24032 && TREE_CODE (cmp_expr.value) != LT_EXPR)
24033 {
24034 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
24035 "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
24036 "condition");
24037 goto saw_error;
24038 }
24039 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
24040 goto saw_error;
24041
24042 extra_scope = true;
24043 eloc = c_parser_peek_token (parser)->location;
24044 expr = c_parser_cast_expression (parser, NULL);
24045 lhs = expr.value;
24046 expr = default_function_array_conversion (eloc, expr);
24047 unfolded_lhs = expr.value;
24048 lhs = c_fully_fold (lhs, false, NULL, true);
24049 orig_lhs = lhs;
24050 if (lhs == error_mark_node)
24051 goto saw_error;
24052 if (!lvalue_p (unfolded_lhs))
24053 lhs = non_lvalue (lhs);
24054 if (!c_parser_next_token_is (parser, type: CPP_EQ))
24055 {
24056 c_parser_error (parser, gmsgid: "expected %<=%>");
24057 goto saw_error;
24058 }
24059 c_parser_consume_token (parser);
24060 eloc = c_parser_peek_token (parser)->location;
24061 expr = c_parser_expr_no_commas (parser, NULL);
24062 rhs1 = expr.value;
24063
24064 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
24065 goto saw_error;
24066
24067 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
24068 goto saw_error;
24069
24070 extra_scope = false;
24071 no_semicolon = true;
24072
24073 if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
24074 {
24075 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24076 {
24077 opcode = COND_EXPR;
24078 rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
24079 false, NULL, true);
24080 rhs1 = c_fully_fold (rhs1, false, NULL, true);
24081 }
24082 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
24083 {
24084 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
24085 ? MIN_EXPR : MAX_EXPR);
24086 rhs = c_fully_fold (rhs1, false, NULL, true);
24087 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
24088 false, NULL, true);
24089 }
24090 else
24091 goto bad_if;
24092 }
24093 else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24094 goto bad_if;
24095 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
24096 && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
24097 {
24098 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
24099 ? MAX_EXPR : MIN_EXPR);
24100 rhs = c_fully_fold (rhs1, false, NULL, true);
24101 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
24102 false, NULL, true);
24103 }
24104 else
24105 {
24106 bad_if:
24107 c_parser_error (parser,
24108 gmsgid: "invalid form of %<#pragma omp atomic compare%>");
24109 goto saw_error;
24110 }
24111
24112 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
24113 {
24114 if (code != OMP_ATOMIC_CAPTURE_NEW
24115 || (structured_block && r == NULL_TREE)
24116 || TREE_CODE (cmp_expr.value) != EQ_EXPR)
24117 {
24118 eloc = c_parser_peek_token (parser)->location;
24119 error_at (eloc, "unexpected %<else%>");
24120 goto saw_error;
24121 }
24122
24123 c_parser_consume_token (parser);
24124
24125 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
24126 goto saw_error;
24127
24128 extra_scope = true;
24129 v = c_parser_cast_expression (parser, NULL).value;
24130 non_lvalue_p = !lvalue_p (v);
24131 v = c_fully_fold (v, false, NULL, true);
24132 if (v == error_mark_node)
24133 goto saw_error;
24134 if (non_lvalue_p)
24135 v = non_lvalue (v);
24136 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
24137 goto saw_error;
24138
24139 expr = c_parser_expr_no_commas (parser, NULL);
24140
24141 if (!c_tree_equal (expr.value, unfolded_lhs))
24142 goto bad_if;
24143
24144 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
24145 goto saw_error;
24146
24147 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
24148 goto saw_error;
24149
24150 extra_scope = false;
24151 code = OMP_ATOMIC_CAPTURE_OLD;
24152 if (r == NULL_TREE)
24153 /* Signal to c_finish_omp_atomic that in
24154 if (x == e) { x = d; } else { v = x; }
24155 case the store to v should be conditional. */
24156 r = void_list_node;
24157 }
24158 else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24159 {
24160 c_parser_require_keyword (parser, keyword: RID_ELSE, msgid: "expected %<else%>");
24161 goto saw_error;
24162 }
24163 else if (code == OMP_ATOMIC_CAPTURE_NEW
24164 && r != NULL_TREE
24165 && v == NULL_TREE)
24166 code = OMP_ATOMIC;
24167 goto stmt_done;
24168 }
24169 eloc = c_parser_peek_token (parser)->location;
24170 expr = c_parser_cast_expression (parser, NULL);
24171 lhs = expr.value;
24172 expr = default_function_array_conversion (eloc, expr);
24173 unfolded_lhs = expr.value;
24174 lhs = c_fully_fold (lhs, false, NULL, true);
24175 orig_lhs = lhs;
24176 switch (TREE_CODE (lhs))
24177 {
24178 invalid_compare:
24179 error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
24180 /* FALLTHRU */
24181 case ERROR_MARK:
24182 saw_error:
24183 c_parser_skip_to_end_of_block_or_statement (parser);
24184 if (extra_scope && c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24185 c_parser_consume_token (parser);
24186 if (structured_block)
24187 {
24188 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24189 c_parser_consume_token (parser);
24190 else if (code == OMP_ATOMIC_CAPTURE_NEW)
24191 {
24192 c_parser_skip_to_end_of_block_or_statement (parser);
24193 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24194 c_parser_consume_token (parser);
24195 }
24196 }
24197 return;
24198
24199 case POSTINCREMENT_EXPR:
24200 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24201 code = OMP_ATOMIC_CAPTURE_OLD;
24202 /* FALLTHROUGH */
24203 case PREINCREMENT_EXPR:
24204 lhs = TREE_OPERAND (lhs, 0);
24205 unfolded_lhs = NULL_TREE;
24206 opcode = PLUS_EXPR;
24207 rhs = integer_one_node;
24208 if (compare)
24209 goto invalid_compare;
24210 break;
24211
24212 case POSTDECREMENT_EXPR:
24213 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24214 code = OMP_ATOMIC_CAPTURE_OLD;
24215 /* FALLTHROUGH */
24216 case PREDECREMENT_EXPR:
24217 lhs = TREE_OPERAND (lhs, 0);
24218 unfolded_lhs = NULL_TREE;
24219 opcode = MINUS_EXPR;
24220 rhs = integer_one_node;
24221 if (compare)
24222 goto invalid_compare;
24223 break;
24224
24225 case COMPOUND_EXPR:
24226 if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
24227 && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
24228 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
24229 && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
24230 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
24231 (TREE_OPERAND (lhs, 1), 0), 0))))
24232 /* Undo effects of boolean_increment for post {in,de}crement. */
24233 lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
24234 /* FALLTHRU */
24235 case MODIFY_EXPR:
24236 if (TREE_CODE (lhs) == MODIFY_EXPR
24237 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
24238 {
24239 /* Undo effects of boolean_increment. */
24240 if (integer_onep (TREE_OPERAND (lhs, 1)))
24241 {
24242 /* This is pre or post increment. */
24243 rhs = TREE_OPERAND (lhs, 1);
24244 lhs = TREE_OPERAND (lhs, 0);
24245 unfolded_lhs = NULL_TREE;
24246 opcode = NOP_EXPR;
24247 if (code == OMP_ATOMIC_CAPTURE_NEW
24248 && !structured_block
24249 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
24250 code = OMP_ATOMIC_CAPTURE_OLD;
24251 if (compare)
24252 goto invalid_compare;
24253 break;
24254 }
24255 if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
24256 && TREE_OPERAND (lhs, 0)
24257 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
24258 {
24259 /* This is pre or post decrement. */
24260 rhs = TREE_OPERAND (lhs, 1);
24261 lhs = TREE_OPERAND (lhs, 0);
24262 unfolded_lhs = NULL_TREE;
24263 opcode = NOP_EXPR;
24264 if (code == OMP_ATOMIC_CAPTURE_NEW
24265 && !structured_block
24266 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
24267 code = OMP_ATOMIC_CAPTURE_OLD;
24268 if (compare)
24269 goto invalid_compare;
24270 break;
24271 }
24272 }
24273 /* FALLTHRU */
24274 default:
24275 if (!lvalue_p (unfolded_lhs))
24276 lhs = non_lvalue (lhs);
24277 if (compare && !c_parser_next_token_is (parser, type: CPP_EQ))
24278 {
24279 c_parser_error (parser, gmsgid: "expected %<=%>");
24280 goto saw_error;
24281 }
24282 switch (c_parser_peek_token (parser)->type)
24283 {
24284 case CPP_MULT_EQ:
24285 opcode = MULT_EXPR;
24286 break;
24287 case CPP_DIV_EQ:
24288 opcode = TRUNC_DIV_EXPR;
24289 break;
24290 case CPP_PLUS_EQ:
24291 opcode = PLUS_EXPR;
24292 break;
24293 case CPP_MINUS_EQ:
24294 opcode = MINUS_EXPR;
24295 break;
24296 case CPP_LSHIFT_EQ:
24297 opcode = LSHIFT_EXPR;
24298 break;
24299 case CPP_RSHIFT_EQ:
24300 opcode = RSHIFT_EXPR;
24301 break;
24302 case CPP_AND_EQ:
24303 opcode = BIT_AND_EXPR;
24304 break;
24305 case CPP_OR_EQ:
24306 opcode = BIT_IOR_EXPR;
24307 break;
24308 case CPP_XOR_EQ:
24309 opcode = BIT_XOR_EXPR;
24310 break;
24311 case CPP_EQ:
24312 c_parser_consume_token (parser);
24313 eloc = c_parser_peek_token (parser)->location;
24314 expr = c_parser_expr_no_commas (parser, NULL, omp_atomic_lhs: unfolded_lhs);
24315 rhs1 = expr.value;
24316 switch (TREE_CODE (rhs1))
24317 {
24318 case MULT_EXPR:
24319 case TRUNC_DIV_EXPR:
24320 case RDIV_EXPR:
24321 case PLUS_EXPR:
24322 case MINUS_EXPR:
24323 case LSHIFT_EXPR:
24324 case RSHIFT_EXPR:
24325 case BIT_AND_EXPR:
24326 case BIT_IOR_EXPR:
24327 case BIT_XOR_EXPR:
24328 if (compare)
24329 break;
24330 if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
24331 {
24332 opcode = TREE_CODE (rhs1);
24333 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24334 true);
24335 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
24336 true);
24337 goto stmt_done;
24338 }
24339 if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
24340 {
24341 opcode = TREE_CODE (rhs1);
24342 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
24343 true);
24344 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24345 true);
24346 swapped = !commutative_tree_code (opcode);
24347 goto stmt_done;
24348 }
24349 break;
24350 case COND_EXPR:
24351 if (!compare)
24352 break;
24353 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
24354 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
24355 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
24356 break;
24357 if (!TREE_OPERAND (rhs1, 1))
24358 break;
24359 if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
24360 break;
24361 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
24362 unfolded_lhs))
24363 {
24364 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
24365 {
24366 opcode = COND_EXPR;
24367 rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24368 0), 1),
24369 false, NULL, true);
24370 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
24371 NULL, true);
24372 goto stmt_done;
24373 }
24374 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
24375 TREE_OPERAND (rhs1, 1)))
24376 {
24377 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
24378 ? MIN_EXPR : MAX_EXPR);
24379 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24380 true);
24381 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24382 0), 0),
24383 false, NULL, true);
24384 goto stmt_done;
24385 }
24386 }
24387 else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
24388 break;
24389 else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
24390 unfolded_lhs))
24391 {
24392 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
24393 TREE_OPERAND (rhs1, 1)))
24394 {
24395 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
24396 ? MAX_EXPR : MIN_EXPR);
24397 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24398 true);
24399 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24400 0), 1),
24401 false, NULL, true);
24402 goto stmt_done;
24403 }
24404 }
24405 break;
24406 case EQ_EXPR:
24407 if (!compare
24408 || code != OMP_ATOMIC_CAPTURE_NEW
24409 || !structured_block
24410 || v
24411 || r)
24412 break;
24413 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
24414 && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
24415 {
24416 r = lhs;
24417 lhs = NULL_TREE;
24418 c_parser_consume_token (parser);
24419 goto restart;
24420 }
24421 break;
24422 case ERROR_MARK:
24423 goto saw_error;
24424 default:
24425 break;
24426 }
24427 if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
24428 {
24429 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
24430 {
24431 code = OMP_ATOMIC_CAPTURE_OLD;
24432 v = lhs;
24433 lhs = NULL_TREE;
24434 expr = default_function_array_read_conversion (eloc, expr);
24435 unfolded_lhs1 = expr.value;
24436 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
24437 rhs1 = NULL_TREE;
24438 c_parser_consume_token (parser);
24439 goto restart;
24440 }
24441 if (structured_block && !compare)
24442 {
24443 opcode = NOP_EXPR;
24444 expr = default_function_array_read_conversion (eloc, expr);
24445 rhs = c_fully_fold (expr.value, false, NULL, true);
24446 rhs1 = NULL_TREE;
24447 goto stmt_done;
24448 }
24449 }
24450 c_parser_error (parser, gmsgid: "invalid form of %<#pragma omp atomic%>");
24451 goto saw_error;
24452 default:
24453 c_parser_error (parser,
24454 gmsgid: "invalid operator for %<#pragma omp atomic%>");
24455 goto saw_error;
24456 }
24457
24458 /* Arrange to pass the location of the assignment operator to
24459 c_finish_omp_atomic. */
24460 loc = c_parser_peek_token (parser)->location;
24461 c_parser_consume_token (parser);
24462 eloc = c_parser_peek_token (parser)->location;
24463 expr = c_parser_expression (parser);
24464 expr = default_function_array_read_conversion (eloc, expr);
24465 rhs = expr.value;
24466 rhs = c_fully_fold (rhs, false, NULL, true);
24467 break;
24468 }
24469stmt_done:
24470 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
24471 {
24472 if (!no_semicolon
24473 && !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
24474 goto saw_error;
24475 no_semicolon = false;
24476 v = c_parser_cast_expression (parser, NULL).value;
24477 non_lvalue_p = !lvalue_p (v);
24478 v = c_fully_fold (v, false, NULL, true);
24479 if (v == error_mark_node)
24480 goto saw_error;
24481 if (non_lvalue_p)
24482 v = non_lvalue (v);
24483 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
24484 goto saw_error;
24485 eloc = c_parser_peek_token (parser)->location;
24486 expr = c_parser_cast_expression (parser, NULL);
24487 lhs1 = expr.value;
24488 expr = default_function_array_read_conversion (eloc, expr);
24489 unfolded_lhs1 = expr.value;
24490 lhs1 = c_fully_fold (lhs1, false, NULL, true);
24491 if (lhs1 == error_mark_node)
24492 goto saw_error;
24493 if (!lvalue_p (unfolded_lhs1))
24494 lhs1 = non_lvalue (lhs1);
24495 }
24496 if (structured_block)
24497 {
24498 if (!no_semicolon)
24499 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
24500 c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>");
24501 }
24502done:
24503 if (weak && opcode != COND_EXPR)
24504 {
24505 error_at (loc, "%<weak%> clause requires atomic equality comparison");
24506 weak = false;
24507 }
24508 if (unfolded_lhs && unfolded_lhs1
24509 && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
24510 {
24511 error ("%<#pragma omp atomic capture%> uses two different "
24512 "expressions for memory");
24513 stmt = error_mark_node;
24514 }
24515 else
24516 stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
24517 swapped, memory_order, weak);
24518 if (stmt != error_mark_node)
24519 add_stmt (stmt);
24520
24521 if (!structured_block && !no_semicolon)
24522 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
24523}
24524
24525
24526/* OpenMP 2.5:
24527 # pragma omp barrier new-line
24528*/
24529
24530static void
24531c_parser_omp_barrier (c_parser *parser)
24532{
24533 location_t loc = c_parser_peek_token (parser)->location;
24534 c_parser_consume_pragma (parser);
24535 c_parser_skip_to_pragma_eol (parser);
24536
24537 c_finish_omp_barrier (loc);
24538}
24539
24540/* OpenMP 2.5:
24541 # pragma omp critical [(name)] new-line
24542 structured-block
24543
24544 OpenMP 4.5:
24545 # pragma omp critical [(name) [hint(expression)]] new-line
24546
24547 LOC is the location of the #pragma itself. */
24548
24549#define OMP_CRITICAL_CLAUSE_MASK \
24550 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
24551
24552static tree
24553c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
24554{
24555 tree stmt, name = NULL_TREE, clauses = NULL_TREE;
24556
24557 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24558 {
24559 c_parser_consume_token (parser);
24560 if (c_parser_next_token_is (parser, type: CPP_NAME))
24561 {
24562 name = c_parser_peek_token (parser)->value;
24563 c_parser_consume_token (parser);
24564 c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
24565 }
24566 else
24567 c_parser_error (parser, gmsgid: "expected identifier");
24568
24569 if (c_parser_next_token_is (parser, type: CPP_COMMA)
24570 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24571 c_parser_consume_token (parser);
24572 }
24573 clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
24574 where: "#pragma omp critical");
24575 stmt = c_parser_omp_structured_block (parser, if_p);
24576 return c_finish_omp_critical (loc, stmt, name, clauses);
24577}
24578
24579/* OpenMP 5.0:
24580 # pragma omp depobj ( depobj ) depobj-clause new-line
24581
24582 depobj-clause:
24583 depend (dependence-type : locator)
24584 destroy
24585 update (dependence-type)
24586
24587 OpenMP 5.2 additionally:
24588 destroy ( depobj )
24589
24590 dependence-type:
24591 in
24592 out
24593 inout
24594 mutexinout */
24595
24596static void
24597c_parser_omp_depobj (c_parser *parser)
24598{
24599 location_t loc = c_parser_peek_token (parser)->location;
24600 c_parser_consume_pragma (parser);
24601 matching_parens parens;
24602 if (!parens.require_open (parser))
24603 {
24604 c_parser_skip_to_pragma_eol (parser);
24605 return;
24606 }
24607
24608 tree depobj = c_parser_expr_no_commas (parser, NULL).value;
24609 if (depobj != error_mark_node)
24610 {
24611 if (!lvalue_p (depobj))
24612 {
24613 error_at (EXPR_LOC_OR_LOC (depobj, loc),
24614 "%<depobj%> expression is not lvalue expression");
24615 depobj = error_mark_node;
24616 }
24617 else
24618 {
24619 tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
24620 depobj, false);
24621 if (addr == error_mark_node)
24622 depobj = error_mark_node;
24623 else
24624 depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
24625 addr, RO_UNARY_STAR);
24626 }
24627 }
24628
24629 parens.skip_until_found_close (parser);
24630 tree clause = NULL_TREE;
24631 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
24632 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24633 c_parser_consume_token (parser);
24634 location_t c_loc = c_parser_peek_token (parser)->location;
24635 if (c_parser_next_token_is (parser, type: CPP_NAME))
24636 {
24637 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24638
24639 c_parser_consume_token (parser);
24640 if (!strcmp (s1: "depend", s2: p))
24641 {
24642 clause = c_parser_omp_clause_depend (parser, NULL_TREE, here: c_loc);
24643 clause = c_finish_omp_clauses (clause, C_ORT_OMP);
24644 if (!clause)
24645 clause = error_mark_node;
24646 }
24647 else if (!strcmp (s1: "destroy", s2: p))
24648 {
24649 matching_parens c_parens;
24650 kind = OMP_CLAUSE_DEPEND_LAST;
24651 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
24652 && c_parens.require_open (parser))
24653 {
24654 tree destobj = c_parser_expr_no_commas (parser, NULL).value;
24655 if (!lvalue_p (destobj))
24656 error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
24657 "%<destroy%> expression is not lvalue expression");
24658 else if (depobj != error_mark_node
24659 && !operand_equal_p (destobj, depobj,
24660 flags: OEP_MATCH_SIDE_EFFECTS
24661 | OEP_LEXICOGRAPHIC))
24662 warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
24663 "the %<destroy%> expression %qE should be the same "
24664 "as the %<depobj%> argument %qE", destobj, depobj);
24665 c_parens.skip_until_found_close (parser);
24666 }
24667 }
24668 else if (!strcmp (s1: "update", s2: p))
24669 {
24670 matching_parens c_parens;
24671 if (c_parens.require_open (parser))
24672 {
24673 location_t c2_loc = c_parser_peek_token (parser)->location;
24674 if (c_parser_next_token_is (parser, type: CPP_NAME))
24675 {
24676 const char *p2
24677 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24678
24679 c_parser_consume_token (parser);
24680 if (!strcmp (s1: "in", s2: p2))
24681 kind = OMP_CLAUSE_DEPEND_IN;
24682 else if (!strcmp (s1: "out", s2: p2))
24683 kind = OMP_CLAUSE_DEPEND_OUT;
24684 else if (!strcmp (s1: "inout", s2: p2))
24685 kind = OMP_CLAUSE_DEPEND_INOUT;
24686 else if (!strcmp (s1: "mutexinoutset", s2: p2))
24687 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
24688 else if (!strcmp (s1: "inoutset", s2: p2))
24689 kind = OMP_CLAUSE_DEPEND_INOUTSET;
24690 }
24691 if (kind == OMP_CLAUSE_DEPEND_INVALID)
24692 {
24693 clause = error_mark_node;
24694 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
24695 "%<mutexinoutset%> or %<inoutset%>");
24696 }
24697 c_parens.skip_until_found_close (parser);
24698 }
24699 else
24700 clause = error_mark_node;
24701 }
24702 }
24703 if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
24704 {
24705 clause = error_mark_node;
24706 error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
24707 }
24708 c_parser_skip_to_pragma_eol (parser);
24709
24710 c_finish_omp_depobj (loc, depobj, kind, clause);
24711}
24712
24713
24714/* OpenMP 2.5:
24715 # pragma omp flush flush-vars[opt] new-line
24716
24717 flush-vars:
24718 ( variable-list )
24719
24720 OpenMP 5.0:
24721 # pragma omp flush memory-order-clause new-line */
24722
24723static void
24724c_parser_omp_flush (c_parser *parser)
24725{
24726 location_t loc = c_parser_peek_token (parser)->location;
24727 c_parser_consume_pragma (parser);
24728 enum memmodel mo = MEMMODEL_LAST;
24729 if (c_parser_next_token_is (parser, type: CPP_COMMA)
24730 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24731 c_parser_consume_token (parser);
24732 if (c_parser_next_token_is (parser, type: CPP_NAME))
24733 {
24734 const char *p
24735 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24736
24737 if (!strcmp (s1: p, s2: "seq_cst"))
24738 mo = MEMMODEL_SEQ_CST;
24739 else if (!strcmp (s1: p, s2: "acq_rel"))
24740 mo = MEMMODEL_ACQ_REL;
24741 else if (!strcmp (s1: p, s2: "release"))
24742 mo = MEMMODEL_RELEASE;
24743 else if (!strcmp (s1: p, s2: "acquire"))
24744 mo = MEMMODEL_ACQUIRE;
24745 else
24746 error_at (c_parser_peek_token (parser)->location,
24747 "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
24748 "%<acquire%>");
24749 c_parser_consume_token (parser);
24750 }
24751 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24752 {
24753 if (mo != MEMMODEL_LAST)
24754 error_at (c_parser_peek_token (parser)->location,
24755 "%<flush%> list specified together with memory order "
24756 "clause");
24757 c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
24758 }
24759 else if (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
24760 c_parser_error (parser, gmsgid: "expected %<(%> or end of line");
24761 c_parser_skip_to_pragma_eol (parser);
24762
24763 c_finish_omp_flush (loc, mo);
24764}
24765
24766/* Return true if next tokens contain a standard attribute that contains
24767 omp::directive (DIRECTIVE). */
24768
24769static bool
24770c_parser_omp_section_scan (c_parser *parser, const char *directive,
24771 bool tentative)
24772{
24773 if (!c_parser_nth_token_starts_std_attributes (parser, n: 1))
24774 return false;
24775 unsigned int n = 3;
24776 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
24777 return false;
24778 c_token *token = c_parser_peek_nth_token_raw (parser, n);
24779 if (token->type != CPP_CLOSE_SQUARE)
24780 return false;
24781 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
24782 if (token->type != CPP_CLOSE_SQUARE)
24783 return false;
24784 if (n < 9)
24785 return false;
24786 if (c_parser_peek_nth_token_raw (parser, n: 3)->type == CPP_NAME
24787 && c_parser_peek_nth_token_raw (parser, n: 4)->type == CPP_OPEN_PAREN
24788 && c_parser_peek_nth_token_raw (parser, n: 5)->type == CPP_NAME)
24789 {
24790 tree first = c_parser_peek_nth_token_raw (parser, n: 3)->value;
24791 tree second = c_parser_peek_nth_token_raw (parser, n: 5)->value;
24792 if (strcmp (IDENTIFIER_POINTER (first), s2: "directive")
24793 && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__"))
24794 return false;
24795 if (strcmp (IDENTIFIER_POINTER (second), s2: directive))
24796 return false;
24797 }
24798 if (tentative)
24799 return true;
24800 location_t first_loc = c_parser_peek_token (parser)->location;
24801 location_t last_loc = c_parser_peek_nth_token_raw (parser, n: n + 1)->location;
24802 location_t middle_loc = UNKNOWN_LOCATION;
24803 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24804 bool seen = false;
24805 int cnt = 0;
24806 for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
24807 if (is_attribute_namespace_p (attr_ns: "omp", attr)
24808 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (attr)))
24809 {
24810 for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
24811 {
24812 tree d = TREE_VALUE (a);
24813 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
24814 c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
24815 cnt++;
24816 if (first->type == CPP_NAME
24817 && strcmp (IDENTIFIER_POINTER (first->value),
24818 s2: directive) == 0)
24819 {
24820 seen = true;
24821 if (middle_loc == UNKNOWN_LOCATION)
24822 middle_loc = first->location;
24823 }
24824 }
24825 }
24826 if (!seen)
24827 return false;
24828 if (cnt != 1 || TREE_CHAIN (std_attrs))
24829 {
24830 error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc),
24831 "%<[[omp::directive(%s)]]%> must be the only specified "
24832 "attribute on a statement", directive);
24833 return false;
24834 }
24835 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
24836 return true;
24837}
24838
24839/* Parse an OpenMP structured block sequence. KIND is the corresponding
24840 separating directive. */
24841
24842static tree
24843c_parser_omp_structured_block_sequence (c_parser *parser,
24844 enum pragma_kind kind)
24845{
24846 tree stmt = push_stmt_list ();
24847 c_parser_statement (parser, NULL);
24848 do
24849 {
24850 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24851 break;
24852 if (c_parser_next_token_is (parser, type: CPP_EOF))
24853 break;
24854
24855 if (kind != PRAGMA_NONE
24856 && c_parser_peek_token (parser)->pragma_kind == kind)
24857 break;
24858
24859 if (kind != PRAGMA_NONE
24860 && c_parser_omp_section_scan (parser,
24861 directive: kind == PRAGMA_OMP_SCAN
24862 ? "scan" : "section", tentative: false))
24863 break;
24864
24865 c_parser_statement (parser, NULL);
24866 }
24867 while (1);
24868 return pop_stmt_list (stmt);
24869}
24870
24871/* OpenMP 5.0:
24872
24873 scan-loop-body:
24874 { structured-block scan-directive structured-block } */
24875
24876static void
24877c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
24878{
24879 tree substmt;
24880 location_t loc;
24881 tree clauses = NULL_TREE;
24882 bool found_scan = false;
24883
24884 loc = c_parser_peek_token (parser)->location;
24885 if (!open_brace_parsed
24886 && !c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
24887 {
24888 /* Avoid skipping until the end of the block. */
24889 parser->error = false;
24890 return;
24891 }
24892
24893 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
24894 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN);
24895 else
24896 {
24897 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24898 "%<#pragma omp scan%> with zero preceding executable "
24899 "statements");
24900 substmt = build_empty_stmt (loc);
24901 }
24902 substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
24903 SET_EXPR_LOCATION (substmt, loc);
24904 add_stmt (substmt);
24905
24906 loc = c_parser_peek_token (parser)->location;
24907 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
24908 {
24909 enum omp_clause_code clause = OMP_CLAUSE_ERROR;
24910 found_scan = true;
24911
24912 c_parser_consume_pragma (parser);
24913
24914 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24915 c_parser_consume_token (parser);
24916
24917 if (c_parser_next_token_is (parser, type: CPP_NAME))
24918 {
24919 const char *p
24920 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24921 if (strcmp (s1: p, s2: "inclusive") == 0)
24922 clause = OMP_CLAUSE_INCLUSIVE;
24923 else if (strcmp (s1: p, s2: "exclusive") == 0)
24924 clause = OMP_CLAUSE_EXCLUSIVE;
24925 }
24926 if (clause != OMP_CLAUSE_ERROR)
24927 {
24928 c_parser_consume_token (parser);
24929 clauses = c_parser_omp_var_list_parens (parser, kind: clause, NULL_TREE);
24930 }
24931 else
24932 c_parser_error (parser, gmsgid: "expected %<inclusive%> or "
24933 "%<exclusive%> clause");
24934 c_parser_skip_to_pragma_eol (parser);
24935 }
24936 else
24937 error ("expected %<#pragma omp scan%>");
24938
24939 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24940 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24941 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE);
24942 else
24943 {
24944 if (found_scan)
24945 warning_at (loc, OPT_Wopenmp,
24946 "%<#pragma omp scan%> with zero succeeding executable "
24947 "statements");
24948 substmt = build_empty_stmt (loc);
24949 }
24950 substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
24951 SET_EXPR_LOCATION (substmt, loc);
24952 add_stmt (substmt);
24953
24954 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
24955 msgid: "expected %<}%>");
24956}
24957
24958
24959/* Check if the next tokens can start a canonical loop. Return true if yes,
24960 otherwise diagnose an error if ERROR_P is true, and return false. */
24961static bool
24962c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser,
24963 enum tree_code code,
24964 bool error_p)
24965{
24966 if (code == OACC_LOOP)
24967 {
24968 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
24969 return true;
24970 if (error_p)
24971 c_parser_error (parser, gmsgid: "for statement expected");
24972 }
24973 else
24974 {
24975 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
24976 return true;
24977
24978 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
24979 switch (c_parser_peek_token (parser)->pragma_kind)
24980 {
24981 case PRAGMA_OMP_UNROLL:
24982 case PRAGMA_OMP_TILE:
24983 return true;
24984 default:
24985 break;
24986 }
24987
24988 /* Skip standard attributes on next for in case they are
24989 [[omp::directive (unroll partial (4))]] or
24990 [[omp::directive (tile sizes (1, 2, 3))]] etc. */
24991 size_t n = c_parser_skip_std_attribute_spec_seq (parser, n: 1);
24992 c_token *token = c_parser_peek_nth_token_raw (parser, n);
24993 /* TOKEN is a raw token that hasn't been converted to a keyword yet,
24994 we have to do the lookup explicitly. */
24995 if (token->type == CPP_NAME
24996 && C_IS_RESERVED_WORD (token->value)
24997 && C_RID_CODE (token->value) == RID_FOR)
24998 return true;
24999 if (error_p)
25000 c_parser_error (parser, gmsgid: "loop nest expected");
25001 }
25002
25003 return false;
25004}
25005
25006static tree c_parser_omp_tile (location_t, c_parser *, bool *);
25007static tree c_parser_omp_unroll (location_t, c_parser *, bool *);
25008
25009/* This function parses a single level of a loop nest, invoking itself
25010 recursively if necessary.
25011
25012 loop-nest :: for (...) loop-body
25013 loop-body :: loop-nest
25014 | { [intervening-code] loop-body [intervening-code] }
25015 | final-loop-body
25016 intervening-code :: structured-block-sequence
25017 final-loop-body :: structured-block
25018
25019 For a collapsed loop nest, only a single OMP_FOR is built, pulling out
25020 all the iterator information from the inner loops into the
25021 parser->omp_for_parse_state structure.
25022
25023 The iterator decl, init, cond, and incr are stored in vectors.
25024
25025 Initialization code for iterator variables is collected into
25026 parser->omp_for_parse_state->pre_body and ends up inserted directly
25027 into the OMP_FOR structure. */
25028
25029static tree
25030c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
25031{
25032 tree decl = NULL_TREE, cond = NULL_TREE, incr = NULL_TREE, init = NULL_TREE;
25033 tree body = NULL_TREE;
25034 matching_parens parens;
25035 bool moreloops;
25036 unsigned char save_in_statement;
25037 tree loop_scope;
25038 location_t loc;
25039 struct omp_for_parse_data *omp_for_parse_state
25040 = parser->omp_for_parse_state;
25041 gcc_assert (omp_for_parse_state);
25042 int depth = omp_for_parse_state->depth;
25043
25044 /* Arrange for C23 standard attribute syntax to be parsed as regular
25045 pragmas. */
25046 if (c_parser_nth_token_starts_std_attributes (parser, n: 1))
25047 {
25048 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
25049 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
25050 if (std_attrs)
25051 error_at (c_parser_peek_token (parser)->location,
25052 "attributes other than OpenMP directives "
25053 "are not allowed on %<for%> in loop nest");
25054 }
25055
25056 loc = c_parser_peek_token (parser)->location;
25057
25058 /* Handle loop transformations first. */
25059 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
25060 {
25061 tree transform = NULL_TREE, sizes, body = NULL_TREE;
25062 int count = 0;
25063 switch (c_parser_peek_token (parser)->pragma_kind)
25064 {
25065 case PRAGMA_OMP_UNROLL:
25066 c_parser_consume_pragma (parser);
25067 body = push_stmt_list ();
25068 transform = c_parser_omp_unroll (loc, parser, if_p);
25069 body = pop_stmt_list (body);
25070 if (transform == NULL_TREE || transform == error_mark_node)
25071 {
25072 transform = error_mark_node;
25073 break;
25074 }
25075 gcc_assert (TREE_CODE (transform) == OMP_UNROLL);
25076 if (omp_find_clause (OMP_FOR_CLAUSES (transform),
25077 kind: OMP_CLAUSE_PARTIAL))
25078 {
25079 if (omp_for_parse_state->count - depth > 1)
25080 {
25081 error_at (loc, "%<unroll%> construct with %<partial%> "
25082 "clause generates just one loop with "
25083 "canonical form but %d loops are needed",
25084 omp_for_parse_state->count - depth);
25085 transform = error_mark_node;
25086 }
25087 else
25088 count = 1;
25089 }
25090 else
25091 {
25092 error_at (loc, "generated loop of %<unroll%> construct "
25093 "without %<partial%> clause does not have "
25094 "canonical form");
25095 transform = error_mark_node;
25096 }
25097 break;
25098 case PRAGMA_OMP_TILE:
25099 c_parser_consume_pragma (parser);
25100 body = push_stmt_list ();
25101 transform = c_parser_omp_tile (loc, parser, if_p);
25102 body = pop_stmt_list (body);
25103 if (transform == NULL_TREE || transform == error_mark_node)
25104 {
25105 transform = error_mark_node;
25106 break;
25107 }
25108 gcc_assert (TREE_CODE (transform) == OMP_TILE);
25109 sizes = omp_find_clause (OMP_FOR_CLAUSES (transform),
25110 kind: OMP_CLAUSE_SIZES);
25111 gcc_assert (sizes);
25112 count = list_length (OMP_CLAUSE_SIZES_LIST (sizes));
25113 if (depth + count < omp_for_parse_state->count)
25114 {
25115 error_at (loc, "%<tile%> construct generates %d loops "
25116 "with canonical form but %d loops are needed",
25117 count, omp_for_parse_state->count - depth);
25118 transform = error_mark_node;
25119 }
25120 break;
25121 default:
25122 c_parser_pragma (parser, context: pragma_stmt, NULL, void_list_node);
25123 break;
25124 }
25125 if (transform == NULL_TREE)
25126 error_at (loc, "expected %<for%> loop or OpenMP loop "
25127 "transformation construct");
25128 if (transform == NULL_TREE || transform == error_mark_node)
25129 {
25130 omp_for_parse_state->fail = true;
25131 return NULL_TREE;
25132 }
25133 for (count = omp_for_parse_state->count; depth < count; ++depth)
25134 {
25135 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE;
25136 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE;
25137 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE;
25138 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE;
25139 }
25140 omp_for_parse_state->want_nested_loop = false;
25141 return body;
25142 }
25143
25144 /* We have already matched the FOR token but not consumed it yet. */
25145 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
25146 c_parser_consume_token (parser);
25147
25148 /* Forbid break/continue in the loop initializer, condition, and
25149 increment expressions. */
25150 save_in_statement = in_statement;
25151 in_statement = IN_OMP_BLOCK;
25152
25153 /* We are not in intervening code now. */
25154 omp_for_parse_state->in_intervening_code = false;
25155
25156 if (!parens.require_open (parser))
25157 {
25158 omp_for_parse_state->fail = true;
25159 return NULL_TREE;
25160 }
25161
25162 /* An implicit scope block surrounds each level of FOR loop, for
25163 declarations of iteration variables at this loop depth. */
25164 loop_scope = c_begin_compound_stmt (true);
25165
25166 /* Parse the initialization declaration or expression. */
25167 if (c_parser_next_tokens_start_declaration (parser))
25168 {
25169 /* This is a declaration, which must be added to the pre_body code. */
25170 tree this_pre_body = push_stmt_list ();
25171 c_in_omp_for = true;
25172 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
25173 simple_ok: false);
25174 c_in_omp_for = false;
25175 this_pre_body = pop_stmt_list (this_pre_body);
25176 append_to_statement_list_force (this_pre_body,
25177 &(omp_for_parse_state->pre_body));
25178 decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
25179 if (decl == NULL)
25180 goto error_init;
25181 if (DECL_INITIAL (decl) == error_mark_node)
25182 decl = error_mark_node;
25183 init = decl;
25184 }
25185 else if (c_parser_next_token_is (parser, type: CPP_NAME)
25186 && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
25187 {
25188 struct c_expr decl_exp;
25189 struct c_expr init_exp;
25190 location_t init_loc;
25191
25192 decl_exp = c_parser_postfix_expression (parser);
25193 decl = decl_exp.value;
25194
25195 c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>");
25196
25197 init_loc = c_parser_peek_token (parser)->location;
25198 init_exp = c_parser_expr_no_commas (parser, NULL);
25199 init_exp = default_function_array_read_conversion (init_loc,
25200 init_exp);
25201 c_in_omp_for = true;
25202 init = build_modify_expr (init_loc, decl, decl_exp.original_type,
25203 NOP_EXPR, init_loc, init_exp.value,
25204 init_exp.original_type);
25205 c_in_omp_for = false;
25206 init = c_process_expr_stmt (init_loc, init);
25207
25208 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
25209 }
25210 else
25211 {
25212 error_init:
25213 c_parser_error (parser,
25214 gmsgid: "expected iteration declaration or initialization");
25215 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
25216 msgid: "expected %<)%>");
25217 omp_for_parse_state->fail = true;
25218 goto parse_next;
25219 }
25220
25221 /* Parse the loop condition. */
25222 if (c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
25223 {
25224 location_t cond_loc = c_parser_peek_token (parser)->location;
25225 c_in_omp_for = true;
25226 struct c_expr cond_expr
25227 = c_parser_binary_expression (parser, NULL, NULL_TREE);
25228 c_in_omp_for = false;
25229
25230 cond = cond_expr.value;
25231 cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
25232 switch (cond_expr.original_code)
25233 {
25234 case GT_EXPR:
25235 case GE_EXPR:
25236 case LT_EXPR:
25237 case LE_EXPR:
25238 break;
25239 case NE_EXPR:
25240 if (omp_for_parse_state->code != OACC_LOOP)
25241 break;
25242 /* FALLTHRU. */
25243 default:
25244 /* Can't be cond = error_mark_node, because we want to preserve
25245 the location until c_finish_omp_for. */
25246 cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
25247 break;
25248 }
25249 protected_set_expr_location (cond, cond_loc);
25250 }
25251 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
25252
25253 /* Parse the increment expression. */
25254 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
25255 {
25256 location_t incr_loc = c_parser_peek_token (parser)->location;
25257
25258 incr = c_process_expr_stmt (incr_loc,
25259 c_parser_expression (parser).value);
25260 }
25261 parens.skip_until_found_close (parser);
25262
25263 if (decl == NULL || decl == error_mark_node || init == error_mark_node)
25264 omp_for_parse_state->fail = true;
25265 else
25266 {
25267 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
25268 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
25269 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
25270 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
25271 }
25272
25273parse_next:
25274 moreloops = depth < omp_for_parse_state->count - 1;
25275 omp_for_parse_state->want_nested_loop = moreloops;
25276 if (moreloops
25277 && c_parser_omp_next_tokens_can_be_canon_loop (parser,
25278 code: omp_for_parse_state->code,
25279 error_p: false))
25280 {
25281 omp_for_parse_state->depth++;
25282 body = c_parser_omp_loop_nest (parser, if_p);
25283 omp_for_parse_state->depth--;
25284 }
25285 else if (moreloops && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
25286 {
25287 /* This is the open brace in the loop-body grammar production. Rather
25288 than trying to special-case braces, just parse it as a compound
25289 statement and handle the nested loop-body case there. Note that
25290 when we see a further open brace inside the compound statement
25291 loop-body, we don't know whether it is the start of intervening
25292 code that is a compound statement, or a level of braces
25293 surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
25294 bit to ensure we have only one nested loop at each level. */
25295 omp_for_parse_state->in_intervening_code = true;
25296 body = c_parser_compound_statement (parser, NULL);
25297 omp_for_parse_state->in_intervening_code = false;
25298 if (omp_for_parse_state->want_nested_loop)
25299 {
25300 /* We have already parsed the whole loop body and not found a
25301 nested loop. */
25302 error_at (omp_for_parse_state->for_loc,
25303 "not enough nested loops");
25304 omp_for_parse_state->fail = true;
25305 }
25306 if_p = NULL;
25307 }
25308 else
25309 {
25310 /* This is the final-loop-body case in the grammar: we have
25311 something that is not a FOR and not an open brace. */
25312 if (moreloops)
25313 {
25314 /* If we were expecting a nested loop, give an error and mark
25315 that parsing has failed, and try to recover by parsing the
25316 body as regular code without further collapsing. */
25317 error_at (omp_for_parse_state->for_loc,
25318 "not enough nested loops");
25319 omp_for_parse_state->fail = true;
25320 }
25321 in_statement = IN_OMP_FOR;
25322 parser->omp_for_parse_state = NULL;
25323 body = push_stmt_list ();
25324 if (omp_for_parse_state->inscan)
25325 c_parser_omp_scan_loop_body (parser, open_brace_parsed: false);
25326 else
25327 add_stmt (c_parser_c99_block_statement (parser, if_p));
25328 body = pop_stmt_list (body);
25329 parser->omp_for_parse_state = omp_for_parse_state;
25330 }
25331 in_statement = save_in_statement;
25332 omp_for_parse_state->want_nested_loop = false;
25333 omp_for_parse_state->in_intervening_code = true;
25334
25335 /* Pop and return the implicit scope surrounding this level of loop.
25336 If the iteration variable at this depth was bound in the for loop,
25337 pull out and save the binding. Later in c_parser_omp_for_loop,
25338 these bindings will be moved to the scope surrounding the entire
25339 OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
25340 we have already resolved all references to the iteration variable
25341 in its true scope. */
25342 if (body)
25343 add_stmt (body);
25344 body = c_end_compound_stmt (loc, loop_scope, true);
25345 if (decl && TREE_CODE (body) == BIND_EXPR)
25346 {
25347 tree t = BIND_EXPR_VARS (body);
25348 tree prev = NULL_TREE, next = NULL_TREE;
25349 while (t)
25350 {
25351 next = DECL_CHAIN (t);
25352 if (t == decl)
25353 {
25354 if (prev)
25355 DECL_CHAIN (prev) = next;
25356 else
25357 {
25358 BIND_EXPR_VARS (body) = next;
25359 BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
25360 }
25361 DECL_CHAIN (t) = omp_for_parse_state->bindings;
25362 omp_for_parse_state->bindings = t;
25363 break;
25364 }
25365 else
25366 {
25367 prev = t;
25368 t = next;
25369 }
25370 }
25371 if (BIND_EXPR_VARS (body) == NULL_TREE)
25372 body = BIND_EXPR_BODY (body);
25373 }
25374
25375 return body;
25376}
25377
25378/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
25379 The real trick here is to determine the loop control variable early
25380 so that we can push a new decl if necessary to make it private.
25381 LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
25382 respectively. */
25383
25384static tree
25385c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
25386 tree clauses, tree *cclauses, bool *if_p)
25387{
25388 tree body, stmt, cl;
25389 tree ret = NULL_TREE;
25390 tree ordered_cl = NULL_TREE;
25391 int i, collapse = 1, ordered = 0, count;
25392 bool oacc_tiling = false;
25393 bool inscan = false;
25394 struct omp_for_parse_data data;
25395 struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
25396
25397 for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
25398 if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
25399 collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
25400 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
25401 {
25402 oacc_tiling = true;
25403 collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
25404 }
25405 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES)
25406 collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl));
25407 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
25408 && OMP_CLAUSE_ORDERED_EXPR (cl))
25409 {
25410 ordered_cl = cl;
25411 ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
25412 }
25413 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
25414 && OMP_CLAUSE_REDUCTION_INSCAN (cl)
25415 && (code == OMP_SIMD || code == OMP_FOR))
25416 inscan = true;
25417
25418 if (ordered && ordered < collapse)
25419 {
25420 error_at (OMP_CLAUSE_LOCATION (ordered_cl),
25421 "%<ordered%> clause parameter is less than %<collapse%>");
25422 OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
25423 = build_int_cst (NULL_TREE, collapse);
25424 ordered = collapse;
25425 }
25426
25427 gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0));
25428 count = ordered ? ordered : collapse;
25429
25430 if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, error_p: true))
25431 return NULL;
25432
25433 /* Initialize parse state for recursive descent. */
25434 data.declv = make_tree_vec (count);
25435 data.initv = make_tree_vec (count);
25436 data.condv = make_tree_vec (count);
25437 data.incrv = make_tree_vec (count);
25438 data.pre_body = NULL_TREE;
25439 data.bindings = NULL_TREE;
25440 data.for_loc = c_parser_peek_token (parser)->location;
25441 data.count = count;
25442 data.depth = 0;
25443 data.want_nested_loop = true;
25444 data.ordered = ordered > 0;
25445 data.in_intervening_code = false;
25446 data.perfect_nesting_fail = false;
25447 data.fail = false;
25448 data.inscan = inscan;
25449 data.saw_intervening_code = false;
25450 data.code = code;
25451 parser->omp_for_parse_state = &data;
25452
25453 body = c_parser_omp_loop_nest (parser, if_p);
25454
25455 /* Add saved bindings for iteration variables that were declared in
25456 the nested for loop to the scope surrounding the entire loop. */
25457 for (tree t = data.bindings; t; )
25458 {
25459 tree n = TREE_CHAIN (t);
25460 TREE_CHAIN (t) = NULL_TREE;
25461 pushdecl (t);
25462 t = n;
25463 }
25464
25465 /* Only bother calling c_finish_omp_for if we haven't already generated
25466 an error from the initialization parsing. */
25467 if (!data.fail)
25468 {
25469 c_in_omp_for = true;
25470 stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
25471 data.condv, data.incrv,
25472 body, data.pre_body, true);
25473 c_in_omp_for = false;
25474
25475 /* Check for iterators appearing in lb, b or incr expressions. */
25476 if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
25477 stmt = NULL_TREE;
25478
25479 /* Check for errors involving lb/ub/incr expressions referencing
25480 variables declared in intervening code. */
25481 if (data.saw_intervening_code
25482 && stmt
25483 && !c_omp_check_loop_binding_exprs (stmt, NULL))
25484 stmt = NULL_TREE;
25485
25486 if (stmt)
25487 {
25488 add_stmt (stmt);
25489
25490 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
25491 {
25492 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
25493 if (init == NULL_TREE)
25494 break;
25495 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
25496 tree decl = TREE_OPERAND (init, 0);
25497 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
25498 gcc_assert (COMPARISON_CLASS_P (cond));
25499 gcc_assert (TREE_OPERAND (cond, 0) == decl);
25500
25501 tree op0 = TREE_OPERAND (init, 1);
25502 if (!OMP_FOR_NON_RECTANGULAR (stmt)
25503 || TREE_CODE (op0) != TREE_VEC)
25504 TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
25505 else
25506 {
25507 TREE_VEC_ELT (op0, 1)
25508 = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
25509 TREE_VEC_ELT (op0, 2)
25510 = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
25511 }
25512
25513 tree op1 = TREE_OPERAND (cond, 1);
25514 if (!OMP_FOR_NON_RECTANGULAR (stmt)
25515 || TREE_CODE (op1) != TREE_VEC)
25516 TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
25517 else
25518 {
25519 TREE_VEC_ELT (op1, 1)
25520 = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
25521 TREE_VEC_ELT (op1, 2)
25522 = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
25523 }
25524 }
25525
25526 if (cclauses != NULL
25527 && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
25528 {
25529 tree *c;
25530 for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
25531 if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
25532 && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
25533 c = &OMP_CLAUSE_CHAIN (*c);
25534 else
25535 {
25536 for (i = 0; i < count; i++)
25537 if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
25538 break;
25539 if (i == count)
25540 c = &OMP_CLAUSE_CHAIN (*c);
25541 else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
25542 {
25543 error_at (loc,
25544 "iteration variable %qD should not be firstprivate",
25545 OMP_CLAUSE_DECL (*c));
25546 *c = OMP_CLAUSE_CHAIN (*c);
25547 }
25548 else
25549 {
25550 /* Move lastprivate (decl) clause to
25551 OMP_FOR_CLAUSES. */
25552 tree l = *c;
25553 *c = OMP_CLAUSE_CHAIN (*c);
25554 if (code == OMP_SIMD)
25555 {
25556 OMP_CLAUSE_CHAIN (l)
25557 = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25558 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
25559 }
25560 else
25561 {
25562 OMP_CLAUSE_CHAIN (l) = clauses;
25563 clauses = l;
25564 }
25565 }
25566 }
25567 }
25568 OMP_FOR_CLAUSES (stmt) = clauses;
25569 }
25570 ret = stmt;
25571 }
25572
25573 parser->omp_for_parse_state = save_data;
25574 return ret;
25575}
25576
25577/* Helper function for OpenMP parsing, split clauses and call
25578 finish_omp_clauses on each of the set of clauses afterwards. */
25579
25580static void
25581omp_split_clauses (location_t loc, enum tree_code code,
25582 omp_clause_mask mask, tree clauses, tree *cclauses)
25583{
25584 int i;
25585 c_omp_split_clauses (loc, code, mask, clauses, cclauses);
25586 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
25587 if (cclauses[i])
25588 cclauses[i] = c_finish_omp_clauses (cclauses[i],
25589 i == C_OMP_CLAUSE_SPLIT_TARGET
25590 ? C_ORT_OMP_TARGET : C_ORT_OMP);
25591}
25592
25593/* OpenMP 5.0:
25594 #pragma omp loop loop-clause[optseq] new-line
25595 for-loop
25596
25597 LOC is the location of the #pragma token.
25598*/
25599
25600#define OMP_LOOP_CLAUSE_MASK \
25601 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25602 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25603 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25604 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25605 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
25606 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25607
25608static tree
25609c_parser_omp_loop (location_t loc, c_parser *parser,
25610 char *p_name, omp_clause_mask mask, tree *cclauses,
25611 bool *if_p)
25612{
25613 tree block, clauses, ret;
25614
25615 strcat (dest: p_name, src: " loop");
25616 mask |= OMP_LOOP_CLAUSE_MASK;
25617
25618 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25619 if (cclauses)
25620 {
25621 omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses);
25622 clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
25623 }
25624
25625 block = c_begin_compound_stmt (true);
25626 ret = c_parser_omp_for_loop (loc, parser, code: OMP_LOOP, clauses, cclauses, if_p);
25627 block = c_end_compound_stmt (loc, block, true);
25628 add_stmt (block);
25629
25630 return ret;
25631}
25632
25633/* OpenMP 4.0:
25634 #pragma omp simd simd-clause[optseq] new-line
25635 for-loop
25636
25637 LOC is the location of the #pragma token.
25638*/
25639
25640#define OMP_SIMD_CLAUSE_MASK \
25641 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
25642 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
25643 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
25644 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
25645 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25646 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25647 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25648 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25649 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25650 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
25651 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25652
25653static tree
25654c_parser_omp_simd (location_t loc, c_parser *parser,
25655 char *p_name, omp_clause_mask mask, tree *cclauses,
25656 bool *if_p)
25657{
25658 tree block, clauses, ret;
25659
25660 strcat (dest: p_name, src: " simd");
25661 mask |= OMP_SIMD_CLAUSE_MASK;
25662
25663 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25664 if (cclauses)
25665 {
25666 omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses);
25667 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
25668 }
25669
25670 block = c_begin_compound_stmt (true);
25671 ret = c_parser_omp_for_loop (loc, parser, code: OMP_SIMD, clauses, cclauses, if_p);
25672 block = c_end_compound_stmt (loc, block, true);
25673 add_stmt (block);
25674
25675 return ret;
25676}
25677
25678/* OpenMP 2.5:
25679 #pragma omp for for-clause[optseq] new-line
25680 for-loop
25681
25682 OpenMP 4.0:
25683 #pragma omp for simd for-simd-clause[optseq] new-line
25684 for-loop
25685
25686 LOC is the location of the #pragma token.
25687*/
25688
25689#define OMP_FOR_CLAUSE_MASK \
25690 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25691 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25692 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25693 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
25694 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25695 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
25696 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
25697 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25698 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25699 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25700 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25701
25702static tree
25703c_parser_omp_for (location_t loc, c_parser *parser,
25704 char *p_name, omp_clause_mask mask, tree *cclauses,
25705 bool *if_p)
25706{
25707 tree block, clauses, ret;
25708
25709 strcat (dest: p_name, src: " for");
25710 mask |= OMP_FOR_CLAUSE_MASK;
25711 /* parallel for{, simd} disallows nowait clause, but for
25712 target {teams distribute ,}parallel for{, simd} it should be accepted. */
25713 if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
25714 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25715 /* Composite distribute parallel for{, simd} disallows ordered clause. */
25716 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25717 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
25718
25719 if (c_parser_next_token_is (parser, type: CPP_NAME))
25720 {
25721 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25722
25723 if (strcmp (s1: p, s2: "simd") == 0)
25724 {
25725 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25726 if (cclauses == NULL)
25727 cclauses = cclauses_buf;
25728
25729 c_parser_consume_token (parser);
25730 if (!flag_openmp) /* flag_openmp_simd */
25731 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25732 if_p);
25733 block = c_begin_compound_stmt (true);
25734 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
25735 block = c_end_compound_stmt (loc, block, true);
25736 if (ret == NULL_TREE)
25737 return ret;
25738 ret = make_node (OMP_FOR);
25739 TREE_TYPE (ret) = void_type_node;
25740 OMP_FOR_BODY (ret) = block;
25741 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25742 SET_EXPR_LOCATION (ret, loc);
25743 add_stmt (ret);
25744 return ret;
25745 }
25746 }
25747 if (!flag_openmp) /* flag_openmp_simd */
25748 {
25749 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25750 return NULL_TREE;
25751 }
25752
25753 /* Composite distribute parallel for disallows linear clause. */
25754 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25755 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
25756
25757 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25758 if (cclauses)
25759 {
25760 omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses);
25761 clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25762 }
25763
25764 block = c_begin_compound_stmt (true);
25765 ret = c_parser_omp_for_loop (loc, parser, code: OMP_FOR, clauses, cclauses, if_p);
25766 block = c_end_compound_stmt (loc, block, true);
25767 add_stmt (block);
25768
25769 return ret;
25770}
25771
25772static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
25773 omp_clause_mask, tree *, bool *);
25774
25775/* OpenMP 2.5:
25776 # pragma omp master new-line
25777 structured-block
25778
25779 LOC is the location of the #pragma token.
25780*/
25781
25782static tree
25783c_parser_omp_master (location_t loc, c_parser *parser,
25784 char *p_name, omp_clause_mask mask, tree *cclauses,
25785 bool *if_p, location_t master_loc)
25786{
25787 tree block, clauses, ret;
25788 gcc_rich_location richloc (loc);
25789 if (master_loc != UNKNOWN_LOCATION)
25790 richloc.add_fixit_replace (where: master_loc, new_content: "masked");
25791 warning_at (&richloc, OPT_Wdeprecated_openmp,
25792 "%<master%> construct deprecated since OpenMP 5.1, use "
25793 "%<masked%>");
25794
25795 strcat (dest: p_name, src: " master");
25796
25797 if (c_parser_next_token_is (parser, type: CPP_NAME))
25798 {
25799 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25800
25801 if (strcmp (s1: p, s2: "taskloop") == 0)
25802 {
25803 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25804 if (cclauses == NULL)
25805 cclauses = cclauses_buf;
25806
25807 c_parser_consume_token (parser);
25808 if (!flag_openmp) /* flag_openmp_simd */
25809 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25810 if_p);
25811 block = c_begin_compound_stmt (true);
25812 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25813 if_p);
25814 block = c_end_compound_stmt (loc, block, true);
25815 if (ret == NULL_TREE)
25816 return ret;
25817 ret = c_finish_omp_master (loc, block);
25818 OMP_MASTER_COMBINED (ret) = 1;
25819 return ret;
25820 }
25821 }
25822 if (!flag_openmp) /* flag_openmp_simd */
25823 {
25824 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25825 return NULL_TREE;
25826 }
25827
25828 if (cclauses)
25829 {
25830 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: false);
25831 omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses);
25832 }
25833 else
25834 c_parser_skip_to_pragma_eol (parser);
25835
25836 return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
25837 if_p));
25838}
25839
25840/* OpenMP 5.1:
25841 # pragma omp masked masked-clauses new-line
25842 structured-block
25843
25844 LOC is the location of the #pragma token.
25845*/
25846
25847#define OMP_MASKED_CLAUSE_MASK \
25848 (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
25849
25850static tree
25851c_parser_omp_masked (location_t loc, c_parser *parser,
25852 char *p_name, omp_clause_mask mask, tree *cclauses,
25853 bool *if_p)
25854{
25855 tree block, clauses, ret;
25856
25857 strcat (dest: p_name, src: " masked");
25858 mask |= OMP_MASKED_CLAUSE_MASK;
25859
25860 if (c_parser_next_token_is (parser, type: CPP_NAME))
25861 {
25862 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25863
25864 if (strcmp (s1: p, s2: "taskloop") == 0)
25865 {
25866 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25867 if (cclauses == NULL)
25868 cclauses = cclauses_buf;
25869
25870 c_parser_consume_token (parser);
25871 if (!flag_openmp) /* flag_openmp_simd */
25872 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25873 if_p);
25874 block = c_begin_compound_stmt (true);
25875 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25876 if_p);
25877 block = c_end_compound_stmt (loc, block, true);
25878 if (ret == NULL_TREE)
25879 return ret;
25880 ret = c_finish_omp_masked (loc, block,
25881 cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
25882 OMP_MASKED_COMBINED (ret) = 1;
25883 return ret;
25884 }
25885 }
25886 if (!flag_openmp) /* flag_openmp_simd */
25887 {
25888 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25889 return NULL_TREE;
25890 }
25891
25892 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25893 if (cclauses)
25894 {
25895 omp_split_clauses (loc, code: OMP_MASKED, mask, clauses, cclauses);
25896 clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
25897 }
25898
25899 return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
25900 if_p),
25901 clauses);
25902}
25903
25904/* OpenMP 5.1:
25905 # pragma omp interop clauses[opt] new-line */
25906
25907#define OMP_INTEROP_CLAUSE_MASK \
25908 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25909 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DESTROY) \
25910 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25911 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INIT) \
25912 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25913 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE))
25914
25915static void
25916c_parser_omp_interop (c_parser *parser)
25917{
25918 location_t loc = c_parser_peek_token (parser)->location;
25919 c_parser_consume_pragma (parser);
25920 tree clauses = c_parser_omp_all_clauses (parser,
25921 OMP_INTEROP_CLAUSE_MASK,
25922 where: "#pragma omp interop");
25923 tree stmt = make_node (OMP_INTEROP);
25924 TREE_TYPE (stmt) = void_type_node;
25925 OMP_INTEROP_CLAUSES (stmt) = clauses;
25926 SET_EXPR_LOCATION (stmt, loc);
25927 add_stmt (stmt);
25928}
25929
25930/* OpenMP 2.5:
25931 # pragma omp ordered new-line
25932 structured-block
25933
25934 OpenMP 4.5:
25935 # pragma omp ordered ordered-clauses new-line
25936 structured-block
25937
25938 # pragma omp ordered depend-clauses new-line
25939
25940 OpenMP 5.2
25941 # pragma omp ordered doacross-clauses new-line */
25942
25943#define OMP_ORDERED_CLAUSE_MASK \
25944 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
25945 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
25946
25947#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
25948 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25949 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
25950
25951static bool
25952c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
25953 bool *if_p)
25954{
25955 location_t loc = c_parser_peek_token (parser)->location;
25956 c_parser_consume_pragma (parser);
25957
25958 if (context != pragma_stmt && context != pragma_compound)
25959 {
25960 c_parser_error (parser, gmsgid: "expected declaration specifiers");
25961 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25962 return false;
25963 }
25964
25965 int n = 1;
25966 if (c_parser_next_token_is (parser, type: CPP_COMMA))
25967 n = 2;
25968
25969 if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
25970 {
25971 const char *p
25972 = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
25973
25974 if (!strcmp (s1: "depend", s2: p) || !strcmp (s1: "doacross", s2: p))
25975 {
25976 if (!flag_openmp) /* flag_openmp_simd */
25977 {
25978 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25979 return false;
25980 }
25981 if (context == pragma_stmt)
25982 {
25983 error_at (loc,
25984 "%<#pragma omp ordered%> with %qs clause may "
25985 "only be used in compound statements", p);
25986 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25987 return true;
25988 }
25989
25990 tree clauses
25991 = c_parser_omp_all_clauses (parser,
25992 OMP_ORDERED_DEPEND_CLAUSE_MASK,
25993 where: "#pragma omp ordered");
25994 c_finish_omp_ordered (loc, clauses, NULL_TREE);
25995 return false;
25996 }
25997 }
25998
25999 tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
26000 where: "#pragma omp ordered");
26001
26002 if (!flag_openmp /* flag_openmp_simd */
26003 && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE)
26004 return false;
26005
26006 c_finish_omp_ordered (loc, clauses,
26007 c_parser_omp_structured_block (parser, if_p));
26008 return true;
26009}
26010
26011/* OpenMP 2.5:
26012
26013 section-scope:
26014 { section-sequence }
26015
26016 section-sequence:
26017 section-directive[opt] structured-block
26018 section-sequence section-directive structured-block
26019
26020 OpenMP 5.1 allows structured-block-sequence instead of structured-block.
26021
26022 SECTIONS_LOC is the location of the #pragma omp sections. */
26023
26024static tree
26025c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
26026{
26027 tree stmt, substmt;
26028 bool error_suppress = false;
26029 location_t loc;
26030
26031 loc = c_parser_peek_token (parser)->location;
26032 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
26033 {
26034 /* Avoid skipping until the end of the block. */
26035 parser->error = false;
26036 return NULL_TREE;
26037 }
26038
26039 stmt = push_stmt_list ();
26040
26041 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
26042 && !c_parser_omp_section_scan (parser, directive: "section", tentative: true))
26043 {
26044 substmt = c_parser_omp_structured_block_sequence (parser,
26045 kind: PRAGMA_OMP_SECTION);
26046 substmt = build1 (OMP_SECTION, void_type_node, substmt);
26047 SET_EXPR_LOCATION (substmt, loc);
26048 add_stmt (substmt);
26049 }
26050
26051 while (1)
26052 {
26053 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
26054 break;
26055 if (c_parser_next_token_is (parser, type: CPP_EOF))
26056 break;
26057
26058 loc = c_parser_peek_token (parser)->location;
26059 c_parser_omp_section_scan (parser, directive: "section", tentative: false);
26060 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
26061 {
26062 c_parser_consume_pragma (parser);
26063 c_parser_skip_to_pragma_eol (parser);
26064 error_suppress = false;
26065 }
26066 else if (!error_suppress)
26067 {
26068 error_at (loc, "expected %<#pragma omp section%> or %<}%>");
26069 error_suppress = true;
26070 }
26071
26072 substmt = c_parser_omp_structured_block_sequence (parser,
26073 kind: PRAGMA_OMP_SECTION);
26074 substmt = build1 (OMP_SECTION, void_type_node, substmt);
26075 SET_EXPR_LOCATION (substmt, loc);
26076 add_stmt (substmt);
26077 }
26078 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
26079 msgid: "expected %<#pragma omp section%> or %<}%>");
26080
26081 substmt = pop_stmt_list (stmt);
26082
26083 stmt = make_node (OMP_SECTIONS);
26084 SET_EXPR_LOCATION (stmt, sections_loc);
26085 TREE_TYPE (stmt) = void_type_node;
26086 OMP_SECTIONS_BODY (stmt) = substmt;
26087
26088 return add_stmt (stmt);
26089}
26090
26091/* OpenMP 2.5:
26092 # pragma omp sections sections-clause[optseq] newline
26093 sections-scope
26094
26095 LOC is the location of the #pragma token.
26096*/
26097
26098#define OMP_SECTIONS_CLAUSE_MASK \
26099 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26100 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26101 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26102 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26103 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26104 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26105
26106static tree
26107c_parser_omp_sections (location_t loc, c_parser *parser,
26108 char *p_name, omp_clause_mask mask, tree *cclauses)
26109{
26110 tree block, clauses, ret;
26111
26112 strcat (dest: p_name, src: " sections");
26113 mask |= OMP_SECTIONS_CLAUSE_MASK;
26114 if (cclauses)
26115 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
26116
26117 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26118 if (cclauses)
26119 {
26120 omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses);
26121 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
26122 }
26123
26124 block = c_begin_compound_stmt (true);
26125 ret = c_parser_omp_sections_scope (sections_loc: loc, parser);
26126 if (ret)
26127 OMP_SECTIONS_CLAUSES (ret) = clauses;
26128 block = c_end_compound_stmt (loc, block, true);
26129 add_stmt (block);
26130
26131 return ret;
26132}
26133
26134/* OpenMP 2.5:
26135 # pragma omp parallel parallel-clause[optseq] new-line
26136 structured-block
26137 # pragma omp parallel for parallel-for-clause[optseq] new-line
26138 structured-block
26139 # pragma omp parallel sections parallel-sections-clause[optseq] new-line
26140 structured-block
26141
26142 OpenMP 4.0:
26143 # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
26144 structured-block
26145
26146 LOC is the location of the #pragma token.
26147*/
26148
26149#define OMP_PARALLEL_CLAUSE_MASK \
26150 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26151 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26152 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26153 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
26154 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26155 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
26156 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26157 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
26158 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26159 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
26160
26161static tree
26162c_parser_omp_parallel (location_t loc, c_parser *parser,
26163 char *p_name, omp_clause_mask mask, tree *cclauses,
26164 bool *if_p)
26165{
26166 tree stmt, clauses, block;
26167
26168 strcat (dest: p_name, src: " parallel");
26169 mask |= OMP_PARALLEL_CLAUSE_MASK;
26170 /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
26171 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
26172 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
26173 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
26174
26175 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
26176 {
26177 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26178 if (cclauses == NULL)
26179 cclauses = cclauses_buf;
26180
26181 c_parser_consume_token (parser);
26182 if (!flag_openmp) /* flag_openmp_simd */
26183 return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
26184 block = c_begin_omp_parallel ();
26185 tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
26186 stmt
26187 = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26188 block);
26189 if (ret == NULL_TREE)
26190 return ret;
26191 OMP_PARALLEL_COMBINED (stmt) = 1;
26192 return stmt;
26193 }
26194 /* When combined with distribute, parallel has to be followed by for.
26195 #pragma omp target parallel is allowed though. */
26196 else if (cclauses
26197 && (mask & (OMP_CLAUSE_MASK_1
26198 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
26199 {
26200 error_at (loc, "expected %<for%> after %qs", p_name);
26201 c_parser_skip_to_pragma_eol (parser);
26202 return NULL_TREE;
26203 }
26204 else if (c_parser_next_token_is (parser, type: CPP_NAME))
26205 {
26206 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26207 location_t ploc = c_parser_peek_token (parser)->location;
26208 if (cclauses == NULL && strcmp (s1: p, s2: "masked") == 0)
26209 {
26210 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26211 cclauses = cclauses_buf;
26212
26213 c_parser_consume_token (parser);
26214 if (!flag_openmp) /* flag_openmp_simd */
26215 return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
26216 if_p);
26217 block = c_begin_omp_parallel ();
26218 tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
26219 if_p);
26220 stmt = c_finish_omp_parallel (loc,
26221 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26222 block);
26223 if (ret == NULL)
26224 return ret;
26225 /* masked does have just filter clause, but during gimplification
26226 isn't represented by a gimplification omp context, so for
26227 #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
26228 so that
26229 #pragma omp parallel masked
26230 #pragma omp taskloop simd lastprivate (x)
26231 isn't confused with
26232 #pragma omp parallel masked taskloop simd lastprivate (x) */
26233 if (OMP_MASKED_COMBINED (ret))
26234 OMP_PARALLEL_COMBINED (stmt) = 1;
26235 return stmt;
26236 }
26237 else if (cclauses == NULL && strcmp (s1: p, s2: "master") == 0)
26238 {
26239 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26240 cclauses = cclauses_buf;
26241
26242 c_parser_consume_token (parser);
26243 if (!flag_openmp) /* flag_openmp_simd */
26244 return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
26245 if_p, master_loc: ploc);
26246 block = c_begin_omp_parallel ();
26247 tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
26248 if_p, master_loc: ploc);
26249 stmt = c_finish_omp_parallel (loc,
26250 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26251 block);
26252 if (ret == NULL)
26253 return ret;
26254 /* master doesn't have any clauses and during gimplification
26255 isn't represented by a gimplification omp context, so for
26256 #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
26257 so that
26258 #pragma omp parallel master
26259 #pragma omp taskloop simd lastprivate (x)
26260 isn't confused with
26261 #pragma omp parallel master taskloop simd lastprivate (x) */
26262 if (OMP_MASTER_COMBINED (ret))
26263 OMP_PARALLEL_COMBINED (stmt) = 1;
26264 return stmt;
26265 }
26266 else if (strcmp (s1: p, s2: "loop") == 0)
26267 {
26268 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26269 if (cclauses == NULL)
26270 cclauses = cclauses_buf;
26271
26272 c_parser_consume_token (parser);
26273 if (!flag_openmp) /* flag_openmp_simd */
26274 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26275 if_p);
26276 block = c_begin_omp_parallel ();
26277 tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26278 if_p);
26279 stmt
26280 = c_finish_omp_parallel (loc,
26281 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26282 block);
26283 if (ret == NULL_TREE)
26284 return ret;
26285 OMP_PARALLEL_COMBINED (stmt) = 1;
26286 return stmt;
26287 }
26288 else if (!flag_openmp) /* flag_openmp_simd */
26289 {
26290 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26291 return NULL_TREE;
26292 }
26293 else if (cclauses == NULL && strcmp (s1: p, s2: "sections") == 0)
26294 {
26295 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26296 cclauses = cclauses_buf;
26297
26298 c_parser_consume_token (parser);
26299 block = c_begin_omp_parallel ();
26300 c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
26301 stmt = c_finish_omp_parallel (loc,
26302 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26303 block);
26304 OMP_PARALLEL_COMBINED (stmt) = 1;
26305 return stmt;
26306 }
26307 }
26308 else if (!flag_openmp) /* flag_openmp_simd */
26309 {
26310 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26311 return NULL_TREE;
26312 }
26313
26314 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26315 if (cclauses)
26316 {
26317 omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses);
26318 clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
26319 }
26320
26321 block = c_begin_omp_parallel ();
26322 parser->omp_attrs_forbidden_p = true;
26323 c_parser_statement (parser, if_p);
26324 stmt = c_finish_omp_parallel (loc, clauses, block);
26325
26326 return stmt;
26327}
26328
26329/* OpenMP 2.5:
26330 # pragma omp single single-clause[optseq] new-line
26331 structured-block
26332
26333 LOC is the location of the #pragma.
26334*/
26335
26336#define OMP_SINGLE_CLAUSE_MASK \
26337 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26338 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26339 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
26340 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26341 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26342
26343static tree
26344c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
26345{
26346 tree stmt = make_node (OMP_SINGLE);
26347 SET_EXPR_LOCATION (stmt, loc);
26348 TREE_TYPE (stmt) = void_type_node;
26349
26350 OMP_SINGLE_CLAUSES (stmt)
26351 = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
26352 where: "#pragma omp single");
26353 OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
26354
26355 return add_stmt (stmt);
26356}
26357
26358/* OpenMP 5.1:
26359 # pragma omp scope scope-clause[optseq] new-line
26360 structured-block
26361
26362 LOC is the location of the #pragma.
26363*/
26364
26365#define OMP_SCOPE_CLAUSE_MASK \
26366 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26367 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26368 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26369 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26370 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26371
26372static tree
26373c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
26374{
26375 tree stmt = make_node (OMP_SCOPE);
26376 SET_EXPR_LOCATION (stmt, loc);
26377 TREE_TYPE (stmt) = void_type_node;
26378
26379 OMP_SCOPE_CLAUSES (stmt)
26380 = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
26381 where: "#pragma omp scope");
26382 OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
26383
26384 return add_stmt (stmt);
26385}
26386
26387/* Parse a function dispatch structured block:
26388
26389 lvalue-expression = target-call ( [expression-list] );
26390 or
26391 target-call ( [expression-list] );
26392
26393 Adapted from c_parser_expr_no_commas and c_parser_postfix_expression
26394 (CPP_NAME/C_ID_ID) for the function name.
26395*/
26396static tree
26397c_parser_omp_dispatch_body (c_parser *parser)
26398{
26399 struct c_expr lhs, rhs, ret;
26400 location_t expr_loc = c_parser_peek_token (parser)->location;
26401 source_range tok_range = c_parser_peek_token (parser)->get_range ();
26402
26403 lhs = c_parser_conditional_expression (parser, NULL, NULL);
26404 if (TREE_CODE (lhs.value) == CALL_EXPR)
26405 return lhs.value;
26406
26407 location_t op_location = c_parser_peek_token (parser)->location;
26408 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
26409 return error_mark_node;
26410
26411 /* Parse function name. */
26412 if (!c_parser_next_token_is (parser, type: CPP_NAME))
26413 {
26414 c_parser_error (parser, gmsgid: "expected a function name");
26415 return error_mark_node;
26416 }
26417 expr_loc = c_parser_peek_token (parser)->location;
26418 tree id = c_parser_peek_token (parser)->value;
26419 c_parser_consume_token (parser);
26420 if (!c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
26421 {
26422 c_parser_error (parser, gmsgid: "expected a function name");
26423 return error_mark_node;
26424 }
26425
26426 rhs.value = build_external_ref (expr_loc, id, true, &rhs.original_type);
26427 set_c_expr_source_range (expr: &rhs, src_range: tok_range);
26428
26429 /* Parse argument list. */
26430 rhs = c_parser_postfix_expression_after_primary (
26431 parser, EXPR_LOC_OR_LOC (rhs.value, expr_loc), expr: rhs);
26432 if (TREE_CODE (rhs.value) != CALL_EXPR)
26433 {
26434 error_at (EXPR_LOC_OR_LOC (rhs.value, expr_loc),
26435 "expected target-function call");
26436 return error_mark_node;
26437 }
26438
26439 /* Build assignment. */
26440 rhs = convert_lvalue_to_rvalue (expr_loc, rhs, true, true);
26441 ret.value
26442 = build_modify_expr (op_location, lhs.value, lhs.original_type, NOP_EXPR,
26443 expr_loc, rhs.value, rhs.original_type);
26444 ret.m_decimal = 0;
26445 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
26446 ret.original_code = MODIFY_EXPR;
26447 ret.original_type = NULL;
26448 return ret.value;
26449}
26450
26451/* OpenMP 5.1:
26452 # pragma omp dispatch dispatch-clause[optseq] new-line
26453 expression-stmt
26454
26455 LOC is the location of the #pragma.
26456*/
26457
26458#define OMP_DISPATCH_CLAUSE_MASK \
26459 ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26460 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26461 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
26462 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
26463 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
26464 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \
26465 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
26466 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26467
26468static tree
26469c_parser_omp_dispatch (location_t loc, c_parser *parser)
26470{
26471 tree stmt = make_node (OMP_DISPATCH);
26472 SET_EXPR_LOCATION (stmt, loc);
26473 TREE_TYPE (stmt) = void_type_node;
26474
26475 OMP_DISPATCH_CLAUSES (stmt)
26476 = c_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
26477 where: "#pragma omp dispatch");
26478
26479 // Extract depend clauses and create taskwait
26480 tree depend_clauses = NULL_TREE;
26481 tree *depend_clauses_ptr = &depend_clauses;
26482 for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
26483 {
26484 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
26485 {
26486 *depend_clauses_ptr = c;
26487 depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
26488 }
26489 }
26490 if (depend_clauses != NULL_TREE)
26491 {
26492 tree stmt = make_node (OMP_TASK);
26493 TREE_TYPE (stmt) = void_node;
26494 OMP_TASK_CLAUSES (stmt) = depend_clauses;
26495 OMP_TASK_BODY (stmt) = NULL_TREE;
26496 SET_EXPR_LOCATION (stmt, loc);
26497 add_stmt (stmt);
26498 }
26499
26500 // Parse body as expression statement
26501 loc = c_parser_peek_token (parser)->location;
26502 tree dispatch_body = c_parser_omp_dispatch_body (parser);
26503 if (dispatch_body == error_mark_node)
26504 {
26505 inform (loc, "%<#pragma omp dispatch%> must be followed by a function "
26506 "call with optional assignment");
26507 c_parser_skip_to_end_of_block_or_statement (parser);
26508 return NULL_TREE;
26509 }
26510
26511 // Walk the tree to find the dispatch function call and wrap it into an IFN
26512 gcc_assert (TREE_CODE (dispatch_body) == CALL_EXPR
26513 || TREE_CODE (dispatch_body) == MODIFY_EXPR);
26514 tree *dispatch_call = TREE_CODE (dispatch_body) == MODIFY_EXPR
26515 ? &TREE_OPERAND (dispatch_body, 1)
26516 : &dispatch_body;
26517 while (TREE_CODE (*dispatch_call) == FLOAT_EXPR
26518 || TREE_CODE (*dispatch_call) == CONVERT_EXPR
26519 || TREE_CODE (*dispatch_call) == NOP_EXPR)
26520 dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
26521 *dispatch_call = build_call_expr_internal_loc (
26522 loc, IFN_GOMP_DISPATCH,
26523 TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*dispatch_call))), 1, *dispatch_call);
26524
26525 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
26526 OMP_DISPATCH_BODY (stmt) = dispatch_body;
26527
26528 return add_stmt (stmt);
26529}
26530
26531/* OpenMP 3.0:
26532 # pragma omp task task-clause[optseq] new-line
26533
26534 LOC is the location of the #pragma.
26535*/
26536
26537#define OMP_TASK_CLAUSE_MASK \
26538 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26539 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
26540 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
26541 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26542 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26543 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26544 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
26545 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
26546 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26547 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
26548 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26549 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
26550 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
26551 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
26552
26553static tree
26554c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
26555{
26556 tree clauses, block;
26557
26558 clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
26559 where: "#pragma omp task");
26560
26561 block = c_begin_omp_task ();
26562 parser->omp_attrs_forbidden_p = true;
26563 c_parser_statement (parser, if_p);
26564 return c_finish_omp_task (loc, clauses, block);
26565}
26566
26567/* OpenMP 3.0:
26568 # pragma omp taskwait new-line
26569
26570 OpenMP 5.0:
26571 # pragma omp taskwait taskwait-clause[optseq] new-line
26572*/
26573
26574#define OMP_TASKWAIT_CLAUSE_MASK \
26575 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26576 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26577
26578static void
26579c_parser_omp_taskwait (c_parser *parser)
26580{
26581 location_t loc = c_parser_peek_token (parser)->location;
26582 c_parser_consume_pragma (parser);
26583
26584 tree clauses
26585 = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
26586 where: "#pragma omp taskwait");
26587
26588 if (clauses)
26589 {
26590 tree stmt = make_node (OMP_TASK);
26591 TREE_TYPE (stmt) = void_node;
26592 OMP_TASK_CLAUSES (stmt) = clauses;
26593 OMP_TASK_BODY (stmt) = NULL_TREE;
26594 SET_EXPR_LOCATION (stmt, loc);
26595 add_stmt (stmt);
26596 }
26597 else
26598 c_finish_omp_taskwait (loc);
26599}
26600
26601/* OpenMP 3.1:
26602 # pragma omp taskyield new-line
26603*/
26604
26605static void
26606c_parser_omp_taskyield (c_parser *parser)
26607{
26608 location_t loc = c_parser_peek_token (parser)->location;
26609 c_parser_consume_pragma (parser);
26610 c_parser_skip_to_pragma_eol (parser);
26611
26612 c_finish_omp_taskyield (loc);
26613}
26614
26615/* OpenMP 4.0:
26616 # pragma omp taskgroup new-line
26617
26618 OpenMP 5.0:
26619 # pragma omp taskgroup taskgroup-clause[optseq] new-line
26620*/
26621
26622#define OMP_TASKGROUP_CLAUSE_MASK \
26623 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26624 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
26625
26626static tree
26627c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
26628{
26629 tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
26630 where: "#pragma omp taskgroup");
26631
26632 tree body = c_parser_omp_structured_block (parser, if_p);
26633 return c_finish_omp_taskgroup (loc, body, clauses);
26634}
26635
26636/* OpenMP 4.0:
26637 # pragma omp cancel cancel-clause[optseq] new-line
26638
26639 LOC is the location of the #pragma.
26640*/
26641
26642#define OMP_CANCEL_CLAUSE_MASK \
26643 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
26644 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
26645 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
26646 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
26647 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
26648
26649static void
26650c_parser_omp_cancel (c_parser *parser)
26651{
26652 location_t loc = c_parser_peek_token (parser)->location;
26653
26654 c_parser_consume_pragma (parser);
26655 tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
26656 where: "#pragma omp cancel");
26657
26658 c_finish_omp_cancel (loc, clauses);
26659}
26660
26661/* OpenMP 4.0:
26662 # pragma omp cancellation point cancelpt-clause[optseq] new-line
26663
26664 LOC is the location of the #pragma.
26665*/
26666
26667#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
26668 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
26669 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
26670 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
26671 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
26672
26673static bool
26674c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
26675{
26676 location_t loc = c_parser_peek_token (parser)->location;
26677 tree clauses;
26678 bool point_seen = false;
26679
26680 c_parser_consume_pragma (parser);
26681 if (c_parser_next_token_is (parser, type: CPP_NAME))
26682 {
26683 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26684 if (strcmp (s1: p, s2: "point") == 0)
26685 {
26686 c_parser_consume_token (parser);
26687 point_seen = true;
26688 }
26689 }
26690 if (!point_seen)
26691 {
26692 c_parser_error (parser, gmsgid: "expected %<point%>");
26693 c_parser_skip_to_pragma_eol (parser);
26694 return false;
26695 }
26696
26697 if (context != pragma_compound)
26698 {
26699 if (context == pragma_stmt)
26700 error_at (loc,
26701 "%<#pragma %s%> may only be used in compound statements",
26702 "omp cancellation point");
26703 else
26704 c_parser_error (parser, gmsgid: "expected declaration specifiers");
26705 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26706 return true;
26707 }
26708
26709 clauses
26710 = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
26711 where: "#pragma omp cancellation point");
26712
26713 c_finish_omp_cancellation_point (loc, clauses);
26714 return true;
26715}
26716
26717/* OpenMP 4.0:
26718 #pragma omp distribute distribute-clause[optseq] new-line
26719 for-loop */
26720
26721#define OMP_DISTRIBUTE_CLAUSE_MASK \
26722 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26723 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26724 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26725 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
26726 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26727 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
26728 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
26729
26730static tree
26731c_parser_omp_distribute (location_t loc, c_parser *parser,
26732 char *p_name, omp_clause_mask mask, tree *cclauses,
26733 bool *if_p)
26734{
26735 tree clauses, block, ret;
26736
26737 strcat (dest: p_name, src: " distribute");
26738 mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
26739
26740 if (c_parser_next_token_is (parser, type: CPP_NAME))
26741 {
26742 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26743 bool simd = false;
26744 bool parallel = false;
26745
26746 if (strcmp (s1: p, s2: "simd") == 0)
26747 simd = true;
26748 else
26749 parallel = strcmp (s1: p, s2: "parallel") == 0;
26750 if (parallel || simd)
26751 {
26752 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26753 if (cclauses == NULL)
26754 cclauses = cclauses_buf;
26755 c_parser_consume_token (parser);
26756 if (!flag_openmp) /* flag_openmp_simd */
26757 {
26758 if (simd)
26759 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26760 if_p);
26761 else
26762 return c_parser_omp_parallel (loc, parser, p_name, mask,
26763 cclauses, if_p);
26764 }
26765 block = c_begin_compound_stmt (true);
26766 if (simd)
26767 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26768 if_p);
26769 else
26770 ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
26771 if_p);
26772 block = c_end_compound_stmt (loc, block, true);
26773 if (ret == NULL)
26774 return ret;
26775 ret = make_node (OMP_DISTRIBUTE);
26776 TREE_TYPE (ret) = void_type_node;
26777 OMP_FOR_BODY (ret) = block;
26778 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26779 SET_EXPR_LOCATION (ret, loc);
26780 add_stmt (ret);
26781 return ret;
26782 }
26783 }
26784 if (!flag_openmp) /* flag_openmp_simd */
26785 {
26786 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26787 return NULL_TREE;
26788 }
26789
26790 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26791 if (cclauses)
26792 {
26793 omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses);
26794 clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26795 }
26796
26797 block = c_begin_compound_stmt (true);
26798 ret = c_parser_omp_for_loop (loc, parser, code: OMP_DISTRIBUTE, clauses, NULL,
26799 if_p);
26800 block = c_end_compound_stmt (loc, block, true);
26801 add_stmt (block);
26802
26803 return ret;
26804}
26805
26806/* OpenMP 4.0:
26807 # pragma omp teams teams-clause[optseq] new-line
26808 structured-block */
26809
26810#define OMP_TEAMS_CLAUSE_MASK \
26811 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26812 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26813 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26814 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26815 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
26816 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26817 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26818 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
26819
26820static tree
26821c_parser_omp_teams (location_t loc, c_parser *parser,
26822 char *p_name, omp_clause_mask mask, tree *cclauses,
26823 bool *if_p)
26824{
26825 tree clauses, block, ret;
26826
26827 strcat (dest: p_name, src: " teams");
26828 mask |= OMP_TEAMS_CLAUSE_MASK;
26829
26830 if (c_parser_next_token_is (parser, type: CPP_NAME))
26831 {
26832 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26833 if (strcmp (s1: p, s2: "distribute") == 0)
26834 {
26835 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26836 if (cclauses == NULL)
26837 cclauses = cclauses_buf;
26838
26839 c_parser_consume_token (parser);
26840 if (!flag_openmp) /* flag_openmp_simd */
26841 return c_parser_omp_distribute (loc, parser, p_name, mask,
26842 cclauses, if_p);
26843 block = c_begin_omp_parallel ();
26844 ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
26845 if_p);
26846 block = c_end_compound_stmt (loc, block, true);
26847 if (ret == NULL)
26848 return ret;
26849 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26850 ret = make_node (OMP_TEAMS);
26851 TREE_TYPE (ret) = void_type_node;
26852 OMP_TEAMS_CLAUSES (ret) = clauses;
26853 OMP_TEAMS_BODY (ret) = block;
26854 OMP_TEAMS_COMBINED (ret) = 1;
26855 SET_EXPR_LOCATION (ret, loc);
26856 return add_stmt (ret);
26857 }
26858 else if (strcmp (s1: p, s2: "loop") == 0)
26859 {
26860 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26861 if (cclauses == NULL)
26862 cclauses = cclauses_buf;
26863
26864 c_parser_consume_token (parser);
26865 if (!flag_openmp) /* flag_openmp_simd */
26866 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26867 if_p);
26868 block = c_begin_omp_parallel ();
26869 ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
26870 block = c_end_compound_stmt (loc, block, true);
26871 if (ret == NULL)
26872 return ret;
26873 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26874 ret = make_node (OMP_TEAMS);
26875 TREE_TYPE (ret) = void_type_node;
26876 OMP_TEAMS_CLAUSES (ret) = clauses;
26877 OMP_TEAMS_BODY (ret) = block;
26878 OMP_TEAMS_COMBINED (ret) = 1;
26879 SET_EXPR_LOCATION (ret, loc);
26880 return add_stmt (ret);
26881 }
26882 }
26883 if (!flag_openmp) /* flag_openmp_simd */
26884 {
26885 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26886 return NULL_TREE;
26887 }
26888
26889 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26890 if (cclauses)
26891 {
26892 omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses);
26893 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26894 }
26895
26896 tree stmt = make_node (OMP_TEAMS);
26897 TREE_TYPE (stmt) = void_type_node;
26898 OMP_TEAMS_CLAUSES (stmt) = clauses;
26899 block = c_begin_omp_parallel ();
26900 add_stmt (c_parser_omp_structured_block (parser, if_p));
26901 OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26902 SET_EXPR_LOCATION (stmt, loc);
26903
26904 return add_stmt (stmt);
26905}
26906
26907/* OpenMP 4.0:
26908 # pragma omp target data target-data-clause[optseq] new-line
26909 structured-block */
26910
26911#define OMP_TARGET_DATA_CLAUSE_MASK \
26912 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26913 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26914 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26915 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
26916 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
26917
26918static tree
26919c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
26920{
26921 if (flag_openmp)
26922 omp_requires_mask
26923 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26924
26925 tree clauses
26926 = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
26927 where: "#pragma omp target data");
26928 c_omp_adjust_map_clauses (clauses, false);
26929 int map_seen = 0;
26930 for (tree *pc = &clauses; *pc;)
26931 {
26932 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26933 switch (OMP_CLAUSE_MAP_KIND (*pc))
26934 {
26935 case GOMP_MAP_TO:
26936 case GOMP_MAP_ALWAYS_TO:
26937 case GOMP_MAP_PRESENT_TO:
26938 case GOMP_MAP_ALWAYS_PRESENT_TO:
26939 case GOMP_MAP_FROM:
26940 case GOMP_MAP_ALWAYS_FROM:
26941 case GOMP_MAP_PRESENT_FROM:
26942 case GOMP_MAP_ALWAYS_PRESENT_FROM:
26943 case GOMP_MAP_TOFROM:
26944 case GOMP_MAP_ALWAYS_TOFROM:
26945 case GOMP_MAP_PRESENT_TOFROM:
26946 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26947 case GOMP_MAP_ALLOC:
26948 case GOMP_MAP_PRESENT_ALLOC:
26949 map_seen = 3;
26950 break;
26951 case GOMP_MAP_FIRSTPRIVATE_POINTER:
26952 case GOMP_MAP_ALWAYS_POINTER:
26953 case GOMP_MAP_ATTACH_DETACH:
26954 case GOMP_MAP_ATTACH:
26955 break;
26956 default:
26957 map_seen |= 1;
26958 error_at (OMP_CLAUSE_LOCATION (*pc),
26959 "%<#pragma omp target data%> with map-type other "
26960 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26961 "on %<map%> clause");
26962 *pc = OMP_CLAUSE_CHAIN (*pc);
26963 continue;
26964 }
26965 else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
26966 || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
26967 map_seen = 3;
26968 pc = &OMP_CLAUSE_CHAIN (*pc);
26969 }
26970
26971 if (map_seen != 3)
26972 {
26973 if (map_seen == 0)
26974 error_at (loc,
26975 "%<#pragma omp target data%> must contain at least "
26976 "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
26977 "clause");
26978 return NULL_TREE;
26979 }
26980
26981 tree stmt = make_node (OMP_TARGET_DATA);
26982 TREE_TYPE (stmt) = void_type_node;
26983 OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
26984 keep_next_level ();
26985 tree block = c_begin_compound_stmt (true);
26986 add_stmt (c_parser_omp_structured_block (parser, if_p));
26987 OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26988
26989 SET_EXPR_LOCATION (stmt, loc);
26990 return add_stmt (stmt);
26991}
26992
26993/* OpenMP 4.0:
26994 # pragma omp target update target-update-clause[optseq] new-line */
26995
26996#define OMP_TARGET_UPDATE_CLAUSE_MASK \
26997 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
26998 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
26999 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27000 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27001 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27002 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27003
27004static bool
27005c_parser_omp_target_update (location_t loc, c_parser *parser,
27006 enum pragma_context context)
27007{
27008 if (context == pragma_stmt)
27009 {
27010 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27011 "omp target update");
27012 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27013 return true;
27014 }
27015
27016 tree clauses
27017 = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
27018 where: "#pragma omp target update");
27019 if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE
27020 && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE)
27021 {
27022 error_at (loc,
27023 "%<#pragma omp target update%> must contain at least one "
27024 "%<from%> or %<to%> clauses");
27025 return false;
27026 }
27027
27028 if (flag_openmp)
27029 omp_requires_mask
27030 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27031
27032 tree stmt = make_node (OMP_TARGET_UPDATE);
27033 TREE_TYPE (stmt) = void_type_node;
27034 OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
27035 SET_EXPR_LOCATION (stmt, loc);
27036 add_stmt (stmt);
27037 return false;
27038}
27039
27040/* OpenMP 4.5:
27041 # pragma omp target enter data target-data-clause[optseq] new-line */
27042
27043#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
27044 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27045 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27046 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27047 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27048 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27049
27050static bool
27051c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
27052 enum pragma_context context)
27053{
27054 bool data_seen = false;
27055 if (c_parser_next_token_is (parser, type: CPP_NAME))
27056 {
27057 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27058 if (strcmp (s1: p, s2: "data") == 0)
27059 {
27060 c_parser_consume_token (parser);
27061 data_seen = true;
27062 }
27063 }
27064 if (!data_seen)
27065 {
27066 c_parser_error (parser, gmsgid: "expected %<data%>");
27067 c_parser_skip_to_pragma_eol (parser);
27068 return false;
27069 }
27070
27071 if (context == pragma_stmt)
27072 {
27073 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27074 "omp target enter data");
27075 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27076 return true;
27077 }
27078
27079 if (flag_openmp)
27080 omp_requires_mask
27081 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27082
27083 tree clauses
27084 = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
27085 where: "#pragma omp target enter data");
27086 c_omp_adjust_map_clauses (clauses, false);
27087 int map_seen = 0;
27088 for (tree *pc = &clauses; *pc;)
27089 {
27090 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27091 switch (OMP_CLAUSE_MAP_KIND (*pc))
27092 {
27093 case GOMP_MAP_TO:
27094 case GOMP_MAP_ALWAYS_TO:
27095 case GOMP_MAP_PRESENT_TO:
27096 case GOMP_MAP_ALWAYS_PRESENT_TO:
27097 case GOMP_MAP_ALLOC:
27098 case GOMP_MAP_PRESENT_ALLOC:
27099 map_seen = 3;
27100 break;
27101 case GOMP_MAP_TOFROM:
27102 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
27103 map_seen = 3;
27104 break;
27105 case GOMP_MAP_ALWAYS_TOFROM:
27106 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
27107 map_seen = 3;
27108 break;
27109 case GOMP_MAP_PRESENT_TOFROM:
27110 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
27111 map_seen = 3;
27112 break;
27113 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27114 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
27115 map_seen = 3;
27116 break;
27117 case GOMP_MAP_FIRSTPRIVATE_POINTER:
27118 case GOMP_MAP_ALWAYS_POINTER:
27119 case GOMP_MAP_ATTACH_DETACH:
27120 case GOMP_MAP_ATTACH:
27121 break;
27122 default:
27123 map_seen |= 1;
27124 error_at (OMP_CLAUSE_LOCATION (*pc),
27125 "%<#pragma omp target enter data%> with map-type other "
27126 "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
27127 *pc = OMP_CLAUSE_CHAIN (*pc);
27128 continue;
27129 }
27130 pc = &OMP_CLAUSE_CHAIN (*pc);
27131 }
27132
27133 if (map_seen != 3)
27134 {
27135 if (map_seen == 0)
27136 error_at (loc,
27137 "%<#pragma omp target enter data%> must contain at least "
27138 "one %<map%> clause");
27139 return true;
27140 }
27141
27142 tree stmt = make_node (OMP_TARGET_ENTER_DATA);
27143 TREE_TYPE (stmt) = void_type_node;
27144 OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
27145 SET_EXPR_LOCATION (stmt, loc);
27146 add_stmt (stmt);
27147 return true;
27148}
27149
27150/* OpenMP 4.5:
27151 # pragma omp target exit data target-data-clause[optseq] new-line */
27152
27153#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
27154 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27155 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27156 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27157 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27158 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27159
27160static bool
27161c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
27162 enum pragma_context context)
27163{
27164 bool data_seen = false;
27165 if (c_parser_next_token_is (parser, type: CPP_NAME))
27166 {
27167 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27168 if (strcmp (s1: p, s2: "data") == 0)
27169 {
27170 c_parser_consume_token (parser);
27171 data_seen = true;
27172 }
27173 }
27174 if (!data_seen)
27175 {
27176 c_parser_error (parser, gmsgid: "expected %<data%>");
27177 c_parser_skip_to_pragma_eol (parser);
27178 return false;
27179 }
27180
27181 if (context == pragma_stmt)
27182 {
27183 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27184 "omp target exit data");
27185 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27186 return true;
27187 }
27188
27189 if (flag_openmp)
27190 omp_requires_mask
27191 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27192
27193 tree clauses
27194 = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
27195 where: "#pragma omp target exit data", finish_p: false);
27196 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
27197 c_omp_adjust_map_clauses (clauses, false);
27198 int map_seen = 0;
27199 for (tree *pc = &clauses; *pc;)
27200 {
27201 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27202 switch (OMP_CLAUSE_MAP_KIND (*pc))
27203 {
27204 case GOMP_MAP_FROM:
27205 case GOMP_MAP_ALWAYS_FROM:
27206 case GOMP_MAP_PRESENT_FROM:
27207 case GOMP_MAP_ALWAYS_PRESENT_FROM:
27208 case GOMP_MAP_RELEASE:
27209 case GOMP_MAP_DELETE:
27210 map_seen = 3;
27211 break;
27212 case GOMP_MAP_TOFROM:
27213 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
27214 map_seen = 3;
27215 break;
27216 case GOMP_MAP_ALWAYS_TOFROM:
27217 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
27218 map_seen = 3;
27219 break;
27220 case GOMP_MAP_PRESENT_TOFROM:
27221 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
27222 map_seen = 3;
27223 break;
27224 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27225 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
27226 map_seen = 3;
27227 break;
27228 case GOMP_MAP_FIRSTPRIVATE_POINTER:
27229 case GOMP_MAP_ALWAYS_POINTER:
27230 case GOMP_MAP_ATTACH_DETACH:
27231 case GOMP_MAP_DETACH:
27232 break;
27233 default:
27234 map_seen |= 1;
27235 error_at (OMP_CLAUSE_LOCATION (*pc),
27236 "%<#pragma omp target exit data%> with map-type other "
27237 "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
27238 "on %<map%> clause");
27239 *pc = OMP_CLAUSE_CHAIN (*pc);
27240 continue;
27241 }
27242 pc = &OMP_CLAUSE_CHAIN (*pc);
27243 }
27244
27245 if (map_seen != 3)
27246 {
27247 if (map_seen == 0)
27248 error_at (loc,
27249 "%<#pragma omp target exit data%> must contain at least one "
27250 "%<map%> clause");
27251 return true;
27252 }
27253
27254 tree stmt = make_node (OMP_TARGET_EXIT_DATA);
27255 TREE_TYPE (stmt) = void_type_node;
27256 OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
27257 SET_EXPR_LOCATION (stmt, loc);
27258 add_stmt (stmt);
27259 return true;
27260}
27261
27262/* OpenMP 4.0:
27263 # pragma omp target target-clause[optseq] new-line
27264 structured-block */
27265
27266#define OMP_TARGET_CLAUSE_MASK \
27267 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
27268 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
27269 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27270 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27271 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27272 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
27273 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
27274 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
27275 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27276 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
27277 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
27278 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27279 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
27280 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
27281 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
27282 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USES_ALLOCATORS))
27283
27284static bool
27285c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
27286{
27287 location_t loc = c_parser_peek_token (parser)->location;
27288 c_parser_consume_pragma (parser);
27289 tree *pc = NULL, stmt, block, body, clauses;
27290
27291 if (context != pragma_stmt && context != pragma_compound)
27292 {
27293 c_parser_error (parser, gmsgid: "expected declaration specifiers");
27294 c_parser_skip_to_pragma_eol (parser);
27295 return false;
27296 }
27297
27298 if (flag_openmp)
27299 omp_requires_mask
27300 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27301
27302 if (c_parser_next_token_is (parser, type: CPP_NAME))
27303 {
27304 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27305 enum tree_code ccode = ERROR_MARK;
27306
27307 if (strcmp (s1: p, s2: "teams") == 0)
27308 ccode = OMP_TEAMS;
27309 else if (strcmp (s1: p, s2: "parallel") == 0)
27310 ccode = OMP_PARALLEL;
27311 else if (strcmp (s1: p, s2: "simd") == 0)
27312 ccode = OMP_SIMD;
27313 if (ccode != ERROR_MARK)
27314 {
27315 tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
27316 char p_name[sizeof ("#pragma omp target teams distribute "
27317 "parallel for simd")];
27318
27319 c_parser_consume_token (parser);
27320 strcpy (dest: p_name, src: "#pragma omp target");
27321 if (!flag_openmp) /* flag_openmp_simd */
27322 {
27323 tree stmt;
27324 switch (ccode)
27325 {
27326 case OMP_TEAMS:
27327 stmt = c_parser_omp_teams (loc, parser, p_name,
27328 OMP_TARGET_CLAUSE_MASK,
27329 cclauses, if_p);
27330 break;
27331 case OMP_PARALLEL:
27332 stmt = c_parser_omp_parallel (loc, parser, p_name,
27333 OMP_TARGET_CLAUSE_MASK,
27334 cclauses, if_p);
27335 break;
27336 case OMP_SIMD:
27337 stmt = c_parser_omp_simd (loc, parser, p_name,
27338 OMP_TARGET_CLAUSE_MASK,
27339 cclauses, if_p);
27340 break;
27341 default:
27342 gcc_unreachable ();
27343 }
27344 return stmt != NULL_TREE;
27345 }
27346 keep_next_level ();
27347 tree block = c_begin_compound_stmt (true), ret;
27348 switch (ccode)
27349 {
27350 case OMP_TEAMS:
27351 ret = c_parser_omp_teams (loc, parser, p_name,
27352 OMP_TARGET_CLAUSE_MASK, cclauses,
27353 if_p);
27354 break;
27355 case OMP_PARALLEL:
27356 ret = c_parser_omp_parallel (loc, parser, p_name,
27357 OMP_TARGET_CLAUSE_MASK, cclauses,
27358 if_p);
27359 break;
27360 case OMP_SIMD:
27361 ret = c_parser_omp_simd (loc, parser, p_name,
27362 OMP_TARGET_CLAUSE_MASK, cclauses,
27363 if_p);
27364 break;
27365 default:
27366 gcc_unreachable ();
27367 }
27368 block = c_end_compound_stmt (loc, block, true);
27369 if (ret == NULL_TREE)
27370 return false;
27371 if (ccode == OMP_TEAMS)
27372 /* For combined target teams, ensure the num_teams and
27373 thread_limit clause expressions are evaluated on the host,
27374 before entering the target construct. */
27375 for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
27376 c; c = OMP_CLAUSE_CHAIN (c))
27377 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
27378 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
27379 for (int i = 0;
27380 i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
27381 if (OMP_CLAUSE_OPERAND (c, i)
27382 && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
27383 {
27384 tree expr = OMP_CLAUSE_OPERAND (c, i);
27385 tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
27386 expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
27387 expr, NULL_TREE, NULL_TREE);
27388 add_stmt (expr);
27389 OMP_CLAUSE_OPERAND (c, i) = expr;
27390 tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
27391 OMP_CLAUSE_FIRSTPRIVATE);
27392 OMP_CLAUSE_DECL (tc) = tmp;
27393 OMP_CLAUSE_CHAIN (tc)
27394 = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
27395 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
27396 }
27397 tree stmt = make_node (OMP_TARGET);
27398 TREE_TYPE (stmt) = void_type_node;
27399 OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
27400 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
27401 OMP_TARGET_BODY (stmt) = block;
27402 OMP_TARGET_COMBINED (stmt) = 1;
27403 SET_EXPR_LOCATION (stmt, loc);
27404 add_stmt (stmt);
27405 pc = &OMP_TARGET_CLAUSES (stmt);
27406 goto check_clauses;
27407 }
27408 else if (!flag_openmp) /* flag_openmp_simd */
27409 {
27410 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27411 return false;
27412 }
27413 else if (strcmp (s1: p, s2: "data") == 0)
27414 {
27415 c_parser_consume_token (parser);
27416 c_parser_omp_target_data (loc, parser, if_p);
27417 return true;
27418 }
27419 else if (strcmp (s1: p, s2: "enter") == 0)
27420 {
27421 c_parser_consume_token (parser);
27422 return c_parser_omp_target_enter_data (loc, parser, context);
27423 }
27424 else if (strcmp (s1: p, s2: "exit") == 0)
27425 {
27426 c_parser_consume_token (parser);
27427 return c_parser_omp_target_exit_data (loc, parser, context);
27428 }
27429 else if (strcmp (s1: p, s2: "update") == 0)
27430 {
27431 c_parser_consume_token (parser);
27432 return c_parser_omp_target_update (loc, parser, context);
27433 }
27434 }
27435 if (!flag_openmp) /* flag_openmp_simd */
27436 {
27437 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27438 return false;
27439 }
27440
27441 stmt = make_node (OMP_TARGET);
27442 TREE_TYPE (stmt) = void_type_node;
27443
27444 clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
27445 where: "#pragma omp target", finish_p: false);
27446 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27447 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
27448 {
27449 tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
27450 OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
27451 OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
27452 OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
27453 OMP_CLAUSE_CHAIN (c) = nc;
27454 }
27455 clauses = c_omp_instantiate_mappers (clauses);
27456 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
27457 c_omp_adjust_map_clauses (clauses, true);
27458
27459 keep_next_level ();
27460 block = c_begin_compound_stmt (true);
27461 body = c_parser_omp_structured_block (parser, if_p);
27462
27463 c_omp_scan_mapper_bindings (loc, &clauses, body);
27464
27465 add_stmt (body);
27466 OMP_TARGET_CLAUSES (stmt) = clauses;
27467 pc = &OMP_TARGET_CLAUSES (stmt);
27468 OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
27469
27470 SET_EXPR_LOCATION (stmt, loc);
27471 add_stmt (stmt);
27472
27473check_clauses:
27474 while (*pc)
27475 {
27476 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27477 switch (OMP_CLAUSE_MAP_KIND (*pc))
27478 {
27479 case GOMP_MAP_TO:
27480 case GOMP_MAP_ALWAYS_TO:
27481 case GOMP_MAP_PRESENT_TO:
27482 case GOMP_MAP_ALWAYS_PRESENT_TO:
27483 case GOMP_MAP_FROM:
27484 case GOMP_MAP_ALWAYS_FROM:
27485 case GOMP_MAP_PRESENT_FROM:
27486 case GOMP_MAP_ALWAYS_PRESENT_FROM:
27487 case GOMP_MAP_TOFROM:
27488 case GOMP_MAP_ALWAYS_TOFROM:
27489 case GOMP_MAP_PRESENT_TOFROM:
27490 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27491 case GOMP_MAP_ALLOC:
27492 case GOMP_MAP_PRESENT_ALLOC:
27493 case GOMP_MAP_FIRSTPRIVATE_POINTER:
27494 case GOMP_MAP_ALWAYS_POINTER:
27495 case GOMP_MAP_POINTER:
27496 case GOMP_MAP_ATTACH_DETACH:
27497 case GOMP_MAP_ATTACH:
27498 break;
27499 default:
27500 error_at (OMP_CLAUSE_LOCATION (*pc),
27501 "%<#pragma omp target%> with map-type other "
27502 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
27503 "on %<map%> clause");
27504 *pc = OMP_CLAUSE_CHAIN (*pc);
27505 continue;
27506 }
27507 pc = &OMP_CLAUSE_CHAIN (*pc);
27508 }
27509 cfun->has_omp_target = true;
27510 return true;
27511}
27512
27513/* OpenMP 4.0:
27514 # pragma omp declare simd declare-simd-clauses[optseq] new-line
27515
27516 OpenMP 5.0:
27517 # pragma omp declare variant (identifier) match(context-selector) new-line
27518
27519 OpenMP 5.1
27520 # pragma omp declare variant (identifier) match(context-selector) \
27521 adjust_args(adjust-op:argument-list) append_args(interop-list) new-line
27522 */
27523
27524#define OMP_DECLARE_SIMD_CLAUSE_MASK \
27525 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
27526 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
27527 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
27528 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
27529 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
27530 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
27531
27532static void
27533c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
27534{
27535 c_token *token = c_parser_peek_token (parser);
27536 gcc_assert (token->type == CPP_NAME);
27537 tree kind = token->value;
27538 gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
27539 || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
27540
27541 auto_vec<c_token> clauses;
27542 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
27543 {
27544 c_token *token = c_parser_peek_token (parser);
27545 if (token->type == CPP_EOF)
27546 {
27547 c_parser_skip_to_pragma_eol (parser);
27548 return;
27549 }
27550 clauses.safe_push (obj: *token);
27551 c_parser_consume_token (parser);
27552 }
27553 clauses.safe_push (obj: *c_parser_peek_token (parser));
27554 c_parser_skip_to_pragma_eol (parser);
27555
27556 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
27557 {
27558 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
27559 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
27560 || c_parser_peek_2nd_token (parser)->value != kind)
27561 {
27562 error ("%<#pragma omp declare %s%> must be followed by "
27563 "function declaration or definition or another "
27564 "%<#pragma omp declare %s%>",
27565 IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
27566 return;
27567 }
27568 c_parser_consume_pragma (parser);
27569 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
27570 {
27571 c_token *token = c_parser_peek_token (parser);
27572 if (token->type == CPP_EOF)
27573 {
27574 c_parser_skip_to_pragma_eol (parser);
27575 return;
27576 }
27577 clauses.safe_push (obj: *token);
27578 c_parser_consume_token (parser);
27579 }
27580 clauses.safe_push (obj: *c_parser_peek_token (parser));
27581 c_parser_skip_to_pragma_eol (parser);
27582 }
27583
27584 /* Make sure nothing tries to read past the end of the tokens. */
27585 c_token eof_token;
27586 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
27587 eof_token.type = CPP_EOF;
27588 clauses.safe_push (obj: eof_token);
27589 clauses.safe_push (obj: eof_token);
27590
27591 switch (context)
27592 {
27593 case pragma_external:
27594 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27595 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
27596 {
27597 int ext = disable_extension_diagnostics ();
27598 do
27599 c_parser_consume_token (parser);
27600 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27601 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
27602 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
27603 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses);
27604 restore_extension_diagnostics (flags: ext);
27605 }
27606 else
27607 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
27608 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses);
27609 break;
27610 case pragma_struct:
27611 case pragma_param:
27612 case pragma_stmt:
27613 error ("%<#pragma omp declare %s%> must be followed by "
27614 "function declaration or definition",
27615 IDENTIFIER_POINTER (kind));
27616 break;
27617 case pragma_compound:
27618 bool have_std_attrs;
27619 tree std_attrs;
27620 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
27621 if (have_std_attrs)
27622 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
27623 else
27624 std_attrs = NULL_TREE;
27625 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27626 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
27627 {
27628 int ext = disable_extension_diagnostics ();
27629 do
27630 c_parser_consume_token (parser);
27631 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27632 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
27633 if (c_parser_next_tokens_start_declaration (parser)
27634 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
27635 {
27636 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
27637 start_attr_ok: true, simple_ok: false, NULL, omp_declare_simd_clauses: &clauses,
27638 have_attrs: have_std_attrs, attrs: std_attrs);
27639 restore_extension_diagnostics (flags: ext);
27640 break;
27641 }
27642 restore_extension_diagnostics (flags: ext);
27643 }
27644 else if (c_parser_next_tokens_start_declaration (parser))
27645 {
27646 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
27647 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses, have_attrs: have_std_attrs,
27648 attrs: std_attrs);
27649 break;
27650 }
27651 error ("%<#pragma omp declare %s%> must be followed by "
27652 "function declaration or definition",
27653 IDENTIFIER_POINTER (kind));
27654 break;
27655 default:
27656 gcc_unreachable ();
27657 }
27658}
27659
27660/* OpenMP 5.0:
27661
27662 trait-selector:
27663 trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
27664
27665 trait-score:
27666 score(score-expression)
27667
27668 Note that this function returns a list of trait selectors for the
27669 trait-selector-set SET. */
27670
27671static tree
27672c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
27673 tree parms)
27674{
27675 tree ret = NULL_TREE;
27676 do
27677 {
27678 tree selector;
27679 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27680 || c_parser_next_token_is (parser, type: CPP_NAME))
27681 selector = c_parser_peek_token (parser)->value;
27682 else
27683 {
27684 c_parser_error (parser, gmsgid: "expected trait selector name");
27685 return error_mark_node;
27686 }
27687 enum omp_ts_code sel
27688 = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
27689
27690 if (sel == OMP_TRAIT_INVALID)
27691 {
27692 /* Per the spec, "Implementations can ignore specified selectors
27693 that are not those described in this section"; however, we
27694 must record such selectors because they cause match failures. */
27695 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
27696 "unknown selector %qs for context selector set %qs",
27697 IDENTIFIER_POINTER (selector), omp_tss_map[set]);
27698 c_parser_consume_token (parser);
27699 ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
27700 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
27701 c_parser_balanced_token_sequence (parser);
27702 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27703 {
27704 c_parser_consume_token (parser);
27705 continue;
27706 }
27707 else
27708 break;
27709 }
27710
27711 c_parser_consume_token (parser);
27712
27713 tree properties = NULL_TREE;
27714 tree scoreval = NULL_TREE;
27715 enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
27716 bool allow_score = omp_ts_map[sel].allow_score;
27717 tree t;
27718
27719 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
27720 {
27721 if (property_kind == OMP_TRAIT_PROPERTY_NONE)
27722 {
27723 error_at (c_parser_peek_token (parser)->location,
27724 "selector %qs does not accept any properties",
27725 IDENTIFIER_POINTER (selector));
27726 return error_mark_node;
27727 }
27728
27729 matching_parens parens;
27730 parens.require_open (parser);
27731
27732 c_token *token = c_parser_peek_token (parser);
27733 if (c_parser_next_token_is (parser, type: CPP_NAME)
27734 && strcmp (IDENTIFIER_POINTER (token->value), s2: "score") == 0
27735 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
27736 {
27737 c_parser_consume_token (parser);
27738
27739 matching_parens parens2;
27740 parens2.require_open (parser);
27741 tree score = c_parser_expr_no_commas (parser, NULL).value;
27742 parens2.skip_until_found_close (parser);
27743 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
27744 if (!allow_score)
27745 error_at (token->location,
27746 "%<score%> cannot be specified in traits "
27747 "in the %qs trait-selector-set",
27748 omp_tss_map[set]);
27749 else if (score != error_mark_node)
27750 {
27751 mark_exp_read (score);
27752 score = c_fully_fold (score, false, NULL);
27753 if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
27754 || TREE_CODE (score) != INTEGER_CST)
27755 error_at (token->location, "%<score%> argument must "
27756 "be constant integer expression");
27757 else if (tree_int_cst_sgn (score) < 0)
27758 error_at (token->location, "%<score%> argument must "
27759 "be non-negative");
27760 else
27761 scoreval = score;
27762 }
27763 token = c_parser_peek_token (parser);
27764 }
27765
27766 switch (property_kind)
27767 {
27768 case OMP_TRAIT_PROPERTY_ID:
27769 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27770 || c_parser_next_token_is (parser, type: CPP_NAME))
27771 {
27772 tree prop = c_parser_peek_token (parser)->value;
27773 c_parser_consume_token (parser);
27774 properties = make_trait_property (prop, NULL_TREE,
27775 properties);
27776 }
27777 else
27778 {
27779 c_parser_error (parser, gmsgid: "expected identifier");
27780 return error_mark_node;
27781 }
27782 break;
27783 case OMP_TRAIT_PROPERTY_NAME_LIST:
27784 do
27785 {
27786 tree prop = OMP_TP_NAMELIST_NODE;
27787 tree value = NULL_TREE;
27788 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
27789 || c_parser_next_token_is (parser, type: CPP_NAME))
27790 {
27791 value = c_parser_peek_token (parser)->value;
27792 c_parser_consume_token (parser);
27793 }
27794 else if (c_parser_next_token_is (parser, type: CPP_STRING))
27795 value = c_parser_string_literal (parser, translate: false,
27796 wide_ok: false).value;
27797 else
27798 {
27799 c_parser_error (parser, gmsgid: "expected identifier or "
27800 "string literal");
27801 return error_mark_node;
27802 }
27803
27804 properties = make_trait_property (prop, value, properties);
27805
27806 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27807 c_parser_consume_token (parser);
27808 else
27809 break;
27810 }
27811 while (1);
27812 break;
27813 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
27814 case OMP_TRAIT_PROPERTY_BOOL_EXPR:
27815 {
27816 c_expr texpr = c_parser_expr_no_commas (parser, NULL);
27817 texpr = convert_lvalue_to_rvalue (token->location, texpr,
27818 true, true);
27819 t = texpr.value;
27820 }
27821 if (t == error_mark_node)
27822 return error_mark_node;
27823 mark_exp_read (t);
27824 if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
27825 {
27826 t = c_objc_common_truthvalue_conversion (token->location,
27827 t,
27828 boolean_type_node);
27829 if (t == error_mark_node)
27830 return error_mark_node;
27831 }
27832 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
27833 {
27834 error_at (token->location,
27835 "property must be integer expression");
27836 return error_mark_node;
27837 }
27838 t = c_fully_fold (t, false, NULL);
27839 properties = make_trait_property (NULL_TREE, t, properties);
27840 break;
27841 case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
27842 if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
27843 {
27844 if (parms == NULL_TREE)
27845 {
27846 error_at (token->location, "properties for %<simd%> "
27847 "selector may not be specified in "
27848 "%<metadirective%>");
27849 return error_mark_node;
27850 }
27851 tree c;
27852 c = c_parser_omp_all_clauses (parser,
27853 OMP_DECLARE_SIMD_CLAUSE_MASK,
27854 where: "simd", finish_p: true, nested: 2);
27855 c = c_omp_declare_simd_clauses_to_numbers (parms
27856 == error_mark_node
27857 ? NULL_TREE : parms,
27858 c);
27859 properties = c;
27860 }
27861 else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
27862 {
27863 /* FIXME: The "requires" selector was added in OpenMP 5.1.
27864 Currently only the now-deprecated syntax
27865 from OpenMP 5.0 is supported. */
27866 sorry_at (token->location,
27867 "%<requires%> selector is not supported yet");
27868 return error_mark_node;
27869 }
27870 else
27871 gcc_unreachable ();
27872 break;
27873 default:
27874 gcc_unreachable ();
27875 }
27876
27877 parens.skip_until_found_close (parser);
27878 properties = nreverse (properties);
27879 }
27880 else if (property_kind != OMP_TRAIT_PROPERTY_NONE
27881 && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
27882 && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
27883 {
27884 c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>");
27885 return error_mark_node;
27886 }
27887
27888 ret = make_trait_selector (sel, scoreval, properties, ret);
27889
27890 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27891 c_parser_consume_token (parser);
27892 else
27893 break;
27894 }
27895 while (1);
27896
27897 return nreverse (ret);
27898}
27899
27900/* OpenMP 5.0:
27901
27902 trait-set-selector[,trait-set-selector[,...]]
27903
27904 trait-set-selector:
27905 trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
27906
27907 trait-set-selector-name:
27908 constructor
27909 device
27910 implementation
27911 user */
27912
27913static tree
27914c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
27915{
27916 tree ret = NULL_TREE;
27917 do
27918 {
27919 const char *setp = "";
27920 if (c_parser_next_token_is (parser, type: CPP_NAME))
27921 setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27922 enum omp_tss_code set = omp_lookup_tss_code (setp);
27923
27924 if (set == OMP_TRAIT_SET_INVALID)
27925 {
27926 c_parser_error (parser, gmsgid: "expected context selector set name");
27927 return error_mark_node;
27928 }
27929
27930 c_parser_consume_token (parser);
27931
27932 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
27933 return error_mark_node;
27934
27935 matching_braces braces;
27936 if (!braces.require_open (parser))
27937 return error_mark_node;
27938
27939 tree selectors = c_parser_omp_context_selector (parser, set, parms);
27940 if (selectors == error_mark_node)
27941 {
27942 c_parser_skip_to_closing_brace (parser);
27943 ret = error_mark_node;
27944 }
27945 else if (ret != error_mark_node)
27946 ret = make_trait_set_selector (set, selectors, ret);
27947
27948 braces.require_close (parser);
27949
27950 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27951 c_parser_consume_token (parser);
27952 else
27953 break;
27954 }
27955 while (1);
27956
27957 if (ret == error_mark_node)
27958 return ret;
27959 return nreverse (ret);
27960}
27961
27962/* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
27963 that into "omp declare variant base" attribute. */
27964
27965static void
27966c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
27967{
27968 matching_parens parens;
27969 if (!parens.require_open (parser))
27970 {
27971 fail:
27972 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27973 return;
27974 }
27975
27976 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
27977 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
27978 {
27979 c_parser_error (parser, gmsgid: "expected identifier");
27980 goto fail;
27981 }
27982
27983 c_token *token = c_parser_peek_token (parser);
27984 tree variant = lookup_name (token->value);
27985
27986 if (variant == NULL_TREE)
27987 {
27988 undeclared_variable (token->location, token->value);
27989 variant = error_mark_node;
27990 }
27991 else if (TREE_CODE (variant) != FUNCTION_DECL)
27992 {
27993 error_at (token->location, "variant %qD is not a function",
27994 variant);
27995 variant = error_mark_node;
27996 }
27997 else if (fndecl_built_in_p (node: variant)
27998 && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27999 s2: "__builtin_", n: strlen (s: "__builtin_")) == 0
28000 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
28001 s2: "__sync_", n: strlen (s: "__sync_")) == 0
28002 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
28003 s2: "__atomic_", n: strlen (s: "__atomic_")) == 0))
28004 {
28005 error_at (token->location, "variant %qD is a built-in",
28006 variant);
28007 variant = error_mark_node;
28008 }
28009 else if (variant == fndecl)
28010 {
28011 error_at (token->location, "variant %qD is the same as base function",
28012 variant);
28013 variant = error_mark_node;
28014 }
28015
28016 c_parser_consume_token (parser);
28017
28018 parens.require_close (parser);
28019
28020 tree append_args_tree = NULL_TREE;
28021 tree append_args_last;
28022 vec<tree> adjust_args_list = vNULL;
28023 bool has_match = false, has_adjust_args = false;
28024 location_t adjust_args_loc = UNKNOWN_LOCATION;
28025 location_t append_args_loc = UNKNOWN_LOCATION;
28026 location_t match_loc = UNKNOWN_LOCATION;
28027 tree need_device_ptr_list = NULL_TREE;
28028 tree ctx = error_mark_node;
28029
28030 do
28031 {
28032 if (c_parser_next_token_is (parser, type: CPP_COMMA)
28033 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28034 c_parser_consume_token (parser);
28035
28036 const char *clause = "";
28037 location_t loc = c_parser_peek_token (parser)->location;
28038 if (c_parser_next_token_is (parser, type: CPP_NAME))
28039 clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28040
28041 enum clause
28042 {
28043 match,
28044 adjust_args,
28045 append_args
28046 } ccode;
28047
28048 if (strcmp (s1: clause, s2: "match") == 0)
28049 {
28050 ccode = match;
28051 match_loc = loc;
28052 }
28053 else if (strcmp (s1: clause, s2: "adjust_args") == 0)
28054 {
28055 ccode = adjust_args;
28056 adjust_args_loc = loc;
28057 }
28058 else if (strcmp (s1: clause, s2: "append_args") == 0)
28059 {
28060 ccode = append_args;
28061 append_args_loc = loc;
28062 }
28063 else
28064 {
28065 c_parser_error (parser, gmsgid: "expected %<match%>, %<adjust_args%> or "
28066 "%<append_args%> clause");
28067 goto fail;
28068 }
28069
28070 c_parser_consume_token (parser);
28071
28072 if (!parens.require_open (parser))
28073 goto fail;
28074
28075 if (parms == NULL_TREE)
28076 parms = error_mark_node;
28077
28078 if (ccode == match)
28079 {
28080 if (has_match)
28081 error_at (match_loc, "too many %<match%> clauses");
28082 has_match = true;
28083 ctx = c_parser_omp_context_selector_specification (parser, parms);
28084 if (ctx == error_mark_node)
28085 goto fail;
28086 ctx = omp_check_context_selector (loc: match_loc, ctx,
28087 directive: OMP_CTX_DECLARE_VARIANT);
28088
28089 /* The OpenMP spec says the merging rules for enclosing
28090 "begin declare variant" contexts apply to "declare variant
28091 directives" -- the term it uses to refer to both directive
28092 forms. */
28093 if (ctx != error_mark_node
28094 && !vec_safe_is_empty (v: current_omp_declare_variant_attribute))
28095 {
28096 c_omp_declare_variant_attr a
28097 = current_omp_declare_variant_attribute->last ();
28098 tree outer_ctx = a.selector;
28099 ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx,
28100 OMP_CTX_DECLARE_VARIANT);
28101 }
28102 }
28103 else if (ccode == adjust_args)
28104 {
28105 has_adjust_args = true;
28106 if (c_parser_next_token_is (parser, type: CPP_NAME)
28107 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
28108 {
28109 const char *p
28110 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28111 if (strcmp (s1: p, s2: "need_device_ptr") == 0
28112 || strcmp (s1: p, s2: "nothing") == 0)
28113 {
28114 c_parser_consume_token (parser); // need_device_ptr
28115 c_parser_consume_token (parser); // :
28116
28117 loc = c_parser_peek_token (parser)->location;
28118 tree list
28119 = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_ERROR,
28120 NULL_TREE);
28121
28122 tree arg;
28123 if (variant != error_mark_node)
28124 for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
28125 {
28126 tree decl = TREE_PURPOSE (c);
28127 location_t arg_loc = EXPR_LOCATION (TREE_VALUE (c));
28128 int idx;
28129 for (arg = parms, idx = 0; arg != NULL;
28130 arg = TREE_CHAIN (arg), idx++)
28131 if (arg == decl)
28132 break;
28133 if (arg == NULL_TREE)
28134 {
28135 error_at (arg_loc,
28136 "%qD is not a function argument",
28137 decl);
28138 goto fail;
28139 }
28140 if (adjust_args_list.contains (search: arg))
28141 {
28142 error_at (arg_loc,
28143 "%qD is specified more than once",
28144 decl);
28145 goto fail;
28146 }
28147 if (strcmp (s1: p, s2: "need_device_ptr") == 0
28148 && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
28149 {
28150 error_at (loc, "%qD is not of pointer type", decl);
28151 goto fail;
28152 }
28153 adjust_args_list.safe_push (obj: arg);
28154 if (strcmp (s1: p, s2: "need_device_ptr") == 0)
28155 {
28156 need_device_ptr_list = chainon (
28157 need_device_ptr_list,
28158 build_tree_list (
28159 NULL_TREE,
28160 build_int_cst (
28161 integer_type_node,
28162 idx))); // Store 0-based argument index,
28163 // as in gimplify_call_expr
28164 }
28165 }
28166 }
28167 else
28168 {
28169 error_at (c_parser_peek_token (parser)->location,
28170 "expected %<nothing%> or %<need_device_ptr%>");
28171 if (strcmp (s1: p, s2: "need_device_addr") == 0)
28172 inform (c_parser_peek_token (parser)->location,
28173 "%<need_device_addr%> is not valid for C");
28174 goto fail;
28175 }
28176 }
28177 else
28178 {
28179 error_at (c_parser_peek_token (parser)->location,
28180 "expected %<nothing%> or %<need_device_ptr%> "
28181 "followed by %<:%>");
28182 goto fail;
28183 }
28184 }
28185 else if (ccode == append_args)
28186 {
28187 if (append_args_tree)
28188 {
28189 error_at (append_args_loc, "too many %qs clauses", "append_args");
28190 append_args_tree = NULL_TREE;
28191 }
28192 do
28193 {
28194 location_t loc = c_parser_peek_token (parser)->location;
28195 if (!c_parser_next_token_is (parser, type: CPP_NAME)
28196 || strcmp (s1: "interop",
28197 IDENTIFIER_POINTER (
28198 c_parser_peek_token (parser)->value)))
28199 {
28200 error_at (loc, "expected %<interop%>");
28201 goto fail;
28202 }
28203 c_parser_consume_token (parser);
28204
28205 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
28206 goto fail;
28207 bool target = false;
28208 bool targetsync = false;
28209 tree prefer_type_tree = NULL_TREE;
28210 if (!c_parser_omp_clause_init_modifiers (parser, target: &target,
28211 targetsync: &targetsync,
28212 prefer_type_tree: &prefer_type_tree)
28213 || !c_parser_require (parser, type: CPP_CLOSE_PAREN,
28214 msgid: "expected %<)%> or %<,%>"))
28215 goto fail;
28216 if (!target && !targetsync)
28217 error_at (loc,
28218 "missing required %<target%> and/or "
28219 "%<targetsync%> modifier");
28220 tree t = build_tree_list (target ? boolean_true_node
28221 : boolean_false_node,
28222 targetsync ? boolean_true_node
28223 : boolean_false_node);
28224 t = build1_loc (loc, code: NOP_EXPR, void_type_node, arg1: t);
28225 t = build_tree_list (t, prefer_type_tree);
28226 if (append_args_tree)
28227 {
28228 TREE_CHAIN (append_args_last) = t;
28229 append_args_last = t;
28230 }
28231 else
28232 append_args_tree = append_args_last = t;
28233 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
28234 break;
28235 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<)%> or %<,%>"))
28236 goto fail;
28237 }
28238 while (true);
28239 }
28240
28241 parens.require_close (parser);
28242 } while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL));
28243 if (variant != error_mark_node && !has_match)
28244 {
28245 c_parser_error (parser, gmsgid: "expected %<match%> clause");
28246 variant = error_mark_node;
28247 }
28248 c_parser_skip_to_pragma_eol (parser);
28249
28250 /* At this point, we have completed parsing of the pragma, now it's
28251 on to error checking. */
28252 if (variant == error_mark_node || ctx == error_mark_node)
28253 /* Previously diagnosed error. */
28254 return;
28255
28256 if ((has_adjust_args || append_args_tree)
28257 && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
28258 OMP_TRAIT_CONSTRUCT_DISPATCH))
28259 {
28260 error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
28261 "an %qs clause can only be specified if the "
28262 "%<dispatch%> selector of the %<construct%> selector "
28263 "set appears in the %<match%> clause",
28264 has_adjust_args ? "adjust_args" : "append_args");
28265 return;
28266 }
28267
28268 if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
28269 OMP_TRAIT_CONSTRUCT_SIMD))
28270 /* Check that the base and variant have compatible types. */
28271 {
28272 tree base_type = TREE_TYPE (fndecl);
28273 tree variant_type = TREE_TYPE (variant);
28274 bool unprototyped_variant
28275 = (TYPE_ARG_TYPES (variant_type) == NULL_TREE
28276 && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type));
28277
28278 if (append_args_tree
28279 && TYPE_ARG_TYPES (base_type) == NULL_TREE
28280 && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type))
28281 {
28282 /* The base function is a pre-C23 unprototyped function. Without
28283 a prototype, we don't know the offset where the append_args go.
28284 That offset needs to be stored with the append_args in the
28285 variant function attributes, so we cannot presently handle
28286 this case. */
28287 sorry_at (append_args_loc,
28288 "%<append_args%> with unprototyped base function "
28289 "is not supported yet");
28290 inform (DECL_SOURCE_LOCATION (fndecl),
28291 "base function %qD declared here", fndecl);
28292 return;
28293 }
28294 else if (append_args_tree)
28295 {
28296 /* Find nbase_args, the number of fixed arguments in the base
28297 function. */
28298 int nappend_args = 0;
28299 int nbase_args = 0;
28300 for (tree t = TYPE_ARG_TYPES (base_type);
28301 t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
28302 nbase_args++;
28303 for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
28304 nappend_args++;
28305
28306 /* Store as purpose = arg number after which to append
28307 and value = list of interop items. */
28308 append_args_tree = build_tree_list (build_int_cst (integer_type_node,
28309 nbase_args),
28310 append_args_tree);
28311
28312 /* Give a specific diagnostic if the append_args parameters
28313 of the variant are of the wrong type, or missing. The
28314 compatible types test below could fail to detect this if
28315 the variant is a varargs function. */
28316 if (!unprototyped_variant)
28317 {
28318 tree args = TYPE_ARG_TYPES (variant_type);
28319 for (int i = 0; args && i < nbase_args;
28320 i++, args = TREE_CHAIN (args))
28321 ;
28322 for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args))
28323 if (!args || !c_omp_interop_t_p (TREE_VALUE (args)))
28324 {
28325 error_at (DECL_SOURCE_LOCATION (variant),
28326 "argument %d of %qD must be of "
28327 "%<omp_interop_t%>",
28328 nbase_args + i + 1, variant);
28329 inform (append_args_loc,
28330 "%<append_args%> specified here");
28331 return;
28332 }
28333 }
28334
28335 /* Perform the "implementation defined transformation" on the type
28336 of the base function to add the append_args before checking it
28337 for compatibility with the function variant's type. */
28338 tree args = TYPE_ARG_TYPES (base_type);
28339 tree newargs = NULL_TREE;
28340 tree lastarg = NULL_TREE;
28341 for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args))
28342 {
28343 tree t = tree_cons (TREE_PURPOSE (args),
28344 TREE_VALUE (args), NULL_TREE);
28345 if (lastarg)
28346 TREE_CHAIN (lastarg) = t;
28347 else
28348 newargs = t;
28349 lastarg = t;
28350 }
28351 tree type = lookup_name (get_identifier ("omp_interop_t"));
28352 type = type ? TREE_TYPE (type) : pointer_sized_int_node;
28353 for (int j = 0; j < nappend_args; j++)
28354 {
28355 tree t = tree_cons (NULL_TREE, type, NULL_TREE);
28356 if (lastarg)
28357 TREE_CHAIN (lastarg) = t;
28358 else
28359 newargs = t;
28360 lastarg = t;
28361 }
28362 TREE_CHAIN (lastarg) = args;
28363
28364 /* Temporarily stuff newargs into the original base_type. */
28365 tree saveargs = TYPE_ARG_TYPES (base_type);
28366 TYPE_ARG_TYPES (base_type) = newargs;
28367 bool fail = !comptypes (base_type, variant_type);
28368 TYPE_ARG_TYPES (base_type) = saveargs;
28369
28370 if (fail)
28371 {
28372 error_at (token->location,
28373 "variant %qD and base %qD have incompatible types "
28374 "after %<append_args%> adjustment",
28375 variant, fndecl);
28376 inform (DECL_SOURCE_LOCATION (variant),
28377 "%<declare variant%> candidate %qD declared here",
28378 variant);
28379 return;
28380 }
28381 else if (unprototyped_variant)
28382 /* If we've got an unprototyped variant, copy the transformed
28383 base arg types to the variant. This is needed later by
28384 modify_call_for_omp_dispatch. */
28385 TYPE_ARG_TYPES (variant_type) = newargs;
28386 }
28387 else /* No append_args present. */
28388 {
28389 if (!comptypes (base_type, variant_type))
28390 {
28391 error_at (token->location,
28392 "variant %qD and base %qD have incompatible types",
28393 variant, fndecl);
28394 inform (DECL_SOURCE_LOCATION (variant),
28395 "%<declare variant%> candidate %qD declared here",
28396 variant);
28397 return;
28398 }
28399 else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE
28400 && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)
28401 && TYPE_ARG_TYPES (base_type) != NULL_TREE)
28402 /* If we've got an unprototyped variant but the base has
28403 a prototype, copy the base arg types to the variant. */
28404 TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type);
28405 }
28406 }
28407
28408 /* If we made it here, store the parsed information. */
28409 C_DECL_USED (variant) = 1;
28410 tree construct = omp_get_context_selector_list (ctx,
28411 OMP_TRAIT_SET_CONSTRUCT);
28412 omp_mark_declare_variant (loc: match_loc, variant, construct);
28413 if (omp_context_selector_matches (ctx, NULL_TREE, false))
28414 {
28415 tree attr = tree_cons (get_identifier ("omp declare variant base"),
28416 build_tree_list (variant, ctx),
28417 DECL_ATTRIBUTES (fndecl));
28418 DECL_ATTRIBUTES (fndecl) = attr;
28419 }
28420
28421 if (need_device_ptr_list || append_args_tree)
28422 {
28423 tree variant_decl = tree_strip_nop_conversions (variant);
28424 tree t = build_tree_list (need_device_ptr_list,
28425 NULL_TREE /* need_device_addr */);
28426 TREE_CHAIN (t) = append_args_tree;
28427 DECL_ATTRIBUTES (variant_decl)
28428 = tree_cons (get_identifier ("omp declare variant variant args"), t,
28429 DECL_ATTRIBUTES (variant_decl));
28430 }
28431}
28432
28433/* Finalize #pragma omp declare simd or #pragma omp declare variant
28434 clauses after FNDECL has been parsed, and put that into "omp declare simd"
28435 or "omp declare variant base" attribute. */
28436
28437static void
28438c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
28439 vec<c_token> *pclauses)
28440{
28441 vec<c_token> &clauses = *pclauses;
28442
28443 /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
28444 indicates error has been reported and CPP_PRAGMA that
28445 c_finish_omp_declare_simd has already processed the tokens. */
28446 if (clauses.exists () && clauses[0].type == CPP_EOF)
28447 return;
28448 const char *kind = "simd";
28449 if (clauses.exists ()
28450 && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
28451 kind = IDENTIFIER_POINTER (clauses[0].value);
28452 gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
28453 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
28454 {
28455 error ("%<#pragma omp declare %s%> not immediately followed by "
28456 "a function declaration or definition", kind);
28457 clauses[0].type = CPP_EOF;
28458 return;
28459 }
28460 if (clauses.exists () && clauses[0].type != CPP_NAME)
28461 {
28462 error_at (DECL_SOURCE_LOCATION (fndecl),
28463 "%<#pragma omp declare %s%> not immediately followed by "
28464 "a single function declaration or definition", kind);
28465 clauses[0].type = CPP_EOF;
28466 return;
28467 }
28468 if (DECL_FUNCTION_VERSIONED (fndecl))
28469 {
28470 error_at (DECL_SOURCE_LOCATION (fndecl),
28471 "%<#pragma omp declare %s%> cannot be used with function "
28472 "multi-versioning", kind);
28473 return;
28474 }
28475
28476 if (parms == NULL_TREE)
28477 parms = DECL_ARGUMENTS (fndecl);
28478
28479 unsigned int tokens_avail = parser->tokens_avail;
28480 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
28481
28482 parser->tokens = clauses.address ();
28483 parser->tokens_avail = clauses.length ();
28484
28485 /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
28486 while (parser->tokens_avail > 3)
28487 {
28488 c_token *token = c_parser_peek_token (parser);
28489 gcc_assert (token->type == CPP_NAME);
28490 kind = IDENTIFIER_POINTER (token->value);
28491 c_parser_consume_token (parser);
28492 parser->in_pragma = true;
28493
28494 if (strcmp (s1: kind, s2: "simd") == 0)
28495 {
28496 tree c;
28497 c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
28498 where: "#pragma omp declare simd");
28499 c = c_omp_declare_simd_clauses_to_numbers (parms, c);
28500 if (c != NULL_TREE)
28501 c = tree_cons (NULL_TREE, c, NULL_TREE);
28502 c = build_tree_list (get_identifier ("omp declare simd"), c);
28503 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
28504 DECL_ATTRIBUTES (fndecl) = c;
28505 }
28506 else
28507 {
28508 gcc_assert (strcmp (kind, "variant") == 0);
28509 c_finish_omp_declare_variant (parser, fndecl, parms);
28510 }
28511 }
28512
28513 parser->tokens = &parser->tokens_buf[0];
28514 parser->tokens_avail = tokens_avail;
28515 if (clauses.exists ())
28516 clauses[0].type = CPP_PRAGMA;
28517}
28518
28519/* This is consistent with the C++ front end. */
28520
28521#if !defined (NO_DOT_IN_LABEL)
28522#define JOIN_STR "."
28523#elif !defined (NO_DOLLAR_IN_LABEL)
28524#define JOIN_STR "$"
28525#else
28526#define JOIN_STR "_"
28527#endif
28528
28529/* Helper function for OpenMP "begin declare variant" directives.
28530 Function definitions inside the construct need to have their names
28531 mangled according to the context selector CTX. The DECLARATOR is
28532 modified in place to point to a new identifier; the original name of
28533 the function is returned. */
28534static tree
28535omp_start_variant_function (c_declarator *declarator, tree ctx)
28536{
28537 c_declarator *id = declarator;
28538 while (id->kind != cdk_id)
28539 {
28540 id = id->declarator;
28541 gcc_assert (id);
28542 }
28543 tree name = id->u.id.id;
28544 id->u.id.id = omp_mangle_variant_name (base_id: name, ctx, JOIN_STR);
28545 return name;
28546}
28547
28548/* Helper function for OpenMP "begin declare variant" directives. Now
28549 that we have a DECL for the variant function, and BASE_NAME for the
28550 base function, add an "omp declare variant base" attribute pointing
28551 at CTX to the base decl, and an "omp declare variant variant"
28552 attribute to the variant DECL. */
28553static void
28554omp_finish_variant_function (tree decl, tree base_name, tree ctx)
28555{
28556 /* First look up BASE_NAME and ensure it matches DECL. */
28557 tree base_decl = lookup_name (base_name);
28558 if (base_decl == error_mark_node)
28559 base_decl = NULL_TREE;
28560 if (!base_decl)
28561 {
28562 error_at (DECL_SOURCE_LOCATION (decl),
28563 "no declaration of base function %qs",
28564 IDENTIFIER_POINTER (base_name));
28565 return;
28566 }
28567
28568 if (!comptypes (TREE_TYPE (decl), TREE_TYPE (base_decl)))
28569 {
28570 error_at (DECL_SOURCE_LOCATION (decl),
28571 "variant function definition does not match "
28572 "declaration of %qE", base_decl);
28573 inform (DECL_SOURCE_LOCATION (base_decl),
28574 "%qE declared here", base_decl);
28575 return;
28576 }
28577
28578 /* Now set the attributes on the base and variant decls for the middle
28579 end. */
28580 omp_check_for_duplicate_variant (DECL_SOURCE_LOCATION (decl),
28581 base_decl, ctx);
28582 tree construct
28583 = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
28584 omp_mark_declare_variant (DECL_SOURCE_LOCATION (decl), variant: decl, construct);
28585 tree attrs = DECL_ATTRIBUTES (base_decl);
28586 tree match_loc_node
28587 = maybe_wrap_with_location (integer_zero_node,
28588 DECL_SOURCE_LOCATION (base_decl));
28589 tree loc_node = tree_cons (match_loc_node, integer_zero_node,
28590 build_tree_list (match_loc_node,
28591 integer_zero_node));
28592 attrs = tree_cons (get_identifier ("omp declare variant base"),
28593 tree_cons (decl, ctx, loc_node), attrs);
28594 DECL_ATTRIBUTES (base_decl) = attrs;
28595
28596 /* Variant functions are essentially anonymous and cannot be referenced
28597 outside the compilation unit. */
28598 TREE_PUBLIC (decl) = 0;
28599 DECL_COMDAT (decl) = 0;
28600}
28601
28602
28603/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
28604 a threadprivate, groupprivate, allocate or declare target directive,
28605 return true and parse it for DECL. */
28606
28607bool
28608c_maybe_parse_omp_decl (tree decl, tree d)
28609{
28610 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
28611 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
28612 c_token *first = toks->address ();
28613 c_token *last = first + toks->length ();
28614 const char *directive[3] = {};
28615 for (int j = 0; j < 3; j++)
28616 {
28617 tree id = NULL_TREE;
28618 if (first + j == last)
28619 break;
28620 if (first[j].type == CPP_NAME)
28621 id = first[j].value;
28622 else if (first[j].type == CPP_KEYWORD)
28623 id = ridpointers[(int) first[j].keyword];
28624 else
28625 break;
28626 directive[j] = IDENTIFIER_POINTER (id);
28627 }
28628 const c_omp_directive *dir = NULL;
28629 if (directive[0])
28630 dir = c_omp_categorize_directive (directive[0], directive[1],
28631 directive[2]);
28632 if (dir == NULL)
28633 {
28634 error_at (first->location,
28635 "unknown OpenMP directive name in "
28636 "%qs attribute argument", "omp::decl");
28637 return false;
28638 }
28639 if (dir->id != PRAGMA_OMP_THREADPRIVATE
28640 && dir->id != PRAGMA_OMP_GROUPPRIVATE
28641 && dir->id != PRAGMA_OMP_ALLOCATE
28642 && (dir->id != PRAGMA_OMP_DECLARE
28643 || strcmp (s1: directive[1], s2: "target") != 0))
28644 return false;
28645
28646 if (!flag_openmp && !dir->simd)
28647 return true;
28648
28649 c_parser *parser = the_parser;
28650 unsigned int tokens_avail = parser->tokens_avail;
28651 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
28652 toks = NULL;
28653 vec_safe_reserve (v&: toks, nelems: last - first + 2, exact: true);
28654 c_token tok = {};
28655 tok.type = CPP_PRAGMA;
28656 tok.keyword = RID_MAX;
28657 tok.pragma_kind = pragma_kind (dir->id);
28658 tok.location = first->location;
28659 toks->quick_push (obj: tok);
28660 while (++first < last)
28661 toks->quick_push (obj: *first);
28662 tok = {};
28663 tok.type = CPP_PRAGMA_EOL;
28664 tok.keyword = RID_MAX;
28665 tok.location = last[-1].location;
28666 toks->quick_push (obj: tok);
28667 tok = {};
28668 tok.type = CPP_EOF;
28669 tok.keyword = RID_MAX;
28670 tok.location = last[-1].location;
28671 toks->quick_push (obj: tok);
28672 parser->in_omp_decl_attribute = decl;
28673 gcc_assert (!parser->in_omp_attribute_pragma);
28674 parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
28675 parser->in_omp_attribute_pragma->token_vec = toks;
28676 parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
28677 parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
28678 parser->tokens = toks->address ();
28679 parser->tokens_avail = toks->length ();
28680 c_parser_pragma (parser, context: pragma_external, NULL, NULL_TREE);
28681 parser->in_omp_decl_attribute = NULL_TREE;
28682 return true;
28683}
28684
28685/* OpenMP 4.0:
28686 # pragma omp declare target new-line
28687 declarations and definitions
28688 # pragma omp end declare target new-line
28689
28690 OpenMP 4.5:
28691 # pragma omp declare target ( extended-list ) new-line
28692
28693 # pragma omp declare target declare-target-clauses[seq] new-line */
28694
28695#define OMP_DECLARE_TARGET_CLAUSE_MASK \
28696 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
28697 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
28698 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
28699 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
28700 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
28701
28702static void
28703c_parser_omp_declare_target (c_parser *parser)
28704{
28705 tree clauses = NULL_TREE;
28706 int device_type = 0;
28707 bool indirect = false;
28708 bool only_device_type_or_indirect = true;
28709 if (flag_openmp)
28710 omp_requires_mask
28711 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
28712 if (c_parser_next_token_is (parser, type: CPP_NAME)
28713 || (c_parser_next_token_is (parser, type: CPP_COMMA)
28714 && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
28715 clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
28716 where: "#pragma omp declare target");
28717 else if (parser->in_omp_decl_attribute
28718 || c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
28719 {
28720 clauses = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
28721 list: clauses);
28722 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
28723 c_parser_skip_to_pragma_eol (parser);
28724 }
28725 else
28726 {
28727 warning_at (c_parser_peek_token (parser)->location,
28728 OPT_Wdeprecated_openmp,
28729 "use of %<omp declare target%> as a synonym for "
28730 "%<omp begin declare target%> has been deprecated since "
28731 "OpenMP 5.2");
28732 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28733 c_parser_skip_to_pragma_eol (parser);
28734 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: -1, .indirect: 0 };
28735 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
28736 return;
28737 }
28738 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28739 {
28740 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
28741 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
28742 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28743 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
28744 }
28745 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28746 {
28747 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
28748 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28749 continue;
28750 tree t = OMP_CLAUSE_DECL (c), id;
28751 tree at1 = lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (t));
28752 tree at2 = lookup_attribute (attr_name: "omp declare target link",
28753 DECL_ATTRIBUTES (t));
28754 only_device_type_or_indirect = false;
28755 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
28756 {
28757 id = get_identifier ("omp declare target link");
28758 std::swap (a&: at1, b&: at2);
28759 }
28760 else
28761 id = get_identifier ("omp declare target");
28762 if (at2)
28763 {
28764 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
28765 error_at (OMP_CLAUSE_LOCATION (c),
28766 "%qD specified both in declare target %<link%> and %qs"
28767 " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
28768 else
28769 error_at (OMP_CLAUSE_LOCATION (c),
28770 "%qD specified both in declare target %<link%> and "
28771 "%<to%> or %<enter%> clauses", t);
28772 continue;
28773 }
28774 if (!at1)
28775 {
28776 DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28777 if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
28778 continue;
28779
28780 symtab_node *node = symtab_node::get (decl: t);
28781 if (node != NULL)
28782 {
28783 node->offloadable = 1;
28784 if (ENABLE_OFFLOADING)
28785 {
28786 g->have_offload = true;
28787 if (is_a <varpool_node *> (p: node))
28788 vec_safe_push (v&: offload_vars, obj: t);
28789 }
28790 }
28791 }
28792 if (TREE_CODE (t) != FUNCTION_DECL)
28793 continue;
28794 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
28795 {
28796 tree at3 = lookup_attribute (attr_name: "omp declare target host",
28797 DECL_ATTRIBUTES (t));
28798 if (at3 == NULL_TREE)
28799 {
28800 id = get_identifier ("omp declare target host");
28801 DECL_ATTRIBUTES (t)
28802 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28803 }
28804 }
28805 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
28806 {
28807 tree at3 = lookup_attribute (attr_name: "omp declare target nohost",
28808 DECL_ATTRIBUTES (t));
28809 if (at3 == NULL_TREE)
28810 {
28811 id = get_identifier ("omp declare target nohost");
28812 DECL_ATTRIBUTES (t)
28813 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28814 }
28815 }
28816 if (indirect)
28817 {
28818 tree at4 = lookup_attribute (attr_name: "omp declare target indirect",
28819 DECL_ATTRIBUTES (t));
28820 if (at4 == NULL_TREE)
28821 {
28822 id = get_identifier ("omp declare target indirect");
28823 DECL_ATTRIBUTES (t)
28824 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28825 }
28826 }
28827 }
28828 if ((device_type || indirect) && only_device_type_or_indirect)
28829 error_at (OMP_CLAUSE_LOCATION (clauses),
28830 "directive with only %<device_type%> or %<indirect%> clauses");
28831 if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
28832 error_at (OMP_CLAUSE_LOCATION (clauses),
28833 "%<device_type%> clause must specify 'any' when used with "
28834 "an %<indirect%> clause");
28835}
28836
28837/* OpenMP 5.1
28838 #pragma omp begin assumes clauses[optseq] new-line
28839
28840 #pragma omp begin declare target clauses[optseq] new-line
28841
28842 #pragma omp begin declare variant match (context-selector) new-line */
28843
28844#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
28845 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
28846 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
28847
28848static void
28849c_parser_omp_begin (c_parser *parser)
28850{
28851 const char *p = "";
28852 c_parser_consume_pragma (parser);
28853 if (c_parser_next_token_is (parser, type: CPP_NAME))
28854 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28855 if (strcmp (s1: p, s2: "declare") == 0)
28856 {
28857 c_parser_consume_token (parser);
28858 p = "";
28859 if (c_parser_next_token_is (parser, type: CPP_NAME))
28860 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28861 if (strcmp (s1: p, s2: "target") == 0)
28862 {
28863 c_parser_consume_token (parser);
28864 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28865 tree clauses
28866 = c_parser_omp_all_clauses (parser,
28867 OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
28868 where: "#pragma omp begin declare target");
28869 int device_type = 0;
28870 int indirect = 0;
28871 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28872 {
28873 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
28874 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
28875 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28876 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
28877 }
28878 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: device_type,
28879 .indirect: indirect };
28880 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
28881 }
28882 else if (strcmp (s1: p, s2: "variant") == 0)
28883 {
28884 c_parser_consume_token (parser);
28885 const char *clause = "";
28886 matching_parens parens;
28887 location_t match_loc = c_parser_peek_token (parser)->location;
28888 if (c_parser_next_token_is (parser, type: CPP_COMMA))
28889 c_parser_consume_token (parser);
28890 if (c_parser_next_token_is (parser, type: CPP_NAME))
28891 {
28892 tree id = c_parser_peek_token (parser)->value;
28893 clause = IDENTIFIER_POINTER (id);
28894 }
28895 if (strcmp (s1: clause, s2: "match") != 0)
28896 {
28897 c_parser_error (parser, gmsgid: "expected %<match%>");
28898 c_parser_skip_to_pragma_eol (parser);
28899 return;
28900 }
28901
28902 c_parser_consume_token (parser);
28903
28904 if (!parens.require_open (parser))
28905 {
28906 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28907 return;
28908 }
28909
28910 tree ctx =
28911 c_parser_omp_context_selector_specification (parser, NULL_TREE);
28912 if (ctx != error_mark_node)
28913 ctx = omp_check_context_selector (loc: match_loc, ctx,
28914 directive: OMP_CTX_BEGIN_DECLARE_VARIANT);
28915
28916 if (ctx != error_mark_node
28917 && !vec_safe_is_empty (v: current_omp_declare_variant_attribute))
28918 {
28919 c_omp_declare_variant_attr a
28920 = current_omp_declare_variant_attribute->last ();
28921 tree outer_ctx = a.selector;
28922 ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx,
28923 OMP_CTX_BEGIN_DECLARE_VARIANT);
28924 }
28925
28926 if (ctx == error_mark_node
28927 || !omp_context_selector_matches (ctx, NULL_TREE, false, true))
28928 {
28929 /* The context is either invalid or cannot possibly match.
28930 In the latter case the spec says all code in the begin/end
28931 sequence will be elided. In the former case we'll get bogus
28932 errors from trying to parse it without a valid context to
28933 use for name-mangling, so elide that too. */
28934 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28935 c_parser_skip_to_pragma_omp_end_declare_variant (parser);
28936 return;
28937 }
28938 else
28939 {
28940 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28941 c_omp_declare_variant_attr a = { .attr_syntax: attr_syntax, .selector: ctx };
28942 vec_safe_push (v&: current_omp_declare_variant_attribute, obj: a);
28943 }
28944
28945 parens.require_close (parser);
28946 c_parser_skip_to_pragma_eol (parser);
28947 }
28948 else
28949 {
28950 c_parser_error (parser, gmsgid: "expected %<target%> or %<variant%>");
28951 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28952 }
28953 }
28954 else if (strcmp (s1: p, s2: "assumes") == 0)
28955 {
28956 c_parser_consume_token (parser);
28957 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28958 c_parser_omp_assumption_clauses (parser, false);
28959 struct c_omp_begin_assumes_data a = { .attr_syntax: attr_syntax };
28960 vec_safe_push (v&: current_omp_begin_assumes, obj: a);
28961 }
28962 else
28963 {
28964 c_parser_error (parser, gmsgid: "expected %<declare target%>, "
28965 "%<declare variant%>, or %<assumes%>");
28966 c_parser_skip_to_pragma_eol (parser);
28967 }
28968}
28969
28970/* OpenMP 4.0
28971 #pragma omp end declare target
28972
28973 OpenMP 5.1
28974 #pragma omp end assumes
28975 #pragma omp end declare variant */
28976
28977static void
28978c_parser_omp_end (c_parser *parser)
28979{
28980 location_t loc = c_parser_peek_token (parser)->location;
28981 const char *p = "";
28982 c_parser_consume_pragma (parser);
28983 if (c_parser_next_token_is (parser, type: CPP_NAME))
28984 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28985 if (strcmp (s1: p, s2: "declare") == 0)
28986 {
28987 c_parser_consume_token (parser);
28988 p = "";
28989 if (c_parser_next_token_is (parser, type: CPP_NAME))
28990 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28991 if (strcmp (s1: p, s2: "target") == 0)
28992 {
28993 c_parser_consume_token (parser);
28994 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28995 c_parser_skip_to_pragma_eol (parser);
28996 if (!vec_safe_length (v: current_omp_declare_target_attribute))
28997 error_at (loc, "%<#pragma omp end declare target%> without "
28998 "corresponding %<#pragma omp declare target%> or "
28999 "%<#pragma omp begin declare target%>");
29000 else
29001 {
29002 c_omp_declare_target_attr
29003 a = current_omp_declare_target_attribute->pop ();
29004 if (a.attr_syntax != attr_syntax)
29005 {
29006 if (a.attr_syntax)
29007 error_at (loc,
29008 "%qs in attribute syntax terminated "
29009 "with %qs in pragma syntax",
29010 a.device_type >= 0 ? "begin declare target"
29011 : "declare target",
29012 "end declare target");
29013 else
29014 error_at (loc,
29015 "%qs in pragma syntax terminated "
29016 "with %qs in attribute syntax",
29017 a.device_type >= 0 ? "begin declare target"
29018 : "declare target",
29019 "end declare target");
29020 }
29021 }
29022 }
29023 else if (strcmp (s1: p, s2: "variant") == 0)
29024 {
29025 c_parser_consume_token (parser);
29026 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
29027 c_parser_skip_to_pragma_eol (parser);
29028 if (!vec_safe_length (v: current_omp_declare_variant_attribute))
29029 error_at (loc, "%<#pragma omp end declare variant%> without "
29030 "corresponding %<#pragma omp begin declare variant%>");
29031 else
29032 {
29033 c_omp_declare_variant_attr
29034 a = current_omp_declare_variant_attribute->pop ();
29035 if (a.attr_syntax != attr_syntax)
29036 {
29037 if (a.attr_syntax)
29038 error_at (loc,
29039 "%<begin declare variant%> in attribute syntax "
29040 "terminated with "
29041 "%<end declare variant%> in pragma syntax");
29042 else
29043 error_at (loc,
29044 "%<begin declare variant%> in pragma syntax "
29045 "terminated with "
29046 "%<end declare variant%> in attribute syntax");
29047 }
29048 }
29049 }
29050 else
29051 {
29052 c_parser_error (parser, gmsgid: "expected %<target%> or %<variant%>");
29053 c_parser_skip_to_pragma_eol (parser);
29054 return;
29055 }
29056 }
29057 else if (strcmp (s1: p, s2: "assumes") == 0)
29058 {
29059 c_parser_consume_token (parser);
29060 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
29061 c_parser_skip_to_pragma_eol (parser);
29062 if (!vec_safe_length (v: current_omp_begin_assumes))
29063 error_at (loc, "%qs without corresponding %qs",
29064 "#pragma omp end assumes", "#pragma omp begin assumes");
29065 else
29066 {
29067 c_omp_begin_assumes_data
29068 a = current_omp_begin_assumes->pop ();
29069 if (a.attr_syntax != attr_syntax)
29070 {
29071 if (a.attr_syntax)
29072 error_at (loc,
29073 "%qs in attribute syntax terminated "
29074 "with %qs in pragma syntax",
29075 "begin assumes", "end assumes");
29076 else
29077 error_at (loc,
29078 "%qs in pragma syntax terminated "
29079 "with %qs in attribute syntax",
29080 "begin assumes", "end assumes");
29081 }
29082 }
29083 }
29084 else
29085 {
29086 c_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>");
29087 c_parser_skip_to_pragma_eol (parser);
29088 }
29089}
29090
29091/* OpenMP 5.0
29092 #pragma omp declare mapper ([mapper-identifier :] type var) \
29093 [clause [ [,] clause ] ... ] new-line */
29094
29095static void
29096c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
29097{
29098 tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
29099 tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
29100 c_token *token;
29101
29102 if (context == pragma_struct || context == pragma_param)
29103 {
29104 error ("%<#pragma omp declare mapper%> not at file or block scope");
29105 goto fail;
29106 }
29107
29108 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
29109 goto fail;
29110
29111 token = c_parser_peek_token (parser);
29112
29113 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
29114 {
29115 switch (token->type)
29116 {
29117 case CPP_NAME:
29118 mapper_name = token->value;
29119 c_parser_consume_token (parser);
29120 break;
29121 case CPP_KEYWORD:
29122 if (token->keyword == RID_DEFAULT)
29123 {
29124 mapper_name = NULL_TREE;
29125 c_parser_consume_token (parser);
29126 break;
29127 }
29128 /* Fallthrough. */
29129 default:
29130 error_at (token->location, "expected identifier or %<default%>");
29131 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29132 return;
29133 }
29134
29135 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
29136 goto fail;
29137 }
29138
29139 mapper_id = c_omp_mapper_id (mapper_name);
29140 mapper_decl = c_omp_mapper_decl (mapper_id);
29141
29142 {
29143 location_t loc = c_parser_peek_token (parser)->location;
29144 struct c_type_name *ctype = c_parser_type_name (parser);
29145 type = groktypename (ctype, NULL, NULL);
29146 if (type == error_mark_node)
29147 goto fail;
29148 if (!RECORD_OR_UNION_TYPE_P (type))
29149 {
29150 error_at (loc, "%qT is not a struct or union type in "
29151 "%<#pragma omp declare mapper%>", type);
29152 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29153 return;
29154 }
29155 for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
29156 if (comptypes (TREE_PURPOSE (t), type))
29157 {
29158 error_at (loc, "redeclaration of %qs %<#pragma omp declare "
29159 "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
29160 + sizeof ("omp declare mapper ") - 1,
29161 type);
29162 tree prevmapper = TREE_VALUE (t);
29163 /* Hmm, this location might not be very accurate. */
29164 location_t ploc
29165 = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
29166 inform (ploc, "%<#pragma omp declare mapper%> "
29167 "previously declared here");
29168 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29169 return;
29170 }
29171 }
29172
29173 token = c_parser_peek_token (parser);
29174 if (token->type == CPP_NAME)
29175 {
29176 var = build_decl (token->location, VAR_DECL, token->value, type);
29177 c_parser_consume_token (parser);
29178 DECL_ARTIFICIAL (var) = 1;
29179 }
29180 else
29181 {
29182 error_at (token->location, "expected identifier");
29183 goto fail;
29184 }
29185
29186 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
29187 goto fail;
29188
29189 push_scope ();
29190 stmtlist = push_stmt_list ();
29191 pushdecl (var);
29192 DECL_CONTEXT (var) = current_function_decl;
29193
29194 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
29195 {
29196 location_t here;
29197 pragma_omp_clause c_kind;
29198 here = c_parser_peek_token (parser)->location;
29199 c_kind = c_parser_omp_clause_name (parser);
29200 if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
29201 {
29202 error_at (here, "unexpected clause");
29203 goto fail;
29204 }
29205 maplist = c_parser_omp_clause_map (parser, list: maplist, declare_mapper_p: true);
29206 }
29207
29208 if (maplist == NULL_TREE)
29209 {
29210 error_at (input_location, "missing %<map%> clause");
29211 goto fail;
29212 }
29213
29214 stmt = make_node (OMP_DECLARE_MAPPER);
29215 TREE_TYPE (stmt) = type;
29216 OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
29217 OMP_DECLARE_MAPPER_DECL (stmt) = var;
29218 OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
29219
29220 add_stmt (stmt);
29221
29222 pop_stmt_list (stmtlist);
29223 pop_scope ();
29224
29225 c_parser_skip_to_pragma_eol (parser);
29226
29227 t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
29228 DECL_INITIAL (mapper_decl) = t;
29229
29230 return;
29231
29232 fail:
29233 c_parser_skip_to_pragma_eol (parser);
29234}
29235
29236/* OpenMP 4.0
29237 #pragma omp declare reduction (reduction-id : typename-list : expression) \
29238 initializer-clause[opt] new-line
29239
29240 initializer-clause:
29241 initializer (omp_priv = initializer)
29242 initializer (function-name (argument-list)) */
29243
29244static void
29245c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
29246{
29247 unsigned int tokens_avail = 0, i;
29248 c_token *saved_tokens = NULL;
29249 vec<tree> types = vNULL;
29250 vec<c_token> clauses = vNULL;
29251 enum tree_code reduc_code = ERROR_MARK;
29252 tree reduc_id = NULL_TREE;
29253 tree type;
29254 location_t rloc = c_parser_peek_token (parser)->location;
29255
29256 if (context == pragma_struct || context == pragma_param)
29257 {
29258 error ("%<#pragma omp declare reduction%> not at file or block scope");
29259 goto fail;
29260 }
29261
29262 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
29263 goto fail;
29264
29265 switch (c_parser_peek_token (parser)->type)
29266 {
29267 case CPP_PLUS:
29268 reduc_code = PLUS_EXPR;
29269 break;
29270 case CPP_MULT:
29271 reduc_code = MULT_EXPR;
29272 break;
29273 case CPP_MINUS:
29274 reduc_code = MINUS_EXPR;
29275 break;
29276 case CPP_AND:
29277 reduc_code = BIT_AND_EXPR;
29278 break;
29279 case CPP_XOR:
29280 reduc_code = BIT_XOR_EXPR;
29281 break;
29282 case CPP_OR:
29283 reduc_code = BIT_IOR_EXPR;
29284 break;
29285 case CPP_AND_AND:
29286 reduc_code = TRUTH_ANDIF_EXPR;
29287 break;
29288 case CPP_OR_OR:
29289 reduc_code = TRUTH_ORIF_EXPR;
29290 break;
29291 case CPP_NAME:
29292 const char *p;
29293 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29294 if (strcmp (s1: p, s2: "min") == 0)
29295 {
29296 reduc_code = MIN_EXPR;
29297 break;
29298 }
29299 if (strcmp (s1: p, s2: "max") == 0)
29300 {
29301 reduc_code = MAX_EXPR;
29302 break;
29303 }
29304 reduc_id = c_parser_peek_token (parser)->value;
29305 break;
29306 default:
29307 c_parser_error (parser,
29308 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
29309 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
29310 goto fail;
29311 }
29312
29313 tree orig_reduc_id, reduc_decl;
29314 orig_reduc_id = reduc_id;
29315 reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
29316 reduc_decl = c_omp_reduction_decl (reduc_id);
29317 c_parser_consume_token (parser);
29318
29319 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
29320 goto fail;
29321
29322 while (true)
29323 {
29324 location_t loc = c_parser_peek_token (parser)->location;
29325 struct c_type_name *ctype = c_parser_type_name (parser);
29326 if (ctype != NULL)
29327 {
29328 type = groktypename (ctype, NULL, NULL);
29329 if (type == error_mark_node)
29330 ;
29331 else if ((INTEGRAL_TYPE_P (type)
29332 || SCALAR_FLOAT_TYPE_P (type)
29333 || TREE_CODE (type) == COMPLEX_TYPE)
29334 && orig_reduc_id == NULL_TREE)
29335 error_at (loc, "predeclared arithmetic type in "
29336 "%<#pragma omp declare reduction%>");
29337 else if (TREE_CODE (type) == FUNCTION_TYPE
29338 || TREE_CODE (type) == ARRAY_TYPE)
29339 error_at (loc, "function or array type in "
29340 "%<#pragma omp declare reduction%>");
29341 else if (TYPE_ATOMIC (type))
29342 error_at (loc, "%<_Atomic%> qualified type in "
29343 "%<#pragma omp declare reduction%>");
29344 else if (TYPE_QUALS_NO_ADDR_SPACE (type))
29345 error_at (loc, "const, volatile or restrict qualified type in "
29346 "%<#pragma omp declare reduction%>");
29347 else
29348 {
29349 tree t;
29350 for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
29351 if (comptypes (TREE_PURPOSE (t), type))
29352 {
29353 error_at (loc, "redeclaration of %qs "
29354 "%<#pragma omp declare reduction%> for "
29355 "type %qT",
29356 IDENTIFIER_POINTER (reduc_id)
29357 + sizeof ("omp declare reduction ") - 1,
29358 type);
29359 location_t ploc
29360 = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
29361 0));
29362 inform (ploc, "%<#pragma omp declare reduction%> "
29363 "previously declared here");
29364 break;
29365 }
29366 if (t == NULL_TREE)
29367 types.safe_push (obj: type);
29368 }
29369 if (c_parser_next_token_is (parser, type: CPP_COMMA))
29370 c_parser_consume_token (parser);
29371 else
29372 break;
29373 }
29374 else
29375 break;
29376 }
29377
29378 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>")
29379 || types.is_empty ())
29380 {
29381 fail:
29382 clauses.release ();
29383 types.release ();
29384 while (true)
29385 {
29386 c_token *token = c_parser_peek_token (parser);
29387 if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
29388 break;
29389 c_parser_consume_token (parser);
29390 }
29391 c_parser_skip_to_pragma_eol (parser);
29392 return;
29393 }
29394
29395 if (types.length () > 1)
29396 {
29397 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
29398 {
29399 c_token *token = c_parser_peek_token (parser);
29400 if (token->type == CPP_EOF)
29401 goto fail;
29402 clauses.safe_push (obj: *token);
29403 c_parser_consume_token (parser);
29404 }
29405 clauses.safe_push (obj: *c_parser_peek_token (parser));
29406 c_parser_skip_to_pragma_eol (parser);
29407
29408 /* Make sure nothing tries to read past the end of the tokens. */
29409 c_token eof_token;
29410 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
29411 eof_token.type = CPP_EOF;
29412 clauses.safe_push (obj: eof_token);
29413 clauses.safe_push (obj: eof_token);
29414 }
29415
29416 int errs = errorcount;
29417 FOR_EACH_VEC_ELT (types, i, type)
29418 {
29419 saved_tokens = parser->tokens;
29420 tokens_avail = parser->tokens_avail;
29421 if (!clauses.is_empty ())
29422 {
29423 parser->tokens = clauses.address ();
29424 parser->tokens_avail = clauses.length ();
29425 parser->in_pragma = true;
29426 }
29427
29428 bool nested = current_function_decl != NULL_TREE;
29429 if (nested)
29430 c_push_function_context ();
29431 tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
29432 reduc_id, default_function_type);
29433 current_function_decl = fndecl;
29434 allocate_struct_function (fndecl, true);
29435 push_scope ();
29436 tree stmt = push_stmt_list ();
29437 /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
29438 warn about these. */
29439 tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
29440 get_identifier ("omp_out"), type);
29441 DECL_ARTIFICIAL (omp_out) = 1;
29442 DECL_CONTEXT (omp_out) = fndecl;
29443 pushdecl (omp_out);
29444 tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
29445 get_identifier ("omp_in"), type);
29446 DECL_ARTIFICIAL (omp_in) = 1;
29447 DECL_CONTEXT (omp_in) = fndecl;
29448 pushdecl (omp_in);
29449 struct c_expr combiner = c_parser_expression (parser);
29450 struct c_expr initializer;
29451 tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
29452 bool bad = false;
29453 initializer.set_error ();
29454 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
29455 bad = true;
29456 else if (c_parser_next_token_is (parser, type: CPP_COMMA)
29457 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29458 c_parser_consume_token (parser);
29459 if (!bad
29460 && (c_parser_next_token_is (parser, type: CPP_NAME)
29461 && strcmp (IDENTIFIER_POINTER
29462 (c_parser_peek_token (parser)->value),
29463 s2: "initializer") == 0))
29464 {
29465 c_parser_consume_token (parser);
29466 pop_scope ();
29467 push_scope ();
29468 omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
29469 get_identifier ("omp_priv"), type);
29470 DECL_ARTIFICIAL (omp_priv) = 1;
29471 DECL_INITIAL (omp_priv) = error_mark_node;
29472 DECL_CONTEXT (omp_priv) = fndecl;
29473 pushdecl (omp_priv);
29474 omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
29475 get_identifier ("omp_orig"), type);
29476 DECL_ARTIFICIAL (omp_orig) = 1;
29477 DECL_CONTEXT (omp_orig) = fndecl;
29478 pushdecl (omp_orig);
29479 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
29480 bad = true;
29481 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
29482 {
29483 c_parser_error (parser, gmsgid: "expected %<omp_priv%> or "
29484 "function-name");
29485 bad = true;
29486 }
29487 else if (strcmp (IDENTIFIER_POINTER
29488 (c_parser_peek_token (parser)->value),
29489 s2: "omp_priv") != 0)
29490 {
29491 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
29492 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
29493 {
29494 c_parser_error (parser, gmsgid: "expected function-name %<(%>");
29495 bad = true;
29496 }
29497 else
29498 initializer = c_parser_postfix_expression (parser);
29499 if (initializer.value
29500 && TREE_CODE (initializer.value) == CALL_EXPR)
29501 {
29502 int j;
29503 tree c = initializer.value;
29504 for (j = 0; j < call_expr_nargs (c); j++)
29505 {
29506 tree a = CALL_EXPR_ARG (c, j);
29507 STRIP_NOPS (a);
29508 if (TREE_CODE (a) == ADDR_EXPR
29509 && TREE_OPERAND (a, 0) == omp_priv)
29510 break;
29511 }
29512 if (j == call_expr_nargs (c))
29513 error ("one of the initializer call arguments should be "
29514 "%<&omp_priv%>");
29515 }
29516 }
29517 else
29518 {
29519 c_parser_consume_token (parser);
29520 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
29521 bad = true;
29522 else
29523 {
29524 tree st = push_stmt_list ();
29525 location_t loc = c_parser_peek_token (parser)->location;
29526 rich_location richloc (line_table, loc);
29527 start_init (omp_priv, NULL_TREE, false, false, &richloc);
29528 struct c_expr init = c_parser_initializer (parser, decl: omp_priv);
29529 finish_init ();
29530 finish_decl (omp_priv, loc, init.value,
29531 init.original_type, NULL_TREE);
29532 pop_stmt_list (st);
29533 }
29534 }
29535 if (!bad
29536 && !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
29537 bad = true;
29538 }
29539
29540 if (!bad)
29541 {
29542 c_parser_skip_to_pragma_eol (parser);
29543
29544 tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
29545 DECL_INITIAL (reduc_decl));
29546 DECL_INITIAL (reduc_decl) = t;
29547 DECL_SOURCE_LOCATION (omp_out) = rloc;
29548 TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
29549 TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
29550 TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
29551 walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
29552 &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
29553 if (omp_priv)
29554 {
29555 DECL_SOURCE_LOCATION (omp_priv) = rloc;
29556 TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
29557 TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
29558 TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
29559 walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
29560 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
29561 walk_tree (&DECL_INITIAL (omp_priv),
29562 c_check_omp_declare_reduction_r,
29563 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
29564 }
29565 }
29566
29567 pop_stmt_list (stmt);
29568 pop_scope ();
29569 if (cfun->language != NULL)
29570 {
29571 ggc_free (cfun->language);
29572 cfun->language = NULL;
29573 }
29574 set_cfun (NULL);
29575 current_function_decl = NULL_TREE;
29576 if (nested)
29577 c_pop_function_context ();
29578
29579 if (!clauses.is_empty ())
29580 {
29581 parser->tokens = saved_tokens;
29582 parser->tokens_avail = tokens_avail;
29583 }
29584 if (bad)
29585 goto fail;
29586 if (errs != errorcount)
29587 break;
29588 }
29589
29590 clauses.release ();
29591 types.release ();
29592}
29593
29594/* OpenMP 4.0
29595 #pragma omp declare simd declare-simd-clauses[optseq] new-line
29596 #pragma omp declare reduction (reduction-id : typename-list : expression) \
29597 initializer-clause[opt] new-line
29598 #pragma omp declare target new-line
29599
29600 OpenMP 5.0
29601 #pragma omp declare variant (identifier) match (context-selector)
29602
29603 OpenMP 5.1
29604 #pragma omp declare variant (identifier) match (context-selector) \
29605 adjust_args(adjust-op:argument-list) */
29606
29607static bool
29608c_parser_omp_declare (c_parser *parser, enum pragma_context context)
29609{
29610 c_parser_consume_pragma (parser);
29611 if (c_parser_next_token_is (parser, type: CPP_NAME))
29612 {
29613 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29614 if (strcmp (s1: p, s2: "simd") == 0)
29615 {
29616 /* c_parser_consume_token (parser); done in
29617 c_parser_omp_declare_simd. */
29618 c_parser_omp_declare_simd (parser, context);
29619 return true;
29620 }
29621 if (strcmp (s1: p, s2: "reduction") == 0)
29622 {
29623 c_parser_consume_token (parser);
29624 c_parser_omp_declare_reduction (parser, context);
29625 return false;
29626 }
29627 if (strcmp (s1: p, s2: "mapper") == 0)
29628 {
29629 c_parser_consume_token (parser);
29630 c_parser_omp_declare_mapper (parser, context);
29631 return false;
29632 }
29633 if (!flag_openmp) /* flag_openmp_simd */
29634 {
29635 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29636 return false;
29637 }
29638 if (strcmp (s1: p, s2: "target") == 0)
29639 {
29640 c_parser_consume_token (parser);
29641 c_parser_omp_declare_target (parser);
29642 return false;
29643 }
29644 if (strcmp (s1: p, s2: "variant") == 0)
29645 {
29646 /* c_parser_consume_token (parser); done in
29647 c_parser_omp_declare_simd. */
29648 c_parser_omp_declare_simd (parser, context);
29649 return true;
29650 }
29651 }
29652
29653 c_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, "
29654 "%<target%> or %<variant%>");
29655 c_parser_skip_to_pragma_eol (parser);
29656 return false;
29657}
29658
29659/* OpenMP 5.0
29660 #pragma omp requires clauses[optseq] new-line */
29661
29662static void
29663c_parser_omp_requires (c_parser *parser)
29664{
29665 enum omp_requires new_req = (enum omp_requires) 0;
29666
29667 c_parser_consume_pragma (parser);
29668
29669 location_t loc = c_parser_peek_token (parser)->location;
29670 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
29671 {
29672 if (c_parser_next_token_is (parser, type: CPP_COMMA)
29673 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29674 c_parser_consume_token (parser);
29675
29676 if (c_parser_next_token_is (parser, type: CPP_NAME))
29677 {
29678 const char *p
29679 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29680 location_t cloc = c_parser_peek_token (parser)->location;
29681 enum omp_requires this_req = (enum omp_requires) 0;
29682
29683 if (!strcmp (s1: p, s2: "unified_address"))
29684 this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
29685 else if (!strcmp (s1: p, s2: "unified_shared_memory"))
29686 this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
29687 else if (!strcmp (s1: p, s2: "self_maps"))
29688 this_req = OMP_REQUIRES_SELF_MAPS;
29689 else if (!strcmp (s1: p, s2: "dynamic_allocators"))
29690 this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
29691 else if (!strcmp (s1: p, s2: "reverse_offload"))
29692 this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
29693 else if (!strcmp (s1: p, s2: "atomic_default_mem_order"))
29694 {
29695 c_parser_consume_token (parser);
29696
29697 matching_parens parens;
29698 if (parens.require_open (parser))
29699 {
29700 if (c_parser_next_token_is (parser, type: CPP_NAME))
29701 {
29702 tree v = c_parser_peek_token (parser)->value;
29703 p = IDENTIFIER_POINTER (v);
29704
29705 if (!strcmp (s1: p, s2: "seq_cst"))
29706 this_req
29707 = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
29708 else if (!strcmp (s1: p, s2: "relaxed"))
29709 this_req
29710 = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
29711 else if (!strcmp (s1: p, s2: "release"))
29712 this_req
29713 = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
29714 else if (!strcmp (s1: p, s2: "acq_rel"))
29715 this_req
29716 = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
29717 else if (!strcmp (s1: p, s2: "acquire"))
29718 this_req
29719 = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
29720 }
29721 if (this_req == 0)
29722 {
29723 error_at (c_parser_peek_token (parser)->location,
29724 "expected %<acq_rel%>, %<acquire%>, "
29725 "%<relaxed%>, %<release%> or %<seq_cst%>");
29726 switch (c_parser_peek_token (parser)->type)
29727 {
29728 case CPP_EOF:
29729 case CPP_PRAGMA_EOL:
29730 case CPP_CLOSE_PAREN:
29731 break;
29732 default:
29733 if (c_parser_peek_2nd_token (parser)->type
29734 == CPP_CLOSE_PAREN)
29735 c_parser_consume_token (parser);
29736 break;
29737 }
29738 }
29739 else
29740 c_parser_consume_token (parser);
29741
29742 parens.skip_until_found_close (parser);
29743 if (this_req == 0)
29744 {
29745 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29746 return;
29747 }
29748 }
29749 p = NULL;
29750 }
29751 else
29752 {
29753 error_at (cloc, "expected %<unified_address%>, "
29754 "%<unified_shared_memory%>, "
29755 "%<self_maps%>, "
29756 "%<dynamic_allocators%>, "
29757 "%<reverse_offload%> "
29758 "or %<atomic_default_mem_order%> clause");
29759 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29760 return;
29761 }
29762 if (p)
29763 c_parser_consume_token (parser);
29764 if (this_req)
29765 {
29766 if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29767 {
29768 if ((this_req & new_req) != 0)
29769 error_at (cloc, "too many %qs clauses", p);
29770 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
29771 && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
29772 error_at (cloc, "%qs clause used lexically after first "
29773 "target construct or offloading API", p);
29774 }
29775 else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29776 {
29777 error_at (cloc, "too many %qs clauses",
29778 "atomic_default_mem_order");
29779 this_req = (enum omp_requires) 0;
29780 }
29781 else if ((omp_requires_mask
29782 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29783 {
29784 error_at (cloc, "more than one %<atomic_default_mem_order%>"
29785 " clause in a single compilation unit");
29786 this_req
29787 = (enum omp_requires)
29788 (omp_requires_mask
29789 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
29790 }
29791 else if ((omp_requires_mask
29792 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
29793 error_at (cloc, "%<atomic_default_mem_order%> clause used "
29794 "lexically after first %<atomic%> construct "
29795 "without memory order clause");
29796 new_req = (enum omp_requires) (new_req | this_req);
29797 omp_requires_mask
29798 = (enum omp_requires) (omp_requires_mask | this_req);
29799 continue;
29800 }
29801 }
29802 break;
29803 }
29804 c_parser_skip_to_pragma_eol (parser);
29805
29806 if (new_req == 0)
29807 error_at (loc, "%<pragma omp requires%> requires at least one clause");
29808}
29809
29810/* Helper function for c_parser_omp_taskloop.
29811 Disallow zero sized or potentially zero sized task reductions. */
29812
29813static tree
29814c_finish_taskloop_clauses (tree clauses)
29815{
29816 tree *pc = &clauses;
29817 for (tree c = clauses; c; c = *pc)
29818 {
29819 bool remove = false;
29820 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
29821 {
29822 tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
29823 if (integer_zerop (TYPE_SIZE_UNIT (type)))
29824 {
29825 error_at (OMP_CLAUSE_LOCATION (c),
29826 "zero sized type %qT in %<reduction%> clause", type);
29827 remove = true;
29828 }
29829 else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
29830 {
29831 error_at (OMP_CLAUSE_LOCATION (c),
29832 "variable sized type %qT in %<reduction%> clause",
29833 type);
29834 remove = true;
29835 }
29836 }
29837 if (remove)
29838 *pc = OMP_CLAUSE_CHAIN (c);
29839 else
29840 pc = &OMP_CLAUSE_CHAIN (c);
29841 }
29842 return clauses;
29843}
29844
29845/* OpenMP 4.5:
29846 #pragma omp taskloop taskloop-clause[optseq] new-line
29847 for-loop
29848
29849 #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
29850 for-loop */
29851
29852#define OMP_TASKLOOP_CLAUSE_MASK \
29853 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
29854 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
29855 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
29856 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
29857 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
29858 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
29859 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
29860 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
29861 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
29862 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
29863 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
29864 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
29865 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
29866 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
29867 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
29868 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
29869 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
29870
29871static tree
29872c_parser_omp_taskloop (location_t loc, c_parser *parser,
29873 char *p_name, omp_clause_mask mask, tree *cclauses,
29874 bool *if_p)
29875{
29876 tree clauses, block, ret;
29877
29878 strcat (dest: p_name, src: " taskloop");
29879 mask |= OMP_TASKLOOP_CLAUSE_MASK;
29880 /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
29881 clause. */
29882 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
29883 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
29884
29885 if (c_parser_next_token_is (parser, type: CPP_NAME))
29886 {
29887 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29888
29889 if (strcmp (s1: p, s2: "simd") == 0)
29890 {
29891 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
29892 if (cclauses == NULL)
29893 cclauses = cclauses_buf;
29894 c_parser_consume_token (parser);
29895 if (!flag_openmp) /* flag_openmp_simd */
29896 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
29897 if_p);
29898 block = c_begin_compound_stmt (true);
29899 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
29900 block = c_end_compound_stmt (loc, block, true);
29901 if (ret == NULL)
29902 return ret;
29903 ret = make_node (OMP_TASKLOOP);
29904 TREE_TYPE (ret) = void_type_node;
29905 OMP_FOR_BODY (ret) = block;
29906 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29907 OMP_FOR_CLAUSES (ret)
29908 = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
29909 SET_EXPR_LOCATION (ret, loc);
29910 add_stmt (ret);
29911 return ret;
29912 }
29913 }
29914 if (!flag_openmp) /* flag_openmp_simd */
29915 {
29916 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29917 return NULL_TREE;
29918 }
29919
29920 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
29921 if (cclauses)
29922 {
29923 omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses);
29924 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29925 }
29926
29927 clauses = c_finish_taskloop_clauses (clauses);
29928 block = c_begin_compound_stmt (true);
29929 ret = c_parser_omp_for_loop (loc, parser, code: OMP_TASKLOOP, clauses, NULL, if_p);
29930 block = c_end_compound_stmt (loc, block, true);
29931 add_stmt (block);
29932
29933 return ret;
29934}
29935
29936/* OpenMP 5.1: Parse sizes list for "omp tile sizes"
29937 sizes ( size-expr-list ) */
29938static tree
29939c_parser_omp_tile_sizes (c_parser *parser, location_t loc)
29940{
29941 tree sizes = NULL_TREE;
29942
29943 if (c_parser_next_token_is (parser, type: CPP_COMMA))
29944 c_parser_consume_token (parser);
29945
29946 c_token *tok = c_parser_peek_token (parser);
29947 if (tok->type != CPP_NAME
29948 || strcmp (s1: "sizes", IDENTIFIER_POINTER (tok->value)))
29949 {
29950 c_parser_error (parser, gmsgid: "expected %<sizes%>");
29951 return error_mark_node;
29952 }
29953 c_parser_consume_token (parser);
29954
29955 matching_parens parens;
29956 if (!parens.require_open (parser))
29957 return error_mark_node;
29958
29959 vec<tree, va_gc> *sizes_vec
29960 = c_parser_expr_list (parser, convert_p: true, fold_p: true, NULL, NULL, NULL, NULL);
29961 sizes = build_tree_list_vec (sizes_vec);
29962 release_tree_vector (sizes_vec);
29963
29964 for (tree s = sizes; s; s = TREE_CHAIN (s))
29965 {
29966 tree expr = TREE_VALUE (s);
29967 if (expr == error_mark_node)
29968 {
29969 parens.skip_until_found_close (parser);
29970 return error_mark_node;
29971 }
29972
29973 HOST_WIDE_INT n;
29974 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
29975 || !tree_fits_shwi_p (expr)
29976 || (n = tree_to_shwi (expr)) <= 0
29977 || (int) n != n)
29978 {
29979 c_parser_error (parser, gmsgid: "%<sizes%> argument needs positive"
29980 " integral constant");
29981 TREE_VALUE (s) = integer_one_node;
29982 }
29983 }
29984 parens.require_close (parser);
29985
29986 gcc_assert (sizes);
29987 tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES);
29988 OMP_CLAUSE_SIZES_LIST (c) = sizes;
29989
29990 return c;
29991}
29992
29993/* OpenMP 5.1:
29994 #pragma omp tile sizes ( size-expr-list ) new-line
29995 for-loop
29996
29997 LOC is the location of the #pragma token. */
29998
29999static tree
30000c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p)
30001{
30002 tree clauses = c_parser_omp_tile_sizes (parser, loc);
30003 c_parser_skip_to_pragma_eol (parser);
30004
30005 if (!clauses || clauses == error_mark_node)
30006 return error_mark_node;
30007
30008 tree block = c_begin_compound_stmt (true);
30009 tree ret = c_parser_omp_for_loop (loc, parser, code: OMP_TILE, clauses,
30010 NULL, if_p);
30011 block = c_end_compound_stmt (loc, block, true);
30012 add_stmt (block);
30013
30014 return ret;
30015}
30016
30017#define OMP_UNROLL_CLAUSE_MASK \
30018 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \
30019 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL))
30020
30021/* OpenMP 5.1
30022 #pragma omp unroll unroll-clause[optseq] new-line
30023 for-loop
30024
30025 LOC is the location of the #pragma token. */
30026
30027static tree
30028c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p)
30029{
30030 tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK,
30031 where: "#pragma omp unroll", finish_p: true);
30032
30033 tree block = c_begin_compound_stmt (true);
30034 tree ret = c_parser_omp_for_loop (loc, parser, code: OMP_UNROLL, clauses,
30035 NULL, if_p);
30036 block = c_end_compound_stmt (loc, block, true);
30037 add_stmt (block);
30038
30039 return ret;
30040}
30041
30042/* OpenMP 5.1
30043 #pragma omp nothing new-line */
30044
30045static void
30046c_parser_omp_nothing (c_parser *parser)
30047{
30048 c_parser_consume_pragma (parser);
30049 c_parser_skip_to_pragma_eol (parser);
30050}
30051
30052/* OpenMP 5.1
30053 #pragma omp error clauses[optseq] new-line */
30054
30055static bool
30056c_parser_omp_error (c_parser *parser, enum pragma_context context)
30057{
30058 int at_compilation = -1;
30059 int severity_fatal = -1;
30060 tree message = NULL_TREE;
30061 bool bad = false;
30062 location_t loc = c_parser_peek_token (parser)->location;
30063
30064 c_parser_consume_pragma (parser);
30065
30066 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
30067 {
30068 if (c_parser_next_token_is (parser, type: CPP_COMMA)
30069 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
30070 c_parser_consume_token (parser);
30071
30072 if (!c_parser_next_token_is (parser, type: CPP_NAME))
30073 break;
30074
30075 const char *p
30076 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30077 location_t cloc = c_parser_peek_token (parser)->location;
30078 static const char *args[] = {
30079 "execution", "compilation", "warning", "fatal"
30080 };
30081 int *v = NULL;
30082 int idx = 0, n = -1;
30083 tree m = NULL_TREE;
30084
30085 if (!strcmp (s1: p, s2: "at"))
30086 v = &at_compilation;
30087 else if (!strcmp (s1: p, s2: "severity"))
30088 {
30089 v = &severity_fatal;
30090 idx += 2;
30091 }
30092 else if (strcmp (s1: p, s2: "message"))
30093 {
30094 error_at (cloc,
30095 "expected %<at%>, %<severity%> or %<message%> clause");
30096 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
30097 return false;
30098 }
30099
30100 c_parser_consume_token (parser);
30101
30102 matching_parens parens;
30103 if (parens.require_open (parser))
30104 {
30105 if (v == NULL)
30106 {
30107 location_t expr_loc = c_parser_peek_token (parser)->location;
30108 c_expr expr = c_parser_expr_no_commas (parser, NULL);
30109 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
30110 m = convert (const_string_type_node, expr.value);
30111 m = c_fully_fold (m, false, NULL);
30112 }
30113 else
30114 {
30115 if (c_parser_next_token_is (parser, type: CPP_NAME))
30116 {
30117 tree val = c_parser_peek_token (parser)->value;
30118 const char *q = IDENTIFIER_POINTER (val);
30119
30120 if (!strcmp (s1: q, s2: args[idx]))
30121 n = 0;
30122 else if (!strcmp (s1: q, s2: args[idx + 1]))
30123 n = 1;
30124 }
30125 if (n == -1)
30126 {
30127 error_at (c_parser_peek_token (parser)->location,
30128 "expected %qs or %qs", args[idx], args[idx + 1]);
30129 bad = true;
30130 switch (c_parser_peek_token (parser)->type)
30131 {
30132 case CPP_EOF:
30133 case CPP_PRAGMA_EOL:
30134 case CPP_CLOSE_PAREN:
30135 break;
30136 default:
30137 if (c_parser_peek_2nd_token (parser)->type
30138 == CPP_CLOSE_PAREN)
30139 c_parser_consume_token (parser);
30140 break;
30141 }
30142 }
30143 else
30144 c_parser_consume_token (parser);
30145 }
30146
30147 parens.skip_until_found_close (parser);
30148
30149 if (v == NULL)
30150 {
30151 if (message)
30152 {
30153 error_at (cloc, "too many %qs clauses", p);
30154 bad = true;
30155 }
30156 else
30157 message = m;
30158 }
30159 else if (n != -1)
30160 {
30161 if (*v != -1)
30162 {
30163 error_at (cloc, "too many %qs clauses", p);
30164 bad = true;
30165 }
30166 else
30167 *v = n;
30168 }
30169 }
30170 else
30171 bad = true;
30172 }
30173 c_parser_skip_to_pragma_eol (parser);
30174 if (bad)
30175 return true;
30176
30177 if (at_compilation == -1)
30178 at_compilation = 1;
30179 if (severity_fatal == -1)
30180 severity_fatal = 1;
30181 if (!at_compilation)
30182 {
30183 if (context != pragma_compound)
30184 {
30185 error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
30186 "may only be used in compound statements");
30187 return true;
30188 }
30189 if (parser->omp_for_parse_state
30190 && parser->omp_for_parse_state->in_intervening_code)
30191 {
30192 error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
30193 "may not be used in intervening code");
30194 parser->omp_for_parse_state->fail = true;
30195 return true;
30196 }
30197 tree fndecl
30198 = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR
30199 : BUILT_IN_GOMP_WARNING);
30200 if (!message)
30201 message = build_zero_cst (const_string_type_node);
30202 tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
30203 build_all_ones_cst (size_type_node));
30204 add_stmt (stmt);
30205 return true;
30206 }
30207 const char *msg = NULL;
30208 if (message)
30209 {
30210 msg = c_getstr (message);
30211 if (msg == NULL)
30212 msg = _("<message unknown at compile time>");
30213 }
30214 const enum diagnostics::kind diag_kind = (severity_fatal
30215 ? diagnostics::kind::error
30216 : diagnostics::kind::warning);
30217 if (msg)
30218 emit_diagnostic (diag_kind, loc, 0,
30219 "%<pragma omp error%> encountered: %s", msg);
30220 else
30221 emit_diagnostic (diag_kind, loc, 0,
30222 "%<pragma omp error%> encountered");
30223 return false;
30224}
30225
30226/* Assumption clauses
30227 OpenMP 5.1:
30228 absent (directive-name-list)
30229 contains (directive-name-list)
30230 holds (expression)
30231 no_openmp
30232 no_openmp_routines
30233 no_parallelism
30234
30235 OpenMP 6.0:
30236 no_openmp_constructs */
30237
30238static void
30239c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
30240{
30241 bool no_openmp = false;
30242 bool no_openmp_constructs = false;
30243 bool no_openmp_routines = false;
30244 bool no_parallelism = false;
30245 bitmap_head absent_head, contains_head;
30246
30247 bitmap_obstack_initialize (NULL);
30248 bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack);
30249 bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack);
30250
30251 if (c_parser_next_token_is (parser, type: CPP_PRAGMA_EOL))
30252 error_at (c_parser_peek_token (parser)->location,
30253 "expected at least one assumption clause");
30254
30255 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
30256 {
30257 if (c_parser_next_token_is (parser, type: CPP_COMMA)
30258 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
30259 c_parser_consume_token (parser);
30260
30261 if (!c_parser_next_token_is (parser, type: CPP_NAME))
30262 break;
30263
30264 const char *p
30265 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30266 location_t cloc = c_parser_peek_token (parser)->location;
30267
30268 if (!strcmp (s1: p, s2: "no_openmp"))
30269 {
30270 c_parser_consume_token (parser);
30271 if (no_openmp)
30272 error_at (cloc, "too many %qs clauses", "no_openmp");
30273 no_openmp = true;
30274 }
30275 else if (!strcmp (s1: p, s2: "no_openmp_constructs"))
30276 {
30277 c_parser_consume_token (parser);
30278 if (no_openmp_constructs)
30279 error_at (cloc, "too many %qs clauses", "no_openmp_constructs");
30280 no_openmp_constructs = true;
30281 }
30282 else if (!strcmp (s1: p, s2: "no_openmp_routines"))
30283 {
30284 c_parser_consume_token (parser);
30285 if (no_openmp_routines)
30286 error_at (cloc, "too many %qs clauses", "no_openmp_routines");
30287 no_openmp_routines = true;
30288 }
30289 else if (!strcmp (s1: p, s2: "no_parallelism"))
30290 {
30291 c_parser_consume_token (parser);
30292 if (no_parallelism)
30293 error_at (cloc, "too many %qs clauses", "no_parallelism");
30294 no_parallelism = true;
30295 }
30296 else if (!strcmp (s1: p, s2: "holds"))
30297 {
30298 c_parser_consume_token (parser);
30299 matching_parens parens;
30300 if (parens.require_open (parser))
30301 {
30302 location_t eloc = c_parser_peek_token (parser)->location;
30303 c_expr expr = c_parser_expr_no_commas (parser, NULL);
30304 tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
30305 t = c_objc_common_truthvalue_conversion (eloc, t);
30306 t = c_fully_fold (t, false, NULL);
30307 if (is_assume && t != error_mark_node)
30308 {
30309 tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
30310 void_type_node, 1,
30311 t);
30312 add_stmt (fn);
30313 }
30314 parens.skip_until_found_close (parser);
30315 }
30316 }
30317 else if (!strcmp (s1: p, s2: "absent") || !strcmp (s1: p, s2: "contains"))
30318 {
30319 c_parser_consume_token (parser);
30320 matching_parens parens;
30321 if (parens.require_open (parser))
30322 {
30323 do
30324 {
30325 const char *directive[3] = {};
30326 int i;
30327 location_t dloc = c_parser_peek_token (parser)->location;
30328 for (i = 0; i < 3; i++)
30329 {
30330 tree id;
30331 if (c_parser_peek_nth_token (parser, n: i + 1)->type
30332 == CPP_NAME)
30333 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
30334 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
30335 != RID_MAX)
30336 {
30337 enum rid rid
30338 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
30339 id = ridpointers[rid];
30340 }
30341 else
30342 break;
30343 directive[i] = IDENTIFIER_POINTER (id);
30344 }
30345 if (i == 0)
30346 error_at (dloc, "expected directive name");
30347 else
30348 {
30349 const struct c_omp_directive *dir
30350 = c_omp_categorize_directive (directive[0],
30351 directive[1],
30352 directive[2]);
30353 if (dir
30354 && dir->id != PRAGMA_OMP_END
30355 && (dir->kind == C_OMP_DIR_DECLARATIVE
30356 || dir->kind == C_OMP_DIR_INFORMATIONAL
30357 || dir->kind == C_OMP_DIR_META))
30358 error_at (dloc, "invalid OpenMP directive name in "
30359 "%qs clause argument: declarative, "
30360 "informational, and meta directives "
30361 "not permitted", p);
30362 else if (dir == NULL
30363 || dir->id == PRAGMA_OMP_END
30364 || (!dir->second && directive[1])
30365 || (!dir->third && directive[2]))
30366 error_at (dloc, "unknown OpenMP directive name in "
30367 "%qs clause argument", p);
30368 else
30369 {
30370 int id = dir - c_omp_directives;
30371 if (bitmap_bit_p (p[0] == 'a' ? &contains_head
30372 : &absent_head, id))
30373 error_at (dloc, "%<%s%s%s%s%s%> directive "
30374 "mentioned in both %<absent%> and "
30375 "%<contains%> clauses",
30376 directive[0],
30377 directive[1] ? " " : "",
30378 directive[1] ? directive[1] : "",
30379 directive[2] ? " " : "",
30380 directive[2] ? directive[2] : "");
30381 else if (!bitmap_set_bit (p[0] == 'a'
30382 ? &absent_head
30383 : &contains_head, id))
30384 error_at (dloc, "%<%s%s%s%s%s%> directive "
30385 "mentioned multiple times in %qs "
30386 "clauses",
30387 directive[0],
30388 directive[1] ? " " : "",
30389 directive[1] ? directive[1] : "",
30390 directive[2] ? " " : "",
30391 directive[2] ? directive[2] : "", p);
30392 }
30393 for (; i; --i)
30394 c_parser_consume_token (parser);
30395 }
30396 if (c_parser_next_token_is (parser, type: CPP_COMMA))
30397 c_parser_consume_token (parser);
30398 else
30399 break;
30400 }
30401 while (1);
30402 parens.skip_until_found_close (parser);
30403 }
30404 }
30405 else if (startswith (str: p, prefix: "ext_"))
30406 {
30407 warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
30408 c_parser_consume_token (parser);
30409 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
30410 {
30411 matching_parens parens;
30412 parens.consume_open (parser);
30413 c_parser_balanced_token_sequence (parser);
30414 parens.require_close (parser);
30415 }
30416 }
30417 else
30418 {
30419 c_parser_consume_token (parser);
30420 error_at (cloc, "expected assumption clause");
30421 break;
30422 }
30423 }
30424 c_parser_skip_to_pragma_eol (parser);
30425}
30426
30427/* OpenMP 5.1
30428 #pragma omp assume clauses[optseq] new-line */
30429
30430static void
30431c_parser_omp_assume (c_parser *parser, bool *if_p)
30432{
30433 c_parser_omp_assumption_clauses (parser, is_assume: true);
30434 add_stmt (c_parser_omp_structured_block (parser, if_p));
30435}
30436
30437/* OpenMP 5.1
30438 #pragma omp assumes clauses[optseq] new-line */
30439
30440static void
30441c_parser_omp_assumes (c_parser *parser)
30442{
30443 c_parser_consume_pragma (parser);
30444 c_parser_omp_assumption_clauses (parser, is_assume: false);
30445}
30446
30447/* Helper function for c_parser_omp_metadirective. */
30448
30449static void
30450analyze_metadirective_body (c_parser *parser,
30451 vec<c_token> &tokens,
30452 vec<tree> &labels)
30453{
30454 int nesting_depth = 0;
30455 int bracket_depth = 0;
30456 bool ignore_label = false;
30457
30458 /* Read in the body tokens to the tokens for each candidate directive. */
30459 while (1)
30460 {
30461 c_token *token = c_parser_peek_token (parser);
30462 bool stop = false;
30463
30464 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
30465 ignore_label = true;
30466
30467 switch (token->type)
30468 {
30469 case CPP_EOF:
30470 break;
30471 case CPP_NAME:
30472 if (!ignore_label
30473 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
30474 labels.safe_push (obj: token->value);
30475 goto add;
30476 case CPP_OPEN_BRACE:
30477 ++nesting_depth;
30478 goto add;
30479 case CPP_CLOSE_BRACE:
30480 if (--nesting_depth == 0 && bracket_depth == 0)
30481 stop = true;
30482 goto add;
30483 case CPP_OPEN_PAREN:
30484 ++bracket_depth;
30485 goto add;
30486 case CPP_CLOSE_PAREN:
30487 --bracket_depth;
30488 goto add;
30489 case CPP_COLON:
30490 ignore_label = false;
30491 goto add;
30492 case CPP_SEMICOLON:
30493 if (nesting_depth == 0 && bracket_depth == 0)
30494 stop = true;
30495 goto add;
30496 default:
30497 add:
30498 tokens.safe_push (obj: *token);
30499 if (token->type == CPP_PRAGMA)
30500 c_parser_consume_pragma (parser);
30501 else if (token->type == CPP_PRAGMA_EOL)
30502 c_parser_skip_to_pragma_eol (parser);
30503 else
30504 c_parser_consume_token (parser);
30505 if (stop)
30506 break;
30507 continue;
30508 }
30509 break;
30510 }
30511}
30512
30513/* OpenMP 5.0:
30514
30515 # pragma omp metadirective [clause[, clause]]
30516*/
30517
30518static void
30519c_parser_omp_metadirective (c_parser *parser, bool *if_p)
30520{
30521 static unsigned int metadirective_region_count = 0;
30522
30523 tree ret;
30524 auto_vec<c_token> directive_tokens;
30525 auto_vec<c_token> body_tokens;
30526 auto_vec<tree> body_labels;
30527 auto_vec<const struct c_omp_directive *> directives;
30528 auto_vec<tree> ctxs;
30529 vec<struct omp_variant> candidates;
30530 bool default_seen = false;
30531 int directive_token_idx = 0;
30532 tree standalone_body = NULL_TREE;
30533 location_t pragma_loc = c_parser_peek_token (parser)->location;
30534 bool requires_body = false;
30535
30536 ret = make_node (OMP_METADIRECTIVE);
30537 SET_EXPR_LOCATION (ret, pragma_loc);
30538 TREE_TYPE (ret) = void_type_node;
30539 OMP_METADIRECTIVE_VARIANTS (ret) = NULL_TREE;
30540
30541 c_parser_consume_pragma (parser);
30542 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
30543 {
30544 if (c_parser_next_token_is (parser, type: CPP_COMMA))
30545 c_parser_consume_token (parser);
30546 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
30547 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
30548 {
30549 c_parser_error (parser, gmsgid: "expected %<when%>, "
30550 "%<otherwise%>, or %<default%> clause");
30551 goto error;
30552 }
30553
30554 location_t match_loc = c_parser_peek_token (parser)->location;
30555 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30556 if (strcmp (s1: p, s2: "default") == 0)
30557 {
30558 gcc_rich_location richloc (pragma_loc);
30559 richloc.add_fixit_replace (where: match_loc, new_content: "otherwise");
30560 warning_at (&richloc, OPT_Wdeprecated_openmp,
30561 "%<default%> clause on metadirectives deprecated since "
30562 "OpenMP 5.2, use %<otherwise%>");
30563 }
30564 c_parser_consume_token (parser);
30565 bool default_p
30566 = strcmp (s1: p, s2: "default") == 0 || strcmp (s1: p, s2: "otherwise") == 0;
30567 if (default_p)
30568 {
30569 if (default_seen)
30570 {
30571 error_at (match_loc, "too many %<otherwise%> or %<default%> "
30572 "clauses in %<metadirective%>");
30573 goto error;
30574 }
30575 default_seen = true;
30576 }
30577 else if (default_seen)
30578 {
30579 error_at (match_loc, "%<otherwise%> or %<default%> clause "
30580 "must appear last in %<metadirective%>");
30581 goto error;
30582 }
30583 if (!default_p && strcmp (s1: p, s2: "when") != 0)
30584 {
30585 error_at (match_loc, "%qs is not valid for %qs",
30586 p, "metadirective");
30587 goto error;
30588 }
30589
30590 matching_parens parens;
30591 tree ctx = NULL_TREE;
30592 bool skip = false;
30593
30594 if (!parens.require_open (parser))
30595 goto error;
30596
30597 if (!default_p)
30598 {
30599 ctx = c_parser_omp_context_selector_specification (parser,
30600 NULL_TREE);
30601 if (ctx == error_mark_node)
30602 goto error;
30603 ctx = omp_check_context_selector (loc: match_loc, ctx,
30604 directive: OMP_CTX_METADIRECTIVE);
30605 if (ctx == error_mark_node)
30606 goto error;
30607
30608 /* Remove the selector from further consideration if it can be
30609 evaluated as a non-match at this point. */
30610 skip = (omp_context_selector_matches (ctx, NULL_TREE, false) == 0);
30611
30612 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
30613 {
30614 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
30615 goto error;
30616 }
30617 c_parser_consume_token (parser);
30618 }
30619
30620 /* Read in the directive type and create a dummy pragma token for
30621 it. */
30622 location_t loc = c_parser_peek_token (parser)->location;
30623
30624 const char *directive[3] = {};
30625 int i;
30626 for (i = 0; i < 3; i++)
30627 {
30628 tree id;
30629 if (c_parser_peek_nth_token (parser, n: i + 1)->type
30630 == CPP_CLOSE_PAREN)
30631 {
30632 if (i == 0)
30633 directive[i++] = "nothing";
30634 break;
30635 }
30636 else if (c_parser_peek_nth_token (parser, n: i + 1)->type
30637 == CPP_NAME)
30638 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
30639 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
30640 != RID_MAX)
30641 {
30642 enum rid rid
30643 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
30644 id = ridpointers[rid];
30645 }
30646 else
30647 break;
30648
30649 directive[i] = IDENTIFIER_POINTER (id);
30650 }
30651 if (i == 0)
30652 {
30653 error_at (loc, "expected directive name");
30654 goto error;
30655 }
30656
30657 const struct c_omp_directive *omp_directive
30658 = c_omp_categorize_directive (directive[0],
30659 directive[1],
30660 directive[2]);
30661
30662 if (omp_directive == NULL)
30663 {
30664 for (int j = 0; j < i; j++)
30665 c_parser_consume_token (parser);
30666 c_parser_error (parser, gmsgid: "unknown directive name");
30667 goto error;
30668 }
30669 else
30670 {
30671 int token_count = 0;
30672 if (omp_directive->first) token_count++;
30673 if (omp_directive->second) token_count++;
30674 if (omp_directive->third) token_count++;
30675 for (int j = 0; j < token_count; j++)
30676 c_parser_consume_token (parser);
30677 }
30678 if (omp_directive->id == PRAGMA_OMP_METADIRECTIVE)
30679 {
30680 c_parser_error (parser,
30681 gmsgid: "metadirectives cannot be used as variants of a "
30682 "%<metadirective%>");
30683 goto error;
30684 }
30685 if (omp_directive->kind == C_OMP_DIR_DECLARATIVE)
30686 {
30687 sorry_at (loc, "declarative directive variants of a "
30688 "%<metadirective%> are not supported");
30689 goto error;
30690 }
30691 if (omp_directive->kind == C_OMP_DIR_CONSTRUCT)
30692 requires_body = true;
30693
30694 if (!skip)
30695 {
30696 c_token pragma_token;
30697 pragma_token.type = CPP_PRAGMA;
30698 pragma_token.location = loc;
30699 pragma_token.pragma_kind = (enum pragma_kind) omp_directive->id;
30700
30701 directives.safe_push (obj: omp_directive);
30702 directive_tokens.safe_push (obj: pragma_token);
30703 ctxs.safe_push (obj: ctx);
30704 }
30705
30706 /* Read in tokens for the directive clauses. */
30707 int nesting_depth = 0;
30708 while (1)
30709 {
30710 c_token *token = c_parser_peek_token (parser);
30711 switch (token->type)
30712 {
30713 case CPP_EOF:
30714 case CPP_PRAGMA_EOL:
30715 break;
30716 case CPP_OPEN_PAREN:
30717 ++nesting_depth;
30718 goto add;
30719 case CPP_CLOSE_PAREN:
30720 if (nesting_depth-- == 0)
30721 {
30722 c_parser_consume_token (parser);
30723 break;
30724 }
30725 goto add;
30726 default:
30727 add:
30728 if (!skip)
30729 directive_tokens.safe_push (obj: *token);
30730 c_parser_consume_token (parser);
30731 continue;
30732 }
30733 break;
30734 }
30735
30736 if (!skip)
30737 {
30738 c_token eol_token;
30739 memset (s: &eol_token, c: 0, n: sizeof (eol_token));
30740 eol_token.type = CPP_PRAGMA_EOL;
30741 directive_tokens.safe_push (obj: eol_token);
30742 }
30743 }
30744 c_parser_skip_to_pragma_eol (parser);
30745
30746 /* If only one selector matches and it evaluates to 'omp nothing', no need to
30747 proceed. */
30748 if (ctxs.length () == 1)
30749 {
30750 tree ctx = ctxs[0];
30751 if (ctx == NULL_TREE
30752 || (omp_context_selector_matches (ctx, NULL_TREE, false) == 1
30753 && directive_tokens[0].pragma_kind == PRAGMA_OMP_NOTHING))
30754 return;
30755 }
30756
30757 if (!default_seen)
30758 {
30759 /* Add a default clause that evaluates to 'omp nothing'. */
30760 const struct c_omp_directive *omp_directive
30761 = c_omp_categorize_directive ("nothing", NULL, NULL);
30762
30763 c_token pragma_token;
30764 pragma_token.type = CPP_PRAGMA;
30765 pragma_token.location = UNKNOWN_LOCATION;
30766 pragma_token.pragma_kind = PRAGMA_OMP_NOTHING;
30767
30768 directives.safe_push (obj: omp_directive);
30769 directive_tokens.safe_push (obj: pragma_token);
30770 ctxs.safe_push (NULL_TREE);
30771
30772 c_token eol_token;
30773 memset (s: &eol_token, c: 0, n: sizeof (eol_token));
30774 eol_token.type = CPP_PRAGMA_EOL;
30775 directive_tokens.safe_push (obj: eol_token);
30776 }
30777
30778 if (requires_body)
30779 analyze_metadirective_body (parser, tokens&: body_tokens, labels&: body_labels);
30780
30781 /* Process each candidate directive. */
30782 unsigned i;
30783 tree ctx;
30784
30785 FOR_EACH_VEC_ELT (ctxs, i, ctx)
30786 {
30787 auto_vec<c_token> tokens;
30788
30789 /* Add the directive tokens. */
30790 do
30791 tokens.safe_push (obj: directive_tokens [directive_token_idx++]);
30792 while (tokens.last ().type != CPP_PRAGMA_EOL);
30793
30794 /* Add the body tokens. */
30795 gcc_assert (requires_body || body_tokens.is_empty ());
30796 for (unsigned j = 0; j < body_tokens.length (); j++)
30797 tokens.safe_push (obj: body_tokens[j]);
30798
30799 /* Make sure nothing tries to read past the end of the tokens. */
30800 c_token eof_token;
30801 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
30802 eof_token.type = CPP_EOF;
30803 tokens.safe_push (obj: eof_token);
30804 tokens.safe_push (obj: eof_token);
30805
30806 unsigned int old_tokens_avail = parser->tokens_avail;
30807 c_token *old_tokens = parser->tokens;
30808 struct omp_attribute_pragma_state *old_in_omp_attribute_pragma
30809 = parser->in_omp_attribute_pragma;
30810 struct omp_metadirective_parse_data *old_state
30811 = parser->omp_metadirective_state;
30812
30813 struct omp_metadirective_parse_data new_state;
30814 new_state.body_labels = &body_labels;
30815 new_state.region_num = ++metadirective_region_count;
30816
30817 parser->tokens = tokens.address ();
30818 parser->tokens_avail = tokens.length ();
30819 parser->in_omp_attribute_pragma = NULL;
30820 parser->omp_metadirective_state = &new_state;
30821
30822 int prev_errorcount = errorcount;
30823 tree directive = c_begin_compound_stmt (true);
30824
30825 c_parser_pragma (parser, context: pragma_compound, if_p, NULL_TREE);
30826 directive = c_end_compound_stmt (pragma_loc, directive, true);
30827 bool standalone_p
30828 = directives[i]->kind == C_OMP_DIR_STANDALONE
30829 || directives[i]->kind == C_OMP_DIR_UTILITY;
30830 if (standalone_p && requires_body)
30831 {
30832 /* Parsing standalone directives will not consume the body
30833 tokens, so do that here. */
30834 if (standalone_body == NULL_TREE)
30835 {
30836 standalone_body = push_stmt_list ();
30837 c_parser_statement (parser, if_p); // TODO skip this
30838 standalone_body = pop_stmt_list (standalone_body);
30839 }
30840 else
30841 c_parser_skip_to_end_of_block_or_statement (parser, metadirective_p: true);
30842 }
30843
30844 tree body = standalone_p ? standalone_body : NULL_TREE;
30845 tree variant = make_omp_metadirective_variant (ctx, directive, body);
30846 OMP_METADIRECTIVE_VARIANTS (ret)
30847 = chainon (OMP_METADIRECTIVE_VARIANTS (ret), variant);
30848
30849 /* Check that all valid tokens have been consumed if no parse errors
30850 encountered. */
30851 if (errorcount == prev_errorcount)
30852 {
30853 gcc_assert (parser->tokens_avail == 2);
30854 gcc_assert (c_parser_next_token_is (parser, CPP_EOF));
30855 gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF);
30856 }
30857
30858 parser->tokens = old_tokens;
30859 parser->tokens_avail = old_tokens_avail;
30860 parser->in_omp_attribute_pragma = old_in_omp_attribute_pragma;
30861 parser->omp_metadirective_state = old_state;
30862 }
30863
30864 /* Try to resolve the metadirective early. */
30865 candidates = omp_early_resolve_metadirective (ret);
30866 if (!candidates.is_empty ())
30867 ret = c_omp_expand_variant_construct (candidates);
30868
30869 add_stmt (ret);
30870 return;
30871
30872error:
30873 /* Skip the metadirective pragma. Do not skip the metadirective body. */
30874 if (parser->in_pragma)
30875 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
30876}
30877
30878/* Main entry point to parsing most OpenMP pragmas. */
30879
30880static void
30881c_parser_omp_construct (c_parser *parser, bool *if_p)
30882{
30883 enum pragma_kind p_kind;
30884 location_t loc;
30885 tree stmt;
30886 char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
30887 omp_clause_mask mask (0);
30888
30889 loc = c_parser_peek_token (parser)->location;
30890 p_kind = c_parser_peek_token (parser)->pragma_kind;
30891 c_parser_consume_pragma (parser);
30892
30893 switch (p_kind)
30894 {
30895 case PRAGMA_OACC_ATOMIC:
30896 c_parser_omp_atomic (loc, parser, openacc: true);
30897 return;
30898 case PRAGMA_OACC_CACHE:
30899 strcpy (dest: p_name, src: "#pragma acc");
30900 stmt = c_parser_oacc_cache (loc, parser);
30901 break;
30902 case PRAGMA_OACC_DATA:
30903 stmt = c_parser_oacc_data (loc, parser, if_p);
30904 break;
30905 case PRAGMA_OACC_HOST_DATA:
30906 stmt = c_parser_oacc_host_data (loc, parser, if_p);
30907 break;
30908 case PRAGMA_OACC_KERNELS:
30909 case PRAGMA_OACC_PARALLEL:
30910 case PRAGMA_OACC_SERIAL:
30911 strcpy (dest: p_name, src: "#pragma acc");
30912 stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
30913 break;
30914 case PRAGMA_OACC_LOOP:
30915 strcpy (dest: p_name, src: "#pragma acc");
30916 stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
30917 break;
30918 case PRAGMA_OACC_WAIT:
30919 strcpy (dest: p_name, src: "#pragma wait");
30920 stmt = c_parser_oacc_wait (loc, parser, p_name);
30921 break;
30922 case PRAGMA_OMP_ATOMIC:
30923 c_parser_omp_atomic (loc, parser, openacc: false);
30924 return;
30925 case PRAGMA_OMP_CRITICAL:
30926 stmt = c_parser_omp_critical (loc, parser, if_p);
30927 break;
30928 case PRAGMA_OMP_DISTRIBUTE:
30929 strcpy (dest: p_name, src: "#pragma omp");
30930 stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
30931 break;
30932 case PRAGMA_OMP_FOR:
30933 strcpy (dest: p_name, src: "#pragma omp");
30934 stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
30935 break;
30936 case PRAGMA_OMP_LOOP:
30937 strcpy (dest: p_name, src: "#pragma omp");
30938 stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
30939 break;
30940 case PRAGMA_OMP_MASKED:
30941 strcpy (dest: p_name, src: "#pragma omp");
30942 stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
30943 break;
30944 case PRAGMA_OMP_MASTER:
30945 strcpy (dest: p_name, src: "#pragma omp");
30946 stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p,
30947 UNKNOWN_LOCATION);
30948 break;
30949 case PRAGMA_OMP_PARALLEL:
30950 strcpy (dest: p_name, src: "#pragma omp");
30951 stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
30952 break;
30953 case PRAGMA_OMP_SCOPE:
30954 stmt = c_parser_omp_scope (loc, parser, if_p);
30955 break;
30956 case PRAGMA_OMP_SECTIONS:
30957 strcpy (dest: p_name, src: "#pragma omp");
30958 stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
30959 break;
30960 case PRAGMA_OMP_SIMD:
30961 strcpy (dest: p_name, src: "#pragma omp");
30962 stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
30963 break;
30964 case PRAGMA_OMP_SINGLE:
30965 stmt = c_parser_omp_single (loc, parser, if_p);
30966 break;
30967 case PRAGMA_OMP_TASK:
30968 stmt = c_parser_omp_task (loc, parser, if_p);
30969 break;
30970 case PRAGMA_OMP_TASKGROUP:
30971 stmt = c_parser_omp_taskgroup (loc, parser, if_p);
30972 break;
30973 case PRAGMA_OMP_TASKLOOP:
30974 strcpy (dest: p_name, src: "#pragma omp");
30975 stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
30976 break;
30977 case PRAGMA_OMP_TEAMS:
30978 strcpy (dest: p_name, src: "#pragma omp");
30979 stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
30980 break;
30981 case PRAGMA_OMP_ASSUME:
30982 c_parser_omp_assume (parser, if_p);
30983 return;
30984 case PRAGMA_OMP_TILE:
30985 stmt = c_parser_omp_tile (loc, parser, if_p);
30986 break;
30987 case PRAGMA_OMP_UNROLL:
30988 stmt = c_parser_omp_unroll (loc, parser, if_p);
30989 break;
30990 case PRAGMA_OMP_DISPATCH:
30991 stmt = c_parser_omp_dispatch (loc, parser);
30992 break;
30993 default:
30994 gcc_unreachable ();
30995 }
30996
30997 if (stmt && stmt != error_mark_node)
30998 gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
30999}
31000
31001/* OpenMP 6.0:
31002 # pragma omp groupprivate (variable-list) [device_type(...)] */
31003
31004#define OMP_GROUPPRIVATE_CLAUSE_MASK \
31005 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) )
31006
31007static void
31008c_parser_omp_groupprivate (c_parser *parser)
31009{
31010 location_t loc = c_parser_peek_token (parser)->location;
31011 c_parser_consume_pragma (parser);
31012 tree vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
31013 tree clauses = c_parser_omp_all_clauses (parser, OMP_GROUPPRIVATE_CLAUSE_MASK,
31014 where: "#pragma omp groupprivate");
31015 /* TODO: Implies 'declare target local' with specified device_type, check for
31016 conflicts. Check for other restrictions. */
31017 (void) vars;
31018 (void) clauses;
31019 sorry_at (loc, "%<omp groupprivate%>");
31020}
31021
31022/* OpenMP 2.5:
31023 # pragma omp threadprivate (variable-list) */
31024
31025static void
31026c_parser_omp_threadprivate (c_parser *parser)
31027{
31028 tree vars, t;
31029 location_t loc;
31030
31031 c_parser_consume_pragma (parser);
31032 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
31033
31034 /* Mark every variable in VARS to be assigned thread local storage. */
31035 for (t = vars; t; t = TREE_CHAIN (t))
31036 {
31037 tree v = TREE_PURPOSE (t);
31038 loc = EXPR_LOCATION (TREE_VALUE (t));
31039
31040 /* If V had already been marked threadprivate, it doesn't matter
31041 whether it had been used prior to this point. */
31042 if (!VAR_P (v))
31043 error_at (loc, "%qD is not a variable", v);
31044 else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
31045 error_at (loc, "%qE declared %<threadprivate%> after first use", v);
31046 else if (! is_global_var (t: v))
31047 error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
31048 else if (TREE_TYPE (v) == error_mark_node)
31049 ;
31050 else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
31051 error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
31052 else
31053 {
31054 if (! DECL_THREAD_LOCAL_P (v))
31055 {
31056 set_decl_tls_model (v, decl_default_tls_model (v));
31057 /* If rtl has been already set for this var, call
31058 make_decl_rtl once again, so that encode_section_info
31059 has a chance to look at the new decl flags. */
31060 if (DECL_RTL_SET_P (v))
31061 make_decl_rtl (v);
31062 }
31063 C_DECL_THREADPRIVATE_P (v) = 1;
31064 }
31065 }
31066
31067 c_parser_skip_to_pragma_eol (parser);
31068}
31069
31070/* Parse a transaction attribute (GCC Extension).
31071
31072 transaction-attribute:
31073 gnu-attributes
31074 attribute-specifier
31075*/
31076
31077static tree
31078c_parser_transaction_attributes (c_parser *parser)
31079{
31080 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
31081 return c_parser_gnu_attributes (parser);
31082
31083 if (!c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
31084 return NULL_TREE;
31085 return c_parser_std_attribute_specifier (parser, for_tm: true);
31086}
31087
31088/* Parse a __transaction_atomic or __transaction_relaxed statement
31089 (GCC Extension).
31090
31091 transaction-statement:
31092 __transaction_atomic transaction-attribute[opt] compound-statement
31093 __transaction_relaxed compound-statement
31094
31095 Note that the only valid attribute is: "outer".
31096*/
31097
31098static tree
31099c_parser_transaction (c_parser *parser, enum rid keyword)
31100{
31101 unsigned int old_in = parser->in_transaction;
31102 unsigned int this_in = 1, new_in;
31103 location_t loc = c_parser_peek_token (parser)->location;
31104 tree stmt, attrs;
31105
31106 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
31107 || keyword == RID_TRANSACTION_RELAXED)
31108 && c_parser_next_token_is_keyword (parser, keyword));
31109 c_parser_consume_token (parser);
31110
31111 if (keyword == RID_TRANSACTION_RELAXED)
31112 this_in |= TM_STMT_ATTR_RELAXED;
31113 else
31114 {
31115 attrs = c_parser_transaction_attributes (parser);
31116 if (attrs)
31117 this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
31118 }
31119
31120 /* Keep track if we're in the lexical scope of an outer transaction. */
31121 new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
31122
31123 parser->in_transaction = new_in;
31124 stmt = c_parser_compound_statement (parser);
31125 parser->in_transaction = old_in;
31126
31127 if (flag_tm)
31128 stmt = c_finish_transaction (loc, stmt, this_in);
31129 else
31130 error_at (loc,
31131 keyword == RID_TRANSACTION_ATOMIC
31132 ? G_("%<__transaction_atomic%> without transactional memory "
31133 "support enabled")
31134 : G_("%<__transaction_relaxed%> without transactional memory "
31135 "support enabled"));
31136
31137 return stmt;
31138}
31139
31140/* Parse a __transaction_atomic or __transaction_relaxed expression
31141 (GCC Extension).
31142
31143 transaction-expression:
31144 __transaction_atomic ( expression )
31145 __transaction_relaxed ( expression )
31146*/
31147
31148static struct c_expr
31149c_parser_transaction_expression (c_parser *parser, enum rid keyword)
31150{
31151 struct c_expr ret;
31152 unsigned int old_in = parser->in_transaction;
31153 unsigned int this_in = 1;
31154 location_t loc = c_parser_peek_token (parser)->location;
31155 tree attrs;
31156
31157 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
31158 || keyword == RID_TRANSACTION_RELAXED)
31159 && c_parser_next_token_is_keyword (parser, keyword));
31160 c_parser_consume_token (parser);
31161
31162 if (keyword == RID_TRANSACTION_RELAXED)
31163 this_in |= TM_STMT_ATTR_RELAXED;
31164 else
31165 {
31166 attrs = c_parser_transaction_attributes (parser);
31167 if (attrs)
31168 this_in |= parse_tm_stmt_attr (attrs, 0);
31169 }
31170
31171 parser->in_transaction = this_in;
31172 matching_parens parens;
31173 if (parens.require_open (parser))
31174 {
31175 tree expr = c_parser_expression (parser).value;
31176 ret.original_type = TREE_TYPE (expr);
31177 ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
31178 if (this_in & TM_STMT_ATTR_RELAXED)
31179 TRANSACTION_EXPR_RELAXED (ret.value) = 1;
31180 SET_EXPR_LOCATION (ret.value, loc);
31181 ret.original_code = TRANSACTION_EXPR;
31182 ret.m_decimal = 0;
31183 if (!parens.require_close (parser))
31184 {
31185 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
31186 goto error;
31187 }
31188 }
31189 else
31190 {
31191 error:
31192 ret.set_error ();
31193 ret.original_code = ERROR_MARK;
31194 ret.original_type = NULL;
31195 }
31196 parser->in_transaction = old_in;
31197
31198 if (!flag_tm)
31199 error_at (loc,
31200 keyword == RID_TRANSACTION_ATOMIC
31201 ? G_("%<__transaction_atomic%> without transactional memory "
31202 "support enabled")
31203 : G_("%<__transaction_relaxed%> without transactional memory "
31204 "support enabled"));
31205
31206 set_c_expr_source_range (expr: &ret, start: loc, finish: loc);
31207
31208 return ret;
31209}
31210
31211/* Parse a __transaction_cancel statement (GCC Extension).
31212
31213 transaction-cancel-statement:
31214 __transaction_cancel transaction-attribute[opt] ;
31215
31216 Note that the only valid attribute is "outer".
31217*/
31218
31219static tree
31220c_parser_transaction_cancel (c_parser *parser)
31221{
31222 location_t loc = c_parser_peek_token (parser)->location;
31223 tree attrs;
31224 bool is_outer = false;
31225
31226 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
31227 c_parser_consume_token (parser);
31228
31229 attrs = c_parser_transaction_attributes (parser);
31230 if (attrs)
31231 is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
31232
31233 if (!flag_tm)
31234 {
31235 error_at (loc, "%<__transaction_cancel%> without "
31236 "transactional memory support enabled");
31237 goto ret_error;
31238 }
31239 else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
31240 {
31241 error_at (loc, "%<__transaction_cancel%> within a "
31242 "%<__transaction_relaxed%>");
31243 goto ret_error;
31244 }
31245 else if (is_outer)
31246 {
31247 if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
31248 && !is_tm_may_cancel_outer (current_function_decl))
31249 {
31250 error_at (loc, "outer %<__transaction_cancel%> not "
31251 "within outer %<__transaction_atomic%> or "
31252 "a %<transaction_may_cancel_outer%> function");
31253 goto ret_error;
31254 }
31255 }
31256 else if (parser->in_transaction == 0)
31257 {
31258 error_at (loc, "%<__transaction_cancel%> not within "
31259 "%<__transaction_atomic%>");
31260 goto ret_error;
31261 }
31262
31263 return add_stmt (build_tm_abort_call (loc, is_outer));
31264
31265 ret_error:
31266 return build1 (NOP_EXPR, void_type_node, error_mark_node);
31267}
31268
31269/* Parse a single source file. */
31270
31271void
31272c_parse_file (void)
31273{
31274 /* Use local storage to begin. If the first token is a pragma, parse it.
31275 If it is #pragma GCC pch_preprocess, then this will load a PCH file
31276 which will cause garbage collection. */
31277 c_parser tparser;
31278
31279 memset (s: &tparser, c: 0, n: sizeof tparser);
31280 tparser.translate_strings_p = true;
31281 tparser.tokens = &tparser.tokens_buf[0];
31282 the_parser = &tparser;
31283
31284 if (c_parser_peek_token (parser: &tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
31285 c_parser_pragma_pch_preprocess (parser: &tparser);
31286 else
31287 c_common_no_more_pch ();
31288
31289 the_parser = ggc_alloc<c_parser> ();
31290 *the_parser = tparser;
31291 if (tparser.tokens == &tparser.tokens_buf[0])
31292 the_parser->tokens = &the_parser->tokens_buf[0];
31293
31294 /* Initialize EH, if we've been told to do so. */
31295 if (flag_exceptions)
31296 using_eh_for_cleanups ();
31297
31298 c_parser_translation_unit (parser: the_parser);
31299 the_parser = NULL;
31300}
31301
31302void
31303c_init_preprocess (void)
31304{
31305 /* Create a parser for use by pragma_lex during preprocessing. */
31306 the_parser = ggc_alloc<c_parser> ();
31307 memset (s: the_parser, c: 0, n: sizeof (c_parser));
31308 the_parser->tokens = &the_parser->tokens_buf[0];
31309}
31310
31311/* Parse the body of a function declaration marked with "__RTL".
31312
31313 The RTL parser works on the level of characters read from a
31314 FILE *, whereas c_parser works at the level of tokens.
31315 Square this circle by consuming all of the tokens up to and
31316 including the closing brace, recording the start/end of the RTL
31317 fragment, and reopening the file and re-reading the relevant
31318 lines within the RTL parser.
31319
31320 This requires the opening and closing braces of the C function
31321 to be on separate lines from the RTL they wrap.
31322
31323 Take ownership of START_WITH_PASS, if non-NULL. */
31324
31325location_t
31326c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
31327{
31328 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
31329 {
31330 free (ptr: start_with_pass);
31331 return c_parser_peek_token (parser)->location;
31332 }
31333
31334 location_t start_loc = c_parser_peek_token (parser)->location;
31335
31336 /* Consume all tokens, up to the closing brace, handling
31337 matching pairs of braces in the rtl dump. */
31338 int num_open_braces = 1;
31339 while (1)
31340 {
31341 switch (c_parser_peek_token (parser)->type)
31342 {
31343 case CPP_OPEN_BRACE:
31344 num_open_braces++;
31345 break;
31346 case CPP_CLOSE_BRACE:
31347 if (--num_open_braces == 0)
31348 goto found_closing_brace;
31349 break;
31350 case CPP_EOF:
31351 error_at (start_loc, "no closing brace");
31352 free (ptr: start_with_pass);
31353 return c_parser_peek_token (parser)->location;
31354 default:
31355 break;
31356 }
31357 c_parser_consume_token (parser);
31358 }
31359
31360 found_closing_brace:
31361 /* At the closing brace; record its location. */
31362 location_t end_loc = c_parser_peek_token (parser)->location;
31363
31364 /* Consume the closing brace. */
31365 c_parser_consume_token (parser);
31366
31367 /* Invoke the RTL parser. */
31368 if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
31369 {
31370 free (ptr: start_with_pass);
31371 return end_loc;
31372 }
31373
31374 /* Run the backend on the cfun created above, transferring ownership of
31375 START_WITH_PASS. */
31376 run_rtl_passes (initial_pass_name: start_with_pass);
31377 return end_loc;
31378}
31379
31380#include "gt-c-c-parser.h"
31381

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