1/* Parser for C and Objective-C.
2 Copyright (C) 1987-2024 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_MEMORY
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
78/* We need to walk over decls with incomplete struct/union/enum types
79 after parsing the whole translation unit.
80 In finish_decl(), if the decl is static, has incomplete
81 struct/union/enum type, it is appended to incomplete_record_decls.
82 In c_parser_translation_unit(), we iterate over incomplete_record_decls
83 and report error if any of the decls are still incomplete. */
84
85vec<tree> incomplete_record_decls;
86
87void
88set_c_expr_source_range (c_expr *expr,
89 location_t start, location_t finish)
90{
91 expr->src_range.m_start = start;
92 expr->src_range.m_finish = finish;
93 if (expr->value)
94 set_source_range (expr: expr->value, start, finish);
95}
96
97void
98set_c_expr_source_range (c_expr *expr,
99 source_range src_range)
100{
101 expr->src_range = src_range;
102 if (expr->value)
103 set_source_range (expr: expr->value, src_range);
104}
105
106
107/* Initialization routine for this file. */
108
109void
110c_parse_init (void)
111{
112 /* The only initialization required is of the reserved word
113 identifiers. */
114 unsigned int i;
115 tree id;
116 int mask = 0;
117
118 /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
119 the c_token structure. */
120 gcc_assert (RID_MAX <= 255);
121
122 mask |= D_CXXONLY;
123 if (!flag_isoc99)
124 mask |= D_C99;
125 if (!flag_isoc23)
126 mask |= D_C23;
127 if (flag_no_asm)
128 {
129 mask |= D_ASM | D_EXT;
130 if (!flag_isoc99)
131 mask |= D_EXT89;
132 if (!flag_isoc23)
133 mask |= D_EXT11;
134 }
135 if (!c_dialect_objc ())
136 mask |= D_OBJC | D_CXX_OBJC;
137
138 ridpointers = ggc_cleared_vec_alloc<tree> (c: (int) RID_MAX);
139 for (i = 0; i < num_c_common_reswords; i++)
140 {
141 /* If a keyword is disabled, do not enter it into the table
142 and so create a canonical spelling that isn't a keyword. */
143 if (c_common_reswords[i].disable & mask)
144 {
145 if (warn_cxx_compat
146 && (c_common_reswords[i].disable & D_CXXWARN))
147 {
148 id = get_identifier (c_common_reswords[i].word);
149 C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
150 C_IS_RESERVED_WORD (id) = 1;
151 }
152 continue;
153 }
154
155 id = get_identifier (c_common_reswords[i].word);
156 C_SET_RID_CODE (id, c_common_reswords[i].rid);
157 C_IS_RESERVED_WORD (id) = 1;
158 ridpointers [(int) c_common_reswords[i].rid] = id;
159 }
160
161 for (i = 0; i < NUM_INT_N_ENTS; i++)
162 {
163 /* We always create the symbols but they aren't always supported. */
164 char name[50];
165 sprintf (s: name, format: "__int%d", int_n_data[i].bitsize);
166 id = get_identifier (name);
167 C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
168 C_IS_RESERVED_WORD (id) = 1;
169
170 sprintf (s: name, format: "__int%d__", int_n_data[i].bitsize);
171 id = get_identifier (name);
172 C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
173 C_IS_RESERVED_WORD (id) = 1;
174 }
175
176 if (flag_openmp)
177 {
178 id = get_identifier ("omp_all_memory");
179 C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
180 C_IS_RESERVED_WORD (id) = 1;
181 ridpointers [RID_OMP_ALL_MEMORY] = id;
182 }
183}
184
185/* A parser structure recording information about the state and
186 context of parsing. Includes lexer information with up to two
187 tokens of look-ahead; more are not needed for C. */
188struct GTY(()) c_parser {
189 /* The look-ahead tokens. */
190 c_token * GTY((skip)) tokens;
191 /* Buffer for look-ahead tokens. */
192 c_token tokens_buf[4];
193 /* How many look-ahead tokens are available (0 - 4, or
194 more if parsing from pre-lexed tokens). */
195 unsigned int tokens_avail;
196 /* Raw look-ahead tokens, used only for checking in Objective-C
197 whether '[[' starts attributes. */
198 vec<c_token, va_gc> *raw_tokens;
199 /* The number of raw look-ahead tokens that have since been fully
200 lexed. */
201 unsigned int raw_tokens_used;
202 /* True if a syntax error is being recovered from; false otherwise.
203 c_parser_error sets this flag. It should clear this flag when
204 enough tokens have been consumed to recover from the error. */
205 BOOL_BITFIELD error : 1;
206 /* True if we're processing a pragma, and shouldn't automatically
207 consume CPP_PRAGMA_EOL. */
208 BOOL_BITFIELD in_pragma : 1;
209 /* True if we're parsing the outermost block of an if statement. */
210 BOOL_BITFIELD in_if_block : 1;
211 /* True if we want to lex a translated, joined string (for an
212 initial #pragma pch_preprocess). Otherwise the parser is
213 responsible for concatenating strings and translating to the
214 execution character set as needed. */
215 BOOL_BITFIELD lex_joined_string : 1;
216 /* True if, when the parser is concatenating string literals, it
217 should translate them to the execution character set (false
218 inside attributes). */
219 BOOL_BITFIELD translate_strings_p : 1;
220
221 /* Objective-C specific parser/lexer information. */
222
223 /* True if we are in a context where the Objective-C "PQ" keywords
224 are considered keywords. */
225 BOOL_BITFIELD objc_pq_context : 1;
226 /* True if we are parsing a (potential) Objective-C foreach
227 statement. This is set to true after we parsed 'for (' and while
228 we wait for 'in' or ';' to decide if it's a standard C for loop or an
229 Objective-C foreach loop. */
230 BOOL_BITFIELD objc_could_be_foreach_context : 1;
231 /* The following flag is needed to contextualize Objective-C lexical
232 analysis. In some cases (e.g., 'int NSObject;'), it is
233 undesirable to bind an identifier to an Objective-C class, even
234 if a class with that name exists. */
235 BOOL_BITFIELD objc_need_raw_identifier : 1;
236 /* Nonzero if we're processing a __transaction statement. The value
237 is 1 | TM_STMT_ATTR_*. */
238 unsigned int in_transaction : 4;
239 /* True if we are in a context where the Objective-C "Property attribute"
240 keywords are valid. */
241 BOOL_BITFIELD objc_property_attr_context : 1;
242
243 /* Whether we have just seen/constructed a string-literal. Set when
244 returning a string-literal from c_parser_string_literal. Reset
245 in consume_token. Useful when we get a parse error and see an
246 unknown token, which could have been a string-literal constant
247 macro. */
248 BOOL_BITFIELD seen_string_literal : 1;
249
250 /* TRUE if omp::directive, omp::decl or omp::sequence attributes may not
251 appear. */
252 BOOL_BITFIELD omp_attrs_forbidden_p : 1;
253
254 /* Location of the last consumed token. */
255 location_t last_token_location;
256
257 /* Holds state for parsing collapsed OMP_FOR loops. Managed by
258 c_parser_omp_for_loop. */
259 struct omp_for_parse_data * GTY((skip)) omp_for_parse_state;
260
261 /* If we're in the context of OpenMP directives written as C23
262 attributes turned into pragma, vector of tokens created from that,
263 otherwise NULL. */
264 vec<c_token, va_gc> *in_omp_attribute_pragma;
265
266 /* Set for omp::decl attribute parsing to the decl to which it
267 appertains. */
268 tree in_omp_decl_attribute;
269};
270
271/* Return a pointer to the Nth token in PARSERs tokens_buf. */
272
273c_token *
274c_parser_tokens_buf (c_parser *parser, unsigned n)
275{
276 return &parser->tokens_buf[n];
277}
278
279/* Return the error state of PARSER. */
280
281bool
282c_parser_error (c_parser *parser)
283{
284 return parser->error;
285}
286
287/* Set the error state of PARSER to ERR. */
288
289void
290c_parser_set_error (c_parser *parser, bool err)
291{
292 parser->error = err;
293}
294
295
296/* The actual parser and external interface. ??? Does this need to be
297 garbage-collected? */
298
299static GTY (()) c_parser *the_parser;
300
301/* Read in and lex a single token, storing it in *TOKEN. If RAW,
302 context-sensitive postprocessing of the token is not done. */
303
304static void
305c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
306{
307 timevar_push (tv: TV_LEX);
308
309 if (raw || vec_safe_length (v: parser->raw_tokens) == 0)
310 {
311 token->type = c_lex_with_flags (&token->value, &token->location,
312 &token->flags,
313 (parser->lex_joined_string
314 ? 0 : C_LEX_STRING_NO_JOIN));
315 token->id_kind = C_ID_NONE;
316 token->keyword = RID_MAX;
317 token->pragma_kind = PRAGMA_NONE;
318 }
319 else
320 {
321 /* Use a token previously lexed as a raw look-ahead token, and
322 complete the processing on it. */
323 *token = (*parser->raw_tokens)[parser->raw_tokens_used];
324 ++parser->raw_tokens_used;
325 if (parser->raw_tokens_used == vec_safe_length (v: parser->raw_tokens))
326 {
327 vec_free (v&: parser->raw_tokens);
328 parser->raw_tokens_used = 0;
329 }
330 }
331
332 if (raw)
333 goto out;
334
335 switch (token->type)
336 {
337 case CPP_NAME:
338 {
339 tree decl;
340
341 bool objc_force_identifier = parser->objc_need_raw_identifier;
342 if (c_dialect_objc ())
343 parser->objc_need_raw_identifier = false;
344
345 if (C_IS_RESERVED_WORD (token->value))
346 {
347 enum rid rid_code = C_RID_CODE (token->value);
348
349 if (rid_code == RID_CXX_COMPAT_WARN)
350 {
351 warning_at (token->location,
352 OPT_Wc___compat,
353 "identifier %qE conflicts with C++ keyword",
354 token->value);
355 }
356 else if (rid_code >= RID_FIRST_ADDR_SPACE
357 && rid_code <= RID_LAST_ADDR_SPACE)
358 {
359 addr_space_t as;
360 as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
361 targetm.addr_space.diagnose_usage (as, token->location);
362 token->id_kind = C_ID_ADDRSPACE;
363 token->keyword = rid_code;
364 break;
365 }
366 else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
367 {
368 /* We found an Objective-C "pq" keyword (in, out,
369 inout, bycopy, byref, oneway). They need special
370 care because the interpretation depends on the
371 context. */
372 if (parser->objc_pq_context)
373 {
374 token->type = CPP_KEYWORD;
375 token->keyword = rid_code;
376 break;
377 }
378 else if (parser->objc_could_be_foreach_context
379 && rid_code == RID_IN)
380 {
381 /* We are in Objective-C, inside a (potential)
382 foreach context (which means after having
383 parsed 'for (', but before having parsed ';'),
384 and we found 'in'. We consider it the keyword
385 which terminates the declaration at the
386 beginning of a foreach-statement. Note that
387 this means you can't use 'in' for anything else
388 in that context; in particular, in Objective-C
389 you can't use 'in' as the name of the running
390 variable in a C for loop. We could potentially
391 try to add code here to disambiguate, but it
392 seems a reasonable limitation. */
393 token->type = CPP_KEYWORD;
394 token->keyword = rid_code;
395 break;
396 }
397 /* Else, "pq" keywords outside of the "pq" context are
398 not keywords, and we fall through to the code for
399 normal tokens. */
400 }
401 else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
402 {
403 /* We found an Objective-C "property attribute"
404 keyword (getter, setter, readonly, etc). These are
405 only valid in the property context. */
406 if (parser->objc_property_attr_context)
407 {
408 token->type = CPP_KEYWORD;
409 token->keyword = rid_code;
410 break;
411 }
412 /* Else they are not special keywords.
413 */
414 }
415 else if (c_dialect_objc ()
416 && (OBJC_IS_AT_KEYWORD (rid_code)
417 || OBJC_IS_CXX_KEYWORD (rid_code)))
418 {
419 /* We found one of the Objective-C "@" keywords (defs,
420 selector, synchronized, etc) or one of the
421 Objective-C "cxx" keywords (class, private,
422 protected, public, try, catch, throw) without a
423 preceding '@' sign. Do nothing and fall through to
424 the code for normal tokens (in C++ we would still
425 consider the CXX ones keywords, but not in C). */
426 ;
427 }
428 else
429 {
430 token->type = CPP_KEYWORD;
431 token->keyword = rid_code;
432 break;
433 }
434 }
435
436 decl = lookup_name (token->value);
437 if (decl)
438 {
439 if (TREE_CODE (decl) == TYPE_DECL)
440 {
441 token->id_kind = C_ID_TYPENAME;
442 break;
443 }
444 }
445 else if (c_dialect_objc ())
446 {
447 tree objc_interface_decl = objc_is_class_name (token->value);
448 /* Objective-C class names are in the same namespace as
449 variables and typedefs, and hence are shadowed by local
450 declarations. */
451 if (objc_interface_decl
452 && (!objc_force_identifier || global_bindings_p ()))
453 {
454 token->value = objc_interface_decl;
455 token->id_kind = C_ID_CLASSNAME;
456 break;
457 }
458 }
459 token->id_kind = C_ID_ID;
460 }
461 break;
462 case CPP_AT_NAME:
463 /* This only happens in Objective-C; it must be a keyword. */
464 token->type = CPP_KEYWORD;
465 switch (C_RID_CODE (token->value))
466 {
467 /* Replace 'class' with '@class', 'private' with '@private',
468 etc. This prevents confusion with the C++ keyword
469 'class', and makes the tokens consistent with other
470 Objective-C 'AT' keywords. For example '@class' is
471 reported as RID_AT_CLASS which is consistent with
472 '@synchronized', which is reported as
473 RID_AT_SYNCHRONIZED.
474 */
475 case RID_CLASS: token->keyword = RID_AT_CLASS; break;
476 case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
477 case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
478 case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
479 case RID_THROW: token->keyword = RID_AT_THROW; break;
480 case RID_TRY: token->keyword = RID_AT_TRY; break;
481 case RID_CATCH: token->keyword = RID_AT_CATCH; break;
482 case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
483 default: token->keyword = C_RID_CODE (token->value);
484 }
485 break;
486 case CPP_COLON:
487 case CPP_COMMA:
488 case CPP_CLOSE_PAREN:
489 case CPP_SEMICOLON:
490 /* These tokens may affect the interpretation of any identifiers
491 following, if doing Objective-C. */
492 if (c_dialect_objc ())
493 parser->objc_need_raw_identifier = false;
494 break;
495 case CPP_PRAGMA:
496 /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
497 token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
498 token->value = NULL;
499 break;
500 default:
501 break;
502 }
503 out:
504 timevar_pop (tv: TV_LEX);
505}
506
507/* Return a pointer to the next token from PARSER, reading it in if
508 necessary. */
509
510c_token *
511c_parser_peek_token (c_parser *parser)
512{
513 if (parser->tokens_avail == 0)
514 {
515 c_lex_one_token (parser, token: &parser->tokens[0]);
516 parser->tokens_avail = 1;
517 }
518 return &parser->tokens[0];
519}
520
521/* Return a pointer to the next-but-one token from PARSER, reading it
522 in if necessary. The next token is already read in. */
523
524c_token *
525c_parser_peek_2nd_token (c_parser *parser)
526{
527 if (parser->tokens_avail >= 2)
528 return &parser->tokens[1];
529 gcc_assert (parser->tokens_avail == 1);
530 gcc_assert (parser->tokens[0].type != CPP_EOF);
531 gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
532 c_lex_one_token (parser, token: &parser->tokens[1]);
533 parser->tokens_avail = 2;
534 return &parser->tokens[1];
535}
536
537/* Return a pointer to the Nth token from PARSER, reading it
538 in if necessary. The N-1th token is already read in. */
539
540c_token *
541c_parser_peek_nth_token (c_parser *parser, unsigned int n)
542{
543 /* N is 1-based, not zero-based. */
544 gcc_assert (n > 0);
545
546 if (parser->tokens_avail >= n)
547 return &parser->tokens[n - 1];
548 gcc_assert (parser->tokens_avail == n - 1);
549 c_lex_one_token (parser, token: &parser->tokens[n - 1]);
550 parser->tokens_avail = n;
551 return &parser->tokens[n - 1];
552}
553
554/* Return a pointer to the Nth token from PARSER, reading it in as a
555 raw look-ahead token if necessary. The N-1th token is already read
556 in. Raw look-ahead tokens remain available for when the non-raw
557 functions above are called. */
558
559c_token *
560c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
561{
562 /* N is 1-based, not zero-based. */
563 gcc_assert (n > 0);
564
565 if (parser->tokens_avail >= n)
566 return &parser->tokens[n - 1];
567 unsigned int raw_len = vec_safe_length (v: parser->raw_tokens);
568 unsigned int raw_avail
569 = parser->tokens_avail + raw_len - parser->raw_tokens_used;
570 gcc_assert (raw_avail >= n - 1);
571 if (raw_avail >= n)
572 return &(*parser->raw_tokens)[parser->raw_tokens_used
573 + n - 1 - parser->tokens_avail];
574 vec_safe_reserve (v&: parser->raw_tokens, nelems: 1);
575 parser->raw_tokens->quick_grow (len: raw_len + 1);
576 c_lex_one_token (parser, token: &(*parser->raw_tokens)[raw_len], raw: true);
577 return &(*parser->raw_tokens)[raw_len];
578}
579
580bool
581c_keyword_starts_typename (enum rid keyword)
582{
583 switch (keyword)
584 {
585 case RID_UNSIGNED:
586 case RID_LONG:
587 case RID_SHORT:
588 case RID_SIGNED:
589 case RID_COMPLEX:
590 case RID_INT:
591 case RID_CHAR:
592 case RID_FLOAT:
593 case RID_DOUBLE:
594 case RID_VOID:
595 case RID_DFLOAT32:
596 case RID_DFLOAT64:
597 case RID_DFLOAT128:
598 CASE_RID_FLOATN_NX:
599 case RID_BOOL:
600 case RID_BITINT:
601 case RID_ENUM:
602 case RID_STRUCT:
603 case RID_UNION:
604 case RID_TYPEOF:
605 case RID_TYPEOF_UNQUAL:
606 case RID_CONST:
607 case RID_ATOMIC:
608 case RID_VOLATILE:
609 case RID_RESTRICT:
610 case RID_ATTRIBUTE:
611 case RID_FRACT:
612 case RID_ACCUM:
613 case RID_SAT:
614 case RID_AUTO_TYPE:
615 case RID_ALIGNAS:
616 return true;
617 default:
618 if (keyword >= RID_FIRST_INT_N
619 && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
620 && int_n_enabled_p[keyword - RID_FIRST_INT_N])
621 return true;
622 return false;
623 }
624}
625
626/* Return true if TOKEN can start a type name,
627 false otherwise. */
628bool
629c_token_starts_typename (c_token *token)
630{
631 switch (token->type)
632 {
633 case CPP_NAME:
634 switch (token->id_kind)
635 {
636 case C_ID_ID:
637 return false;
638 case C_ID_ADDRSPACE:
639 return true;
640 case C_ID_TYPENAME:
641 return true;
642 case C_ID_CLASSNAME:
643 gcc_assert (c_dialect_objc ());
644 return true;
645 default:
646 gcc_unreachable ();
647 }
648 case CPP_KEYWORD:
649 return c_keyword_starts_typename (keyword: token->keyword);
650 case CPP_LESS:
651 if (c_dialect_objc ())
652 return true;
653 return false;
654 default:
655 return false;
656 }
657}
658
659/* Return true if the next token from PARSER can start a type name,
660 false otherwise. LA specifies how to do lookahead in order to
661 detect unknown type names. If unsure, pick CLA_PREFER_ID. */
662
663static inline bool
664c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
665{
666 c_token *token = c_parser_peek_token (parser);
667 if (c_token_starts_typename (token))
668 return true;
669
670 /* Try a bit harder to detect an unknown typename. */
671 if (la != cla_prefer_id
672 && token->type == CPP_NAME
673 && token->id_kind == C_ID_ID
674
675 /* Do not try too hard when we could have "object in array". */
676 && !parser->objc_could_be_foreach_context
677
678 && (la == cla_prefer_type
679 || c_parser_peek_2nd_token (parser)->type == CPP_NAME
680 || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
681
682 /* Only unknown identifiers. */
683 && !lookup_name (token->value))
684 return true;
685
686 return false;
687}
688
689/* Return true if TOKEN, after an open parenthesis, can start a
690 compound literal (either a storage class specifier allowed in that
691 context, or a type name), false otherwise. */
692static bool
693c_token_starts_compound_literal (c_token *token)
694{
695 switch (token->type)
696 {
697 case CPP_KEYWORD:
698 switch (token->keyword)
699 {
700 case RID_CONSTEXPR:
701 case RID_REGISTER:
702 case RID_STATIC:
703 case RID_THREAD:
704 return true;
705 default:
706 break;
707 }
708 /* Fall through. */
709 default:
710 return c_token_starts_typename (token);
711 }
712}
713
714/* Return true if TOKEN is a type qualifier, false otherwise. */
715static bool
716c_token_is_qualifier (c_token *token)
717{
718 switch (token->type)
719 {
720 case CPP_NAME:
721 switch (token->id_kind)
722 {
723 case C_ID_ADDRSPACE:
724 return true;
725 default:
726 return false;
727 }
728 case CPP_KEYWORD:
729 switch (token->keyword)
730 {
731 case RID_CONST:
732 case RID_VOLATILE:
733 case RID_RESTRICT:
734 case RID_ATTRIBUTE:
735 case RID_ATOMIC:
736 return true;
737 default:
738 return false;
739 }
740 case CPP_LESS:
741 return false;
742 default:
743 gcc_unreachable ();
744 }
745}
746
747/* Return true if the next token from PARSER is a type qualifier,
748 false otherwise. */
749static inline bool
750c_parser_next_token_is_qualifier (c_parser *parser)
751{
752 c_token *token = c_parser_peek_token (parser);
753 return c_token_is_qualifier (token);
754}
755
756/* Return true if TOKEN can start declaration specifiers (not
757 including standard attributes), false otherwise. */
758static bool
759c_token_starts_declspecs (c_token *token)
760{
761 switch (token->type)
762 {
763 case CPP_NAME:
764 switch (token->id_kind)
765 {
766 case C_ID_ID:
767 return false;
768 case C_ID_ADDRSPACE:
769 return true;
770 case C_ID_TYPENAME:
771 return true;
772 case C_ID_CLASSNAME:
773 gcc_assert (c_dialect_objc ());
774 return true;
775 default:
776 gcc_unreachable ();
777 }
778 case CPP_KEYWORD:
779 switch (token->keyword)
780 {
781 case RID_STATIC:
782 case RID_EXTERN:
783 case RID_REGISTER:
784 case RID_TYPEDEF:
785 case RID_INLINE:
786 case RID_NORETURN:
787 case RID_AUTO:
788 case RID_THREAD:
789 case RID_UNSIGNED:
790 case RID_LONG:
791 case RID_SHORT:
792 case RID_SIGNED:
793 case RID_COMPLEX:
794 case RID_INT:
795 case RID_CHAR:
796 case RID_FLOAT:
797 case RID_DOUBLE:
798 case RID_VOID:
799 case RID_DFLOAT32:
800 case RID_DFLOAT64:
801 case RID_DFLOAT128:
802 CASE_RID_FLOATN_NX:
803 case RID_BOOL:
804 case RID_BITINT:
805 case RID_ENUM:
806 case RID_STRUCT:
807 case RID_UNION:
808 case RID_TYPEOF:
809 case RID_TYPEOF_UNQUAL:
810 case RID_CONST:
811 case RID_VOLATILE:
812 case RID_RESTRICT:
813 case RID_ATTRIBUTE:
814 case RID_FRACT:
815 case RID_ACCUM:
816 case RID_SAT:
817 case RID_ALIGNAS:
818 case RID_ATOMIC:
819 case RID_AUTO_TYPE:
820 case RID_CONSTEXPR:
821 return true;
822 default:
823 if (token->keyword >= RID_FIRST_INT_N
824 && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
825 && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
826 return true;
827 return false;
828 }
829 case CPP_LESS:
830 if (c_dialect_objc ())
831 return true;
832 return false;
833 default:
834 return false;
835 }
836}
837
838
839/* Return true if TOKEN can start declaration specifiers (not
840 including standard attributes) or a static assertion, false
841 otherwise. */
842static bool
843c_token_starts_declaration (c_token *token)
844{
845 if (c_token_starts_declspecs (token)
846 || token->keyword == RID_STATIC_ASSERT)
847 return true;
848 else
849 return false;
850}
851
852/* Return true if the next token from PARSER can start declaration
853 specifiers (not including standard attributes), false
854 otherwise. */
855bool
856c_parser_next_token_starts_declspecs (c_parser *parser)
857{
858 c_token *token = c_parser_peek_token (parser);
859
860 /* In Objective-C, a classname normally starts a declspecs unless it
861 is immediately followed by a dot. In that case, it is the
862 Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
863 setter/getter on the class. c_token_starts_declspecs() can't
864 differentiate between the two cases because it only checks the
865 current token, so we have a special check here. */
866 if (c_dialect_objc ()
867 && token->type == CPP_NAME
868 && token->id_kind == C_ID_CLASSNAME
869 && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
870 return false;
871
872 return c_token_starts_declspecs (token);
873}
874
875/* Return true if the next tokens from PARSER can start declaration
876 specifiers (not including standard attributes) or a static
877 assertion, false otherwise. */
878bool
879c_parser_next_tokens_start_declaration (c_parser *parser)
880{
881 c_token *token = c_parser_peek_token (parser);
882
883 /* Same as above. */
884 if (c_dialect_objc ()
885 && token->type == CPP_NAME
886 && token->id_kind == C_ID_CLASSNAME
887 && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
888 return false;
889
890 /* Labels do not start declarations. */
891 if (token->type == CPP_NAME
892 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
893 return false;
894
895 if (c_token_starts_declaration (token))
896 return true;
897
898 if (c_parser_next_tokens_start_typename (parser, la: cla_nonabstract_decl))
899 return true;
900
901 return false;
902}
903
904/* Consume the next token from PARSER. */
905
906void
907c_parser_consume_token (c_parser *parser)
908{
909 gcc_assert (parser->tokens_avail >= 1);
910 gcc_assert (parser->tokens[0].type != CPP_EOF);
911 gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
912 gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
913 parser->last_token_location = parser->tokens[0].location;
914 if (parser->tokens != &parser->tokens_buf[0])
915 parser->tokens++;
916 else if (parser->tokens_avail >= 2)
917 {
918 parser->tokens[0] = parser->tokens[1];
919 if (parser->tokens_avail >= 3)
920 {
921 parser->tokens[1] = parser->tokens[2];
922 if (parser->tokens_avail >= 4)
923 parser->tokens[2] = parser->tokens[3];
924 }
925 }
926 parser->tokens_avail--;
927 parser->seen_string_literal = false;
928}
929
930/* Expect the current token to be a #pragma. Consume it and remember
931 that we've begun parsing a pragma. */
932
933static void
934c_parser_consume_pragma (c_parser *parser)
935{
936 gcc_assert (!parser->in_pragma);
937 gcc_assert (parser->tokens_avail >= 1);
938 gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
939 if (parser->tokens != &parser->tokens_buf[0])
940 parser->tokens++;
941 else if (parser->tokens_avail >= 2)
942 {
943 parser->tokens[0] = parser->tokens[1];
944 if (parser->tokens_avail >= 3)
945 parser->tokens[1] = parser->tokens[2];
946 }
947 parser->tokens_avail--;
948 parser->in_pragma = true;
949}
950
951/* Update the global input_location from TOKEN. */
952static inline void
953c_parser_set_source_position_from_token (c_token *token)
954{
955 if (token->type != CPP_EOF)
956 {
957 input_location = token->location;
958 }
959}
960
961/* Helper function for c_parser_error.
962 Having peeked a token of kind TOK1_KIND that might signify
963 a conflict marker, peek successor tokens to determine
964 if we actually do have a conflict marker.
965 Specifically, we consider a run of 7 '<', '=' or '>' characters
966 at the start of a line as a conflict marker.
967 These come through the lexer as three pairs and a single,
968 e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
969 If it returns true, *OUT_LOC is written to with the location/range
970 of the marker. */
971
972static bool
973c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
974 location_t *out_loc)
975{
976 c_token *token2 = c_parser_peek_2nd_token (parser);
977 if (token2->type != tok1_kind)
978 return false;
979 c_token *token3 = c_parser_peek_nth_token (parser, n: 3);
980 if (token3->type != tok1_kind)
981 return false;
982 c_token *token4 = c_parser_peek_nth_token (parser, n: 4);
983 if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
984 return false;
985
986 /* It must be at the start of the line. */
987 location_t start_loc = c_parser_peek_token (parser)->location;
988 if (LOCATION_COLUMN (start_loc) != 1)
989 return false;
990
991 /* We have a conflict marker. Construct a location of the form:
992 <<<<<<<
993 ^~~~~~~
994 with start == caret, finishing at the end of the marker. */
995 location_t finish_loc = get_finish (loc: token4->location);
996 *out_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc);
997
998 return true;
999}
1000
1001/* Issue a diagnostic of the form
1002 FILE:LINE: MESSAGE before TOKEN
1003 where TOKEN is the next token in the input stream of PARSER.
1004 MESSAGE (specified by the caller) is usually of the form "expected
1005 OTHER-TOKEN".
1006
1007 Use RICHLOC as the location of the diagnostic.
1008
1009 Do not issue a diagnostic if still recovering from an error.
1010
1011 Return true iff an error was actually emitted.
1012
1013 ??? This is taken from the C++ parser, but building up messages in
1014 this way is not i18n-friendly and some other approach should be
1015 used. */
1016
1017static bool
1018c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1019 rich_location *richloc)
1020{
1021 c_token *token = c_parser_peek_token (parser);
1022 if (parser->error)
1023 return false;
1024 parser->error = true;
1025 if (!gmsgid)
1026 return false;
1027
1028 /* If this is actually a conflict marker, report it as such. */
1029 if (token->type == CPP_LSHIFT
1030 || token->type == CPP_RSHIFT
1031 || token->type == CPP_EQ_EQ)
1032 {
1033 location_t loc;
1034 if (c_parser_peek_conflict_marker (parser, tok1_kind: token->type, out_loc: &loc))
1035 {
1036 error_at (loc, "version control conflict marker in file");
1037 return true;
1038 }
1039 }
1040
1041 /* If we were parsing a string-literal and there is an unknown name
1042 token right after, then check to see if that could also have been
1043 a literal string by checking the name against a list of known
1044 standard string literal constants defined in header files. If
1045 there is one, then add that as an hint to the error message. */
1046 auto_diagnostic_group d;
1047 name_hint h;
1048 if (parser->seen_string_literal && token->type == CPP_NAME)
1049 {
1050 tree name = token->value;
1051 const char *token_name = IDENTIFIER_POINTER (name);
1052 const char *header_hint
1053 = get_c_stdlib_header_for_string_macro_name (n: token_name);
1054 if (header_hint != NULL)
1055 h = name_hint (NULL, new suggest_missing_header (token->location,
1056 token_name,
1057 header_hint));
1058 }
1059
1060 c_parse_error (gmsgid,
1061 /* Because c_parse_error does not understand
1062 CPP_KEYWORD, keywords are treated like
1063 identifiers. */
1064 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
1065 /* ??? The C parser does not save the cpp flags of a
1066 token, we need to pass 0 here and we will not get
1067 the source spelling of some tokens but rather the
1068 canonical spelling. */
1069 token->value, /*flags=*/0, richloc);
1070 return true;
1071}
1072
1073/* As c_parser_error_richloc, but issue the message at the
1074 location of PARSER's next token, or at input_location
1075 if the next token is EOF. */
1076
1077bool
1078c_parser_error (c_parser *parser, const char *gmsgid)
1079{
1080 c_token *token = c_parser_peek_token (parser);
1081 c_parser_set_source_position_from_token (token);
1082 rich_location richloc (line_table, input_location);
1083 return c_parser_error_richloc (parser, gmsgid, richloc: &richloc);
1084}
1085
1086/* Some tokens naturally come in pairs e.g.'(' and ')'.
1087 This class is for tracking such a matching pair of symbols.
1088 In particular, it tracks the location of the first token,
1089 so that if the second token is missing, we can highlight the
1090 location of the first token when notifying the user about the
1091 problem. */
1092
1093template <typename traits_t>
1094class token_pair
1095{
1096 public:
1097 /* token_pair's ctor. */
1098 token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
1099
1100 /* If the next token is the opening symbol for this pair, consume it and
1101 return true.
1102 Otherwise, issue an error and return false.
1103 In either case, record the location of the opening token. */
1104
1105 bool require_open (c_parser *parser)
1106 {
1107 c_token *token = c_parser_peek_token (parser);
1108 if (token)
1109 m_open_loc = token->location;
1110
1111 return c_parser_require (parser, traits_t::open_token_type,
1112 traits_t::open_gmsgid);
1113 }
1114
1115 /* Consume the next token from PARSER, recording its location as
1116 that of the opening token within the pair. */
1117
1118 void consume_open (c_parser *parser)
1119 {
1120 c_token *token = c_parser_peek_token (parser);
1121 gcc_assert (token->type == traits_t::open_token_type);
1122 m_open_loc = token->location;
1123 c_parser_consume_token (parser);
1124 }
1125
1126 /* If the next token is the closing symbol for this pair, consume it
1127 and return true.
1128 Otherwise, issue an error, highlighting the location of the
1129 corresponding opening token, and return false. */
1130
1131 bool require_close (c_parser *parser) const
1132 {
1133 return c_parser_require (parser, traits_t::close_token_type,
1134 traits_t::close_gmsgid, m_open_loc);
1135 }
1136
1137 /* Like token_pair::require_close, except that tokens will be skipped
1138 until the desired token is found. An error message is still produced
1139 if the next token is not as expected. */
1140
1141 void skip_until_found_close (c_parser *parser) const
1142 {
1143 c_parser_skip_until_found (parser, traits_t::close_token_type,
1144 traits_t::close_gmsgid, m_open_loc);
1145 }
1146
1147 private:
1148 location_t m_open_loc;
1149};
1150
1151/* Traits for token_pair<T> for tracking matching pairs of parentheses. */
1152
1153struct matching_paren_traits
1154{
1155 static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
1156 static const char * const open_gmsgid;
1157 static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
1158 static const char * const close_gmsgid;
1159};
1160
1161const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
1162const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
1163
1164/* "matching_parens" is a token_pair<T> class for tracking matching
1165 pairs of parentheses. */
1166
1167typedef token_pair<matching_paren_traits> matching_parens;
1168
1169/* Traits for token_pair<T> for tracking matching pairs of braces. */
1170
1171struct matching_brace_traits
1172{
1173 static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
1174 static const char * const open_gmsgid;
1175 static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
1176 static const char * const close_gmsgid;
1177};
1178
1179const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
1180const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
1181
1182/* "matching_braces" is a token_pair<T> class for tracking matching
1183 pairs of braces. */
1184
1185typedef token_pair<matching_brace_traits> matching_braces;
1186
1187/* Get a description of the matching symbol to TYPE e.g. "(" for
1188 CPP_CLOSE_PAREN. */
1189
1190static const char *
1191get_matching_symbol (enum cpp_ttype type)
1192{
1193 switch (type)
1194 {
1195 default:
1196 gcc_unreachable ();
1197 case CPP_CLOSE_PAREN:
1198 return "(";
1199 case CPP_CLOSE_BRACE:
1200 return "{";
1201 }
1202}
1203
1204/* If the next token is of the indicated TYPE, consume it. Otherwise,
1205 issue the error MSGID. If MSGID is NULL then a message has already
1206 been produced and no message will be produced this time. Returns
1207 true if found, false otherwise.
1208
1209 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1210 within any error as the location of an "opening" token matching
1211 the close token TYPE (e.g. the location of the '(' when TYPE is
1212 CPP_CLOSE_PAREN).
1213
1214 If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
1215 one type (e.g. "expected %<)%>") and thus it may be reasonable to
1216 attempt to generate a fix-it hint for the problem.
1217 Otherwise msgid describes multiple token types (e.g.
1218 "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
1219 generate a fix-it hint. */
1220
1221bool
1222c_parser_require (c_parser *parser,
1223 enum cpp_ttype type,
1224 const char *msgid,
1225 location_t matching_location,
1226 bool type_is_unique)
1227{
1228 if (c_parser_next_token_is (parser, type))
1229 {
1230 c_parser_consume_token (parser);
1231 return true;
1232 }
1233 else
1234 {
1235 location_t next_token_loc = c_parser_peek_token (parser)->location;
1236 gcc_rich_location richloc (next_token_loc);
1237
1238 /* Potentially supply a fix-it hint, suggesting to add the
1239 missing token immediately after the *previous* token.
1240 This may move the primary location within richloc. */
1241 if (!parser->error && type_is_unique)
1242 maybe_suggest_missing_token_insertion (richloc: &richloc, token_type: type,
1243 prev_token_loc: parser->last_token_location);
1244
1245 /* If matching_location != UNKNOWN_LOCATION, highlight it.
1246 Attempt to consolidate diagnostics by printing it as a
1247 secondary range within the main diagnostic. */
1248 bool added_matching_location = false;
1249 if (matching_location != UNKNOWN_LOCATION)
1250 added_matching_location
1251 = richloc.add_location_if_nearby (loc: matching_location);
1252
1253 if (c_parser_error_richloc (parser, gmsgid: msgid, richloc: &richloc))
1254 /* If we weren't able to consolidate matching_location, then
1255 print it as a secondary diagnostic. */
1256 if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1257 inform (matching_location, "to match this %qs",
1258 get_matching_symbol (type));
1259
1260 return false;
1261 }
1262}
1263
1264/* If the next token is the indicated keyword, consume it. Otherwise,
1265 issue the error MSGID. Returns true if found, false otherwise. */
1266
1267static bool
1268c_parser_require_keyword (c_parser *parser,
1269 enum rid keyword,
1270 const char *msgid)
1271{
1272 if (c_parser_next_token_is_keyword (parser, keyword))
1273 {
1274 c_parser_consume_token (parser);
1275 return true;
1276 }
1277 else
1278 {
1279 c_parser_error (parser, gmsgid: msgid);
1280 return false;
1281 }
1282}
1283
1284/* Like c_parser_require, except that tokens will be skipped until the
1285 desired token is found. An error message is still produced if the
1286 next token is not as expected. If MSGID is NULL then a message has
1287 already been produced and no message will be produced this
1288 time.
1289
1290 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1291 within any error as the location of an "opening" token matching
1292 the close token TYPE (e.g. the location of the '(' when TYPE is
1293 CPP_CLOSE_PAREN). */
1294
1295void
1296c_parser_skip_until_found (c_parser *parser,
1297 enum cpp_ttype type,
1298 const char *msgid,
1299 location_t matching_location)
1300{
1301 unsigned nesting_depth = 0;
1302
1303 if (c_parser_require (parser, type, msgid, matching_location))
1304 {
1305 if (UNLIKELY (type == CPP_PRAGMA_EOL) && parser->in_omp_attribute_pragma)
1306 {
1307 c_token *token = c_parser_peek_token (parser);
1308 if (token->type == CPP_EOF)
1309 {
1310 parser->tokens = &parser->tokens_buf[0];
1311 parser->tokens_avail = token->flags;
1312 parser->in_omp_attribute_pragma = NULL;
1313 }
1314 }
1315 return;
1316 }
1317
1318 /* Skip tokens until the desired token is found. */
1319 while (true)
1320 {
1321 /* Peek at the next token. */
1322 c_token *token = c_parser_peek_token (parser);
1323 /* If we've reached the token we want, consume it and stop. */
1324 if (token->type == type && !nesting_depth)
1325 {
1326 c_parser_consume_token (parser);
1327 if (UNLIKELY (type == CPP_PRAGMA_EOL)
1328 && parser->in_omp_attribute_pragma)
1329 {
1330 c_token *token = c_parser_peek_token (parser);
1331 if (token->type == CPP_EOF)
1332 {
1333 parser->tokens = &parser->tokens_buf[0];
1334 parser->tokens_avail = token->flags;
1335 parser->in_omp_attribute_pragma = NULL;
1336 }
1337 }
1338 break;
1339 }
1340
1341 /* If we've run out of tokens, stop. */
1342 if (token->type == CPP_EOF)
1343 return;
1344 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1345 return;
1346 if (token->type == CPP_OPEN_BRACE
1347 || token->type == CPP_OPEN_PAREN
1348 || token->type == CPP_OPEN_SQUARE)
1349 ++nesting_depth;
1350 else if (token->type == CPP_CLOSE_BRACE
1351 || token->type == CPP_CLOSE_PAREN
1352 || token->type == CPP_CLOSE_SQUARE)
1353 {
1354 if (nesting_depth-- == 0)
1355 break;
1356 }
1357 /* Consume this token. */
1358 c_parser_consume_token (parser);
1359 }
1360 parser->error = false;
1361}
1362
1363/* Skip tokens until the end of a parameter is found, but do not
1364 consume the comma, semicolon or closing delimiter. */
1365
1366static void
1367c_parser_skip_to_end_of_parameter (c_parser *parser)
1368{
1369 unsigned nesting_depth = 0;
1370
1371 while (true)
1372 {
1373 c_token *token = c_parser_peek_token (parser);
1374 if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1375 && !nesting_depth)
1376 break;
1377 /* If we've run out of tokens, stop. */
1378 if (token->type == CPP_EOF)
1379 return;
1380 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1381 return;
1382 if (token->type == CPP_OPEN_BRACE
1383 || token->type == CPP_OPEN_PAREN
1384 || token->type == CPP_OPEN_SQUARE)
1385 ++nesting_depth;
1386 else if (token->type == CPP_CLOSE_BRACE
1387 || token->type == CPP_CLOSE_PAREN
1388 || token->type == CPP_CLOSE_SQUARE)
1389 {
1390 if (nesting_depth-- == 0)
1391 break;
1392 }
1393 /* Consume this token. */
1394 c_parser_consume_token (parser);
1395 }
1396 parser->error = false;
1397}
1398
1399/* Expect to be at the end of the pragma directive and consume an
1400 end of line marker. */
1401
1402static void
1403c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1404{
1405 gcc_assert (parser->in_pragma);
1406 parser->in_pragma = false;
1407
1408 if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
1409 c_parser_error (parser, gmsgid: "expected end of line");
1410
1411 cpp_ttype token_type;
1412 do
1413 {
1414 c_token *token = c_parser_peek_token (parser);
1415 token_type = token->type;
1416 if (token_type == CPP_EOF)
1417 break;
1418 c_parser_consume_token (parser);
1419 }
1420 while (token_type != CPP_PRAGMA_EOL);
1421
1422 if (parser->in_omp_attribute_pragma)
1423 {
1424 c_token *token = c_parser_peek_token (parser);
1425 if (token->type == CPP_EOF)
1426 {
1427 parser->tokens = &parser->tokens_buf[0];
1428 parser->tokens_avail = token->flags;
1429 parser->in_omp_attribute_pragma = NULL;
1430 }
1431 }
1432
1433 parser->error = false;
1434}
1435
1436/* Skip tokens until we have consumed an entire block, or until we
1437 have consumed a non-nested ';'. */
1438
1439static void
1440c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
1441{
1442 unsigned nesting_depth = 0;
1443 bool save_error = parser->error;
1444
1445 while (true)
1446 {
1447 c_token *token;
1448
1449 /* Peek at the next token. */
1450 token = c_parser_peek_token (parser);
1451
1452 switch (token->type)
1453 {
1454 case CPP_EOF:
1455 return;
1456
1457 case CPP_PRAGMA_EOL:
1458 if (parser->in_pragma)
1459 return;
1460 break;
1461
1462 case CPP_SEMICOLON:
1463 /* If the next token is a ';', we have reached the
1464 end of the statement. */
1465 if (!nesting_depth)
1466 {
1467 /* Consume the ';'. */
1468 c_parser_consume_token (parser);
1469 goto finished;
1470 }
1471 break;
1472
1473 case CPP_CLOSE_BRACE:
1474 /* If the next token is a non-nested '}', then we have
1475 reached the end of the current block. */
1476 if (nesting_depth == 0 || --nesting_depth == 0)
1477 {
1478 c_parser_consume_token (parser);
1479 goto finished;
1480 }
1481 break;
1482
1483 case CPP_OPEN_BRACE:
1484 /* If it the next token is a '{', then we are entering a new
1485 block. Consume the entire block. */
1486 ++nesting_depth;
1487 break;
1488
1489 case CPP_PRAGMA:
1490 /* If we see a pragma, consume the whole thing at once. We
1491 have some safeguards against consuming pragmas willy-nilly.
1492 Normally, we'd expect to be here with parser->error set,
1493 which disables these safeguards. But it's possible to get
1494 here for secondary error recovery, after parser->error has
1495 been cleared. */
1496 c_parser_consume_pragma (parser);
1497 c_parser_skip_to_pragma_eol (parser);
1498 parser->error = save_error;
1499 continue;
1500
1501 default:
1502 break;
1503 }
1504
1505 c_parser_consume_token (parser);
1506 }
1507
1508 finished:
1509 parser->error = false;
1510}
1511
1512/* CPP's options (initialized by c-opts.cc). */
1513extern cpp_options *cpp_opts;
1514
1515/* Save the warning flags which are controlled by __extension__. */
1516
1517static inline int
1518disable_extension_diagnostics (void)
1519{
1520 int ret = (pedantic
1521 | (warn_pointer_arith << 1)
1522 | (warn_traditional << 2)
1523 | (flag_iso << 3)
1524 | (warn_long_long << 4)
1525 | (warn_cxx_compat << 5)
1526 | (warn_overlength_strings << 6)
1527 /* warn_c90_c99_compat has three states: -1/0/1, so we must
1528 play tricks to properly restore it. */
1529 | ((warn_c90_c99_compat == 1) << 7)
1530 | ((warn_c90_c99_compat == -1) << 8)
1531 /* Similarly for warn_c99_c11_compat. */
1532 | ((warn_c99_c11_compat == 1) << 9)
1533 | ((warn_c99_c11_compat == -1) << 10)
1534 /* Similarly for warn_c11_c23_compat. */
1535 | ((warn_c11_c23_compat == 1) << 11)
1536 | ((warn_c11_c23_compat == -1) << 12)
1537 );
1538 cpp_opts->cpp_pedantic = pedantic = 0;
1539 warn_pointer_arith = 0;
1540 cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1541 flag_iso = 0;
1542 cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1543 warn_cxx_compat = 0;
1544 warn_overlength_strings = 0;
1545 warn_c90_c99_compat = 0;
1546 warn_c99_c11_compat = 0;
1547 warn_c11_c23_compat = 0;
1548 return ret;
1549}
1550
1551/* Restore the warning flags which are controlled by __extension__.
1552 FLAGS is the return value from disable_extension_diagnostics. */
1553
1554static inline void
1555restore_extension_diagnostics (int flags)
1556{
1557 cpp_opts->cpp_pedantic = pedantic = flags & 1;
1558 warn_pointer_arith = (flags >> 1) & 1;
1559 cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1560 flag_iso = (flags >> 3) & 1;
1561 cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1562 warn_cxx_compat = (flags >> 5) & 1;
1563 warn_overlength_strings = (flags >> 6) & 1;
1564 /* See above for why is this needed. */
1565 warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1566 warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1567 warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1568}
1569
1570/* Helper data structure for parsing #pragma acc routine. */
1571struct oacc_routine_data {
1572 bool error_seen; /* Set if error has been reported. */
1573 bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
1574 tree clauses;
1575 location_t loc;
1576};
1577
1578/* Used for parsing objc foreach statements. */
1579static tree objc_foreach_break_label, objc_foreach_continue_label;
1580
1581/* Used for parsing OMP for loops.
1582
1583 Some notes on flags used for context:
1584 parser->omp_for_parse_state is non-null anywhere inside the OMP FOR
1585 construct, except for the final-loop-body.
1586 The want_nested_loop flag is true if inside a {} sequence where
1587 a loop-nest (or another {} sequence containing a loop-nest) is expected,
1588 but has not yet been seen. It's false when parsing intervening code
1589 statements or their substatements that cannot contain a loop-nest.
1590 The in_intervening_code flag is true when parsing any intervening code,
1591 including substatements, and whether or not want_nested_loop is true.
1592
1593 And, about error handling:
1594 The saw_intervening_code flag is set if the loop is not perfectly
1595 nested, even in the usual case where this is not an error.
1596 perfect_nesting_fail is set if an error has been diagnosed because an
1597 imperfectly-nested loop was found where a perfectly-nested one is
1598 required (we diagnose this only once).
1599 fail is set if any kind of structural error in the loop nest
1600 has been found and diagnosed.
1601 */
1602struct omp_for_parse_data {
1603 enum tree_code code;
1604 tree declv, condv, incrv, initv;
1605 tree pre_body;
1606 tree bindings;
1607 int count; /* Expected nesting depth. */
1608 int depth; /* Current nesting depth. */
1609 location_t for_loc;
1610 bool ordered : 1;
1611 bool inscan : 1;
1612 bool want_nested_loop : 1;
1613 bool in_intervening_code : 1;
1614 bool saw_intervening_code: 1;
1615 bool perfect_nesting_fail : 1;
1616 bool fail : 1;
1617};
1618
1619static bool c_parser_nth_token_starts_std_attributes (c_parser *,
1620 unsigned int);
1621static tree c_parser_std_attribute_specifier_sequence (c_parser *);
1622static void c_parser_external_declaration (c_parser *);
1623static void c_parser_asm_definition (c_parser *);
1624static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
1625 bool, bool, tree * = NULL,
1626 vec<c_token> * = NULL,
1627 bool have_attrs = false,
1628 tree attrs = NULL,
1629 struct oacc_routine_data * = NULL,
1630 bool * = NULL);
1631static bool c_parser_handle_statement_omp_attributes (c_parser *, tree &,
1632 bool *);
1633static void c_parser_static_assert_declaration_no_semi (c_parser *);
1634static void c_parser_static_assert_declaration (c_parser *);
1635static struct c_typespec c_parser_enum_specifier (c_parser *);
1636static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
1637static tree c_parser_struct_declaration (c_parser *, tree *);
1638static struct c_typespec c_parser_typeof_specifier (c_parser *);
1639static tree c_parser_alignas_specifier (c_parser *);
1640static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
1641 c_dtr_syn, bool *);
1642static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
1643 bool,
1644 struct c_declarator *);
1645static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
1646 bool);
1647static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
1648 tree, bool);
1649static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
1650static tree c_parser_simple_asm_expr (c_parser *);
1651static tree c_parser_gnu_attributes (c_parser *);
1652static struct c_expr c_parser_initializer (c_parser *, tree);
1653static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
1654 struct obstack *, tree);
1655static void c_parser_initelt (c_parser *, struct obstack *);
1656static void c_parser_initval (c_parser *, struct c_expr *,
1657 struct obstack *);
1658static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
1659static location_t c_parser_compound_statement_nostart (c_parser *);
1660static void c_parser_label (c_parser *, tree);
1661static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
1662static void c_parser_statement_after_labels (c_parser *, bool *,
1663 vec<tree> * = NULL);
1664static tree c_parser_c99_block_statement (c_parser *, bool *,
1665 location_t * = NULL);
1666static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
1667static void c_parser_switch_statement (c_parser *, bool *);
1668static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
1669 bool *);
1670static void c_parser_do_statement (c_parser *, bool, unsigned short, bool);
1671static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
1672 bool *);
1673static tree c_parser_asm_statement (c_parser *);
1674static tree c_parser_asm_operands (c_parser *);
1675static tree c_parser_asm_goto_operands (c_parser *);
1676static tree c_parser_asm_clobbers (c_parser *);
1677static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
1678 tree = NULL_TREE);
1679static struct c_expr c_parser_conditional_expression (c_parser *,
1680 struct c_expr *, tree);
1681static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
1682 tree);
1683static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
1684static struct c_expr c_parser_unary_expression (c_parser *);
1685static struct c_expr c_parser_sizeof_expression (c_parser *);
1686static struct c_expr c_parser_alignof_expression (c_parser *);
1687static struct c_expr c_parser_postfix_expression (c_parser *);
1688static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
1689 struct c_declspecs *,
1690 struct c_type_name *,
1691 location_t);
1692static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
1693 location_t loc,
1694 struct c_expr);
1695static tree c_parser_transaction (c_parser *, enum rid);
1696static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
1697static tree c_parser_transaction_cancel (c_parser *);
1698static struct c_expr c_parser_expression (c_parser *);
1699static struct c_expr c_parser_expression_conv (c_parser *);
1700static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
1701 vec<tree, va_gc> **, location_t *,
1702 tree *, vec<location_t> *,
1703 unsigned int * = NULL);
1704static struct c_expr c_parser_has_attribute_expression (c_parser *);
1705
1706static void c_parser_oacc_declare (c_parser *);
1707static void c_parser_oacc_enter_exit_data (c_parser *, bool);
1708static void c_parser_oacc_update (c_parser *);
1709static void c_parser_omp_construct (c_parser *, bool *);
1710static void c_parser_omp_threadprivate (c_parser *);
1711static void c_parser_omp_barrier (c_parser *);
1712static void c_parser_omp_depobj (c_parser *);
1713static void c_parser_omp_flush (c_parser *);
1714static tree c_parser_omp_loop_nest (c_parser *, bool *);
1715static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
1716 tree, tree *, bool *);
1717static void c_parser_omp_taskwait (c_parser *);
1718static void c_parser_omp_taskyield (c_parser *);
1719static void c_parser_omp_cancel (c_parser *);
1720static void c_parser_omp_nothing (c_parser *);
1721
1722enum pragma_context { pragma_external, pragma_struct, pragma_param,
1723 pragma_stmt, pragma_compound };
1724static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
1725static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
1726static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
1727static void c_parser_omp_begin (c_parser *);
1728static void c_parser_omp_end (c_parser *);
1729static bool c_parser_omp_declare (c_parser *, enum pragma_context);
1730static void c_parser_omp_requires (c_parser *);
1731static bool c_parser_omp_error (c_parser *, enum pragma_context);
1732static void c_parser_omp_assumption_clauses (c_parser *, bool);
1733static void c_parser_omp_allocate (c_parser *);
1734static void c_parser_omp_assumes (c_parser *);
1735static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
1736static void c_parser_oacc_routine (c_parser *, enum pragma_context);
1737
1738/* These Objective-C parser functions are only ever called when
1739 compiling Objective-C. */
1740static void c_parser_objc_class_definition (c_parser *, tree);
1741static void c_parser_objc_class_instance_variables (c_parser *);
1742static void c_parser_objc_class_declaration (c_parser *);
1743static void c_parser_objc_alias_declaration (c_parser *);
1744static void c_parser_objc_protocol_definition (c_parser *, tree);
1745static bool c_parser_objc_method_type (c_parser *);
1746static void c_parser_objc_method_definition (c_parser *);
1747static void c_parser_objc_methodprotolist (c_parser *);
1748static void c_parser_objc_methodproto (c_parser *);
1749static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
1750static tree c_parser_objc_type_name (c_parser *);
1751static tree c_parser_objc_protocol_refs (c_parser *);
1752static void c_parser_objc_try_catch_finally_statement (c_parser *);
1753static void c_parser_objc_synchronized_statement (c_parser *);
1754static tree c_parser_objc_selector (c_parser *);
1755static tree c_parser_objc_selector_arg (c_parser *);
1756static tree c_parser_objc_receiver (c_parser *);
1757static tree c_parser_objc_message_args (c_parser *);
1758static tree c_parser_objc_keywordexpr (c_parser *);
1759static void c_parser_objc_at_property_declaration (c_parser *);
1760static void c_parser_objc_at_synthesize_declaration (c_parser *);
1761static void c_parser_objc_at_dynamic_declaration (c_parser *);
1762static bool c_parser_objc_diagnose_bad_element_prefix
1763 (c_parser *, struct c_declspecs *);
1764static location_t c_parser_parse_rtl_body (c_parser *, char *);
1765
1766#if ENABLE_ANALYZER
1767
1768namespace ana {
1769
1770/* Concrete implementation of ana::translation_unit for the C frontend. */
1771
1772class c_translation_unit : public translation_unit
1773{
1774public:
1775 /* Implementation of translation_unit::lookup_constant_by_id for use by the
1776 analyzer to look up named constants in the user's source code. */
1777 tree lookup_constant_by_id (tree id) const final override
1778 {
1779 /* Consider decls. */
1780 if (tree decl = lookup_name (id))
1781 if (TREE_CODE (decl) == CONST_DECL)
1782 if (tree value = DECL_INITIAL (decl))
1783 if (TREE_CODE (value) == INTEGER_CST)
1784 return value;
1785
1786 /* Consider macros. */
1787 cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1788 if (cpp_macro_p (node: hashnode))
1789 if (tree value = consider_macro (macro: hashnode->value.macro))
1790 return value;
1791
1792 return NULL_TREE;
1793 }
1794
1795 tree
1796 lookup_type_by_id (tree id) const final override
1797 {
1798 if (tree type_decl = lookup_name (id))
1799 if (TREE_CODE (type_decl) == TYPE_DECL)
1800 {
1801 tree record_type = TREE_TYPE (type_decl);
1802 if (TREE_CODE (record_type) == RECORD_TYPE)
1803 return record_type;
1804 }
1805
1806 return NULL_TREE;
1807 }
1808
1809 tree
1810 lookup_global_var_by_id (tree id) const final override
1811 {
1812 if (tree var_decl = lookup_name (id))
1813 if (TREE_CODE (var_decl) == VAR_DECL)
1814 return var_decl;
1815
1816 return NULL_TREE;
1817 }
1818
1819private:
1820 /* Attempt to get an INTEGER_CST from MACRO.
1821 Only handle the simplest cases: where MACRO's definition is a single
1822 token containing a number, by lexing the number again.
1823 This will handle e.g.
1824 #define NAME 42
1825 and other bases but not negative numbers, parentheses or e.g.
1826 #define NAME 1 << 7
1827 as doing so would require a parser. */
1828 tree consider_macro (cpp_macro *macro) const
1829 {
1830 if (macro->paramc > 0)
1831 return NULL_TREE;
1832 if (macro->kind != cmk_macro)
1833 return NULL_TREE;
1834 if (macro->count != 1)
1835 return NULL_TREE;
1836 const cpp_token &tok = macro->exp.tokens[0];
1837 if (tok.type != CPP_NUMBER)
1838 return NULL_TREE;
1839
1840 cpp_reader *old_parse_in = parse_in;
1841 parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
1842
1843 pretty_printer pp;
1844 pp_string (&pp, (const char *) tok.val.str.text);
1845 pp_newline (&pp);
1846 cpp_push_buffer (parse_in,
1847 (const unsigned char *) pp_formatted_text (&pp),
1848 strlen (s: pp_formatted_text (&pp)),
1849 0);
1850
1851 tree value;
1852 location_t loc;
1853 unsigned char cpp_flags;
1854 c_lex_with_flags (&value, &loc, &cpp_flags, 0);
1855
1856 cpp_destroy (parse_in);
1857 parse_in = old_parse_in;
1858
1859 if (value && TREE_CODE (value) == INTEGER_CST)
1860 return value;
1861
1862 return NULL_TREE;
1863 }
1864};
1865
1866} // namespace ana
1867
1868#endif /* #if ENABLE_ANALYZER */
1869
1870/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
1871
1872 translation-unit:
1873 external-declarations
1874
1875 external-declarations:
1876 external-declaration
1877 external-declarations external-declaration
1878
1879 GNU extensions:
1880
1881 translation-unit:
1882 empty
1883*/
1884
1885static void
1886c_parser_translation_unit (c_parser *parser)
1887{
1888 if (c_parser_next_token_is (parser, type: CPP_EOF))
1889 {
1890 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
1891 "ISO C forbids an empty translation unit");
1892 }
1893 else
1894 {
1895 void *obstack_position = obstack_alloc (&parser_obstack, 0);
1896 mark_valid_location_for_stdc_pragma (false);
1897 do
1898 {
1899 ggc_collect ();
1900 c_parser_external_declaration (parser);
1901 obstack_free (&parser_obstack, obstack_position);
1902 }
1903 while (c_parser_next_token_is_not (parser, type: CPP_EOF));
1904 }
1905
1906 unsigned int i;
1907 tree decl;
1908 FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
1909 if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
1910 error ("storage size of %q+D isn%'t known", decl);
1911
1912 if (vec_safe_length (v: current_omp_declare_target_attribute))
1913 {
1914 c_omp_declare_target_attr
1915 a = current_omp_declare_target_attribute->pop ();
1916 if (!errorcount)
1917 error ("%qs without corresponding %qs",
1918 a.device_type >= 0 ? "#pragma omp begin declare target"
1919 : "#pragma omp declare target",
1920 "#pragma omp end declare target");
1921 vec_safe_truncate (v: current_omp_declare_target_attribute, size: 0);
1922 }
1923 if (vec_safe_length (v: current_omp_begin_assumes))
1924 {
1925 if (!errorcount)
1926 error ("%qs without corresponding %qs",
1927 "#pragma omp begin assumes", "#pragma omp end assumes");
1928 vec_safe_truncate (v: current_omp_begin_assumes, size: 0);
1929 }
1930
1931#if ENABLE_ANALYZER
1932 if (flag_analyzer)
1933 {
1934 ana::c_translation_unit tu;
1935 ana::on_finish_translation_unit (tu);
1936 }
1937#endif
1938}
1939
1940/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
1941
1942 external-declaration:
1943 function-definition
1944 declaration
1945
1946 GNU extensions:
1947
1948 external-declaration:
1949 asm-definition
1950 ;
1951 __extension__ external-declaration
1952
1953 Objective-C:
1954
1955 external-declaration:
1956 objc-class-definition
1957 objc-class-declaration
1958 objc-alias-declaration
1959 objc-protocol-definition
1960 objc-method-definition
1961 @end
1962*/
1963
1964static void
1965c_parser_external_declaration (c_parser *parser)
1966{
1967 int ext;
1968 switch (c_parser_peek_token (parser)->type)
1969 {
1970 case CPP_KEYWORD:
1971 switch (c_parser_peek_token (parser)->keyword)
1972 {
1973 case RID_EXTENSION:
1974 ext = disable_extension_diagnostics ();
1975 c_parser_consume_token (parser);
1976 c_parser_external_declaration (parser);
1977 restore_extension_diagnostics (flags: ext);
1978 break;
1979 case RID_ASM:
1980 c_parser_asm_definition (parser);
1981 break;
1982 case RID_AT_INTERFACE:
1983 case RID_AT_IMPLEMENTATION:
1984 gcc_assert (c_dialect_objc ());
1985 c_parser_objc_class_definition (parser, NULL_TREE);
1986 break;
1987 case RID_AT_CLASS:
1988 gcc_assert (c_dialect_objc ());
1989 c_parser_objc_class_declaration (parser);
1990 break;
1991 case RID_AT_ALIAS:
1992 gcc_assert (c_dialect_objc ());
1993 c_parser_objc_alias_declaration (parser);
1994 break;
1995 case RID_AT_PROTOCOL:
1996 gcc_assert (c_dialect_objc ());
1997 c_parser_objc_protocol_definition (parser, NULL_TREE);
1998 break;
1999 case RID_AT_PROPERTY:
2000 gcc_assert (c_dialect_objc ());
2001 c_parser_objc_at_property_declaration (parser);
2002 break;
2003 case RID_AT_SYNTHESIZE:
2004 gcc_assert (c_dialect_objc ());
2005 c_parser_objc_at_synthesize_declaration (parser);
2006 break;
2007 case RID_AT_DYNAMIC:
2008 gcc_assert (c_dialect_objc ());
2009 c_parser_objc_at_dynamic_declaration (parser);
2010 break;
2011 case RID_AT_END:
2012 gcc_assert (c_dialect_objc ());
2013 c_parser_consume_token (parser);
2014 objc_finish_implementation ();
2015 break;
2016 default:
2017 goto decl_or_fndef;
2018 }
2019 break;
2020 case CPP_SEMICOLON:
2021 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2022 "ISO C does not allow extra %<;%> outside of a function");
2023 c_parser_consume_token (parser);
2024 break;
2025 case CPP_PRAGMA:
2026 mark_valid_location_for_stdc_pragma (true);
2027 c_parser_pragma (parser, pragma_external, NULL);
2028 mark_valid_location_for_stdc_pragma (false);
2029 break;
2030 case CPP_PLUS:
2031 case CPP_MINUS:
2032 if (c_dialect_objc ())
2033 {
2034 c_parser_objc_method_definition (parser);
2035 break;
2036 }
2037 /* Else fall through, and yield a syntax error trying to parse
2038 as a declaration or function definition. */
2039 /* FALLTHRU */
2040 default:
2041 decl_or_fndef:
2042 /* A declaration or a function definition (or, in Objective-C,
2043 an @interface or @protocol with prefix attributes). We can
2044 only tell which after parsing the declaration specifiers, if
2045 any, and the first declarator. */
2046 c_parser_declaration_or_fndef (parser, true, true, true, false, true);
2047 break;
2048 }
2049}
2050
2051static void c_parser_handle_directive_omp_attributes (tree &, vec<c_token> *&,
2052 vec<c_token> *);
2053static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
2054static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
2055
2056/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
2057
2058static void
2059add_debug_begin_stmt (location_t loc)
2060{
2061 /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2062 if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2063 return;
2064
2065 tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2066 SET_EXPR_LOCATION (stmt, loc);
2067 add_stmt (stmt);
2068}
2069
2070/* Helper function for c_parser_declaration_or_fndef and
2071 Handle assume attribute(s). */
2072
2073static tree
2074handle_assume_attribute (location_t here, tree attrs, bool nested)
2075{
2076 if (nested)
2077 for (tree attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: attrs); attr;
2078 attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", TREE_CHAIN (attr)))
2079 {
2080 tree args = TREE_VALUE (attr);
2081 int nargs = list_length (args);
2082 if (nargs != 1)
2083 {
2084 error_at (here, "wrong number of arguments specified "
2085 "for %qE attribute",
2086 get_attribute_name (attr));
2087 inform (here, "expected %i, found %i", 1, nargs);
2088 }
2089 else
2090 {
2091 tree arg = TREE_VALUE (args);
2092 arg = c_objc_common_truthvalue_conversion (here, arg);
2093 arg = c_fully_fold (arg, false, NULL);
2094 if (arg != error_mark_node)
2095 {
2096 tree fn = build_call_expr_internal_loc (here, IFN_ASSUME,
2097 void_type_node, 1,
2098 arg);
2099 add_stmt (fn);
2100 }
2101 }
2102 }
2103 else
2104 pedwarn (here, OPT_Wattributes,
2105 "%<assume%> attribute at top level");
2106
2107 return remove_attribute ("gnu", "assume", attrs);
2108}
2109
2110/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
2111 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
2112 is accepted; otherwise (old-style parameter declarations) only other
2113 declarations are accepted. If STATIC_ASSERT_OK is true, a static
2114 assertion is accepted; otherwise (old-style parameter declarations)
2115 it is not. If NESTED is true, we are inside a function or parsing
2116 old-style parameter declarations; any functions encountered are
2117 nested functions and declaration specifiers are required; otherwise
2118 we are at top level and functions are normal functions and
2119 declaration specifiers may be optional. If EMPTY_OK is true, empty
2120 declarations are OK (subject to all other constraints); otherwise
2121 (old-style parameter declarations) they are diagnosed. If
2122 START_ATTR_OK is true, the declaration specifiers may start with
2123 attributes (GNU or standard); otherwise they may not.
2124 OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
2125 declaration when parsing an Objective-C foreach statement.
2126 FALLTHRU_ATTR_P is used to signal whether this function parsed
2127 "__attribute__((fallthrough));". ATTRS are any standard attributes
2128 parsed in the caller (in contexts where such attributes had to be
2129 parsed to determine whether what follows is a declaration or a
2130 statement); HAVE_ATTRS says whether there were any such attributes
2131 (even empty).
2132
2133 declaration:
2134 declaration-specifiers init-declarator-list[opt] ;
2135 static_assert-declaration
2136
2137 function-definition:
2138 declaration-specifiers[opt] declarator declaration-list[opt]
2139 compound-statement
2140
2141 declaration-list:
2142 declaration
2143 declaration-list declaration
2144
2145 init-declarator-list:
2146 init-declarator
2147 init-declarator-list , init-declarator
2148
2149 init-declarator:
2150 declarator simple-asm-expr[opt] gnu-attributes[opt]
2151 declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
2152
2153 GNU extensions:
2154
2155 nested-function-definition:
2156 declaration-specifiers declarator declaration-list[opt]
2157 compound-statement
2158
2159 attribute ;
2160
2161 Objective-C:
2162 gnu-attributes objc-class-definition
2163 gnu-attributes objc-category-definition
2164 gnu-attributes objc-protocol-definition
2165
2166 The simple-asm-expr and gnu-attributes are GNU extensions.
2167
2168 This function does not handle __extension__; that is handled in its
2169 callers. ??? Following the old parser, __extension__ may start
2170 external declarations, declarations in functions and declarations
2171 at the start of "for" loops, but not old-style parameter
2172 declarations.
2173
2174 C99 requires declaration specifiers in a function definition; the
2175 absence is diagnosed through the diagnosis of implicit int. In GNU
2176 C we also allow but diagnose declarations without declaration
2177 specifiers, but only at top level (elsewhere they conflict with
2178 other syntax).
2179
2180 In Objective-C, declarations of the looping variable in a foreach
2181 statement are exceptionally terminated by 'in' (for example, 'for
2182 (NSObject *object in array) { ... }').
2183
2184 OpenMP:
2185
2186 declaration:
2187 threadprivate-directive
2188
2189 GIMPLE:
2190
2191 gimple-function-definition:
2192 declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
2193 declaration-list[opt] compound-statement
2194
2195 rtl-function-definition:
2196 declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
2197 declaration-list[opt] compound-statement */
2198
2199static void
2200c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
2201 bool static_assert_ok, bool empty_ok,
2202 bool nested, bool start_attr_ok,
2203 tree *objc_foreach_object_declaration
2204 /* = NULL */,
2205 vec<c_token> *omp_declare_simd_clauses
2206 /* = NULL */,
2207 bool have_attrs /* = false */,
2208 tree attrs /* = NULL_TREE */,
2209 struct oacc_routine_data *oacc_routine_data
2210 /* = NULL */,
2211 bool *fallthru_attr_p /* = NULL */)
2212{
2213 struct c_declspecs *specs;
2214 tree prefix_attrs;
2215 tree all_prefix_attrs;
2216 bool diagnosed_no_specs = false;
2217 location_t here = c_parser_peek_token (parser)->location;
2218
2219 add_debug_begin_stmt (loc: c_parser_peek_token (parser)->location);
2220
2221 if (static_assert_ok
2222 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
2223 {
2224 c_parser_static_assert_declaration (parser);
2225 return;
2226 }
2227 specs = build_null_declspecs ();
2228
2229 /* Handle any standard attributes parsed in the caller. */
2230 if (have_attrs)
2231 {
2232 declspecs_add_attrs (here, specs, attrs);
2233 specs->non_std_attrs_seen_p = false;
2234 }
2235
2236 /* Try to detect an unknown type name when we have "A B" or "A *B". */
2237 if (c_parser_peek_token (parser)->type == CPP_NAME
2238 && c_parser_peek_token (parser)->id_kind == C_ID_ID
2239 && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2240 || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2241 && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2242 {
2243 tree name = c_parser_peek_token (parser)->value;
2244
2245 /* Issue a warning about NAME being an unknown type name, perhaps
2246 with some kind of hint.
2247 If the user forgot a "struct" etc, suggest inserting
2248 it. Otherwise, attempt to look for misspellings. */
2249 gcc_rich_location richloc (here);
2250 if (tag_exists_p (RECORD_TYPE, name))
2251 {
2252 /* This is not C++ with its implicit typedef. */
2253 richloc.add_fixit_insert_before (new_content: "struct ");
2254 error_at (&richloc,
2255 "unknown type name %qE;"
2256 " use %<struct%> keyword to refer to the type",
2257 name);
2258 }
2259 else if (tag_exists_p (UNION_TYPE, name))
2260 {
2261 richloc.add_fixit_insert_before (new_content: "union ");
2262 error_at (&richloc,
2263 "unknown type name %qE;"
2264 " use %<union%> keyword to refer to the type",
2265 name);
2266 }
2267 else if (tag_exists_p (ENUMERAL_TYPE, name))
2268 {
2269 richloc.add_fixit_insert_before (new_content: "enum ");
2270 error_at (&richloc,
2271 "unknown type name %qE;"
2272 " use %<enum%> keyword to refer to the type",
2273 name);
2274 }
2275 else
2276 {
2277 auto_diagnostic_group d;
2278 name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2279 here);
2280 if (const char *suggestion = hint.suggestion ())
2281 {
2282 richloc.add_fixit_replace (new_content: suggestion);
2283 error_at (&richloc,
2284 "unknown type name %qE; did you mean %qs?",
2285 name, suggestion);
2286 }
2287 else
2288 error_at (here, "unknown type name %qE", name);
2289 }
2290
2291 /* Parse declspecs normally to get a correct pointer type, but avoid
2292 a further "fails to be a type name" error. Refuse nested functions
2293 since it is not how the user likely wants us to recover. */
2294 c_parser_peek_token (parser)->type = CPP_KEYWORD;
2295 c_parser_peek_token (parser)->keyword = RID_VOID;
2296 c_parser_peek_token (parser)->value = error_mark_node;
2297 fndef_ok = !nested;
2298 }
2299
2300 /* When there are standard attributes at the start of the
2301 declaration (to apply to the entity being declared), an
2302 init-declarator-list or function definition must be present. */
2303 if (c_parser_nth_token_starts_std_attributes (parser, 1))
2304 have_attrs = true;
2305
2306 c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2307 true, true, start_attr_ok, true, cla_nonabstract_decl);
2308 if (parser->error)
2309 {
2310 c_parser_skip_to_end_of_block_or_statement (parser);
2311 return;
2312 }
2313 if (nested && !specs->declspecs_seen_p)
2314 {
2315 c_parser_error (parser, gmsgid: "expected declaration specifiers");
2316 c_parser_skip_to_end_of_block_or_statement (parser);
2317 return;
2318 }
2319
2320 finish_declspecs (specs);
2321 bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2322 bool std_auto_type_p = specs->c23_auto_p;
2323 bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2324 gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2325 const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2326 if (specs->constexpr_p)
2327 {
2328 /* An underspecified declaration may not declare tags or members
2329 or structures or unions; it is undefined behavior to declare
2330 the members of an enumeration. Where the structure, union or
2331 enumeration type is declared within an initializer, this is
2332 diagnosed elsewhere. Diagnose here the case of declaring
2333 such a type in the type specifiers of a constexpr
2334 declaration. */
2335 switch (specs->typespec_kind)
2336 {
2337 case ctsk_tagfirstref:
2338 case ctsk_tagfirstref_attrs:
2339 error_at (here, "%qT declared in underspecified object declaration",
2340 specs->type);
2341 break;
2342
2343 case ctsk_tagdef:
2344 error_at (here, "%qT defined in underspecified object declaration",
2345 specs->type);
2346 break;
2347
2348 default:
2349 break;
2350 }
2351 }
2352 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
2353 {
2354 bool handled_assume = false;
2355 if (specs->attrs
2356 && !nested
2357 && specs->typespec_kind == ctsk_none
2358 && c_parser_handle_statement_omp_attributes (parser, specs->attrs,
2359 NULL))
2360 {
2361 if (specs->attrs)
2362 c_warn_unused_attributes (specs->attrs);
2363 while (parser->in_omp_attribute_pragma)
2364 {
2365 gcc_assert (c_parser_next_token_is (parser, CPP_PRAGMA));
2366 c_parser_pragma (parser, pragma_external, NULL);
2367 }
2368 c_parser_consume_token (parser);
2369 return;
2370 }
2371 if (specs->typespec_kind == ctsk_none
2372 && lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2373 {
2374 handled_assume = true;
2375 specs->attrs
2376 = handle_assume_attribute (here, attrs: specs->attrs, nested);
2377 }
2378 if (any_auto_type_p)
2379 error_at (here, "%qs in empty declaration", auto_type_keyword);
2380 else if (specs->typespec_kind == ctsk_none
2381 && attribute_fallthrough_p (specs->attrs))
2382 {
2383 if (fallthru_attr_p != NULL)
2384 *fallthru_attr_p = true;
2385 if (nested)
2386 {
2387 tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2388 void_type_node, 0);
2389 add_stmt (fn);
2390 }
2391 else
2392 pedwarn (here, OPT_Wattributes,
2393 "%<fallthrough%> attribute at top level");
2394 }
2395 else if (empty_ok
2396 && !(have_attrs && specs->non_std_attrs_seen_p)
2397 && !handled_assume)
2398 shadow_tag (specs);
2399 else
2400 {
2401 shadow_tag_warned (specs, 1);
2402 if (!handled_assume)
2403 pedwarn (here, 0, "empty declaration");
2404 }
2405 /* We still have to evaluate size expressions. */
2406 if (specs->expr)
2407 add_stmt (fold_convert (void_type_node, specs->expr));
2408 c_parser_consume_token (parser);
2409 if (oacc_routine_data)
2410 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2411 return;
2412 }
2413
2414 /* Provide better error recovery. Note that a type name here is usually
2415 better diagnosed as a redeclaration. */
2416 if (empty_ok
2417 && specs->typespec_kind == ctsk_tagdef
2418 && c_parser_next_token_starts_declspecs (parser)
2419 && !c_parser_next_token_is (parser, type: CPP_NAME))
2420 {
2421 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
2422 parser->error = false;
2423 shadow_tag_warned (specs, 1);
2424 return;
2425 }
2426 else if (c_dialect_objc () && !any_auto_type_p)
2427 {
2428 /* Prefix attributes are an error on method decls. */
2429 switch (c_parser_peek_token (parser)->type)
2430 {
2431 case CPP_PLUS:
2432 case CPP_MINUS:
2433 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2434 return;
2435 if (specs->attrs)
2436 {
2437 warning_at (c_parser_peek_token (parser)->location,
2438 OPT_Wattributes,
2439 "prefix attributes are ignored for methods");
2440 specs->attrs = NULL_TREE;
2441 }
2442 if (fndef_ok)
2443 c_parser_objc_method_definition (parser);
2444 else
2445 c_parser_objc_methodproto (parser);
2446 return;
2447 break;
2448 default:
2449 break;
2450 }
2451 /* This is where we parse 'attributes @interface ...',
2452 'attributes @implementation ...', 'attributes @protocol ...'
2453 (where attributes could be, for example, __attribute__
2454 ((deprecated)).
2455 */
2456 switch (c_parser_peek_token (parser)->keyword)
2457 {
2458 case RID_AT_INTERFACE:
2459 {
2460 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2461 return;
2462 c_parser_objc_class_definition (parser, specs->attrs);
2463 return;
2464 }
2465 break;
2466 case RID_AT_IMPLEMENTATION:
2467 {
2468 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2469 return;
2470 if (specs->attrs)
2471 {
2472 warning_at (c_parser_peek_token (parser)->location,
2473 OPT_Wattributes,
2474 "prefix attributes are ignored for implementations");
2475 specs->attrs = NULL_TREE;
2476 }
2477 c_parser_objc_class_definition (parser, NULL_TREE);
2478 return;
2479 }
2480 break;
2481 case RID_AT_PROTOCOL:
2482 {
2483 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2484 return;
2485 c_parser_objc_protocol_definition (parser, specs->attrs);
2486 return;
2487 }
2488 break;
2489 case RID_AT_ALIAS:
2490 case RID_AT_CLASS:
2491 case RID_AT_END:
2492 case RID_AT_PROPERTY:
2493 if (specs->attrs)
2494 {
2495 c_parser_error (parser, gmsgid: "unexpected attribute");
2496 specs->attrs = NULL;
2497 }
2498 break;
2499 default:
2500 break;
2501 }
2502 }
2503 else if (attribute_fallthrough_p (specs->attrs))
2504 warning_at (here, OPT_Wattributes,
2505 "%<fallthrough%> attribute not followed by %<;%>");
2506 else if (lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2507 warning_at (here, OPT_Wattributes,
2508 "%<assume%> attribute not followed by %<;%>");
2509
2510 auto_vec<c_token> omp_declare_simd_attr_clauses;
2511 c_parser_handle_directive_omp_attributes (specs->attrs,
2512 omp_declare_simd_clauses,
2513 &omp_declare_simd_attr_clauses);
2514 pending_xref_error ();
2515 prefix_attrs = specs->attrs;
2516 all_prefix_attrs = prefix_attrs;
2517 specs->attrs = NULL_TREE;
2518 while (true)
2519 {
2520 struct c_declarator *declarator;
2521 bool dummy = false;
2522 timevar_id_t tv;
2523 tree fnbody = NULL_TREE;
2524 tree underspec_name = NULL_TREE;
2525 auto_vec<c_token> omp_dsimd_idattr_clauses;
2526 /* Declaring either one or more declarators (in which case we
2527 should diagnose if there were no declaration specifiers) or a
2528 function definition (in which case the diagnostic for
2529 implicit int suffices). */
2530 declarator = c_parser_declarator (parser,
2531 type_seen_p: specs->typespec_kind != ctsk_none,
2532 kind: C_DTR_NORMAL, seen_id: &dummy);
2533 if (declarator == NULL)
2534 {
2535 if (omp_declare_simd_clauses)
2536 c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2537 omp_declare_simd_clauses);
2538 if (oacc_routine_data)
2539 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2540 c_parser_skip_to_end_of_block_or_statement (parser);
2541 return;
2542 }
2543 if (flag_openmp || flag_openmp_simd)
2544 {
2545 struct c_declarator *d = declarator;
2546 while (d->kind != cdk_id)
2547 d = d->declarator;
2548 vec<c_token> *dummy = NULL;
2549 c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2550 &omp_dsimd_idattr_clauses);
2551 }
2552 if (gnu_auto_type_p && declarator->kind != cdk_id)
2553 {
2554 error_at (here,
2555 "%<__auto_type%> requires a plain identifier"
2556 " as declarator");
2557 c_parser_skip_to_end_of_block_or_statement (parser);
2558 return;
2559 }
2560 if (std_auto_type_p)
2561 {
2562 struct c_declarator *d = declarator;
2563 while (d->kind == cdk_attrs)
2564 d = d->declarator;
2565 if (d->kind != cdk_id)
2566 {
2567 error_at (here,
2568 "%<auto%> requires a plain identifier, possibly with"
2569 " attributes, as declarator");
2570 c_parser_skip_to_end_of_block_or_statement (parser);
2571 return;
2572 }
2573 underspec_name = d->u.id.id;
2574 }
2575 else if (specs->constexpr_p)
2576 {
2577 struct c_declarator *d = declarator;
2578 while (d->kind != cdk_id)
2579 d = d->declarator;
2580 underspec_name = d->u.id.id;
2581 }
2582 if (c_parser_next_token_is (parser, type: CPP_EQ)
2583 || c_parser_next_token_is (parser, type: CPP_COMMA)
2584 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
2585 || c_parser_next_token_is_keyword (parser, keyword: RID_ASM)
2586 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE)
2587 || c_parser_next_token_is_keyword (parser, keyword: RID_IN))
2588 {
2589 tree asm_name = NULL_TREE;
2590 tree postfix_attrs = NULL_TREE;
2591 if (!diagnosed_no_specs && !specs->declspecs_seen_p)
2592 {
2593 diagnosed_no_specs = true;
2594 pedwarn (here, 0, "data definition has no type or storage class");
2595 }
2596 /* Having seen a data definition, there cannot now be a
2597 function definition. */
2598 fndef_ok = false;
2599 if (c_parser_next_token_is_keyword (parser, keyword: RID_ASM))
2600 asm_name = c_parser_simple_asm_expr (parser);
2601 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
2602 {
2603 postfix_attrs = c_parser_gnu_attributes (parser);
2604 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
2605 {
2606 /* This means there is an attribute specifier after
2607 the declarator in a function definition. Provide
2608 some more information for the user. */
2609 error_at (here, "attributes should be specified before the "
2610 "declarator in a function definition");
2611 c_parser_skip_to_end_of_block_or_statement (parser);
2612 return;
2613 }
2614 }
2615 if (c_parser_next_token_is (parser, type: CPP_EQ))
2616 {
2617 tree d;
2618 struct c_expr init;
2619 location_t init_loc;
2620 c_parser_consume_token (parser);
2621 if (any_auto_type_p)
2622 {
2623 init_loc = c_parser_peek_token (parser)->location;
2624 rich_location richloc (line_table, init_loc);
2625 unsigned int underspec_state = 0;
2626 if (std_auto_type_p)
2627 underspec_state =
2628 start_underspecified_init (init_loc, underspec_name);
2629 start_init (NULL_TREE, asm_name,
2630 (global_bindings_p ()
2631 || specs->storage_class == csc_static
2632 || specs->constexpr_p),
2633 specs->constexpr_p, &richloc);
2634 /* A parameter is initialized, which is invalid. Don't
2635 attempt to instrument the initializer. */
2636 int flag_sanitize_save = flag_sanitize;
2637 if (nested && !empty_ok)
2638 flag_sanitize = 0;
2639 init = c_parser_expr_no_commas (parser, NULL);
2640 if (std_auto_type_p)
2641 finish_underspecified_init (underspec_name,
2642 underspec_state);
2643 flag_sanitize = flag_sanitize_save;
2644 if (gnu_auto_type_p
2645 && TREE_CODE (init.value) == COMPONENT_REF
2646 && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
2647 error_at (here,
2648 "%<__auto_type%> used with a bit-field"
2649 " initializer");
2650 init = convert_lvalue_to_rvalue (init_loc, init, true, true,
2651 true);
2652 tree init_type = TREE_TYPE (init.value);
2653 bool vm_type = c_type_variably_modified_p (t: init_type);
2654 if (vm_type)
2655 init.value = save_expr (init.value);
2656 finish_init ();
2657 specs->typespec_kind = ctsk_typeof;
2658 specs->locations[cdw_typedef] = init_loc;
2659 specs->typedef_p = true;
2660 specs->type = init_type;
2661 if (specs->postfix_attrs)
2662 {
2663 /* Postfix [[]] attributes are valid with C23
2664 auto, although not with __auto_type, and
2665 modify the type given by the initializer. */
2666 specs->postfix_attrs =
2667 c_warn_type_attributes (specs->postfix_attrs);
2668 decl_attributes (&specs->type, specs->postfix_attrs, 0);
2669 specs->postfix_attrs = NULL_TREE;
2670 }
2671 if (vm_type)
2672 {
2673 bool maybe_const = true;
2674 tree type_expr = c_fully_fold (init.value, false,
2675 &maybe_const);
2676 specs->expr_const_operands &= maybe_const;
2677 if (specs->expr)
2678 specs->expr = build2 (COMPOUND_EXPR,
2679 TREE_TYPE (type_expr),
2680 specs->expr, type_expr);
2681 else
2682 specs->expr = type_expr;
2683 }
2684 d = start_decl (declarator, specs, true,
2685 chainon (postfix_attrs, all_prefix_attrs));
2686 if (!d)
2687 d = error_mark_node;
2688 if (omp_declare_simd_clauses)
2689 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2690 omp_declare_simd_clauses);
2691 if (!omp_dsimd_idattr_clauses.is_empty ())
2692 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2693 &omp_dsimd_idattr_clauses);
2694 }
2695 else
2696 {
2697 /* The declaration of the variable is in effect while
2698 its initializer is parsed, except for a constexpr
2699 variable. */
2700 init_loc = c_parser_peek_token (parser)->location;
2701 rich_location richloc (line_table, init_loc);
2702 unsigned int underspec_state = 0;
2703 if (specs->constexpr_p)
2704 underspec_state =
2705 start_underspecified_init (init_loc, underspec_name);
2706 d = start_decl (declarator, specs, true,
2707 chainon (postfix_attrs,
2708 all_prefix_attrs),
2709 !specs->constexpr_p);
2710 if (!d)
2711 d = error_mark_node;
2712 if (!specs->constexpr_p && omp_declare_simd_clauses)
2713 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2714 omp_declare_simd_clauses);
2715 if (!specs->constexpr_p
2716 && !omp_dsimd_idattr_clauses.is_empty ())
2717 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2718 &omp_dsimd_idattr_clauses);
2719 start_init (d, asm_name,
2720 TREE_STATIC (d) || specs->constexpr_p,
2721 specs->constexpr_p, &richloc);
2722 /* A parameter is initialized, which is invalid. Don't
2723 attempt to instrument the initializer. */
2724 int flag_sanitize_save = flag_sanitize;
2725 if (TREE_CODE (d) == PARM_DECL)
2726 flag_sanitize = 0;
2727 init = c_parser_initializer (parser, d);
2728 flag_sanitize = flag_sanitize_save;
2729 if (specs->constexpr_p)
2730 {
2731 finish_underspecified_init (underspec_name,
2732 underspec_state);
2733 d = pushdecl (d);
2734 if (omp_declare_simd_clauses)
2735 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2736 omp_declare_simd_clauses);
2737 if (!specs->constexpr_p
2738 && !omp_dsimd_idattr_clauses.is_empty ())
2739 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2740 &omp_dsimd_idattr_clauses);
2741 }
2742 finish_init ();
2743 }
2744 if (oacc_routine_data)
2745 c_finish_oacc_routine (oacc_routine_data, d, false);
2746 if (d != error_mark_node)
2747 {
2748 maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
2749 finish_decl (d, init_loc, init.value,
2750 init.original_type, asm_name);
2751 }
2752 }
2753 else
2754 {
2755 if (any_auto_type_p || specs->constexpr_p)
2756 {
2757 error_at (here,
2758 "%qs requires an initialized data declaration",
2759 any_auto_type_p ? auto_type_keyword : "constexpr");
2760 c_parser_skip_to_end_of_block_or_statement (parser);
2761 return;
2762 }
2763
2764 location_t lastloc = UNKNOWN_LOCATION;
2765 tree attrs = chainon (postfix_attrs, all_prefix_attrs);
2766 tree d = start_decl (declarator, specs, false, attrs, true,
2767 &lastloc);
2768 if (d && TREE_CODE (d) == FUNCTION_DECL)
2769 {
2770 /* Find the innermost declarator that is neither cdk_id
2771 nor cdk_attrs. */
2772 const struct c_declarator *decl = declarator;
2773 const struct c_declarator *last_non_id_attrs = NULL;
2774
2775 while (decl)
2776 switch (decl->kind)
2777 {
2778 case cdk_array:
2779 case cdk_function:
2780 case cdk_pointer:
2781 last_non_id_attrs = decl;
2782 decl = decl->declarator;
2783 break;
2784
2785 case cdk_attrs:
2786 decl = decl->declarator;
2787 break;
2788
2789 case cdk_id:
2790 decl = 0;
2791 break;
2792
2793 default:
2794 gcc_unreachable ();
2795 }
2796
2797 /* If it exists and is cdk_function declaration whose
2798 arguments have not been set yet, use its arguments. */
2799 if (last_non_id_attrs
2800 && last_non_id_attrs->kind == cdk_function)
2801 {
2802 tree parms = last_non_id_attrs->u.arg_info->parms;
2803 if (DECL_ARGUMENTS (d) == NULL_TREE
2804 && DECL_INITIAL (d) == NULL_TREE)
2805 DECL_ARGUMENTS (d) = parms;
2806
2807 warn_parm_array_mismatch (lastloc, d, parms);
2808 }
2809 }
2810 if (omp_declare_simd_clauses
2811 || !omp_dsimd_idattr_clauses.is_empty ())
2812 {
2813 tree parms = NULL_TREE;
2814 if (d && TREE_CODE (d) == FUNCTION_DECL)
2815 {
2816 struct c_declarator *ce = declarator;
2817 while (ce != NULL)
2818 if (ce->kind == cdk_function)
2819 {
2820 parms = ce->u.arg_info->parms;
2821 break;
2822 }
2823 else
2824 ce = ce->declarator;
2825 }
2826 if (parms)
2827 temp_store_parm_decls (d, parms);
2828 if (omp_declare_simd_clauses)
2829 c_finish_omp_declare_simd (parser, d, parms,
2830 omp_declare_simd_clauses);
2831 if (!specs->constexpr_p
2832 && !omp_dsimd_idattr_clauses.is_empty ())
2833 c_finish_omp_declare_simd (parser, d, parms,
2834 &omp_dsimd_idattr_clauses);
2835 if (parms)
2836 temp_pop_parm_decls ();
2837 }
2838 if (oacc_routine_data)
2839 c_finish_oacc_routine (oacc_routine_data, d, false);
2840 if (d)
2841 finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
2842 NULL_TREE, asm_name);
2843
2844 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
2845 {
2846 if (d)
2847 *objc_foreach_object_declaration = d;
2848 else
2849 *objc_foreach_object_declaration = error_mark_node;
2850 }
2851 }
2852 if (c_parser_next_token_is (parser, type: CPP_COMMA))
2853 {
2854 if (any_auto_type_p || specs->constexpr_p)
2855 {
2856 error_at (here,
2857 "%qs may only be used with a single declarator",
2858 any_auto_type_p ? auto_type_keyword : "constexpr");
2859 c_parser_skip_to_end_of_block_or_statement (parser);
2860 return;
2861 }
2862 c_parser_consume_token (parser);
2863 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
2864 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
2865 prefix_attrs);
2866 else
2867 all_prefix_attrs = prefix_attrs;
2868 continue;
2869 }
2870 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
2871 {
2872 c_parser_consume_token (parser);
2873 return;
2874 }
2875 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
2876 {
2877 /* This can only happen in Objective-C: we found the
2878 'in' that terminates the declaration inside an
2879 Objective-C foreach statement. Do not consume the
2880 token, so that the caller can use it to determine
2881 that this indeed is a foreach context. */
2882 return;
2883 }
2884 else
2885 {
2886 c_parser_error (parser, gmsgid: "expected %<,%> or %<;%>");
2887 c_parser_skip_to_end_of_block_or_statement (parser);
2888 return;
2889 }
2890 }
2891 else if (any_auto_type_p || specs->constexpr_p)
2892 {
2893 error_at (here,
2894 "%qs requires an initialized data declaration",
2895 any_auto_type_p ? auto_type_keyword : "constexpr");
2896 c_parser_skip_to_end_of_block_or_statement (parser);
2897 return;
2898 }
2899 else if (!fndef_ok)
2900 {
2901 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, "
2902 "%<asm%> or %<__attribute__%>");
2903 c_parser_skip_to_end_of_block_or_statement (parser);
2904 return;
2905 }
2906 /* Function definition (nested or otherwise). */
2907 if (nested)
2908 {
2909 pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
2910 c_push_function_context ();
2911 }
2912 if (!start_function (specs, declarator, all_prefix_attrs))
2913 {
2914 /* At this point we've consumed:
2915 declaration-specifiers declarator
2916 and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
2917 RID_ASM, RID_ATTRIBUTE, or RID_IN,
2918 but the
2919 declaration-specifiers declarator
2920 aren't grokkable as a function definition, so we have
2921 an error. */
2922 gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
2923 if (c_parser_next_token_starts_declspecs (parser))
2924 {
2925 /* If we have
2926 declaration-specifiers declarator decl-specs
2927 then assume we have a missing semicolon, which would
2928 give us:
2929 declaration-specifiers declarator decl-specs
2930 ^
2931 ;
2932 <~~~~~~~~~ declaration ~~~~~~~~~~>
2933 Use c_parser_require to get an error with a fix-it hint. */
2934 c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
2935 parser->error = false;
2936 }
2937 else
2938 {
2939 /* This can appear in many cases looking nothing like a
2940 function definition, so we don't give a more specific
2941 error suggesting there was one. */
2942 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, %<asm%> "
2943 "or %<__attribute__%>");
2944 }
2945 if (nested)
2946 c_pop_function_context ();
2947 break;
2948 }
2949
2950 if (DECL_DECLARED_INLINE_P (current_function_decl))
2951 tv = TV_PARSE_INLINE;
2952 else
2953 tv = TV_PARSE_FUNC;
2954 auto_timevar at (g_timer, tv);
2955
2956 /* Parse old-style parameter declarations. ??? Attributes are
2957 not allowed to start declaration specifiers here because of a
2958 syntax conflict between a function declaration with attribute
2959 suffix and a function definition with an attribute prefix on
2960 first old-style parameter declaration. Following the old
2961 parser, they are not accepted on subsequent old-style
2962 parameter declarations either. However, there is no
2963 ambiguity after the first declaration, nor indeed on the
2964 first as long as we don't allow postfix attributes after a
2965 declarator with a nonempty identifier list in a definition;
2966 and postfix attributes have never been accepted here in
2967 function definitions either. */
2968 int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
2969 debug_nonbind_markers_p = 0;
2970 while (c_parser_next_token_is_not (parser, type: CPP_EOF)
2971 && c_parser_next_token_is_not (parser, type: CPP_OPEN_BRACE))
2972 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: false,
2973 nested: true, start_attr_ok: false);
2974 debug_nonbind_markers_p = save_debug_nonbind_markers_p;
2975 store_parm_decls ();
2976 if (omp_declare_simd_clauses)
2977 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
2978 omp_declare_simd_clauses);
2979 if (!omp_dsimd_idattr_clauses.is_empty ())
2980 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
2981 &omp_dsimd_idattr_clauses);
2982 if (oacc_routine_data)
2983 c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
2984 location_t startloc = c_parser_peek_token (parser)->location;
2985 DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
2986 = startloc;
2987 location_t endloc = startloc;
2988
2989 /* If the definition was marked with __RTL, use the RTL parser now,
2990 consuming the function body. */
2991 if (specs->declspec_il == cdil_rtl)
2992 {
2993 endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
2994
2995 /* Normally, store_parm_decls sets next_is_function_body,
2996 anticipating a function body. We need a push_scope/pop_scope
2997 pair to flush out this state, or subsequent function parsing
2998 will go wrong. */
2999 push_scope ();
3000 pop_scope ();
3001
3002 finish_function (endloc);
3003 return;
3004 }
3005 /* If the definition was marked with __GIMPLE then parse the
3006 function body as GIMPLE. */
3007 else if (specs->declspec_il != cdil_none)
3008 {
3009 bool saved = in_late_binary_op;
3010 in_late_binary_op = true;
3011 c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3012 specs->declspec_il,
3013 specs->entry_bb_count);
3014 in_late_binary_op = saved;
3015 }
3016 else
3017 fnbody = c_parser_compound_statement (parser, &endloc);
3018 tree fndecl = current_function_decl;
3019 if (nested)
3020 {
3021 tree decl = current_function_decl;
3022 /* Mark nested functions as needing static-chain initially.
3023 lower_nested_functions will recompute it but the
3024 DECL_STATIC_CHAIN flag is also used before that happens,
3025 by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
3026 DECL_STATIC_CHAIN (decl) = 1;
3027 add_stmt (fnbody);
3028 finish_function (endloc);
3029 c_pop_function_context ();
3030 add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
3031 }
3032 else
3033 {
3034 if (fnbody)
3035 add_stmt (fnbody);
3036 finish_function (endloc);
3037 }
3038 /* Get rid of the empty stmt list for GIMPLE/RTL. */
3039 if (specs->declspec_il != cdil_none)
3040 DECL_SAVED_TREE (fndecl) = NULL_TREE;
3041
3042 break;
3043 }
3044}
3045
3046/* Parse an asm-definition (asm() outside a function body). This is a
3047 GNU extension.
3048
3049 asm-definition:
3050 simple-asm-expr ;
3051*/
3052
3053static void
3054c_parser_asm_definition (c_parser *parser)
3055{
3056 tree asm_str = c_parser_simple_asm_expr (parser);
3057 if (asm_str)
3058 symtab->finalize_toplevel_asm (asm_str);
3059 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
3060}
3061
3062/* Parse a static assertion (C11 6.7.10).
3063
3064 static_assert-declaration:
3065 static_assert-declaration-no-semi ;
3066*/
3067
3068static void
3069c_parser_static_assert_declaration (c_parser *parser)
3070{
3071 c_parser_static_assert_declaration_no_semi (parser);
3072 if (parser->error
3073 || !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
3074 c_parser_skip_to_end_of_block_or_statement (parser);
3075}
3076
3077/* Parse a static assertion (C11 6.7.10), without the trailing
3078 semicolon.
3079
3080 static_assert-declaration-no-semi:
3081 _Static_assert ( constant-expression , string-literal )
3082
3083 C23:
3084 static_assert-declaration-no-semi:
3085 _Static_assert ( constant-expression )
3086*/
3087
3088static void
3089c_parser_static_assert_declaration_no_semi (c_parser *parser)
3090{
3091 location_t assert_loc, value_loc;
3092 tree value;
3093 tree string = NULL_TREE;
3094
3095 gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3096 tree spelling = c_parser_peek_token (parser)->value;
3097 assert_loc = c_parser_peek_token (parser)->location;
3098 if (flag_isoc99)
3099 pedwarn_c99 (assert_loc, opt: OPT_Wpedantic,
3100 "ISO C99 does not support %qE", spelling);
3101 else
3102 pedwarn_c99 (assert_loc, opt: OPT_Wpedantic,
3103 "ISO C90 does not support %qE", spelling);
3104 c_parser_consume_token (parser);
3105 matching_parens parens;
3106 if (!parens.require_open (parser))
3107 return;
3108 location_t value_tok_loc = c_parser_peek_token (parser)->location;
3109 value = convert_lvalue_to_rvalue (value_tok_loc,
3110 c_parser_expr_no_commas (parser, NULL),
3111 true, true).value;
3112 value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3113 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3114 {
3115 c_parser_consume_token (parser);
3116 switch (c_parser_peek_token (parser)->type)
3117 {
3118 case CPP_STRING:
3119 case CPP_STRING16:
3120 case CPP_STRING32:
3121 case CPP_WSTRING:
3122 case CPP_UTF8STRING:
3123 string = c_parser_string_literal (parser, false, true).value;
3124 break;
3125 default:
3126 c_parser_error (parser, gmsgid: "expected string literal");
3127 return;
3128 }
3129 }
3130 else if (flag_isoc11)
3131 /* If pedantic for pre-C11, the use of _Static_assert itself will
3132 have been diagnosed, so do not also diagnose the use of this
3133 new C23 feature of _Static_assert. */
3134 pedwarn_c11 (assert_loc, opt: OPT_Wpedantic,
3135 "ISO C11 does not support omitting the string in "
3136 "%qE", spelling);
3137 parens.require_close (parser);
3138
3139 if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
3140 {
3141 error_at (value_loc, "expression in static assertion is not an integer");
3142 return;
3143 }
3144 if (TREE_CODE (value) != INTEGER_CST)
3145 {
3146 value = c_fully_fold (value, false, NULL);
3147 /* Strip no-op conversions. */
3148 STRIP_TYPE_NOPS (value);
3149 if (TREE_CODE (value) == INTEGER_CST)
3150 pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
3151 "is not an integer constant expression");
3152 }
3153 if (TREE_CODE (value) != INTEGER_CST)
3154 {
3155 error_at (value_loc, "expression in static assertion is not constant");
3156 return;
3157 }
3158 constant_expression_warning (value);
3159 if (integer_zerop (value))
3160 {
3161 if (string)
3162 error_at (assert_loc, "static assertion failed: %E", string);
3163 else
3164 error_at (assert_loc, "static assertion failed");
3165 }
3166}
3167
3168/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
3169 6.7, C11 6.7), adding them to SPECS (which may already include some).
3170 Storage class specifiers are accepted iff SCSPEC_OK; type
3171 specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
3172 accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
3173 iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
3174 addition to the syntax shown, standard attributes are accepted at
3175 the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
3176 unlike gnu-attributes, they are not accepted in the middle of the
3177 list. (This combines various different syntax productions in the C
3178 standard, and in some cases gnu-attributes and standard attributes
3179 at the start may already have been parsed before this function is
3180 called.)
3181
3182 declaration-specifiers:
3183 storage-class-specifier declaration-specifiers[opt]
3184 type-specifier declaration-specifiers[opt]
3185 type-qualifier declaration-specifiers[opt]
3186 function-specifier declaration-specifiers[opt]
3187 alignment-specifier declaration-specifiers[opt]
3188
3189 Function specifiers (inline) are from C99, and are currently
3190 handled as storage class specifiers, as is __thread. Alignment
3191 specifiers are from C11.
3192
3193 C90 6.5.1, C99 6.7.1, C11 6.7.1:
3194 storage-class-specifier:
3195 typedef
3196 extern
3197 static
3198 auto
3199 register
3200 _Thread_local
3201
3202 (_Thread_local is new in C11.)
3203
3204 C99 6.7.4, C11 6.7.4:
3205 function-specifier:
3206 inline
3207 _Noreturn
3208
3209 (_Noreturn is new in C11.)
3210
3211 C90 6.5.2, C99 6.7.2, C11 6.7.2:
3212 type-specifier:
3213 void
3214 char
3215 short
3216 int
3217 long
3218 float
3219 double
3220 signed
3221 unsigned
3222 _Bool
3223 _Complex
3224 [_Imaginary removed in C99 TC2]
3225 _BitInt ( constant-expression )
3226 struct-or-union-specifier
3227 enum-specifier
3228 typedef-name
3229 atomic-type-specifier
3230
3231 (_Bool and _Complex are new in C99.)
3232 (atomic-type-specifier is new in C11.)
3233 (_BitInt is new in C23.)
3234
3235 C90 6.5.3, C99 6.7.3, C11 6.7.3:
3236
3237 type-qualifier:
3238 const
3239 restrict
3240 volatile
3241 address-space-qualifier
3242 _Atomic
3243
3244 (restrict is new in C99.)
3245 (_Atomic is new in C11.)
3246
3247 GNU extensions:
3248
3249 declaration-specifiers:
3250 gnu-attributes declaration-specifiers[opt]
3251
3252 type-qualifier:
3253 address-space
3254
3255 address-space:
3256 identifier recognized by the target
3257
3258 storage-class-specifier:
3259 __thread
3260
3261 type-specifier:
3262 typeof-specifier
3263 __auto_type
3264 __intN
3265 _Decimal32
3266 _Decimal64
3267 _Decimal128
3268 _Fract
3269 _Accum
3270 _Sat
3271
3272 (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
3273 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
3274
3275 atomic-type-specifier
3276 _Atomic ( type-name )
3277
3278 Objective-C:
3279
3280 type-specifier:
3281 class-name objc-protocol-refs[opt]
3282 typedef-name objc-protocol-refs
3283 objc-protocol-refs
3284*/
3285
3286void
3287c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
3288 bool scspec_ok, bool typespec_ok, bool start_attr_ok,
3289 bool alignspec_ok, bool auto_type_ok,
3290 bool start_std_attr_ok, bool end_std_attr_ok,
3291 enum c_lookahead_kind la)
3292{
3293 bool attrs_ok = start_attr_ok;
3294 bool seen_type = specs->typespec_kind != ctsk_none;
3295
3296 if (!typespec_ok)
3297 gcc_assert (la == cla_prefer_id);
3298
3299 if (start_std_attr_ok
3300 && c_parser_nth_token_starts_std_attributes (parser, 1))
3301 {
3302 gcc_assert (!specs->non_std_attrs_seen_p);
3303 location_t loc = c_parser_peek_token (parser)->location;
3304 tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3305 declspecs_add_attrs (loc, specs, attrs);
3306 specs->non_std_attrs_seen_p = false;
3307 }
3308
3309 while (c_parser_next_token_is (parser, type: CPP_NAME)
3310 || c_parser_next_token_is (parser, type: CPP_KEYWORD)
3311 || (c_dialect_objc () && c_parser_next_token_is (parser, type: CPP_LESS)))
3312 {
3313 struct c_typespec t;
3314 tree attrs;
3315 tree align;
3316 location_t loc = c_parser_peek_token (parser)->location;
3317
3318 /* If we cannot accept a type, exit if the next token must start
3319 one. Also, if we already have seen a tagged definition,
3320 a typename would be an error anyway and likely the user
3321 has simply forgotten a semicolon, so we exit. */
3322 if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3323 && c_parser_next_tokens_start_typename (parser, la)
3324 && !c_parser_next_token_is_qualifier (parser)
3325 && !c_parser_next_token_is_keyword (parser, keyword: RID_ALIGNAS))
3326 break;
3327
3328 if (c_parser_next_token_is (parser, type: CPP_NAME))
3329 {
3330 c_token *name_token = c_parser_peek_token (parser);
3331 tree value = name_token->value;
3332 c_id_kind kind = name_token->id_kind;
3333
3334 if (kind == C_ID_ADDRSPACE)
3335 {
3336 addr_space_t as
3337 = name_token->keyword - RID_FIRST_ADDR_SPACE;
3338 declspecs_add_addrspace (name_token->location, specs, as);
3339 c_parser_consume_token (parser);
3340 attrs_ok = true;
3341 continue;
3342 }
3343
3344 gcc_assert (!c_parser_next_token_is_qualifier (parser));
3345
3346 /* If we cannot accept a type, and the next token must start one,
3347 exit. Do the same if we already have seen a tagged definition,
3348 since it would be an error anyway and likely the user has simply
3349 forgotten a semicolon. */
3350 if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
3351 break;
3352
3353 /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
3354 a C_ID_CLASSNAME. */
3355 c_parser_consume_token (parser);
3356 seen_type = true;
3357 attrs_ok = true;
3358 if (kind == C_ID_ID)
3359 {
3360 auto_diagnostic_group d;
3361 name_hint hint = lookup_name_fuzzy (value, FUZZY_LOOKUP_TYPENAME,
3362 loc);
3363 if (const char *suggestion = hint.suggestion ())
3364 {
3365 gcc_rich_location richloc (loc);
3366 richloc.add_fixit_replace (new_content: suggestion);
3367 error_at (&richloc,
3368 "unknown type name %qE; did you mean %qs?",
3369 value, suggestion);
3370 }
3371 else
3372 error_at (loc, "unknown type name %qE", value);
3373 t.kind = ctsk_typedef;
3374 t.spec = error_mark_node;
3375 }
3376 else if (kind == C_ID_TYPENAME
3377 && (!c_dialect_objc ()
3378 || c_parser_next_token_is_not (parser, type: CPP_LESS)))
3379 {
3380 t.kind = ctsk_typedef;
3381 /* For a typedef name, record the meaning, not the name.
3382 In case of 'foo foo, bar;'. */
3383 t.spec = lookup_name (value);
3384 }
3385 else
3386 {
3387 tree proto = NULL_TREE;
3388 gcc_assert (c_dialect_objc ());
3389 t.kind = ctsk_objc;
3390 if (c_parser_next_token_is (parser, type: CPP_LESS))
3391 proto = c_parser_objc_protocol_refs (parser);
3392 t.spec = objc_get_protocol_qualified_type (value, proto);
3393 }
3394 t.expr = NULL_TREE;
3395 t.expr_const_operands = true;
3396 t.has_enum_type_specifier = false;
3397 declspecs_add_type (name_token->location, specs, t);
3398 continue;
3399 }
3400 if (c_parser_next_token_is (parser, type: CPP_LESS))
3401 {
3402 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
3403 nisse@lysator.liu.se. */
3404 tree proto;
3405 gcc_assert (c_dialect_objc ());
3406 if (!typespec_ok || seen_type)
3407 break;
3408 proto = c_parser_objc_protocol_refs (parser);
3409 t.kind = ctsk_objc;
3410 t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
3411 t.expr = NULL_TREE;
3412 t.expr_const_operands = true;
3413 t.has_enum_type_specifier = false;
3414 declspecs_add_type (loc, specs, t);
3415 continue;
3416 }
3417 gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3418 switch (c_parser_peek_token (parser)->keyword)
3419 {
3420 case RID_STATIC:
3421 case RID_EXTERN:
3422 case RID_REGISTER:
3423 case RID_TYPEDEF:
3424 case RID_INLINE:
3425 case RID_NORETURN:
3426 case RID_AUTO:
3427 case RID_THREAD:
3428 case RID_CONSTEXPR:
3429 if (!scspec_ok)
3430 goto out;
3431 attrs_ok = true;
3432 /* TODO: Distinguish between function specifiers (inline, noreturn)
3433 and storage class specifiers, either here or in
3434 declspecs_add_scspec. */
3435 declspecs_add_scspec (loc, specs,
3436 c_parser_peek_token (parser)->value);
3437 c_parser_consume_token (parser);
3438 break;
3439 case RID_AUTO_TYPE:
3440 if (!auto_type_ok)
3441 goto out;
3442 /* Fall through. */
3443 case RID_UNSIGNED:
3444 case RID_LONG:
3445 case RID_SHORT:
3446 case RID_SIGNED:
3447 case RID_COMPLEX:
3448 case RID_INT:
3449 case RID_CHAR:
3450 case RID_FLOAT:
3451 case RID_DOUBLE:
3452 case RID_VOID:
3453 case RID_DFLOAT32:
3454 case RID_DFLOAT64:
3455 case RID_DFLOAT128:
3456 CASE_RID_FLOATN_NX:
3457 case RID_BOOL:
3458 case RID_FRACT:
3459 case RID_ACCUM:
3460 case RID_SAT:
3461 case RID_INT_N_0:
3462 case RID_INT_N_1:
3463 case RID_INT_N_2:
3464 case RID_INT_N_3:
3465 if (!typespec_ok)
3466 goto out;
3467 attrs_ok = true;
3468 seen_type = true;
3469 if (c_dialect_objc ())
3470 parser->objc_need_raw_identifier = true;
3471 t.kind = ctsk_resword;
3472 t.spec = c_parser_peek_token (parser)->value;
3473 t.expr = NULL_TREE;
3474 t.expr_const_operands = true;
3475 t.has_enum_type_specifier = false;
3476 declspecs_add_type (loc, specs, t);
3477 c_parser_consume_token (parser);
3478 break;
3479 case RID_ENUM:
3480 if (!typespec_ok)
3481 goto out;
3482 attrs_ok = true;
3483 seen_type = true;
3484 t = c_parser_enum_specifier (parser);
3485 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3486 declspecs_add_type (loc, specs, t);
3487 break;
3488 case RID_STRUCT:
3489 case RID_UNION:
3490 if (!typespec_ok)
3491 goto out;
3492 attrs_ok = true;
3493 seen_type = true;
3494 t = c_parser_struct_or_union_specifier (parser);
3495 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3496 declspecs_add_type (loc, specs, t);
3497 break;
3498 case RID_TYPEOF:
3499 case RID_TYPEOF_UNQUAL:
3500 /* ??? The old parser rejected typeof after other type
3501 specifiers, but is a syntax error the best way of
3502 handling this? */
3503 if (!typespec_ok || seen_type)
3504 goto out;
3505 attrs_ok = true;
3506 seen_type = true;
3507 t = c_parser_typeof_specifier (parser);
3508 declspecs_add_type (loc, specs, t);
3509 break;
3510 case RID_BITINT:
3511 if (!typespec_ok)
3512 goto out;
3513 else
3514 {
3515 attrs_ok = true;
3516 seen_type = true;
3517 t.kind = ctsk_resword;
3518 t.spec = c_parser_peek_token (parser)->value;
3519 t.expr = error_mark_node;
3520 t.expr_const_operands = true;
3521 t.has_enum_type_specifier = false;
3522 c_parser_consume_token (parser);
3523 matching_parens parens;
3524 if (parens.require_open (parser))
3525 {
3526 c_expr expr = c_parser_expr_no_commas (parser, NULL);
3527 t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3528 true).value;
3529 parens.skip_until_found_close (parser);
3530 }
3531 declspecs_add_type (loc, specs, t);
3532 }
3533 break;
3534 case RID_ATOMIC:
3535 /* C parser handling of Objective-C constructs needs
3536 checking for correct lvalue-to-rvalue conversions, and
3537 the code in build_modify_expr handling various
3538 Objective-C cases, and that in build_unary_op handling
3539 Objective-C cases for increment / decrement, also needs
3540 updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
3541 and objc_types_are_equivalent may also need updates. */
3542 if (c_dialect_objc ())
3543 sorry ("%<_Atomic%> in Objective-C");
3544 if (flag_isoc99)
3545 pedwarn_c99 (loc, opt: OPT_Wpedantic,
3546 "ISO C99 does not support the %<_Atomic%> qualifier");
3547 else
3548 pedwarn_c99 (loc, opt: OPT_Wpedantic,
3549 "ISO C90 does not support the %<_Atomic%> qualifier");
3550 attrs_ok = true;
3551 tree value;
3552 value = c_parser_peek_token (parser)->value;
3553 c_parser_consume_token (parser);
3554 if (typespec_ok && c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
3555 {
3556 /* _Atomic ( type-name ). */
3557 seen_type = true;
3558 c_parser_consume_token (parser);
3559 struct c_type_name *type = c_parser_type_name (parser);
3560 t.kind = ctsk_typeof;
3561 t.spec = error_mark_node;
3562 t.expr = NULL_TREE;
3563 t.expr_const_operands = true;
3564 t.has_enum_type_specifier = false;
3565 if (type != NULL)
3566 t.spec = groktypename (type, &t.expr,
3567 &t.expr_const_operands);
3568 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
3569 msgid: "expected %<)%>");
3570 if (t.spec != error_mark_node)
3571 {
3572 if (TREE_CODE (t.spec) == ARRAY_TYPE)
3573 error_at (loc, "%<_Atomic%>-qualified array type");
3574 else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
3575 error_at (loc, "%<_Atomic%>-qualified function type");
3576 else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
3577 error_at (loc, "%<_Atomic%> applied to a qualified type");
3578 else
3579 t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
3580 }
3581 declspecs_add_type (loc, specs, t);
3582 }
3583 else
3584 declspecs_add_qual (loc, specs, value);
3585 break;
3586 case RID_CONST:
3587 case RID_VOLATILE:
3588 case RID_RESTRICT:
3589 attrs_ok = true;
3590 declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3591 c_parser_consume_token (parser);
3592 break;
3593 case RID_ATTRIBUTE:
3594 if (!attrs_ok)
3595 goto out;
3596 attrs = c_parser_gnu_attributes (parser);
3597 declspecs_add_attrs (loc, specs, attrs);
3598 break;
3599 case RID_ALIGNAS:
3600 if (!alignspec_ok)
3601 goto out;
3602 align = c_parser_alignas_specifier (parser);
3603 declspecs_add_alignas (loc, specs, align);
3604 break;
3605 case RID_GIMPLE:
3606 if (! flag_gimple)
3607 error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
3608 c_parser_consume_token (parser);
3609 specs->declspec_il = cdil_gimple;
3610 specs->locations[cdw_gimple] = loc;
3611 c_parser_gimple_or_rtl_pass_list (parser, specs);
3612 break;
3613 case RID_RTL:
3614 c_parser_consume_token (parser);
3615 specs->declspec_il = cdil_rtl;
3616 specs->locations[cdw_rtl] = loc;
3617 c_parser_gimple_or_rtl_pass_list (parser, specs);
3618 break;
3619 default:
3620 goto out;
3621 }
3622 }
3623 out:
3624 if (end_std_attr_ok
3625 && c_parser_nth_token_starts_std_attributes (parser, 1))
3626 specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
3627}
3628
3629/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
3630
3631 enum-specifier:
3632 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3633 { enumerator-list } gnu-attributes[opt]
3634 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3635 { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
3636 enum gnu-attributes[opt] identifier
3637
3638 The form with trailing comma is new in C99; enum-type-specifiers
3639 are new in C23. The forms with gnu-attributes are GNU extensions.
3640 In GNU C, we accept any expression without commas in the syntax
3641 (assignment expressions, not just conditional expressions);
3642 assignment expressions will be diagnosed as non-constant.
3643
3644 enum-type-specifier:
3645 : specifier-qualifier-list
3646
3647 enumerator-list:
3648 enumerator
3649 enumerator-list , enumerator
3650
3651 enumerator:
3652 enumeration-constant attribute-specifier-sequence[opt]
3653 enumeration-constant attribute-specifier-sequence[opt]
3654 = constant-expression
3655
3656 GNU Extensions:
3657
3658 enumerator:
3659 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3660 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3661 = constant-expression
3662
3663*/
3664
3665static struct c_typespec
3666c_parser_enum_specifier (c_parser *parser)
3667{
3668 struct c_typespec ret;
3669 bool have_std_attrs;
3670 bool potential_nesting_p = false;
3671 tree std_attrs = NULL_TREE;
3672 tree attrs;
3673 tree ident = NULL_TREE;
3674 tree fixed_underlying_type = NULL_TREE;
3675 location_t enum_loc;
3676 location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3677 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
3678 c_parser_consume_token (parser);
3679 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3680 if (have_std_attrs)
3681 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3682 attrs = c_parser_gnu_attributes (parser);
3683 enum_loc = c_parser_peek_token (parser)->location;
3684 /* Set the location in case we create a decl now. */
3685 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
3686 if (c_parser_next_token_is (parser, type: CPP_NAME))
3687 {
3688 ident = c_parser_peek_token (parser)->value;
3689 ident_loc = c_parser_peek_token (parser)->location;
3690 enum_loc = ident_loc;
3691 c_parser_consume_token (parser);
3692 }
3693 if (c_parser_next_token_is (parser, type: CPP_COLON)
3694 /* Distinguish an enum-type-specifier from a bit-field
3695 declaration of the form "enum e : constant-expression;". */
3696 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
3697 {
3698 pedwarn_c11 (enum_loc, opt: OPT_Wpedantic,
3699 "ISO C does not support specifying %<enum%> underlying "
3700 "types before C23");
3701 if (ident)
3702 {
3703 /* The tag is in scope during the enum-type-specifier (which
3704 may refer to the tag inside typeof). */
3705 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
3706 have_std_attrs, std_attrs, true);
3707 if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
3708 error_at (enum_loc, "%<enum%> declared both with and without "
3709 "fixed underlying type");
3710 potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
3711 }
3712 else
3713 {
3714 /* There must be an enum definition, so this initialization
3715 (to avoid possible warnings about uninitialized data)
3716 will be replaced later (either with the results of that
3717 definition, or with the results of error handling for the
3718 case of no tag and no definition). */
3719 ret.spec = NULL_TREE;
3720 ret.kind = ctsk_tagdef;
3721 ret.expr = NULL_TREE;
3722 ret.expr_const_operands = true;
3723 ret.has_enum_type_specifier = true;
3724 }
3725 c_parser_consume_token (parser);
3726 struct c_declspecs *specs = build_null_declspecs ();
3727 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: false, alignspec_ok: false, auto_type_ok: false,
3728 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_id);
3729 finish_declspecs (specs);
3730 if (specs->default_int_p)
3731 error_at (enum_loc, "no %<enum%> underlying type specified");
3732 else if (TREE_CODE (specs->type) != INTEGER_TYPE
3733 && TREE_CODE (specs->type) != BOOLEAN_TYPE)
3734 {
3735 error_at (enum_loc, "invalid %<enum%> underlying type");
3736 specs->type = integer_type_node;
3737 }
3738 else if (specs->restrict_p)
3739 error_at (enum_loc, "invalid use of %<restrict%>");
3740 fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
3741 if (ident)
3742 {
3743 /* The type specified must be consistent with any previously
3744 specified underlying type. If this is a newly declared
3745 type, it is now a complete type. */
3746 if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
3747 && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
3748 {
3749 TYPE_MIN_VALUE (ret.spec) =
3750 TYPE_MIN_VALUE (fixed_underlying_type);
3751 TYPE_MAX_VALUE (ret.spec) =
3752 TYPE_MAX_VALUE (fixed_underlying_type);
3753 TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
3754 SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
3755 TYPE_SIZE (ret.spec) = NULL_TREE;
3756 TYPE_PRECISION (ret.spec) =
3757 TYPE_PRECISION (fixed_underlying_type);
3758 ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
3759 layout_type (ret.spec);
3760 }
3761 else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
3762 && !comptypes (fixed_underlying_type,
3763 ENUM_UNDERLYING_TYPE (ret.spec)))
3764 {
3765 error_at (enum_loc, "%<enum%> underlying type incompatible with "
3766 "previous declaration");
3767 fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
3768 }
3769 }
3770 }
3771 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
3772 {
3773 /* Parse an enum definition. */
3774 struct c_enum_contents the_enum;
3775 tree type;
3776 tree postfix_attrs;
3777 /* We chain the enumerators in reverse order, then put them in
3778 forward order at the end. */
3779 tree values;
3780 timevar_push (tv: TV_PARSE_ENUM);
3781 type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
3782 potential_nesting_p);
3783 values = NULL_TREE;
3784 c_parser_consume_token (parser);
3785 while (true)
3786 {
3787 tree enum_id;
3788 tree enum_value;
3789 tree enum_decl;
3790 bool seen_comma;
3791 c_token *token;
3792 location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3793 location_t decl_loc, value_loc;
3794 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
3795 {
3796 /* Give a nicer error for "enum {}". */
3797 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
3798 && !parser->error)
3799 {
3800 error_at (c_parser_peek_token (parser)->location,
3801 "empty enum is invalid");
3802 parser->error = true;
3803 }
3804 else
3805 c_parser_error (parser, gmsgid: "expected identifier");
3806 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
3807 values = error_mark_node;
3808 break;
3809 }
3810 token = c_parser_peek_token (parser);
3811 enum_id = token->value;
3812 /* Set the location in case we create a decl now. */
3813 c_parser_set_source_position_from_token (token);
3814 decl_loc = value_loc = token->location;
3815 c_parser_consume_token (parser);
3816 /* Parse any specified attributes. */
3817 tree std_attrs = NULL_TREE;
3818 if (c_parser_nth_token_starts_std_attributes (parser, 1))
3819 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3820 tree enum_attrs = chainon (std_attrs,
3821 c_parser_gnu_attributes (parser));
3822 if (c_parser_next_token_is (parser, type: CPP_EQ))
3823 {
3824 c_parser_consume_token (parser);
3825 value_loc = c_parser_peek_token (parser)->location;
3826 enum_value = convert_lvalue_to_rvalue (value_loc,
3827 (c_parser_expr_no_commas
3828 (parser, NULL)),
3829 true, true).value;
3830 }
3831 else
3832 enum_value = NULL_TREE;
3833 enum_decl = build_enumerator (decl_loc, value_loc,
3834 &the_enum, enum_id, enum_value);
3835 if (enum_attrs)
3836 decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
3837 TREE_CHAIN (enum_decl) = values;
3838 values = enum_decl;
3839 seen_comma = false;
3840 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3841 {
3842 comma_loc = c_parser_peek_token (parser)->location;
3843 seen_comma = true;
3844 c_parser_consume_token (parser);
3845 }
3846 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
3847 {
3848 if (seen_comma)
3849 pedwarn_c90 (comma_loc, opt: OPT_Wpedantic,
3850 "comma at end of enumerator list");
3851 c_parser_consume_token (parser);
3852 break;
3853 }
3854 if (!seen_comma)
3855 {
3856 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
3857 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
3858 values = error_mark_node;
3859 break;
3860 }
3861 }
3862 postfix_attrs = c_parser_gnu_attributes (parser);
3863 ret.spec = finish_enum (type, nreverse (values),
3864 chainon (std_attrs,
3865 chainon (attrs, postfix_attrs)));
3866 ret.kind = ctsk_tagdef;
3867 ret.expr = NULL_TREE;
3868 ret.expr_const_operands = true;
3869 ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
3870 timevar_pop (tv: TV_PARSE_ENUM);
3871 return ret;
3872 }
3873 else if (!ident)
3874 {
3875 c_parser_error (parser, gmsgid: "expected %<{%>");
3876 ret.spec = error_mark_node;
3877 ret.kind = ctsk_tagref;
3878 ret.expr = NULL_TREE;
3879 ret.expr_const_operands = true;
3880 ret.has_enum_type_specifier = false;
3881 return ret;
3882 }
3883 /* Attributes may only appear when the members are defined or in
3884 certain forward declarations (treat enum forward declarations in
3885 GNU C analogously to struct and union forward declarations in
3886 standard C). */
3887 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
3888 c_parser_error (parser, gmsgid: "expected %<;%>");
3889 if (fixed_underlying_type == NULL_TREE)
3890 {
3891 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
3892 std_attrs, false);
3893 /* In ISO C, enumerated types without a fixed underlying type
3894 can be referred to only if already defined. */
3895 if (pedantic && !COMPLETE_TYPE_P (ret.spec))
3896 {
3897 gcc_assert (ident);
3898 pedwarn (enum_loc, OPT_Wpedantic,
3899 "ISO C forbids forward references to %<enum%> types");
3900 }
3901 }
3902 return ret;
3903}
3904
3905/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
3906
3907 struct-or-union-specifier:
3908 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
3909 identifier[opt] { struct-contents } gnu-attributes[opt]
3910 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
3911 identifier
3912
3913 struct-contents:
3914 struct-declaration-list
3915
3916 struct-declaration-list:
3917 struct-declaration ;
3918 struct-declaration-list struct-declaration ;
3919
3920 GNU extensions:
3921
3922 struct-contents:
3923 empty
3924 struct-declaration
3925 struct-declaration-list struct-declaration
3926
3927 struct-declaration-list:
3928 struct-declaration-list ;
3929 ;
3930
3931 (Note that in the syntax here, unlike that in ISO C, the semicolons
3932 are included here rather than in struct-declaration, in order to
3933 describe the syntax with extra semicolons and missing semicolon at
3934 end.)
3935
3936 Objective-C:
3937
3938 struct-declaration-list:
3939 @defs ( class-name )
3940
3941 (Note this does not include a trailing semicolon, but can be
3942 followed by further declarations, and gets a pedwarn-if-pedantic
3943 when followed by a semicolon.) */
3944
3945static struct c_typespec
3946c_parser_struct_or_union_specifier (c_parser *parser)
3947{
3948 struct c_typespec ret;
3949 bool have_std_attrs;
3950 tree std_attrs = NULL_TREE;
3951 tree attrs;
3952 tree ident = NULL_TREE;
3953 location_t struct_loc;
3954 location_t ident_loc = UNKNOWN_LOCATION;
3955 enum tree_code code;
3956 switch (c_parser_peek_token (parser)->keyword)
3957 {
3958 case RID_STRUCT:
3959 code = RECORD_TYPE;
3960 break;
3961 case RID_UNION:
3962 code = UNION_TYPE;
3963 break;
3964 default:
3965 gcc_unreachable ();
3966 }
3967 struct_loc = c_parser_peek_token (parser)->location;
3968 c_parser_consume_token (parser);
3969 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3970 if (have_std_attrs)
3971 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3972 attrs = c_parser_gnu_attributes (parser);
3973
3974 /* Set the location in case we create a decl now. */
3975 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
3976
3977 if (c_parser_next_token_is (parser, type: CPP_NAME))
3978 {
3979 ident = c_parser_peek_token (parser)->value;
3980 ident_loc = c_parser_peek_token (parser)->location;
3981 struct_loc = ident_loc;
3982 c_parser_consume_token (parser);
3983 }
3984 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
3985 {
3986 /* Parse a struct or union definition. Start the scope of the
3987 tag before parsing components. */
3988 class c_struct_parse_info *struct_info;
3989 tree type = start_struct (struct_loc, code, ident, &struct_info);
3990 tree postfix_attrs;
3991 /* We chain the components in reverse order, then put them in
3992 forward order at the end. Each struct-declaration may
3993 declare multiple components (comma-separated), so we must use
3994 chainon to join them, although when parsing each
3995 struct-declaration we can use TREE_CHAIN directly.
3996
3997 The theory behind all this is that there will be more
3998 semicolon separated fields than comma separated fields, and
3999 so we'll be minimizing the number of node traversals required
4000 by chainon. */
4001 tree contents;
4002 tree expr = NULL;
4003 timevar_push (tv: TV_PARSE_STRUCT);
4004 contents = NULL_TREE;
4005 c_parser_consume_token (parser);
4006 /* Handle the Objective-C @defs construct,
4007 e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4008 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_DEFS))
4009 {
4010 tree name;
4011 gcc_assert (c_dialect_objc ());
4012 c_parser_consume_token (parser);
4013 matching_parens parens;
4014 if (!parens.require_open (parser))
4015 goto end_at_defs;
4016 if (c_parser_next_token_is (parser, type: CPP_NAME)
4017 && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4018 {
4019 name = c_parser_peek_token (parser)->value;
4020 c_parser_consume_token (parser);
4021 }
4022 else
4023 {
4024 c_parser_error (parser, gmsgid: "expected class name");
4025 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4026 goto end_at_defs;
4027 }
4028 parens.skip_until_found_close (parser);
4029 contents = nreverse (objc_get_class_ivars (name));
4030 }
4031 end_at_defs:
4032 /* Parse the struct-declarations and semicolons. Problems with
4033 semicolons are diagnosed here; empty structures are diagnosed
4034 elsewhere. */
4035 while (true)
4036 {
4037 tree decls;
4038 /* Parse any stray semicolon. */
4039 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4040 {
4041 location_t semicolon_loc
4042 = c_parser_peek_token (parser)->location;
4043 gcc_rich_location richloc (semicolon_loc);
4044 richloc.add_fixit_remove ();
4045 pedwarn (&richloc, OPT_Wpedantic,
4046 "extra semicolon in struct or union specified");
4047 c_parser_consume_token (parser);
4048 continue;
4049 }
4050 /* Stop if at the end of the struct or union contents. */
4051 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4052 {
4053 c_parser_consume_token (parser);
4054 break;
4055 }
4056 /* Accept #pragmas at struct scope. */
4057 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
4058 {
4059 c_parser_pragma (parser, pragma_struct, NULL);
4060 continue;
4061 }
4062 /* Parse some comma-separated declarations, but not the
4063 trailing semicolon if any. */
4064 decls = c_parser_struct_declaration (parser, &expr);
4065 contents = chainon (decls, contents);
4066 /* If no semicolon follows, either we have a parse error or
4067 are at the end of the struct or union and should
4068 pedwarn. */
4069 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4070 c_parser_consume_token (parser);
4071 else
4072 {
4073 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4074 pedwarn (c_parser_peek_token (parser)->location, 0,
4075 "no semicolon at end of struct or union");
4076 else if (parser->error
4077 || !c_parser_next_token_starts_declspecs (parser))
4078 {
4079 c_parser_error (parser, gmsgid: "expected %<;%>");
4080 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4081 break;
4082 }
4083
4084 /* If we come here, we have already emitted an error
4085 for an expected `;', identifier or `(', and we also
4086 recovered already. Go on with the next field. */
4087 }
4088 }
4089 postfix_attrs = c_parser_gnu_attributes (parser);
4090 ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4091 chainon (std_attrs,
4092 chainon (attrs, postfix_attrs)),
4093 struct_info, expr: &expr);
4094 ret.kind = ctsk_tagdef;
4095 ret.expr = expr;
4096 ret.expr_const_operands = true;
4097 ret.has_enum_type_specifier = false;
4098 timevar_pop (tv: TV_PARSE_STRUCT);
4099 return ret;
4100 }
4101 else if (!ident)
4102 {
4103 c_parser_error (parser, gmsgid: "expected %<{%>");
4104 ret.spec = error_mark_node;
4105 ret.kind = ctsk_tagref;
4106 ret.expr = NULL_TREE;
4107 ret.expr_const_operands = true;
4108 ret.has_enum_type_specifier = false;
4109 return ret;
4110 }
4111 /* Attributes may only appear when the members are defined or in
4112 certain forward declarations. */
4113 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4114 c_parser_error (parser, gmsgid: "expected %<;%>");
4115 /* ??? Existing practice is that GNU attributes are ignored after
4116 the struct or union keyword when not defining the members. */
4117 ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4118 false);
4119 return ret;
4120}
4121
4122/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4123 *without* the trailing semicolon.
4124
4125 struct-declaration:
4126 attribute-specifier-sequence[opt] specifier-qualifier-list
4127 attribute-specifier-sequence[opt] struct-declarator-list
4128 static_assert-declaration-no-semi
4129
4130 specifier-qualifier-list:
4131 type-specifier specifier-qualifier-list[opt]
4132 type-qualifier specifier-qualifier-list[opt]
4133 alignment-specifier specifier-qualifier-list[opt]
4134 gnu-attributes specifier-qualifier-list[opt]
4135
4136 struct-declarator-list:
4137 struct-declarator
4138 struct-declarator-list , gnu-attributes[opt] struct-declarator
4139
4140 struct-declarator:
4141 declarator gnu-attributes[opt]
4142 declarator[opt] : constant-expression gnu-attributes[opt]
4143
4144 GNU extensions:
4145
4146 struct-declaration:
4147 __extension__ struct-declaration
4148 specifier-qualifier-list
4149
4150 Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4151 of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4152 any expression without commas in the syntax (assignment
4153 expressions, not just conditional expressions); assignment
4154 expressions will be diagnosed as non-constant. */
4155
4156static tree
4157c_parser_struct_declaration (c_parser *parser, tree *expr)
4158{
4159 struct c_declspecs *specs;
4160 tree prefix_attrs;
4161 tree all_prefix_attrs;
4162 tree decls;
4163 location_t decl_loc;
4164 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
4165 {
4166 int ext;
4167 tree decl;
4168 ext = disable_extension_diagnostics ();
4169 c_parser_consume_token (parser);
4170 decl = c_parser_struct_declaration (parser, expr);
4171 restore_extension_diagnostics (flags: ext);
4172 return decl;
4173 }
4174 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
4175 {
4176 c_parser_static_assert_declaration_no_semi (parser);
4177 return NULL_TREE;
4178 }
4179 specs = build_null_declspecs ();
4180 decl_loc = c_parser_peek_token (parser)->location;
4181 /* Strictly by the standard, we shouldn't allow _Alignas here,
4182 but it appears to have been intended to allow it there, so
4183 we're keeping it as it is until WG14 reaches a conclusion
4184 of N1731.
4185 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4186 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true,
4187 alignspec_ok: true, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: true, la: cla_nonabstract_decl);
4188 if (parser->error)
4189 return NULL_TREE;
4190 if (!specs->declspecs_seen_p)
4191 {
4192 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
4193 return NULL_TREE;
4194 }
4195 finish_declspecs (specs);
4196 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4197 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4198 {
4199 tree ret;
4200 if (specs->typespec_kind == ctsk_none)
4201 {
4202 pedwarn (decl_loc, OPT_Wpedantic,
4203 "ISO C forbids member declarations with no members");
4204 shadow_tag_warned (specs, pedantic);
4205 ret = NULL_TREE;
4206 }
4207 else
4208 {
4209 /* Support for unnamed structs or unions as members of
4210 structs or unions (which is [a] useful and [b] supports
4211 MS P-SDK). */
4212 tree attrs = NULL;
4213
4214 ret = grokfield (c_parser_peek_token (parser)->location,
4215 build_id_declarator (NULL_TREE), specs,
4216 NULL_TREE, &attrs, expr);
4217 if (ret)
4218 decl_attributes (&ret, attrs, 0);
4219 }
4220 return ret;
4221 }
4222
4223 /* Provide better error recovery. Note that a type name here is valid,
4224 and will be treated as a field name. */
4225 if (specs->typespec_kind == ctsk_tagdef
4226 && TREE_CODE (specs->type) != ENUMERAL_TYPE
4227 && c_parser_next_token_starts_declspecs (parser)
4228 && !c_parser_next_token_is (parser, type: CPP_NAME))
4229 {
4230 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
4231 parser->error = false;
4232 return NULL_TREE;
4233 }
4234
4235 pending_xref_error ();
4236 prefix_attrs = specs->attrs;
4237 all_prefix_attrs = prefix_attrs;
4238 specs->attrs = NULL_TREE;
4239 decls = NULL_TREE;
4240 while (true)
4241 {
4242 /* Declaring one or more declarators or un-named bit-fields. */
4243 struct c_declarator *declarator;
4244 bool dummy = false;
4245 if (c_parser_next_token_is (parser, type: CPP_COLON))
4246 declarator = build_id_declarator (NULL_TREE);
4247 else
4248 declarator = c_parser_declarator (parser,
4249 type_seen_p: specs->typespec_kind != ctsk_none,
4250 kind: C_DTR_NORMAL, seen_id: &dummy);
4251 if (declarator == NULL)
4252 {
4253 c_parser_skip_to_end_of_block_or_statement (parser);
4254 break;
4255 }
4256 if (c_parser_next_token_is (parser, type: CPP_COLON)
4257 || c_parser_next_token_is (parser, type: CPP_COMMA)
4258 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4259 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
4260 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4261 {
4262 tree postfix_attrs = NULL_TREE;
4263 tree width = NULL_TREE;
4264 tree d;
4265 if (c_parser_next_token_is (parser, type: CPP_COLON))
4266 {
4267 c_parser_consume_token (parser);
4268 location_t loc = c_parser_peek_token (parser)->location;
4269 width = convert_lvalue_to_rvalue (loc,
4270 (c_parser_expr_no_commas
4271 (parser, NULL)),
4272 true, true).value;
4273 }
4274 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4275 postfix_attrs = c_parser_gnu_attributes (parser);
4276 d = grokfield (c_parser_peek_token (parser)->location,
4277 declarator, specs, width, &all_prefix_attrs, expr);
4278 decl_attributes (&d, chainon (postfix_attrs,
4279 all_prefix_attrs), 0);
4280 DECL_CHAIN (d) = decls;
4281 decls = d;
4282 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4283 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4284 prefix_attrs);
4285 else
4286 all_prefix_attrs = prefix_attrs;
4287 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4288 c_parser_consume_token (parser);
4289 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4290 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4291 {
4292 /* Semicolon consumed in caller. */
4293 break;
4294 }
4295 else
4296 {
4297 c_parser_error (parser, gmsgid: "expected %<,%>, %<;%> or %<}%>");
4298 break;
4299 }
4300 }
4301 else
4302 {
4303 c_parser_error (parser,
4304 gmsgid: "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4305 "%<__attribute__%>");
4306 break;
4307 }
4308 }
4309 return decls;
4310}
4311
4312/* Parse a typeof specifier (a GNU extension adopted in C23).
4313
4314 typeof-specifier:
4315 typeof ( expression )
4316 typeof ( type-name )
4317 typeof_unqual ( expression )
4318 typeof_unqual ( type-name )
4319*/
4320
4321static struct c_typespec
4322c_parser_typeof_specifier (c_parser *parser)
4323{
4324 bool is_unqual;
4325 bool is_std;
4326 struct c_typespec ret;
4327 ret.kind = ctsk_typeof;
4328 ret.spec = error_mark_node;
4329 ret.expr = NULL_TREE;
4330 ret.expr_const_operands = true;
4331 ret.has_enum_type_specifier = false;
4332 if (c_parser_next_token_is_keyword (parser, keyword: RID_TYPEOF))
4333 {
4334 is_unqual = false;
4335 tree spelling = c_parser_peek_token (parser)->value;
4336 is_std = (flag_isoc23
4337 && strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof") == 0);
4338 }
4339 else
4340 {
4341 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4342 is_unqual = true;
4343 tree spelling = c_parser_peek_token (parser)->value;
4344 is_std = strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof_unqual") == 0;
4345 }
4346 c_parser_consume_token (parser);
4347 c_inhibit_evaluation_warnings++;
4348 in_typeof++;
4349 matching_parens parens;
4350 if (!parens.require_open (parser))
4351 {
4352 c_inhibit_evaluation_warnings--;
4353 in_typeof--;
4354 return ret;
4355 }
4356 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4357 {
4358 struct c_type_name *type = c_parser_type_name (parser);
4359 c_inhibit_evaluation_warnings--;
4360 in_typeof--;
4361 if (type != NULL)
4362 {
4363 ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4364 pop_maybe_used (c_type_variably_modified_p (t: ret.spec));
4365 }
4366 }
4367 else
4368 {
4369 bool was_vm;
4370 location_t here = c_parser_peek_token (parser)->location;
4371 struct c_expr expr = c_parser_expression (parser);
4372 c_inhibit_evaluation_warnings--;
4373 in_typeof--;
4374 if (TREE_CODE (expr.value) == COMPONENT_REF
4375 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4376 error_at (here, "%<typeof%> applied to a bit-field");
4377 mark_exp_read (expr.value);
4378 ret.spec = TREE_TYPE (expr.value);
4379 was_vm = c_type_variably_modified_p (t: ret.spec);
4380 /* This is returned with the type so that when the type is
4381 evaluated, this can be evaluated. */
4382 if (was_vm)
4383 ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4384 pop_maybe_used (was_vm);
4385 }
4386 parens.skip_until_found_close (parser);
4387 if (ret.spec != error_mark_node)
4388 {
4389 if (is_unqual && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4390 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4391 if (is_std)
4392 {
4393 /* In ISO C terms, _Noreturn is not part of the type of
4394 expressions such as &abort, but in GCC it is represented
4395 internally as a type qualifier. */
4396 if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4397 && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4398 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4399 else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4400 && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4401 ret.spec
4402 = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4403 }
4404 }
4405 return ret;
4406}
4407
4408/* Parse an alignment-specifier.
4409
4410 C11 6.7.5:
4411
4412 alignment-specifier:
4413 _Alignas ( type-name )
4414 _Alignas ( constant-expression )
4415*/
4416
4417static tree
4418c_parser_alignas_specifier (c_parser * parser)
4419{
4420 tree ret = error_mark_node;
4421 location_t loc = c_parser_peek_token (parser)->location;
4422 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4423 tree spelling = c_parser_peek_token (parser)->value;
4424 c_parser_consume_token (parser);
4425 if (flag_isoc99)
4426 pedwarn_c99 (loc, opt: OPT_Wpedantic,
4427 "ISO C99 does not support %qE", spelling);
4428 else
4429 pedwarn_c99 (loc, opt: OPT_Wpedantic,
4430 "ISO C90 does not support %qE", spelling);
4431 matching_parens parens;
4432 if (!parens.require_open (parser))
4433 return ret;
4434 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4435 {
4436 struct c_type_name *type = c_parser_type_name (parser);
4437 if (type != NULL)
4438 ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4439 false, true, 1);
4440 }
4441 else
4442 ret = convert_lvalue_to_rvalue (loc,
4443 c_parser_expr_no_commas (parser, NULL),
4444 true, true).value;
4445 parens.skip_until_found_close (parser);
4446 return ret;
4447}
4448
4449/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4450 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4451 a typedef name may be redeclared; otherwise it may not. KIND
4452 indicates which kind of declarator is wanted. Returns a valid
4453 declarator except in the case of a syntax error in which case NULL is
4454 returned. *SEEN_ID is set to true if an identifier being declared is
4455 seen; this is used to diagnose bad forms of abstract array declarators
4456 and to determine whether an identifier list is syntactically permitted.
4457
4458 declarator:
4459 pointer[opt] direct-declarator
4460
4461 direct-declarator:
4462 identifier
4463 ( gnu-attributes[opt] declarator )
4464 direct-declarator array-declarator
4465 direct-declarator ( parameter-type-list )
4466 direct-declarator ( identifier-list[opt] )
4467
4468 pointer:
4469 * type-qualifier-list[opt]
4470 * type-qualifier-list[opt] pointer
4471
4472 type-qualifier-list:
4473 type-qualifier
4474 gnu-attributes
4475 type-qualifier-list type-qualifier
4476 type-qualifier-list gnu-attributes
4477
4478 array-declarator:
4479 [ type-qualifier-list[opt] assignment-expression[opt] ]
4480 [ static type-qualifier-list[opt] assignment-expression ]
4481 [ type-qualifier-list static assignment-expression ]
4482 [ type-qualifier-list[opt] * ]
4483
4484 parameter-type-list:
4485 parameter-list
4486 parameter-list , ...
4487
4488 parameter-list:
4489 parameter-declaration
4490 parameter-list , parameter-declaration
4491
4492 parameter-declaration:
4493 declaration-specifiers declarator gnu-attributes[opt]
4494 declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4495
4496 identifier-list:
4497 identifier
4498 identifier-list , identifier
4499
4500 abstract-declarator:
4501 pointer
4502 pointer[opt] direct-abstract-declarator
4503
4504 direct-abstract-declarator:
4505 ( gnu-attributes[opt] abstract-declarator )
4506 direct-abstract-declarator[opt] array-declarator
4507 direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4508
4509 GNU extensions:
4510
4511 direct-declarator:
4512 direct-declarator ( parameter-forward-declarations
4513 parameter-type-list[opt] )
4514
4515 direct-abstract-declarator:
4516 direct-abstract-declarator[opt] ( parameter-forward-declarations
4517 parameter-type-list[opt] )
4518
4519 parameter-forward-declarations:
4520 parameter-list ;
4521 parameter-forward-declarations parameter-list ;
4522
4523 The uses of gnu-attributes shown above are GNU extensions.
4524
4525 Some forms of array declarator are not included in C99 in the
4526 syntax for abstract declarators; these are disallowed elsewhere.
4527 This may be a defect (DR#289).
4528
4529 This function also accepts an omitted abstract declarator as being
4530 an abstract declarator, although not part of the formal syntax. */
4531
4532struct c_declarator *
4533c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4534 bool *seen_id)
4535{
4536 /* Parse any initial pointer part. */
4537 if (c_parser_next_token_is (parser, type: CPP_MULT))
4538 {
4539 struct c_declspecs *quals_attrs = build_null_declspecs ();
4540 struct c_declarator *inner;
4541 c_parser_consume_token (parser);
4542 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4543 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: false, la: cla_prefer_id);
4544 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4545 if (inner == NULL)
4546 return NULL;
4547 else
4548 return make_pointer_declarator (quals_attrs, inner);
4549 }
4550 /* Now we have a direct declarator, direct abstract declarator or
4551 nothing (which counts as a direct abstract declarator here). */
4552 return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
4553}
4554
4555/* Parse a direct declarator or direct abstract declarator; arguments
4556 as c_parser_declarator. */
4557
4558static struct c_declarator *
4559c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4560 bool *seen_id)
4561{
4562 /* The direct declarator must start with an identifier (possibly
4563 omitted) or a parenthesized declarator (possibly abstract). In
4564 an ordinary declarator, initial parentheses must start a
4565 parenthesized declarator. In an abstract declarator or parameter
4566 declarator, they could start a parenthesized declarator or a
4567 parameter list. To tell which, the open parenthesis and any
4568 following gnu-attributes must be read. If a declaration
4569 specifier or standard attributes follow, then it is a parameter
4570 list; if the specifier is a typedef name, there might be an
4571 ambiguity about redeclaring it, which is resolved in the
4572 direction of treating it as a typedef name. If a close
4573 parenthesis follows, it is also an empty parameter list, as the
4574 syntax does not permit empty abstract declarators. Otherwise, it
4575 is a parenthesized declarator (in which case the analysis may be
4576 repeated inside it, recursively).
4577
4578 ??? There is an ambiguity in a parameter declaration "int
4579 (__attribute__((foo)) x)", where x is not a typedef name: it
4580 could be an abstract declarator for a function, or declare x with
4581 parentheses. The proper resolution of this ambiguity needs
4582 documenting. At present we follow an accident of the old
4583 parser's implementation, whereby the first parameter must have
4584 some declaration specifiers other than just gnu-attributes. Thus as
4585 a parameter declaration it is treated as a parenthesized
4586 parameter named x, and as an abstract declarator it is
4587 rejected.
4588
4589 ??? Also following the old parser, gnu-attributes inside an empty
4590 parameter list are ignored, making it a list not yielding a
4591 prototype, rather than giving an error or making it have one
4592 parameter with implicit type int.
4593
4594 ??? Also following the old parser, typedef names may be
4595 redeclared in declarators, but not Objective-C class names. */
4596
4597 if (kind != C_DTR_ABSTRACT
4598 && c_parser_next_token_is (parser, type: CPP_NAME)
4599 && ((type_seen_p
4600 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
4601 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
4602 || c_parser_peek_token (parser)->id_kind == C_ID_ID))
4603 {
4604 struct c_declarator *inner
4605 = build_id_declarator (c_parser_peek_token (parser)->value);
4606 *seen_id = true;
4607 inner->id_loc = c_parser_peek_token (parser)->location;
4608 c_parser_consume_token (parser);
4609 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4610 inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
4611 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4612 }
4613
4614 if (kind != C_DTR_NORMAL
4615 && c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
4616 && !c_parser_nth_token_starts_std_attributes (parser, 1))
4617 {
4618 struct c_declarator *inner = build_id_declarator (NULL_TREE);
4619 inner->id_loc = c_parser_peek_token (parser)->location;
4620 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4621 }
4622
4623 /* Either we are at the end of an abstract declarator, or we have
4624 parentheses. */
4625
4626 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
4627 {
4628 tree attrs;
4629 struct c_declarator *inner;
4630 c_parser_consume_token (parser);
4631 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4632 keyword: RID_ATTRIBUTE);
4633 attrs = c_parser_gnu_attributes (parser);
4634 if (kind != C_DTR_NORMAL
4635 && (c_parser_next_token_starts_declspecs (parser)
4636 || (!have_gnu_attrs
4637 && (c_parser_nth_token_starts_std_attributes (parser, 1)
4638 || c_parser_next_token_is (parser, type: CPP_ELLIPSIS)))
4639 || c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN)))
4640 {
4641 struct c_arg_info *args
4642 = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
4643 attrs, have_gnu_attrs);
4644 if (args == NULL)
4645 return NULL;
4646 else
4647 {
4648 inner = build_id_declarator (NULL_TREE);
4649 if (!(args->types
4650 && args->types != error_mark_node
4651 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4652 && c_parser_nth_token_starts_std_attributes (parser, 1))
4653 {
4654 tree std_attrs
4655 = c_parser_std_attribute_specifier_sequence (parser);
4656 if (std_attrs)
4657 inner = build_attrs_declarator (std_attrs, inner);
4658 }
4659 inner = build_function_declarator (args, inner);
4660 return c_parser_direct_declarator_inner (parser, *seen_id,
4661 inner);
4662 }
4663 }
4664 /* A parenthesized declarator. */
4665 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4666 if (inner != NULL && attrs != NULL)
4667 inner = build_attrs_declarator (attrs, inner);
4668 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4669 {
4670 c_parser_consume_token (parser);
4671 if (inner == NULL)
4672 return NULL;
4673 else
4674 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4675 }
4676 else
4677 {
4678 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4679 msgid: "expected %<)%>");
4680 return NULL;
4681 }
4682 }
4683 else
4684 {
4685 if (kind == C_DTR_NORMAL)
4686 {
4687 c_parser_error (parser, gmsgid: "expected identifier or %<(%>");
4688 return NULL;
4689 }
4690 else
4691 return build_id_declarator (NULL_TREE);
4692 }
4693}
4694
4695/* Parse part of a direct declarator or direct abstract declarator,
4696 given that some (in INNER) has already been parsed; ID_PRESENT is
4697 true if an identifier is present, false for an abstract
4698 declarator. */
4699
4700static struct c_declarator *
4701c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
4702 struct c_declarator *inner)
4703{
4704 /* Parse a sequence of array declarators and parameter lists. */
4705 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
4706 && !c_parser_nth_token_starts_std_attributes (parser, 1))
4707 {
4708 location_t brace_loc = c_parser_peek_token (parser)->location;
4709 struct c_declarator *declarator;
4710 struct c_declspecs *quals_attrs = build_null_declspecs ();
4711 bool static_seen;
4712 bool star_seen;
4713 struct c_expr dimen;
4714 dimen.value = NULL_TREE;
4715 dimen.original_code = ERROR_MARK;
4716 dimen.original_type = NULL_TREE;
4717 c_parser_consume_token (parser);
4718 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4719 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
4720 static_seen = c_parser_next_token_is_keyword (parser, keyword: RID_STATIC);
4721 if (static_seen)
4722 c_parser_consume_token (parser);
4723 if (static_seen && !quals_attrs->declspecs_seen_p)
4724 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4725 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
4726 if (!quals_attrs->declspecs_seen_p)
4727 quals_attrs = NULL;
4728 /* If "static" is present, there must be an array dimension.
4729 Otherwise, there may be a dimension, "*", or no
4730 dimension. */
4731 if (static_seen)
4732 {
4733 star_seen = false;
4734 dimen = c_parser_expr_no_commas (parser, NULL);
4735 }
4736 else
4737 {
4738 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
4739 {
4740 dimen.value = NULL_TREE;
4741 star_seen = false;
4742 }
4743 else if (c_parser_next_token_is (parser, type: CPP_MULT))
4744 {
4745 if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
4746 {
4747 dimen.value = NULL_TREE;
4748 star_seen = true;
4749 c_parser_consume_token (parser);
4750 }
4751 else
4752 {
4753 star_seen = false;
4754 dimen = c_parser_expr_no_commas (parser, NULL);
4755 }
4756 }
4757 else
4758 {
4759 star_seen = false;
4760 dimen = c_parser_expr_no_commas (parser, NULL);
4761 }
4762 }
4763 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
4764 c_parser_consume_token (parser);
4765 else
4766 {
4767 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
4768 msgid: "expected %<]%>");
4769 return NULL;
4770 }
4771 if (dimen.value)
4772 dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
4773 declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
4774 static_seen, star_seen);
4775 if (declarator == NULL)
4776 return NULL;
4777 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4778 {
4779 tree std_attrs
4780 = c_parser_std_attribute_specifier_sequence (parser);
4781 if (std_attrs)
4782 inner = build_attrs_declarator (std_attrs, inner);
4783 }
4784 inner = set_array_declarator_inner (declarator, inner);
4785 return c_parser_direct_declarator_inner (parser, id_present, inner);
4786 }
4787 else if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
4788 {
4789 tree attrs;
4790 struct c_arg_info *args;
4791 c_parser_consume_token (parser);
4792 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4793 keyword: RID_ATTRIBUTE);
4794 attrs = c_parser_gnu_attributes (parser);
4795 args = c_parser_parms_declarator (parser, id_present, attrs,
4796 have_gnu_attrs);
4797 if (args == NULL)
4798 return NULL;
4799 else
4800 {
4801 if (!(args->types
4802 && args->types != error_mark_node
4803 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4804 && c_parser_nth_token_starts_std_attributes (parser, 1))
4805 {
4806 tree std_attrs
4807 = c_parser_std_attribute_specifier_sequence (parser);
4808 if (std_attrs)
4809 inner = build_attrs_declarator (std_attrs, inner);
4810 }
4811 inner = build_function_declarator (args, inner);
4812 return c_parser_direct_declarator_inner (parser, id_present, inner);
4813 }
4814 }
4815 return inner;
4816}
4817
4818/* Parse a parameter list or identifier list, including the closing
4819 parenthesis but not the opening one. ATTRS are the gnu-attributes
4820 at the start of the list. ID_LIST_OK is true if an identifier list
4821 is acceptable; such a list must not have attributes at the start.
4822 HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
4823 attributes) were present (in which case standard attributes cannot
4824 occur). */
4825
4826static struct c_arg_info *
4827c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
4828 bool have_gnu_attrs)
4829{
4830 push_scope ();
4831 declare_parm_level ();
4832 /* If the list starts with an identifier, it is an identifier list.
4833 Otherwise, it is either a prototype list or an empty list. */
4834 if (id_list_ok
4835 && !attrs
4836 && c_parser_next_token_is (parser, type: CPP_NAME)
4837 && c_parser_peek_token (parser)->id_kind == C_ID_ID
4838
4839 /* Look ahead to detect typos in type names. */
4840 && c_parser_peek_2nd_token (parser)->type != CPP_NAME
4841 && c_parser_peek_2nd_token (parser)->type != CPP_MULT
4842 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
4843 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
4844 && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
4845 {
4846 tree list = NULL_TREE, *nextp = &list;
4847 while (c_parser_next_token_is (parser, type: CPP_NAME)
4848 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
4849 {
4850 *nextp = build_tree_list (NULL_TREE,
4851 c_parser_peek_token (parser)->value);
4852 nextp = & TREE_CHAIN (*nextp);
4853 c_parser_consume_token (parser);
4854 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
4855 break;
4856 c_parser_consume_token (parser);
4857 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4858 {
4859 c_parser_error (parser, gmsgid: "expected identifier");
4860 break;
4861 }
4862 }
4863 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4864 {
4865 struct c_arg_info *ret = build_arg_info ();
4866 ret->types = list;
4867 c_parser_consume_token (parser);
4868 pop_scope ();
4869 return ret;
4870 }
4871 else
4872 {
4873 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4874 msgid: "expected %<)%>");
4875 pop_scope ();
4876 return NULL;
4877 }
4878 }
4879 else
4880 {
4881 struct c_arg_info *ret
4882 = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
4883 pop_scope ();
4884 return ret;
4885 }
4886}
4887
4888/* Parse a parameter list (possibly empty), including the closing
4889 parenthesis but not the opening one. ATTRS are the gnu-attributes
4890 at the start of the list; if HAVE_GNU_ATTRS, there were some such
4891 attributes (possibly empty, in which case ATTRS is NULL_TREE),
4892 which means standard attributes cannot start the list. EXPR is
4893 NULL or an expression that needs to be evaluated for the side
4894 effects of array size expressions in the parameters. */
4895
4896static struct c_arg_info *
4897c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
4898 bool have_gnu_attrs)
4899{
4900 bool bad_parm = false;
4901
4902 /* ??? Following the old parser, forward parameter declarations may
4903 use abstract declarators, and if no real parameter declarations
4904 follow the forward declarations then this is not diagnosed. Also
4905 note as above that gnu-attributes are ignored as the only contents of
4906 the parentheses, or as the only contents after forward
4907 declarations. */
4908 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4909 {
4910 struct c_arg_info *ret = build_arg_info ();
4911 c_parser_consume_token (parser);
4912 return ret;
4913 }
4914 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS) && !have_gnu_attrs)
4915 {
4916 struct c_arg_info *ret = build_arg_info ();
4917
4918 ret->types = NULL_TREE;
4919 pedwarn_c11 (c_parser_peek_token (parser)->location, opt: OPT_Wpedantic,
4920 "ISO C requires a named argument before %<...%> "
4921 "before C23");
4922 c_parser_consume_token (parser);
4923 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4924 {
4925 ret->no_named_args_stdarg_p = true;
4926 c_parser_consume_token (parser);
4927 return ret;
4928 }
4929 else
4930 {
4931 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4932 msgid: "expected %<)%>");
4933 return NULL;
4934 }
4935 }
4936 /* Nonempty list of parameters, either terminated with semicolon
4937 (forward declarations; recurse) or with close parenthesis (normal
4938 function) or with ", ... )" (variadic function). */
4939 while (true)
4940 {
4941 /* Parse a parameter. */
4942 struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
4943 have_gnu_attrs);
4944 attrs = NULL_TREE;
4945 have_gnu_attrs = false;
4946 if (parm == NULL)
4947 bad_parm = true;
4948 else
4949 push_parm_decl (parm, &expr);
4950 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4951 {
4952 tree new_attrs;
4953 c_parser_consume_token (parser);
4954 mark_forward_parm_decls ();
4955 bool new_have_gnu_attrs
4956 = c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE);
4957 new_attrs = c_parser_gnu_attributes (parser);
4958 return c_parser_parms_list_declarator (parser, attrs: new_attrs, expr,
4959 have_gnu_attrs: new_have_gnu_attrs);
4960 }
4961 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4962 {
4963 c_parser_consume_token (parser);
4964 if (bad_parm)
4965 return NULL;
4966 else
4967 return get_parm_info (false, expr);
4968 }
4969 if (!c_parser_require (parser, type: CPP_COMMA,
4970 msgid: "expected %<;%>, %<,%> or %<)%>",
4971 UNKNOWN_LOCATION, type_is_unique: false))
4972 {
4973 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4974 return NULL;
4975 }
4976 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
4977 {
4978 c_parser_consume_token (parser);
4979 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4980 {
4981 c_parser_consume_token (parser);
4982 if (bad_parm)
4983 return NULL;
4984 else
4985 return get_parm_info (true, expr);
4986 }
4987 else
4988 {
4989 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4990 msgid: "expected %<)%>");
4991 return NULL;
4992 }
4993 }
4994 }
4995}
4996
4997/* Parse a parameter declaration. ATTRS are the gnu-attributes at the
4998 start of the declaration if it is the first parameter;
4999 HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
5000 empty) there. */
5001
5002static struct c_parm *
5003c_parser_parameter_declaration (c_parser *parser, tree attrs,
5004 bool have_gnu_attrs)
5005{
5006 struct c_declspecs *specs;
5007 struct c_declarator *declarator;
5008 tree prefix_attrs;
5009 tree postfix_attrs = NULL_TREE;
5010 bool dummy = false;
5011
5012 /* Accept #pragmas between parameter declarations. */
5013 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
5014 c_parser_pragma (parser, pragma_param, NULL);
5015
5016 if (!c_parser_next_token_starts_declspecs (parser)
5017 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5018 {
5019 c_token *token = c_parser_peek_token (parser);
5020 if (parser->error)
5021 return NULL;
5022 c_parser_set_source_position_from_token (token);
5023 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
5024 {
5025 auto_diagnostic_group d;
5026 name_hint hint = lookup_name_fuzzy (token->value,
5027 FUZZY_LOOKUP_TYPENAME,
5028 token->location);
5029 if (const char *suggestion = hint.suggestion ())
5030 {
5031 gcc_rich_location richloc (token->location);
5032 richloc.add_fixit_replace (new_content: suggestion);
5033 error_at (&richloc,
5034 "unknown type name %qE; did you mean %qs?",
5035 token->value, suggestion);
5036 }
5037 else
5038 error_at (token->location, "unknown type name %qE", token->value);
5039 parser->error = true;
5040 }
5041 /* ??? In some Objective-C cases '...' isn't applicable so there
5042 should be a different message. */
5043 else
5044 c_parser_error (parser,
5045 gmsgid: "expected declaration specifiers or %<...%>");
5046 c_parser_skip_to_end_of_parameter (parser);
5047 return NULL;
5048 }
5049
5050 location_t start_loc = c_parser_peek_token (parser)->location;
5051
5052 specs = build_null_declspecs ();
5053 if (attrs)
5054 {
5055 declspecs_add_attrs (input_location, specs, attrs);
5056 attrs = NULL_TREE;
5057 }
5058 c_parser_declspecs (parser, specs, scspec_ok: true, typespec_ok: true, start_attr_ok: true, alignspec_ok: true, auto_type_ok: false,
5059 start_std_attr_ok: !have_gnu_attrs, end_std_attr_ok: true, la: cla_nonabstract_decl);
5060 finish_declspecs (specs);
5061 pending_xref_error ();
5062 prefix_attrs = specs->attrs;
5063 specs->attrs = NULL_TREE;
5064 declarator = c_parser_declarator (parser,
5065 type_seen_p: specs->typespec_kind != ctsk_none,
5066 kind: C_DTR_PARM, seen_id: &dummy);
5067 if (declarator == NULL)
5068 {
5069 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
5070 return NULL;
5071 }
5072 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5073 postfix_attrs = c_parser_gnu_attributes (parser);
5074
5075 /* Generate a location for the parameter, ranging from the start of the
5076 initial token to the end of the final token.
5077
5078 If we have a identifier, then use it for the caret location, e.g.
5079
5080 extern int callee (int one, int (*two)(int, int), float three);
5081 ~~~~~~^~~~~~~~~~~~~~
5082
5083 otherwise, reuse the start location for the caret location e.g.:
5084
5085 extern int callee (int one, int (*)(int, int), float three);
5086 ^~~~~~~~~~~~~~~~~
5087 */
5088 location_t end_loc = parser->last_token_location;
5089
5090 /* Find any cdk_id declarator; determine if we have an identifier. */
5091 c_declarator *id_declarator = declarator;
5092 while (id_declarator && id_declarator->kind != cdk_id)
5093 id_declarator = id_declarator->declarator;
5094 location_t caret_loc = (id_declarator->u.id.id
5095 ? id_declarator->id_loc
5096 : start_loc);
5097 location_t param_loc = make_location (caret: caret_loc, start: start_loc, finish: end_loc);
5098
5099 return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5100 declarator, param_loc);
5101}
5102
5103/* Parse a string literal in an asm expression. It should not be
5104 translated, and wide string literals are an error although
5105 permitted by the syntax. This is a GNU extension.
5106
5107 asm-string-literal:
5108 string-literal
5109*/
5110
5111static tree
5112c_parser_asm_string_literal (c_parser *parser)
5113{
5114 tree str;
5115 int save_flag = warn_overlength_strings;
5116 warn_overlength_strings = 0;
5117 str = c_parser_string_literal (parser, false, false).value;
5118 warn_overlength_strings = save_flag;
5119 return str;
5120}
5121
5122/* Parse a simple asm expression. This is used in restricted
5123 contexts, where a full expression with inputs and outputs does not
5124 make sense. This is a GNU extension.
5125
5126 simple-asm-expr:
5127 asm ( asm-string-literal )
5128*/
5129
5130static tree
5131c_parser_simple_asm_expr (c_parser *parser)
5132{
5133 tree str;
5134 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5135 c_parser_consume_token (parser);
5136 matching_parens parens;
5137 if (!parens.require_open (parser))
5138 return NULL_TREE;
5139 str = c_parser_asm_string_literal (parser);
5140 if (!parens.require_close (parser))
5141 {
5142 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5143 return NULL_TREE;
5144 }
5145 return str;
5146}
5147
5148static tree
5149c_parser_gnu_attribute_any_word (c_parser *parser)
5150{
5151 tree attr_name = NULL_TREE;
5152
5153 if (c_parser_next_token_is (parser, type: CPP_KEYWORD))
5154 {
5155 /* ??? See comment above about what keywords are accepted here. */
5156 bool ok;
5157 switch (c_parser_peek_token (parser)->keyword)
5158 {
5159 case RID_STATIC:
5160 case RID_UNSIGNED:
5161 case RID_LONG:
5162 case RID_CONST:
5163 case RID_EXTERN:
5164 case RID_REGISTER:
5165 case RID_TYPEDEF:
5166 case RID_SHORT:
5167 case RID_INLINE:
5168 case RID_NORETURN:
5169 case RID_VOLATILE:
5170 case RID_SIGNED:
5171 case RID_AUTO:
5172 case RID_RESTRICT:
5173 case RID_COMPLEX:
5174 case RID_THREAD:
5175 case RID_INT:
5176 case RID_CHAR:
5177 case RID_FLOAT:
5178 case RID_DOUBLE:
5179 case RID_VOID:
5180 case RID_DFLOAT32:
5181 case RID_DFLOAT64:
5182 case RID_DFLOAT128:
5183 CASE_RID_FLOATN_NX:
5184 case RID_BOOL:
5185 case RID_BITINT:
5186 case RID_FRACT:
5187 case RID_ACCUM:
5188 case RID_SAT:
5189 case RID_TRANSACTION_ATOMIC:
5190 case RID_TRANSACTION_CANCEL:
5191 case RID_ATOMIC:
5192 case RID_AUTO_TYPE:
5193 case RID_CONSTEXPR:
5194 case RID_INT_N_0:
5195 case RID_INT_N_1:
5196 case RID_INT_N_2:
5197 case RID_INT_N_3:
5198 ok = true;
5199 break;
5200 default:
5201 ok = false;
5202 break;
5203 }
5204 if (!ok)
5205 return NULL_TREE;
5206
5207 /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5208 attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5209 }
5210 else if (c_parser_next_token_is (parser, type: CPP_NAME))
5211 attr_name = c_parser_peek_token (parser)->value;
5212
5213 return attr_name;
5214}
5215
5216/* Parse attribute arguments. This is a common form of syntax
5217 covering all currently valid GNU and standard attributes.
5218
5219 gnu-attribute-arguments:
5220 identifier
5221 identifier , nonempty-expr-list
5222 expr-list
5223
5224 where the "identifier" must not be declared as a type. ??? Why not
5225 allow identifiers declared as types to start the arguments? */
5226
5227static tree
5228c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5229 bool require_string, bool assume_attr,
5230 bool allow_empty_args)
5231{
5232 vec<tree, va_gc> *expr_list;
5233 tree attr_args;
5234 /* Parse the attribute contents. If they start with an
5235 identifier which is followed by a comma or close
5236 parenthesis, then the arguments start with that
5237 identifier; otherwise they are an expression list.
5238 In objective-c the identifier may be a classname. */
5239 if (c_parser_next_token_is (parser, type: CPP_NAME)
5240 && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5241 || (c_dialect_objc ()
5242 && c_parser_peek_token (parser)->id_kind
5243 == C_ID_CLASSNAME))
5244 && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5245 || (c_parser_peek_2nd_token (parser)->type
5246 == CPP_CLOSE_PAREN))
5247 && (takes_identifier
5248 || (c_dialect_objc ()
5249 && !assume_attr
5250 && c_parser_peek_token (parser)->id_kind
5251 == C_ID_CLASSNAME)))
5252 {
5253 tree arg1 = c_parser_peek_token (parser)->value;
5254 c_parser_consume_token (parser);
5255 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5256 attr_args = build_tree_list (NULL_TREE, arg1);
5257 else
5258 {
5259 tree tree_list;
5260 c_parser_consume_token (parser);
5261 expr_list = c_parser_expr_list (parser, false, true,
5262 NULL, NULL, NULL, NULL);
5263 tree_list = build_tree_list_vec (expr_list);
5264 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5265 release_tree_vector (expr_list);
5266 }
5267 }
5268 else
5269 {
5270 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5271 {
5272 if (!allow_empty_args)
5273 error_at (c_parser_peek_token (parser)->location,
5274 "parentheses must be omitted if "
5275 "attribute argument list is empty");
5276 attr_args = NULL_TREE;
5277 }
5278 else if (require_string)
5279 {
5280 /* The only valid argument for this attribute is a string
5281 literal. Handle this specially here to avoid accepting
5282 string literals with excess parentheses. */
5283 tree string = c_parser_string_literal (parser, false, true).value;
5284 attr_args = build_tree_list (NULL_TREE, string);
5285 }
5286 else if (assume_attr)
5287 {
5288 tree cond
5289 = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5290 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
5291 attr_args = build_tree_list (NULL_TREE, cond);
5292 else
5293 {
5294 tree tree_list;
5295 c_parser_consume_token (parser);
5296 expr_list = c_parser_expr_list (parser, false, true,
5297 NULL, NULL, NULL, NULL);
5298 tree_list = build_tree_list_vec (expr_list);
5299 attr_args = tree_cons (NULL_TREE, cond, tree_list);
5300 release_tree_vector (expr_list);
5301 }
5302 }
5303 else
5304 {
5305 expr_list = c_parser_expr_list (parser, false, true,
5306 NULL, NULL, NULL, NULL);
5307 attr_args = build_tree_list_vec (expr_list);
5308 release_tree_vector (expr_list);
5309 }
5310 }
5311 return attr_args;
5312}
5313
5314/* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5315
5316 gnu-attributes:
5317 empty
5318 gnu-attributes gnu-attribute
5319
5320 gnu-attribute:
5321 __attribute__ ( ( gnu-attribute-list ) )
5322
5323 gnu-attribute-list:
5324 gnu-attrib
5325 gnu-attribute_list , gnu-attrib
5326
5327 gnu-attrib:
5328 empty
5329 any-word
5330 any-word ( gnu-attribute-arguments )
5331
5332 where "any-word" may be any identifier (including one declared as a
5333 type), a reserved word storage class specifier, type specifier or
5334 type qualifier. ??? This still leaves out most reserved keywords
5335 (following the old parser), shouldn't we include them?
5336 When EXPECT_COMMA is true, expect the attribute to be preceded
5337 by a comma and fail if it isn't.
5338 When EMPTY_OK is true, allow and consume any number of consecutive
5339 commas with no attributes in between. */
5340
5341static tree
5342c_parser_gnu_attribute (c_parser *parser, tree attrs,
5343 bool expect_comma = false, bool empty_ok = true)
5344{
5345 bool comma_first = c_parser_next_token_is (parser, type: CPP_COMMA);
5346 if (!comma_first
5347 && !c_parser_next_token_is (parser, type: CPP_NAME)
5348 && !c_parser_next_token_is (parser, type: CPP_KEYWORD))
5349 return NULL_TREE;
5350
5351 while (c_parser_next_token_is (parser, type: CPP_COMMA))
5352 {
5353 c_parser_consume_token (parser);
5354 if (!empty_ok)
5355 return attrs;
5356 }
5357
5358 tree attr_name = c_parser_gnu_attribute_any_word (parser);
5359 if (attr_name == NULL_TREE)
5360 return NULL_TREE;
5361
5362 attr_name = canonicalize_attr_name (attr_name);
5363 c_parser_consume_token (parser);
5364
5365 tree attr;
5366 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5367 {
5368 if (expect_comma && !comma_first)
5369 {
5370 /* A comma is missing between the last attribute on the chain
5371 and this one. */
5372 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5373 msgid: "expected %<)%>");
5374 return error_mark_node;
5375 }
5376 attr = build_tree_list (attr_name, NULL_TREE);
5377 /* Add this attribute to the list. */
5378 attrs = chainon (attrs, attr);
5379 return attrs;
5380 }
5381 c_parser_consume_token (parser);
5382
5383 tree attr_args
5384 = c_parser_attribute_arguments (parser,
5385 takes_identifier: attribute_takes_identifier_p (attr_name),
5386 require_string: false,
5387 assume_attr: is_attribute_p (attr_name: "assume", ident: attr_name),
5388 allow_empty_args: true);
5389
5390 attr = build_tree_list (attr_name, attr_args);
5391 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5392 c_parser_consume_token (parser);
5393 else
5394 {
5395 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5396 msgid: "expected %<)%>");
5397 return error_mark_node;
5398 }
5399
5400 if (expect_comma && !comma_first)
5401 {
5402 /* A comma is missing between the last attribute on the chain
5403 and this one. */
5404 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5405 msgid: "expected %<)%>");
5406 return error_mark_node;
5407 }
5408
5409 /* Add this attribute to the list. */
5410 attrs = chainon (attrs, attr);
5411 return attrs;
5412}
5413
5414static tree
5415c_parser_gnu_attributes (c_parser *parser)
5416{
5417 tree attrs = NULL_TREE;
5418 while (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5419 {
5420 bool save_translate_strings_p = parser->translate_strings_p;
5421 parser->translate_strings_p = false;
5422 /* Consume the `__attribute__' keyword. */
5423 c_parser_consume_token (parser);
5424 /* Look for the two `(' tokens. */
5425 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5426 {
5427 parser->translate_strings_p = save_translate_strings_p;
5428 return attrs;
5429 }
5430 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5431 {
5432 parser->translate_strings_p = save_translate_strings_p;
5433 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5434 return attrs;
5435 }
5436 /* Parse the attribute list. Require a comma between successive
5437 (possibly empty) attributes. */
5438 for (bool expect_comma = false; ; expect_comma = true)
5439 {
5440 /* Parse a single attribute. */
5441 tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5442 if (attr == error_mark_node)
5443 return attrs;
5444 if (!attr)
5445 break;
5446 attrs = attr;
5447 }
5448
5449 /* Look for the two `)' tokens. */
5450 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5451 c_parser_consume_token (parser);
5452 else
5453 {
5454 parser->translate_strings_p = save_translate_strings_p;
5455 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5456 msgid: "expected %<)%>");
5457 return attrs;
5458 }
5459 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5460 c_parser_consume_token (parser);
5461 else
5462 {
5463 parser->translate_strings_p = save_translate_strings_p;
5464 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5465 msgid: "expected %<)%>");
5466 return attrs;
5467 }
5468 parser->translate_strings_p = save_translate_strings_p;
5469 }
5470
5471 return attrs;
5472}
5473
5474/* Parse an optional balanced token sequence.
5475
5476 balanced-token-sequence:
5477 balanced-token
5478 balanced-token-sequence balanced-token
5479
5480 balanced-token:
5481 ( balanced-token-sequence[opt] )
5482 [ balanced-token-sequence[opt] ]
5483 { balanced-token-sequence[opt] }
5484 any token other than ()[]{}
5485*/
5486
5487static void
5488c_parser_balanced_token_sequence (c_parser *parser)
5489{
5490 while (true)
5491 {
5492 c_token *token = c_parser_peek_token (parser);
5493 switch (token->type)
5494 {
5495 case CPP_OPEN_BRACE:
5496 {
5497 matching_braces braces;
5498 braces.consume_open (parser);
5499 c_parser_balanced_token_sequence (parser);
5500 braces.require_close (parser);
5501 break;
5502 }
5503
5504 case CPP_OPEN_PAREN:
5505 {
5506 matching_parens parens;
5507 parens.consume_open (parser);
5508 c_parser_balanced_token_sequence (parser);
5509 parens.require_close (parser);
5510 break;
5511 }
5512
5513 case CPP_OPEN_SQUARE:
5514 c_parser_consume_token (parser);
5515 c_parser_balanced_token_sequence (parser);
5516 c_parser_require (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5517 break;
5518
5519 case CPP_CLOSE_BRACE:
5520 case CPP_CLOSE_PAREN:
5521 case CPP_CLOSE_SQUARE:
5522 case CPP_EOF:
5523 return;
5524
5525 case CPP_PRAGMA:
5526 c_parser_consume_pragma (parser);
5527 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
5528 break;
5529
5530 default:
5531 c_parser_consume_token (parser);
5532 break;
5533 }
5534 }
5535}
5536
5537static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
5538 unsigned int *);
5539
5540/* Parse arguments of omp::directive or omp::decl attribute.
5541
5542 directive-name ,[opt] clause-list[opt]
5543
5544 For directive just remember the tokens in a vector for subsequent
5545 parsing. */
5546
5547static void
5548c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5549{
5550 unsigned int n = 1;
5551 c_token *first = c_parser_peek_token (parser);
5552 if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
5553 || (c_parser_peek_nth_token_raw (parser, n)->type
5554 != CPP_CLOSE_PAREN))
5555 {
5556 c_parser_balanced_token_sequence (parser);
5557 TREE_VALUE (attribute) = NULL_TREE;
5558 return;
5559 }
5560 if (n == 1)
5561 {
5562 error_at (first->location, "expected OpenMP directive name");
5563 TREE_VALUE (attribute) = NULL_TREE;
5564 return;
5565 }
5566 vec<c_token, va_gc> *v;
5567 vec_alloc (v, nelems: n - 1);
5568 for (--n; n; --n)
5569 {
5570 c_token *tok = c_parser_peek_token (parser);
5571 v->quick_push (obj: *tok);
5572 c_parser_consume_token (parser);
5573 }
5574 tree arg = make_node (C_TOKEN_VEC);
5575 C_TOKEN_VEC_TOKENS (arg) = v;
5576 if (decl_p)
5577 TREE_PUBLIC (arg) = 1;
5578 TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
5579}
5580
5581/* Parse arguments of omp::sequence attribute.
5582
5583 omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
5584
5585static void
5586c_parser_omp_sequence_args (c_parser *parser, tree attribute)
5587{
5588 do
5589 {
5590 c_token *token = c_parser_peek_token (parser);
5591 if (token->type == CPP_NAME
5592 && strcmp (IDENTIFIER_POINTER (token->value), s2: "omp") == 0
5593 && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
5594 {
5595 c_parser_consume_token (parser);
5596 c_parser_consume_token (parser);
5597 token = c_parser_peek_token (parser);
5598 }
5599 bool directive = false;
5600 const char *p;
5601 if (token->type != CPP_NAME)
5602 p = "";
5603 else
5604 p = IDENTIFIER_POINTER (token->value);
5605 if (strcmp (s1: p, s2: "directive") == 0)
5606 directive = true;
5607 else if (strcmp (s1: p, s2: "sequence") != 0)
5608 {
5609 error_at (token->location, "expected %<directive%> or %<sequence%>");
5610 unsigned nesting_depth = 0;
5611
5612 while (true)
5613 {
5614 /* Peek at the next token. */
5615 token = c_parser_peek_token (parser);
5616 /* If we've reached the token we want, consume it and stop. */
5617 if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
5618 && !nesting_depth)
5619 break;
5620 /* If we've run out of tokens, stop. */
5621 if (token->type == CPP_EOF)
5622 break;
5623 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
5624 break;
5625 if (token->type == CPP_OPEN_BRACE
5626 || token->type == CPP_OPEN_PAREN
5627 || token->type == CPP_OPEN_SQUARE)
5628 ++nesting_depth;
5629 else if (token->type == CPP_CLOSE_BRACE
5630 || token->type == CPP_CLOSE_PAREN
5631 || token->type == CPP_CLOSE_SQUARE)
5632 {
5633 if (nesting_depth-- == 0)
5634 break;
5635 }
5636 /* Consume this token. */
5637 c_parser_consume_token (parser);
5638 }
5639 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5640 break;
5641 c_parser_consume_token (parser);
5642 continue;
5643 }
5644 c_parser_consume_token (parser);
5645 matching_parens parens;
5646 if (parens.require_open (parser))
5647 {
5648 if (directive)
5649 c_parser_omp_directive_args (parser, attribute, decl_p: false);
5650 else
5651 c_parser_omp_sequence_args (parser, attribute);
5652 parens.skip_until_found_close (parser);
5653 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5654 break;
5655 c_parser_consume_token (parser);
5656 }
5657 else if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5658 break;
5659 else
5660 c_parser_consume_token (parser);
5661 }
5662 while (1);
5663}
5664
5665/* Parse standard (C23) attributes (including GNU attributes in the
5666 gnu:: namespace).
5667
5668 attribute-specifier-sequence:
5669 attribute-specifier-sequence[opt] attribute-specifier
5670
5671 attribute-specifier:
5672 [ [ attribute-list ] ]
5673
5674 attribute-list:
5675 attribute[opt]
5676 attribute-list, attribute[opt]
5677
5678 attribute:
5679 attribute-token attribute-argument-clause[opt]
5680
5681 attribute-token:
5682 standard-attribute
5683 attribute-prefixed-token
5684
5685 standard-attribute:
5686 identifier
5687
5688 attribute-prefixed-token:
5689 attribute-prefix :: identifier
5690
5691 attribute-prefix:
5692 identifier
5693
5694 attribute-argument-clause:
5695 ( balanced-token-sequence[opt] )
5696
5697 Keywords are accepted as identifiers for this purpose.
5698
5699 As an extension, we permit an attribute-specifier to be:
5700
5701 [ [ __extension__ attribute-list ] ]
5702
5703 Two colons are then accepted as a synonym for ::. No attempt is made
5704 to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
5705 indicates whether this relaxation is in effect. */
5706
5707static tree
5708c_parser_std_attribute (c_parser *parser, bool for_tm)
5709{
5710 c_token *token = c_parser_peek_token (parser);
5711 tree ns, name, attribute;
5712
5713 /* Parse the attribute-token. */
5714 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
5715 {
5716 c_parser_error (parser, gmsgid: "expected identifier");
5717 return error_mark_node;
5718 }
5719 name = canonicalize_attr_name (attr_name: token->value);
5720 c_parser_consume_token (parser);
5721 if (c_parser_next_token_is (parser, type: CPP_SCOPE)
5722 || (c_parser_next_token_is (parser, type: CPP_COLON)
5723 && (c_parser_peek_token (parser)->flags & COLON_SCOPE) != 0
5724 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
5725 {
5726 ns = name;
5727 if (c_parser_next_token_is (parser, type: CPP_COLON))
5728 c_parser_consume_token (parser);
5729 c_parser_consume_token (parser);
5730 token = c_parser_peek_token (parser);
5731 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
5732 {
5733 c_parser_error (parser, gmsgid: "expected identifier");
5734 return error_mark_node;
5735 }
5736 name = canonicalize_attr_name (attr_name: token->value);
5737 c_parser_consume_token (parser);
5738 }
5739 else
5740 ns = NULL_TREE;
5741 attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
5742
5743 /* Parse the arguments, if any. */
5744 const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
5745 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5746 {
5747 if ((flag_openmp || flag_openmp_simd)
5748 && ns
5749 && is_attribute_p (attr_name: "omp", ident: ns)
5750 && (is_attribute_p (attr_name: "directive", ident: name)
5751 || is_attribute_p (attr_name: "sequence", ident: name)
5752 || is_attribute_p (attr_name: "decl", ident: name)))
5753 {
5754 error ("%<omp::%E%> attribute requires argument", name);
5755 return error_mark_node;
5756 }
5757 goto out;
5758 }
5759 {
5760 location_t open_loc = c_parser_peek_token (parser)->location;
5761 matching_parens parens;
5762 parens.consume_open (parser);
5763 if ((as && as->max_length == 0)
5764 /* Special-case the transactional-memory attribute "outer",
5765 which is specially handled but not registered as an
5766 attribute, to avoid allowing arbitrary balanced token
5767 sequences as arguments. */
5768 || is_attribute_p (attr_name: "outer", ident: name))
5769 {
5770 error_at (open_loc, "%qE attribute does not take any arguments", name);
5771 parens.skip_until_found_close (parser);
5772 return error_mark_node;
5773 }
5774 /* If this is a fake attribute created to handle -Wno-attributes,
5775 we must skip parsing the arguments. */
5776 if (as && !attribute_ignored_p (as))
5777 {
5778 bool takes_identifier
5779 = (ns != NULL_TREE
5780 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
5781 && attribute_takes_identifier_p (name));
5782 bool require_string
5783 = (ns == NULL_TREE
5784 && (strcmp (IDENTIFIER_POINTER (name), s2: "deprecated") == 0
5785 || strcmp (IDENTIFIER_POINTER (name), s2: "nodiscard") == 0));
5786 bool assume_attr
5787 = (ns != NULL_TREE
5788 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
5789 && strcmp (IDENTIFIER_POINTER (name), s2: "assume") == 0);
5790 TREE_VALUE (attribute)
5791 = c_parser_attribute_arguments (parser, takes_identifier,
5792 require_string, assume_attr, allow_empty_args: false);
5793 }
5794 else
5795 {
5796 if ((flag_openmp || flag_openmp_simd)
5797 && ns
5798 && is_attribute_p (attr_name: "omp", ident: ns))
5799 {
5800 if (is_attribute_p (attr_name: "directive", ident: name))
5801 {
5802 c_parser_omp_directive_args (parser, attribute, decl_p: false);
5803 parens.skip_until_found_close (parser);
5804 return attribute;
5805 }
5806 else if (is_attribute_p (attr_name: "decl", ident: name))
5807 {
5808 TREE_VALUE (TREE_PURPOSE (attribute))
5809 = get_identifier ("directive");
5810 c_parser_omp_directive_args (parser, attribute, decl_p: true);
5811 parens.skip_until_found_close (parser);
5812 return attribute;
5813 }
5814 else if (is_attribute_p (attr_name: "sequence", ident: name))
5815 {
5816 TREE_VALUE (TREE_PURPOSE (attribute))
5817 = get_identifier ("directive");
5818 c_parser_omp_sequence_args (parser, attribute);
5819 parens.skip_until_found_close (parser);
5820 TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
5821 return attribute;
5822 }
5823 }
5824 c_parser_balanced_token_sequence (parser);
5825 }
5826 parens.require_close (parser);
5827 }
5828 out:
5829 if (ns == NULL_TREE && !for_tm && !as)
5830 {
5831 /* An attribute with standard syntax and no namespace specified
5832 is a constraint violation if it is not one of the known
5833 standard attributes. Diagnose it here with a pedwarn and
5834 then discard it to prevent a duplicate warning later. */
5835 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
5836 name);
5837 return error_mark_node;
5838 }
5839 return attribute;
5840}
5841
5842static tree
5843c_parser_std_attribute_list (c_parser *parser, bool for_tm)
5844{
5845 tree attributes = NULL_TREE;
5846 while (true)
5847 {
5848 c_token *token = c_parser_peek_token (parser);
5849 if (token->type == CPP_CLOSE_SQUARE)
5850 break;
5851 if (token->type == CPP_COMMA)
5852 {
5853 c_parser_consume_token (parser);
5854 continue;
5855 }
5856 tree attribute = c_parser_std_attribute (parser, for_tm);
5857 if (attribute != error_mark_node)
5858 {
5859 TREE_CHAIN (attribute) = attributes;
5860 attributes = attribute;
5861 }
5862 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5863 break;
5864 }
5865 return attributes;
5866}
5867
5868static tree
5869c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
5870{
5871 location_t loc = c_parser_peek_token (parser)->location;
5872 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
5873 return NULL_TREE;
5874 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
5875 {
5876 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5877 return NULL_TREE;
5878 }
5879 tree attributes;
5880 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
5881 {
5882 auto ext = disable_extension_diagnostics ();
5883 c_parser_consume_token (parser);
5884 attributes = c_parser_std_attribute_list (parser, for_tm);
5885 restore_extension_diagnostics (flags: ext);
5886 }
5887 else
5888 {
5889 if (!for_tm)
5890 pedwarn_c11 (loc, opt: OPT_Wpedantic,
5891 "ISO C does not support %<[[]]%> attributes before C23");
5892 attributes = c_parser_std_attribute_list (parser, for_tm);
5893 }
5894 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5895 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5896 return nreverse (attributes);
5897}
5898
5899/* Look past an optional balanced token sequence of raw look-ahead
5900 tokens starting with the *Nth token. *N is updated to point to the
5901 following token. Return true if such a sequence was found, false
5902 if the tokens parsed were not balanced. */
5903
5904static bool
5905c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
5906{
5907 while (true)
5908 {
5909 c_token *token = c_parser_peek_nth_token_raw (parser, n: *n);
5910 switch (token->type)
5911 {
5912 case CPP_OPEN_BRACE:
5913 {
5914 ++*n;
5915 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5916 {
5917 token = c_parser_peek_nth_token_raw (parser, n: *n);
5918 if (token->type == CPP_CLOSE_BRACE)
5919 ++*n;
5920 else
5921 return false;
5922 }
5923 else
5924 return false;
5925 break;
5926 }
5927
5928 case CPP_OPEN_PAREN:
5929 {
5930 ++*n;
5931 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5932 {
5933 token = c_parser_peek_nth_token_raw (parser, n: *n);
5934 if (token->type == CPP_CLOSE_PAREN)
5935 ++*n;
5936 else
5937 return false;
5938 }
5939 else
5940 return false;
5941 break;
5942 }
5943
5944 case CPP_OPEN_SQUARE:
5945 {
5946 ++*n;
5947 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5948 {
5949 token = c_parser_peek_nth_token_raw (parser, n: *n);
5950 if (token->type == CPP_CLOSE_SQUARE)
5951 ++*n;
5952 else
5953 return false;
5954 }
5955 else
5956 return false;
5957 break;
5958 }
5959
5960 case CPP_CLOSE_BRACE:
5961 case CPP_CLOSE_PAREN:
5962 case CPP_CLOSE_SQUARE:
5963 case CPP_EOF:
5964 return true;
5965
5966 default:
5967 ++*n;
5968 break;
5969 }
5970 }
5971}
5972
5973/* Return whether standard attributes start with the Nth token. */
5974
5975static bool
5976c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
5977{
5978 if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
5979 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_OPEN_SQUARE))
5980 return false;
5981 /* In C, '[[' must start attributes. In Objective-C, we need to
5982 check whether '[[' is matched by ']]'. */
5983 if (!c_dialect_objc ())
5984 return true;
5985 n += 2;
5986 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
5987 return false;
5988 c_token *token = c_parser_peek_nth_token_raw (parser, n);
5989 if (token->type != CPP_CLOSE_SQUARE)
5990 return false;
5991 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
5992 return token->type == CPP_CLOSE_SQUARE;
5993}
5994
5995static tree
5996c_parser_std_attribute_specifier_sequence (c_parser *parser)
5997{
5998 tree attributes = NULL_TREE;
5999 do
6000 {
6001 tree attrs = c_parser_std_attribute_specifier (parser, for_tm: false);
6002 attributes = chainon (attributes, attrs);
6003 }
6004 while (c_parser_nth_token_starts_std_attributes (parser, n: 1));
6005 return attributes;
6006}
6007
6008/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6009 says whether alignment specifiers are OK (only in cases that might
6010 be the type name of a compound literal).
6011
6012 type-name:
6013 specifier-qualifier-list abstract-declarator[opt]
6014*/
6015
6016struct c_type_name *
6017c_parser_type_name (c_parser *parser, bool alignas_ok)
6018{
6019 struct c_declspecs *specs = build_null_declspecs ();
6020 struct c_declarator *declarator;
6021 struct c_type_name *ret;
6022 bool dummy = false;
6023 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true, alignspec_ok: alignas_ok, auto_type_ok: false,
6024 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_type);
6025 if (!specs->declspecs_seen_p)
6026 {
6027 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
6028 return NULL;
6029 }
6030 if (specs->type != error_mark_node)
6031 {
6032 pending_xref_error ();
6033 finish_declspecs (specs);
6034 }
6035 declarator = c_parser_declarator (parser,
6036 type_seen_p: specs->typespec_kind != ctsk_none,
6037 kind: C_DTR_ABSTRACT, seen_id: &dummy);
6038 if (declarator == NULL)
6039 return NULL;
6040 ret = XOBNEW (&parser_obstack, struct c_type_name);
6041 ret->specs = specs;
6042 ret->declarator = declarator;
6043 return ret;
6044}
6045
6046/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6047
6048 initializer:
6049 assignment-expression
6050 { initializer-list }
6051 { initializer-list , }
6052
6053 initializer-list:
6054 designation[opt] initializer
6055 initializer-list , designation[opt] initializer
6056
6057 designation:
6058 designator-list =
6059
6060 designator-list:
6061 designator
6062 designator-list designator
6063
6064 designator:
6065 array-designator
6066 . identifier
6067
6068 array-designator:
6069 [ constant-expression ]
6070
6071 GNU extensions:
6072
6073 initializer:
6074 { }
6075
6076 designation:
6077 array-designator
6078 identifier :
6079
6080 array-designator:
6081 [ constant-expression ... constant-expression ]
6082
6083 Any expression without commas is accepted in the syntax for the
6084 constant-expressions, with non-constant expressions rejected later.
6085
6086 DECL is the declaration we're parsing this initializer for.
6087
6088 This function is only used for top-level initializers; for nested
6089 ones, see c_parser_initval. */
6090
6091static struct c_expr
6092c_parser_initializer (c_parser *parser, tree decl)
6093{
6094 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
6095 return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
6096 else
6097 {
6098 struct c_expr ret;
6099 location_t loc = c_parser_peek_token (parser)->location;
6100 ret = c_parser_expr_no_commas (parser, NULL);
6101 if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6102 {
6103 error_at (loc,
6104 "variable-sized object may not be initialized except "
6105 "with an empty initializer");
6106 ret.set_error ();
6107 }
6108 /* This is handled mostly by gimplify.cc, but we have to deal with
6109 not warning about int x = x; as it is a GCC extension to turn off
6110 this warning but only if warn_init_self is zero. */
6111 if (VAR_P (decl)
6112 && !DECL_EXTERNAL (decl)
6113 && !TREE_STATIC (decl)
6114 && ret.value == decl
6115 && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), opt: OPT_Winit_self))
6116 suppress_warning (decl, OPT_Winit_self);
6117 if (TREE_CODE (ret.value) != STRING_CST
6118 && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6119 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6120 (ret.value))))
6121 ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6122 return ret;
6123 }
6124}
6125
6126/* The location of the last comma within the current initializer list,
6127 or UNKNOWN_LOCATION if not within one. */
6128
6129location_t last_init_list_comma;
6130
6131/* Parse a braced initializer list. TYPE is the type specified for a
6132 compound literal, and NULL_TREE for other initializers and for
6133 nested braced lists. NESTED_P is true for nested braced lists,
6134 false for the list of a compound literal or the list that is the
6135 top-level initializer in a declaration. DECL is the declaration for
6136 the top-level initializer for a declaration, otherwise NULL_TREE. */
6137
6138static struct c_expr
6139c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6140 struct obstack *outer_obstack, tree decl)
6141{
6142 struct c_expr ret;
6143 struct obstack braced_init_obstack;
6144 location_t brace_loc = c_parser_peek_token (parser)->location;
6145 gcc_obstack_init (&braced_init_obstack);
6146 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6147 bool save_c_omp_array_section_p = c_omp_array_section_p;
6148 c_omp_array_section_p = false;
6149 matching_braces braces;
6150 braces.consume_open (parser);
6151 if (nested_p)
6152 {
6153 finish_implicit_inits (brace_loc, outer_obstack);
6154 push_init_level (brace_loc, 0, &braced_init_obstack);
6155 }
6156 else
6157 really_start_incremental_init (type);
6158 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6159 {
6160 pedwarn_c11 (brace_loc, opt: OPT_Wpedantic,
6161 "ISO C forbids empty initializer braces before C23");
6162 }
6163 else
6164 {
6165 if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6166 error_at (brace_loc,
6167 "variable-sized object may not be initialized except "
6168 "with an empty initializer");
6169 /* Parse a non-empty initializer list, possibly with a trailing
6170 comma. */
6171 while (true)
6172 {
6173 c_parser_initelt (parser, &braced_init_obstack);
6174 if (parser->error)
6175 break;
6176 if (c_parser_next_token_is (parser, type: CPP_COMMA))
6177 {
6178 last_init_list_comma = c_parser_peek_token (parser)->location;
6179 c_parser_consume_token (parser);
6180 }
6181 else
6182 break;
6183 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6184 break;
6185 }
6186 }
6187 c_omp_array_section_p = save_c_omp_array_section_p;
6188 c_token *next_tok = c_parser_peek_token (parser);
6189 if (next_tok->type != CPP_CLOSE_BRACE)
6190 {
6191 ret.set_error ();
6192 ret.original_code = ERROR_MARK;
6193 ret.original_type = NULL;
6194 braces.skip_until_found_close (parser);
6195 pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6196 obstack_free (&braced_init_obstack, NULL);
6197 return ret;
6198 }
6199 location_t close_loc = next_tok->location;
6200 c_parser_consume_token (parser);
6201 ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6202 obstack_free (&braced_init_obstack, NULL);
6203 set_c_expr_source_range (expr: &ret, start: brace_loc, finish: close_loc);
6204 return ret;
6205}
6206
6207/* Parse a nested initializer, including designators. */
6208
6209static void
6210c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6211{
6212 /* Parse any designator or designator list. A single array
6213 designator may have the subsequent "=" omitted in GNU C, but a
6214 longer list or a structure member designator may not. */
6215 if (c_parser_next_token_is (parser, type: CPP_NAME)
6216 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6217 {
6218 /* Old-style structure member designator. */
6219 set_init_label (c_parser_peek_token (parser)->location,
6220 c_parser_peek_token (parser)->value,
6221 c_parser_peek_token (parser)->location,
6222 braced_init_obstack);
6223 /* Use the colon as the error location. */
6224 pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6225 "obsolete use of designated initializer with %<:%>");
6226 c_parser_consume_token (parser);
6227 c_parser_consume_token (parser);
6228 }
6229 else
6230 {
6231 /* des_seen is 0 if there have been no designators, 1 if there
6232 has been a single array designator and 2 otherwise. */
6233 int des_seen = 0;
6234 /* Location of a designator. */
6235 location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6236 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
6237 || c_parser_next_token_is (parser, type: CPP_DOT))
6238 {
6239 int des_prev = des_seen;
6240 if (!des_seen)
6241 des_loc = c_parser_peek_token (parser)->location;
6242 if (des_seen < 2)
6243 des_seen++;
6244 if (c_parser_next_token_is (parser, type: CPP_DOT))
6245 {
6246 des_seen = 2;
6247 c_parser_consume_token (parser);
6248 if (c_parser_next_token_is (parser, type: CPP_NAME))
6249 {
6250 set_init_label (des_loc, c_parser_peek_token (parser)->value,
6251 c_parser_peek_token (parser)->location,
6252 braced_init_obstack);
6253 c_parser_consume_token (parser);
6254 }
6255 else
6256 {
6257 struct c_expr init;
6258 init.set_error ();
6259 init.original_code = ERROR_MARK;
6260 init.original_type = NULL;
6261 c_parser_error (parser, gmsgid: "expected identifier");
6262 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6263 process_init_element (input_location, init, false,
6264 braced_init_obstack);
6265 return;
6266 }
6267 }
6268 else
6269 {
6270 struct c_expr first_expr;
6271 tree first, second;
6272 location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6273 location_t array_index_loc = UNKNOWN_LOCATION;
6274 /* ??? Following the old parser, [ objc-receiver
6275 objc-message-args ] is accepted as an initializer,
6276 being distinguished from a designator by what follows
6277 the first assignment expression inside the square
6278 brackets, but after a first array designator a
6279 subsequent square bracket is for Objective-C taken to
6280 start an expression, using the obsolete form of
6281 designated initializer without '=', rather than
6282 possibly being a second level of designation: in LALR
6283 terms, the '[' is shifted rather than reducing
6284 designator to designator-list. */
6285 if (des_prev == 1 && c_dialect_objc ())
6286 {
6287 des_seen = des_prev;
6288 break;
6289 }
6290 if (des_prev == 0 && c_dialect_objc ())
6291 {
6292 /* This might be an array designator or an
6293 Objective-C message expression. If the former,
6294 continue parsing here; if the latter, parse the
6295 remainder of the initializer given the starting
6296 primary-expression. ??? It might make sense to
6297 distinguish when des_prev == 1 as well; see
6298 previous comment. */
6299 tree rec, args;
6300 struct c_expr mexpr;
6301 c_parser_consume_token (parser);
6302 if (c_parser_peek_token (parser)->type == CPP_NAME
6303 && ((c_parser_peek_token (parser)->id_kind
6304 == C_ID_TYPENAME)
6305 || (c_parser_peek_token (parser)->id_kind
6306 == C_ID_CLASSNAME)))
6307 {
6308 /* Type name receiver. */
6309 tree id = c_parser_peek_token (parser)->value;
6310 c_parser_consume_token (parser);
6311 rec = objc_get_class_reference (id);
6312 goto parse_message_args;
6313 }
6314 array_index_loc = c_parser_peek_token (parser)->location;
6315 first_expr = c_parser_expr_no_commas (parser, NULL);
6316 mark_exp_read (first_expr.value);
6317 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS)
6318 || c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6319 goto array_desig_after_first;
6320 first = first_expr.value;
6321 /* Expression receiver. So far only one part
6322 without commas has been parsed; there might be
6323 more of the expression. */
6324 rec = first;
6325 while (c_parser_next_token_is (parser, type: CPP_COMMA))
6326 {
6327 struct c_expr next;
6328 location_t comma_loc, exp_loc;
6329 comma_loc = c_parser_peek_token (parser)->location;
6330 c_parser_consume_token (parser);
6331 exp_loc = c_parser_peek_token (parser)->location;
6332 next = c_parser_expr_no_commas (parser, NULL);
6333 next = convert_lvalue_to_rvalue (exp_loc, next,
6334 true, true);
6335 rec = build_compound_expr (comma_loc, rec, next.value);
6336 }
6337 parse_message_args:
6338 /* Now parse the objc-message-args. */
6339 args = c_parser_objc_message_args (parser);
6340 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6341 msgid: "expected %<]%>");
6342 mexpr.value
6343 = objc_build_message_expr (rec, args);
6344 mexpr.original_code = ERROR_MARK;
6345 mexpr.original_type = NULL;
6346 mexpr.m_decimal = 0;
6347 /* Now parse and process the remainder of the
6348 initializer, starting with this message
6349 expression as a primary-expression. */
6350 c_parser_initval (parser, &mexpr, braced_init_obstack);
6351 return;
6352 }
6353 c_parser_consume_token (parser);
6354 array_index_loc = c_parser_peek_token (parser)->location;
6355 first_expr = c_parser_expr_no_commas (parser, NULL);
6356 mark_exp_read (first_expr.value);
6357 array_desig_after_first:
6358 first_expr = convert_lvalue_to_rvalue (array_index_loc,
6359 first_expr,
6360 true, true);
6361 first = first_expr.value;
6362 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
6363 {
6364 ellipsis_loc = c_parser_peek_token (parser)->location;
6365 c_parser_consume_token (parser);
6366 second = convert_lvalue_to_rvalue (ellipsis_loc,
6367 (c_parser_expr_no_commas
6368 (parser, NULL)),
6369 true, true).value;
6370 mark_exp_read (second);
6371 }
6372 else
6373 second = NULL_TREE;
6374 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6375 {
6376 c_parser_consume_token (parser);
6377 set_init_index (array_index_loc, first, second,
6378 braced_init_obstack);
6379 if (second)
6380 pedwarn (ellipsis_loc, OPT_Wpedantic,
6381 "ISO C forbids specifying range of elements to initialize");
6382 }
6383 else
6384 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6385 msgid: "expected %<]%>");
6386 }
6387 }
6388 if (des_seen >= 1)
6389 {
6390 if (c_parser_next_token_is (parser, type: CPP_EQ))
6391 {
6392 pedwarn_c90 (des_loc, opt: OPT_Wpedantic,
6393 "ISO C90 forbids specifying subobject "
6394 "to initialize");
6395 c_parser_consume_token (parser);
6396 }
6397 else
6398 {
6399 if (des_seen == 1)
6400 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6401 "obsolete use of designated initializer without %<=%>");
6402 else
6403 {
6404 struct c_expr init;
6405 init.set_error ();
6406 init.original_code = ERROR_MARK;
6407 init.original_type = NULL;
6408 c_parser_error (parser, gmsgid: "expected %<=%>");
6409 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6410 process_init_element (input_location, init, false,
6411 braced_init_obstack);
6412 return;
6413 }
6414 }
6415 }
6416 }
6417 c_parser_initval (parser, NULL, braced_init_obstack);
6418}
6419
6420/* Parse a nested initializer; as c_parser_initializer but parses
6421 initializers within braced lists, after any designators have been
6422 applied. If AFTER is not NULL then it is an Objective-C message
6423 expression which is the primary-expression starting the
6424 initializer. */
6425
6426static void
6427c_parser_initval (c_parser *parser, struct c_expr *after,
6428 struct obstack * braced_init_obstack)
6429{
6430 struct c_expr init;
6431 gcc_assert (!after || c_dialect_objc ());
6432 location_t loc = c_parser_peek_token (parser)->location;
6433
6434 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE) && !after)
6435 init = c_parser_braced_init (parser, NULL_TREE, nested_p: true,
6436 outer_obstack: braced_init_obstack, NULL_TREE);
6437 else
6438 {
6439 init = c_parser_expr_no_commas (parser, after);
6440 if (init.value != NULL_TREE
6441 && TREE_CODE (init.value) != STRING_CST
6442 && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6443 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6444 (init.value))))
6445 init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6446 }
6447 process_init_element (loc, init, false, braced_init_obstack);
6448}
6449
6450/* Parse a compound statement (possibly a function body) (C90 6.6.2,
6451 C99 6.8.2, C11 6.8.2, C23 6.8.2).
6452
6453 compound-statement:
6454 { block-item-list[opt] }
6455 { label-declarations block-item-list }
6456
6457 block-item-list:
6458 block-item
6459 block-item-list block-item
6460
6461 block-item:
6462 label
6463 nested-declaration
6464 statement
6465
6466 nested-declaration:
6467 declaration
6468
6469 GNU extensions:
6470
6471 compound-statement:
6472 { label-declarations block-item-list }
6473
6474 nested-declaration:
6475 __extension__ nested-declaration
6476 nested-function-definition
6477
6478 label-declarations:
6479 label-declaration
6480 label-declarations label-declaration
6481
6482 label-declaration:
6483 __label__ identifier-list ;
6484
6485 Allowing the mixing of declarations and code is new in C99. The
6486 GNU syntax also permits (not shown above) labels at the end of
6487 compound statements, which yield an error. We don't allow labels
6488 on declarations; this might seem like a natural extension, but
6489 there would be a conflict between gnu-attributes on the label and
6490 prefix gnu-attributes on the declaration. ??? The syntax follows the
6491 old parser in requiring something after label declarations.
6492 Although they are erroneous if the labels declared aren't defined,
6493 is it useful for the syntax to be this way?
6494
6495 OpenACC:
6496
6497 block-item:
6498 openacc-directive
6499
6500 openacc-directive:
6501 update-directive
6502
6503 OpenMP:
6504
6505 block-item:
6506 openmp-directive
6507
6508 openmp-directive:
6509 barrier-directive
6510 flush-directive
6511 taskwait-directive
6512 taskyield-directive
6513 cancel-directive
6514 cancellation-point-directive */
6515
6516static tree
6517c_parser_compound_statement (c_parser *parser, location_t *endlocp)
6518{
6519 tree stmt;
6520 location_t brace_loc;
6521 brace_loc = c_parser_peek_token (parser)->location;
6522 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
6523 {
6524 /* Ensure a scope is entered and left anyway to avoid confusion
6525 if we have just prepared to enter a function body. */
6526 stmt = c_begin_compound_stmt (true);
6527 c_end_compound_stmt (brace_loc, stmt, true);
6528 return error_mark_node;
6529 }
6530 stmt = c_begin_compound_stmt (true);
6531 location_t end_loc = c_parser_compound_statement_nostart (parser);
6532 if (endlocp)
6533 *endlocp = end_loc;
6534
6535 return c_end_compound_stmt (brace_loc, stmt, true);
6536}
6537
6538/* Diagnose errors related to imperfectly nested loops in an OMP
6539 loop construct. This function is called when such code is seen.
6540 Only issue one such diagnostic no matter how much invalid
6541 intervening code there is in the loop.
6542 FIXME: maybe the location associated with the diagnostic should
6543 be the current parser token instead of the location of the outer loop
6544 nest. */
6545
6546static void
6547check_omp_intervening_code (c_parser *parser)
6548{
6549 struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
6550 gcc_assert (omp_for_parse_state);
6551
6552 if (!omp_for_parse_state->in_intervening_code)
6553 return;
6554 omp_for_parse_state->saw_intervening_code = true;
6555
6556 /* Only diagnose errors related to perfect nesting once. */
6557 if (!omp_for_parse_state->perfect_nesting_fail)
6558 {
6559
6560 /* OpenACC does not (yet) permit intervening code, in
6561 addition to situations forbidden by the OpenMP spec. */
6562 if (omp_for_parse_state->code == OACC_LOOP)
6563 {
6564 error_at (omp_for_parse_state->for_loc,
6565 "inner loops must be perfectly nested in "
6566 "%<#pragma acc loop%>");
6567 omp_for_parse_state->perfect_nesting_fail = true;
6568 }
6569 else if (omp_for_parse_state->ordered)
6570 {
6571 error_at (omp_for_parse_state->for_loc,
6572 "inner loops must be perfectly nested with "
6573 "%<ordered%> clause");
6574 omp_for_parse_state->perfect_nesting_fail = true;
6575 }
6576 else if (omp_for_parse_state->inscan)
6577 {
6578 error_at (omp_for_parse_state->for_loc,
6579 "inner loops must be perfectly nested with "
6580 "%<reduction%> %<inscan%> clause");
6581 omp_for_parse_state->perfect_nesting_fail = true;
6582 }
6583 /* TODO: Also reject loops with TILE directive. */
6584 if (omp_for_parse_state->perfect_nesting_fail)
6585 omp_for_parse_state->fail = true;
6586 }
6587}
6588
6589/* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
6590 and add the statement to the current list. If SL is an empty statement
6591 list, do nothing. */
6592static void
6593add_structured_block_stmt (tree sl)
6594{
6595 if (TREE_CODE (sl) != STATEMENT_LIST
6596 || !tsi_end_p (i: tsi_start (t: sl)))
6597 add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
6598}
6599
6600struct c_omp_attribute_data
6601{
6602 vec<c_token, va_gc> *tokens;
6603 const c_omp_directive *dir;
6604 c_omp_directive_kind kind;
6605};
6606
6607/* Handle omp::directive and omp::sequence attributes in ATTRS
6608 (if any) at the start of a statement or in attribute-declaration. */
6609
6610static bool
6611c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
6612 bool *have_std_attrs)
6613{
6614 if (!flag_openmp && !flag_openmp_simd)
6615 return false;
6616
6617 auto_vec<c_omp_attribute_data, 16> vd;
6618 int cnt = 0;
6619 int tokens = 0;
6620 bool bad = false;
6621 for (tree *pa = &attrs; *pa; )
6622 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6623 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
6624 {
6625 cnt++;
6626 for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
6627 {
6628 tree d = TREE_VALUE (a);
6629 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
6630 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
6631 c_token *first = toks->address ();
6632 c_token *last = first + toks->length ();
6633 if (parser->omp_attrs_forbidden_p)
6634 {
6635 error_at (first->location,
6636 "mixing OpenMP directives with attribute and pragma "
6637 "syntax on the same statement");
6638 parser->omp_attrs_forbidden_p = false;
6639 bad = true;
6640 }
6641 else if (TREE_PUBLIC (d))
6642 {
6643 error_at (first->location,
6644 "OpenMP %<omp::decl%> attribute on a statement");
6645 bad = true;
6646 }
6647 const char *directive[3] = {};
6648 for (int i = 0; i < 3; i++)
6649 {
6650 tree id = NULL_TREE;
6651 if (first + i == last)
6652 break;
6653 if (first[i].type == CPP_NAME)
6654 id = first[i].value;
6655 else if (first[i].type == CPP_KEYWORD)
6656 id = ridpointers[(int) first[i].keyword];
6657 else
6658 break;
6659 directive[i] = IDENTIFIER_POINTER (id);
6660 }
6661 const c_omp_directive *dir = NULL;
6662 if (directive[0])
6663 dir = c_omp_categorize_directive (directive[0], directive[1],
6664 directive[2]);
6665 if (dir == NULL)
6666 {
6667 error_at (first->location,
6668 "unknown OpenMP directive name in %qs attribute "
6669 "argument",
6670 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
6671 continue;
6672 }
6673 c_omp_directive_kind kind = dir->kind;
6674 if (dir->id == PRAGMA_OMP_ORDERED)
6675 {
6676 /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
6677 depend/doacross clause. */
6678 if (directive[1]
6679 && (strcmp (s1: directive[1], s2: "depend") == 0
6680 || strcmp (s1: directive[1], s2: "doacross") == 0))
6681 kind = C_OMP_DIR_STANDALONE;
6682 else if (first + 2 < last
6683 && first[1].type == CPP_COMMA
6684 && first[2].type == CPP_NAME
6685 && (strcmp (IDENTIFIER_POINTER (first[2].value),
6686 s2: "depend") == 0
6687 || strcmp (IDENTIFIER_POINTER (first[2].value),
6688 s2: "doacross") == 0))
6689 kind = C_OMP_DIR_STANDALONE;
6690 }
6691 else if (dir->id == PRAGMA_OMP_ERROR)
6692 {
6693 /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
6694 int paren_depth = 0;
6695 for (int i = 1; first + i < last; i++)
6696 if (first[i].type == CPP_OPEN_PAREN)
6697 paren_depth++;
6698 else if (first[i].type == CPP_CLOSE_PAREN)
6699 paren_depth--;
6700 else if (paren_depth == 0
6701 && first + i + 2 < last
6702 && first[i].type == CPP_NAME
6703 && first[i + 1].type == CPP_OPEN_PAREN
6704 && first[i + 2].type == CPP_NAME
6705 && !strcmp (IDENTIFIER_POINTER (first[i].value),
6706 s2: "at")
6707 && !strcmp (IDENTIFIER_POINTER (first[i
6708 + 2].value),
6709 s2: "execution"))
6710 {
6711 kind = C_OMP_DIR_STANDALONE;
6712 break;
6713 }
6714 }
6715 c_omp_attribute_data v = { .tokens: toks, .dir: dir, .kind: kind };
6716 vd.safe_push (obj: v);
6717 if (flag_openmp || dir->simd)
6718 tokens += (last - first) + 1;
6719 }
6720 c_omp_attribute_data v = {};
6721 vd.safe_push (obj: v);
6722 *pa = TREE_CHAIN (*pa);
6723 }
6724 else
6725 pa = &TREE_CHAIN (*pa);
6726
6727 if (bad)
6728 {
6729 fail:
6730 if (have_std_attrs && attrs == NULL)
6731 *have_std_attrs = false;
6732 return false;
6733 }
6734
6735 unsigned int i;
6736 c_omp_attribute_data *v;
6737 c_omp_attribute_data *construct_seen = nullptr;
6738 c_omp_attribute_data *standalone_seen = nullptr;
6739 c_omp_attribute_data *prev_standalone_seen = nullptr;
6740 FOR_EACH_VEC_ELT (vd, i, v)
6741 if (v->tokens)
6742 {
6743 if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
6744 construct_seen = v;
6745 else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
6746 standalone_seen = v;
6747 }
6748 else
6749 {
6750 if (standalone_seen && !prev_standalone_seen)
6751 {
6752 prev_standalone_seen = standalone_seen;
6753 standalone_seen = nullptr;
6754 }
6755 }
6756
6757 if (cnt > 1 && construct_seen)
6758 {
6759 error_at ((*construct_seen->tokens)[0].location,
6760 "OpenMP construct among %<omp::directive%> attributes"
6761 " requires all %<omp::directive%> attributes on the"
6762 " same statement to be in the same %<omp::sequence%>");
6763 goto fail;
6764 }
6765 if (cnt > 1 && standalone_seen && prev_standalone_seen)
6766 {
6767 error_at ((*standalone_seen->tokens)[0].location,
6768 "multiple OpenMP standalone directives among"
6769 " %<omp::directive%> attributes must be all within the"
6770 " same %<omp::sequence%>");
6771 goto fail;
6772 }
6773
6774 if (prev_standalone_seen)
6775 standalone_seen = prev_standalone_seen;
6776 if (standalone_seen
6777 && !c_parser_next_token_is (parser, type: CPP_SEMICOLON))
6778 {
6779 error_at (standalone_seen->tokens->address ()->location,
6780 "standalone OpenMP directives in %<omp::directive%> attribute"
6781 " can only appear on an empty statement");
6782 goto fail;
6783 }
6784 if (cnt && c_parser_next_token_is (parser, type: CPP_PRAGMA))
6785 {
6786 c_token *token = c_parser_peek_token (parser);
6787 enum pragma_kind kind = token->pragma_kind;
6788 if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
6789 {
6790 error_at (token->location,
6791 "mixing OpenMP directives with attribute and pragma "
6792 "syntax on the same statement");
6793 goto fail;
6794 }
6795 }
6796
6797 if (!tokens)
6798 return false;
6799
6800 unsigned int tokens_avail = parser->tokens_avail;
6801 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
6802
6803 tokens++;
6804 vec<c_token, va_gc> *toks = NULL;
6805 vec_safe_reserve (v&: toks, nelems: tokens, exact: true);
6806 FOR_EACH_VEC_ELT (vd, i, v)
6807 {
6808 if (!v->tokens)
6809 continue;
6810 if (!flag_openmp && !v->dir->simd)
6811 continue;
6812 c_token *first = v->tokens->address ();
6813 c_token *last = first + v->tokens->length ();
6814 c_token tok = {};
6815 tok.type = CPP_PRAGMA;
6816 tok.keyword = RID_MAX;
6817 tok.pragma_kind = pragma_kind (v->dir->id);
6818 tok.location = first->location;
6819 toks->quick_push (obj: tok);
6820 while (++first < last)
6821 toks->quick_push (obj: *first);
6822 tok = {};
6823 tok.type = CPP_PRAGMA_EOL;
6824 tok.keyword = RID_MAX;
6825 tok.location = last[-1].location;
6826 toks->quick_push (obj: tok);
6827 }
6828
6829 c_token tok = {};
6830 tok.type = CPP_EOF;
6831 tok.keyword = RID_MAX;
6832 tok.location = toks->last ().location;
6833 tok.flags = tokens_avail;
6834 toks->quick_push (obj: tok);
6835
6836 parser->tokens = toks->address ();
6837 parser->tokens_avail = tokens;
6838 parser->in_omp_attribute_pragma = toks;
6839 return true;
6840}
6841
6842/* Handle omp::directive and omp::sequence attributes in ATTRS
6843 (if any) at the start or after declaration-id of a declaration. */
6844
6845static void
6846c_parser_handle_directive_omp_attributes (tree &attrs,
6847 vec<c_token> *&pragma_clauses,
6848 vec<c_token> *attr_clauses)
6849{
6850 if (!flag_openmp && !flag_openmp_simd)
6851 return;
6852
6853 for (tree *pa = &attrs; *pa; )
6854 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6855 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
6856 {
6857 int cnt = 0;
6858 for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
6859 {
6860 tree a = *pa2;
6861 tree d = TREE_VALUE (a);
6862 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
6863 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
6864 c_token *first = toks->address ();
6865 c_token *last = first + toks->length ();
6866 const char *directive[3] = {};
6867 for (int i = 0; i < 3; i++)
6868 {
6869 tree id = NULL_TREE;
6870 if (first + i == last)
6871 break;
6872 if (first[i].type == CPP_NAME)
6873 id = first[i].value;
6874 else if (first[i].type == CPP_KEYWORD)
6875 id = ridpointers[(int) first[i].keyword];
6876 else
6877 break;
6878 directive[i] = IDENTIFIER_POINTER (id);
6879 }
6880 const c_omp_directive *dir = NULL;
6881 if (directive[0])
6882 dir = c_omp_categorize_directive (directive[0], directive[1],
6883 directive[2]);
6884 if (dir == NULL)
6885 {
6886 error_at (first->location,
6887 "unknown OpenMP directive name in "
6888 "%qs attribute argument",
6889 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
6890 *pa2 = TREE_CHAIN (a);
6891 }
6892 else if (dir->id == PRAGMA_OMP_DECLARE
6893 && (strcmp (s1: directive[1], s2: "simd") == 0
6894 || strcmp (s1: directive[1], s2: "variant") == 0))
6895 {
6896 if (pragma_clauses)
6897 {
6898 error_at (first->location,
6899 "mixing OpenMP directives with attribute and "
6900 "pragma syntax on the same declaration");
6901 for (pa = &attrs; *pa; )
6902 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6903 && is_attribute_p (attr_name: "directive",
6904 ident: get_attribute_name (*pa)))
6905 *pa = TREE_CHAIN (*pa);
6906 else
6907 pa = &TREE_CHAIN (*pa);
6908 return;
6909 }
6910 ++cnt;
6911 attr_clauses->reserve (nelems: attr_clauses->length ()
6912 + toks->length () + 2);
6913 for (++first; first < last; ++first)
6914 attr_clauses->quick_push (obj: *first);
6915 c_token tok = {};
6916 tok.type = CPP_PRAGMA_EOL;
6917 tok.keyword = RID_MAX;
6918 tok.location = last[-1].location;
6919 attr_clauses->quick_push (obj: tok);
6920 *pa2 = TREE_CHAIN (a);
6921 }
6922 else
6923 pa2 = &TREE_CHAIN (a);
6924 }
6925 if (cnt && TREE_VALUE (*pa) == NULL_TREE)
6926 *pa = TREE_CHAIN (*pa);
6927 else
6928 pa = &TREE_CHAIN (*pa);
6929 }
6930 else
6931 pa = &TREE_CHAIN (*pa);
6932 if (attr_clauses->length ())
6933 {
6934 c_token tok = {};
6935 tok.type = CPP_EOF;
6936 tok.keyword = RID_MAX;
6937 tok.location = attr_clauses->last ().location;
6938 attr_clauses->quick_push (obj: tok);
6939 attr_clauses->quick_push (obj: tok);
6940 pragma_clauses = attr_clauses;
6941 }
6942}
6943
6944/* Parse a compound statement except for the opening brace. This is
6945 used for parsing both compound statements and statement expressions
6946 (which follow different paths to handling the opening). */
6947
6948static location_t
6949c_parser_compound_statement_nostart (c_parser *parser)
6950{
6951 bool last_stmt = false;
6952 bool last_label = false;
6953 bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
6954 location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6955 struct omp_for_parse_data *omp_for_parse_state
6956 = parser->omp_for_parse_state;
6957 bool in_omp_loop_block
6958 = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
6959 tree sl = NULL_TREE;
6960
6961 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6962 {
6963 location_t endloc = c_parser_peek_token (parser)->location;
6964 add_debug_begin_stmt (loc: endloc);
6965 c_parser_consume_token (parser);
6966 return endloc;
6967 }
6968
6969 /* If we're parsing a {} sequence in an OMP_FOR body, start a
6970 statement list for intervening code. */
6971 if (in_omp_loop_block)
6972 sl = push_stmt_list ();
6973
6974 mark_valid_location_for_stdc_pragma (true);
6975 if (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
6976 {
6977 /* Read zero or more forward-declarations for labels that nested
6978 functions can jump to. */
6979 mark_valid_location_for_stdc_pragma (false);
6980 if (in_omp_loop_block)
6981 check_omp_intervening_code (parser);
6982 while (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
6983 {
6984 label_loc = c_parser_peek_token (parser)->location;
6985 c_parser_consume_token (parser);
6986 /* Any identifiers, including those declared as type names,
6987 are OK here. */
6988 while (true)
6989 {
6990 tree label;
6991 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
6992 {
6993 c_parser_error (parser, gmsgid: "expected identifier");
6994 break;
6995 }
6996 label
6997 = declare_label (c_parser_peek_token (parser)->value);
6998 C_DECLARED_LABEL_FLAG (label) = 1;
6999 add_stmt (build_stmt (label_loc, DECL_EXPR, label));
7000 c_parser_consume_token (parser);
7001 if (c_parser_next_token_is (parser, type: CPP_COMMA))
7002 c_parser_consume_token (parser);
7003 else
7004 break;
7005 }
7006 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7007 }
7008 pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7009 }
7010 /* We must now have at least one statement, label or declaration. */
7011 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7012 {
7013 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7014 c_parser_error (parser, gmsgid: "expected declaration or statement");
7015 location_t endloc = c_parser_peek_token (parser)->location;
7016 c_parser_consume_token (parser);
7017 return endloc;
7018 }
7019 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_BRACE))
7020 {
7021 location_t loc = c_parser_peek_token (parser)->location;
7022 loc = expansion_point_location_if_in_system_header (loc);
7023
7024 bool want_nested_loop = (omp_for_parse_state
7025 ? omp_for_parse_state->want_nested_loop
7026 : false);
7027
7028 /* First take care of special cases for OpenMP "canonical loop
7029 nest form", that do not allow standard attributes, labels, or
7030 __extension__ before the nested statement. */
7031 if (in_omp_loop_block && !last_label)
7032 {
7033 if (want_nested_loop
7034 && c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
7035 {
7036 /* Found the next nested loop. If there were intervening
7037 code statements collected before now, wrap them in an
7038 OMP_STRUCTURED_BLOCK node, and start a new structured
7039 block to hold statements that may come after the FOR. */
7040 gcc_assert (sl);
7041 add_structured_block_stmt (sl: pop_stmt_list (sl));
7042 omp_for_parse_state->depth++;
7043 add_stmt (c_parser_omp_loop_nest (parser, NULL));
7044 omp_for_parse_state->depth--;
7045 sl = push_stmt_list ();
7046 parser->error = false;
7047 continue;
7048 }
7049 else if (want_nested_loop
7050 && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7051 {
7052 /* If this nested compound statement contains the nested loop,
7053 we need to separate the other statements in the current
7054 statement into separate blocks of intervening code. If
7055 there's no nested loop, it's all part of the same
7056 chunk of intervening code. */
7057 tree pre_sl = pop_stmt_list (sl);
7058 tree nested_sl = push_stmt_list ();
7059 mark_valid_location_for_stdc_pragma (false);
7060 c_parser_statement_after_labels (parser, NULL);
7061 nested_sl = pop_stmt_list (nested_sl);
7062 if (omp_for_parse_state->want_nested_loop)
7063 {
7064 /* This block didn't contain a loop-nest, so it's
7065 all part of the same chunk of intervening code. */
7066 check_omp_intervening_code (parser);
7067 sl = push_stmt_list ();
7068 add_stmt (pre_sl);
7069 add_stmt (nested_sl);
7070 }
7071 else
7072 {
7073 /* It contains the nested loop. */
7074 add_structured_block_stmt (sl: pre_sl);
7075 add_stmt (nested_sl);
7076 sl = push_stmt_list ();
7077 }
7078 parser->error = false;
7079 continue;
7080 }
7081 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7082 {
7083 /* Prior to implementing the OpenMP 5.1 syntax for canonical
7084 loop form, GCC used to accept an empty statements that
7085 would now be flagged as intervening code. Continue to
7086 do that, as an extension. */
7087 /* FIXME: Maybe issue a warning or something here? */
7088 c_parser_consume_token (parser);
7089 continue;
7090 }
7091 }
7092
7093 /* Standard attributes may start a label, statement or declaration. */
7094 bool have_std_attrs
7095 = c_parser_nth_token_starts_std_attributes (parser, n: 1);
7096 tree std_attrs = NULL_TREE;
7097 if (have_std_attrs)
7098 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7099 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7100 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7101 || (c_parser_next_token_is (parser, type: CPP_NAME)
7102 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7103 {
7104 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7105 label_loc = c_parser_peek_2nd_token (parser)->location;
7106 else
7107 label_loc = c_parser_peek_token (parser)->location;
7108 last_label = true;
7109 last_stmt = false;
7110 mark_valid_location_for_stdc_pragma (false);
7111 if (in_omp_loop_block)
7112 check_omp_intervening_code (parser);
7113 c_parser_label (parser, std_attrs);
7114 }
7115 else if (c_parser_next_tokens_start_declaration (parser)
7116 || (have_std_attrs
7117 && !c_parser_handle_statement_omp_attributes
7118 (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7119 && c_parser_next_token_is (parser, type: CPP_SEMICOLON)
7120 && (have_std_attrs = true)))
7121 {
7122 if (last_label)
7123 pedwarn_c11 (c_parser_peek_token (parser)->location, opt: OPT_Wpedantic,
7124 "a label can only be part of a statement and "
7125 "a declaration is not a statement");
7126 /* It's unlikely we'll see a nested loop in a declaration in
7127 intervening code in an OMP loop, but disallow it anyway. */
7128 if (in_omp_loop_block)
7129 {
7130 check_omp_intervening_code (parser);
7131 omp_for_parse_state->want_nested_loop = false;
7132 }
7133 mark_valid_location_for_stdc_pragma (false);
7134 bool fallthru_attr_p = false;
7135 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: !have_std_attrs,
7136 empty_ok: true, nested: true, start_attr_ok: true, NULL,
7137 NULL, have_attrs: have_std_attrs, attrs: std_attrs,
7138 NULL, fallthru_attr_p: &fallthru_attr_p);
7139
7140 if (in_omp_loop_block)
7141 omp_for_parse_state->want_nested_loop = want_nested_loop;
7142 if (last_stmt && !fallthru_attr_p)
7143 pedwarn_c90 (loc, opt: OPT_Wdeclaration_after_statement,
7144 "ISO C90 forbids mixed declarations and code");
7145 last_stmt = fallthru_attr_p;
7146 last_label = false;
7147 }
7148 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
7149 {
7150 /* __extension__ can start a declaration, but is also an
7151 unary operator that can start an expression. Consume all
7152 but the last of a possible series of __extension__ to
7153 determine which. If standard attributes have already
7154 been seen, it must start a statement, not a declaration,
7155 but standard attributes starting a declaration may appear
7156 after __extension__. */
7157 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7158 && (c_parser_peek_2nd_token (parser)->keyword
7159 == RID_EXTENSION))
7160 c_parser_consume_token (parser);
7161 if (!have_std_attrs
7162 && (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
7163 || c_parser_nth_token_starts_std_attributes (parser, n: 2)))
7164 {
7165 int ext;
7166 ext = disable_extension_diagnostics ();
7167 c_parser_consume_token (parser);
7168 last_label = false;
7169 /* It's unlikely we'll see a nested loop in a declaration in
7170 intervening code in an OMP loop, but disallow it anyway. */
7171 if (in_omp_loop_block)
7172 {
7173 check_omp_intervening_code (parser);
7174 omp_for_parse_state->want_nested_loop = false;
7175 }
7176 mark_valid_location_for_stdc_pragma (false);
7177 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
7178 start_attr_ok: true);
7179 if (in_omp_loop_block)
7180 omp_for_parse_state->want_nested_loop = want_nested_loop;
7181 /* Following the old parser, __extension__ does not
7182 disable this diagnostic. */
7183 restore_extension_diagnostics (flags: ext);
7184 if (last_stmt)
7185 pedwarn_c90 (loc, opt: OPT_Wdeclaration_after_statement,
7186 "ISO C90 forbids mixed declarations and code");
7187 last_stmt = false;
7188 }
7189 else
7190 goto statement;
7191 }
7192 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
7193 {
7194 if (have_std_attrs && !parser->in_omp_attribute_pragma)
7195 c_parser_error (parser, gmsgid: "expected declaration or statement");
7196 else if (std_attrs)
7197 c_warn_unused_attributes (std_attrs);
7198 /* External pragmas, and some omp pragmas, are not associated
7199 with regular c code, and so are not to be considered statements
7200 syntactically. This ensures that the user doesn't put them
7201 places that would turn into syntax errors if the directive
7202 were ignored. */
7203 if (omp_for_parse_state)
7204 omp_for_parse_state->want_nested_loop = false;
7205 if (c_parser_pragma (parser,
7206 last_label ? pragma_stmt : pragma_compound,
7207 NULL))
7208 {
7209 last_label = false;
7210 last_stmt = true;
7211 if (omp_for_parse_state)
7212 check_omp_intervening_code (parser);
7213 }
7214 if (omp_for_parse_state)
7215 omp_for_parse_state->want_nested_loop = want_nested_loop;
7216 }
7217 else if (c_parser_next_token_is (parser, type: CPP_EOF))
7218 {
7219 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7220 c_parser_error (parser, gmsgid: "expected declaration or statement");
7221 return c_parser_peek_token (parser)->location;
7222 }
7223 else if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7224 {
7225 if (parser->in_if_block)
7226 {
7227 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7228 error_at (loc, "expected %<}%> before %<else%>");
7229 return c_parser_peek_token (parser)->location;
7230 }
7231 else
7232 {
7233 error_at (loc, "%<else%> without a previous %<if%>");
7234 c_parser_consume_token (parser);
7235 continue;
7236 }
7237 }
7238 else
7239 {
7240 statement:
7241 c_warn_unused_attributes (std_attrs);
7242 last_label = false;
7243 last_stmt = true;
7244 mark_valid_location_for_stdc_pragma (false);
7245 if (!omp_for_parse_state)
7246 c_parser_statement_after_labels (parser, NULL);
7247 else
7248 {
7249 /* In canonical loop nest form, nested loops can only appear
7250 directly, or in a directly nested compound statement. We
7251 already took care of those cases above, so now we have
7252 something else. This statement and everything inside
7253 it must be intervening code. */
7254 omp_for_parse_state->want_nested_loop = false;
7255 check_omp_intervening_code (parser);
7256 c_parser_statement_after_labels (parser, NULL);
7257 omp_for_parse_state->want_nested_loop = want_nested_loop;
7258 }
7259 }
7260
7261 parser->error = false;
7262 }
7263 if (last_label)
7264 pedwarn_c11 (label_loc, opt: OPT_Wpedantic, "label at end of compound statement");
7265 location_t endloc = c_parser_peek_token (parser)->location;
7266 c_parser_consume_token (parser);
7267
7268 /* Restore the value we started with. */
7269 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7270
7271 /* Package leftover intervening code, or the whole contents of the
7272 compound statement if we were looking for a nested loop in an OMP_FOR
7273 construct and didn't find one. */
7274 if (sl)
7275 {
7276 sl = pop_stmt_list (sl);
7277 if (omp_for_parse_state->want_nested_loop)
7278 add_stmt (sl);
7279 else
7280 add_structured_block_stmt (sl);
7281 }
7282 return endloc;
7283}
7284
7285/* Parse all consecutive labels, possibly preceded by standard
7286 attributes. In this context, a statement is required, not a
7287 declaration, so attributes must be followed by a statement that is
7288 not just a semicolon. */
7289
7290static void
7291c_parser_all_labels (c_parser *parser)
7292{
7293 bool have_std_attrs;
7294 tree std_attrs = NULL;
7295 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1)))
7296 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7297 while (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7298 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7299 || (c_parser_next_token_is (parser, type: CPP_NAME)
7300 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7301 {
7302 c_parser_label (parser, std_attrs);
7303 std_attrs = NULL;
7304 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
7305 n: 1)))
7306 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7307 }
7308 if (std_attrs
7309 && (!c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7310 || std_attrs))
7311 {
7312 if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7313 c_parser_error (parser, gmsgid: "expected statement");
7314 c_warn_unused_attributes (std_attrs);
7315 }
7316 else if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7317 c_parser_error (parser, gmsgid: "expected statement");
7318}
7319
7320/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
7321
7322 label:
7323 identifier : gnu-attributes[opt]
7324 case constant-expression :
7325 default :
7326
7327 GNU extensions:
7328
7329 label:
7330 case constant-expression ... constant-expression :
7331
7332 The use of gnu-attributes on labels is a GNU extension. The syntax in
7333 GNU C accepts any expressions without commas, non-constant
7334 expressions being rejected later. Any standard
7335 attribute-specifier-sequence before the first label has been parsed
7336 in the caller, to distinguish statements from declarations. Any
7337 attribute-specifier-sequence after the label is parsed in this
7338 function. */
7339static void
7340c_parser_label (c_parser *parser, tree std_attrs)
7341{
7342 location_t loc1 = c_parser_peek_token (parser)->location;
7343 tree label = NULL_TREE;
7344
7345 /* Remember whether this case or a user-defined label is allowed to fall
7346 through to. */
7347 bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
7348
7349 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7350 {
7351 tree exp1, exp2;
7352 c_parser_consume_token (parser);
7353 exp1 = convert_lvalue_to_rvalue (loc1,
7354 c_parser_expr_no_commas (parser, NULL),
7355 true, true).value;
7356 if (c_parser_next_token_is (parser, type: CPP_COLON))
7357 {
7358 c_parser_consume_token (parser);
7359 label = do_case (loc1, exp1, NULL_TREE, std_attrs);
7360 }
7361 else if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
7362 {
7363 c_parser_consume_token (parser);
7364 exp2 = convert_lvalue_to_rvalue (loc1,
7365 c_parser_expr_no_commas (parser,
7366 NULL),
7367 true, true).value;
7368 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7369 label = do_case (loc1, exp1, exp2, std_attrs);
7370 }
7371 else
7372 c_parser_error (parser, gmsgid: "expected %<:%> or %<...%>");
7373 }
7374 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
7375 {
7376 c_parser_consume_token (parser);
7377 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7378 label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
7379 }
7380 else
7381 {
7382 tree name = c_parser_peek_token (parser)->value;
7383 tree tlab;
7384 tree attrs;
7385 location_t loc2 = c_parser_peek_token (parser)->location;
7386 gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
7387 c_parser_consume_token (parser);
7388 gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
7389 c_parser_consume_token (parser);
7390 attrs = c_parser_gnu_attributes (parser);
7391 tlab = define_label (loc2, name);
7392 if (tlab)
7393 {
7394 decl_attributes (&tlab, attrs, 0);
7395 decl_attributes (&tlab, std_attrs, 0);
7396 label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
7397 }
7398 if (attrs
7399 && c_parser_next_tokens_start_declaration (parser))
7400 warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
7401 " label and declaration appertains to the label");
7402 }
7403 if (label)
7404 {
7405 if (TREE_CODE (label) == LABEL_EXPR)
7406 FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
7407 else
7408 FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
7409 }
7410}
7411
7412/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
7413
7414 statement:
7415 labeled-statement
7416 attribute-specifier-sequence[opt] compound-statement
7417 expression-statement
7418 attribute-specifier-sequence[opt] selection-statement
7419 attribute-specifier-sequence[opt] iteration-statement
7420 attribute-specifier-sequence[opt] jump-statement
7421
7422 labeled-statement:
7423 attribute-specifier-sequence[opt] label statement
7424
7425 expression-statement:
7426 expression[opt] ;
7427 attribute-specifier-sequence expression ;
7428
7429 selection-statement:
7430 if-statement
7431 switch-statement
7432
7433 iteration-statement:
7434 while-statement
7435 do-statement
7436 for-statement
7437
7438 jump-statement:
7439 goto identifier ;
7440 continue ;
7441 break ;
7442 return expression[opt] ;
7443
7444 GNU extensions:
7445
7446 statement:
7447 attribute-specifier-sequence[opt] asm-statement
7448
7449 jump-statement:
7450 goto * expression ;
7451
7452 expression-statement:
7453 gnu-attributes ;
7454
7455 Objective-C:
7456
7457 statement:
7458 attribute-specifier-sequence[opt] objc-throw-statement
7459 attribute-specifier-sequence[opt] objc-try-catch-statement
7460 attribute-specifier-sequence[opt] objc-synchronized-statement
7461
7462 objc-throw-statement:
7463 @throw expression ;
7464 @throw ;
7465
7466 OpenACC:
7467
7468 statement:
7469 attribute-specifier-sequence[opt] openacc-construct
7470
7471 openacc-construct:
7472 parallel-construct
7473 kernels-construct
7474 data-construct
7475 loop-construct
7476
7477 parallel-construct:
7478 parallel-directive structured-block
7479
7480 kernels-construct:
7481 kernels-directive structured-block
7482
7483 data-construct:
7484 data-directive structured-block
7485
7486 loop-construct:
7487 loop-directive structured-block
7488
7489 OpenMP:
7490
7491 statement:
7492 attribute-specifier-sequence[opt] openmp-construct
7493
7494 openmp-construct:
7495 parallel-construct
7496 for-construct
7497 simd-construct
7498 for-simd-construct
7499 sections-construct
7500 single-construct
7501 parallel-for-construct
7502 parallel-for-simd-construct
7503 parallel-sections-construct
7504 master-construct
7505 critical-construct
7506 atomic-construct
7507 ordered-construct
7508
7509 parallel-construct:
7510 parallel-directive structured-block
7511
7512 for-construct:
7513 for-directive iteration-statement
7514
7515 simd-construct:
7516 simd-directive iteration-statements
7517
7518 for-simd-construct:
7519 for-simd-directive iteration-statements
7520
7521 sections-construct:
7522 sections-directive section-scope
7523
7524 single-construct:
7525 single-directive structured-block
7526
7527 parallel-for-construct:
7528 parallel-for-directive iteration-statement
7529
7530 parallel-for-simd-construct:
7531 parallel-for-simd-directive iteration-statement
7532
7533 parallel-sections-construct:
7534 parallel-sections-directive section-scope
7535
7536 master-construct:
7537 master-directive structured-block
7538
7539 critical-construct:
7540 critical-directive structured-block
7541
7542 atomic-construct:
7543 atomic-directive expression-statement
7544
7545 ordered-construct:
7546 ordered-directive structured-block
7547
7548 Transactional Memory:
7549
7550 statement:
7551 attribute-specifier-sequence[opt] transaction-statement
7552 attribute-specifier-sequence[opt] transaction-cancel-statement
7553
7554 IF_P is used to track whether there's a (possibly labeled) if statement
7555 which is not enclosed in braces and has an else clause. This is used to
7556 implement -Wparentheses. */
7557
7558static void
7559c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
7560{
7561 c_parser_all_labels (parser);
7562 if (loc_after_labels)
7563 *loc_after_labels = c_parser_peek_token (parser)->location;
7564 parser->omp_attrs_forbidden_p = false;
7565 c_parser_statement_after_labels (parser, if_p, NULL);
7566}
7567
7568/* Parse a statement, other than a labeled statement. CHAIN is a vector
7569 of if-else-if conditions. All labels and standard attributes have
7570 been parsed in the caller.
7571
7572 IF_P is used to track whether there's a (possibly labeled) if statement
7573 which is not enclosed in braces and has an else clause. This is used to
7574 implement -Wparentheses. */
7575
7576static void
7577c_parser_statement_after_labels (c_parser *parser, bool *if_p,
7578 vec<tree> *chain)
7579{
7580 location_t loc = c_parser_peek_token (parser)->location;
7581 tree stmt = NULL_TREE;
7582 bool in_if_block = parser->in_if_block;
7583 parser->in_if_block = false;
7584 if (if_p != NULL)
7585 *if_p = false;
7586
7587 if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
7588 add_debug_begin_stmt (loc);
7589
7590 restart:
7591 switch (c_parser_peek_token (parser)->type)
7592 {
7593 case CPP_OPEN_BRACE:
7594 add_stmt (c_parser_compound_statement (parser));
7595 break;
7596 case CPP_KEYWORD:
7597 switch (c_parser_peek_token (parser)->keyword)
7598 {
7599 case RID_IF:
7600 c_parser_if_statement (parser, if_p, chain);
7601 break;
7602 case RID_SWITCH:
7603 c_parser_switch_statement (parser, if_p);
7604 break;
7605 case RID_WHILE:
7606 c_parser_while_statement (parser, false, 0, false, if_p);
7607 break;
7608 case RID_DO:
7609 c_parser_do_statement (parser, false, 0, false);
7610 break;
7611 case RID_FOR:
7612 c_parser_for_statement (parser, false, 0, false, if_p);
7613 break;
7614 case RID_GOTO:
7615 c_parser_consume_token (parser);
7616 if (c_parser_next_token_is (parser, type: CPP_NAME))
7617 {
7618 stmt = c_finish_goto_label (loc,
7619 c_parser_peek_token (parser)->value);
7620 c_parser_consume_token (parser);
7621 }
7622 else if (c_parser_next_token_is (parser, type: CPP_MULT))
7623 {
7624 struct c_expr val;
7625
7626 c_parser_consume_token (parser);
7627 val = c_parser_expression (parser);
7628 val = convert_lvalue_to_rvalue (loc, val, false, true);
7629 stmt = c_finish_goto_ptr (loc, val);
7630 }
7631 else
7632 c_parser_error (parser, gmsgid: "expected identifier or %<*%>");
7633 goto expect_semicolon;
7634 case RID_CONTINUE:
7635 c_parser_consume_token (parser);
7636 stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false);
7637 goto expect_semicolon;
7638 case RID_BREAK:
7639 c_parser_consume_token (parser);
7640 stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true);
7641 goto expect_semicolon;
7642 case RID_RETURN:
7643 c_parser_consume_token (parser);
7644 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7645 {
7646 stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
7647 c_parser_consume_token (parser);
7648 }
7649 else
7650 {
7651 location_t xloc = c_parser_peek_token (parser)->location;
7652 struct c_expr expr = c_parser_expression_conv (parser);
7653 mark_exp_read (expr.value);
7654 stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
7655 expr.value, expr.original_type);
7656 goto expect_semicolon;
7657 }
7658 break;
7659 case RID_ASM:
7660 stmt = c_parser_asm_statement (parser);
7661 break;
7662 case RID_TRANSACTION_ATOMIC:
7663 case RID_TRANSACTION_RELAXED:
7664 stmt = c_parser_transaction (parser,
7665 c_parser_peek_token (parser)->keyword);
7666 break;
7667 case RID_TRANSACTION_CANCEL:
7668 stmt = c_parser_transaction_cancel (parser);
7669 goto expect_semicolon;
7670 case RID_AT_THROW:
7671 gcc_assert (c_dialect_objc ());
7672 c_parser_consume_token (parser);
7673 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7674 {
7675 stmt = objc_build_throw_stmt (loc, NULL_TREE);
7676 c_parser_consume_token (parser);
7677 }
7678 else
7679 {
7680 struct c_expr expr = c_parser_expression (parser);
7681 expr = convert_lvalue_to_rvalue (loc, expr, false, false);
7682 expr.value = c_fully_fold (expr.value, false, NULL);
7683 stmt = objc_build_throw_stmt (loc, expr.value);
7684 goto expect_semicolon;
7685 }
7686 break;
7687 case RID_AT_TRY:
7688 gcc_assert (c_dialect_objc ());
7689 c_parser_objc_try_catch_finally_statement (parser);
7690 break;
7691 case RID_AT_SYNCHRONIZED:
7692 gcc_assert (c_dialect_objc ());
7693 c_parser_objc_synchronized_statement (parser);
7694 break;
7695 case RID_ATTRIBUTE:
7696 {
7697 /* Allow '__attribute__((fallthrough));' or
7698 '__attribute__((assume(cond)));'. */
7699 tree attrs = c_parser_gnu_attributes (parser);
7700 bool has_assume = lookup_attribute (attr_name: "assume", list: attrs);
7701 if (has_assume)
7702 {
7703 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7704 attrs = handle_assume_attribute (here: loc, attrs, nested: true);
7705 else
7706 {
7707 warning_at (loc, OPT_Wattributes,
7708 "%<assume%> attribute not followed by %<;%>");
7709 has_assume = false;
7710 }
7711 }
7712 if (attribute_fallthrough_p (attrs))
7713 {
7714 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7715 {
7716 tree fn = build_call_expr_internal_loc (loc,
7717 IFN_FALLTHROUGH,
7718 void_type_node, 0);
7719 add_stmt (fn);
7720 /* Eat the ';'. */
7721 c_parser_consume_token (parser);
7722 }
7723 else
7724 warning_at (loc, OPT_Wattributes,
7725 "%<fallthrough%> attribute not followed "
7726 "by %<;%>");
7727 }
7728 else if (has_assume)
7729 /* Eat the ';'. */
7730 c_parser_consume_token (parser);
7731 else if (attrs != NULL_TREE)
7732 warning_at (loc, OPT_Wattributes,
7733 "only attribute %<fallthrough%> or %<assume%> can "
7734 "be applied to a null statement");
7735 break;
7736 }
7737 default:
7738 goto expr_stmt;
7739 }
7740 break;
7741 case CPP_SEMICOLON:
7742 c_parser_consume_token (parser);
7743 break;
7744 case CPP_CLOSE_PAREN:
7745 case CPP_CLOSE_SQUARE:
7746 /* Avoid infinite loop in error recovery:
7747 c_parser_skip_until_found stops at a closing nesting
7748 delimiter without consuming it, but here we need to consume
7749 it to proceed further. */
7750 c_parser_error (parser, gmsgid: "expected statement");
7751 c_parser_consume_token (parser);
7752 break;
7753 case CPP_PRAGMA:
7754 if (!c_parser_pragma (parser, pragma_stmt, if_p))
7755 goto restart;
7756 break;
7757 default:
7758 expr_stmt:
7759 stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
7760 expect_semicolon:
7761 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7762 break;
7763 }
7764 /* Two cases cannot and do not have line numbers associated: If stmt
7765 is degenerate, such as "2;", then stmt is an INTEGER_CST, which
7766 cannot hold line numbers. But that's OK because the statement
7767 will either be changed to a MODIFY_EXPR during gimplification of
7768 the statement expr, or discarded. If stmt was compound, but
7769 without new variables, we will have skipped the creation of a
7770 BIND and will have a bare STATEMENT_LIST. But that's OK because
7771 (recursively) all of the component statements should already have
7772 line numbers assigned. ??? Can we discard no-op statements
7773 earlier? */
7774 if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
7775 protected_set_expr_location (stmt, loc);
7776
7777 parser->in_if_block = in_if_block;
7778}
7779
7780/* Parse the condition from an if, do, while or for statements. */
7781
7782static tree
7783c_parser_condition (c_parser *parser)
7784{
7785 location_t loc = c_parser_peek_token (parser)->location;
7786 tree cond;
7787 cond = c_parser_expression_conv (parser).value;
7788 cond = c_objc_common_truthvalue_conversion (loc, cond);
7789 cond = c_fully_fold (cond, false, NULL);
7790 if (warn_sequence_point)
7791 verify_sequence_points (cond);
7792 return cond;
7793}
7794
7795/* Parse a parenthesized condition from an if, do or while statement.
7796
7797 condition:
7798 ( expression )
7799*/
7800static tree
7801c_parser_paren_condition (c_parser *parser)
7802{
7803 tree cond;
7804 matching_parens parens;
7805 if (!parens.require_open (parser))
7806 return error_mark_node;
7807 cond = c_parser_condition (parser);
7808 parens.skip_until_found_close (parser);
7809 return cond;
7810}
7811
7812/* Parse a statement which is a block in C99.
7813
7814 IF_P is used to track whether there's a (possibly labeled) if statement
7815 which is not enclosed in braces and has an else clause. This is used to
7816 implement -Wparentheses. */
7817
7818static tree
7819c_parser_c99_block_statement (c_parser *parser, bool *if_p,
7820 location_t *loc_after_labels)
7821{
7822 tree block = c_begin_compound_stmt (flag_isoc99);
7823 location_t loc = c_parser_peek_token (parser)->location;
7824 c_parser_statement (parser, if_p, loc_after_labels);
7825 return c_end_compound_stmt (loc, block, flag_isoc99);
7826}
7827
7828/* Parse the body of an if statement. This is just parsing a
7829 statement but (a) it is a block in C99, (b) we track whether the
7830 body is an if statement for the sake of -Wparentheses warnings, (c)
7831 we handle an empty body specially for the sake of -Wempty-body
7832 warnings, and (d) we call parser_compound_statement directly
7833 because c_parser_statement_after_labels resets
7834 parser->in_if_block.
7835
7836 IF_P is used to track whether there's a (possibly labeled) if statement
7837 which is not enclosed in braces and has an else clause. This is used to
7838 implement -Wparentheses. */
7839
7840static tree
7841c_parser_if_body (c_parser *parser, bool *if_p,
7842 const token_indent_info &if_tinfo)
7843{
7844 tree block = c_begin_compound_stmt (flag_isoc99);
7845 location_t body_loc = c_parser_peek_token (parser)->location;
7846 location_t body_loc_after_labels = UNKNOWN_LOCATION;
7847 token_indent_info body_tinfo
7848 = get_token_indent_info (token: c_parser_peek_token (parser));
7849
7850 c_parser_all_labels (parser);
7851 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7852 {
7853 location_t loc = c_parser_peek_token (parser)->location;
7854 add_stmt (build_empty_stmt (loc));
7855 c_parser_consume_token (parser);
7856 if (!c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7857 warning_at (loc, OPT_Wempty_body,
7858 "suggest braces around empty body in an %<if%> statement");
7859 }
7860 else if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7861 add_stmt (c_parser_compound_statement (parser));
7862 else
7863 {
7864 body_loc_after_labels = c_parser_peek_token (parser)->location;
7865 c_parser_statement_after_labels (parser, if_p);
7866 }
7867
7868 token_indent_info next_tinfo
7869 = get_token_indent_info (token: c_parser_peek_token (parser));
7870 warn_for_misleading_indentation (guard_tinfo: if_tinfo, body_tinfo, next_tinfo);
7871 if (body_loc_after_labels != UNKNOWN_LOCATION
7872 && next_tinfo.type != CPP_SEMICOLON)
7873 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
7874 if_tinfo.location, RID_IF);
7875
7876 return c_end_compound_stmt (body_loc, block, flag_isoc99);
7877}
7878
7879/* Parse the else body of an if statement. This is just parsing a
7880 statement but (a) it is a block in C99, (b) we handle an empty body
7881 specially for the sake of -Wempty-body warnings. CHAIN is a vector
7882 of if-else-if conditions. */
7883
7884static tree
7885c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
7886 vec<tree> *chain)
7887{
7888 location_t body_loc = c_parser_peek_token (parser)->location;
7889 tree block = c_begin_compound_stmt (flag_isoc99);
7890 token_indent_info body_tinfo
7891 = get_token_indent_info (token: c_parser_peek_token (parser));
7892 location_t body_loc_after_labels = UNKNOWN_LOCATION;
7893
7894 c_parser_all_labels (parser);
7895 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7896 {
7897 location_t loc = c_parser_peek_token (parser)->location;
7898 warning_at (loc,
7899 OPT_Wempty_body,
7900 "suggest braces around empty body in an %<else%> statement");
7901 add_stmt (build_empty_stmt (loc));
7902 c_parser_consume_token (parser);
7903 }
7904 else
7905 {
7906 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7907 body_loc_after_labels = c_parser_peek_token (parser)->location;
7908 c_parser_statement_after_labels (parser, NULL, chain);
7909 }
7910
7911 token_indent_info next_tinfo
7912 = get_token_indent_info (token: c_parser_peek_token (parser));
7913 warn_for_misleading_indentation (guard_tinfo: else_tinfo, body_tinfo, next_tinfo);
7914 if (body_loc_after_labels != UNKNOWN_LOCATION
7915 && next_tinfo.type != CPP_SEMICOLON)
7916 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
7917 else_tinfo.location, RID_ELSE);
7918
7919 return c_end_compound_stmt (body_loc, block, flag_isoc99);
7920}
7921
7922/* We might need to reclassify any previously-lexed identifier, e.g.
7923 when we've left a for loop with an if-statement without else in the
7924 body - we might have used a wrong scope for the token. See PR67784. */
7925
7926static void
7927c_parser_maybe_reclassify_token (c_parser *parser)
7928{
7929 if (c_parser_next_token_is (parser, type: CPP_NAME))
7930 {
7931 c_token *token = c_parser_peek_token (parser);
7932
7933 if (token->id_kind != C_ID_CLASSNAME)
7934 {
7935 tree decl = lookup_name (token->value);
7936
7937 token->id_kind = C_ID_ID;
7938 if (decl)
7939 {
7940 if (TREE_CODE (decl) == TYPE_DECL)
7941 token->id_kind = C_ID_TYPENAME;
7942 }
7943 else if (c_dialect_objc ())
7944 {
7945 tree objc_interface_decl = objc_is_class_name (token->value);
7946 /* Objective-C class names are in the same namespace as
7947 variables and typedefs, and hence are shadowed by local
7948 declarations. */
7949 if (objc_interface_decl)
7950 {
7951 token->value = objc_interface_decl;
7952 token->id_kind = C_ID_CLASSNAME;
7953 }
7954 }
7955 }
7956 }
7957}
7958
7959/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
7960
7961 if-statement:
7962 if ( expression ) statement
7963 if ( expression ) statement else statement
7964
7965 CHAIN is a vector of if-else-if conditions.
7966 IF_P is used to track whether there's a (possibly labeled) if statement
7967 which is not enclosed in braces and has an else clause. This is used to
7968 implement -Wparentheses. */
7969
7970static void
7971c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
7972{
7973 tree block;
7974 location_t loc;
7975 tree cond;
7976 bool nested_if = false;
7977 tree first_body, second_body;
7978 bool in_if_block;
7979
7980 gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
7981 token_indent_info if_tinfo
7982 = get_token_indent_info (token: c_parser_peek_token (parser));
7983 c_parser_consume_token (parser);
7984 block = c_begin_compound_stmt (flag_isoc99);
7985 loc = c_parser_peek_token (parser)->location;
7986 cond = c_parser_paren_condition (parser);
7987 in_if_block = parser->in_if_block;
7988 parser->in_if_block = true;
7989 first_body = c_parser_if_body (parser, if_p: &nested_if, if_tinfo);
7990 parser->in_if_block = in_if_block;
7991
7992 if (warn_duplicated_cond)
7993 warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
7994
7995 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7996 {
7997 token_indent_info else_tinfo
7998 = get_token_indent_info (token: c_parser_peek_token (parser));
7999 c_parser_consume_token (parser);
8000 if (warn_duplicated_cond)
8001 {
8002 if (c_parser_next_token_is_keyword (parser, keyword: RID_IF)
8003 && chain == NULL)
8004 {
8005 /* We've got "if (COND) else if (COND2)". Start the
8006 condition chain and add COND as the first element. */
8007 chain = new vec<tree> ();
8008 if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8009 chain->safe_push (obj: cond);
8010 }
8011 else if (!c_parser_next_token_is_keyword (parser, keyword: RID_IF))
8012 /* This is if-else without subsequent if. Zap the condition
8013 chain; we would have already warned at this point. */
8014 vec_free (v&: chain);
8015 }
8016 second_body = c_parser_else_body (parser, else_tinfo, chain);
8017 /* Set IF_P to true to indicate that this if statement has an
8018 else clause. This may trigger the Wparentheses warning
8019 below when we get back up to the parent if statement. */
8020 if (if_p != NULL)
8021 *if_p = true;
8022 }
8023 else
8024 {
8025 second_body = NULL_TREE;
8026
8027 /* Diagnose an ambiguous else if if-then-else is nested inside
8028 if-then. */
8029 if (nested_if)
8030 warning_at (loc, OPT_Wdangling_else,
8031 "suggest explicit braces to avoid ambiguous %<else%>");
8032
8033 if (warn_duplicated_cond)
8034 /* This if statement does not have an else clause. We don't
8035 need the condition chain anymore. */
8036 vec_free (v&: chain);
8037 }
8038 c_finish_if_stmt (loc, cond, first_body, second_body);
8039 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8040
8041 c_parser_maybe_reclassify_token (parser);
8042}
8043
8044/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8045
8046 switch-statement:
8047 switch (expression) statement
8048*/
8049
8050static void
8051c_parser_switch_statement (c_parser *parser, bool *if_p)
8052{
8053 struct c_expr ce;
8054 tree block, expr, body;
8055 unsigned char save_in_statement;
8056 location_t switch_loc = c_parser_peek_token (parser)->location;
8057 location_t switch_cond_loc;
8058 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8059 c_parser_consume_token (parser);
8060 block = c_begin_compound_stmt (flag_isoc99);
8061 bool explicit_cast_p = false;
8062 matching_parens parens;
8063 if (parens.require_open (parser))
8064 {
8065 switch_cond_loc = c_parser_peek_token (parser)->location;
8066 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
8067 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
8068 explicit_cast_p = true;
8069 ce = c_parser_expression (parser);
8070 ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8071 expr = ce.value;
8072 /* ??? expr has no valid location? */
8073 parens.skip_until_found_close (parser);
8074 }
8075 else
8076 {
8077 switch_cond_loc = UNKNOWN_LOCATION;
8078 expr = error_mark_node;
8079 ce.original_type = error_mark_node;
8080 }
8081 c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p);
8082 save_in_statement = in_statement;
8083 in_statement |= IN_SWITCH_STMT;
8084 location_t loc_after_labels;
8085 bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8086 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8087 location_t next_loc = c_parser_peek_token (parser)->location;
8088 if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8089 warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8090 RID_SWITCH);
8091 c_finish_switch (body, ce.original_type);
8092 in_statement = save_in_statement;
8093 add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8094 c_parser_maybe_reclassify_token (parser);
8095}
8096
8097/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8098
8099 while-statement:
8100 while (expression) statement
8101
8102 IF_P is used to track whether there's a (possibly labeled) if statement
8103 which is not enclosed in braces and has an else clause. This is used to
8104 implement -Wparentheses. */
8105
8106static void
8107c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8108 bool novector, bool *if_p)
8109{
8110 tree block, cond, body;
8111 unsigned char save_in_statement;
8112 location_t loc;
8113 gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8114 token_indent_info while_tinfo
8115 = get_token_indent_info (token: c_parser_peek_token (parser));
8116
8117 if (parser->omp_for_parse_state)
8118 {
8119 error_at (c_parser_peek_token (parser)->location,
8120 "loop not permitted in intervening code in OpenMP loop body");
8121 parser->omp_for_parse_state->fail = true;
8122 }
8123
8124 c_parser_consume_token (parser);
8125 block = c_begin_compound_stmt (flag_isoc99);
8126 loc = c_parser_peek_token (parser)->location;
8127 cond = c_parser_paren_condition (parser);
8128 if (ivdep && cond != error_mark_node)
8129 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8130 build_int_cst (integer_type_node,
8131 annot_expr_ivdep_kind),
8132 integer_zero_node);
8133 if (unroll && cond != error_mark_node)
8134 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8135 build_int_cst (integer_type_node,
8136 annot_expr_unroll_kind),
8137 build_int_cst (integer_type_node, unroll));
8138 if (novector && cond != error_mark_node)
8139 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8140 build_int_cst (integer_type_node,
8141 annot_expr_no_vector_kind),
8142 integer_zero_node);
8143 save_in_statement = in_statement;
8144 in_statement = IN_ITERATION_STMT;
8145
8146 token_indent_info body_tinfo
8147 = get_token_indent_info (token: c_parser_peek_token (parser));
8148
8149 location_t loc_after_labels;
8150 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
8151 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8152 add_stmt (build_stmt (loc, WHILE_STMT, cond, body));
8153 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8154 c_parser_maybe_reclassify_token (parser);
8155
8156 token_indent_info next_tinfo
8157 = get_token_indent_info (token: c_parser_peek_token (parser));
8158 warn_for_misleading_indentation (guard_tinfo: while_tinfo, body_tinfo, next_tinfo);
8159
8160 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8161 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8162 while_tinfo.location, RID_WHILE);
8163
8164 in_statement = save_in_statement;
8165}
8166
8167/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8168
8169 do-statement:
8170 do statement while ( expression ) ;
8171*/
8172
8173static void
8174c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8175 bool novector)
8176{
8177 tree block, cond, body;
8178 unsigned char save_in_statement;
8179 location_t loc;
8180 gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
8181
8182 if (parser->omp_for_parse_state)
8183 {
8184 error_at (c_parser_peek_token (parser)->location,
8185 "loop not permitted in intervening code in OpenMP loop body");
8186 parser->omp_for_parse_state->fail = true;
8187 }
8188
8189 c_parser_consume_token (parser);
8190 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8191 warning_at (c_parser_peek_token (parser)->location,
8192 OPT_Wempty_body,
8193 "suggest braces around empty body in %<do%> statement");
8194 block = c_begin_compound_stmt (flag_isoc99);
8195 loc = c_parser_peek_token (parser)->location;
8196 save_in_statement = in_statement;
8197 in_statement = IN_ITERATION_STMT;
8198 body = c_parser_c99_block_statement (parser, NULL);
8199 c_parser_require_keyword (parser, keyword: RID_WHILE, msgid: "expected %<while%>");
8200 in_statement = save_in_statement;
8201 cond = c_parser_paren_condition (parser);
8202 if (ivdep && cond != error_mark_node)
8203 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8204 build_int_cst (integer_type_node,
8205 annot_expr_ivdep_kind),
8206 integer_zero_node);
8207 if (unroll && cond != error_mark_node)
8208 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8209 build_int_cst (integer_type_node,
8210 annot_expr_unroll_kind),
8211 build_int_cst (integer_type_node, unroll));
8212 if (novector && cond != error_mark_node)
8213 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8214 build_int_cst (integer_type_node,
8215 annot_expr_no_vector_kind),
8216 integer_zero_node);
8217 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
8218 c_parser_skip_to_end_of_block_or_statement (parser);
8219
8220 add_stmt (build_stmt (loc, DO_STMT, cond, body));
8221 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8222}
8223
8224/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8225
8226 for-statement:
8227 for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
8228 for ( nested-declaration expression[opt] ; expression[opt] ) statement
8229
8230 The form with a declaration is new in C99.
8231
8232 ??? In accordance with the old parser, the declaration may be a
8233 nested function, which is then rejected in check_for_loop_decls,
8234 but does it make any sense for this to be included in the grammar?
8235 Note in particular that the nested function does not include a
8236 trailing ';', whereas the "declaration" production includes one.
8237 Also, can we reject bad declarations earlier and cheaper than
8238 check_for_loop_decls?
8239
8240 In Objective-C, there are two additional variants:
8241
8242 foreach-statement:
8243 for ( expression in expresssion ) statement
8244 for ( declaration in expression ) statement
8245
8246 This is inconsistent with C, because the second variant is allowed
8247 even if c99 is not enabled.
8248
8249 The rest of the comment documents these Objective-C foreach-statement.
8250
8251 Here is the canonical example of the first variant:
8252 for (object in array) { do something with object }
8253 we call the first expression ("object") the "object_expression" and
8254 the second expression ("array") the "collection_expression".
8255 object_expression must be an lvalue of type "id" (a generic Objective-C
8256 object) because the loop works by assigning to object_expression the
8257 various objects from the collection_expression. collection_expression
8258 must evaluate to something of type "id" which responds to the method
8259 countByEnumeratingWithState:objects:count:.
8260
8261 The canonical example of the second variant is:
8262 for (id object in array) { do something with object }
8263 which is completely equivalent to
8264 {
8265 id object;
8266 for (object in array) { do something with object }
8267 }
8268 Note that initizializing 'object' in some way (eg, "for ((object =
8269 xxx) in array) { do something with object }") is possibly
8270 technically valid, but completely pointless as 'object' will be
8271 assigned to something else as soon as the loop starts. We should
8272 most likely reject it (TODO).
8273
8274 The beginning of the Objective-C foreach-statement looks exactly
8275 like the beginning of the for-statement, and we can tell it is a
8276 foreach-statement only because the initial declaration or
8277 expression is terminated by 'in' instead of ';'.
8278
8279 IF_P is used to track whether there's a (possibly labeled) if statement
8280 which is not enclosed in braces and has an else clause. This is used to
8281 implement -Wparentheses. */
8282
8283static void
8284c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8285 bool novector, bool *if_p)
8286{
8287 tree block, cond, incr, body;
8288 unsigned char save_in_statement;
8289 tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
8290 /* The following are only used when parsing an ObjC foreach statement. */
8291 tree object_expression;
8292 /* Silence the bogus uninitialized warning. */
8293 tree collection_expression = NULL;
8294 location_t loc = c_parser_peek_token (parser)->location;
8295 location_t for_loc = loc;
8296 bool is_foreach_statement = false;
8297 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
8298 token_indent_info for_tinfo
8299 = get_token_indent_info (token: c_parser_peek_token (parser));
8300
8301 if (parser->omp_for_parse_state)
8302 {
8303 error_at (for_loc,
8304 "loop not permitted in intervening code in OpenMP loop body");
8305 parser->omp_for_parse_state->fail = true;
8306 }
8307
8308 c_parser_consume_token (parser);
8309 /* Open a compound statement in Objective-C as well, just in case this is
8310 as foreach expression. */
8311 block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
8312 cond = error_mark_node;
8313 incr = error_mark_node;
8314 matching_parens parens;
8315 if (parens.require_open (parser))
8316 {
8317 /* Parse the initialization declaration or expression. */
8318 object_expression = error_mark_node;
8319 parser->objc_could_be_foreach_context = c_dialect_objc ();
8320 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8321 {
8322 parser->objc_could_be_foreach_context = false;
8323 c_parser_consume_token (parser);
8324 c_finish_expr_stmt (loc, NULL_TREE);
8325 }
8326 else if (c_parser_next_tokens_start_declaration (parser)
8327 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
8328 {
8329 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
8330 objc_foreach_object_declaration: &object_expression);
8331 parser->objc_could_be_foreach_context = false;
8332
8333 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8334 {
8335 c_parser_consume_token (parser);
8336 is_foreach_statement = true;
8337 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
8338 c_parser_error (parser, gmsgid: "multiple iterating variables in "
8339 "fast enumeration");
8340 }
8341 else
8342 check_for_loop_decls (for_loc, flag_isoc99);
8343 }
8344 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
8345 {
8346 /* __extension__ can start a declaration, but is also an
8347 unary operator that can start an expression. Consume all
8348 but the last of a possible series of __extension__ to
8349 determine which. */
8350 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
8351 && (c_parser_peek_2nd_token (parser)->keyword
8352 == RID_EXTENSION))
8353 c_parser_consume_token (parser);
8354 if (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
8355 || c_parser_nth_token_starts_std_attributes (parser, n: 2))
8356 {
8357 int ext;
8358 ext = disable_extension_diagnostics ();
8359 c_parser_consume_token (parser);
8360 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
8361 start_attr_ok: true, objc_foreach_object_declaration: &object_expression);
8362 parser->objc_could_be_foreach_context = false;
8363
8364 restore_extension_diagnostics (flags: ext);
8365 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8366 {
8367 c_parser_consume_token (parser);
8368 is_foreach_statement = true;
8369 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
8370 c_parser_error (parser, gmsgid: "multiple iterating variables in "
8371 "fast enumeration");
8372 }
8373 else
8374 check_for_loop_decls (for_loc, flag_isoc99);
8375 }
8376 else
8377 goto init_expr;
8378 }
8379 else
8380 {
8381 init_expr:
8382 {
8383 struct c_expr ce;
8384 tree init_expression;
8385 ce = c_parser_expression (parser);
8386 init_expression = ce.value;
8387 parser->objc_could_be_foreach_context = false;
8388 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8389 {
8390 c_parser_consume_token (parser);
8391 is_foreach_statement = true;
8392 if (! lvalue_p (init_expression))
8393 c_parser_error (parser, gmsgid: "invalid iterating variable in "
8394 "fast enumeration");
8395 object_expression
8396 = c_fully_fold (init_expression, false, NULL);
8397 }
8398 else
8399 {
8400 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
8401 init_expression = ce.value;
8402 c_finish_expr_stmt (loc, init_expression);
8403 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
8404 msgid: "expected %<;%>");
8405 }
8406 }
8407 }
8408 /* Parse the loop condition. In the case of a foreach
8409 statement, there is no loop condition. */
8410 gcc_assert (!parser->objc_could_be_foreach_context);
8411 if (!is_foreach_statement)
8412 {
8413 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8414 {
8415 if (ivdep)
8416 {
8417 c_parser_error (parser, gmsgid: "missing loop condition in loop "
8418 "with %<GCC ivdep%> pragma");
8419 cond = error_mark_node;
8420 }
8421 else if (unroll)
8422 {
8423 c_parser_error (parser, gmsgid: "missing loop condition in loop "
8424 "with %<GCC unroll%> pragma");
8425 cond = error_mark_node;
8426 }
8427 else
8428 {
8429 c_parser_consume_token (parser);
8430 cond = NULL_TREE;
8431 }
8432 }
8433 else
8434 {
8435 cond = c_parser_condition (parser);
8436 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
8437 msgid: "expected %<;%>");
8438 }
8439 if (ivdep && cond != error_mark_node)
8440 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8441 build_int_cst (integer_type_node,
8442 annot_expr_ivdep_kind),
8443 integer_zero_node);
8444 if (unroll && cond != error_mark_node)
8445 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8446 build_int_cst (integer_type_node,
8447 annot_expr_unroll_kind),
8448 build_int_cst (integer_type_node, unroll));
8449 if (novector && cond && cond != error_mark_node)
8450 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8451 build_int_cst (integer_type_node,
8452 annot_expr_no_vector_kind),
8453 integer_zero_node);
8454 }
8455 /* Parse the increment expression (the third expression in a
8456 for-statement). In the case of a foreach-statement, this is
8457 the expression that follows the 'in'. */
8458 loc = c_parser_peek_token (parser)->location;
8459 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
8460 {
8461 if (is_foreach_statement)
8462 {
8463 c_parser_error (parser,
8464 gmsgid: "missing collection in fast enumeration");
8465 collection_expression = error_mark_node;
8466 }
8467 else
8468 incr = c_process_expr_stmt (loc, NULL_TREE);
8469 }
8470 else
8471 {
8472 if (is_foreach_statement)
8473 collection_expression
8474 = c_fully_fold (c_parser_expression (parser).value, false, NULL);
8475 else
8476 {
8477 struct c_expr ce = c_parser_expression (parser);
8478 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
8479 incr = c_process_expr_stmt (loc, ce.value);
8480 }
8481 }
8482 parens.skip_until_found_close (parser);
8483 }
8484 save_in_statement = in_statement;
8485 if (is_foreach_statement)
8486 {
8487 in_statement = IN_OBJC_FOREACH;
8488 save_objc_foreach_break_label = objc_foreach_break_label;
8489 save_objc_foreach_continue_label = objc_foreach_continue_label;
8490 objc_foreach_break_label = create_artificial_label (loc);
8491 objc_foreach_continue_label = create_artificial_label (loc);
8492 }
8493 else
8494 in_statement = IN_ITERATION_STMT;
8495
8496 token_indent_info body_tinfo
8497 = get_token_indent_info (token: c_parser_peek_token (parser));
8498
8499 location_t loc_after_labels;
8500 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
8501 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8502
8503 if (is_foreach_statement)
8504 objc_finish_foreach_loop (for_loc, object_expression,
8505 collection_expression, body,
8506 objc_foreach_break_label,
8507 objc_foreach_continue_label);
8508 else
8509 add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
8510 body, NULL_TREE));
8511 add_stmt (c_end_compound_stmt (for_loc, block,
8512 flag_isoc99 || c_dialect_objc ()));
8513 c_parser_maybe_reclassify_token (parser);
8514
8515 token_indent_info next_tinfo
8516 = get_token_indent_info (token: c_parser_peek_token (parser));
8517 warn_for_misleading_indentation (guard_tinfo: for_tinfo, body_tinfo, next_tinfo);
8518
8519 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8520 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8521 for_tinfo.location, RID_FOR);
8522
8523 in_statement = save_in_statement;
8524 if (is_foreach_statement)
8525 {
8526 objc_foreach_break_label = save_objc_foreach_break_label;
8527 objc_foreach_continue_label = save_objc_foreach_continue_label;
8528 }
8529}
8530
8531/* Parse an asm statement, a GNU extension. This is a full-blown asm
8532 statement with inputs, outputs, clobbers, and volatile, inline, and goto
8533 tags allowed.
8534
8535 asm-qualifier:
8536 volatile
8537 inline
8538 goto
8539
8540 asm-qualifier-list:
8541 asm-qualifier-list asm-qualifier
8542 asm-qualifier
8543
8544 asm-statement:
8545 asm asm-qualifier-list[opt] ( asm-argument ) ;
8546
8547 asm-argument:
8548 asm-string-literal
8549 asm-string-literal : asm-operands[opt]
8550 asm-string-literal : asm-operands[opt] : asm-operands[opt]
8551 asm-string-literal : asm-operands[opt] : asm-operands[opt] \
8552 : asm-clobbers[opt]
8553 asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
8554 : asm-goto-operands
8555
8556 The form with asm-goto-operands is valid if and only if the
8557 asm-qualifier-list contains goto, and is the only allowed form in that case.
8558 Duplicate asm-qualifiers are not allowed.
8559
8560 The :: token is considered equivalent to two consecutive : tokens. */
8561
8562static tree
8563c_parser_asm_statement (c_parser *parser)
8564{
8565 tree str, outputs, inputs, clobbers, labels, ret;
8566 bool simple;
8567 location_t asm_loc = c_parser_peek_token (parser)->location;
8568 int section, nsections;
8569
8570 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
8571 c_parser_consume_token (parser);
8572
8573 /* Handle the asm-qualifier-list. */
8574 location_t volatile_loc = UNKNOWN_LOCATION;
8575 location_t inline_loc = UNKNOWN_LOCATION;
8576 location_t goto_loc = UNKNOWN_LOCATION;
8577 for (;;)
8578 {
8579 c_token *token = c_parser_peek_token (parser);
8580 location_t loc = token->location;
8581 switch (token->keyword)
8582 {
8583 case RID_VOLATILE:
8584 if (volatile_loc)
8585 {
8586 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8587 inform (volatile_loc, "first seen here");
8588 }
8589 else
8590 volatile_loc = loc;
8591 c_parser_consume_token (parser);
8592 continue;
8593
8594 case RID_INLINE:
8595 if (inline_loc)
8596 {
8597 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8598 inform (inline_loc, "first seen here");
8599 }
8600 else
8601 inline_loc = loc;
8602 c_parser_consume_token (parser);
8603 continue;
8604
8605 case RID_GOTO:
8606 if (goto_loc)
8607 {
8608 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8609 inform (goto_loc, "first seen here");
8610 }
8611 else
8612 goto_loc = loc;
8613 c_parser_consume_token (parser);
8614 continue;
8615
8616 case RID_CONST:
8617 case RID_RESTRICT:
8618 error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
8619 c_parser_consume_token (parser);
8620 continue;
8621
8622 default:
8623 break;
8624 }
8625 break;
8626 }
8627
8628 bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
8629 bool is_inline = (inline_loc != UNKNOWN_LOCATION);
8630 bool is_goto = (goto_loc != UNKNOWN_LOCATION);
8631
8632 ret = NULL;
8633
8634 matching_parens parens;
8635 if (!parens.require_open (parser))
8636 goto error;
8637
8638 str = c_parser_asm_string_literal (parser);
8639 if (str == NULL_TREE)
8640 goto error_close_paren;
8641
8642 simple = true;
8643 outputs = NULL_TREE;
8644 inputs = NULL_TREE;
8645 clobbers = NULL_TREE;
8646 labels = NULL_TREE;
8647
8648 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
8649 goto done_asm;
8650
8651 /* Parse each colon-delimited section of operands. */
8652 nsections = 3 + is_goto;
8653 for (section = 0; section < nsections; ++section)
8654 {
8655 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
8656 {
8657 ++section;
8658 if (section == nsections)
8659 {
8660 c_parser_error (parser, gmsgid: "expected %<)%>");
8661 goto error_close_paren;
8662 }
8663 c_parser_consume_token (parser);
8664 }
8665 else if (!c_parser_require (parser, type: CPP_COLON,
8666 msgid: is_goto
8667 ? G_("expected %<:%>")
8668 : G_("expected %<:%> or %<)%>"),
8669 UNKNOWN_LOCATION, type_is_unique: is_goto))
8670 goto error_close_paren;
8671
8672 /* Once past any colon, we're no longer a simple asm. */
8673 simple = false;
8674
8675 if ((!c_parser_next_token_is (parser, type: CPP_COLON)
8676 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
8677 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
8678 || section == 3)
8679 switch (section)
8680 {
8681 case 0:
8682 outputs = c_parser_asm_operands (parser);
8683 break;
8684 case 1:
8685 inputs = c_parser_asm_operands (parser);
8686 break;
8687 case 2:
8688 clobbers = c_parser_asm_clobbers (parser);
8689 break;
8690 case 3:
8691 labels = c_parser_asm_goto_operands (parser);
8692 break;
8693 default:
8694 gcc_unreachable ();
8695 }
8696
8697 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
8698 goto done_asm;
8699 }
8700
8701 done_asm:
8702 if (!parens.require_close (parser))
8703 {
8704 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8705 goto error;
8706 }
8707
8708 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
8709 c_parser_skip_to_end_of_block_or_statement (parser);
8710
8711 ret = build_asm_stmt (is_volatile,
8712 build_asm_expr (asm_loc, str, outputs, inputs,
8713 clobbers, labels, simple, is_inline));
8714
8715 error:
8716 return ret;
8717
8718 error_close_paren:
8719 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8720 goto error;
8721}
8722
8723/* Parse asm operands, a GNU extension.
8724
8725 asm-operands:
8726 asm-operand
8727 asm-operands , asm-operand
8728
8729 asm-operand:
8730 asm-string-literal ( expression )
8731 [ identifier ] asm-string-literal ( expression )
8732*/
8733
8734static tree
8735c_parser_asm_operands (c_parser *parser)
8736{
8737 tree list = NULL_TREE;
8738 while (true)
8739 {
8740 tree name, str;
8741 struct c_expr expr;
8742 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
8743 {
8744 c_parser_consume_token (parser);
8745 if (c_parser_next_token_is (parser, type: CPP_NAME))
8746 {
8747 tree id = c_parser_peek_token (parser)->value;
8748 c_parser_consume_token (parser);
8749 name = build_string (IDENTIFIER_LENGTH (id),
8750 IDENTIFIER_POINTER (id));
8751 }
8752 else
8753 {
8754 c_parser_error (parser, gmsgid: "expected identifier");
8755 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, NULL);
8756 return NULL_TREE;
8757 }
8758 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
8759 msgid: "expected %<]%>");
8760 }
8761 else
8762 name = NULL_TREE;
8763 str = c_parser_asm_string_literal (parser);
8764 if (str == NULL_TREE)
8765 return NULL_TREE;
8766 matching_parens parens;
8767 if (!parens.require_open (parser))
8768 return NULL_TREE;
8769 expr = c_parser_expression (parser);
8770 mark_exp_read (expr.value);
8771 if (!parens.require_close (parser))
8772 {
8773 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8774 return NULL_TREE;
8775 }
8776 list = chainon (list, build_tree_list (build_tree_list (name, str),
8777 expr.value));
8778 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8779 c_parser_consume_token (parser);
8780 else
8781 break;
8782 }
8783 return list;
8784}
8785
8786/* Parse asm clobbers, a GNU extension.
8787
8788 asm-clobbers:
8789 asm-string-literal
8790 asm-clobbers , asm-string-literal
8791*/
8792
8793static tree
8794c_parser_asm_clobbers (c_parser *parser)
8795{
8796 tree list = NULL_TREE;
8797 while (true)
8798 {
8799 tree str = c_parser_asm_string_literal (parser);
8800 if (str)
8801 list = tree_cons (NULL_TREE, str, list);
8802 else
8803 return NULL_TREE;
8804 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8805 c_parser_consume_token (parser);
8806 else
8807 break;
8808 }
8809 return list;
8810}
8811
8812/* Parse asm goto labels, a GNU extension.
8813
8814 asm-goto-operands:
8815 identifier
8816 asm-goto-operands , identifier
8817*/
8818
8819static tree
8820c_parser_asm_goto_operands (c_parser *parser)
8821{
8822 tree list = NULL_TREE;
8823 while (true)
8824 {
8825 tree name, label;
8826
8827 if (c_parser_next_token_is (parser, type: CPP_NAME))
8828 {
8829 c_token *tok = c_parser_peek_token (parser);
8830 name = tok->value;
8831 label = lookup_label_for_goto (tok->location, name);
8832 c_parser_consume_token (parser);
8833 TREE_USED (label) = 1;
8834 }
8835 else
8836 {
8837 c_parser_error (parser, gmsgid: "expected identifier");
8838 return NULL_TREE;
8839 }
8840
8841 name = build_string (IDENTIFIER_LENGTH (name),
8842 IDENTIFIER_POINTER (name));
8843 list = tree_cons (name, label, list);
8844 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8845 c_parser_consume_token (parser);
8846 else
8847 return nreverse (list);
8848 }
8849}
8850
8851/* Parse a possibly concatenated sequence of string literals.
8852 TRANSLATE says whether to translate them to the execution character
8853 set; WIDE_OK says whether any kind of prefixed string literal is
8854 permitted in this context. This code is based on that in
8855 lex_string. */
8856
8857struct c_expr
8858c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
8859{
8860 struct c_expr ret;
8861 size_t count;
8862 struct obstack str_ob;
8863 struct obstack loc_ob;
8864 cpp_string str, istr, *strs;
8865 c_token *tok;
8866 location_t loc, last_tok_loc;
8867 enum cpp_ttype type;
8868 tree value, string_tree;
8869
8870 tok = c_parser_peek_token (parser);
8871 loc = tok->location;
8872 last_tok_loc = linemap_resolve_location (line_table, loc,
8873 lrk: LRK_MACRO_DEFINITION_LOCATION,
8874 NULL);
8875 type = tok->type;
8876 switch (type)
8877 {
8878 case CPP_STRING:
8879 case CPP_WSTRING:
8880 case CPP_STRING16:
8881 case CPP_STRING32:
8882 case CPP_UTF8STRING:
8883 string_tree = tok->value;
8884 break;
8885
8886 default:
8887 c_parser_error (parser, gmsgid: "expected string literal");
8888 ret.set_error ();
8889 ret.value = NULL_TREE;
8890 ret.original_code = ERROR_MARK;
8891 ret.original_type = NULL_TREE;
8892 return ret;
8893 }
8894
8895 /* Try to avoid the overhead of creating and destroying an obstack
8896 for the common case of just one string. */
8897 switch (c_parser_peek_2nd_token (parser)->type)
8898 {
8899 default:
8900 c_parser_consume_token (parser);
8901 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
8902 str.len = TREE_STRING_LENGTH (string_tree);
8903 count = 1;
8904 strs = &str;
8905 break;
8906
8907 case CPP_STRING:
8908 case CPP_WSTRING:
8909 case CPP_STRING16:
8910 case CPP_STRING32:
8911 case CPP_UTF8STRING:
8912 gcc_obstack_init (&str_ob);
8913 gcc_obstack_init (&loc_ob);
8914 count = 0;
8915 do
8916 {
8917 c_parser_consume_token (parser);
8918 count++;
8919 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
8920 str.len = TREE_STRING_LENGTH (string_tree);
8921 if (type != tok->type)
8922 {
8923 if (type == CPP_STRING)
8924 type = tok->type;
8925 else if (tok->type != CPP_STRING)
8926 error ("unsupported non-standard concatenation "
8927 "of string literals");
8928 }
8929 obstack_grow (&str_ob, &str, sizeof (cpp_string));
8930 obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
8931 tok = c_parser_peek_token (parser);
8932 string_tree = tok->value;
8933 last_tok_loc
8934 = linemap_resolve_location (line_table, loc: tok->location,
8935 lrk: LRK_MACRO_DEFINITION_LOCATION, NULL);
8936 }
8937 while (tok->type == CPP_STRING
8938 || tok->type == CPP_WSTRING
8939 || tok->type == CPP_STRING16
8940 || tok->type == CPP_STRING32
8941 || tok->type == CPP_UTF8STRING);
8942 strs = (cpp_string *) obstack_finish (&str_ob);
8943 }
8944
8945 if (count > 1 && !in_system_header_at (loc: input_location))
8946 warning (OPT_Wtraditional,
8947 "traditional C rejects string constant concatenation");
8948
8949 if ((type == CPP_STRING || wide_ok)
8950 && ((translate
8951 ? cpp_interpret_string : cpp_interpret_string_notranslate)
8952 (parse_in, strs, count, &istr, type)))
8953 {
8954 value = build_string (istr.len, (const char *) istr.text);
8955 free (CONST_CAST (unsigned char *, istr.text));
8956 if (count > 1)
8957 {
8958 location_t *locs = (location_t *) obstack_finish (&loc_ob);
8959 gcc_assert (g_string_concat_db);
8960 g_string_concat_db->record_string_concatenation (num: count, locs);
8961 }
8962 }
8963 else
8964 {
8965 if (type != CPP_STRING && !wide_ok)
8966 {
8967 error_at (loc, "a wide string is invalid in this context");
8968 type = CPP_STRING;
8969 }
8970 /* Callers cannot generally handle error_mark_node in this
8971 context, so return the empty string instead. An error has
8972 been issued, either above or from cpp_interpret_string. */
8973 switch (type)
8974 {
8975 default:
8976 case CPP_STRING:
8977 case CPP_UTF8STRING:
8978 if (type == CPP_UTF8STRING && flag_char8_t)
8979 {
8980 value = build_string (TYPE_PRECISION (char8_type_node)
8981 / TYPE_PRECISION (char_type_node),
8982 ""); /* char8_t is 8 bits */
8983 }
8984 else
8985 value = build_string (1, "");
8986 break;
8987 case CPP_STRING16:
8988 value = build_string (TYPE_PRECISION (char16_type_node)
8989 / TYPE_PRECISION (char_type_node),
8990 "\0"); /* char16_t is 16 bits */
8991 break;
8992 case CPP_STRING32:
8993 value = build_string (TYPE_PRECISION (char32_type_node)
8994 / TYPE_PRECISION (char_type_node),
8995 "\0\0\0"); /* char32_t is 32 bits */
8996 break;
8997 case CPP_WSTRING:
8998 value = build_string (TYPE_PRECISION (wchar_type_node)
8999 / TYPE_PRECISION (char_type_node),
9000 "\0\0\0"); /* widest supported wchar_t
9001 is 32 bits */
9002 break;
9003 }
9004 }
9005
9006 switch (type)
9007 {
9008 default:
9009 case CPP_STRING:
9010 TREE_TYPE (value) = char_array_type_node;
9011 break;
9012 case CPP_UTF8STRING:
9013 if (flag_char8_t)
9014 TREE_TYPE (value) = char8_array_type_node;
9015 else
9016 TREE_TYPE (value) = char_array_type_node;
9017 break;
9018 case CPP_STRING16:
9019 TREE_TYPE (value) = char16_array_type_node;
9020 break;
9021 case CPP_STRING32:
9022 TREE_TYPE (value) = char32_array_type_node;
9023 break;
9024 case CPP_WSTRING:
9025 TREE_TYPE (value) = wchar_array_type_node;
9026 }
9027 value = fix_string_type (value);
9028
9029 if (count > 1)
9030 {
9031 obstack_free (&str_ob, 0);
9032 obstack_free (&loc_ob, 0);
9033 }
9034
9035 ret.value = value;
9036 ret.original_code = STRING_CST;
9037 ret.original_type = NULL_TREE;
9038 set_c_expr_source_range (expr: &ret, src_range: get_range_from_loc (set: line_table, loc));
9039 ret.m_decimal = 0;
9040 parser->seen_string_literal = true;
9041 return ret;
9042}
9043
9044/* Parse an expression other than a compound expression; that is, an
9045 assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9046 AFTER is not NULL then it is an Objective-C message expression which
9047 is the primary-expression starting the expression as an initializer.
9048
9049 assignment-expression:
9050 conditional-expression
9051 unary-expression assignment-operator assignment-expression
9052
9053 assignment-operator: one of
9054 = *= /= %= += -= <<= >>= &= ^= |=
9055
9056 In GNU C we accept any conditional expression on the LHS and
9057 diagnose the invalid lvalue rather than producing a syntax
9058 error. */
9059
9060static struct c_expr
9061c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
9062 tree omp_atomic_lhs)
9063{
9064 struct c_expr lhs, rhs, ret;
9065 enum tree_code code;
9066 location_t op_location, exp_location;
9067 bool save_in_omp_for = c_in_omp_for;
9068 c_in_omp_for = false;
9069 gcc_assert (!after || c_dialect_objc ());
9070 lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
9071 op_location = c_parser_peek_token (parser)->location;
9072 switch (c_parser_peek_token (parser)->type)
9073 {
9074 case CPP_EQ:
9075 code = NOP_EXPR;
9076 break;
9077 case CPP_MULT_EQ:
9078 code = MULT_EXPR;
9079 break;
9080 case CPP_DIV_EQ:
9081 code = TRUNC_DIV_EXPR;
9082 break;
9083 case CPP_MOD_EQ:
9084 code = TRUNC_MOD_EXPR;
9085 break;
9086 case CPP_PLUS_EQ:
9087 code = PLUS_EXPR;
9088 break;
9089 case CPP_MINUS_EQ:
9090 code = MINUS_EXPR;
9091 break;
9092 case CPP_LSHIFT_EQ:
9093 code = LSHIFT_EXPR;
9094 break;
9095 case CPP_RSHIFT_EQ:
9096 code = RSHIFT_EXPR;
9097 break;
9098 case CPP_AND_EQ:
9099 code = BIT_AND_EXPR;
9100 break;
9101 case CPP_XOR_EQ:
9102 code = BIT_XOR_EXPR;
9103 break;
9104 case CPP_OR_EQ:
9105 code = BIT_IOR_EXPR;
9106 break;
9107 default:
9108 c_in_omp_for = save_in_omp_for;
9109 return lhs;
9110 }
9111 c_parser_consume_token (parser);
9112 exp_location = c_parser_peek_token (parser)->location;
9113 rhs = c_parser_expr_no_commas (parser, NULL);
9114 rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
9115
9116 ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
9117 code, exp_location, rhs.value,
9118 rhs.original_type);
9119 ret.m_decimal = 0;
9120 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
9121 if (code == NOP_EXPR)
9122 ret.original_code = MODIFY_EXPR;
9123 else
9124 {
9125 suppress_warning (ret.value, OPT_Wparentheses);
9126 ret.original_code = ERROR_MARK;
9127 }
9128 ret.original_type = NULL;
9129 c_in_omp_for = save_in_omp_for;
9130 return ret;
9131}
9132
9133/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
9134 AFTER is not NULL then it is an Objective-C message expression which is
9135 the primary-expression starting the expression as an initializer.
9136
9137 conditional-expression:
9138 logical-OR-expression
9139 logical-OR-expression ? expression : conditional-expression
9140
9141 GNU extensions:
9142
9143 conditional-expression:
9144 logical-OR-expression ? : conditional-expression
9145*/
9146
9147static struct c_expr
9148c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
9149 tree omp_atomic_lhs)
9150{
9151 struct c_expr cond, exp1, exp2, ret;
9152 location_t start, cond_loc, colon_loc;
9153 bool save_c_omp_array_section_p = c_omp_array_section_p;
9154
9155 gcc_assert (!after || c_dialect_objc ());
9156
9157 cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
9158
9159 if (c_parser_next_token_is_not (parser, type: CPP_QUERY))
9160 return cond;
9161 c_omp_array_section_p = false;
9162 if (cond.value != error_mark_node)
9163 start = cond.get_start ();
9164 else
9165 start = UNKNOWN_LOCATION;
9166 cond_loc = c_parser_peek_token (parser)->location;
9167 cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
9168 c_parser_consume_token (parser);
9169 if (c_parser_next_token_is (parser, type: CPP_COLON))
9170 {
9171 tree eptype = NULL_TREE;
9172
9173 location_t middle_loc = c_parser_peek_token (parser)->location;
9174 pedwarn (middle_loc, OPT_Wpedantic,
9175 "ISO C forbids omitting the middle term of a %<?:%> expression");
9176 if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
9177 {
9178 eptype = TREE_TYPE (cond.value);
9179 cond.value = TREE_OPERAND (cond.value, 0);
9180 }
9181 tree e = cond.value;
9182 while (TREE_CODE (e) == COMPOUND_EXPR)
9183 e = TREE_OPERAND (e, 1);
9184 warn_for_omitted_condop (middle_loc, e);
9185 /* Make sure first operand is calculated only once. */
9186 exp1.value = save_expr (default_conversion (cond.value));
9187 if (eptype)
9188 exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
9189 exp1.original_type = NULL;
9190 exp1.src_range = cond.src_range;
9191 cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
9192 c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
9193 }
9194 else
9195 {
9196 cond.value
9197 = c_objc_common_truthvalue_conversion
9198 (cond_loc, default_conversion (cond.value));
9199 c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
9200 exp1 = c_parser_expression_conv (parser);
9201 mark_exp_read (exp1.value);
9202 c_inhibit_evaluation_warnings +=
9203 ((cond.value == truthvalue_true_node)
9204 - (cond.value == truthvalue_false_node));
9205 }
9206
9207 colon_loc = c_parser_peek_token (parser)->location;
9208 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
9209 {
9210 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
9211 ret.set_error ();
9212 ret.original_code = ERROR_MARK;
9213 ret.original_type = NULL;
9214 c_omp_array_section_p = save_c_omp_array_section_p;
9215 return ret;
9216 }
9217 {
9218 location_t exp2_loc = c_parser_peek_token (parser)->location;
9219 exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
9220 exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
9221 }
9222 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
9223 location_t loc1 = make_location (caret: exp1.get_start (), src_range: exp1.src_range);
9224 location_t loc2 = make_location (caret: exp2.get_start (), src_range: exp2.src_range);
9225 if (UNLIKELY (omp_atomic_lhs != NULL)
9226 && (TREE_CODE (cond.value) == GT_EXPR
9227 || TREE_CODE (cond.value) == LT_EXPR
9228 || TREE_CODE (cond.value) == EQ_EXPR)
9229 && c_tree_equal (exp2.value, omp_atomic_lhs)
9230 && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
9231 || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
9232 ret.value = build3_loc (loc: colon_loc, code: COND_EXPR, TREE_TYPE (omp_atomic_lhs),
9233 arg0: cond.value, arg1: exp1.value, arg2: exp2.value);
9234 else
9235 ret.value
9236 = build_conditional_expr (colon_loc, cond.value,
9237 cond.original_code == C_MAYBE_CONST_EXPR,
9238 exp1.value, exp1.original_type, loc1,
9239 exp2.value, exp2.original_type, loc2);
9240 ret.original_code = ERROR_MARK;
9241 if (exp1.value == error_mark_node || exp2.value == error_mark_node)
9242 ret.original_type = NULL;
9243 else
9244 {
9245 tree t1, t2;
9246
9247 /* If both sides are enum type, the default conversion will have
9248 made the type of the result be an integer type. We want to
9249 remember the enum types we started with. */
9250 t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
9251 t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
9252 ret.original_type = ((t1 != error_mark_node
9253 && t2 != error_mark_node
9254 && (TYPE_MAIN_VARIANT (t1)
9255 == TYPE_MAIN_VARIANT (t2)))
9256 ? t1
9257 : NULL);
9258 }
9259 set_c_expr_source_range (expr: &ret, start, finish: exp2.get_finish ());
9260 ret.m_decimal = 0;
9261 c_omp_array_section_p = save_c_omp_array_section_p;
9262 return ret;
9263}
9264
9265/* Parse a binary expression; that is, a logical-OR-expression (C90
9266 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
9267 NULL then it is an Objective-C message expression which is the
9268 primary-expression starting the expression as an initializer.
9269
9270 OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
9271 when it should be the unfolded lhs. In a valid OpenMP source,
9272 one of the operands of the toplevel binary expression must be equal
9273 to it. In that case, just return a build2 created binary operation
9274 rather than result of parser_build_binary_op.
9275
9276 multiplicative-expression:
9277 cast-expression
9278 multiplicative-expression * cast-expression
9279 multiplicative-expression / cast-expression
9280 multiplicative-expression % cast-expression
9281
9282 additive-expression:
9283 multiplicative-expression
9284 additive-expression + multiplicative-expression
9285 additive-expression - multiplicative-expression
9286
9287 shift-expression:
9288 additive-expression
9289 shift-expression << additive-expression
9290 shift-expression >> additive-expression
9291
9292 relational-expression:
9293 shift-expression
9294 relational-expression < shift-expression
9295 relational-expression > shift-expression
9296 relational-expression <= shift-expression
9297 relational-expression >= shift-expression
9298
9299 equality-expression:
9300 relational-expression
9301 equality-expression == relational-expression
9302 equality-expression != relational-expression
9303
9304 AND-expression:
9305 equality-expression
9306 AND-expression & equality-expression
9307
9308 exclusive-OR-expression:
9309 AND-expression
9310 exclusive-OR-expression ^ AND-expression
9311
9312 inclusive-OR-expression:
9313 exclusive-OR-expression
9314 inclusive-OR-expression | exclusive-OR-expression
9315
9316 logical-AND-expression:
9317 inclusive-OR-expression
9318 logical-AND-expression && inclusive-OR-expression
9319
9320 logical-OR-expression:
9321 logical-AND-expression
9322 logical-OR-expression || logical-AND-expression
9323*/
9324
9325static struct c_expr
9326c_parser_binary_expression (c_parser *parser, struct c_expr *after,
9327 tree omp_atomic_lhs)
9328{
9329 /* A binary expression is parsed using operator-precedence parsing,
9330 with the operands being cast expressions. All the binary
9331 operators are left-associative. Thus a binary expression is of
9332 form:
9333
9334 E0 op1 E1 op2 E2 ...
9335
9336 which we represent on a stack. On the stack, the precedence
9337 levels are strictly increasing. When a new operator is
9338 encountered of higher precedence than that at the top of the
9339 stack, it is pushed; its LHS is the top expression, and its RHS
9340 is everything parsed until it is popped. When a new operator is
9341 encountered with precedence less than or equal to that at the top
9342 of the stack, triples E[i-1] op[i] E[i] are popped and replaced
9343 by the result of the operation until the operator at the top of
9344 the stack has lower precedence than the new operator or there is
9345 only one element on the stack; then the top expression is the LHS
9346 of the new operator. In the case of logical AND and OR
9347 expressions, we also need to adjust c_inhibit_evaluation_warnings
9348 as appropriate when the operators are pushed and popped. */
9349
9350 struct {
9351 /* The expression at this stack level. */
9352 struct c_expr expr;
9353 /* The precedence of the operator on its left, PREC_NONE at the
9354 bottom of the stack. */
9355 enum c_parser_prec prec;
9356 /* The operation on its left. */
9357 enum tree_code op;
9358 /* The source location of this operation. */
9359 location_t loc;
9360 /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
9361 tree sizeof_arg;
9362 } stack[NUM_PRECS];
9363 int sp;
9364 /* Location of the binary operator. */
9365 location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
9366#define POP \
9367 do { \
9368 switch (stack[sp].op) \
9369 { \
9370 case TRUTH_ANDIF_EXPR: \
9371 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
9372 == truthvalue_false_node); \
9373 break; \
9374 case TRUTH_ORIF_EXPR: \
9375 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
9376 == truthvalue_true_node); \
9377 break; \
9378 case TRUNC_DIV_EXPR: \
9379 if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
9380 || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
9381 && (stack[sp].expr.original_code == SIZEOF_EXPR \
9382 || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
9383 { \
9384 tree type0 = stack[sp - 1].sizeof_arg; \
9385 tree type1 = stack[sp].sizeof_arg; \
9386 tree first_arg = type0; \
9387 if (!TYPE_P (type0)) \
9388 type0 = TREE_TYPE (type0); \
9389 if (!TYPE_P (type1)) \
9390 type1 = TREE_TYPE (type1); \
9391 if (POINTER_TYPE_P (type0) \
9392 && comptypes (TREE_TYPE (type0), type1) \
9393 && !(TREE_CODE (first_arg) == PARM_DECL \
9394 && C_ARRAY_PARAMETER (first_arg) \
9395 && warn_sizeof_array_argument)) \
9396 { \
9397 auto_diagnostic_group d; \
9398 if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
9399 "division %<sizeof (%T) / sizeof (%T)%> " \
9400 "does not compute the number of array " \
9401 "elements", \
9402 type0, type1)) \
9403 if (DECL_P (first_arg)) \
9404 inform (DECL_SOURCE_LOCATION (first_arg), \
9405 "first %<sizeof%> operand was declared here"); \
9406 } \
9407 else if (TREE_CODE (type0) == ARRAY_TYPE \
9408 && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
9409 && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
9410 maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
9411 stack[sp].sizeof_arg, type1); \
9412 } \
9413 break; \
9414 default: \
9415 break; \
9416 } \
9417 stack[sp - 1].expr \
9418 = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
9419 stack[sp - 1].expr, true, true); \
9420 stack[sp].expr \
9421 = convert_lvalue_to_rvalue (stack[sp].loc, \
9422 stack[sp].expr, true, true); \
9423 if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
9424 && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
9425 && ((1 << stack[sp].prec) \
9426 & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
9427 | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
9428 | (1 << PREC_ADD) | (1 << PREC_MULT) \
9429 | (1 << PREC_EQ)))) \
9430 || ((c_parser_next_token_is (parser, CPP_QUERY) \
9431 || (omp_atomic_lhs == void_list_node \
9432 && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
9433 && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
9434 && stack[sp].op != TRUNC_MOD_EXPR \
9435 && stack[sp].op != GE_EXPR \
9436 && stack[sp].op != LE_EXPR \
9437 && stack[sp].op != NE_EXPR \
9438 && stack[0].expr.value != error_mark_node \
9439 && stack[1].expr.value != error_mark_node \
9440 && (omp_atomic_lhs == void_list_node \
9441 || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
9442 || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
9443 || (stack[sp].op == EQ_EXPR \
9444 && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
9445 { \
9446 tree t = make_node (stack[1].op); \
9447 TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
9448 TREE_OPERAND (t, 0) = stack[0].expr.value; \
9449 TREE_OPERAND (t, 1) = stack[1].expr.value; \
9450 stack[0].expr.value = t; \
9451 stack[0].expr.m_decimal = 0; \
9452 } \
9453 else \
9454 stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
9455 stack[sp].op, \
9456 stack[sp - 1].expr, \
9457 stack[sp].expr); \
9458 sp--; \
9459 } while (0)
9460 gcc_assert (!after || c_dialect_objc ());
9461 stack[0].loc = c_parser_peek_token (parser)->location;
9462 stack[0].expr = c_parser_cast_expression (parser, after);
9463 stack[0].prec = PREC_NONE;
9464 stack[0].sizeof_arg = c_last_sizeof_arg;
9465 sp = 0;
9466 while (true)
9467 {
9468 enum c_parser_prec oprec;
9469 enum tree_code ocode;
9470 source_range src_range;
9471 if (parser->error)
9472 goto out;
9473 switch (c_parser_peek_token (parser)->type)
9474 {
9475 case CPP_MULT:
9476 oprec = PREC_MULT;
9477 ocode = MULT_EXPR;
9478 break;
9479 case CPP_DIV:
9480 oprec = PREC_MULT;
9481 ocode = TRUNC_DIV_EXPR;
9482 break;
9483 case CPP_MOD:
9484 oprec = PREC_MULT;
9485 ocode = TRUNC_MOD_EXPR;
9486 break;
9487 case CPP_PLUS:
9488 oprec = PREC_ADD;
9489 ocode = PLUS_EXPR;
9490 break;
9491 case CPP_MINUS:
9492 oprec = PREC_ADD;
9493 ocode = MINUS_EXPR;
9494 break;
9495 case CPP_LSHIFT:
9496 oprec = PREC_SHIFT;
9497 ocode = LSHIFT_EXPR;
9498 break;
9499 case CPP_RSHIFT:
9500 oprec = PREC_SHIFT;
9501 ocode = RSHIFT_EXPR;
9502 break;
9503 case CPP_LESS:
9504 oprec = PREC_REL;
9505 ocode = LT_EXPR;
9506 break;
9507 case CPP_GREATER:
9508 oprec = PREC_REL;
9509 ocode = GT_EXPR;
9510 break;
9511 case CPP_LESS_EQ:
9512 oprec = PREC_REL;
9513 ocode = LE_EXPR;
9514 break;
9515 case CPP_GREATER_EQ:
9516 oprec = PREC_REL;
9517 ocode = GE_EXPR;
9518 break;
9519 case CPP_EQ_EQ:
9520 oprec = PREC_EQ;
9521 ocode = EQ_EXPR;
9522 break;
9523 case CPP_NOT_EQ:
9524 oprec = PREC_EQ;
9525 ocode = NE_EXPR;
9526 break;
9527 case CPP_AND:
9528 oprec = PREC_BITAND;
9529 ocode = BIT_AND_EXPR;
9530 break;
9531 case CPP_XOR:
9532 oprec = PREC_BITXOR;
9533 ocode = BIT_XOR_EXPR;
9534 break;
9535 case CPP_OR:
9536 oprec = PREC_BITOR;
9537 ocode = BIT_IOR_EXPR;
9538 break;
9539 case CPP_AND_AND:
9540 oprec = PREC_LOGAND;
9541 ocode = TRUTH_ANDIF_EXPR;
9542 break;
9543 case CPP_OR_OR:
9544 oprec = PREC_LOGOR;
9545 ocode = TRUTH_ORIF_EXPR;
9546 break;
9547 default:
9548 /* Not a binary operator, so end of the binary
9549 expression. */
9550 goto out;
9551 }
9552 binary_loc = c_parser_peek_token (parser)->location;
9553 while (oprec <= stack[sp].prec)
9554 POP;
9555 c_parser_consume_token (parser);
9556 switch (ocode)
9557 {
9558 case TRUTH_ANDIF_EXPR:
9559 src_range = stack[sp].expr.src_range;
9560 stack[sp].expr
9561 = convert_lvalue_to_rvalue (stack[sp].loc,
9562 stack[sp].expr, true, true);
9563 stack[sp].expr.value = c_objc_common_truthvalue_conversion
9564 (stack[sp].loc, default_conversion (stack[sp].expr.value));
9565 c_inhibit_evaluation_warnings += (stack[sp].expr.value
9566 == truthvalue_false_node);
9567 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
9568 break;
9569 case TRUTH_ORIF_EXPR:
9570 src_range = stack[sp].expr.src_range;
9571 stack[sp].expr
9572 = convert_lvalue_to_rvalue (stack[sp].loc,
9573 stack[sp].expr, true, true);
9574 stack[sp].expr.value = c_objc_common_truthvalue_conversion
9575 (stack[sp].loc, default_conversion (stack[sp].expr.value));
9576 c_inhibit_evaluation_warnings += (stack[sp].expr.value
9577 == truthvalue_true_node);
9578 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
9579 break;
9580 default:
9581 break;
9582 }
9583 sp++;
9584 stack[sp].loc = binary_loc;
9585 stack[sp].expr = c_parser_cast_expression (parser, NULL);
9586 stack[sp].prec = oprec;
9587 stack[sp].op = ocode;
9588 stack[sp].sizeof_arg = c_last_sizeof_arg;
9589 }
9590 out:
9591 while (sp > 0)
9592 POP;
9593 return stack[0].expr;
9594#undef POP
9595}
9596
9597/* Parse any storage class specifiers after an open parenthesis in a
9598 context where a compound literal is permitted. */
9599
9600static struct c_declspecs *
9601c_parser_compound_literal_scspecs (c_parser *parser)
9602{
9603 bool seen_scspec = false;
9604 struct c_declspecs *specs = build_null_declspecs ();
9605 while (c_parser_next_token_is (parser, type: CPP_KEYWORD))
9606 {
9607 switch (c_parser_peek_token (parser)->keyword)
9608 {
9609 case RID_CONSTEXPR:
9610 case RID_REGISTER:
9611 case RID_STATIC:
9612 case RID_THREAD:
9613 seen_scspec = true;
9614 declspecs_add_scspec (c_parser_peek_token (parser)->location,
9615 specs, c_parser_peek_token (parser)->value);
9616 c_parser_consume_token (parser);
9617 break;
9618 default:
9619 goto out;
9620 }
9621 }
9622 out:
9623 return seen_scspec ? specs : NULL;
9624}
9625
9626/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
9627 is not NULL then it is an Objective-C message expression which is the
9628 primary-expression starting the expression as an initializer.
9629
9630 cast-expression:
9631 unary-expression
9632 ( type-name ) unary-expression
9633*/
9634
9635static struct c_expr
9636c_parser_cast_expression (c_parser *parser, struct c_expr *after)
9637{
9638 location_t cast_loc = c_parser_peek_token (parser)->location;
9639 gcc_assert (!after || c_dialect_objc ());
9640 if (after)
9641 return c_parser_postfix_expression_after_primary (parser,
9642 loc: cast_loc, *after);
9643 /* If the expression begins with a parenthesized type name, it may
9644 be either a cast or a compound literal; we need to see whether
9645 the next character is '{' to tell the difference. If not, it is
9646 an unary expression. Full detection of unknown typenames here
9647 would require a 3-token lookahead. */
9648 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9649 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9650 {
9651 struct c_declspecs *scspecs;
9652 struct c_type_name *type_name;
9653 struct c_expr ret;
9654 struct c_expr expr;
9655 matching_parens parens;
9656 parens.consume_open (parser);
9657 scspecs = c_parser_compound_literal_scspecs (parser);
9658 type_name = c_parser_type_name (parser, alignas_ok: true);
9659 parens.skip_until_found_close (parser);
9660 if (type_name == NULL)
9661 {
9662 ret.set_error ();
9663 ret.original_code = ERROR_MARK;
9664 ret.original_type = NULL;
9665 return ret;
9666 }
9667
9668 /* Save casted types in the function's used types hash table. */
9669 used_types_insert (type_name->specs->type);
9670
9671 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9672 return c_parser_postfix_expression_after_paren_type (parser, scspecs,
9673 type_name,
9674 cast_loc);
9675 if (scspecs)
9676 error_at (cast_loc, "storage class specifier in cast");
9677 if (type_name->specs->alignas_p)
9678 error_at (type_name->specs->locations[cdw_alignas],
9679 "alignment specified for type name in cast");
9680 {
9681 location_t expr_loc = c_parser_peek_token (parser)->location;
9682 expr = c_parser_cast_expression (parser, NULL);
9683 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
9684 }
9685 ret.value = c_cast_expr (cast_loc, type_name, expr.value);
9686 if (ret.value && expr.value)
9687 set_c_expr_source_range (expr: &ret, start: cast_loc, finish: expr.get_finish ());
9688 ret.original_code = ERROR_MARK;
9689 ret.original_type = NULL;
9690 ret.m_decimal = 0;
9691 return ret;
9692 }
9693 else
9694 return c_parser_unary_expression (parser);
9695}
9696
9697/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
9698
9699 unary-expression:
9700 postfix-expression
9701 ++ unary-expression
9702 -- unary-expression
9703 unary-operator cast-expression
9704 sizeof unary-expression
9705 sizeof ( type-name )
9706
9707 unary-operator: one of
9708 & * + - ~ !
9709
9710 GNU extensions:
9711
9712 unary-expression:
9713 __alignof__ unary-expression
9714 __alignof__ ( type-name )
9715 && identifier
9716
9717 (C11 permits _Alignof with type names only.)
9718
9719 unary-operator: one of
9720 __extension__ __real__ __imag__
9721
9722 Transactional Memory:
9723
9724 unary-expression:
9725 transaction-expression
9726
9727 In addition, the GNU syntax treats ++ and -- as unary operators, so
9728 they may be applied to cast expressions with errors for non-lvalues
9729 given later. */
9730
9731static struct c_expr
9732c_parser_unary_expression (c_parser *parser)
9733{
9734 int ext;
9735 struct c_expr ret, op;
9736 location_t op_loc = c_parser_peek_token (parser)->location;
9737 location_t exp_loc;
9738 location_t finish;
9739 ret.original_code = ERROR_MARK;
9740 ret.original_type = NULL;
9741 switch (c_parser_peek_token (parser)->type)
9742 {
9743 case CPP_PLUS_PLUS:
9744 c_parser_consume_token (parser);
9745 exp_loc = c_parser_peek_token (parser)->location;
9746 op = c_parser_cast_expression (parser, NULL);
9747
9748 op = default_function_array_read_conversion (exp_loc, op);
9749 return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
9750 case CPP_MINUS_MINUS:
9751 c_parser_consume_token (parser);
9752 exp_loc = c_parser_peek_token (parser)->location;
9753 op = c_parser_cast_expression (parser, NULL);
9754
9755 op = default_function_array_read_conversion (exp_loc, op);
9756 return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
9757 case CPP_AND:
9758 c_parser_consume_token (parser);
9759 op = c_parser_cast_expression (parser, NULL);
9760 mark_exp_read (op.value);
9761 return parser_build_unary_op (op_loc, ADDR_EXPR, op);
9762 case CPP_MULT:
9763 {
9764 c_parser_consume_token (parser);
9765 exp_loc = c_parser_peek_token (parser)->location;
9766 op = c_parser_cast_expression (parser, NULL);
9767 finish = op.get_finish ();
9768 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9769 location_t combined_loc = make_location (caret: op_loc, start: op_loc, finish);
9770 ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
9771 ret.src_range.m_start = op_loc;
9772 ret.src_range.m_finish = finish;
9773 ret.m_decimal = 0;
9774 return ret;
9775 }
9776 case CPP_PLUS:
9777 if (!c_dialect_objc () && !in_system_header_at (loc: input_location))
9778 warning_at (op_loc,
9779 OPT_Wtraditional,
9780 "traditional C rejects the unary plus operator");
9781 c_parser_consume_token (parser);
9782 exp_loc = c_parser_peek_token (parser)->location;
9783 op = c_parser_cast_expression (parser, NULL);
9784 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9785 return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
9786 case CPP_MINUS:
9787 c_parser_consume_token (parser);
9788 exp_loc = c_parser_peek_token (parser)->location;
9789 op = c_parser_cast_expression (parser, NULL);
9790 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9791 return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
9792 case CPP_COMPL:
9793 c_parser_consume_token (parser);
9794 exp_loc = c_parser_peek_token (parser)->location;
9795 op = c_parser_cast_expression (parser, NULL);
9796 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9797 return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
9798 case CPP_NOT:
9799 c_parser_consume_token (parser);
9800 exp_loc = c_parser_peek_token (parser)->location;
9801 op = c_parser_cast_expression (parser, NULL);
9802 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9803 return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
9804 case CPP_AND_AND:
9805 /* Refer to the address of a label as a pointer. */
9806 c_parser_consume_token (parser);
9807 if (c_parser_next_token_is (parser, type: CPP_NAME))
9808 {
9809 ret.value = finish_label_address_expr
9810 (c_parser_peek_token (parser)->value, op_loc);
9811 set_c_expr_source_range (expr: &ret, start: op_loc,
9812 finish: c_parser_peek_token (parser)->get_finish ());
9813 c_parser_consume_token (parser);
9814 }
9815 else
9816 {
9817 c_parser_error (parser, gmsgid: "expected identifier");
9818 ret.set_error ();
9819 }
9820 return ret;
9821 case CPP_KEYWORD:
9822 switch (c_parser_peek_token (parser)->keyword)
9823 {
9824 case RID_SIZEOF:
9825 return c_parser_sizeof_expression (parser);
9826 case RID_ALIGNOF:
9827 return c_parser_alignof_expression (parser);
9828 case RID_BUILTIN_HAS_ATTRIBUTE:
9829 return c_parser_has_attribute_expression (parser);
9830 case RID_EXTENSION:
9831 c_parser_consume_token (parser);
9832 ext = disable_extension_diagnostics ();
9833 ret = c_parser_cast_expression (parser, NULL);
9834 restore_extension_diagnostics (flags: ext);
9835 return ret;
9836 case RID_REALPART:
9837 c_parser_consume_token (parser);
9838 exp_loc = c_parser_peek_token (parser)->location;
9839 op = c_parser_cast_expression (parser, NULL);
9840 op = default_function_array_conversion (exp_loc, op);
9841 return parser_build_unary_op (op_loc, REALPART_EXPR, op);
9842 case RID_IMAGPART:
9843 c_parser_consume_token (parser);
9844 exp_loc = c_parser_peek_token (parser)->location;
9845 op = c_parser_cast_expression (parser, NULL);
9846 op = default_function_array_conversion (exp_loc, op);
9847 return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
9848 case RID_TRANSACTION_ATOMIC:
9849 case RID_TRANSACTION_RELAXED:
9850 return c_parser_transaction_expression (parser,
9851 c_parser_peek_token (parser)->keyword);
9852 default:
9853 return c_parser_postfix_expression (parser);
9854 }
9855 default:
9856 return c_parser_postfix_expression (parser);
9857 }
9858}
9859
9860/* Parse a sizeof expression. */
9861
9862static struct c_expr
9863c_parser_sizeof_expression (c_parser *parser)
9864{
9865 struct c_expr expr;
9866 struct c_expr result;
9867 location_t expr_loc;
9868 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
9869
9870 location_t start;
9871 location_t finish = UNKNOWN_LOCATION;
9872
9873 start = c_parser_peek_token (parser)->location;
9874
9875 c_parser_consume_token (parser);
9876 c_inhibit_evaluation_warnings++;
9877 in_sizeof++;
9878 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9879 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9880 {
9881 /* Either sizeof ( type-name ) or sizeof unary-expression
9882 starting with a compound literal. */
9883 struct c_declspecs *scspecs;
9884 struct c_type_name *type_name;
9885 matching_parens parens;
9886 parens.consume_open (parser);
9887 expr_loc = c_parser_peek_token (parser)->location;
9888 scspecs = c_parser_compound_literal_scspecs (parser);
9889 type_name = c_parser_type_name (parser, alignas_ok: true);
9890 parens.skip_until_found_close (parser);
9891 finish = parser->tokens_buf[0].location;
9892 if (type_name == NULL)
9893 {
9894 struct c_expr ret;
9895 c_inhibit_evaluation_warnings--;
9896 in_sizeof--;
9897 ret.set_error ();
9898 ret.original_code = ERROR_MARK;
9899 ret.original_type = NULL;
9900 return ret;
9901 }
9902 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9903 {
9904 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
9905 type_name,
9906 expr_loc);
9907 finish = expr.get_finish ();
9908 goto sizeof_expr;
9909 }
9910 /* sizeof ( type-name ). */
9911 if (scspecs)
9912 error_at (expr_loc, "storage class specifier in %<sizeof%>");
9913 if (type_name->specs->alignas_p)
9914 error_at (type_name->specs->locations[cdw_alignas],
9915 "alignment specified for type name in %<sizeof%>");
9916 c_inhibit_evaluation_warnings--;
9917 in_sizeof--;
9918 result = c_expr_sizeof_type (expr_loc, type_name);
9919 }
9920 else
9921 {
9922 expr_loc = c_parser_peek_token (parser)->location;
9923 expr = c_parser_unary_expression (parser);
9924 finish = expr.get_finish ();
9925 sizeof_expr:
9926 c_inhibit_evaluation_warnings--;
9927 in_sizeof--;
9928 mark_exp_read (expr.value);
9929 if (TREE_CODE (expr.value) == COMPONENT_REF
9930 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
9931 error_at (expr_loc, "%<sizeof%> applied to a bit-field");
9932 result = c_expr_sizeof_expr (expr_loc, expr);
9933 }
9934 if (finish == UNKNOWN_LOCATION)
9935 finish = start;
9936 set_c_expr_source_range (expr: &result, start, finish);
9937 return result;
9938}
9939
9940/* Parse an alignof expression. */
9941
9942static struct c_expr
9943c_parser_alignof_expression (c_parser *parser)
9944{
9945 struct c_expr expr;
9946 location_t start_loc = c_parser_peek_token (parser)->location;
9947 location_t end_loc;
9948 tree alignof_spelling = c_parser_peek_token (parser)->value;
9949 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
9950 bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
9951 s2: "_Alignof") == 0
9952 || strcmp (IDENTIFIER_POINTER (alignof_spelling),
9953 s2: "alignof") == 0);
9954 /* A diagnostic is not required for the use of this identifier in
9955 the implementation namespace; only diagnose it for the C11 or C23
9956 spelling because of existing code using the other spellings. */
9957 if (is_c11_alignof)
9958 {
9959 if (flag_isoc99)
9960 pedwarn_c99 (start_loc, opt: OPT_Wpedantic, "ISO C99 does not support %qE",
9961 alignof_spelling);
9962 else
9963 pedwarn_c99 (start_loc, opt: OPT_Wpedantic, "ISO C90 does not support %qE",
9964 alignof_spelling);
9965 }
9966 c_parser_consume_token (parser);
9967 c_inhibit_evaluation_warnings++;
9968 in_alignof++;
9969 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9970 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9971 {
9972 /* Either __alignof__ ( type-name ) or __alignof__
9973 unary-expression starting with a compound literal. */
9974 location_t loc;
9975 struct c_declspecs *scspecs;
9976 struct c_type_name *type_name;
9977 struct c_expr ret;
9978 matching_parens parens;
9979 parens.consume_open (parser);
9980 loc = c_parser_peek_token (parser)->location;
9981 scspecs = c_parser_compound_literal_scspecs (parser);
9982 type_name = c_parser_type_name (parser, alignas_ok: true);
9983 end_loc = c_parser_peek_token (parser)->location;
9984 parens.skip_until_found_close (parser);
9985 if (type_name == NULL)
9986 {
9987 struct c_expr ret;
9988 c_inhibit_evaluation_warnings--;
9989 in_alignof--;
9990 ret.set_error ();
9991 ret.original_code = ERROR_MARK;
9992 ret.original_type = NULL;
9993 return ret;
9994 }
9995 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9996 {
9997 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
9998 type_name,
9999 loc);
10000 goto alignof_expr;
10001 }
10002 /* alignof ( type-name ). */
10003 if (scspecs)
10004 error_at (loc, "storage class specifier in %qE", alignof_spelling);
10005 if (type_name->specs->alignas_p)
10006 error_at (type_name->specs->locations[cdw_alignas],
10007 "alignment specified for type name in %qE",
10008 alignof_spelling);
10009 c_inhibit_evaluation_warnings--;
10010 in_alignof--;
10011 ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
10012 NULL, NULL),
10013 false, is_c11_alignof, 1);
10014 ret.original_code = ERROR_MARK;
10015 ret.original_type = NULL;
10016 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10017 ret.m_decimal = 0;
10018 return ret;
10019 }
10020 else
10021 {
10022 struct c_expr ret;
10023 expr = c_parser_unary_expression (parser);
10024 end_loc = expr.src_range.m_finish;
10025 alignof_expr:
10026 mark_exp_read (expr.value);
10027 c_inhibit_evaluation_warnings--;
10028 in_alignof--;
10029 if (is_c11_alignof)
10030 pedwarn (start_loc,
10031 OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
10032 alignof_spelling);
10033 ret.value = c_alignof_expr (start_loc, expr.value);
10034 ret.original_code = ERROR_MARK;
10035 ret.original_type = NULL;
10036 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10037 ret.m_decimal = 0;
10038 return ret;
10039 }
10040}
10041
10042/* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
10043 expression. */
10044
10045static struct c_expr
10046c_parser_has_attribute_expression (c_parser *parser)
10047{
10048 gcc_assert (c_parser_next_token_is_keyword (parser,
10049 RID_BUILTIN_HAS_ATTRIBUTE));
10050 location_t start = c_parser_peek_token (parser)->location;
10051 c_parser_consume_token (parser);
10052
10053 c_inhibit_evaluation_warnings++;
10054
10055 matching_parens parens;
10056 if (!parens.require_open (parser))
10057 {
10058 c_inhibit_evaluation_warnings--;
10059 in_typeof--;
10060
10061 struct c_expr result;
10062 result.set_error ();
10063 result.original_code = ERROR_MARK;
10064 result.original_type = NULL;
10065 return result;
10066 }
10067
10068 /* Treat the type argument the same way as in typeof for the purposes
10069 of warnings. FIXME: Generalize this so the warning refers to
10070 __builtin_has_attribute rather than typeof. */
10071 in_typeof++;
10072
10073 /* The first operand: one of DECL, EXPR, or TYPE. */
10074 tree oper = NULL_TREE;
10075 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
10076 {
10077 struct c_type_name *tname = c_parser_type_name (parser);
10078 in_typeof--;
10079 if (tname)
10080 {
10081 oper = groktypename (tname, NULL, NULL);
10082 pop_maybe_used (c_type_variably_modified_p (t: oper));
10083 }
10084 }
10085 else
10086 {
10087 struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
10088 c_inhibit_evaluation_warnings--;
10089 in_typeof--;
10090 if (cexpr.value != error_mark_node)
10091 {
10092 mark_exp_read (cexpr.value);
10093 oper = cexpr.value;
10094 tree etype = TREE_TYPE (oper);
10095 bool was_vm = c_type_variably_modified_p (t: etype);
10096 /* This is returned with the type so that when the type is
10097 evaluated, this can be evaluated. */
10098 if (was_vm)
10099 oper = c_fully_fold (oper, false, NULL);
10100 pop_maybe_used (was_vm);
10101 }
10102 }
10103
10104 struct c_expr result;
10105 result.original_code = ERROR_MARK;
10106 result.original_type = NULL;
10107
10108 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10109 {
10110 /* Consume the closing parenthesis if that's the next token
10111 in the likely case the built-in was invoked with fewer
10112 than two arguments. */
10113 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10114 c_parser_consume_token (parser);
10115 c_inhibit_evaluation_warnings--;
10116 result.set_error ();
10117 return result;
10118 }
10119
10120 bool save_translate_strings_p = parser->translate_strings_p;
10121
10122 location_t atloc = c_parser_peek_token (parser)->location;
10123 /* Parse a single attribute. Require no leading comma and do not
10124 allow empty attributes. */
10125 tree attr = c_parser_gnu_attribute (parser, NULL_TREE, expect_comma: false, empty_ok: false);
10126
10127 parser->translate_strings_p = save_translate_strings_p;
10128
10129 location_t finish = c_parser_peek_token (parser)->location;
10130 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10131 c_parser_consume_token (parser);
10132 else
10133 {
10134 c_parser_error (parser, gmsgid: "expected identifier");
10135 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10136
10137 result.set_error ();
10138 return result;
10139 }
10140
10141 if (!attr)
10142 {
10143 error_at (atloc, "expected identifier");
10144 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10145 msgid: "expected %<)%>");
10146 result.set_error ();
10147 return result;
10148 }
10149
10150 result.original_code = INTEGER_CST;
10151 result.original_type = boolean_type_node;
10152
10153 if (has_attribute (atloc, oper, attr, default_conversion))
10154 result.value = boolean_true_node;
10155 else
10156 result.value = boolean_false_node;
10157
10158 set_c_expr_source_range (expr: &result, start, finish);
10159 result.m_decimal = 0;
10160 return result;
10161}
10162
10163/* Helper function to read arguments of builtins which are interfaces
10164 for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
10165 others. The name of the builtin is passed using BNAME parameter.
10166 Function returns true if there were no errors while parsing and
10167 stores the arguments in CEXPR_LIST. If it returns true,
10168 *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
10169 parenthesis. */
10170static bool
10171c_parser_get_builtin_args (c_parser *parser, const char *bname,
10172 vec<c_expr_t, va_gc> **ret_cexpr_list,
10173 bool choose_expr_p,
10174 location_t *out_close_paren_loc)
10175{
10176 location_t loc = c_parser_peek_token (parser)->location;
10177 vec<c_expr_t, va_gc> *cexpr_list;
10178 c_expr_t expr;
10179 bool saved_force_folding_builtin_constant_p;
10180
10181 *ret_cexpr_list = NULL;
10182 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
10183 {
10184 error_at (loc, "cannot take address of %qs", bname);
10185 return false;
10186 }
10187
10188 c_parser_consume_token (parser);
10189
10190 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10191 {
10192 *out_close_paren_loc = c_parser_peek_token (parser)->location;
10193 c_parser_consume_token (parser);
10194 return true;
10195 }
10196
10197 saved_force_folding_builtin_constant_p
10198 = force_folding_builtin_constant_p;
10199 force_folding_builtin_constant_p |= choose_expr_p;
10200 expr = c_parser_expr_no_commas (parser, NULL);
10201 force_folding_builtin_constant_p
10202 = saved_force_folding_builtin_constant_p;
10203 vec_alloc (v&: cexpr_list, nelems: 1);
10204 vec_safe_push (v&: cexpr_list, obj: expr);
10205 while (c_parser_next_token_is (parser, type: CPP_COMMA))
10206 {
10207 c_parser_consume_token (parser);
10208 expr = c_parser_expr_no_commas (parser, NULL);
10209 vec_safe_push (v&: cexpr_list, obj: expr);
10210 }
10211
10212 *out_close_paren_loc = c_parser_peek_token (parser)->location;
10213 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
10214 return false;
10215
10216 *ret_cexpr_list = cexpr_list;
10217 return true;
10218}
10219
10220/* This represents a single generic-association. */
10221
10222struct c_generic_association
10223{
10224 /* The location of the starting token of the type. */
10225 location_t type_location;
10226 /* The association's type, or NULL_TREE for 'default'. */
10227 tree type;
10228 /* The association's expression. */
10229 struct c_expr expression;
10230};
10231
10232/* Parse a generic-selection. (C11 6.5.1.1).
10233
10234 generic-selection:
10235 _Generic ( assignment-expression , generic-assoc-list )
10236
10237 generic-assoc-list:
10238 generic-association
10239 generic-assoc-list , generic-association
10240
10241 generic-association:
10242 type-name : assignment-expression
10243 default : assignment-expression
10244*/
10245
10246static struct c_expr
10247c_parser_generic_selection (c_parser *parser)
10248{
10249 struct c_expr selector, error_expr;
10250 tree selector_type;
10251 struct c_generic_association matched_assoc;
10252 int match_found = -1;
10253 location_t generic_loc, selector_loc;
10254
10255 error_expr.original_code = ERROR_MARK;
10256 error_expr.original_type = NULL;
10257 error_expr.set_error ();
10258 matched_assoc.type_location = UNKNOWN_LOCATION;
10259 matched_assoc.type = NULL_TREE;
10260 matched_assoc.expression = error_expr;
10261
10262 gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
10263 generic_loc = c_parser_peek_token (parser)->location;
10264 c_parser_consume_token (parser);
10265 if (flag_isoc99)
10266 pedwarn_c99 (generic_loc, opt: OPT_Wpedantic,
10267 "ISO C99 does not support %<_Generic%>");
10268 else
10269 pedwarn_c99 (generic_loc, opt: OPT_Wpedantic,
10270 "ISO C90 does not support %<_Generic%>");
10271
10272 matching_parens parens;
10273 if (!parens.require_open (parser))
10274 return error_expr;
10275
10276 c_inhibit_evaluation_warnings++;
10277 selector_loc = c_parser_peek_token (parser)->location;
10278 selector = c_parser_expr_no_commas (parser, NULL);
10279 selector = default_function_array_conversion (selector_loc, selector);
10280 c_inhibit_evaluation_warnings--;
10281
10282 if (selector.value == error_mark_node)
10283 {
10284 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10285 return selector;
10286 }
10287 mark_exp_read (selector.value);
10288 selector_type = TREE_TYPE (selector.value);
10289 /* In ISO C terms, rvalues (including the controlling expression of
10290 _Generic) do not have qualified types. */
10291 if (TREE_CODE (selector_type) != ARRAY_TYPE)
10292 selector_type = TYPE_MAIN_VARIANT (selector_type);
10293 /* In ISO C terms, _Noreturn is not part of the type of expressions
10294 such as &abort, but in GCC it is represented internally as a type
10295 qualifier. */
10296 if (FUNCTION_POINTER_TYPE_P (selector_type)
10297 && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
10298 selector_type
10299 = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
10300
10301 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10302 {
10303 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10304 return error_expr;
10305 }
10306
10307 auto_vec<c_generic_association> associations;
10308 while (1)
10309 {
10310 struct c_generic_association assoc, *iter;
10311 unsigned int ix;
10312 c_token *token = c_parser_peek_token (parser);
10313
10314 assoc.type_location = token->location;
10315 if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
10316 {
10317 c_parser_consume_token (parser);
10318 assoc.type = NULL_TREE;
10319 }
10320 else
10321 {
10322 struct c_type_name *type_name;
10323
10324 type_name = c_parser_type_name (parser);
10325 if (type_name == NULL)
10326 {
10327 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10328 return error_expr;
10329 }
10330 assoc.type = groktypename (type_name, NULL, NULL);
10331 if (assoc.type == error_mark_node)
10332 {
10333 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10334 return error_expr;
10335 }
10336
10337 if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
10338 error_at (assoc.type_location,
10339 "%<_Generic%> association has function type");
10340 else if (!COMPLETE_TYPE_P (assoc.type))
10341 error_at (assoc.type_location,
10342 "%<_Generic%> association has incomplete type");
10343
10344 if (c_type_variably_modified_p (t: assoc.type))
10345 error_at (assoc.type_location,
10346 "%<_Generic%> association has "
10347 "variable length type");
10348 }
10349
10350 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
10351 {
10352 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10353 return error_expr;
10354 }
10355
10356 bool match = assoc.type == NULL_TREE
10357 || comptypes (assoc.type, selector_type);
10358
10359 if (!match)
10360 c_inhibit_evaluation_warnings++;
10361
10362 assoc.expression = c_parser_expr_no_commas (parser, NULL);
10363
10364 if (!match)
10365 c_inhibit_evaluation_warnings--;
10366
10367 if (assoc.expression.value == error_mark_node)
10368 {
10369 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10370 return error_expr;
10371 }
10372
10373 for (ix = 0; associations.iterate (ix, ptr: &iter); ++ix)
10374 {
10375 if (assoc.type == NULL_TREE)
10376 {
10377 if (iter->type == NULL_TREE)
10378 {
10379 error_at (assoc.type_location,
10380 "duplicate %<default%> case in %<_Generic%>");
10381 inform (iter->type_location, "original %<default%> is here");
10382 }
10383 }
10384 else if (iter->type != NULL_TREE)
10385 {
10386 if (comptypes (assoc.type, iter->type))
10387 {
10388 error_at (assoc.type_location,
10389 "%<_Generic%> specifies two compatible types");
10390 inform (iter->type_location, "compatible type is here");
10391 }
10392 }
10393 }
10394
10395 if (assoc.type == NULL_TREE)
10396 {
10397 if (match_found < 0)
10398 {
10399 matched_assoc = assoc;
10400 match_found = associations.length ();
10401 }
10402 }
10403 else if (match)
10404 {
10405 if (match_found < 0 || matched_assoc.type == NULL_TREE)
10406 {
10407 matched_assoc = assoc;
10408 match_found = associations.length ();
10409 }
10410 else
10411 {
10412 error_at (assoc.type_location,
10413 "%<_Generic%> selector matches multiple associations");
10414 inform (matched_assoc.type_location,
10415 "other match is here");
10416 }
10417 }
10418
10419 associations.safe_push (obj: assoc);
10420
10421 if (c_parser_peek_token (parser)->type != CPP_COMMA)
10422 break;
10423 c_parser_consume_token (parser);
10424 }
10425
10426 unsigned int ix;
10427 struct c_generic_association *iter;
10428 FOR_EACH_VEC_ELT (associations, ix, iter)
10429 if (ix != (unsigned) match_found)
10430 mark_exp_read (iter->expression.value);
10431
10432 if (!parens.require_close (parser))
10433 {
10434 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10435 return error_expr;
10436 }
10437
10438 if (match_found < 0)
10439 {
10440 error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
10441 "compatible with any association",
10442 selector_type);
10443 return error_expr;
10444 }
10445
10446 return matched_assoc.expression;
10447}
10448
10449/* Check the validity of a function pointer argument *EXPR (argument
10450 position POS) to __builtin_tgmath. Return the number of function
10451 arguments if possibly valid; return 0 having reported an error if
10452 not valid. */
10453
10454static unsigned int
10455check_tgmath_function (c_expr *expr, unsigned int pos)
10456{
10457 tree type = TREE_TYPE (expr->value);
10458 if (!FUNCTION_POINTER_TYPE_P (type))
10459 {
10460 error_at (expr->get_location (),
10461 "argument %u of %<__builtin_tgmath%> is not a function pointer",
10462 pos);
10463 return 0;
10464 }
10465 type = TREE_TYPE (type);
10466 if (!prototype_p (type))
10467 {
10468 error_at (expr->get_location (),
10469 "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
10470 return 0;
10471 }
10472 if (stdarg_p (type))
10473 {
10474 error_at (expr->get_location (),
10475 "argument %u of %<__builtin_tgmath%> has variable arguments",
10476 pos);
10477 return 0;
10478 }
10479 unsigned int nargs = 0;
10480 function_args_iterator iter;
10481 tree t;
10482 FOREACH_FUNCTION_ARGS (type, t, iter)
10483 {
10484 if (t == void_type_node)
10485 break;
10486 nargs++;
10487 }
10488 if (nargs == 0)
10489 {
10490 error_at (expr->get_location (),
10491 "argument %u of %<__builtin_tgmath%> has no arguments", pos);
10492 return 0;
10493 }
10494 return nargs;
10495}
10496
10497/* Ways in which a parameter or return value of a type-generic macro
10498 may vary between the different functions the macro may call. */
10499enum tgmath_parm_kind
10500 {
10501 tgmath_fixed, tgmath_real, tgmath_complex
10502 };
10503
10504/* Helper function for c_parser_postfix_expression. Parse predefined
10505 identifiers. */
10506
10507static struct c_expr
10508c_parser_predefined_identifier (c_parser *parser)
10509{
10510 location_t loc = c_parser_peek_token (parser)->location;
10511 switch (c_parser_peek_token (parser)->keyword)
10512 {
10513 case RID_FUNCTION_NAME:
10514 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
10515 "identifier", "__FUNCTION__");
10516 break;
10517 case RID_PRETTY_FUNCTION_NAME:
10518 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
10519 "identifier", "__PRETTY_FUNCTION__");
10520 break;
10521 case RID_C99_FUNCTION_NAME:
10522 pedwarn_c90 (loc, opt: OPT_Wpedantic, "ISO C90 does not support "
10523 "%<__func__%> predefined identifier");
10524 break;
10525 default:
10526 gcc_unreachable ();
10527 }
10528
10529 struct c_expr expr;
10530 expr.original_code = ERROR_MARK;
10531 expr.original_type = NULL;
10532 expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
10533 c_parser_peek_token (parser)->value);
10534 set_c_expr_source_range (expr: &expr, start: loc, finish: loc);
10535 expr.m_decimal = 0;
10536 c_parser_consume_token (parser);
10537 return expr;
10538}
10539
10540/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
10541 C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
10542 call c_parser_postfix_expression_after_paren_type on encountering them.
10543
10544 postfix-expression:
10545 primary-expression
10546 postfix-expression [ expression ]
10547 postfix-expression ( argument-expression-list[opt] )
10548 postfix-expression . identifier
10549 postfix-expression -> identifier
10550 postfix-expression ++
10551 postfix-expression --
10552 ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
10553 ( storage-class-specifiers[opt] type-name ) { initializer-list , }
10554
10555 argument-expression-list:
10556 argument-expression
10557 argument-expression-list , argument-expression
10558
10559 primary-expression:
10560 identifier
10561 constant
10562 string-literal
10563 ( expression )
10564 generic-selection
10565
10566 GNU extensions:
10567
10568 primary-expression:
10569 __func__
10570 (treated as a keyword in GNU C)
10571 __FUNCTION__
10572 __PRETTY_FUNCTION__
10573 ( compound-statement )
10574 __builtin_va_arg ( assignment-expression , type-name )
10575 __builtin_offsetof ( type-name , offsetof-member-designator )
10576 __builtin_choose_expr ( assignment-expression ,
10577 assignment-expression ,
10578 assignment-expression )
10579 __builtin_types_compatible_p ( type-name , type-name )
10580 __builtin_tgmath ( expr-list )
10581 __builtin_complex ( assignment-expression , assignment-expression )
10582 __builtin_shuffle ( assignment-expression , assignment-expression )
10583 __builtin_shuffle ( assignment-expression ,
10584 assignment-expression ,
10585 assignment-expression, )
10586 __builtin_convertvector ( assignment-expression , type-name )
10587 __builtin_assoc_barrier ( assignment-expression )
10588
10589 offsetof-member-designator:
10590 identifier
10591 offsetof-member-designator . identifier
10592 offsetof-member-designator [ expression ]
10593
10594 Objective-C:
10595
10596 primary-expression:
10597 [ objc-receiver objc-message-args ]
10598 @selector ( objc-selector-arg )
10599 @protocol ( identifier )
10600 @encode ( type-name )
10601 objc-string-literal
10602 Classname . identifier
10603*/
10604
10605static struct c_expr
10606c_parser_postfix_expression (c_parser *parser)
10607{
10608 struct c_expr expr, e1;
10609 struct c_type_name *t1, *t2;
10610 location_t loc = c_parser_peek_token (parser)->location;
10611 source_range tok_range = c_parser_peek_token (parser)->get_range ();
10612 expr.original_code = ERROR_MARK;
10613 expr.original_type = NULL;
10614 expr.m_decimal = 0;
10615 switch (c_parser_peek_token (parser)->type)
10616 {
10617 case CPP_NUMBER:
10618 expr.value = c_parser_peek_token (parser)->value;
10619 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10620 loc = c_parser_peek_token (parser)->location;
10621 expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
10622 c_parser_consume_token (parser);
10623 if (TREE_CODE (expr.value) == FIXED_CST
10624 && !targetm.fixed_point_supported_p ())
10625 {
10626 error_at (loc, "fixed-point types not supported for this target");
10627 expr.set_error ();
10628 }
10629 break;
10630 case CPP_CHAR:
10631 case CPP_CHAR16:
10632 case CPP_CHAR32:
10633 case CPP_UTF8CHAR:
10634 case CPP_WCHAR:
10635 expr.value = c_parser_peek_token (parser)->value;
10636 /* For the purpose of warning when a pointer is compared with
10637 a zero character constant. */
10638 expr.original_type = char_type_node;
10639 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10640 c_parser_consume_token (parser);
10641 break;
10642 case CPP_STRING:
10643 case CPP_STRING16:
10644 case CPP_STRING32:
10645 case CPP_WSTRING:
10646 case CPP_UTF8STRING:
10647 expr = c_parser_string_literal (parser, translate: parser->translate_strings_p,
10648 wide_ok: true);
10649 break;
10650 case CPP_OBJC_STRING:
10651 gcc_assert (c_dialect_objc ());
10652 expr.value
10653 = objc_build_string_object (c_parser_peek_token (parser)->value);
10654 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10655 c_parser_consume_token (parser);
10656 break;
10657 case CPP_NAME:
10658 switch (c_parser_peek_token (parser)->id_kind)
10659 {
10660 case C_ID_ID:
10661 {
10662 tree id = c_parser_peek_token (parser)->value;
10663 c_parser_consume_token (parser);
10664 expr.value = build_external_ref (loc, id,
10665 (c_parser_peek_token (parser)->type
10666 == CPP_OPEN_PAREN),
10667 &expr.original_type);
10668 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10669 break;
10670 }
10671 case C_ID_CLASSNAME:
10672 {
10673 /* Here we parse the Objective-C 2.0 Class.name dot
10674 syntax. */
10675 tree class_name = c_parser_peek_token (parser)->value;
10676 tree component;
10677 c_parser_consume_token (parser);
10678 gcc_assert (c_dialect_objc ());
10679 if (!c_parser_require (parser, type: CPP_DOT, msgid: "expected %<.%>"))
10680 {
10681 expr.set_error ();
10682 break;
10683 }
10684 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
10685 {
10686 c_parser_error (parser, gmsgid: "expected identifier");
10687 expr.set_error ();
10688 break;
10689 }
10690 c_token *component_tok = c_parser_peek_token (parser);
10691 component = component_tok->value;
10692 location_t end_loc = component_tok->get_finish ();
10693 c_parser_consume_token (parser);
10694 expr.value = objc_build_class_component_ref (class_name,
10695 component);
10696 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
10697 break;
10698 }
10699 default:
10700 c_parser_error (parser, gmsgid: "expected expression");
10701 expr.set_error ();
10702 break;
10703 }
10704 break;
10705 case CPP_OPEN_PAREN:
10706 /* A parenthesized expression, statement expression or compound
10707 literal. */
10708 if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
10709 {
10710 /* A statement expression. */
10711 tree stmt;
10712 location_t brace_loc;
10713 bool save_c_omp_array_section_p = c_omp_array_section_p;
10714 c_parser_consume_token (parser);
10715 brace_loc = c_parser_peek_token (parser)->location;
10716 c_parser_consume_token (parser);
10717 /* If we've not yet started the current function's statement list,
10718 or we're in the parameter scope of an old-style function
10719 declaration, statement expressions are not allowed. */
10720 if (!building_stmt_list_p () || old_style_parameter_scope ())
10721 {
10722 error_at (loc, "braced-group within expression allowed "
10723 "only inside a function");
10724 parser->error = true;
10725 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
10726 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10727 expr.set_error ();
10728 break;
10729 }
10730 c_omp_array_section_p = false;
10731 stmt = c_begin_stmt_expr ();
10732 c_parser_compound_statement_nostart (parser);
10733 location_t close_loc = c_parser_peek_token (parser)->location;
10734 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10735 msgid: "expected %<)%>");
10736 pedwarn (loc, OPT_Wpedantic,
10737 "ISO C forbids braced-groups within expressions");
10738 expr.value = c_finish_stmt_expr (brace_loc, stmt);
10739 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
10740 mark_exp_read (expr.value);
10741 c_omp_array_section_p = save_c_omp_array_section_p;
10742 }
10743 else
10744 {
10745 /* A parenthesized expression. */
10746 location_t loc_open_paren = c_parser_peek_token (parser)->location;
10747 c_parser_consume_token (parser);
10748 expr = c_parser_expression (parser);
10749 if (TREE_CODE (expr.value) == MODIFY_EXPR)
10750 suppress_warning (expr.value, OPT_Wparentheses);
10751 if (expr.original_code != C_MAYBE_CONST_EXPR
10752 && expr.original_code != SIZEOF_EXPR)
10753 expr.original_code = ERROR_MARK;
10754 /* Remember that we saw ( ) around the sizeof. */
10755 if (expr.original_code == SIZEOF_EXPR)
10756 expr.original_code = PAREN_SIZEOF_EXPR;
10757 /* Don't change EXPR.ORIGINAL_TYPE. */
10758 location_t loc_close_paren = c_parser_peek_token (parser)->location;
10759 set_c_expr_source_range (expr: &expr, start: loc_open_paren, finish: loc_close_paren);
10760 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10761 msgid: "expected %<)%>", matching_location: loc_open_paren);
10762 }
10763 break;
10764 case CPP_KEYWORD:
10765 switch (c_parser_peek_token (parser)->keyword)
10766 {
10767 case RID_FUNCTION_NAME:
10768 case RID_PRETTY_FUNCTION_NAME:
10769 case RID_C99_FUNCTION_NAME:
10770 expr = c_parser_predefined_identifier (parser);
10771 break;
10772 case RID_VA_ARG:
10773 {
10774 location_t start_loc = loc;
10775 c_parser_consume_token (parser);
10776 matching_parens parens;
10777 if (!parens.require_open (parser))
10778 {
10779 expr.set_error ();
10780 break;
10781 }
10782 e1 = c_parser_expr_no_commas (parser, NULL);
10783 mark_exp_read (e1.value);
10784 e1.value = c_fully_fold (e1.value, false, NULL);
10785 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10786 {
10787 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10788 expr.set_error ();
10789 break;
10790 }
10791 loc = c_parser_peek_token (parser)->location;
10792 t1 = c_parser_type_name (parser);
10793 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
10794 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10795 msgid: "expected %<)%>");
10796 if (t1 == NULL)
10797 {
10798 expr.set_error ();
10799 }
10800 else
10801 {
10802 tree type_expr = NULL_TREE;
10803 expr.value = c_build_va_arg (start_loc, e1.value, loc,
10804 groktypename (t1, &type_expr, NULL));
10805 if (type_expr)
10806 {
10807 expr.value = build2 (C_MAYBE_CONST_EXPR,
10808 TREE_TYPE (expr.value), type_expr,
10809 expr.value);
10810 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
10811 }
10812 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
10813 }
10814 }
10815 break;
10816 case RID_OFFSETOF:
10817 {
10818 c_parser_consume_token (parser);
10819 matching_parens parens;
10820 if (!parens.require_open (parser))
10821 {
10822 expr.set_error ();
10823 break;
10824 }
10825 t1 = c_parser_type_name (parser);
10826 if (t1 == NULL)
10827 parser->error = true;
10828 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10829 gcc_assert (parser->error);
10830 if (parser->error)
10831 {
10832 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10833 expr.set_error ();
10834 break;
10835 }
10836 tree type = groktypename (t1, NULL, NULL);
10837 tree offsetof_ref;
10838 if (type == error_mark_node)
10839 offsetof_ref = error_mark_node;
10840 else
10841 {
10842 offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
10843 SET_EXPR_LOCATION (offsetof_ref, loc);
10844 }
10845 /* Parse the second argument to __builtin_offsetof. We
10846 must have one identifier, and beyond that we want to
10847 accept sub structure and sub array references. */
10848 if (c_parser_next_token_is (parser, type: CPP_NAME))
10849 {
10850 c_token *comp_tok = c_parser_peek_token (parser);
10851 offsetof_ref
10852 = build_component_ref (loc, offsetof_ref, comp_tok->value,
10853 comp_tok->location, UNKNOWN_LOCATION);
10854 c_parser_consume_token (parser);
10855 while (c_parser_next_token_is (parser, type: CPP_DOT)
10856 || c_parser_next_token_is (parser,
10857 type: CPP_OPEN_SQUARE)
10858 || c_parser_next_token_is (parser,
10859 type: CPP_DEREF))
10860 {
10861 if (c_parser_next_token_is (parser, type: CPP_DEREF))
10862 {
10863 loc = c_parser_peek_token (parser)->location;
10864 offsetof_ref = build_array_ref (loc,
10865 offsetof_ref,
10866 integer_zero_node);
10867 goto do_dot;
10868 }
10869 else if (c_parser_next_token_is (parser, type: CPP_DOT))
10870 {
10871 do_dot:
10872 c_parser_consume_token (parser);
10873 if (c_parser_next_token_is_not (parser,
10874 type: CPP_NAME))
10875 {
10876 c_parser_error (parser, gmsgid: "expected identifier");
10877 break;
10878 }
10879 c_token *comp_tok = c_parser_peek_token (parser);
10880 offsetof_ref
10881 = build_component_ref (loc, offsetof_ref,
10882 comp_tok->value,
10883 comp_tok->location,
10884 UNKNOWN_LOCATION);
10885 c_parser_consume_token (parser);
10886 }
10887 else
10888 {
10889 struct c_expr ce;
10890 tree idx;
10891 loc = c_parser_peek_token (parser)->location;
10892 c_parser_consume_token (parser);
10893 ce = c_parser_expression (parser);
10894 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
10895 idx = ce.value;
10896 idx = c_fully_fold (idx, false, NULL);
10897 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
10898 msgid: "expected %<]%>");
10899 offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
10900 }
10901 }
10902 }
10903 else
10904 c_parser_error (parser, gmsgid: "expected identifier");
10905 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
10906 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10907 msgid: "expected %<)%>");
10908 expr.value = fold_offsetof (offsetof_ref);
10909 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
10910 }
10911 break;
10912 case RID_CHOOSE_EXPR:
10913 {
10914 vec<c_expr_t, va_gc> *cexpr_list;
10915 c_expr_t *e1_p, *e2_p, *e3_p;
10916 tree c;
10917 location_t close_paren_loc;
10918
10919 c_parser_consume_token (parser);
10920 if (!c_parser_get_builtin_args (parser,
10921 bname: "__builtin_choose_expr",
10922 ret_cexpr_list: &cexpr_list, choose_expr_p: true,
10923 out_close_paren_loc: &close_paren_loc))
10924 {
10925 expr.set_error ();
10926 break;
10927 }
10928
10929 if (vec_safe_length (v: cexpr_list) != 3)
10930 {
10931 error_at (loc, "wrong number of arguments to "
10932 "%<__builtin_choose_expr%>");
10933 expr.set_error ();
10934 break;
10935 }
10936
10937 e1_p = &(*cexpr_list)[0];
10938 e2_p = &(*cexpr_list)[1];
10939 e3_p = &(*cexpr_list)[2];
10940
10941 c = e1_p->value;
10942 mark_exp_read (e2_p->value);
10943 mark_exp_read (e3_p->value);
10944 if (TREE_CODE (c) != INTEGER_CST
10945 || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
10946 error_at (loc,
10947 "first argument to %<__builtin_choose_expr%> not"
10948 " a constant");
10949 constant_expression_warning (c);
10950 expr = integer_zerop (c) ? *e3_p : *e2_p;
10951 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
10952 break;
10953 }
10954 case RID_TYPES_COMPATIBLE_P:
10955 {
10956 c_parser_consume_token (parser);
10957 matching_parens parens;
10958 if (!parens.require_open (parser))
10959 {
10960 expr.set_error ();
10961 break;
10962 }
10963 t1 = c_parser_type_name (parser);
10964 if (t1 == NULL)
10965 {
10966 expr.set_error ();
10967 break;
10968 }
10969 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10970 {
10971 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10972 expr.set_error ();
10973 break;
10974 }
10975 t2 = c_parser_type_name (parser);
10976 if (t2 == NULL)
10977 {
10978 expr.set_error ();
10979 break;
10980 }
10981 location_t close_paren_loc = c_parser_peek_token (parser)->location;
10982 parens.skip_until_found_close (parser);
10983 tree e1, e2;
10984 e1 = groktypename (t1, NULL, NULL);
10985 e2 = groktypename (t2, NULL, NULL);
10986 if (e1 == error_mark_node || e2 == error_mark_node)
10987 {
10988 expr.set_error ();
10989 break;
10990 }
10991
10992 e1 = TYPE_MAIN_VARIANT (e1);
10993 e2 = TYPE_MAIN_VARIANT (e2);
10994
10995 expr.value
10996 = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
10997 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
10998 }
10999 break;
11000 case RID_BUILTIN_TGMATH:
11001 {
11002 vec<c_expr_t, va_gc> *cexpr_list;
11003 location_t close_paren_loc;
11004
11005 c_parser_consume_token (parser);
11006 if (!c_parser_get_builtin_args (parser,
11007 bname: "__builtin_tgmath",
11008 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11009 out_close_paren_loc: &close_paren_loc))
11010 {
11011 expr.set_error ();
11012 break;
11013 }
11014
11015 if (vec_safe_length (v: cexpr_list) < 3)
11016 {
11017 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11018 expr.set_error ();
11019 break;
11020 }
11021
11022 unsigned int i;
11023 c_expr_t *p;
11024 FOR_EACH_VEC_ELT (*cexpr_list, i, p)
11025 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11026 unsigned int nargs = check_tgmath_function (expr: &(*cexpr_list)[0], pos: 1);
11027 if (nargs == 0)
11028 {
11029 expr.set_error ();
11030 break;
11031 }
11032 if (vec_safe_length (v: cexpr_list) < nargs)
11033 {
11034 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11035 expr.set_error ();
11036 break;
11037 }
11038 unsigned int num_functions = vec_safe_length (v: cexpr_list) - nargs;
11039 if (num_functions < 2)
11040 {
11041 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11042 expr.set_error ();
11043 break;
11044 }
11045
11046 /* The first NUM_FUNCTIONS expressions are the function
11047 pointers. The remaining NARGS expressions are the
11048 arguments that are to be passed to one of those
11049 functions, chosen following <tgmath.h> rules. */
11050 for (unsigned int j = 1; j < num_functions; j++)
11051 {
11052 unsigned int this_nargs
11053 = check_tgmath_function (expr: &(*cexpr_list)[j], pos: j + 1);
11054 if (this_nargs == 0)
11055 {
11056 expr.set_error ();
11057 goto out;
11058 }
11059 if (this_nargs != nargs)
11060 {
11061 error_at ((*cexpr_list)[j].get_location (),
11062 "argument %u of %<__builtin_tgmath%> has "
11063 "wrong number of arguments", j + 1);
11064 expr.set_error ();
11065 goto out;
11066 }
11067 }
11068
11069 /* The functions all have the same number of arguments.
11070 Determine whether arguments and return types vary in
11071 ways permitted for <tgmath.h> functions. */
11072 /* The first entry in each of these vectors is for the
11073 return type, subsequent entries for parameter
11074 types. */
11075 auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
11076 auto_vec<tree> parm_first (nargs + 1);
11077 auto_vec<bool> parm_complex (nargs + 1);
11078 auto_vec<bool> parm_varies (nargs + 1);
11079 tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
11080 tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
11081 parm_first.quick_push (obj: first_ret);
11082 parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
11083 parm_varies.quick_push (obj: false);
11084 function_args_iterator iter;
11085 tree t;
11086 unsigned int argpos;
11087 FOREACH_FUNCTION_ARGS (first_type, t, iter)
11088 {
11089 if (t == void_type_node)
11090 break;
11091 parm_first.quick_push (TYPE_MAIN_VARIANT (t));
11092 parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
11093 parm_varies.quick_push (obj: false);
11094 }
11095 for (unsigned int j = 1; j < num_functions; j++)
11096 {
11097 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11098 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
11099 if (ret != parm_first[0])
11100 {
11101 parm_varies[0] = true;
11102 if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
11103 && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
11104 {
11105 error_at ((*cexpr_list)[0].get_location (),
11106 "invalid type-generic return type for "
11107 "argument %u of %<__builtin_tgmath%>",
11108 1);
11109 expr.set_error ();
11110 goto out;
11111 }
11112 if (!SCALAR_FLOAT_TYPE_P (ret)
11113 && !COMPLEX_FLOAT_TYPE_P (ret))
11114 {
11115 error_at ((*cexpr_list)[j].get_location (),
11116 "invalid type-generic return type for "
11117 "argument %u of %<__builtin_tgmath%>",
11118 j + 1);
11119 expr.set_error ();
11120 goto out;
11121 }
11122 }
11123 if (TREE_CODE (ret) == COMPLEX_TYPE)
11124 parm_complex[0] = true;
11125 argpos = 1;
11126 FOREACH_FUNCTION_ARGS (type, t, iter)
11127 {
11128 if (t == void_type_node)
11129 break;
11130 t = TYPE_MAIN_VARIANT (t);
11131 if (t != parm_first[argpos])
11132 {
11133 parm_varies[argpos] = true;
11134 if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
11135 && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
11136 {
11137 error_at ((*cexpr_list)[0].get_location (),
11138 "invalid type-generic type for "
11139 "argument %u of argument %u of "
11140 "%<__builtin_tgmath%>", argpos, 1);
11141 expr.set_error ();
11142 goto out;
11143 }
11144 if (!SCALAR_FLOAT_TYPE_P (t)
11145 && !COMPLEX_FLOAT_TYPE_P (t))
11146 {
11147 error_at ((*cexpr_list)[j].get_location (),
11148 "invalid type-generic type for "
11149 "argument %u of argument %u of "
11150 "%<__builtin_tgmath%>", argpos, j + 1);
11151 expr.set_error ();
11152 goto out;
11153 }
11154 }
11155 if (TREE_CODE (t) == COMPLEX_TYPE)
11156 parm_complex[argpos] = true;
11157 argpos++;
11158 }
11159 }
11160 enum tgmath_parm_kind max_variation = tgmath_fixed;
11161 for (unsigned int j = 0; j <= nargs; j++)
11162 {
11163 enum tgmath_parm_kind this_kind;
11164 if (parm_varies[j])
11165 {
11166 if (parm_complex[j])
11167 max_variation = this_kind = tgmath_complex;
11168 else
11169 {
11170 this_kind = tgmath_real;
11171 if (max_variation != tgmath_complex)
11172 max_variation = tgmath_real;
11173 }
11174 }
11175 else
11176 this_kind = tgmath_fixed;
11177 parm_kind.quick_push (obj: this_kind);
11178 }
11179 if (max_variation == tgmath_fixed)
11180 {
11181 error_at (loc, "function arguments of %<__builtin_tgmath%> "
11182 "all have the same type");
11183 expr.set_error ();
11184 break;
11185 }
11186
11187 /* Identify a parameter (not the return type) that varies,
11188 including with complex types if any variation includes
11189 complex types; there must be at least one such
11190 parameter. */
11191 unsigned int tgarg = 0;
11192 for (unsigned int j = 1; j <= nargs; j++)
11193 if (parm_kind[j] == max_variation)
11194 {
11195 tgarg = j;
11196 break;
11197 }
11198 if (tgarg == 0)
11199 {
11200 error_at (loc, "function arguments of %<__builtin_tgmath%> "
11201 "lack type-generic parameter");
11202 expr.set_error ();
11203 break;
11204 }
11205
11206 /* Determine the type of the relevant parameter for each
11207 function. */
11208 auto_vec<tree> tg_type (num_functions);
11209 for (unsigned int j = 0; j < num_functions; j++)
11210 {
11211 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11212 argpos = 1;
11213 FOREACH_FUNCTION_ARGS (type, t, iter)
11214 {
11215 if (argpos == tgarg)
11216 {
11217 tg_type.quick_push (TYPE_MAIN_VARIANT (t));
11218 break;
11219 }
11220 argpos++;
11221 }
11222 }
11223
11224 /* Verify that the corresponding types are different for
11225 all the listed functions. Also determine whether all
11226 the types are complex, whether all the types are
11227 standard or binary, and whether all the types are
11228 decimal. */
11229 bool all_complex = true;
11230 bool all_binary = true;
11231 bool all_decimal = true;
11232 hash_set<tree> tg_types;
11233 FOR_EACH_VEC_ELT (tg_type, i, t)
11234 {
11235 if (TREE_CODE (t) == COMPLEX_TYPE)
11236 all_decimal = false;
11237 else
11238 {
11239 all_complex = false;
11240 if (DECIMAL_FLOAT_TYPE_P (t))
11241 all_binary = false;
11242 else
11243 all_decimal = false;
11244 }
11245 if (tg_types.add (k: t))
11246 {
11247 error_at ((*cexpr_list)[i].get_location (),
11248 "duplicate type-generic parameter type for "
11249 "function argument %u of %<__builtin_tgmath%>",
11250 i + 1);
11251 expr.set_error ();
11252 goto out;
11253 }
11254 }
11255
11256 /* Verify that other parameters and the return type whose
11257 types vary have their types varying in the correct
11258 way. */
11259 for (unsigned int j = 0; j < num_functions; j++)
11260 {
11261 tree exp_type = tg_type[j];
11262 tree exp_real_type = exp_type;
11263 if (TREE_CODE (exp_type) == COMPLEX_TYPE)
11264 exp_real_type = TREE_TYPE (exp_type);
11265 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11266 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
11267 if ((parm_kind[0] == tgmath_complex && ret != exp_type)
11268 || (parm_kind[0] == tgmath_real && ret != exp_real_type))
11269 {
11270 error_at ((*cexpr_list)[j].get_location (),
11271 "bad return type for function argument %u "
11272 "of %<__builtin_tgmath%>", j + 1);
11273 expr.set_error ();
11274 goto out;
11275 }
11276 argpos = 1;
11277 FOREACH_FUNCTION_ARGS (type, t, iter)
11278 {
11279 if (t == void_type_node)
11280 break;
11281 t = TYPE_MAIN_VARIANT (t);
11282 if ((parm_kind[argpos] == tgmath_complex
11283 && t != exp_type)
11284 || (parm_kind[argpos] == tgmath_real
11285 && t != exp_real_type))
11286 {
11287 error_at ((*cexpr_list)[j].get_location (),
11288 "bad type for argument %u of "
11289 "function argument %u of "
11290 "%<__builtin_tgmath%>", argpos, j + 1);
11291 expr.set_error ();
11292 goto out;
11293 }
11294 argpos++;
11295 }
11296 }
11297
11298 /* The functions listed are a valid set of functions for a
11299 <tgmath.h> macro to select between. Identify the
11300 matching function, if any. First, the argument types
11301 must be combined following <tgmath.h> rules. Integer
11302 types are treated as _Decimal64 if any type-generic
11303 argument is decimal, or if the only alternatives for
11304 type-generic arguments are of decimal types, and are
11305 otherwise treated as _Float32x (or _Complex _Float32x
11306 for complex integer types) if any type-generic argument
11307 has _FloatNx type, otherwise as double (or _Complex
11308 double for complex integer types). After that
11309 adjustment, types are combined following the usual
11310 arithmetic conversions. If the function only accepts
11311 complex arguments, a complex type is produced. */
11312 bool arg_complex = all_complex;
11313 bool arg_binary = all_binary;
11314 bool arg_int_decimal = all_decimal;
11315 bool arg_int_floatnx = false;
11316 for (unsigned int j = 1; j <= nargs; j++)
11317 {
11318 if (parm_kind[j] == tgmath_fixed)
11319 continue;
11320 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
11321 tree type = TREE_TYPE (ce->value);
11322 if (!INTEGRAL_TYPE_P (type)
11323 && !SCALAR_FLOAT_TYPE_P (type)
11324 && TREE_CODE (type) != COMPLEX_TYPE)
11325 {
11326 error_at (ce->get_location (),
11327 "invalid type of argument %u of type-generic "
11328 "function", j);
11329 expr.set_error ();
11330 goto out;
11331 }
11332 if (DECIMAL_FLOAT_TYPE_P (type))
11333 {
11334 arg_int_decimal = true;
11335 if (all_complex)
11336 {
11337 error_at (ce->get_location (),
11338 "decimal floating-point argument %u to "
11339 "complex-only type-generic function", j);
11340 expr.set_error ();
11341 goto out;
11342 }
11343 else if (all_binary)
11344 {
11345 error_at (ce->get_location (),
11346 "decimal floating-point argument %u to "
11347 "binary-only type-generic function", j);
11348 expr.set_error ();
11349 goto out;
11350 }
11351 else if (arg_complex)
11352 {
11353 error_at (ce->get_location (),
11354 "both complex and decimal floating-point "
11355 "arguments to type-generic function");
11356 expr.set_error ();
11357 goto out;
11358 }
11359 else if (arg_binary)
11360 {
11361 error_at (ce->get_location (),
11362 "both binary and decimal floating-point "
11363 "arguments to type-generic function");
11364 expr.set_error ();
11365 goto out;
11366 }
11367 }
11368 else if (TREE_CODE (type) == COMPLEX_TYPE)
11369 {
11370 arg_complex = true;
11371 if (COMPLEX_FLOAT_TYPE_P (type))
11372 arg_binary = true;
11373 if (all_decimal)
11374 {
11375 error_at (ce->get_location (),
11376 "complex argument %u to "
11377 "decimal-only type-generic function", j);
11378 expr.set_error ();
11379 goto out;
11380 }
11381 else if (arg_int_decimal)
11382 {
11383 error_at (ce->get_location (),
11384 "both complex and decimal floating-point "
11385 "arguments to type-generic function");
11386 expr.set_error ();
11387 goto out;
11388 }
11389 }
11390 else if (SCALAR_FLOAT_TYPE_P (type))
11391 {
11392 arg_binary = true;
11393 if (all_decimal)
11394 {
11395 error_at (ce->get_location (),
11396 "binary argument %u to "
11397 "decimal-only type-generic function", j);
11398 expr.set_error ();
11399 goto out;
11400 }
11401 else if (arg_int_decimal)
11402 {
11403 error_at (ce->get_location (),
11404 "both binary and decimal floating-point "
11405 "arguments to type-generic function");
11406 expr.set_error ();
11407 goto out;
11408 }
11409 }
11410 tree rtype = TYPE_MAIN_VARIANT (type);
11411 if (TREE_CODE (rtype) == COMPLEX_TYPE)
11412 rtype = TREE_TYPE (rtype);
11413 if (SCALAR_FLOAT_TYPE_P (rtype))
11414 for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
11415 if (rtype == FLOATNX_TYPE_NODE (j))
11416 {
11417 arg_int_floatnx = true;
11418 break;
11419 }
11420 }
11421 tree arg_real = NULL_TREE;
11422 for (unsigned int j = 1; j <= nargs; j++)
11423 {
11424 if (parm_kind[j] == tgmath_fixed)
11425 continue;
11426 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
11427 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
11428 if (TREE_CODE (type) == COMPLEX_TYPE)
11429 type = TREE_TYPE (type);
11430 if (INTEGRAL_TYPE_P (type))
11431 type = (arg_int_decimal
11432 ? dfloat64_type_node
11433 : arg_int_floatnx
11434 ? float32x_type_node
11435 : double_type_node);
11436 if (arg_real == NULL_TREE)
11437 arg_real = type;
11438 else
11439 arg_real = common_type (arg_real, type);
11440 if (arg_real == error_mark_node)
11441 {
11442 expr.set_error ();
11443 goto out;
11444 }
11445 }
11446 tree arg_type = (arg_complex
11447 ? build_complex_type (arg_real)
11448 : arg_real);
11449
11450 /* Look for a function to call with type-generic parameter
11451 type ARG_TYPE. */
11452 c_expr_t *fn = NULL;
11453 for (unsigned int j = 0; j < num_functions; j++)
11454 {
11455 if (tg_type[j] == arg_type)
11456 {
11457 fn = &(*cexpr_list)[j];
11458 break;
11459 }
11460 }
11461 if (fn == NULL
11462 && parm_kind[0] == tgmath_fixed
11463 && SCALAR_FLOAT_TYPE_P (parm_first[0]))
11464 {
11465 /* Presume this is a macro that rounds its result to a
11466 narrower type, and look for the first function with
11467 at least the range and precision of the argument
11468 type. */
11469 for (unsigned int j = 0; j < num_functions; j++)
11470 {
11471 if (arg_complex
11472 != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
11473 continue;
11474 tree real_tg_type = (arg_complex
11475 ? TREE_TYPE (tg_type[j])
11476 : tg_type[j]);
11477 if (DECIMAL_FLOAT_TYPE_P (arg_real)
11478 != DECIMAL_FLOAT_TYPE_P (real_tg_type))
11479 continue;
11480 scalar_float_mode arg_mode
11481 = SCALAR_FLOAT_TYPE_MODE (arg_real);
11482 scalar_float_mode tg_mode
11483 = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
11484 const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
11485 const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
11486 if (arg_fmt->b == tg_fmt->b
11487 && arg_fmt->p <= tg_fmt->p
11488 && arg_fmt->emax <= tg_fmt->emax
11489 && (arg_fmt->emin - arg_fmt->p
11490 >= tg_fmt->emin - tg_fmt->p))
11491 {
11492 fn = &(*cexpr_list)[j];
11493 break;
11494 }
11495 }
11496 }
11497 if (fn == NULL)
11498 {
11499 error_at (loc, "no matching function for type-generic call");
11500 expr.set_error ();
11501 break;
11502 }
11503
11504 /* Construct a call to FN. */
11505 vec<tree, va_gc> *args;
11506 vec_alloc (v&: args, nelems: nargs);
11507 vec<tree, va_gc> *origtypes;
11508 vec_alloc (v&: origtypes, nelems: nargs);
11509 auto_vec<location_t> arg_loc (nargs);
11510 for (unsigned int j = 0; j < nargs; j++)
11511 {
11512 c_expr_t *ce = &(*cexpr_list)[num_functions + j];
11513 args->quick_push (obj: ce->value);
11514 arg_loc.quick_push (obj: ce->get_location ());
11515 origtypes->quick_push (obj: ce->original_type);
11516 }
11517 expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
11518 args, origtypes);
11519 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11520 break;
11521 }
11522 case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
11523 {
11524 vec<c_expr_t, va_gc> *cexpr_list;
11525 c_expr_t *e2_p;
11526 tree chain_value;
11527 location_t close_paren_loc;
11528
11529 c_parser_consume_token (parser);
11530 if (!c_parser_get_builtin_args (parser,
11531 bname: "__builtin_call_with_static_chain",
11532 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11533 out_close_paren_loc: &close_paren_loc))
11534 {
11535 expr.set_error ();
11536 break;
11537 }
11538 if (vec_safe_length (v: cexpr_list) != 2)
11539 {
11540 error_at (loc, "wrong number of arguments to "
11541 "%<__builtin_call_with_static_chain%>");
11542 expr.set_error ();
11543 break;
11544 }
11545
11546 expr = (*cexpr_list)[0];
11547 e2_p = &(*cexpr_list)[1];
11548 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
11549 chain_value = e2_p->value;
11550 mark_exp_read (chain_value);
11551
11552 if (TREE_CODE (expr.value) != CALL_EXPR)
11553 error_at (loc, "first argument to "
11554 "%<__builtin_call_with_static_chain%> "
11555 "must be a call expression");
11556 else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
11557 error_at (loc, "second argument to "
11558 "%<__builtin_call_with_static_chain%> "
11559 "must be a pointer type");
11560 else
11561 CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
11562 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11563 break;
11564 }
11565 case RID_BUILTIN_COMPLEX:
11566 {
11567 vec<c_expr_t, va_gc> *cexpr_list;
11568 c_expr_t *e1_p, *e2_p;
11569 location_t close_paren_loc;
11570
11571 c_parser_consume_token (parser);
11572 if (!c_parser_get_builtin_args (parser,
11573 bname: "__builtin_complex",
11574 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11575 out_close_paren_loc: &close_paren_loc))
11576 {
11577 expr.set_error ();
11578 break;
11579 }
11580
11581 if (vec_safe_length (v: cexpr_list) != 2)
11582 {
11583 error_at (loc, "wrong number of arguments to "
11584 "%<__builtin_complex%>");
11585 expr.set_error ();
11586 break;
11587 }
11588
11589 e1_p = &(*cexpr_list)[0];
11590 e2_p = &(*cexpr_list)[1];
11591
11592 *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
11593 if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
11594 e1_p->value = convert (TREE_TYPE (e1_p->value),
11595 TREE_OPERAND (e1_p->value, 0));
11596 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
11597 if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
11598 e2_p->value = convert (TREE_TYPE (e2_p->value),
11599 TREE_OPERAND (e2_p->value, 0));
11600 if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
11601 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
11602 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
11603 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
11604 {
11605 error_at (loc, "%<__builtin_complex%> operand "
11606 "not of real binary floating-point type");
11607 expr.set_error ();
11608 break;
11609 }
11610 if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
11611 != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
11612 {
11613 error_at (loc,
11614 "%<__builtin_complex%> operands of different types");
11615 expr.set_error ();
11616 break;
11617 }
11618 pedwarn_c90 (loc, opt: OPT_Wpedantic,
11619 "ISO C90 does not support complex types");
11620 expr.value = build2_loc (loc, code: COMPLEX_EXPR,
11621 type: build_complex_type
11622 (TYPE_MAIN_VARIANT
11623 (TREE_TYPE (e1_p->value))),
11624 arg0: e1_p->value, arg1: e2_p->value);
11625 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11626 break;
11627 }
11628 case RID_BUILTIN_SHUFFLE:
11629 {
11630 vec<c_expr_t, va_gc> *cexpr_list;
11631 unsigned int i;
11632 c_expr_t *p;
11633 location_t close_paren_loc;
11634
11635 c_parser_consume_token (parser);
11636 if (!c_parser_get_builtin_args (parser,
11637 bname: "__builtin_shuffle",
11638 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11639 out_close_paren_loc: &close_paren_loc))
11640 {
11641 expr.set_error ();
11642 break;
11643 }
11644
11645 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
11646 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11647
11648 if (vec_safe_length (v: cexpr_list) == 2)
11649 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
11650 NULL_TREE,
11651 (*cexpr_list)[1].value);
11652
11653 else if (vec_safe_length (v: cexpr_list) == 3)
11654 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
11655 (*cexpr_list)[1].value,
11656 (*cexpr_list)[2].value);
11657 else
11658 {
11659 error_at (loc, "wrong number of arguments to "
11660 "%<__builtin_shuffle%>");
11661 expr.set_error ();
11662 }
11663 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11664 break;
11665 }
11666 case RID_BUILTIN_SHUFFLEVECTOR:
11667 {
11668 vec<c_expr_t, va_gc> *cexpr_list;
11669 unsigned int i;
11670 c_expr_t *p;
11671 location_t close_paren_loc;
11672
11673 c_parser_consume_token (parser);
11674 if (!c_parser_get_builtin_args (parser,
11675 bname: "__builtin_shufflevector",
11676 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11677 out_close_paren_loc: &close_paren_loc))
11678 {
11679 expr.set_error ();
11680 break;
11681 }
11682
11683 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
11684 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11685
11686 if (vec_safe_length (v: cexpr_list) < 3)
11687 {
11688 error_at (loc, "wrong number of arguments to "
11689 "%<__builtin_shuffle%>");
11690 expr.set_error ();
11691 }
11692 else
11693 {
11694 auto_vec<tree, 16> mask;
11695 for (i = 2; i < cexpr_list->length (); ++i)
11696 mask.safe_push (obj: (*cexpr_list)[i].value);
11697 expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
11698 (*cexpr_list)[1].value,
11699 mask);
11700 }
11701 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11702 break;
11703 }
11704 case RID_BUILTIN_CONVERTVECTOR:
11705 {
11706 location_t start_loc = loc;
11707 c_parser_consume_token (parser);
11708 matching_parens parens;
11709 if (!parens.require_open (parser))
11710 {
11711 expr.set_error ();
11712 break;
11713 }
11714 e1 = c_parser_expr_no_commas (parser, NULL);
11715 mark_exp_read (e1.value);
11716 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11717 {
11718 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11719 expr.set_error ();
11720 break;
11721 }
11722 loc = c_parser_peek_token (parser)->location;
11723 t1 = c_parser_type_name (parser);
11724 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11725 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11726 msgid: "expected %<)%>");
11727 if (t1 == NULL)
11728 expr.set_error ();
11729 else
11730 {
11731 tree type_expr = NULL_TREE;
11732 expr.value = c_build_vec_convert (start_loc, e1.value, loc,
11733 groktypename (t1, &type_expr,
11734 NULL));
11735 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11736 }
11737 }
11738 break;
11739 case RID_BUILTIN_ASSOC_BARRIER:
11740 {
11741 location_t start_loc = loc;
11742 c_parser_consume_token (parser);
11743 matching_parens parens;
11744 if (!parens.require_open (parser))
11745 {
11746 expr.set_error ();
11747 break;
11748 }
11749 e1 = c_parser_expr_no_commas (parser, NULL);
11750 mark_exp_read (e1.value);
11751 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11752 parens.skip_until_found_close (parser);
11753 expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
11754 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11755 }
11756 break;
11757 case RID_BUILTIN_STDC:
11758 {
11759 vec<c_expr_t, va_gc> *cexpr_list;
11760 c_expr_t *arg_p;
11761 location_t close_paren_loc;
11762 enum c_builtin_stdc {
11763 C_BUILTIN_STDC_BIT_CEIL,
11764 C_BUILTIN_STDC_BIT_FLOOR,
11765 C_BUILTIN_STDC_BIT_WIDTH,
11766 C_BUILTIN_STDC_COUNT_ONES,
11767 C_BUILTIN_STDC_COUNT_ZEROS,
11768 C_BUILTIN_STDC_FIRST_LEADING_ONE,
11769 C_BUILTIN_STDC_FIRST_LEADING_ZERO,
11770 C_BUILTIN_STDC_FIRST_TRAILING_ONE,
11771 C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
11772 C_BUILTIN_STDC_HAS_SINGLE_BIT,
11773 C_BUILTIN_STDC_LEADING_ONES,
11774 C_BUILTIN_STDC_LEADING_ZEROS,
11775 C_BUILTIN_STDC_TRAILING_ONES,
11776 C_BUILTIN_STDC_TRAILING_ZEROS,
11777 C_BUILTIN_STDC_MAX
11778 } stdc_rid = C_BUILTIN_STDC_MAX;
11779 const char *name
11780 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
11781 switch (name[sizeof ("__builtin_stdc_") - 1])
11782 {
11783 case 'b':
11784 switch (name[sizeof ("__builtin_stdc_bit_") - 1])
11785 {
11786 case 'c':
11787 stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
11788 break;
11789 case 'f':
11790 stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
11791 break;
11792 default:
11793 stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
11794 break;
11795 }
11796 break;
11797 case 'c':
11798 if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
11799 stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
11800 else
11801 stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
11802 break;
11803 case 'f':
11804 switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
11805 {
11806 case 'n':
11807 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
11808 break;
11809 case 'e':
11810 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
11811 break;
11812 case 'o':
11813 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
11814 break;
11815 default:
11816 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
11817 break;
11818 }
11819 break;
11820 case 'h':
11821 stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
11822 break;
11823 case 'l':
11824 if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
11825 stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
11826 else
11827 stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
11828 break;
11829 case 't':
11830 if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
11831 stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
11832 else
11833 stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
11834 break;
11835 }
11836 gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
11837
11838 c_parser_consume_token (parser);
11839 if (!c_parser_get_builtin_args (parser, bname: name,
11840 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11841 out_close_paren_loc: &close_paren_loc))
11842 {
11843 expr.set_error ();
11844 break;
11845 }
11846
11847 if (vec_safe_length (v: cexpr_list) != 1)
11848 {
11849 error_at (loc, "wrong number of arguments to %qs", name);
11850 expr.set_error ();
11851 break;
11852 }
11853
11854 arg_p = &(*cexpr_list)[0];
11855 *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
11856 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
11857 {
11858 error_at (loc, "%qs operand not an integral type", name);
11859 expr.set_error ();
11860 break;
11861 }
11862 if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
11863 {
11864 error_at (loc, "argument %u in call to function "
11865 "%qs has enumerated type", 1, name);
11866 expr.set_error ();
11867 break;
11868 }
11869 if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
11870 {
11871 error_at (loc, "argument %u in call to function "
11872 "%qs has boolean type", 1, name);
11873 expr.set_error ();
11874 break;
11875 }
11876 if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
11877 {
11878 error_at (loc, "argument 1 in call to function "
11879 "%qs has signed type", name);
11880 expr.set_error ();
11881 break;
11882 }
11883 tree arg = arg_p->value;
11884 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
11885 /* Expand:
11886 __builtin_stdc_leading_zeros (arg) as
11887 (unsigned int) __builtin_clzg (arg, prec)
11888 __builtin_stdc_leading_ones (arg) as
11889 (unsigned int) __builtin_clzg ((type) ~arg, prec)
11890 __builtin_stdc_trailing_zeros (arg) as
11891 (unsigned int) __builtin_ctzg (arg, prec)
11892 __builtin_stdc_trailing_ones (arg) as
11893 (unsigned int) __builtin_ctzg ((type) ~arg, prec)
11894 __builtin_stdc_first_leading_zero (arg) as
11895 __builtin_clzg ((type) ~arg, -1) + 1U
11896 __builtin_stdc_first_leading_one (arg) as
11897 __builtin_clzg (arg, -1) + 1U
11898 __builtin_stdc_first_trailing_zero (arg) as
11899 __builtin_ctzg ((type) ~arg, -1) + 1U
11900 __builtin_stdc_first_trailing_one (arg) as
11901 __builtin_ctzg (arg, -1) + 1U
11902 __builtin_stdc_count_zeros (arg) as
11903 (unsigned int) __builtin_popcountg ((type) ~arg)
11904 __builtin_stdc_count_ones (arg) as
11905 (unsigned int) __builtin_popcountg (arg)
11906 __builtin_stdc_has_single_bit (arg) as
11907 (_Bool) (__builtin_popcountg (arg) == 1)
11908 __builtin_stdc_bit_width (arg) as
11909 (unsigned int) (prec - __builtin_clzg (arg, prec))
11910 __builtin_stdc_bit_floor (arg) as
11911 arg == 0 ? (type) 0
11912 : (type) 1 << (prec - 1 - __builtin_clzg (arg))
11913 __builtin_stdc_bit_ceil (arg) as
11914 arg <= 1 ? (type) 1
11915 : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
11916 without evaluating arg multiple times, type being
11917 __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
11918 int prec = TYPE_PRECISION (type);
11919 tree barg1 = arg;
11920 switch (stdc_rid)
11921 {
11922 case C_BUILTIN_STDC_BIT_CEIL:
11923 arg = save_expr (arg);
11924 barg1 = build2_loc (loc, code: PLUS_EXPR, type, arg0: arg,
11925 arg1: build_int_cst (type, -1));
11926 break;
11927 case C_BUILTIN_STDC_BIT_FLOOR:
11928 barg1 = arg = save_expr (arg);
11929 break;
11930 case C_BUILTIN_STDC_COUNT_ZEROS:
11931 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
11932 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
11933 case C_BUILTIN_STDC_LEADING_ONES:
11934 case C_BUILTIN_STDC_TRAILING_ONES:
11935 barg1 = build1_loc (loc, code: BIT_NOT_EXPR, type, arg1: arg);
11936 break;
11937 default:
11938 break;
11939 }
11940 tree barg2 = NULL_TREE;
11941 switch (stdc_rid)
11942 {
11943 case C_BUILTIN_STDC_BIT_WIDTH:
11944 case C_BUILTIN_STDC_LEADING_ONES:
11945 case C_BUILTIN_STDC_LEADING_ZEROS:
11946 case C_BUILTIN_STDC_TRAILING_ONES:
11947 case C_BUILTIN_STDC_TRAILING_ZEROS:
11948 barg2 = build_int_cst (integer_type_node, prec);
11949 break;
11950 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
11951 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
11952 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
11953 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
11954 barg2 = integer_minus_one_node;
11955 break;
11956 default:
11957 break;
11958 }
11959 tree fndecl = NULL_TREE;
11960 switch (stdc_rid)
11961 {
11962 case C_BUILTIN_STDC_BIT_CEIL:
11963 case C_BUILTIN_STDC_BIT_FLOOR:
11964 case C_BUILTIN_STDC_BIT_WIDTH:
11965 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
11966 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
11967 case C_BUILTIN_STDC_LEADING_ONES:
11968 case C_BUILTIN_STDC_LEADING_ZEROS:
11969 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CLZG);
11970 break;
11971 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
11972 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
11973 case C_BUILTIN_STDC_TRAILING_ONES:
11974 case C_BUILTIN_STDC_TRAILING_ZEROS:
11975 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CTZG);
11976 break;
11977 case C_BUILTIN_STDC_COUNT_ONES:
11978 case C_BUILTIN_STDC_COUNT_ZEROS:
11979 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
11980 fndecl = builtin_decl_explicit (fncode: BUILT_IN_POPCOUNTG);
11981 break;
11982 default:
11983 gcc_unreachable ();
11984 }
11985 /* Construct a call to __builtin_{clz,ctz,popcount}g. */
11986 int nargs = barg2 != NULL_TREE ? 2 : 1;
11987 vec<tree, va_gc> *args;
11988 vec_alloc (v&: args, nelems: nargs);
11989 vec<tree, va_gc> *origtypes;
11990 vec_alloc (v&: origtypes, nelems: nargs);
11991 auto_vec<location_t> arg_loc (nargs);
11992 args->quick_push (obj: barg1);
11993 arg_loc.quick_push (obj: arg_p->get_location ());
11994 origtypes->quick_push (obj: arg_p->original_type);
11995 if (nargs == 2)
11996 {
11997 args->quick_push (obj: barg2);
11998 arg_loc.quick_push (obj: loc);
11999 origtypes->quick_push (integer_type_node);
12000 }
12001 expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
12002 args, origtypes);
12003 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12004 if (expr.value == error_mark_node)
12005 break;
12006 switch (stdc_rid)
12007 {
12008 case C_BUILTIN_STDC_BIT_CEIL:
12009 case C_BUILTIN_STDC_BIT_FLOOR:
12010 --prec;
12011 /* FALLTHRU */
12012 case C_BUILTIN_STDC_BIT_WIDTH:
12013 expr.value = build2_loc (loc, code: MINUS_EXPR, integer_type_node,
12014 arg0: build_int_cst (integer_type_node,
12015 prec), arg1: expr.value);
12016 break;
12017 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
12018 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
12019 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
12020 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
12021 expr.value = build2_loc (loc, code: PLUS_EXPR, integer_type_node,
12022 arg0: expr.value, integer_one_node);
12023 break;
12024 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
12025 expr.value = build2_loc (loc, code: EQ_EXPR, boolean_type_node,
12026 arg0: expr.value, integer_one_node);
12027 break;
12028 default:
12029 break;
12030 }
12031
12032 if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
12033 && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
12034 {
12035 if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
12036 expr.value = fold_convert_loc (loc, unsigned_type_node,
12037 expr.value);
12038 break;
12039 }
12040 /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
12041 or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
12042 warnings. The LSHIFT_EXPR is in dead code in that case. */
12043 if (integer_zerop (arg)
12044 || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
12045 expr.value = build_int_cst (type, 0);
12046 else
12047 expr.value
12048 = build2_loc (loc, code: LSHIFT_EXPR, type,
12049 arg0: build_int_cst (type,
12050 (stdc_rid
12051 == C_BUILTIN_STDC_BIT_CEIL
12052 ? 2 : 1)), arg1: expr.value);
12053 if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
12054 expr.value = build3_loc (loc, code: COND_EXPR, type,
12055 arg0: build2_loc (loc, code: LE_EXPR,
12056 boolean_type_node, arg0: arg,
12057 arg1: build_int_cst (type, 1)),
12058 arg1: build_int_cst (type, 1),
12059 arg2: expr.value);
12060 else
12061 expr.value = build3_loc (loc, code: COND_EXPR, type,
12062 arg0: build2_loc (loc, code: EQ_EXPR,
12063 boolean_type_node, arg0: arg,
12064 arg1: build_int_cst (type, 0)),
12065 arg1: build_int_cst (type, 0),
12066 arg2: expr.value);
12067 break;
12068 }
12069 case RID_AT_SELECTOR:
12070 {
12071 gcc_assert (c_dialect_objc ());
12072 c_parser_consume_token (parser);
12073 matching_parens parens;
12074 if (!parens.require_open (parser))
12075 {
12076 expr.set_error ();
12077 break;
12078 }
12079 tree sel = c_parser_objc_selector_arg (parser);
12080 location_t close_loc = c_parser_peek_token (parser)->location;
12081 parens.skip_until_found_close (parser);
12082 expr.value = objc_build_selector_expr (loc, sel);
12083 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
12084 }
12085 break;
12086 case RID_AT_PROTOCOL:
12087 {
12088 gcc_assert (c_dialect_objc ());
12089 c_parser_consume_token (parser);
12090 matching_parens parens;
12091 if (!parens.require_open (parser))
12092 {
12093 expr.set_error ();
12094 break;
12095 }
12096 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12097 {
12098 c_parser_error (parser, gmsgid: "expected identifier");
12099 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12100 expr.set_error ();
12101 break;
12102 }
12103 tree id = c_parser_peek_token (parser)->value;
12104 c_parser_consume_token (parser);
12105 location_t close_loc = c_parser_peek_token (parser)->location;
12106 parens.skip_until_found_close (parser);
12107 expr.value = objc_build_protocol_expr (id);
12108 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
12109 }
12110 break;
12111 case RID_AT_ENCODE:
12112 {
12113 /* Extension to support C-structures in the archiver. */
12114 gcc_assert (c_dialect_objc ());
12115 c_parser_consume_token (parser);
12116 matching_parens parens;
12117 if (!parens.require_open (parser))
12118 {
12119 expr.set_error ();
12120 break;
12121 }
12122 t1 = c_parser_type_name (parser);
12123 if (t1 == NULL)
12124 {
12125 expr.set_error ();
12126 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12127 break;
12128 }
12129 location_t close_loc = c_parser_peek_token (parser)->location;
12130 parens.skip_until_found_close (parser);
12131 tree type = groktypename (t1, NULL, NULL);
12132 expr.value = objc_build_encode_expr (type);
12133 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
12134 }
12135 break;
12136 case RID_GENERIC:
12137 expr = c_parser_generic_selection (parser);
12138 break;
12139 case RID_OMP_ALL_MEMORY:
12140 gcc_assert (flag_openmp);
12141 c_parser_consume_token (parser);
12142 error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
12143 "%<depend%> clause");
12144 expr.set_error ();
12145 break;
12146 /* C23 'nullptr' literal. */
12147 case RID_NULLPTR:
12148 c_parser_consume_token (parser);
12149 expr.value = nullptr_node;
12150 set_c_expr_source_range (expr: &expr, src_range: tok_range);
12151 pedwarn_c11 (loc, opt: OPT_Wpedantic,
12152 "ISO C does not support %qs before C23", "nullptr");
12153 break;
12154 case RID_TRUE:
12155 c_parser_consume_token (parser);
12156 expr.value = boolean_true_node;
12157 set_c_expr_source_range (expr: &expr, src_range: tok_range);
12158 break;
12159 case RID_FALSE:
12160 c_parser_consume_token (parser);
12161 expr.value = boolean_false_node;
12162 set_c_expr_source_range (expr: &expr, src_range: tok_range);
12163 break;
12164 default:
12165 c_parser_error (parser, gmsgid: "expected expression");
12166 expr.set_error ();
12167 break;
12168 }
12169 break;
12170 case CPP_OPEN_SQUARE:
12171 if (c_dialect_objc ())
12172 {
12173 tree receiver, args;
12174 c_parser_consume_token (parser);
12175 receiver = c_parser_objc_receiver (parser);
12176 args = c_parser_objc_message_args (parser);
12177 location_t close_loc = c_parser_peek_token (parser)->location;
12178 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
12179 msgid: "expected %<]%>");
12180 expr.value = objc_build_message_expr (receiver, args);
12181 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
12182 break;
12183 }
12184 /* Else fall through to report error. */
12185 /* FALLTHRU */
12186 default:
12187 c_parser_error (parser, gmsgid: "expected expression");
12188 expr.set_error ();
12189 break;
12190 }
12191 out:
12192 return c_parser_postfix_expression_after_primary
12193 (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
12194}
12195
12196/* Parse a postfix expression after a parenthesized type name: the
12197 brace-enclosed initializer of a compound literal, possibly followed
12198 by some postfix operators. This is separate because it is not
12199 possible to tell until after the type name whether a cast
12200 expression has a cast or a compound literal, or whether the operand
12201 of sizeof is a parenthesized type name or starts with a compound
12202 literal. TYPE_LOC is the location where TYPE_NAME starts--the
12203 location of the first token after the parentheses around the type
12204 name. */
12205
12206static struct c_expr
12207c_parser_postfix_expression_after_paren_type (c_parser *parser,
12208 struct c_declspecs *scspecs,
12209 struct c_type_name *type_name,
12210 location_t type_loc)
12211{
12212 tree type;
12213 struct c_expr init;
12214 bool non_const;
12215 struct c_expr expr;
12216 location_t start_loc;
12217 tree type_expr = NULL_TREE;
12218 bool type_expr_const = true;
12219 bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
12220 unsigned int underspec_state = 0;
12221 check_compound_literal_type (type_loc, type_name);
12222 rich_location richloc (line_table, type_loc);
12223 start_loc = c_parser_peek_token (parser)->location;
12224 if (constexpr_p)
12225 {
12226 underspec_state = start_underspecified_init (start_loc, NULL_TREE);
12227 /* A constexpr compound literal is subject to the constraints on
12228 underspecified declarations, which may not declare tags or
12229 members or structures or unions; it is undefined behavior to
12230 declare the members of an enumeration. Where the structure,
12231 union or enumeration type is declared within the compound
12232 literal initializer, this is diagnosed elsewhere as a result
12233 of the above call to start_underspecified_init. Diagnose
12234 here the case of declaring such a type in the type specifiers
12235 of the compound literal. */
12236 switch (type_name->specs->typespec_kind)
12237 {
12238 case ctsk_tagfirstref:
12239 case ctsk_tagfirstref_attrs:
12240 error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
12241 type_name->specs->type);
12242 break;
12243
12244 case ctsk_tagdef:
12245 error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
12246 type_name->specs->type);
12247 break;
12248
12249 default:
12250 break;
12251 }
12252 }
12253 start_init (NULL_TREE, NULL,
12254 (global_bindings_p ()
12255 || (scspecs && scspecs->storage_class == csc_static)
12256 || constexpr_p), constexpr_p, &richloc);
12257 type = groktypename (type_name, &type_expr, &type_expr_const);
12258 if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
12259 {
12260 error_at (type_loc, "compound literal has variable size");
12261 type = error_mark_node;
12262 }
12263 else if (TREE_CODE (type) == FUNCTION_TYPE)
12264 {
12265 error_at (type_loc, "compound literal has function type");
12266 type = error_mark_node;
12267 }
12268 if (constexpr_p && type != error_mark_node)
12269 {
12270 tree type_no_array = strip_array_types (type);
12271 /* The type of a constexpr object must not be variably modified
12272 (which applies to all compound literals), volatile, atomic or
12273 restrict qualified or have a member with such a qualifier.
12274 const qualification is implicitly added. */
12275 if (TYPE_QUALS (type_no_array)
12276 & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
12277 error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
12278 else if (RECORD_OR_UNION_TYPE_P (type_no_array)
12279 && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
12280 error_at (type_loc, "invalid qualifiers for field of "
12281 "%<constexpr%> object");
12282 type = c_build_qualified_type (type,
12283 (TYPE_QUALS (type_no_array)
12284 | TYPE_QUAL_CONST));
12285 }
12286 init = c_parser_braced_init (parser, type, nested_p: false, NULL, NULL_TREE);
12287 if (constexpr_p)
12288 finish_underspecified_init (NULL_TREE, underspec_state);
12289 finish_init ();
12290 maybe_warn_string_init (type_loc, type, init);
12291
12292 if (type != error_mark_node
12293 && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
12294 && current_function_decl)
12295 {
12296 error ("compound literal qualified by address-space qualifier");
12297 type = error_mark_node;
12298 }
12299
12300 if (!pedwarn_c90 (start_loc, opt: OPT_Wpedantic,
12301 "ISO C90 forbids compound literals") && scspecs)
12302 pedwarn_c11 (start_loc, opt: OPT_Wpedantic,
12303 "ISO C forbids storage class specifiers in compound literals "
12304 "before C23");
12305 non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
12306 ? CONSTRUCTOR_NON_CONST (init.value)
12307 : init.original_code == C_MAYBE_CONST_EXPR);
12308 non_const |= !type_expr_const;
12309 unsigned int alignas_align = 0;
12310 if (type != error_mark_node
12311 && type_name->specs->align_log != -1)
12312 {
12313 alignas_align = 1U << type_name->specs->align_log;
12314 if (alignas_align < min_align_of_type (type))
12315 {
12316 error_at (type_name->specs->locations[cdw_alignas],
12317 "%<_Alignas%> specifiers cannot reduce "
12318 "alignment of compound literal");
12319 alignas_align = 0;
12320 }
12321 }
12322 expr.value = build_compound_literal (start_loc, type, init.value, non_const,
12323 alignas_align, scspecs);
12324 set_c_expr_source_range (expr: &expr, src_range: init.src_range);
12325 expr.m_decimal = 0;
12326 expr.original_code = ERROR_MARK;
12327 expr.original_type = NULL;
12328 if (type != error_mark_node
12329 && expr.value != error_mark_node
12330 && type_expr)
12331 {
12332 if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
12333 {
12334 gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
12335 C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
12336 }
12337 else
12338 {
12339 gcc_assert (!non_const);
12340 expr.value = build2 (C_MAYBE_CONST_EXPR, type,
12341 type_expr, expr.value);
12342 }
12343 }
12344 return c_parser_postfix_expression_after_primary (parser, loc: start_loc, expr);
12345}
12346
12347/* Callback function for sizeof_pointer_memaccess_warning to compare
12348 types. */
12349
12350static bool
12351sizeof_ptr_memacc_comptypes (tree type1, tree type2)
12352{
12353 return comptypes (type1, type2) == 1;
12354}
12355
12356/* Warn for patterns where abs-like function appears to be used incorrectly,
12357 gracefully ignore any non-abs-like function. The warning location should
12358 be LOC. FNDECL is the declaration of called function, it must be a
12359 BUILT_IN_NORMAL function. ARG is the first and only argument of the
12360 call. */
12361
12362static void
12363warn_for_abs (location_t loc, tree fndecl, tree arg)
12364{
12365 /* Avoid warning in unreachable subexpressions. */
12366 if (c_inhibit_evaluation_warnings)
12367 return;
12368
12369 tree atype = TREE_TYPE (arg);
12370
12371 /* Casts from pointers (and thus arrays and fndecls) will generate
12372 -Wint-conversion warnings. Most other wrong types hopefully lead to type
12373 mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
12374 types and possibly other exotic types. */
12375 if (!INTEGRAL_TYPE_P (atype)
12376 && !SCALAR_FLOAT_TYPE_P (atype)
12377 && TREE_CODE (atype) != COMPLEX_TYPE)
12378 return;
12379
12380 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
12381
12382 switch (fcode)
12383 {
12384 case BUILT_IN_ABS:
12385 case BUILT_IN_LABS:
12386 case BUILT_IN_LLABS:
12387 case BUILT_IN_IMAXABS:
12388 if (!INTEGRAL_TYPE_P (atype))
12389 {
12390 if (SCALAR_FLOAT_TYPE_P (atype))
12391 warning_at (loc, OPT_Wabsolute_value,
12392 "using integer absolute value function %qD when "
12393 "argument is of floating-point type %qT",
12394 fndecl, atype);
12395 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12396 warning_at (loc, OPT_Wabsolute_value,
12397 "using integer absolute value function %qD when "
12398 "argument is of complex type %qT", fndecl, atype);
12399 else
12400 gcc_unreachable ();
12401 return;
12402 }
12403 if (TYPE_UNSIGNED (atype))
12404 warning_at (loc, OPT_Wabsolute_value,
12405 "taking the absolute value of unsigned type %qT "
12406 "has no effect", atype);
12407 break;
12408
12409 CASE_FLT_FN (BUILT_IN_FABS):
12410 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
12411 if (!SCALAR_FLOAT_TYPE_P (atype)
12412 || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
12413 {
12414 if (INTEGRAL_TYPE_P (atype))
12415 warning_at (loc, OPT_Wabsolute_value,
12416 "using floating-point absolute value function %qD "
12417 "when argument is of integer type %qT", fndecl, atype);
12418 else if (DECIMAL_FLOAT_TYPE_P (atype))
12419 warning_at (loc, OPT_Wabsolute_value,
12420 "using floating-point absolute value function %qD "
12421 "when argument is of decimal floating-point type %qT",
12422 fndecl, atype);
12423 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12424 warning_at (loc, OPT_Wabsolute_value,
12425 "using floating-point absolute value function %qD when "
12426 "argument is of complex type %qT", fndecl, atype);
12427 else
12428 gcc_unreachable ();
12429 return;
12430 }
12431 break;
12432
12433 CASE_FLT_FN (BUILT_IN_CABS):
12434 if (TREE_CODE (atype) != COMPLEX_TYPE)
12435 {
12436 if (INTEGRAL_TYPE_P (atype))
12437 warning_at (loc, OPT_Wabsolute_value,
12438 "using complex absolute value function %qD when "
12439 "argument is of integer type %qT", fndecl, atype);
12440 else if (SCALAR_FLOAT_TYPE_P (atype))
12441 warning_at (loc, OPT_Wabsolute_value,
12442 "using complex absolute value function %qD when "
12443 "argument is of floating-point type %qT",
12444 fndecl, atype);
12445 else
12446 gcc_unreachable ();
12447
12448 return;
12449 }
12450 break;
12451
12452 case BUILT_IN_FABSD32:
12453 case BUILT_IN_FABSD64:
12454 case BUILT_IN_FABSD128:
12455 if (!DECIMAL_FLOAT_TYPE_P (atype))
12456 {
12457 if (INTEGRAL_TYPE_P (atype))
12458 warning_at (loc, OPT_Wabsolute_value,
12459 "using decimal floating-point absolute value "
12460 "function %qD when argument is of integer type %qT",
12461 fndecl, atype);
12462 else if (SCALAR_FLOAT_TYPE_P (atype))
12463 warning_at (loc, OPT_Wabsolute_value,
12464 "using decimal floating-point absolute value "
12465 "function %qD when argument is of floating-point "
12466 "type %qT", fndecl, atype);
12467 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12468 warning_at (loc, OPT_Wabsolute_value,
12469 "using decimal floating-point absolute value "
12470 "function %qD when argument is of complex type %qT",
12471 fndecl, atype);
12472 else
12473 gcc_unreachable ();
12474 return;
12475 }
12476 break;
12477
12478 default:
12479 return;
12480 }
12481
12482 if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12483 return;
12484
12485 tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
12486 if (TREE_CODE (atype) == COMPLEX_TYPE)
12487 {
12488 gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
12489 atype = TREE_TYPE (atype);
12490 ftype = TREE_TYPE (ftype);
12491 }
12492
12493 if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
12494 warning_at (loc, OPT_Wabsolute_value,
12495 "absolute value function %qD given an argument of type %qT "
12496 "but has parameter of type %qT which may cause truncation "
12497 "of value", fndecl, atype, ftype);
12498}
12499
12500
12501/* Parse a postfix expression after the initial primary or compound
12502 literal; that is, parse a series of postfix operators.
12503
12504 EXPR_LOC is the location of the primary expression. */
12505
12506static struct c_expr
12507c_parser_postfix_expression_after_primary (c_parser *parser,
12508 location_t expr_loc,
12509 struct c_expr expr)
12510{
12511 struct c_expr orig_expr;
12512 tree ident, idx, len;
12513 location_t sizeof_arg_loc[6], comp_loc;
12514 tree sizeof_arg[6];
12515 unsigned int literal_zero_mask;
12516 unsigned int i;
12517 vec<tree, va_gc> *exprlist;
12518 vec<tree, va_gc> *origtypes = NULL;
12519 vec<location_t> arg_loc = vNULL;
12520 location_t start;
12521 location_t finish;
12522
12523 while (true)
12524 {
12525 location_t op_loc = c_parser_peek_token (parser)->location;
12526 switch (c_parser_peek_token (parser)->type)
12527 {
12528 case CPP_OPEN_SQUARE:
12529 /* Array reference. */
12530 c_parser_consume_token (parser);
12531 idx = len = NULL_TREE;
12532 if (!c_omp_array_section_p
12533 || c_parser_next_token_is_not (parser, type: CPP_COLON))
12534 idx = c_parser_expression (parser).value;
12535
12536 if (c_omp_array_section_p
12537 && c_parser_next_token_is (parser, type: CPP_COLON))
12538 {
12539 c_parser_consume_token (parser);
12540 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_SQUARE))
12541 len = c_parser_expression (parser).value;
12542
12543 expr.value = build_omp_array_section (op_loc, expr.value, idx,
12544 len);
12545 }
12546 else
12547 expr.value = build_array_ref (op_loc, expr.value, idx);
12548
12549 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
12550 msgid: "expected %<]%>");
12551
12552 start = expr.get_start ();
12553 finish = parser->tokens_buf[0].location;
12554 set_c_expr_source_range (expr: &expr, start, finish);
12555 expr.original_code = ERROR_MARK;
12556 expr.original_type = NULL;
12557 expr.m_decimal = 0;
12558 break;
12559 case CPP_OPEN_PAREN:
12560 /* Function call. */
12561 {
12562 matching_parens parens;
12563 parens.consume_open (parser);
12564 for (i = 0; i < 6; i++)
12565 {
12566 sizeof_arg[i] = NULL_TREE;
12567 sizeof_arg_loc[i] = UNKNOWN_LOCATION;
12568 }
12569 literal_zero_mask = 0;
12570 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
12571 exprlist = NULL;
12572 else if (TREE_CODE (expr.value) == FUNCTION_DECL
12573 && fndecl_built_in_p (node: expr.value, name1: BUILT_IN_CLASSIFY_TYPE)
12574 && c_parser_next_tokens_start_typename (parser,
12575 la: cla_prefer_id))
12576 {
12577 /* __builtin_classify_type (type) */
12578 c_inhibit_evaluation_warnings++;
12579 in_alignof++;
12580 struct c_type_name *type = c_parser_type_name (parser);
12581 c_inhibit_evaluation_warnings--;
12582 in_alignof--;
12583 struct c_typespec ret;
12584 ret.expr = NULL_TREE;
12585 ret.spec = error_mark_node;
12586 ret.expr_const_operands = false;
12587 if (type != NULL)
12588 ret.spec = groktypename (type, &ret.expr,
12589 &ret.expr_const_operands);
12590 parens.skip_until_found_close (parser);
12591 expr.value = build_int_cst (integer_type_node,
12592 type_to_class (ret.spec));
12593 break;
12594 }
12595 else
12596 exprlist = c_parser_expr_list (parser, true, false, &origtypes,
12597 sizeof_arg_loc, sizeof_arg,
12598 &arg_loc, &literal_zero_mask);
12599 parens.skip_until_found_close (parser);
12600 }
12601 orig_expr = expr;
12602 mark_exp_read (expr.value);
12603 if (warn_sizeof_pointer_memaccess)
12604 sizeof_pointer_memaccess_warning (sizeof_arg_loc,
12605 expr.value, exprlist,
12606 sizeof_arg,
12607 sizeof_ptr_memacc_comptypes);
12608 if (TREE_CODE (expr.value) == FUNCTION_DECL)
12609 {
12610 if (fndecl_built_in_p (node: expr.value, name1: BUILT_IN_MEMSET)
12611 && vec_safe_length (v: exprlist) == 3)
12612 {
12613 tree arg0 = (*exprlist)[0];
12614 tree arg2 = (*exprlist)[2];
12615 warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
12616 }
12617 if (warn_absolute_value
12618 && fndecl_built_in_p (node: expr.value, klass: BUILT_IN_NORMAL)
12619 && vec_safe_length (v: exprlist) == 1)
12620 warn_for_abs (loc: expr_loc, fndecl: expr.value, arg: (*exprlist)[0]);
12621 if (parser->omp_for_parse_state
12622 && parser->omp_for_parse_state->in_intervening_code
12623 && omp_runtime_api_call (fndecl: expr.value))
12624 {
12625 error_at (expr_loc, "calls to the OpenMP runtime API are "
12626 "not permitted in intervening code");
12627 parser->omp_for_parse_state->fail = true;
12628 }
12629 if (warn_calloc_transposed_args)
12630 if (tree attr = lookup_attribute (attr_name: "alloc_size",
12631 TYPE_ATTRIBUTES
12632 (TREE_TYPE (expr.value))))
12633 if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
12634 warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
12635 sizeof_arg, attr);
12636 }
12637
12638 start = expr.get_start ();
12639 finish = parser->tokens_buf[0].get_finish ();
12640 expr.value
12641 = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
12642 exprlist, origtypes);
12643 set_c_expr_source_range (expr: &expr, start, finish);
12644 expr.m_decimal = 0;
12645
12646 expr.original_code = ERROR_MARK;
12647 if (TREE_CODE (expr.value) == INTEGER_CST
12648 && TREE_CODE (orig_expr.value) == FUNCTION_DECL
12649 && fndecl_built_in_p (node: orig_expr.value, name1: BUILT_IN_CONSTANT_P))
12650 expr.original_code = C_MAYBE_CONST_EXPR;
12651 expr.original_type = NULL;
12652 if (exprlist)
12653 {
12654 release_tree_vector (exprlist);
12655 release_tree_vector (origtypes);
12656 }
12657 arg_loc.release ();
12658 break;
12659 case CPP_DOT:
12660 /* Structure element reference. */
12661 c_parser_consume_token (parser);
12662 expr = default_function_array_conversion (expr_loc, expr);
12663 if (c_parser_next_token_is (parser, type: CPP_NAME))
12664 {
12665 c_token *comp_tok = c_parser_peek_token (parser);
12666 ident = comp_tok->value;
12667 comp_loc = comp_tok->location;
12668 }
12669 else
12670 {
12671 c_parser_error (parser, gmsgid: "expected identifier");
12672 expr.set_error ();
12673 expr.original_code = ERROR_MARK;
12674 expr.original_type = NULL;
12675 return expr;
12676 }
12677 start = expr.get_start ();
12678 finish = c_parser_peek_token (parser)->get_finish ();
12679 c_parser_consume_token (parser);
12680 expr.value = build_component_ref (op_loc, expr.value, ident,
12681 comp_loc, UNKNOWN_LOCATION);
12682 set_c_expr_source_range (expr: &expr, start, finish);
12683 expr.original_code = ERROR_MARK;
12684 if (TREE_CODE (expr.value) != COMPONENT_REF)
12685 expr.original_type = NULL;
12686 else
12687 {
12688 /* Remember the original type of a bitfield. */
12689 tree field = TREE_OPERAND (expr.value, 1);
12690 if (TREE_CODE (field) != FIELD_DECL)
12691 expr.original_type = NULL;
12692 else
12693 expr.original_type = DECL_BIT_FIELD_TYPE (field);
12694 }
12695 expr.m_decimal = 0;
12696 break;
12697 case CPP_DEREF:
12698 /* Structure element reference. */
12699 c_parser_consume_token (parser);
12700 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
12701 if (c_parser_next_token_is (parser, type: CPP_NAME))
12702 {
12703 c_token *comp_tok = c_parser_peek_token (parser);
12704 ident = comp_tok->value;
12705 comp_loc = comp_tok->location;
12706 }
12707 else
12708 {
12709 c_parser_error (parser, gmsgid: "expected identifier");
12710 expr.set_error ();
12711 expr.original_code = ERROR_MARK;
12712 expr.original_type = NULL;
12713 return expr;
12714 }
12715 start = expr.get_start ();
12716 finish = c_parser_peek_token (parser)->get_finish ();
12717 c_parser_consume_token (parser);
12718 expr.value = build_component_ref (op_loc,
12719 build_indirect_ref (op_loc,
12720 expr.value,
12721 RO_ARROW),
12722 ident, comp_loc,
12723 expr.get_location ());
12724 set_c_expr_source_range (expr: &expr, start, finish);
12725 expr.original_code = ERROR_MARK;
12726 if (TREE_CODE (expr.value) != COMPONENT_REF)
12727 expr.original_type = NULL;
12728 else
12729 {
12730 /* Remember the original type of a bitfield. */
12731 tree field = TREE_OPERAND (expr.value, 1);
12732 if (TREE_CODE (field) != FIELD_DECL)
12733 expr.original_type = NULL;
12734 else
12735 expr.original_type = DECL_BIT_FIELD_TYPE (field);
12736 }
12737 expr.m_decimal = 0;
12738 break;
12739 case CPP_PLUS_PLUS:
12740 /* Postincrement. */
12741 start = expr.get_start ();
12742 finish = c_parser_peek_token (parser)->get_finish ();
12743 c_parser_consume_token (parser);
12744 expr = default_function_array_read_conversion (expr_loc, expr);
12745 expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
12746 expr.value, false);
12747 set_c_expr_source_range (expr: &expr, start, finish);
12748 expr.original_code = ERROR_MARK;
12749 expr.original_type = NULL;
12750 break;
12751 case CPP_MINUS_MINUS:
12752 /* Postdecrement. */
12753 start = expr.get_start ();
12754 finish = c_parser_peek_token (parser)->get_finish ();
12755 c_parser_consume_token (parser);
12756 expr = default_function_array_read_conversion (expr_loc, expr);
12757 expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
12758 expr.value, false);
12759 set_c_expr_source_range (expr: &expr, start, finish);
12760 expr.original_code = ERROR_MARK;
12761 expr.original_type = NULL;
12762 break;
12763 default:
12764 return expr;
12765 }
12766 }
12767}
12768
12769/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
12770
12771 expression:
12772 assignment-expression
12773 expression , assignment-expression
12774*/
12775
12776static struct c_expr
12777c_parser_expression (c_parser *parser)
12778{
12779 location_t tloc = c_parser_peek_token (parser)->location;
12780 struct c_expr expr;
12781 expr = c_parser_expr_no_commas (parser, NULL);
12782 if (c_parser_next_token_is (parser, type: CPP_COMMA))
12783 expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
12784 while (c_parser_next_token_is (parser, type: CPP_COMMA))
12785 {
12786 struct c_expr next;
12787 tree lhsval;
12788 location_t loc = c_parser_peek_token (parser)->location;
12789 location_t expr_loc;
12790 c_parser_consume_token (parser);
12791 expr_loc = c_parser_peek_token (parser)->location;
12792 lhsval = expr.value;
12793 while (TREE_CODE (lhsval) == COMPOUND_EXPR
12794 || TREE_CODE (lhsval) == NOP_EXPR)
12795 {
12796 if (TREE_CODE (lhsval) == COMPOUND_EXPR)
12797 lhsval = TREE_OPERAND (lhsval, 1);
12798 else
12799 lhsval = TREE_OPERAND (lhsval, 0);
12800 }
12801 if (DECL_P (lhsval) || handled_component_p (t: lhsval))
12802 mark_exp_read (lhsval);
12803 next = c_parser_expr_no_commas (parser, NULL);
12804 next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
12805 expr.value = build_compound_expr (loc, expr.value, next.value);
12806 expr.original_code = COMPOUND_EXPR;
12807 expr.original_type = next.original_type;
12808 expr.m_decimal = 0;
12809 }
12810 return expr;
12811}
12812
12813/* Parse an expression and convert functions or arrays to pointers and
12814 lvalues to rvalues. */
12815
12816static struct c_expr
12817c_parser_expression_conv (c_parser *parser)
12818{
12819 struct c_expr expr;
12820 location_t loc = c_parser_peek_token (parser)->location;
12821 expr = c_parser_expression (parser);
12822 expr = convert_lvalue_to_rvalue (loc, expr, true, false);
12823 return expr;
12824}
12825
12826/* Helper function of c_parser_expr_list. Check if IDXth (0 based)
12827 argument is a literal zero alone and if so, set it in literal_zero_mask. */
12828
12829static inline void
12830c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
12831 unsigned int idx)
12832{
12833 if (idx >= HOST_BITS_PER_INT)
12834 return;
12835
12836 c_token *tok = c_parser_peek_token (parser);
12837 switch (tok->type)
12838 {
12839 case CPP_NUMBER:
12840 case CPP_CHAR:
12841 case CPP_WCHAR:
12842 case CPP_CHAR16:
12843 case CPP_CHAR32:
12844 case CPP_UTF8CHAR:
12845 /* If a parameter is literal zero alone, remember it
12846 for -Wmemset-transposed-args warning. */
12847 if (integer_zerop (tok->value)
12848 && !TREE_OVERFLOW (tok->value)
12849 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
12850 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
12851 *literal_zero_mask |= 1U << idx;
12852 default:
12853 break;
12854 }
12855}
12856
12857/* Parse a non-empty list of expressions. If CONVERT_P, convert
12858 functions and arrays to pointers and lvalues to rvalues. If
12859 FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
12860 locations of function arguments into this vector.
12861
12862 nonempty-expr-list:
12863 assignment-expression
12864 nonempty-expr-list , assignment-expression
12865*/
12866
12867static vec<tree, va_gc> *
12868c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
12869 vec<tree, va_gc> **p_orig_types,
12870 location_t *sizeof_arg_loc, tree *sizeof_arg,
12871 vec<location_t> *locations,
12872 unsigned int *literal_zero_mask)
12873{
12874 vec<tree, va_gc> *ret;
12875 vec<tree, va_gc> *orig_types;
12876 struct c_expr expr;
12877 unsigned int idx = 0;
12878 bool save_c_omp_array_section_p = c_omp_array_section_p;
12879 c_omp_array_section_p = false;
12880
12881 ret = make_tree_vector ();
12882 if (p_orig_types == NULL)
12883 orig_types = NULL;
12884 else
12885 orig_types = make_tree_vector ();
12886
12887 if (literal_zero_mask)
12888 c_parser_check_literal_zero (parser, literal_zero_mask, idx: 0);
12889 expr = c_parser_expr_no_commas (parser, NULL);
12890 if (convert_p)
12891 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
12892 if (fold_p)
12893 expr.value = c_fully_fold (expr.value, false, NULL);
12894 ret->quick_push (obj: expr.value);
12895 if (orig_types)
12896 orig_types->quick_push (obj: expr.original_type);
12897 if (locations)
12898 locations->safe_push (obj: expr.get_location ());
12899 if (sizeof_arg != NULL
12900 && (expr.original_code == SIZEOF_EXPR
12901 || expr.original_code == PAREN_SIZEOF_EXPR))
12902 {
12903 sizeof_arg[0] = c_last_sizeof_arg;
12904 sizeof_arg_loc[0] = c_last_sizeof_loc;
12905 }
12906 while (c_parser_next_token_is (parser, type: CPP_COMMA))
12907 {
12908 c_parser_consume_token (parser);
12909 if (literal_zero_mask)
12910 c_parser_check_literal_zero (parser, literal_zero_mask, idx: idx + 1);
12911 expr = c_parser_expr_no_commas (parser, NULL);
12912 if (convert_p)
12913 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
12914 true);
12915 if (fold_p)
12916 expr.value = c_fully_fold (expr.value, false, NULL);
12917 vec_safe_push (v&: ret, obj: expr.value);
12918 if (orig_types)
12919 vec_safe_push (v&: orig_types, obj: expr.original_type);
12920 if (locations)
12921 locations->safe_push (obj: expr.get_location ());
12922 if (++idx < 6
12923 && sizeof_arg != NULL
12924 && (expr.original_code == SIZEOF_EXPR
12925 || expr.original_code == PAREN_SIZEOF_EXPR))
12926 {
12927 sizeof_arg[idx] = c_last_sizeof_arg;
12928 sizeof_arg_loc[idx] = c_last_sizeof_loc;
12929 }
12930 }
12931 if (orig_types)
12932 *p_orig_types = orig_types;
12933 c_omp_array_section_p = save_c_omp_array_section_p;
12934 return ret;
12935}
12936
12937/* Parse Objective-C-specific constructs. */
12938
12939/* Parse an objc-class-definition.
12940
12941 objc-class-definition:
12942 @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
12943 objc-class-instance-variables[opt] objc-methodprotolist @end
12944 @implementation identifier objc-superclass[opt]
12945 objc-class-instance-variables[opt]
12946 @interface identifier ( identifier ) objc-protocol-refs[opt]
12947 objc-methodprotolist @end
12948 @interface identifier ( ) objc-protocol-refs[opt]
12949 objc-methodprotolist @end
12950 @implementation identifier ( identifier )
12951
12952 objc-superclass:
12953 : identifier
12954
12955 "@interface identifier (" must start "@interface identifier (
12956 identifier ) ...": objc-methodprotolist in the first production may
12957 not start with a parenthesized identifier as a declarator of a data
12958 definition with no declaration specifiers if the objc-superclass,
12959 objc-protocol-refs and objc-class-instance-variables are omitted. */
12960
12961static void
12962c_parser_objc_class_definition (c_parser *parser, tree attributes)
12963{
12964 bool iface_p;
12965 tree id1;
12966 tree superclass;
12967 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_INTERFACE))
12968 iface_p = true;
12969 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_IMPLEMENTATION))
12970 iface_p = false;
12971 else
12972 gcc_unreachable ();
12973
12974 c_parser_consume_token (parser);
12975 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12976 {
12977 c_parser_error (parser, gmsgid: "expected identifier");
12978 return;
12979 }
12980 id1 = c_parser_peek_token (parser)->value;
12981 location_t loc1 = c_parser_peek_token (parser)->location;
12982 c_parser_consume_token (parser);
12983 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
12984 {
12985 /* We have a category or class extension. */
12986 tree id2;
12987 tree proto = NULL_TREE;
12988 matching_parens parens;
12989 parens.consume_open (parser);
12990 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12991 {
12992 if (iface_p && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
12993 {
12994 /* We have a class extension. */
12995 id2 = NULL_TREE;
12996 }
12997 else
12998 {
12999 c_parser_error (parser, gmsgid: "expected identifier or %<)%>");
13000 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13001 return;
13002 }
13003 }
13004 else
13005 {
13006 id2 = c_parser_peek_token (parser)->value;
13007 c_parser_consume_token (parser);
13008 }
13009 parens.skip_until_found_close (parser);
13010 if (!iface_p)
13011 {
13012 objc_start_category_implementation (id1, id2);
13013 return;
13014 }
13015 if (c_parser_next_token_is (parser, type: CPP_LESS))
13016 proto = c_parser_objc_protocol_refs (parser);
13017 objc_start_category_interface (id1, id2, proto, attributes);
13018 c_parser_objc_methodprotolist (parser);
13019 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
13020 objc_finish_interface ();
13021 return;
13022 }
13023 if (c_parser_next_token_is (parser, type: CPP_COLON))
13024 {
13025 c_parser_consume_token (parser);
13026 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13027 {
13028 c_parser_error (parser, gmsgid: "expected identifier");
13029 return;
13030 }
13031 superclass = c_parser_peek_token (parser)->value;
13032 c_parser_consume_token (parser);
13033 }
13034 else
13035 superclass = NULL_TREE;
13036 if (iface_p)
13037 {
13038 tree proto = NULL_TREE;
13039 if (c_parser_next_token_is (parser, type: CPP_LESS))
13040 proto = c_parser_objc_protocol_refs (parser);
13041 objc_start_class_interface (id1, loc1, superclass, proto, attributes);
13042 }
13043 else
13044 objc_start_class_implementation (id1, superclass);
13045 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
13046 c_parser_objc_class_instance_variables (parser);
13047 if (iface_p)
13048 {
13049 objc_continue_interface ();
13050 c_parser_objc_methodprotolist (parser);
13051 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
13052 objc_finish_interface ();
13053 }
13054 else
13055 {
13056 objc_continue_implementation ();
13057 return;
13058 }
13059}
13060
13061/* Parse objc-class-instance-variables.
13062
13063 objc-class-instance-variables:
13064 { objc-instance-variable-decl-list[opt] }
13065
13066 objc-instance-variable-decl-list:
13067 objc-visibility-spec
13068 objc-instance-variable-decl ;
13069 ;
13070 objc-instance-variable-decl-list objc-visibility-spec
13071 objc-instance-variable-decl-list objc-instance-variable-decl ;
13072 objc-instance-variable-decl-list ;
13073
13074 objc-visibility-spec:
13075 @private
13076 @protected
13077 @public
13078
13079 objc-instance-variable-decl:
13080 struct-declaration
13081*/
13082
13083static void
13084c_parser_objc_class_instance_variables (c_parser *parser)
13085{
13086 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
13087 c_parser_consume_token (parser);
13088 while (c_parser_next_token_is_not (parser, type: CPP_EOF))
13089 {
13090 tree decls;
13091 /* Parse any stray semicolon. */
13092 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
13093 {
13094 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
13095 "extra semicolon");
13096 c_parser_consume_token (parser);
13097 continue;
13098 }
13099 /* Stop if at the end of the instance variables. */
13100 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
13101 {
13102 c_parser_consume_token (parser);
13103 break;
13104 }
13105 /* Parse any objc-visibility-spec. */
13106 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PRIVATE))
13107 {
13108 c_parser_consume_token (parser);
13109 objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
13110 continue;
13111 }
13112 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROTECTED))
13113 {
13114 c_parser_consume_token (parser);
13115 objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
13116 continue;
13117 }
13118 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PUBLIC))
13119 {
13120 c_parser_consume_token (parser);
13121 objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
13122 continue;
13123 }
13124 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PACKAGE))
13125 {
13126 c_parser_consume_token (parser);
13127 objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
13128 continue;
13129 }
13130 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
13131 {
13132 c_parser_pragma (parser, pragma_external, NULL);
13133 continue;
13134 }
13135
13136 /* Parse some comma-separated declarations. */
13137 decls = c_parser_struct_declaration (parser, NULL);
13138 if (decls == NULL)
13139 {
13140 /* There is a syntax error. We want to skip the offending
13141 tokens up to the next ';' (included) or '}'
13142 (excluded). */
13143
13144 /* First, skip manually a ')' or ']'. This is because they
13145 reduce the nesting level, so c_parser_skip_until_found()
13146 wouldn't be able to skip past them. */
13147 c_token *token = c_parser_peek_token (parser);
13148 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
13149 c_parser_consume_token (parser);
13150
13151 /* Then, do the standard skipping. */
13152 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13153
13154 /* We hopefully recovered. Start normal parsing again. */
13155 parser->error = false;
13156 continue;
13157 }
13158 else
13159 {
13160 /* Comma-separated instance variables are chained together
13161 in reverse order; add them one by one. */
13162 tree ivar = nreverse (decls);
13163 for (; ivar; ivar = DECL_CHAIN (ivar))
13164 objc_add_instance_variable (copy_node (ivar));
13165 }
13166 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13167 }
13168}
13169
13170/* Parse an objc-class-declaration.
13171
13172 objc-class-declaration:
13173 @class identifier-list ;
13174*/
13175
13176static void
13177c_parser_objc_class_declaration (c_parser *parser)
13178{
13179 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
13180 c_parser_consume_token (parser);
13181 /* Any identifiers, including those declared as type names, are OK
13182 here. */
13183 while (true)
13184 {
13185 tree id;
13186 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13187 {
13188 c_parser_error (parser, gmsgid: "expected identifier");
13189 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13190 parser->error = false;
13191 return;
13192 }
13193 id = c_parser_peek_token (parser)->value;
13194 objc_declare_class (id);
13195 c_parser_consume_token (parser);
13196 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13197 c_parser_consume_token (parser);
13198 else
13199 break;
13200 }
13201 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13202}
13203
13204/* Parse an objc-alias-declaration.
13205
13206 objc-alias-declaration:
13207 @compatibility_alias identifier identifier ;
13208*/
13209
13210static void
13211c_parser_objc_alias_declaration (c_parser *parser)
13212{
13213 tree id1, id2;
13214 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
13215 c_parser_consume_token (parser);
13216 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13217 {
13218 c_parser_error (parser, gmsgid: "expected identifier");
13219 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13220 return;
13221 }
13222 id1 = c_parser_peek_token (parser)->value;
13223 c_parser_consume_token (parser);
13224 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13225 {
13226 c_parser_error (parser, gmsgid: "expected identifier");
13227 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13228 return;
13229 }
13230 id2 = c_parser_peek_token (parser)->value;
13231 c_parser_consume_token (parser);
13232 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13233 objc_declare_alias (id1, id2);
13234}
13235
13236/* Parse an objc-protocol-definition.
13237
13238 objc-protocol-definition:
13239 @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
13240 @protocol identifier-list ;
13241
13242 "@protocol identifier ;" should be resolved as "@protocol
13243 identifier-list ;": objc-methodprotolist may not start with a
13244 semicolon in the first alternative if objc-protocol-refs are
13245 omitted. */
13246
13247static void
13248c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
13249{
13250 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
13251
13252 c_parser_consume_token (parser);
13253 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13254 {
13255 c_parser_error (parser, gmsgid: "expected identifier");
13256 return;
13257 }
13258 if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
13259 || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
13260 {
13261 /* Any identifiers, including those declared as type names, are
13262 OK here. */
13263 while (true)
13264 {
13265 tree id;
13266 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13267 {
13268 c_parser_error (parser, gmsgid: "expected identifier");
13269 break;
13270 }
13271 id = c_parser_peek_token (parser)->value;
13272 objc_declare_protocol (id, attributes);
13273 c_parser_consume_token (parser);
13274 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13275 c_parser_consume_token (parser);
13276 else
13277 break;
13278 }
13279 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13280 }
13281 else
13282 {
13283 tree id = c_parser_peek_token (parser)->value;
13284 tree proto = NULL_TREE;
13285 c_parser_consume_token (parser);
13286 if (c_parser_next_token_is (parser, type: CPP_LESS))
13287 proto = c_parser_objc_protocol_refs (parser);
13288 parser->objc_pq_context = true;
13289 objc_start_protocol (id, proto, attributes);
13290 c_parser_objc_methodprotolist (parser);
13291 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
13292 parser->objc_pq_context = false;
13293 objc_finish_interface ();
13294 }
13295}
13296
13297/* Parse an objc-method-type.
13298
13299 objc-method-type:
13300 +
13301 -
13302
13303 Return true if it is a class method (+) and false if it is
13304 an instance method (-).
13305*/
13306static inline bool
13307c_parser_objc_method_type (c_parser *parser)
13308{
13309 switch (c_parser_peek_token (parser)->type)
13310 {
13311 case CPP_PLUS:
13312 c_parser_consume_token (parser);
13313 return true;
13314 case CPP_MINUS:
13315 c_parser_consume_token (parser);
13316 return false;
13317 default:
13318 gcc_unreachable ();
13319 }
13320}
13321
13322/* Parse an objc-method-definition.
13323
13324 objc-method-definition:
13325 objc-method-type objc-method-decl ;[opt] compound-statement
13326*/
13327
13328static void
13329c_parser_objc_method_definition (c_parser *parser)
13330{
13331 bool is_class_method = c_parser_objc_method_type (parser);
13332 tree decl, attributes = NULL_TREE, expr = NULL_TREE;
13333 parser->objc_pq_context = true;
13334 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
13335 &expr);
13336 if (decl == error_mark_node)
13337 return; /* Bail here. */
13338
13339 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
13340 {
13341 c_parser_consume_token (parser);
13342 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
13343 "extra semicolon in method definition specified");
13344 }
13345
13346 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
13347 {
13348 c_parser_error (parser, gmsgid: "expected %<{%>");
13349 return;
13350 }
13351
13352 parser->objc_pq_context = false;
13353 if (objc_start_method_definition (is_class_method, decl, attributes, expr))
13354 {
13355 add_stmt (c_parser_compound_statement (parser));
13356 objc_finish_method_definition (current_function_decl);
13357 }
13358 else
13359 {
13360 /* This code is executed when we find a method definition
13361 outside of an @implementation context (or invalid for other
13362 reasons). Parse the method (to keep going) but do not emit
13363 any code.
13364 */
13365 c_parser_compound_statement (parser);
13366 }
13367}
13368
13369/* Parse an objc-methodprotolist.
13370
13371 objc-methodprotolist:
13372 empty
13373 objc-methodprotolist objc-methodproto
13374 objc-methodprotolist declaration
13375 objc-methodprotolist ;
13376 @optional
13377 @required
13378
13379 The declaration is a data definition, which may be missing
13380 declaration specifiers under the same rules and diagnostics as
13381 other data definitions outside functions, and the stray semicolon
13382 is diagnosed the same way as a stray semicolon outside a
13383 function. */
13384
13385static void
13386c_parser_objc_methodprotolist (c_parser *parser)
13387{
13388 while (true)
13389 {
13390 /* The list is terminated by @end. */
13391 switch (c_parser_peek_token (parser)->type)
13392 {
13393 case CPP_SEMICOLON:
13394 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
13395 "ISO C does not allow extra %<;%> outside of a function");
13396 c_parser_consume_token (parser);
13397 break;
13398 case CPP_PLUS:
13399 case CPP_MINUS:
13400 c_parser_objc_methodproto (parser);
13401 break;
13402 case CPP_PRAGMA:
13403 c_parser_pragma (parser, pragma_external, NULL);
13404 break;
13405 case CPP_EOF:
13406 return;
13407 default:
13408 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_END))
13409 return;
13410 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROPERTY))
13411 c_parser_objc_at_property_declaration (parser);
13412 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_OPTIONAL))
13413 {
13414 objc_set_method_opt (true);
13415 c_parser_consume_token (parser);
13416 }
13417 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_REQUIRED))
13418 {
13419 objc_set_method_opt (false);
13420 c_parser_consume_token (parser);
13421 }
13422 else
13423 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: true,
13424 nested: false, start_attr_ok: true);
13425 break;
13426 }
13427 }
13428}
13429
13430/* Parse an objc-methodproto.
13431
13432 objc-methodproto:
13433 objc-method-type objc-method-decl ;
13434*/
13435
13436static void
13437c_parser_objc_methodproto (c_parser *parser)
13438{
13439 bool is_class_method = c_parser_objc_method_type (parser);
13440 tree decl, attributes = NULL_TREE;
13441
13442 /* Remember protocol qualifiers in prototypes. */
13443 parser->objc_pq_context = true;
13444 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
13445 NULL);
13446 /* Forget protocol qualifiers now. */
13447 parser->objc_pq_context = false;
13448
13449 /* Do not allow the presence of attributes to hide an erroneous
13450 method implementation in the interface section. */
13451 if (!c_parser_next_token_is (parser, type: CPP_SEMICOLON))
13452 {
13453 c_parser_error (parser, gmsgid: "expected %<;%>");
13454 return;
13455 }
13456
13457 if (decl != error_mark_node)
13458 objc_add_method_declaration (is_class_method, decl, attributes);
13459
13460 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13461}
13462
13463/* If we are at a position that method attributes may be present, check that
13464 there are not any parsed already (a syntax error) and then collect any
13465 specified at the current location. Finally, if new attributes were present,
13466 check that the next token is legal ( ';' for decls and '{' for defs). */
13467
13468static bool
13469c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
13470{
13471 bool bad = false;
13472 if (*attributes)
13473 {
13474 c_parser_error (parser,
13475 gmsgid: "method attributes must be specified at the end only");
13476 *attributes = NULL_TREE;
13477 bad = true;
13478 }
13479
13480 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
13481 *attributes = c_parser_gnu_attributes (parser);
13482
13483 /* If there were no attributes here, just report any earlier error. */
13484 if (*attributes == NULL_TREE || bad)
13485 return bad;
13486
13487 /* If the attributes are followed by a ; or {, then just report any earlier
13488 error. */
13489 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
13490 || c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
13491 return bad;
13492
13493 /* We've got attributes, but not at the end. */
13494 c_parser_error (parser,
13495 gmsgid: "expected %<;%> or %<{%> after method attribute definition");
13496 return true;
13497}
13498
13499/* Parse an objc-method-decl.
13500
13501 objc-method-decl:
13502 ( objc-type-name ) objc-selector
13503 objc-selector
13504 ( objc-type-name ) objc-keyword-selector objc-optparmlist
13505 objc-keyword-selector objc-optparmlist
13506 gnu-attributes
13507
13508 objc-keyword-selector:
13509 objc-keyword-decl
13510 objc-keyword-selector objc-keyword-decl
13511
13512 objc-keyword-decl:
13513 objc-selector : ( objc-type-name ) identifier
13514 objc-selector : identifier
13515 : ( objc-type-name ) identifier
13516 : identifier
13517
13518 objc-optparmlist:
13519 objc-optparms objc-optellipsis
13520
13521 objc-optparms:
13522 empty
13523 objc-opt-parms , parameter-declaration
13524
13525 objc-optellipsis:
13526 empty
13527 , ...
13528*/
13529
13530static tree
13531c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
13532 tree *attributes, tree *expr)
13533{
13534 tree type = NULL_TREE;
13535 tree sel;
13536 tree parms = NULL_TREE;
13537 bool ellipsis = false;
13538 bool attr_err = false;
13539
13540 *attributes = NULL_TREE;
13541 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
13542 {
13543 matching_parens parens;
13544 parens.consume_open (parser);
13545 type = c_parser_objc_type_name (parser);
13546 parens.skip_until_found_close (parser);
13547 }
13548 sel = c_parser_objc_selector (parser);
13549 /* If there is no selector, or a colon follows, we have an
13550 objc-keyword-selector. If there is a selector, and a colon does
13551 not follow, that selector ends the objc-method-decl. */
13552 if (!sel || c_parser_next_token_is (parser, type: CPP_COLON))
13553 {
13554 tree tsel = sel;
13555 tree list = NULL_TREE;
13556 while (true)
13557 {
13558 tree atype = NULL_TREE, id, keyworddecl;
13559 tree param_attr = NULL_TREE;
13560 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
13561 break;
13562 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
13563 {
13564 c_parser_consume_token (parser);
13565 atype = c_parser_objc_type_name (parser);
13566 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
13567 msgid: "expected %<)%>");
13568 }
13569 /* New ObjC allows attributes on method parameters. */
13570 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
13571 param_attr = c_parser_gnu_attributes (parser);
13572 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13573 {
13574 c_parser_error (parser, gmsgid: "expected identifier");
13575 return error_mark_node;
13576 }
13577 id = c_parser_peek_token (parser)->value;
13578 c_parser_consume_token (parser);
13579 keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
13580 list = chainon (list, keyworddecl);
13581 tsel = c_parser_objc_selector (parser);
13582 if (!tsel && c_parser_next_token_is_not (parser, type: CPP_COLON))
13583 break;
13584 }
13585
13586 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
13587
13588 /* Parse the optional parameter list. Optional Objective-C
13589 method parameters follow the C syntax, and may include '...'
13590 to denote a variable number of arguments. */
13591 parms = make_node (TREE_LIST);
13592 while (c_parser_next_token_is (parser, type: CPP_COMMA))
13593 {
13594 struct c_parm *parm;
13595 c_parser_consume_token (parser);
13596 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
13597 {
13598 ellipsis = true;
13599 c_parser_consume_token (parser);
13600 attr_err |= c_parser_objc_maybe_method_attributes
13601 (parser, attributes) ;
13602 break;
13603 }
13604 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
13605 if (parm == NULL)
13606 break;
13607 parms = chainon (parms,
13608 build_tree_list (NULL_TREE, grokparm (parm, expr)));
13609 }
13610 sel = list;
13611 }
13612 else
13613 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
13614
13615 if (sel == NULL)
13616 {
13617 c_parser_error (parser, gmsgid: "objective-c method declaration is expected");
13618 return error_mark_node;
13619 }
13620
13621 if (attr_err)
13622 return error_mark_node;
13623
13624 return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
13625}
13626
13627/* Parse an objc-type-name.
13628
13629 objc-type-name:
13630 objc-type-qualifiers[opt] type-name
13631 objc-type-qualifiers[opt]
13632
13633 objc-type-qualifiers:
13634 objc-type-qualifier
13635 objc-type-qualifiers objc-type-qualifier
13636
13637 objc-type-qualifier: one of
13638 in out inout bycopy byref oneway
13639*/
13640
13641static tree
13642c_parser_objc_type_name (c_parser *parser)
13643{
13644 tree quals = NULL_TREE;
13645 struct c_type_name *type_name = NULL;
13646 tree type = NULL_TREE;
13647 while (true)
13648 {
13649 c_token *token = c_parser_peek_token (parser);
13650 if (token->type == CPP_KEYWORD
13651 && (token->keyword == RID_IN
13652 || token->keyword == RID_OUT
13653 || token->keyword == RID_INOUT
13654 || token->keyword == RID_BYCOPY
13655 || token->keyword == RID_BYREF
13656 || token->keyword == RID_ONEWAY))
13657 {
13658 quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
13659 c_parser_consume_token (parser);
13660 }
13661 else
13662 break;
13663 }
13664 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
13665 type_name = c_parser_type_name (parser);
13666 if (type_name)
13667 type = groktypename (type_name, NULL, NULL);
13668
13669 /* If the type is unknown, and error has already been produced and
13670 we need to recover from the error. In that case, use NULL_TREE
13671 for the type, as if no type had been specified; this will use the
13672 default type ('id') which is good for error recovery. */
13673 if (type == error_mark_node)
13674 type = NULL_TREE;
13675
13676 return build_tree_list (quals, type);
13677}
13678
13679/* Parse objc-protocol-refs.
13680
13681 objc-protocol-refs:
13682 < identifier-list >
13683*/
13684
13685static tree
13686c_parser_objc_protocol_refs (c_parser *parser)
13687{
13688 tree list = NULL_TREE;
13689 gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
13690 c_parser_consume_token (parser);
13691 /* Any identifiers, including those declared as type names, are OK
13692 here. */
13693 while (true)
13694 {
13695 tree id;
13696 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13697 {
13698 c_parser_error (parser, gmsgid: "expected identifier");
13699 break;
13700 }
13701 id = c_parser_peek_token (parser)->value;
13702 list = chainon (list, build_tree_list (NULL_TREE, id));
13703 c_parser_consume_token (parser);
13704 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13705 c_parser_consume_token (parser);
13706 else
13707 break;
13708 }
13709 c_parser_require (parser, type: CPP_GREATER, msgid: "expected %<>%>");
13710 return list;
13711}
13712
13713/* Parse an objc-try-catch-finally-statement.
13714
13715 objc-try-catch-finally-statement:
13716 @try compound-statement objc-catch-list[opt]
13717 @try compound-statement objc-catch-list[opt] @finally compound-statement
13718
13719 objc-catch-list:
13720 @catch ( objc-catch-parameter-declaration ) compound-statement
13721 objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
13722
13723 objc-catch-parameter-declaration:
13724 parameter-declaration
13725 '...'
13726
13727 where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
13728
13729 PS: This function is identical to cp_parser_objc_try_catch_finally_statement
13730 for C++. Keep them in sync. */
13731
13732static void
13733c_parser_objc_try_catch_finally_statement (c_parser *parser)
13734{
13735 location_t location;
13736 tree stmt;
13737
13738 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
13739 c_parser_consume_token (parser);
13740 location = c_parser_peek_token (parser)->location;
13741 objc_maybe_warn_exceptions (location);
13742 stmt = c_parser_compound_statement (parser);
13743 objc_begin_try_stmt (location, stmt);
13744
13745 while (c_parser_next_token_is_keyword (parser, keyword: RID_AT_CATCH))
13746 {
13747 struct c_parm *parm;
13748 tree parameter_declaration = error_mark_node;
13749 bool seen_open_paren = false;
13750
13751 c_parser_consume_token (parser);
13752 matching_parens parens;
13753 if (!parens.require_open (parser))
13754 seen_open_paren = true;
13755 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
13756 {
13757 /* We have "@catch (...)" (where the '...' are literally
13758 what is in the code). Skip the '...'.
13759 parameter_declaration is set to NULL_TREE, and
13760 objc_being_catch_clauses() knows that that means
13761 '...'. */
13762 c_parser_consume_token (parser);
13763 parameter_declaration = NULL_TREE;
13764 }
13765 else
13766 {
13767 /* We have "@catch (NSException *exception)" or something
13768 like that. Parse the parameter declaration. */
13769 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
13770 if (parm == NULL)
13771 parameter_declaration = error_mark_node;
13772 else
13773 parameter_declaration = grokparm (parm, NULL);
13774 }
13775 if (seen_open_paren)
13776 parens.require_close (parser);
13777 else
13778 {
13779 /* If there was no open parenthesis, we are recovering from
13780 an error, and we are trying to figure out what mistake
13781 the user has made. */
13782
13783 /* If there is an immediate closing parenthesis, the user
13784 probably forgot the opening one (ie, they typed "@catch
13785 NSException *e)". Parse the closing parenthesis and keep
13786 going. */
13787 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
13788 c_parser_consume_token (parser);
13789
13790 /* If these is no immediate closing parenthesis, the user
13791 probably doesn't know that parenthesis are required at
13792 all (ie, they typed "@catch NSException *e"). So, just
13793 forget about the closing parenthesis and keep going. */
13794 }
13795 objc_begin_catch_clause (parameter_declaration);
13796 if (c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
13797 c_parser_compound_statement_nostart (parser);
13798 objc_finish_catch_clause ();
13799 }
13800 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_FINALLY))
13801 {
13802 c_parser_consume_token (parser);
13803 location = c_parser_peek_token (parser)->location;
13804 stmt = c_parser_compound_statement (parser);
13805 objc_build_finally_clause (location, stmt);
13806 }
13807 objc_finish_try_stmt ();
13808}
13809
13810/* Parse an objc-synchronized-statement.
13811
13812 objc-synchronized-statement:
13813 @synchronized ( expression ) compound-statement
13814*/
13815
13816static void
13817c_parser_objc_synchronized_statement (c_parser *parser)
13818{
13819 location_t loc;
13820 tree expr, stmt;
13821 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
13822 c_parser_consume_token (parser);
13823 loc = c_parser_peek_token (parser)->location;
13824 objc_maybe_warn_exceptions (loc);
13825 matching_parens parens;
13826 if (parens.require_open (parser))
13827 {
13828 struct c_expr ce = c_parser_expression (parser);
13829 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
13830 expr = ce.value;
13831 expr = c_fully_fold (expr, false, NULL);
13832 parens.skip_until_found_close (parser);
13833 }
13834 else
13835 expr = error_mark_node;
13836 stmt = c_parser_compound_statement (parser);
13837 objc_build_synchronized (loc, expr, stmt);
13838}
13839
13840/* Parse an objc-selector; return NULL_TREE without an error if the
13841 next token is not an objc-selector.
13842
13843 objc-selector:
13844 identifier
13845 one of
13846 enum struct union if else while do for switch case default
13847 break continue return goto asm sizeof typeof typeof_unqual __alignof
13848 unsigned long const short volatile signed restrict _Complex
13849 in out inout bycopy byref oneway int char float double void _Bool
13850 _Atomic
13851
13852 ??? Why this selection of keywords but not, for example, storage
13853 class specifiers? */
13854
13855static tree
13856c_parser_objc_selector (c_parser *parser)
13857{
13858 c_token *token = c_parser_peek_token (parser);
13859 tree value = token->value;
13860 if (token->type == CPP_NAME)
13861 {
13862 c_parser_consume_token (parser);
13863 return value;
13864 }
13865 if (token->type != CPP_KEYWORD)
13866 return NULL_TREE;
13867 switch (token->keyword)
13868 {
13869 case RID_ENUM:
13870 case RID_STRUCT:
13871 case RID_UNION:
13872 case RID_IF:
13873 case RID_ELSE:
13874 case RID_WHILE:
13875 case RID_DO:
13876 case RID_FOR:
13877 case RID_SWITCH:
13878 case RID_CASE:
13879 case RID_DEFAULT:
13880 case RID_BREAK:
13881 case RID_CONTINUE:
13882 case RID_RETURN:
13883 case RID_GOTO:
13884 case RID_ASM:
13885 case RID_SIZEOF:
13886 case RID_TYPEOF:
13887 case RID_TYPEOF_UNQUAL:
13888 case RID_ALIGNOF:
13889 case RID_UNSIGNED:
13890 case RID_LONG:
13891 case RID_CONST:
13892 case RID_SHORT:
13893 case RID_VOLATILE:
13894 case RID_SIGNED:
13895 case RID_RESTRICT:
13896 case RID_COMPLEX:
13897 case RID_IN:
13898 case RID_OUT:
13899 case RID_INOUT:
13900 case RID_BYCOPY:
13901 case RID_BYREF:
13902 case RID_ONEWAY:
13903 case RID_INT:
13904 case RID_CHAR:
13905 case RID_FLOAT:
13906 case RID_DOUBLE:
13907 CASE_RID_FLOATN_NX:
13908 case RID_VOID:
13909 case RID_BOOL:
13910 case RID_ATOMIC:
13911 case RID_AUTO_TYPE:
13912 case RID_INT_N_0:
13913 case RID_INT_N_1:
13914 case RID_INT_N_2:
13915 case RID_INT_N_3:
13916 c_parser_consume_token (parser);
13917 return value;
13918 default:
13919 return NULL_TREE;
13920 }
13921}
13922
13923/* Parse an objc-selector-arg.
13924
13925 objc-selector-arg:
13926 objc-selector
13927 objc-keywordname-list
13928
13929 objc-keywordname-list:
13930 objc-keywordname
13931 objc-keywordname-list objc-keywordname
13932
13933 objc-keywordname:
13934 objc-selector :
13935 :
13936*/
13937
13938static tree
13939c_parser_objc_selector_arg (c_parser *parser)
13940{
13941 tree sel = c_parser_objc_selector (parser);
13942 tree list = NULL_TREE;
13943 if (sel
13944 && c_parser_next_token_is_not (parser, type: CPP_COLON)
13945 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
13946 return sel;
13947 while (true)
13948 {
13949 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
13950 {
13951 c_parser_consume_token (parser);
13952 list = chainon (list, build_tree_list (sel, NULL_TREE));
13953 list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
13954 }
13955 else
13956 {
13957 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
13958 return list;
13959 list = chainon (list, build_tree_list (sel, NULL_TREE));
13960 }
13961 sel = c_parser_objc_selector (parser);
13962 if (!sel
13963 && c_parser_next_token_is_not (parser, type: CPP_COLON)
13964 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
13965 break;
13966 }
13967 return list;
13968}
13969
13970/* Parse an objc-receiver.
13971
13972 objc-receiver:
13973 expression
13974 class-name
13975 type-name
13976*/
13977
13978static tree
13979c_parser_objc_receiver (c_parser *parser)
13980{
13981 location_t loc = c_parser_peek_token (parser)->location;
13982
13983 if (c_parser_peek_token (parser)->type == CPP_NAME
13984 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
13985 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
13986 {
13987 tree id = c_parser_peek_token (parser)->value;
13988 c_parser_consume_token (parser);
13989 return objc_get_class_reference (id);
13990 }
13991 struct c_expr ce = c_parser_expression (parser);
13992 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
13993 return c_fully_fold (ce.value, false, NULL);
13994}
13995
13996/* Parse objc-message-args.
13997
13998 objc-message-args:
13999 objc-selector
14000 objc-keywordarg-list
14001
14002 objc-keywordarg-list:
14003 objc-keywordarg
14004 objc-keywordarg-list objc-keywordarg
14005
14006 objc-keywordarg:
14007 objc-selector : objc-keywordexpr
14008 : objc-keywordexpr
14009*/
14010
14011static tree
14012c_parser_objc_message_args (c_parser *parser)
14013{
14014 tree sel = c_parser_objc_selector (parser);
14015 tree list = NULL_TREE;
14016 if (sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
14017 return sel;
14018 while (true)
14019 {
14020 tree keywordexpr;
14021 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
14022 return error_mark_node;
14023 keywordexpr = c_parser_objc_keywordexpr (parser);
14024 list = chainon (list, build_tree_list (sel, keywordexpr));
14025 sel = c_parser_objc_selector (parser);
14026 if (!sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
14027 break;
14028 }
14029 return list;
14030}
14031
14032/* Parse an objc-keywordexpr.
14033
14034 objc-keywordexpr:
14035 nonempty-expr-list
14036*/
14037
14038static tree
14039c_parser_objc_keywordexpr (c_parser *parser)
14040{
14041 tree ret;
14042 vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, convert_p: true, fold_p: true,
14043 NULL, NULL, NULL, NULL);
14044 if (vec_safe_length (v: expr_list) == 1)
14045 {
14046 /* Just return the expression, remove a level of
14047 indirection. */
14048 ret = (*expr_list)[0];
14049 }
14050 else
14051 {
14052 /* We have a comma expression, we will collapse later. */
14053 ret = build_tree_list_vec (expr_list);
14054 }
14055 release_tree_vector (expr_list);
14056 return ret;
14057}
14058
14059/* A check, needed in several places, that ObjC interface, implementation or
14060 method definitions are not prefixed by incorrect items. */
14061static bool
14062c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
14063 struct c_declspecs *specs)
14064{
14065 if (!specs->declspecs_seen_p || specs->non_sc_seen_p
14066 || specs->typespec_kind != ctsk_none)
14067 {
14068 c_parser_error (parser,
14069 gmsgid: "no type or storage class may be specified here,");
14070 c_parser_skip_to_end_of_block_or_statement (parser);
14071 return true;
14072 }
14073 return false;
14074}
14075
14076/* Parse an Objective-C @property declaration. The syntax is:
14077
14078 objc-property-declaration:
14079 '@property' objc-property-attributes[opt] struct-declaration ;
14080
14081 objc-property-attributes:
14082 '(' objc-property-attribute-list ')'
14083
14084 objc-property-attribute-list:
14085 objc-property-attribute
14086 objc-property-attribute-list, objc-property-attribute
14087
14088 objc-property-attribute
14089 'getter' = identifier
14090 'setter' = identifier
14091 'readonly'
14092 'readwrite'
14093 'assign'
14094 'retain'
14095 'copy'
14096 'nonatomic'
14097
14098 For example:
14099 @property NSString *name;
14100 @property (readonly) id object;
14101 @property (retain, nonatomic, getter=getTheName) id name;
14102 @property int a, b, c;
14103
14104 PS: This function is identical to cp_parser_objc_at_propery_declaration
14105 for C++. Keep them in sync. */
14106static void
14107c_parser_objc_at_property_declaration (c_parser *parser)
14108{
14109 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
14110 location_t loc = c_parser_peek_token (parser)->location;
14111 c_parser_consume_token (parser); /* Eat '@property'. */
14112
14113 /* Parse the optional attribute list.
14114
14115 A list of parsed, but not verified, attributes. */
14116 vec<property_attribute_info *> prop_attr_list = vNULL;
14117
14118 bool syntax_error = false;
14119 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
14120 {
14121 matching_parens parens;
14122
14123 location_t attr_start = c_parser_peek_token (parser)->location;
14124 /* Eat the '(' */
14125 parens.consume_open (parser);
14126
14127 /* Property attribute keywords are valid now. */
14128 parser->objc_property_attr_context = true;
14129
14130 /* Allow @property (), with a warning. */
14131 location_t attr_end = c_parser_peek_token (parser)->location;
14132
14133 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
14134 {
14135 location_t attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
14136 warning_at (attr_comb, OPT_Wattributes,
14137 "empty property attribute list");
14138 }
14139 else
14140 while (true)
14141 {
14142 c_token *token = c_parser_peek_token (parser);
14143 attr_start = token->location;
14144 attr_end = get_finish (loc: token->location);
14145 location_t attr_comb = make_location (caret: attr_start, start: attr_start,
14146 finish: attr_end);
14147
14148 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
14149 {
14150 warning_at (attr_comb, OPT_Wattributes,
14151 "missing property attribute");
14152 if (token->type == CPP_CLOSE_PAREN)
14153 break;
14154 c_parser_consume_token (parser);
14155 continue;
14156 }
14157
14158 tree attr_name = NULL_TREE;
14159 enum rid keyword = RID_MAX; /* Not a valid property attribute. */
14160 bool add_at = false;
14161 if (token->type == CPP_KEYWORD)
14162 {
14163 keyword = token->keyword;
14164 if (OBJC_IS_AT_KEYWORD (keyword))
14165 {
14166 /* For '@' keywords the token value has the keyword,
14167 prepend the '@' for diagnostics. */
14168 attr_name = token->value;
14169 add_at = true;
14170 }
14171 else
14172 attr_name = ridpointers[(int)keyword];
14173 }
14174 else if (token->type == CPP_NAME)
14175 attr_name = token->value;
14176 c_parser_consume_token (parser);
14177
14178 enum objc_property_attribute_kind prop_kind
14179 = objc_prop_attr_kind_for_rid (keyword);
14180 property_attribute_info *prop
14181 = new property_attribute_info (attr_name, attr_comb, prop_kind);
14182 prop_attr_list.safe_push (obj: prop);
14183
14184 tree meth_name;
14185 switch (prop->prop_kind)
14186 {
14187 default: break;
14188 case OBJC_PROPERTY_ATTR_UNKNOWN:
14189 if (attr_name)
14190 error_at (attr_comb, "unknown property attribute %<%s%s%>",
14191 add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
14192 else
14193 error_at (attr_comb, "unknown property attribute");
14194 prop->parse_error = syntax_error = true;
14195 break;
14196
14197 case OBJC_PROPERTY_ATTR_GETTER:
14198 case OBJC_PROPERTY_ATTR_SETTER:
14199 if (c_parser_next_token_is_not (parser, type: CPP_EQ))
14200 {
14201 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
14202 error_at (attr_comb, "expected %<=%> after Objective-C %qE",
14203 attr_name);
14204 prop->parse_error = syntax_error = true;
14205 break;
14206 }
14207 token = c_parser_peek_token (parser);
14208 attr_end = token->location;
14209 c_parser_consume_token (parser); /* eat the = */
14210 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14211 {
14212 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
14213 error_at (attr_comb, "expected %qE selector name",
14214 attr_name);
14215 prop->parse_error = syntax_error = true;
14216 break;
14217 }
14218 /* Get the end of the method name, and consume the name. */
14219 token = c_parser_peek_token (parser);
14220 attr_end = get_finish (loc: token->location);
14221 meth_name = token->value;
14222 c_parser_consume_token (parser);
14223 if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
14224 {
14225 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
14226 {
14227 attr_comb = make_location (caret: attr_end, start: attr_start,
14228 finish: attr_end);
14229 error_at (attr_comb, "setter method names must"
14230 " terminate with %<:%>");
14231 prop->parse_error = syntax_error = true;
14232 }
14233 else
14234 {
14235 attr_end = get_finish (loc: c_parser_peek_token
14236 (parser)->location);
14237 c_parser_consume_token (parser);
14238 }
14239 attr_comb = make_location (caret: attr_start, start: attr_start,
14240 finish: attr_end);
14241 }
14242 else
14243 attr_comb = make_location (caret: attr_start, start: attr_start,
14244 finish: attr_end);
14245 prop->ident = meth_name;
14246 /* Updated location including all that was successfully
14247 parsed. */
14248 prop->prop_loc = attr_comb;
14249 break;
14250 }
14251
14252 /* If we see a comma here, then keep going - even if we already
14253 saw a syntax error. For simple mistakes e.g. (asign, getter=x)
14254 this makes a more useful output and avoid spurious warnings about
14255 missing attributes that are, in fact, specified after the one with
14256 the syntax error. */
14257 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14258 c_parser_consume_token (parser);
14259 else
14260 break;
14261 }
14262 parser->objc_property_attr_context = false;
14263
14264 if (syntax_error && c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
14265 /* We don't really want to chew the whole of the file looking for a
14266 matching closing parenthesis, so we will try to read the decl and
14267 let the error handling for that close out the statement. */
14268 ;
14269 else
14270 syntax_error = false, parens.skip_until_found_close (parser);
14271 }
14272
14273 /* 'properties' is the list of properties that we read. Usually a
14274 single one, but maybe more (eg, in "@property int a, b, c;" there
14275 are three). */
14276 tree properties = c_parser_struct_declaration (parser, NULL);
14277
14278 if (properties == error_mark_node)
14279 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14280 else
14281 {
14282 if (properties == NULL_TREE)
14283 c_parser_error (parser, gmsgid: "expected identifier");
14284 else
14285 {
14286 /* Comma-separated properties are chained together in reverse order;
14287 add them one by one. */
14288 properties = nreverse (properties);
14289 for (; properties; properties = TREE_CHAIN (properties))
14290 objc_add_property_declaration (loc, copy_node (properties),
14291 prop_attr_list);
14292 }
14293 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14294 }
14295
14296 while (!prop_attr_list.is_empty())
14297 delete prop_attr_list.pop ();
14298 prop_attr_list.release ();
14299 parser->error = false;
14300}
14301
14302/* Parse an Objective-C @synthesize declaration. The syntax is:
14303
14304 objc-synthesize-declaration:
14305 @synthesize objc-synthesize-identifier-list ;
14306
14307 objc-synthesize-identifier-list:
14308 objc-synthesize-identifier
14309 objc-synthesize-identifier-list, objc-synthesize-identifier
14310
14311 objc-synthesize-identifier
14312 identifier
14313 identifier = identifier
14314
14315 For example:
14316 @synthesize MyProperty;
14317 @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
14318
14319 PS: This function is identical to cp_parser_objc_at_synthesize_declaration
14320 for C++. Keep them in sync.
14321*/
14322static void
14323c_parser_objc_at_synthesize_declaration (c_parser *parser)
14324{
14325 tree list = NULL_TREE;
14326 location_t loc;
14327 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
14328 loc = c_parser_peek_token (parser)->location;
14329
14330 c_parser_consume_token (parser);
14331 while (true)
14332 {
14333 tree property, ivar;
14334 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14335 {
14336 c_parser_error (parser, gmsgid: "expected identifier");
14337 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14338 /* Once we find the semicolon, we can resume normal parsing.
14339 We have to reset parser->error manually because
14340 c_parser_skip_until_found() won't reset it for us if the
14341 next token is precisely a semicolon. */
14342 parser->error = false;
14343 return;
14344 }
14345 property = c_parser_peek_token (parser)->value;
14346 c_parser_consume_token (parser);
14347 if (c_parser_next_token_is (parser, type: CPP_EQ))
14348 {
14349 c_parser_consume_token (parser);
14350 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14351 {
14352 c_parser_error (parser, gmsgid: "expected identifier");
14353 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14354 parser->error = false;
14355 return;
14356 }
14357 ivar = c_parser_peek_token (parser)->value;
14358 c_parser_consume_token (parser);
14359 }
14360 else
14361 ivar = NULL_TREE;
14362 list = chainon (list, build_tree_list (ivar, property));
14363 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14364 c_parser_consume_token (parser);
14365 else
14366 break;
14367 }
14368 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14369 objc_add_synthesize_declaration (loc, list);
14370}
14371
14372/* Parse an Objective-C @dynamic declaration. The syntax is:
14373
14374 objc-dynamic-declaration:
14375 @dynamic identifier-list ;
14376
14377 For example:
14378 @dynamic MyProperty;
14379 @dynamic MyProperty, AnotherProperty;
14380
14381 PS: This function is identical to cp_parser_objc_at_dynamic_declaration
14382 for C++. Keep them in sync.
14383*/
14384static void
14385c_parser_objc_at_dynamic_declaration (c_parser *parser)
14386{
14387 tree list = NULL_TREE;
14388 location_t loc;
14389 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
14390 loc = c_parser_peek_token (parser)->location;
14391
14392 c_parser_consume_token (parser);
14393 while (true)
14394 {
14395 tree property;
14396 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14397 {
14398 c_parser_error (parser, gmsgid: "expected identifier");
14399 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14400 parser->error = false;
14401 return;
14402 }
14403 property = c_parser_peek_token (parser)->value;
14404 list = chainon (list, build_tree_list (NULL_TREE, property));
14405 c_parser_consume_token (parser);
14406 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14407 c_parser_consume_token (parser);
14408 else
14409 break;
14410 }
14411 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14412 objc_add_dynamic_declaration (loc, list);
14413}
14414
14415
14416/* Parse a pragma GCC ivdep. */
14417
14418static bool
14419c_parse_pragma_ivdep (c_parser *parser)
14420{
14421 c_parser_consume_pragma (parser);
14422 c_parser_skip_to_pragma_eol (parser);
14423 return true;
14424}
14425
14426/* Parse a pragma GCC novector. */
14427
14428static bool
14429c_parse_pragma_novector (c_parser *parser)
14430{
14431 c_parser_consume_pragma (parser);
14432 c_parser_skip_to_pragma_eol (parser);
14433 return true;
14434}
14435
14436/* Parse a pragma GCC unroll. */
14437
14438static unsigned short
14439c_parser_pragma_unroll (c_parser *parser)
14440{
14441 unsigned short unroll;
14442 c_parser_consume_pragma (parser);
14443 location_t location = c_parser_peek_token (parser)->location;
14444 tree expr = c_parser_expr_no_commas (parser, NULL).value;
14445 mark_exp_read (expr);
14446 expr = c_fully_fold (expr, false, NULL);
14447 HOST_WIDE_INT lunroll = 0;
14448 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
14449 || TREE_CODE (expr) != INTEGER_CST
14450 || (lunroll = tree_to_shwi (expr)) < 0
14451 || lunroll >= USHRT_MAX)
14452 {
14453 error_at (location, "%<#pragma GCC unroll%> requires an"
14454 " assignment-expression that evaluates to a non-negative"
14455 " integral constant less than %u", USHRT_MAX);
14456 unroll = 0;
14457 }
14458 else
14459 {
14460 unroll = (unsigned short)lunroll;
14461 if (unroll == 0)
14462 unroll = 1;
14463 }
14464
14465 c_parser_skip_to_pragma_eol (parser);
14466 return unroll;
14467}
14468
14469/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
14470 should be considered, statements. ALLOW_STMT is true if we're within
14471 the context of a function and such pragmas are to be allowed. Returns
14472 true if we actually parsed such a pragma. */
14473
14474static bool
14475c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
14476{
14477 unsigned int id;
14478 const char *construct = NULL;
14479
14480 input_location = c_parser_peek_token (parser)->location;
14481 id = c_parser_peek_token (parser)->pragma_kind;
14482 gcc_assert (id != PRAGMA_NONE);
14483 if (parser->omp_for_parse_state
14484 && parser->omp_for_parse_state->in_intervening_code
14485 && id >= PRAGMA_OMP__START_
14486 && id <= PRAGMA_OMP__LAST_)
14487 {
14488 error_at (input_location,
14489 "intervening code must not contain OpenMP directives");
14490 parser->omp_for_parse_state->fail = true;
14491 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14492 return false;
14493 }
14494
14495 switch (id)
14496 {
14497 case PRAGMA_OACC_DECLARE:
14498 c_parser_oacc_declare (parser);
14499 return false;
14500
14501 case PRAGMA_OACC_ENTER_DATA:
14502 if (context != pragma_compound)
14503 {
14504 construct = "acc enter data";
14505 in_compound:
14506 if (context == pragma_stmt)
14507 {
14508 error_at (c_parser_peek_token (parser)->location,
14509 "%<#pragma %s%> may only be used in compound "
14510 "statements", construct);
14511 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14512 return true;
14513 }
14514 goto bad_stmt;
14515 }
14516 c_parser_oacc_enter_exit_data (parser, true);
14517 return false;
14518
14519 case PRAGMA_OACC_EXIT_DATA:
14520 if (context != pragma_compound)
14521 {
14522 construct = "acc exit data";
14523 goto in_compound;
14524 }
14525 c_parser_oacc_enter_exit_data (parser, false);
14526 return false;
14527
14528 case PRAGMA_OACC_ROUTINE:
14529 if (context != pragma_external)
14530 {
14531 error_at (c_parser_peek_token (parser)->location,
14532 "%<#pragma acc routine%> must be at file scope");
14533 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14534 return false;
14535 }
14536 c_parser_oacc_routine (parser, context);
14537 return false;
14538
14539 case PRAGMA_OACC_UPDATE:
14540 if (context != pragma_compound)
14541 {
14542 construct = "acc update";
14543 goto in_compound;
14544 }
14545 c_parser_oacc_update (parser);
14546 return false;
14547
14548 case PRAGMA_OMP_BARRIER:
14549 if (context != pragma_compound)
14550 {
14551 construct = "omp barrier";
14552 goto in_compound;
14553 }
14554 c_parser_omp_barrier (parser);
14555 return false;
14556
14557 case PRAGMA_OMP_DEPOBJ:
14558 if (context != pragma_compound)
14559 {
14560 construct = "omp depobj";
14561 goto in_compound;
14562 }
14563 c_parser_omp_depobj (parser);
14564 return false;
14565
14566 case PRAGMA_OMP_FLUSH:
14567 if (context != pragma_compound)
14568 {
14569 construct = "omp flush";
14570 goto in_compound;
14571 }
14572 c_parser_omp_flush (parser);
14573 return false;
14574
14575 case PRAGMA_OMP_TASKWAIT:
14576 if (context != pragma_compound)
14577 {
14578 construct = "omp taskwait";
14579 goto in_compound;
14580 }
14581 c_parser_omp_taskwait (parser);
14582 return false;
14583
14584 case PRAGMA_OMP_TASKYIELD:
14585 if (context != pragma_compound)
14586 {
14587 construct = "omp taskyield";
14588 goto in_compound;
14589 }
14590 c_parser_omp_taskyield (parser);
14591 return false;
14592
14593 case PRAGMA_OMP_CANCEL:
14594 if (context != pragma_compound)
14595 {
14596 construct = "omp cancel";
14597 goto in_compound;
14598 }
14599 c_parser_omp_cancel (parser);
14600 return false;
14601
14602 case PRAGMA_OMP_CANCELLATION_POINT:
14603 return c_parser_omp_cancellation_point (parser, context);
14604
14605 case PRAGMA_OMP_THREADPRIVATE:
14606 c_parser_omp_threadprivate (parser);
14607 return false;
14608
14609 case PRAGMA_OMP_TARGET:
14610 return c_parser_omp_target (parser, context, if_p);
14611
14612 case PRAGMA_OMP_BEGIN:
14613 c_parser_omp_begin (parser);
14614 return false;
14615
14616 case PRAGMA_OMP_END:
14617 c_parser_omp_end (parser);
14618 return false;
14619
14620 case PRAGMA_OMP_SCAN:
14621 error_at (c_parser_peek_token (parser)->location,
14622 "%<#pragma omp scan%> may only be used in "
14623 "a loop construct with %<inscan%> %<reduction%> clause");
14624 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14625 return false;
14626
14627 case PRAGMA_OMP_SECTION:
14628 error_at (c_parser_peek_token (parser)->location,
14629 "%<#pragma omp section%> may only be used in "
14630 "%<#pragma omp sections%> construct");
14631 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14632 return false;
14633
14634 case PRAGMA_OMP_DECLARE:
14635 return c_parser_omp_declare (parser, context);
14636
14637 case PRAGMA_OMP_REQUIRES:
14638 if (context != pragma_external)
14639 {
14640 error_at (c_parser_peek_token (parser)->location,
14641 "%<#pragma %s%> may only be used at file scope",
14642 "omp requires");
14643 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14644 return false;
14645 }
14646 c_parser_omp_requires (parser);
14647 return false;
14648
14649 case PRAGMA_OMP_ALLOCATE:
14650 c_parser_omp_allocate (parser);
14651 return false;
14652
14653 case PRAGMA_OMP_ASSUMES:
14654 if (context != pragma_external)
14655 {
14656 error_at (c_parser_peek_token (parser)->location,
14657 "%<#pragma %s%> may only be used at file scope",
14658 "omp assumes");
14659 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14660 return false;
14661 }
14662 c_parser_omp_assumes (parser);
14663 return false;
14664
14665 case PRAGMA_OMP_NOTHING:
14666 c_parser_omp_nothing (parser);
14667 return false;
14668
14669 case PRAGMA_OMP_ERROR:
14670 return c_parser_omp_error (parser, context);
14671
14672 case PRAGMA_OMP_ORDERED:
14673 return c_parser_omp_ordered (parser, context, if_p);
14674
14675 case PRAGMA_NOVECTOR:
14676 case PRAGMA_UNROLL:
14677 case PRAGMA_IVDEP:
14678 {
14679 bool novector = false;
14680 unsigned short unroll = 0;
14681 bool ivdep = false;
14682
14683 switch (id)
14684 {
14685 case PRAGMA_NOVECTOR:
14686 novector = c_parse_pragma_novector (parser);
14687 break;
14688 case PRAGMA_UNROLL:
14689 unroll = c_parser_pragma_unroll (parser);
14690 break;
14691 case PRAGMA_IVDEP:
14692 ivdep = c_parse_pragma_ivdep (parser);
14693 break;
14694 default:
14695 gcc_unreachable ();
14696 }
14697
14698 c_token *tok = c_parser_peek_token (parser);
14699 bool has_more = tok->type == CPP_PRAGMA;
14700 while (has_more)
14701 {
14702 switch (tok->pragma_kind)
14703 {
14704 case PRAGMA_IVDEP:
14705 ivdep = c_parse_pragma_ivdep (parser);
14706 break;
14707 case PRAGMA_UNROLL:
14708 unroll = c_parser_pragma_unroll (parser);
14709 break;
14710 case PRAGMA_NOVECTOR:
14711 novector = c_parse_pragma_novector (parser);
14712 break;
14713 default:
14714 has_more = false;
14715 break;
14716 }
14717 tok = c_parser_peek_token (parser);
14718 has_more = has_more && tok->type == CPP_PRAGMA;
14719 }
14720 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR)
14721 && !c_parser_next_token_is_keyword (parser, keyword: RID_WHILE)
14722 && !c_parser_next_token_is_keyword (parser, keyword: RID_DO))
14723 {
14724 c_parser_error (parser, gmsgid: "for, while or do statement expected");
14725 return false;
14726 }
14727 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
14728 c_parser_for_statement (parser, ivdep, unroll, novector, if_p);
14729 else if (c_parser_next_token_is_keyword (parser, keyword: RID_WHILE))
14730 c_parser_while_statement (parser, ivdep, unroll, novector, if_p);
14731 else
14732 c_parser_do_statement (parser, ivdep, unroll, novector);
14733 }
14734 return true;
14735
14736 case PRAGMA_GCC_PCH_PREPROCESS:
14737 c_parser_error (parser, gmsgid: "%<#pragma GCC pch_preprocess%> must be first");
14738 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14739 return false;
14740
14741 case PRAGMA_OACC_WAIT:
14742 if (context != pragma_compound)
14743 {
14744 construct = "acc wait";
14745 goto in_compound;
14746 }
14747 /* FALL THROUGH. */
14748
14749 default:
14750 if (id < PRAGMA_FIRST_EXTERNAL)
14751 {
14752 if (context != pragma_stmt && context != pragma_compound)
14753 {
14754 bad_stmt:
14755 c_parser_error (parser, gmsgid: "expected declaration specifiers");
14756 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14757 return false;
14758 }
14759 c_parser_omp_construct (parser, if_p);
14760 return true;
14761 }
14762 break;
14763 }
14764
14765 c_parser_consume_pragma (parser);
14766 c_invoke_pragma_handler (id);
14767
14768 /* Skip to EOL, but suppress any error message. Those will have been
14769 generated by the handler routine through calling error, as opposed
14770 to calling c_parser_error. */
14771 parser->error = true;
14772 c_parser_skip_to_pragma_eol (parser);
14773
14774 return false;
14775}
14776
14777/* The interface the pragma parsers have to the lexer. */
14778
14779enum cpp_ttype
14780pragma_lex (tree *value, location_t *loc)
14781{
14782 c_token *tok = c_parser_peek_token (parser: the_parser);
14783 enum cpp_ttype ret = tok->type;
14784
14785 *value = tok->value;
14786 if (loc)
14787 *loc = tok->location;
14788
14789 if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
14790 ret = CPP_EOF;
14791 else if (ret == CPP_STRING)
14792 *value = c_parser_string_literal (parser: the_parser, translate: false, wide_ok: false).value;
14793 else
14794 {
14795 if (ret == CPP_KEYWORD)
14796 ret = CPP_NAME;
14797 c_parser_consume_token (parser: the_parser);
14798 }
14799
14800 return ret;
14801}
14802
14803void
14804pragma_lex_discard_to_eol ()
14805{
14806 cpp_ttype type;
14807 do
14808 {
14809 type = c_parser_peek_token (parser: the_parser)->type;
14810 gcc_assert (type != CPP_EOF);
14811 c_parser_consume_token (parser: the_parser);
14812 } while (type != CPP_PRAGMA_EOL);
14813}
14814
14815static void
14816c_parser_pragma_pch_preprocess (c_parser *parser)
14817{
14818 tree name = NULL;
14819
14820 parser->lex_joined_string = true;
14821 c_parser_consume_pragma (parser);
14822 if (c_parser_next_token_is (parser, type: CPP_STRING))
14823 {
14824 name = c_parser_peek_token (parser)->value;
14825 c_parser_consume_token (parser);
14826 }
14827 else
14828 c_parser_error (parser, gmsgid: "expected string literal");
14829 c_parser_skip_to_pragma_eol (parser);
14830 parser->lex_joined_string = false;
14831
14832 if (name)
14833 c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name));
14834}
14835
14836/* OpenACC and OpenMP parsing routines. */
14837
14838/* Returns name of the next clause.
14839 If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
14840 the token is not consumed. Otherwise appropriate pragma_omp_clause is
14841 returned and the token is consumed. */
14842
14843static pragma_omp_clause
14844c_parser_omp_clause_name (c_parser *parser)
14845{
14846 pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
14847
14848 if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
14849 result = PRAGMA_OACC_CLAUSE_AUTO;
14850 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IF))
14851 result = PRAGMA_OMP_CLAUSE_IF;
14852 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
14853 result = PRAGMA_OMP_CLAUSE_DEFAULT;
14854 else if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
14855 result = PRAGMA_OMP_CLAUSE_FOR;
14856 else if (c_parser_next_token_is (parser, type: CPP_NAME))
14857 {
14858 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
14859
14860 switch (p[0])
14861 {
14862 case 'a':
14863 if (!strcmp (s1: "affinity", s2: p))
14864 result = PRAGMA_OMP_CLAUSE_AFFINITY;
14865 else if (!strcmp (s1: "aligned", s2: p))
14866 result = PRAGMA_OMP_CLAUSE_ALIGNED;
14867 else if (!strcmp (s1: "allocate", s2: p))
14868 result = PRAGMA_OMP_CLAUSE_ALLOCATE;
14869 else if (!strcmp (s1: "async", s2: p))
14870 result = PRAGMA_OACC_CLAUSE_ASYNC;
14871 else if (!strcmp (s1: "attach", s2: p))
14872 result = PRAGMA_OACC_CLAUSE_ATTACH;
14873 break;
14874 case 'b':
14875 if (!strcmp (s1: "bind", s2: p))
14876 result = PRAGMA_OMP_CLAUSE_BIND;
14877 break;
14878 case 'c':
14879 if (!strcmp (s1: "collapse", s2: p))
14880 result = PRAGMA_OMP_CLAUSE_COLLAPSE;
14881 else if (!strcmp (s1: "copy", s2: p))
14882 result = PRAGMA_OACC_CLAUSE_COPY;
14883 else if (!strcmp (s1: "copyin", s2: p))
14884 result = PRAGMA_OMP_CLAUSE_COPYIN;
14885 else if (!strcmp (s1: "copyout", s2: p))
14886 result = PRAGMA_OACC_CLAUSE_COPYOUT;
14887 else if (!strcmp (s1: "copyprivate", s2: p))
14888 result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
14889 else if (!strcmp (s1: "create", s2: p))
14890 result = PRAGMA_OACC_CLAUSE_CREATE;
14891 break;
14892 case 'd':
14893 if (!strcmp (s1: "defaultmap", s2: p))
14894 result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
14895 else if (!strcmp (s1: "delete", s2: p))
14896 result = PRAGMA_OACC_CLAUSE_DELETE;
14897 else if (!strcmp (s1: "depend", s2: p))
14898 result = PRAGMA_OMP_CLAUSE_DEPEND;
14899 else if (!strcmp (s1: "detach", s2: p))
14900 result = PRAGMA_OACC_CLAUSE_DETACH;
14901 else if (!strcmp (s1: "device", s2: p))
14902 result = PRAGMA_OMP_CLAUSE_DEVICE;
14903 else if (!strcmp (s1: "deviceptr", s2: p))
14904 result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
14905 else if (!strcmp (s1: "device_resident", s2: p))
14906 result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
14907 else if (!strcmp (s1: "device_type", s2: p))
14908 result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
14909 else if (!strcmp (s1: "dist_schedule", s2: p))
14910 result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
14911 else if (!strcmp (s1: "doacross", s2: p))
14912 result = PRAGMA_OMP_CLAUSE_DOACROSS;
14913 break;
14914 case 'e':
14915 if (!strcmp (s1: "enter", s2: p))
14916 result = PRAGMA_OMP_CLAUSE_ENTER;
14917 break;
14918 case 'f':
14919 if (!strcmp (s1: "filter", s2: p))
14920 result = PRAGMA_OMP_CLAUSE_FILTER;
14921 else if (!strcmp (s1: "final", s2: p))
14922 result = PRAGMA_OMP_CLAUSE_FINAL;
14923 else if (!strcmp (s1: "finalize", s2: p))
14924 result = PRAGMA_OACC_CLAUSE_FINALIZE;
14925 else if (!strcmp (s1: "firstprivate", s2: p))
14926 result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
14927 else if (!strcmp (s1: "from", s2: p))
14928 result = PRAGMA_OMP_CLAUSE_FROM;
14929 break;
14930 case 'g':
14931 if (!strcmp (s1: "gang", s2: p))
14932 result = PRAGMA_OACC_CLAUSE_GANG;
14933 else if (!strcmp (s1: "grainsize", s2: p))
14934 result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
14935 break;
14936 case 'h':
14937 if (!strcmp (s1: "has_device_addr", s2: p))
14938 result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
14939 else if (!strcmp (s1: "hint", s2: p))
14940 result = PRAGMA_OMP_CLAUSE_HINT;
14941 else if (!strcmp (s1: "host", s2: p))
14942 result = PRAGMA_OACC_CLAUSE_HOST;
14943 break;
14944 case 'i':
14945 if (!strcmp (s1: "if_present", s2: p))
14946 result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
14947 else if (!strcmp (s1: "in_reduction", s2: p))
14948 result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
14949 else if (!strcmp (s1: "inbranch", s2: p))
14950 result = PRAGMA_OMP_CLAUSE_INBRANCH;
14951 else if (!strcmp (s1: "independent", s2: p))
14952 result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
14953 else if (!strcmp (s1: "indirect", s2: p))
14954 result = PRAGMA_OMP_CLAUSE_INDIRECT;
14955 else if (!strcmp (s1: "is_device_ptr", s2: p))
14956 result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
14957 break;
14958 case 'l':
14959 if (!strcmp (s1: "lastprivate", s2: p))
14960 result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
14961 else if (!strcmp (s1: "linear", s2: p))
14962 result = PRAGMA_OMP_CLAUSE_LINEAR;
14963 else if (!strcmp (s1: "link", s2: p))
14964 result = PRAGMA_OMP_CLAUSE_LINK;
14965 break;
14966 case 'm':
14967 if (!strcmp (s1: "map", s2: p))
14968 result = PRAGMA_OMP_CLAUSE_MAP;
14969 else if (!strcmp (s1: "mergeable", s2: p))
14970 result = PRAGMA_OMP_CLAUSE_MERGEABLE;
14971 break;
14972 case 'n':
14973 if (!strcmp (s1: "no_create", s2: p))
14974 result = PRAGMA_OACC_CLAUSE_NO_CREATE;
14975 else if (!strcmp (s1: "nogroup", s2: p))
14976 result = PRAGMA_OMP_CLAUSE_NOGROUP;
14977 else if (!strcmp (s1: "nohost", s2: p))
14978 result = PRAGMA_OACC_CLAUSE_NOHOST;
14979 else if (!strcmp (s1: "nontemporal", s2: p))
14980 result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
14981 else if (!strcmp (s1: "notinbranch", s2: p))
14982 result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
14983 else if (!strcmp (s1: "nowait", s2: p))
14984 result = PRAGMA_OMP_CLAUSE_NOWAIT;
14985 else if (!strcmp (s1: "num_gangs", s2: p))
14986 result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
14987 else if (!strcmp (s1: "num_tasks", s2: p))
14988 result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
14989 else if (!strcmp (s1: "num_teams", s2: p))
14990 result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
14991 else if (!strcmp (s1: "num_threads", s2: p))
14992 result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
14993 else if (!strcmp (s1: "num_workers", s2: p))
14994 result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
14995 break;
14996 case 'o':
14997 if (!strcmp (s1: "ordered", s2: p))
14998 result = PRAGMA_OMP_CLAUSE_ORDERED;
14999 else if (!strcmp (s1: "order", s2: p))
15000 result = PRAGMA_OMP_CLAUSE_ORDER;
15001 break;
15002 case 'p':
15003 if (!strcmp (s1: "parallel", s2: p))
15004 result = PRAGMA_OMP_CLAUSE_PARALLEL;
15005 else if (!strcmp (s1: "present", s2: p))
15006 result = PRAGMA_OACC_CLAUSE_PRESENT;
15007 /* As of OpenACC 2.5, these are now aliases of the non-present_or
15008 clauses. */
15009 else if (!strcmp (s1: "present_or_copy", s2: p)
15010 || !strcmp (s1: "pcopy", s2: p))
15011 result = PRAGMA_OACC_CLAUSE_COPY;
15012 else if (!strcmp (s1: "present_or_copyin", s2: p)
15013 || !strcmp (s1: "pcopyin", s2: p))
15014 result = PRAGMA_OACC_CLAUSE_COPYIN;
15015 else if (!strcmp (s1: "present_or_copyout", s2: p)
15016 || !strcmp (s1: "pcopyout", s2: p))
15017 result = PRAGMA_OACC_CLAUSE_COPYOUT;
15018 else if (!strcmp (s1: "present_or_create", s2: p)
15019 || !strcmp (s1: "pcreate", s2: p))
15020 result = PRAGMA_OACC_CLAUSE_CREATE;
15021 else if (!strcmp (s1: "priority", s2: p))
15022 result = PRAGMA_OMP_CLAUSE_PRIORITY;
15023 else if (!strcmp (s1: "private", s2: p))
15024 result = PRAGMA_OMP_CLAUSE_PRIVATE;
15025 else if (!strcmp (s1: "proc_bind", s2: p))
15026 result = PRAGMA_OMP_CLAUSE_PROC_BIND;
15027 break;
15028 case 'r':
15029 if (!strcmp (s1: "reduction", s2: p))
15030 result = PRAGMA_OMP_CLAUSE_REDUCTION;
15031 break;
15032 case 's':
15033 if (!strcmp (s1: "safelen", s2: p))
15034 result = PRAGMA_OMP_CLAUSE_SAFELEN;
15035 else if (!strcmp (s1: "schedule", s2: p))
15036 result = PRAGMA_OMP_CLAUSE_SCHEDULE;
15037 else if (!strcmp (s1: "sections", s2: p))
15038 result = PRAGMA_OMP_CLAUSE_SECTIONS;
15039 else if (!strcmp (s1: "self", s2: p))
15040 result = PRAGMA_OACC_CLAUSE_SELF;
15041 else if (!strcmp (s1: "seq", s2: p))
15042 result = PRAGMA_OACC_CLAUSE_SEQ;
15043 else if (!strcmp (s1: "shared", s2: p))
15044 result = PRAGMA_OMP_CLAUSE_SHARED;
15045 else if (!strcmp (s1: "simd", s2: p))
15046 result = PRAGMA_OMP_CLAUSE_SIMD;
15047 else if (!strcmp (s1: "simdlen", s2: p))
15048 result = PRAGMA_OMP_CLAUSE_SIMDLEN;
15049 break;
15050 case 't':
15051 if (!strcmp (s1: "task_reduction", s2: p))
15052 result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
15053 else if (!strcmp (s1: "taskgroup", s2: p))
15054 result = PRAGMA_OMP_CLAUSE_TASKGROUP;
15055 else if (!strcmp (s1: "thread_limit", s2: p))
15056 result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
15057 else if (!strcmp (s1: "threads", s2: p))
15058 result = PRAGMA_OMP_CLAUSE_THREADS;
15059 else if (!strcmp (s1: "tile", s2: p))
15060 result = PRAGMA_OACC_CLAUSE_TILE;
15061 else if (!strcmp (s1: "to", s2: p))
15062 result = PRAGMA_OMP_CLAUSE_TO;
15063 break;
15064 case 'u':
15065 if (!strcmp (s1: "uniform", s2: p))
15066 result = PRAGMA_OMP_CLAUSE_UNIFORM;
15067 else if (!strcmp (s1: "untied", s2: p))
15068 result = PRAGMA_OMP_CLAUSE_UNTIED;
15069 else if (!strcmp (s1: "use_device", s2: p))
15070 result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
15071 else if (!strcmp (s1: "use_device_addr", s2: p))
15072 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
15073 else if (!strcmp (s1: "use_device_ptr", s2: p))
15074 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
15075 break;
15076 case 'v':
15077 if (!strcmp (s1: "vector", s2: p))
15078 result = PRAGMA_OACC_CLAUSE_VECTOR;
15079 else if (!strcmp (s1: "vector_length", s2: p))
15080 result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
15081 break;
15082 case 'w':
15083 if (!strcmp (s1: "wait", s2: p))
15084 result = PRAGMA_OACC_CLAUSE_WAIT;
15085 else if (!strcmp (s1: "worker", s2: p))
15086 result = PRAGMA_OACC_CLAUSE_WORKER;
15087 break;
15088 }
15089 }
15090
15091 if (result != PRAGMA_OMP_CLAUSE_NONE)
15092 c_parser_consume_token (parser);
15093
15094 return result;
15095}
15096
15097/* Validate that a clause of the given type does not already exist. */
15098
15099static void
15100check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
15101 const char *name)
15102{
15103 if (tree c = omp_find_clause (clauses, kind: code))
15104 error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
15105}
15106
15107/* OpenACC 2.0
15108 Parse wait clause or wait directive parameters. */
15109
15110static tree
15111c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
15112{
15113 vec<tree, va_gc> *args;
15114 tree t, args_tree;
15115
15116 matching_parens parens;
15117 if (!parens.require_open (parser))
15118 return list;
15119
15120 args = c_parser_expr_list (parser, convert_p: false, fold_p: true, NULL, NULL, NULL, NULL);
15121 args_tree = build_tree_list_vec (args);
15122
15123 for (t = args_tree; t; t = TREE_CHAIN (t))
15124 {
15125 tree targ = TREE_VALUE (t);
15126
15127 if (targ != error_mark_node)
15128 {
15129 if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
15130 {
15131 c_parser_error (parser, gmsgid: "expression must be integral");
15132 targ = error_mark_node;
15133 }
15134 else
15135 {
15136 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
15137
15138 OMP_CLAUSE_DECL (c) = targ;
15139 OMP_CLAUSE_CHAIN (c) = list;
15140 list = c;
15141 }
15142 }
15143 }
15144
15145 release_tree_vector (args);
15146 parens.require_close (parser);
15147 return list;
15148}
15149
15150/* OpenACC 2.0, OpenMP 2.5:
15151 variable-list:
15152 identifier
15153 variable-list , identifier
15154
15155 If KIND is nonzero, create the appropriate node and install the
15156 decl in OMP_CLAUSE_DECL and add the node to the head of the list.
15157 If KIND is nonzero, CLAUSE_LOC is the location of the clause.
15158
15159 If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
15160 return the list created.
15161
15162 The optional ALLOW_DEREF argument is true if list items can use the deref
15163 (->) operator. */
15164
15165struct omp_dim
15166{
15167 tree low_bound, length;
15168 location_t loc;
15169 bool no_colon;
15170 omp_dim (tree lb, tree len, location_t lo, bool nc)
15171 : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
15172};
15173
15174static tree
15175c_parser_omp_variable_list (c_parser *parser,
15176 location_t clause_loc,
15177 enum omp_clause_code kind, tree list,
15178 bool map_lvalue = false)
15179{
15180 auto_vec<omp_dim> dims;
15181 bool array_section_p;
15182 auto_vec<c_token> tokens;
15183 unsigned int tokens_avail = 0;
15184 c_token *saved_tokens = NULL;
15185 bool first = true;
15186
15187 while (1)
15188 {
15189 tree t = NULL_TREE;
15190
15191 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
15192 {
15193 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
15194 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
15195 {
15196 struct c_expr expr;
15197 if (kind == OMP_CLAUSE_DEPEND
15198 && c_parser_next_token_is_keyword (parser,
15199 keyword: RID_OMP_ALL_MEMORY)
15200 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
15201 || (c_parser_peek_2nd_token (parser)->type
15202 == CPP_CLOSE_PAREN)))
15203 {
15204 expr.value = ridpointers[RID_OMP_ALL_MEMORY];
15205 c_parser_consume_token (parser);
15206 }
15207 else
15208 expr = c_parser_expr_no_commas (parser, NULL);
15209 if (expr.value != error_mark_node)
15210 {
15211 tree u = build_omp_clause (clause_loc, kind);
15212 OMP_CLAUSE_DECL (u) = expr.value;
15213 OMP_CLAUSE_CHAIN (u) = list;
15214 list = u;
15215 }
15216
15217 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
15218 break;
15219
15220 c_parser_consume_token (parser);
15221 first = false;
15222 continue;
15223 }
15224
15225 tokens.truncate (size: 0);
15226 unsigned int nesting_depth = 0;
15227 while (1)
15228 {
15229 c_token *token = c_parser_peek_token (parser);
15230 switch (token->type)
15231 {
15232 case CPP_EOF:
15233 case CPP_PRAGMA_EOL:
15234 break;
15235 case CPP_OPEN_BRACE:
15236 case CPP_OPEN_PAREN:
15237 case CPP_OPEN_SQUARE:
15238 ++nesting_depth;
15239 goto add;
15240 case CPP_CLOSE_BRACE:
15241 case CPP_CLOSE_PAREN:
15242 case CPP_CLOSE_SQUARE:
15243 if (nesting_depth-- == 0)
15244 break;
15245 goto add;
15246 case CPP_COMMA:
15247 if (nesting_depth == 0)
15248 break;
15249 goto add;
15250 default:
15251 add:
15252 tokens.safe_push (obj: *token);
15253 c_parser_consume_token (parser);
15254 continue;
15255 }
15256 break;
15257 }
15258
15259 /* Make sure nothing tries to read past the end of the tokens. */
15260 c_token eof_token;
15261 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
15262 eof_token.type = CPP_EOF;
15263 tokens.safe_push (obj: eof_token);
15264 tokens.safe_push (obj: eof_token);
15265
15266 saved_tokens = parser->tokens;
15267 tokens_avail = parser->tokens_avail;
15268 parser->tokens = tokens.address ();
15269 parser->tokens_avail = tokens.length ();
15270 }
15271 else if (map_lvalue
15272 && (kind == OMP_CLAUSE_MAP
15273 || kind == OMP_CLAUSE_TO
15274 || kind == OMP_CLAUSE_FROM))
15275 {
15276 location_t loc = c_parser_peek_token (parser)->location;
15277 bool save_c_omp_array_section_p = c_omp_array_section_p;
15278 c_omp_array_section_p = true;
15279 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15280 if (expr.value != error_mark_node)
15281 mark_exp_read (expr.value);
15282 c_omp_array_section_p = save_c_omp_array_section_p;
15283 tree decl = expr.value;
15284
15285 /* This code rewrites a parsed expression containing various tree
15286 codes used to represent array accesses into a more uniform nest of
15287 OMP_ARRAY_SECTION nodes before it is processed by
15288 c-typeck.cc:handle_omp_array_sections_1. It might be more
15289 efficient to move this logic to that function instead, analysing
15290 the parsed expression directly rather than this preprocessed
15291 form. (See also equivalent code in cp/parser.cc,
15292 cp/semantics.cc). */
15293 dims.truncate (size: 0);
15294 if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
15295 {
15296 while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
15297 {
15298 tree low_bound = TREE_OPERAND (decl, 1);
15299 tree length = TREE_OPERAND (decl, 2);
15300 dims.safe_push (obj: omp_dim (low_bound, length, loc, false));
15301 decl = TREE_OPERAND (decl, 0);
15302 }
15303
15304 while (TREE_CODE (decl) == ARRAY_REF
15305 || TREE_CODE (decl) == INDIRECT_REF
15306 || TREE_CODE (decl) == COMPOUND_EXPR)
15307 {
15308 if (TREE_CODE (decl) == COMPOUND_EXPR)
15309 {
15310 decl = TREE_OPERAND (decl, 1);
15311 STRIP_NOPS (decl);
15312 }
15313 else if (TREE_CODE (decl) == INDIRECT_REF)
15314 {
15315 dims.safe_push (obj: omp_dim (integer_zero_node,
15316 integer_one_node, loc, true));
15317 decl = TREE_OPERAND (decl, 0);
15318 }
15319 else /* ARRAY_REF. */
15320 {
15321 tree index = TREE_OPERAND (decl, 1);
15322 dims.safe_push (obj: omp_dim (index, integer_one_node, loc,
15323 true));
15324 decl = TREE_OPERAND (decl, 0);
15325 }
15326 }
15327
15328 for (int i = dims.length () - 1; i >= 0; i--)
15329 decl = build_omp_array_section (loc, decl, dims[i].low_bound,
15330 dims[i].length);
15331 }
15332 else if (TREE_CODE (decl) == INDIRECT_REF)
15333 {
15334 /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
15335 decl = TREE_OPERAND (decl, 0);
15336 STRIP_NOPS (decl);
15337
15338 decl = build_omp_array_section (loc, decl, integer_zero_node,
15339 integer_one_node);
15340 }
15341 else if (TREE_CODE (decl) == ARRAY_REF)
15342 {
15343 tree idx = TREE_OPERAND (decl, 1);
15344
15345 decl = TREE_OPERAND (decl, 0);
15346 STRIP_NOPS (decl);
15347
15348 decl = build_omp_array_section (loc, decl, idx, integer_one_node);
15349 }
15350 else if (TREE_CODE (decl) == NON_LVALUE_EXPR
15351 || CONVERT_EXPR_P (decl))
15352 decl = TREE_OPERAND (decl, 0);
15353
15354 tree u = build_omp_clause (clause_loc, kind);
15355 OMP_CLAUSE_DECL (u) = decl;
15356 OMP_CLAUSE_CHAIN (u) = list;
15357 list = u;
15358
15359 goto next_item;
15360 }
15361
15362 if (c_parser_next_token_is (parser, type: CPP_NAME)
15363 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
15364 {
15365 t = lookup_name (c_parser_peek_token (parser)->value);
15366
15367 if (t == NULL_TREE)
15368 {
15369 undeclared_variable (c_parser_peek_token (parser)->location,
15370 c_parser_peek_token (parser)->value);
15371 t = error_mark_node;
15372 }
15373
15374 c_parser_consume_token (parser);
15375 }
15376 else if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
15377 && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
15378 || (c_parser_peek_token (parser)->keyword
15379 == RID_PRETTY_FUNCTION_NAME)
15380 || (c_parser_peek_token (parser)->keyword
15381 == RID_C99_FUNCTION_NAME)))
15382 t = c_parser_predefined_identifier (parser).value;
15383 else
15384 {
15385 if (first)
15386 c_parser_error (parser, gmsgid: "expected identifier");
15387 break;
15388 }
15389
15390 if (t == error_mark_node)
15391 ;
15392 else if (kind != 0)
15393 {
15394 switch (kind)
15395 {
15396 case OMP_CLAUSE__CACHE_:
15397 /* The OpenACC cache directive explicitly only allows "array
15398 elements or subarrays". */
15399 if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
15400 {
15401 c_parser_error (parser, gmsgid: "expected %<[%>");
15402 t = error_mark_node;
15403 break;
15404 }
15405 /* FALLTHROUGH */
15406 case OMP_CLAUSE_MAP:
15407 case OMP_CLAUSE_FROM:
15408 case OMP_CLAUSE_TO:
15409 start_component_ref:
15410 while (c_parser_next_token_is (parser, type: CPP_DOT)
15411 || c_parser_next_token_is (parser, type: CPP_DEREF))
15412 {
15413 location_t op_loc = c_parser_peek_token (parser)->location;
15414 location_t arrow_loc = UNKNOWN_LOCATION;
15415 if (c_parser_next_token_is (parser, type: CPP_DEREF))
15416 {
15417 c_expr t_expr;
15418 t_expr.value = t;
15419 t_expr.original_code = ERROR_MARK;
15420 t_expr.original_type = NULL;
15421 set_c_expr_source_range (expr: &t_expr, start: op_loc, finish: op_loc);
15422 t_expr.m_decimal = 0;
15423 t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
15424 true, false);
15425 t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
15426 arrow_loc = t_expr.get_location ();
15427 }
15428 c_parser_consume_token (parser);
15429 if (!c_parser_next_token_is (parser, type: CPP_NAME))
15430 {
15431 c_parser_error (parser, gmsgid: "expected identifier");
15432 t = error_mark_node;
15433 break;
15434 }
15435
15436 c_token *comp_tok = c_parser_peek_token (parser);
15437 tree ident = comp_tok->value;
15438 location_t comp_loc = comp_tok->location;
15439 c_parser_consume_token (parser);
15440 t = build_component_ref (op_loc, t, ident, comp_loc,
15441 arrow_loc);
15442 }
15443 /* FALLTHROUGH */
15444 case OMP_CLAUSE_AFFINITY:
15445 case OMP_CLAUSE_DEPEND:
15446 case OMP_CLAUSE_REDUCTION:
15447 case OMP_CLAUSE_IN_REDUCTION:
15448 case OMP_CLAUSE_TASK_REDUCTION:
15449 case OMP_CLAUSE_HAS_DEVICE_ADDR:
15450 array_section_p = false;
15451 dims.truncate (size: 0);
15452 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
15453 {
15454 location_t loc = UNKNOWN_LOCATION;
15455 tree low_bound = NULL_TREE, length = NULL_TREE;
15456 bool no_colon = false;
15457
15458 c_parser_consume_token (parser);
15459 if (!c_parser_next_token_is (parser, type: CPP_COLON))
15460 {
15461 location_t expr_loc
15462 = c_parser_peek_token (parser)->location;
15463 c_expr expr = c_parser_expression (parser);
15464 expr = convert_lvalue_to_rvalue (expr_loc, expr,
15465 false, true);
15466 low_bound = expr.value;
15467 loc = expr_loc;
15468 }
15469 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
15470 {
15471 length = integer_one_node;
15472 no_colon = true;
15473 }
15474 else
15475 {
15476 /* Look for `:'. */
15477 if (!c_parser_require (parser, type: CPP_COLON,
15478 msgid: "expected %<:%>"))
15479 {
15480 t = error_mark_node;
15481 break;
15482 }
15483 array_section_p = true;
15484 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
15485 {
15486 location_t expr_loc
15487 = c_parser_peek_token (parser)->location;
15488 c_expr expr = c_parser_expression (parser);
15489 expr = convert_lvalue_to_rvalue (expr_loc, expr,
15490 false, true);
15491 length = expr.value;
15492 }
15493 }
15494 /* Look for the closing `]'. */
15495 if (!c_parser_require (parser, type: CPP_CLOSE_SQUARE,
15496 msgid: "expected %<]%>"))
15497 {
15498 t = error_mark_node;
15499 break;
15500 }
15501
15502 dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon));
15503 }
15504
15505 if (t != error_mark_node)
15506 {
15507 if ((kind == OMP_CLAUSE_MAP
15508 || kind == OMP_CLAUSE_FROM
15509 || kind == OMP_CLAUSE_TO)
15510 && !array_section_p
15511 && (c_parser_next_token_is (parser, type: CPP_DOT)
15512 || c_parser_next_token_is (parser, type: CPP_DEREF)))
15513 {
15514 for (unsigned i = 0; i < dims.length (); i++)
15515 {
15516 gcc_assert (dims[i].length == integer_one_node);
15517 t = build_array_ref (dims[i].loc,
15518 t, dims[i].low_bound);
15519 }
15520 goto start_component_ref;
15521 }
15522 else
15523 for (unsigned i = 0; i < dims.length (); i++)
15524 t = build_omp_array_section (clause_loc, t,
15525 dims[i].low_bound,
15526 dims[i].length);
15527 }
15528
15529 if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
15530 && t != error_mark_node
15531 && parser->tokens_avail != 2)
15532 {
15533 if (array_section_p)
15534 {
15535 error_at (c_parser_peek_token (parser)->location,
15536 "expected %<)%> or %<,%>");
15537 t = error_mark_node;
15538 }
15539 else
15540 {
15541 parser->tokens = tokens.address ();
15542 parser->tokens_avail = tokens.length ();
15543
15544 t = c_parser_expr_no_commas (parser, NULL).value;
15545 if (t != error_mark_node && parser->tokens_avail != 2)
15546 {
15547 error_at (c_parser_peek_token (parser)->location,
15548 "expected %<)%> or %<,%>");
15549 t = error_mark_node;
15550 }
15551 }
15552 }
15553 break;
15554 default:
15555 break;
15556 }
15557
15558 if (t != error_mark_node)
15559 {
15560 tree u = build_omp_clause (clause_loc, kind);
15561 OMP_CLAUSE_DECL (u) = t;
15562 OMP_CLAUSE_CHAIN (u) = list;
15563 list = u;
15564 }
15565 }
15566 else
15567 list = tree_cons (t, NULL_TREE, list);
15568
15569 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
15570 {
15571 parser->tokens = saved_tokens;
15572 parser->tokens_avail = tokens_avail;
15573 }
15574
15575 next_item:
15576 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
15577 break;
15578
15579 c_parser_consume_token (parser);
15580 first = false;
15581 }
15582
15583 return list;
15584}
15585
15586/* Similarly, but expect leading and trailing parenthesis. This is a very
15587 common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
15588 argument is true if list items can use the deref (->) operator. */
15589
15590static tree
15591c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
15592 tree list, bool map_lvalue = false)
15593{
15594 /* The clauses location. */
15595 location_t loc = c_parser_peek_token (parser)->location;
15596
15597 if (parser->in_omp_decl_attribute)
15598 {
15599 if (kind)
15600 {
15601 tree u = build_omp_clause (loc, kind);
15602 OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
15603 OMP_CLAUSE_CHAIN (u) = list;
15604 return u;
15605 }
15606 else
15607 return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
15608 }
15609
15610 matching_parens parens;
15611 if (parens.require_open (parser))
15612 {
15613 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list, map_lvalue);
15614 parens.skip_until_found_close (parser);
15615 }
15616 return list;
15617}
15618
15619/* OpenACC 2.0:
15620 copy ( variable-list )
15621 copyin ( variable-list )
15622 copyout ( variable-list )
15623 create ( variable-list )
15624 delete ( variable-list )
15625 present ( variable-list )
15626
15627 OpenACC 2.6:
15628 no_create ( variable-list )
15629 attach ( variable-list )
15630 detach ( variable-list )
15631
15632 OpenACC 2.7:
15633 copyin (readonly : variable-list )
15634 */
15635
15636static tree
15637c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
15638 tree list)
15639{
15640 enum gomp_map_kind kind;
15641 switch (c_kind)
15642 {
15643 case PRAGMA_OACC_CLAUSE_ATTACH:
15644 kind = GOMP_MAP_ATTACH;
15645 break;
15646 case PRAGMA_OACC_CLAUSE_COPY:
15647 kind = GOMP_MAP_TOFROM;
15648 break;
15649 case PRAGMA_OACC_CLAUSE_COPYIN:
15650 kind = GOMP_MAP_TO;
15651 break;
15652 case PRAGMA_OACC_CLAUSE_COPYOUT:
15653 kind = GOMP_MAP_FROM;
15654 break;
15655 case PRAGMA_OACC_CLAUSE_CREATE:
15656 kind = GOMP_MAP_ALLOC;
15657 break;
15658 case PRAGMA_OACC_CLAUSE_DELETE:
15659 kind = GOMP_MAP_RELEASE;
15660 break;
15661 case PRAGMA_OACC_CLAUSE_DETACH:
15662 kind = GOMP_MAP_DETACH;
15663 break;
15664 case PRAGMA_OACC_CLAUSE_DEVICE:
15665 kind = GOMP_MAP_FORCE_TO;
15666 break;
15667 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
15668 kind = GOMP_MAP_DEVICE_RESIDENT;
15669 break;
15670 case PRAGMA_OACC_CLAUSE_LINK:
15671 kind = GOMP_MAP_LINK;
15672 break;
15673 case PRAGMA_OACC_CLAUSE_NO_CREATE:
15674 kind = GOMP_MAP_IF_PRESENT;
15675 break;
15676 case PRAGMA_OACC_CLAUSE_PRESENT:
15677 kind = GOMP_MAP_FORCE_PRESENT;
15678 break;
15679 case PRAGMA_OACC_CLAUSE_SELF:
15680 /* "The 'host' clause is a synonym for the 'self' clause." */
15681 case PRAGMA_OACC_CLAUSE_HOST:
15682 kind = GOMP_MAP_FORCE_FROM;
15683 break;
15684 default:
15685 gcc_unreachable ();
15686 }
15687
15688 tree nl = list;
15689 bool readonly = false;
15690 location_t open_loc = c_parser_peek_token (parser)->location;
15691 matching_parens parens;
15692 if (parens.require_open (parser))
15693 {
15694 /* Turn on readonly modifier parsing for copyin clause. */
15695 if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
15696 {
15697 c_token *token = c_parser_peek_token (parser);
15698 if (token->type == CPP_NAME
15699 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
15700 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
15701 {
15702 c_parser_consume_token (parser);
15703 c_parser_consume_token (parser);
15704 readonly = true;
15705 }
15706 }
15707 nl = c_parser_omp_variable_list (parser, clause_loc: open_loc, kind: OMP_CLAUSE_MAP, list,
15708 map_lvalue: false);
15709 parens.skip_until_found_close (parser);
15710 }
15711
15712 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
15713 {
15714 OMP_CLAUSE_SET_MAP_KIND (c, kind);
15715 if (readonly)
15716 OMP_CLAUSE_MAP_READONLY (c) = 1;
15717 }
15718
15719 return nl;
15720}
15721
15722/* OpenACC 2.0:
15723 deviceptr ( variable-list ) */
15724
15725static tree
15726c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
15727{
15728 location_t loc = c_parser_peek_token (parser)->location;
15729 tree vars, t;
15730
15731 /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
15732 c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
15733 variable-list must only allow for pointer variables. */
15734 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
15735 for (t = vars; t && t; t = TREE_CHAIN (t))
15736 {
15737 tree v = TREE_PURPOSE (t);
15738
15739 /* FIXME diagnostics: Ideally we should keep individual
15740 locations for all the variables in the var list to make the
15741 following errors more precise. Perhaps
15742 c_parser_omp_var_list_parens() should construct a list of
15743 locations to go along with the var list. */
15744
15745 if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
15746 error_at (loc, "%qD is not a variable", v);
15747 else if (TREE_TYPE (v) == error_mark_node)
15748 ;
15749 else if (!POINTER_TYPE_P (TREE_TYPE (v)))
15750 error_at (loc, "%qD is not a pointer variable", v);
15751
15752 tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
15753 OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
15754 OMP_CLAUSE_DECL (u) = v;
15755 OMP_CLAUSE_CHAIN (u) = list;
15756 list = u;
15757 }
15758
15759 return list;
15760}
15761
15762/* OpenACC 2.0, OpenMP 3.0:
15763 collapse ( constant-expression ) */
15764
15765static tree
15766c_parser_omp_clause_collapse (c_parser *parser, tree list)
15767{
15768 tree c, num = error_mark_node;
15769 HOST_WIDE_INT n;
15770 location_t loc;
15771
15772 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
15773 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
15774
15775 loc = c_parser_peek_token (parser)->location;
15776 matching_parens parens;
15777 if (parens.require_open (parser))
15778 {
15779 num = c_parser_expr_no_commas (parser, NULL).value;
15780 parens.skip_until_found_close (parser);
15781 }
15782 if (num == error_mark_node)
15783 return list;
15784 mark_exp_read (num);
15785 num = c_fully_fold (num, false, NULL);
15786 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
15787 || !tree_fits_shwi_p (num)
15788 || (n = tree_to_shwi (num)) <= 0
15789 || (int) n != n)
15790 {
15791 error_at (loc,
15792 "collapse argument needs positive constant integer expression");
15793 return list;
15794 }
15795 c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
15796 OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
15797 OMP_CLAUSE_CHAIN (c) = list;
15798 return c;
15799}
15800
15801/* OpenMP 2.5:
15802 copyin ( variable-list ) */
15803
15804static tree
15805c_parser_omp_clause_copyin (c_parser *parser, tree list)
15806{
15807 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYIN, list);
15808}
15809
15810/* OpenMP 2.5:
15811 copyprivate ( variable-list ) */
15812
15813static tree
15814c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
15815{
15816 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYPRIVATE, list);
15817}
15818
15819/* OpenMP 2.5:
15820 default ( none | shared )
15821
15822 OpenMP 5.1:
15823 default ( private | firstprivate )
15824
15825 OpenACC:
15826 default ( none | present ) */
15827
15828static tree
15829c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
15830{
15831 enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
15832 location_t loc = c_parser_peek_token (parser)->location;
15833 tree c;
15834
15835 matching_parens parens;
15836 if (!parens.require_open (parser))
15837 return list;
15838 if (c_parser_next_token_is (parser, type: CPP_NAME))
15839 {
15840 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
15841
15842 switch (p[0])
15843 {
15844 case 'n':
15845 if (strcmp (s1: "none", s2: p) != 0)
15846 goto invalid_kind;
15847 kind = OMP_CLAUSE_DEFAULT_NONE;
15848 break;
15849
15850 case 'p':
15851 if (is_oacc)
15852 {
15853 if (strcmp (s1: "present", s2: p) != 0)
15854 goto invalid_kind;
15855 kind = OMP_CLAUSE_DEFAULT_PRESENT;
15856 }
15857 else
15858 {
15859 if (strcmp (s1: "private", s2: p) != 0)
15860 goto invalid_kind;
15861 kind = OMP_CLAUSE_DEFAULT_PRIVATE;
15862 }
15863 break;
15864
15865 case 'f':
15866 if (strcmp (s1: "firstprivate", s2: p) != 0 || is_oacc)
15867 goto invalid_kind;
15868 kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
15869 break;
15870
15871 case 's':
15872 if (strcmp (s1: "shared", s2: p) != 0 || is_oacc)
15873 goto invalid_kind;
15874 kind = OMP_CLAUSE_DEFAULT_SHARED;
15875 break;
15876
15877 default:
15878 goto invalid_kind;
15879 }
15880
15881 c_parser_consume_token (parser);
15882 }
15883 else
15884 {
15885 invalid_kind:
15886 if (is_oacc)
15887 c_parser_error (parser, gmsgid: "expected %<none%> or %<present%>");
15888 else
15889 c_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, "
15890 "%<private%> or %<firstprivate%>");
15891 }
15892 parens.skip_until_found_close (parser);
15893
15894 if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
15895 return list;
15896
15897 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default");
15898 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
15899 OMP_CLAUSE_CHAIN (c) = list;
15900 OMP_CLAUSE_DEFAULT_KIND (c) = kind;
15901
15902 return c;
15903}
15904
15905/* OpenMP 2.5:
15906 firstprivate ( variable-list ) */
15907
15908static tree
15909c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
15910{
15911 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, list);
15912}
15913
15914/* OpenMP 3.1:
15915 final ( expression ) */
15916
15917static tree
15918c_parser_omp_clause_final (c_parser *parser, tree list)
15919{
15920 location_t loc = c_parser_peek_token (parser)->location;
15921 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15922 {
15923 matching_parens parens;
15924 tree t, c;
15925 if (!parens.require_open (parser))
15926 t = error_mark_node;
15927 else
15928 {
15929 location_t eloc = c_parser_peek_token (parser)->location;
15930 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15931 t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
15932 t = c_objc_common_truthvalue_conversion (eloc, t);
15933 t = c_fully_fold (t, false, NULL);
15934 parens.skip_until_found_close (parser);
15935 }
15936
15937 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final");
15938
15939 c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
15940 OMP_CLAUSE_FINAL_EXPR (c) = t;
15941 OMP_CLAUSE_CHAIN (c) = list;
15942 list = c;
15943 }
15944 else
15945 c_parser_error (parser, gmsgid: "expected %<(%>");
15946
15947 return list;
15948}
15949
15950/* OpenMP 5.1:
15951 indirect [( expression )]
15952*/
15953
15954static tree
15955c_parser_omp_clause_indirect (c_parser *parser, tree list)
15956{
15957 location_t location = c_parser_peek_token (parser)->location;
15958 tree t;
15959
15960 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
15961 {
15962 matching_parens parens;
15963 if (!parens.require_open (parser))
15964 return list;
15965
15966 location_t loc = c_parser_peek_token (parser)->location;
15967 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15968 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
15969 t = c_objc_common_truthvalue_conversion (loc, expr.value);
15970 t = c_fully_fold (t, false, NULL);
15971 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
15972 || TREE_CODE (t) != INTEGER_CST)
15973 {
15974 c_parser_error (parser, gmsgid: "expected constant logical expression");
15975 return list;
15976 }
15977 parens.skip_until_found_close (parser);
15978 }
15979 else
15980 t = integer_one_node;
15981
15982 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect");
15983
15984 tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
15985 OMP_CLAUSE_INDIRECT_EXPR (c) = t;
15986 OMP_CLAUSE_CHAIN (c) = list;
15987
15988 return c;
15989}
15990
15991/* OpenACC, OpenMP 2.5:
15992 if ( expression )
15993
15994 OpenMP 4.5:
15995 if ( directive-name-modifier : expression )
15996
15997 directive-name-modifier:
15998 parallel | task | taskloop | target data | target | target update
15999 | target enter data | target exit data
16000
16001 OpenMP 5.0:
16002 directive-name-modifier:
16003 ... | simd | cancel */
16004
16005static tree
16006c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
16007{
16008 location_t location = c_parser_peek_token (parser)->location;
16009 enum tree_code if_modifier = ERROR_MARK;
16010
16011 matching_parens parens;
16012 if (!parens.require_open (parser))
16013 return list;
16014
16015 if (is_omp && c_parser_next_token_is (parser, type: CPP_NAME))
16016 {
16017 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16018 int n = 2;
16019 if (strcmp (s1: p, s2: "cancel") == 0)
16020 if_modifier = VOID_CST;
16021 else if (strcmp (s1: p, s2: "parallel") == 0)
16022 if_modifier = OMP_PARALLEL;
16023 else if (strcmp (s1: p, s2: "simd") == 0)
16024 if_modifier = OMP_SIMD;
16025 else if (strcmp (s1: p, s2: "task") == 0)
16026 if_modifier = OMP_TASK;
16027 else if (strcmp (s1: p, s2: "taskloop") == 0)
16028 if_modifier = OMP_TASKLOOP;
16029 else if (strcmp (s1: p, s2: "target") == 0)
16030 {
16031 if_modifier = OMP_TARGET;
16032 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
16033 {
16034 p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
16035 if (strcmp (s1: "data", s2: p) == 0)
16036 if_modifier = OMP_TARGET_DATA;
16037 else if (strcmp (s1: "update", s2: p) == 0)
16038 if_modifier = OMP_TARGET_UPDATE;
16039 else if (strcmp (s1: "enter", s2: p) == 0)
16040 if_modifier = OMP_TARGET_ENTER_DATA;
16041 else if (strcmp (s1: "exit", s2: p) == 0)
16042 if_modifier = OMP_TARGET_EXIT_DATA;
16043 if (if_modifier != OMP_TARGET)
16044 {
16045 n = 3;
16046 c_parser_consume_token (parser);
16047 }
16048 else
16049 {
16050 location_t loc = c_parser_peek_2nd_token (parser)->location;
16051 error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
16052 "or %<exit%>");
16053 if_modifier = ERROR_MARK;
16054 }
16055 if (if_modifier == OMP_TARGET_ENTER_DATA
16056 || if_modifier == OMP_TARGET_EXIT_DATA)
16057 {
16058 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
16059 {
16060 p = IDENTIFIER_POINTER
16061 (c_parser_peek_2nd_token (parser)->value);
16062 if (strcmp (s1: "data", s2: p) == 0)
16063 n = 4;
16064 }
16065 if (n == 4)
16066 c_parser_consume_token (parser);
16067 else
16068 {
16069 location_t loc
16070 = c_parser_peek_2nd_token (parser)->location;
16071 error_at (loc, "expected %<data%>");
16072 if_modifier = ERROR_MARK;
16073 }
16074 }
16075 }
16076 }
16077 if (if_modifier != ERROR_MARK)
16078 {
16079 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16080 {
16081 c_parser_consume_token (parser);
16082 c_parser_consume_token (parser);
16083 }
16084 else
16085 {
16086 if (n > 2)
16087 {
16088 location_t loc = c_parser_peek_2nd_token (parser)->location;
16089 error_at (loc, "expected %<:%>");
16090 }
16091 if_modifier = ERROR_MARK;
16092 }
16093 }
16094 }
16095
16096 location_t loc = c_parser_peek_token (parser)->location;
16097 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16098 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
16099 tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
16100 t = c_fully_fold (t, false, NULL);
16101 parens.skip_until_found_close (parser);
16102
16103 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
16104 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
16105 {
16106 if (if_modifier != ERROR_MARK
16107 && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
16108 {
16109 const char *p = NULL;
16110 switch (if_modifier)
16111 {
16112 case VOID_CST: p = "cancel"; break;
16113 case OMP_PARALLEL: p = "parallel"; break;
16114 case OMP_SIMD: p = "simd"; break;
16115 case OMP_TASK: p = "task"; break;
16116 case OMP_TASKLOOP: p = "taskloop"; break;
16117 case OMP_TARGET_DATA: p = "target data"; break;
16118 case OMP_TARGET: p = "target"; break;
16119 case OMP_TARGET_UPDATE: p = "target update"; break;
16120 case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
16121 case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
16122 default: gcc_unreachable ();
16123 }
16124 error_at (location, "too many %<if%> clauses with %qs modifier",
16125 p);
16126 return list;
16127 }
16128 else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
16129 {
16130 if (!is_omp)
16131 error_at (location, "too many %<if%> clauses");
16132 else
16133 error_at (location, "too many %<if%> clauses without modifier");
16134 return list;
16135 }
16136 else if (if_modifier == ERROR_MARK
16137 || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
16138 {
16139 error_at (location, "if any %<if%> clause has modifier, then all "
16140 "%<if%> clauses have to use modifier");
16141 return list;
16142 }
16143 }
16144
16145 c = build_omp_clause (location, OMP_CLAUSE_IF);
16146 OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
16147 OMP_CLAUSE_IF_EXPR (c) = t;
16148 OMP_CLAUSE_CHAIN (c) = list;
16149 return c;
16150}
16151
16152/* OpenMP 2.5:
16153 lastprivate ( variable-list )
16154
16155 OpenMP 5.0:
16156 lastprivate ( [ lastprivate-modifier : ] variable-list ) */
16157
16158static tree
16159c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
16160{
16161 /* The clauses location. */
16162 location_t loc = c_parser_peek_token (parser)->location;
16163
16164 if (c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
16165 {
16166 bool conditional = false;
16167 if (c_parser_next_token_is (parser, type: CPP_NAME)
16168 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16169 {
16170 const char *p
16171 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16172 if (strcmp (s1: p, s2: "conditional") == 0)
16173 {
16174 conditional = true;
16175 c_parser_consume_token (parser);
16176 c_parser_consume_token (parser);
16177 }
16178 }
16179 tree nlist = c_parser_omp_variable_list (parser, clause_loc: loc,
16180 kind: OMP_CLAUSE_LASTPRIVATE, list);
16181 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
16182 if (conditional)
16183 for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
16184 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
16185 return nlist;
16186 }
16187 return list;
16188}
16189
16190/* OpenMP 3.1:
16191 mergeable */
16192
16193static tree
16194c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
16195{
16196 tree c;
16197
16198 /* FIXME: Should we allow duplicates? */
16199 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable");
16200
16201 c = build_omp_clause (c_parser_peek_token (parser)->location,
16202 OMP_CLAUSE_MERGEABLE);
16203 OMP_CLAUSE_CHAIN (c) = list;
16204
16205 return c;
16206}
16207
16208/* OpenMP 2.5:
16209 nowait */
16210
16211static tree
16212c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
16213{
16214 tree c;
16215 location_t loc = c_parser_peek_token (parser)->location;
16216
16217 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait");
16218
16219 c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
16220 OMP_CLAUSE_CHAIN (c) = list;
16221 return c;
16222}
16223
16224/* OpenMP 2.5:
16225 num_threads ( expression ) */
16226
16227static tree
16228c_parser_omp_clause_num_threads (c_parser *parser, tree list)
16229{
16230 location_t num_threads_loc = c_parser_peek_token (parser)->location;
16231 matching_parens parens;
16232 if (parens.require_open (parser))
16233 {
16234 location_t expr_loc = c_parser_peek_token (parser)->location;
16235 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16236 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16237 tree c, t = expr.value;
16238 t = c_fully_fold (t, false, NULL);
16239
16240 parens.skip_until_found_close (parser);
16241
16242 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16243 {
16244 c_parser_error (parser, gmsgid: "expected integer expression");
16245 return list;
16246 }
16247
16248 /* Attempt to statically determine when the number isn't positive. */
16249 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
16250 build_int_cst (TREE_TYPE (t), 0));
16251 protected_set_expr_location (c, expr_loc);
16252 if (c == boolean_true_node)
16253 {
16254 warning_at (expr_loc, OPT_Wopenmp,
16255 "%<num_threads%> value must be positive");
16256 t = integer_one_node;
16257 }
16258
16259 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, name: "num_threads");
16260
16261 c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
16262 OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
16263 OMP_CLAUSE_CHAIN (c) = list;
16264 list = c;
16265 }
16266
16267 return list;
16268}
16269
16270/* OpenMP 4.5:
16271 num_tasks ( expression )
16272
16273 OpenMP 5.1:
16274 num_tasks ( strict : expression ) */
16275
16276static tree
16277c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
16278{
16279 location_t num_tasks_loc = c_parser_peek_token (parser)->location;
16280 matching_parens parens;
16281 if (parens.require_open (parser))
16282 {
16283 bool strict = false;
16284 if (c_parser_next_token_is (parser, type: CPP_NAME)
16285 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
16286 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
16287 s2: "strict") == 0)
16288 {
16289 strict = true;
16290 c_parser_consume_token (parser);
16291 c_parser_consume_token (parser);
16292 }
16293
16294 location_t expr_loc = c_parser_peek_token (parser)->location;
16295 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16296 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16297 tree c, t = expr.value;
16298 t = c_fully_fold (t, false, NULL);
16299
16300 parens.skip_until_found_close (parser);
16301
16302 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16303 {
16304 c_parser_error (parser, gmsgid: "expected integer expression");
16305 return list;
16306 }
16307
16308 /* Attempt to statically determine when the number isn't positive. */
16309 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
16310 build_int_cst (TREE_TYPE (t), 0));
16311 if (CAN_HAVE_LOCATION_P (c))
16312 SET_EXPR_LOCATION (c, expr_loc);
16313 if (c == boolean_true_node)
16314 {
16315 warning_at (expr_loc, OPT_Wopenmp,
16316 "%<num_tasks%> value must be positive");
16317 t = integer_one_node;
16318 }
16319
16320 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, name: "num_tasks");
16321
16322 c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
16323 OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
16324 OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
16325 OMP_CLAUSE_CHAIN (c) = list;
16326 list = c;
16327 }
16328
16329 return list;
16330}
16331
16332/* OpenMP 4.5:
16333 grainsize ( expression )
16334
16335 OpenMP 5.1:
16336 grainsize ( strict : expression ) */
16337
16338static tree
16339c_parser_omp_clause_grainsize (c_parser *parser, tree list)
16340{
16341 location_t grainsize_loc = c_parser_peek_token (parser)->location;
16342 matching_parens parens;
16343 if (parens.require_open (parser))
16344 {
16345 bool strict = false;
16346 if (c_parser_next_token_is (parser, type: CPP_NAME)
16347 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
16348 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
16349 s2: "strict") == 0)
16350 {
16351 strict = true;
16352 c_parser_consume_token (parser);
16353 c_parser_consume_token (parser);
16354 }
16355
16356 location_t expr_loc = c_parser_peek_token (parser)->location;
16357 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16358 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16359 tree c, t = expr.value;
16360 t = c_fully_fold (t, false, NULL);
16361
16362 parens.skip_until_found_close (parser);
16363
16364 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16365 {
16366 c_parser_error (parser, gmsgid: "expected integer expression");
16367 return list;
16368 }
16369
16370 /* Attempt to statically determine when the number isn't positive. */
16371 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
16372 build_int_cst (TREE_TYPE (t), 0));
16373 if (CAN_HAVE_LOCATION_P (c))
16374 SET_EXPR_LOCATION (c, expr_loc);
16375 if (c == boolean_true_node)
16376 {
16377 warning_at (expr_loc, OPT_Wopenmp,
16378 "%<grainsize%> value must be positive");
16379 t = integer_one_node;
16380 }
16381
16382 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, name: "grainsize");
16383
16384 c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
16385 OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
16386 OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
16387 OMP_CLAUSE_CHAIN (c) = list;
16388 list = c;
16389 }
16390
16391 return list;
16392}
16393
16394/* OpenMP 4.5:
16395 priority ( expression ) */
16396
16397static tree
16398c_parser_omp_clause_priority (c_parser *parser, tree list)
16399{
16400 location_t priority_loc = c_parser_peek_token (parser)->location;
16401 matching_parens parens;
16402 if (parens.require_open (parser))
16403 {
16404 location_t expr_loc = c_parser_peek_token (parser)->location;
16405 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16406 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16407 tree c, t = expr.value;
16408 t = c_fully_fold (t, false, NULL);
16409
16410 parens.skip_until_found_close (parser);
16411
16412 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16413 {
16414 c_parser_error (parser, gmsgid: "expected integer expression");
16415 return list;
16416 }
16417
16418 /* Attempt to statically determine when the number isn't
16419 non-negative. */
16420 c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
16421 build_int_cst (TREE_TYPE (t), 0));
16422 if (CAN_HAVE_LOCATION_P (c))
16423 SET_EXPR_LOCATION (c, expr_loc);
16424 if (c == boolean_true_node)
16425 {
16426 warning_at (expr_loc, OPT_Wopenmp,
16427 "%<priority%> value must be non-negative");
16428 t = integer_one_node;
16429 }
16430
16431 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, name: "priority");
16432
16433 c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
16434 OMP_CLAUSE_PRIORITY_EXPR (c) = t;
16435 OMP_CLAUSE_CHAIN (c) = list;
16436 list = c;
16437 }
16438
16439 return list;
16440}
16441
16442/* OpenMP 4.5:
16443 hint ( expression ) */
16444
16445static tree
16446c_parser_omp_clause_hint (c_parser *parser, tree list)
16447{
16448 location_t hint_loc = c_parser_peek_token (parser)->location;
16449 matching_parens parens;
16450 if (parens.require_open (parser))
16451 {
16452 location_t expr_loc = c_parser_peek_token (parser)->location;
16453 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16454 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16455 tree c, t = expr.value;
16456 t = c_fully_fold (t, false, NULL);
16457 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
16458 || TREE_CODE (t) != INTEGER_CST
16459 || tree_int_cst_sgn (t) == -1)
16460 {
16461 c_parser_error (parser, gmsgid: "expected constant integer expression "
16462 "with valid sync-hint value");
16463 return list;
16464 }
16465 parens.skip_until_found_close (parser);
16466 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint");
16467
16468 c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
16469 OMP_CLAUSE_HINT_EXPR (c) = t;
16470 OMP_CLAUSE_CHAIN (c) = list;
16471 list = c;
16472 }
16473
16474 return list;
16475}
16476
16477/* OpenMP 5.1:
16478 filter ( integer-expression ) */
16479
16480static tree
16481c_parser_omp_clause_filter (c_parser *parser, tree list)
16482{
16483 location_t hint_loc = c_parser_peek_token (parser)->location;
16484 matching_parens parens;
16485 if (parens.require_open (parser))
16486 {
16487 location_t expr_loc = c_parser_peek_token (parser)->location;
16488 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16489 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16490 tree c, t = expr.value;
16491 t = c_fully_fold (t, false, NULL);
16492 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16493 {
16494 c_parser_error (parser, gmsgid: "expected integer expression");
16495 return list;
16496 }
16497 parens.skip_until_found_close (parser);
16498 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter");
16499
16500 c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
16501 OMP_CLAUSE_FILTER_EXPR (c) = t;
16502 OMP_CLAUSE_CHAIN (c) = list;
16503 list = c;
16504 }
16505
16506 return list;
16507}
16508
16509/* OpenMP 4.5:
16510 defaultmap ( tofrom : scalar )
16511
16512 OpenMP 5.0:
16513 defaultmap ( implicit-behavior [ : variable-category ] ) */
16514
16515static tree
16516c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
16517{
16518 location_t loc = c_parser_peek_token (parser)->location;
16519 tree c;
16520 const char *p;
16521 enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
16522 enum omp_clause_defaultmap_kind category
16523 = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
16524
16525 matching_parens parens;
16526 if (!parens.require_open (parser))
16527 return list;
16528 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
16529 p = "default";
16530 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
16531 {
16532 invalid_behavior:
16533 c_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, "
16534 "%<tofrom%>, %<firstprivate%>, %<none%> "
16535 "or %<default%>");
16536 goto out_err;
16537 }
16538 else
16539 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16540
16541 switch (p[0])
16542 {
16543 case 'a':
16544 if (strcmp (s1: "alloc", s2: p) == 0)
16545 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
16546 else
16547 goto invalid_behavior;
16548 break;
16549
16550 case 'd':
16551 if (strcmp (s1: "default", s2: p) == 0)
16552 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
16553 else
16554 goto invalid_behavior;
16555 break;
16556
16557 case 'f':
16558 if (strcmp (s1: "firstprivate", s2: p) == 0)
16559 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
16560 else if (strcmp (s1: "from", s2: p) == 0)
16561 behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
16562 else
16563 goto invalid_behavior;
16564 break;
16565
16566 case 'n':
16567 if (strcmp (s1: "none", s2: p) == 0)
16568 behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
16569 else
16570 goto invalid_behavior;
16571 break;
16572
16573 case 'p':
16574 if (strcmp (s1: "present", s2: p) == 0)
16575 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
16576 else
16577 goto invalid_behavior;
16578 break;
16579
16580 case 't':
16581 if (strcmp (s1: "tofrom", s2: p) == 0)
16582 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
16583 else if (strcmp (s1: "to", s2: p) == 0)
16584 behavior = OMP_CLAUSE_DEFAULTMAP_TO;
16585 else
16586 goto invalid_behavior;
16587 break;
16588
16589 default:
16590 goto invalid_behavior;
16591 }
16592 c_parser_consume_token (parser);
16593
16594 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
16595 {
16596 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
16597 goto out_err;
16598 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16599 {
16600 invalid_category:
16601 c_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, "
16602 "%<pointer%> or %<all%>");
16603 goto out_err;
16604 }
16605 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16606 switch (p[0])
16607 {
16608 case 'a':
16609 if (strcmp (s1: "aggregate", s2: p) == 0)
16610 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
16611 else if (strcmp (s1: "all", s2: p) == 0)
16612 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
16613 else
16614 goto invalid_category;
16615 break;
16616
16617 case 'p':
16618 if (strcmp (s1: "pointer", s2: p) == 0)
16619 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
16620 else
16621 goto invalid_category;
16622 break;
16623
16624 case 's':
16625 if (strcmp (s1: "scalar", s2: p) == 0)
16626 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
16627 else
16628 goto invalid_category;
16629 break;
16630
16631 default:
16632 goto invalid_category;
16633 }
16634
16635 c_parser_consume_token (parser);
16636 }
16637 parens.skip_until_found_close (parser);
16638
16639 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
16640 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
16641 && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
16642 || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
16643 || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
16644 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16645 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
16646 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16647 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
16648 {
16649 enum omp_clause_defaultmap_kind cat = category;
16650 location_t loc = OMP_CLAUSE_LOCATION (c);
16651 if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
16652 || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
16653 && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16654 != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
16655 cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
16656 p = NULL;
16657 switch (cat)
16658 {
16659 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
16660 p = NULL;
16661 break;
16662 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
16663 p = "all";
16664 break;
16665 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
16666 p = "aggregate";
16667 break;
16668 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
16669 p = "pointer";
16670 break;
16671 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
16672 p = "scalar";
16673 break;
16674 default:
16675 gcc_unreachable ();
16676 }
16677 if (p)
16678 error_at (loc, "too many %<defaultmap%> clauses with %qs category",
16679 p);
16680 else
16681 error_at (loc, "too many %<defaultmap%> clauses with unspecified "
16682 "category");
16683 break;
16684 }
16685
16686 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
16687 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
16688 OMP_CLAUSE_CHAIN (c) = list;
16689 return c;
16690
16691 out_err:
16692 parens.skip_until_found_close (parser);
16693 return list;
16694}
16695
16696/* OpenACC 2.0:
16697 use_device ( variable-list )
16698
16699 OpenMP 4.5:
16700 use_device_ptr ( variable-list ) */
16701
16702static tree
16703c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
16704{
16705 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR,
16706 list);
16707}
16708
16709/* OpenMP 5.0:
16710 use_device_addr ( variable-list ) */
16711
16712static tree
16713c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
16714{
16715 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR,
16716 list);
16717}
16718
16719/* OpenMP 5.1:
16720 has_device_addr ( variable-list ) */
16721
16722static tree
16723c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
16724{
16725 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR,
16726 list);
16727}
16728
16729/* OpenMP 4.5:
16730 is_device_ptr ( variable-list ) */
16731
16732static tree
16733c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
16734{
16735 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, list);
16736}
16737
16738/* OpenACC:
16739 num_gangs ( expression )
16740 num_workers ( expression )
16741 vector_length ( expression ) */
16742
16743static tree
16744c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
16745 tree list)
16746{
16747 location_t loc = c_parser_peek_token (parser)->location;
16748
16749 matching_parens parens;
16750 if (!parens.require_open (parser))
16751 return list;
16752
16753 location_t expr_loc = c_parser_peek_token (parser)->location;
16754 c_expr expr = c_parser_expression (parser);
16755 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16756 tree c, t = expr.value;
16757 t = c_fully_fold (t, false, NULL);
16758
16759 parens.skip_until_found_close (parser);
16760
16761 if (t == error_mark_node)
16762 return list;
16763 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16764 {
16765 error_at (expr_loc, "%qs expression must be integral",
16766 omp_clause_code_name[code]);
16767 return list;
16768 }
16769
16770 /* Attempt to statically determine when the number isn't positive. */
16771 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
16772 build_int_cst (TREE_TYPE (t), 0));
16773 protected_set_expr_location (c, expr_loc);
16774 if (c == boolean_true_node)
16775 {
16776 warning_at (expr_loc, 0,
16777 "%qs value must be positive",
16778 omp_clause_code_name[code]);
16779 t = integer_one_node;
16780 }
16781
16782 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
16783
16784 c = build_omp_clause (loc, code);
16785 OMP_CLAUSE_OPERAND (c, 0) = t;
16786 OMP_CLAUSE_CHAIN (c) = list;
16787 return c;
16788}
16789
16790/* OpenACC:
16791
16792 gang [( gang-arg-list )]
16793 worker [( [num:] int-expr )]
16794 vector [( [length:] int-expr )]
16795
16796 where gang-arg is one of:
16797
16798 [num:] int-expr
16799 static: size-expr
16800
16801 and size-expr may be:
16802
16803 *
16804 int-expr
16805*/
16806
16807static tree
16808c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
16809 omp_clause_code kind,
16810 const char *str, tree list)
16811{
16812 const char *id = "num";
16813 tree ops[2] = { NULL_TREE, NULL_TREE }, c;
16814
16815 if (kind == OMP_CLAUSE_VECTOR)
16816 id = "length";
16817
16818 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
16819 {
16820 c_parser_consume_token (parser);
16821
16822 do
16823 {
16824 c_token *next = c_parser_peek_token (parser);
16825 int idx = 0;
16826
16827 /* Gang static argument. */
16828 if (kind == OMP_CLAUSE_GANG
16829 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
16830 {
16831 c_parser_consume_token (parser);
16832
16833 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
16834 goto cleanup_error;
16835
16836 idx = 1;
16837 if (ops[idx] != NULL_TREE)
16838 {
16839 c_parser_error (parser, gmsgid: "too many %<static%> arguments");
16840 goto cleanup_error;
16841 }
16842
16843 /* Check for the '*' argument. */
16844 if (c_parser_next_token_is (parser, type: CPP_MULT)
16845 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16846 || c_parser_peek_2nd_token (parser)->type
16847 == CPP_CLOSE_PAREN))
16848 {
16849 c_parser_consume_token (parser);
16850 ops[idx] = integer_minus_one_node;
16851
16852 if (c_parser_next_token_is (parser, type: CPP_COMMA))
16853 {
16854 c_parser_consume_token (parser);
16855 continue;
16856 }
16857 else
16858 break;
16859 }
16860 }
16861 /* Worker num: argument and vector length: arguments. */
16862 else if (c_parser_next_token_is (parser, type: CPP_NAME)
16863 && strcmp (s1: id, IDENTIFIER_POINTER (next->value)) == 0
16864 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16865 {
16866 c_parser_consume_token (parser); /* id */
16867 c_parser_consume_token (parser); /* ':' */
16868 }
16869
16870 /* Now collect the actual argument. */
16871 if (ops[idx] != NULL_TREE)
16872 {
16873 c_parser_error (parser, gmsgid: "unexpected argument");
16874 goto cleanup_error;
16875 }
16876
16877 location_t expr_loc = c_parser_peek_token (parser)->location;
16878 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
16879 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
16880 tree expr = cexpr.value;
16881 if (expr == error_mark_node)
16882 goto cleanup_error;
16883
16884 expr = c_fully_fold (expr, false, NULL);
16885
16886 /* Attempt to statically determine when the number isn't a
16887 positive integer. */
16888
16889 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
16890 {
16891 c_parser_error (parser, gmsgid: "expected integer expression");
16892 return list;
16893 }
16894
16895 tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
16896 build_int_cst (TREE_TYPE (expr), 0));
16897 if (c == boolean_true_node)
16898 {
16899 warning_at (loc, 0,
16900 "%qs value must be positive", str);
16901 expr = integer_one_node;
16902 }
16903
16904 ops[idx] = expr;
16905
16906 if (kind == OMP_CLAUSE_GANG
16907 && c_parser_next_token_is (parser, type: CPP_COMMA))
16908 {
16909 c_parser_consume_token (parser);
16910 continue;
16911 }
16912 break;
16913 }
16914 while (1);
16915
16916 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
16917 goto cleanup_error;
16918 }
16919
16920 check_no_duplicate_clause (clauses: list, code: kind, name: str);
16921
16922 c = build_omp_clause (loc, kind);
16923
16924 if (ops[1])
16925 OMP_CLAUSE_OPERAND (c, 1) = ops[1];
16926
16927 OMP_CLAUSE_OPERAND (c, 0) = ops[0];
16928 OMP_CLAUSE_CHAIN (c) = list;
16929
16930 return c;
16931
16932 cleanup_error:
16933 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
16934 return list;
16935}
16936
16937/* OpenACC 2.5:
16938 auto
16939 finalize
16940 independent
16941 nohost
16942 seq */
16943
16944static tree
16945c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
16946 tree list)
16947{
16948 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
16949
16950 tree c = build_omp_clause (loc, code);
16951 OMP_CLAUSE_CHAIN (c) = list;
16952
16953 return c;
16954}
16955
16956/* OpenACC:
16957 async [( int-expr )] */
16958
16959static tree
16960c_parser_oacc_clause_async (c_parser *parser, tree list)
16961{
16962 tree c, t;
16963 location_t loc = c_parser_peek_token (parser)->location;
16964
16965 t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
16966
16967 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
16968 {
16969 c_parser_consume_token (parser);
16970
16971 t = c_parser_expr_no_commas (parser, NULL).value;
16972 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16973 c_parser_error (parser, gmsgid: "expected integer expression");
16974 else if (t == error_mark_node
16975 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
16976 return list;
16977 }
16978 else
16979 t = c_fully_fold (t, false, NULL);
16980
16981 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async");
16982
16983 c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
16984 OMP_CLAUSE_ASYNC_EXPR (c) = t;
16985 OMP_CLAUSE_CHAIN (c) = list;
16986 list = c;
16987
16988 return list;
16989}
16990
16991/* OpenACC 2.0:
16992 tile ( size-expr-list ) */
16993
16994static tree
16995c_parser_oacc_clause_tile (c_parser *parser, tree list)
16996{
16997 tree c, expr = error_mark_node;
16998 location_t loc;
16999 tree tile = NULL_TREE;
17000
17001 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
17002 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
17003
17004 loc = c_parser_peek_token (parser)->location;
17005 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
17006 return list;
17007
17008 do
17009 {
17010 if (tile && !c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
17011 return list;
17012
17013 if (c_parser_next_token_is (parser, type: CPP_MULT)
17014 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
17015 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
17016 {
17017 c_parser_consume_token (parser);
17018 expr = integer_zero_node;
17019 }
17020 else
17021 {
17022 location_t expr_loc = c_parser_peek_token (parser)->location;
17023 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
17024 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
17025 expr = cexpr.value;
17026
17027 if (expr == error_mark_node)
17028 {
17029 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
17030 msgid: "expected %<)%>");
17031 return list;
17032 }
17033
17034 expr = c_fully_fold (expr, false, NULL);
17035
17036 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
17037 || !tree_fits_shwi_p (expr)
17038 || tree_to_shwi (expr) <= 0)
17039 {
17040 error_at (expr_loc, "%<tile%> argument needs positive"
17041 " integral constant");
17042 expr = integer_zero_node;
17043 }
17044 }
17045
17046 tile = tree_cons (NULL_TREE, expr, tile);
17047 }
17048 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN));
17049
17050 /* Consume the trailing ')'. */
17051 c_parser_consume_token (parser);
17052
17053 c = build_omp_clause (loc, OMP_CLAUSE_TILE);
17054 tile = nreverse (tile);
17055 OMP_CLAUSE_TILE_LIST (c) = tile;
17056 OMP_CLAUSE_CHAIN (c) = list;
17057 return c;
17058}
17059
17060/* OpenACC:
17061 wait [( int-expr-list )] */
17062
17063static tree
17064c_parser_oacc_clause_wait (c_parser *parser, tree list)
17065{
17066 location_t clause_loc = c_parser_peek_token (parser)->location;
17067
17068 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17069 list = c_parser_oacc_wait_list (parser, clause_loc, list);
17070 else
17071 {
17072 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
17073
17074 OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
17075 OMP_CLAUSE_CHAIN (c) = list;
17076 list = c;
17077 }
17078
17079 return list;
17080}
17081
17082/* OpenACC 2.7:
17083 self [( expression )] */
17084
17085static tree
17086c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
17087{
17088 tree t;
17089 location_t location = c_parser_peek_token (parser)->location;
17090 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17091 {
17092 matching_parens parens;
17093 parens.consume_open (parser);
17094
17095 location_t loc = c_parser_peek_token (parser)->location;
17096 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17097 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17098 t = c_objc_common_truthvalue_conversion (loc, expr.value);
17099 t = c_fully_fold (t, false, NULL);
17100 parens.skip_until_found_close (parser);
17101 }
17102 else
17103 t = truthvalue_true_node;
17104
17105 for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
17106 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
17107 {
17108 error_at (location, "too many %<self%> clauses");
17109 return list;
17110 }
17111
17112 tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
17113 OMP_CLAUSE_SELF_EXPR (c) = t;
17114 OMP_CLAUSE_CHAIN (c) = list;
17115 return c;
17116}
17117
17118/* OpenMP 5.0:
17119 order ( concurrent )
17120
17121 OpenMP 5.1:
17122 order ( order-modifier : concurrent )
17123
17124 order-modifier:
17125 reproducible
17126 unconstrained */
17127
17128static tree
17129c_parser_omp_clause_order (c_parser *parser, tree list)
17130{
17131 location_t loc = c_parser_peek_token (parser)->location;
17132 tree c;
17133 const char *p;
17134 bool unconstrained = false;
17135 bool reproducible = false;
17136
17137 matching_parens parens;
17138 if (!parens.require_open (parser))
17139 return list;
17140 if (c_parser_next_token_is (parser, type: CPP_NAME)
17141 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17142 {
17143 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17144 if (strcmp (s1: p, s2: "unconstrained") == 0)
17145 unconstrained = true;
17146 else if (strcmp (s1: p, s2: "reproducible") == 0)
17147 reproducible = true;
17148 else
17149 {
17150 c_parser_error (parser, gmsgid: "expected %<reproducible%> or "
17151 "%<unconstrained%>");
17152 goto out_err;
17153 }
17154 c_parser_consume_token (parser);
17155 c_parser_consume_token (parser);
17156 }
17157 if (!c_parser_next_token_is (parser, type: CPP_NAME))
17158 {
17159 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
17160 goto out_err;
17161 }
17162 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17163 if (strcmp (s1: p, s2: "concurrent") != 0)
17164 {
17165 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
17166 goto out_err;
17167 }
17168 c_parser_consume_token (parser);
17169 parens.skip_until_found_close (parser);
17170 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order");
17171 c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
17172 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
17173 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
17174 OMP_CLAUSE_CHAIN (c) = list;
17175 return c;
17176
17177 out_err:
17178 parens.skip_until_found_close (parser);
17179 return list;
17180}
17181
17182
17183/* OpenMP 5.0:
17184 bind ( teams | parallel | thread ) */
17185
17186static tree
17187c_parser_omp_clause_bind (c_parser *parser, tree list)
17188{
17189 location_t loc = c_parser_peek_token (parser)->location;
17190 tree c;
17191 const char *p;
17192 enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
17193
17194 matching_parens parens;
17195 if (!parens.require_open (parser))
17196 return list;
17197 if (!c_parser_next_token_is (parser, type: CPP_NAME))
17198 {
17199 invalid:
17200 c_parser_error (parser,
17201 gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>");
17202 parens.skip_until_found_close (parser);
17203 return list;
17204 }
17205 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17206 if (strcmp (s1: p, s2: "teams") == 0)
17207 kind = OMP_CLAUSE_BIND_TEAMS;
17208 else if (strcmp (s1: p, s2: "parallel") == 0)
17209 kind = OMP_CLAUSE_BIND_PARALLEL;
17210 else if (strcmp (s1: p, s2: "thread") != 0)
17211 goto invalid;
17212 c_parser_consume_token (parser);
17213 parens.skip_until_found_close (parser);
17214 /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
17215 c = build_omp_clause (loc, OMP_CLAUSE_BIND);
17216 OMP_CLAUSE_BIND_KIND (c) = kind;
17217 OMP_CLAUSE_CHAIN (c) = list;
17218 return c;
17219}
17220
17221
17222/* OpenMP 2.5:
17223 ordered
17224
17225 OpenMP 4.5:
17226 ordered ( constant-expression ) */
17227
17228static tree
17229c_parser_omp_clause_ordered (c_parser *parser, tree list)
17230{
17231 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, name: "ordered");
17232
17233 tree c, num = NULL_TREE;
17234 HOST_WIDE_INT n;
17235 location_t loc = c_parser_peek_token (parser)->location;
17236 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
17237 {
17238 matching_parens parens;
17239 parens.consume_open (parser);
17240 num = c_parser_expr_no_commas (parser, NULL).value;
17241 parens.skip_until_found_close (parser);
17242 }
17243 if (num == error_mark_node)
17244 return list;
17245 if (num)
17246 {
17247 mark_exp_read (num);
17248 num = c_fully_fold (num, false, NULL);
17249 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17250 || !tree_fits_shwi_p (num)
17251 || (n = tree_to_shwi (num)) <= 0
17252 || (int) n != n)
17253 {
17254 error_at (loc, "ordered argument needs positive "
17255 "constant integer expression");
17256 return list;
17257 }
17258 }
17259 c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
17260 OMP_CLAUSE_ORDERED_EXPR (c) = num;
17261 OMP_CLAUSE_CHAIN (c) = list;
17262 return c;
17263}
17264
17265/* OpenMP 2.5:
17266 private ( variable-list ) */
17267
17268static tree
17269c_parser_omp_clause_private (c_parser *parser, tree list)
17270{
17271 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_PRIVATE, list);
17272}
17273
17274/* OpenMP 2.5:
17275 reduction ( reduction-operator : variable-list )
17276
17277 reduction-operator:
17278 One of: + * - & ^ | && ||
17279
17280 OpenMP 3.1:
17281
17282 reduction-operator:
17283 One of: + * - & ^ | && || max min
17284
17285 OpenMP 4.0:
17286
17287 reduction-operator:
17288 One of: + * - & ^ | && ||
17289 identifier
17290
17291 OpenMP 5.0:
17292 reduction ( reduction-modifier, reduction-operator : variable-list )
17293 in_reduction ( reduction-operator : variable-list )
17294 task_reduction ( reduction-operator : variable-list ) */
17295
17296static tree
17297c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
17298 bool is_omp, tree list)
17299{
17300 location_t clause_loc = c_parser_peek_token (parser)->location;
17301 matching_parens parens;
17302 if (parens.require_open (parser))
17303 {
17304 bool task = false;
17305 bool inscan = false;
17306 enum tree_code code = ERROR_MARK;
17307 tree reduc_id = NULL_TREE;
17308
17309 if (kind == OMP_CLAUSE_REDUCTION && is_omp)
17310 {
17311 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
17312 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
17313 {
17314 c_parser_consume_token (parser);
17315 c_parser_consume_token (parser);
17316 }
17317 else if (c_parser_next_token_is (parser, type: CPP_NAME)
17318 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
17319 {
17320 const char *p
17321 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17322 if (strcmp (s1: p, s2: "task") == 0)
17323 task = true;
17324 else if (strcmp (s1: p, s2: "inscan") == 0)
17325 inscan = true;
17326 if (task || inscan)
17327 {
17328 c_parser_consume_token (parser);
17329 c_parser_consume_token (parser);
17330 }
17331 }
17332 }
17333
17334 switch (c_parser_peek_token (parser)->type)
17335 {
17336 case CPP_PLUS:
17337 code = PLUS_EXPR;
17338 break;
17339 case CPP_MULT:
17340 code = MULT_EXPR;
17341 break;
17342 case CPP_MINUS:
17343 code = MINUS_EXPR;
17344 break;
17345 case CPP_AND:
17346 code = BIT_AND_EXPR;
17347 break;
17348 case CPP_XOR:
17349 code = BIT_XOR_EXPR;
17350 break;
17351 case CPP_OR:
17352 code = BIT_IOR_EXPR;
17353 break;
17354 case CPP_AND_AND:
17355 code = TRUTH_ANDIF_EXPR;
17356 break;
17357 case CPP_OR_OR:
17358 code = TRUTH_ORIF_EXPR;
17359 break;
17360 case CPP_NAME:
17361 {
17362 const char *p
17363 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17364 if (strcmp (s1: p, s2: "min") == 0)
17365 {
17366 code = MIN_EXPR;
17367 break;
17368 }
17369 if (strcmp (s1: p, s2: "max") == 0)
17370 {
17371 code = MAX_EXPR;
17372 break;
17373 }
17374 reduc_id = c_parser_peek_token (parser)->value;
17375 break;
17376 }
17377 default:
17378 c_parser_error (parser,
17379 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
17380 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
17381 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
17382 return list;
17383 }
17384 c_parser_consume_token (parser);
17385 reduc_id = c_omp_reduction_id (code, reduc_id);
17386 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
17387 {
17388 tree nl, c;
17389
17390 nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
17391 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17392 {
17393 tree d = OMP_CLAUSE_DECL (c), type;
17394 if (TREE_CODE (d) != OMP_ARRAY_SECTION)
17395 type = TREE_TYPE (d);
17396 else
17397 {
17398 int cnt = 0;
17399 tree t;
17400 for (t = d;
17401 TREE_CODE (t) == OMP_ARRAY_SECTION;
17402 t = TREE_OPERAND (t, 0))
17403 cnt++;
17404 type = TREE_TYPE (t);
17405 while (cnt > 0)
17406 {
17407 if (TREE_CODE (type) != POINTER_TYPE
17408 && TREE_CODE (type) != ARRAY_TYPE)
17409 break;
17410 type = TREE_TYPE (type);
17411 cnt--;
17412 }
17413 }
17414 while (TREE_CODE (type) == ARRAY_TYPE)
17415 type = TREE_TYPE (type);
17416 OMP_CLAUSE_REDUCTION_CODE (c) = code;
17417 if (task)
17418 OMP_CLAUSE_REDUCTION_TASK (c) = 1;
17419 else if (inscan)
17420 OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
17421 if (code == ERROR_MARK
17422 || !(INTEGRAL_TYPE_P (type)
17423 || SCALAR_FLOAT_TYPE_P (type)
17424 || TREE_CODE (type) == COMPLEX_TYPE))
17425 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
17426 = c_omp_reduction_lookup (reduc_id,
17427 TYPE_MAIN_VARIANT (type));
17428 }
17429
17430 list = nl;
17431 }
17432 parens.skip_until_found_close (parser);
17433 }
17434 return list;
17435}
17436
17437/* OpenMP 2.5:
17438 schedule ( schedule-kind )
17439 schedule ( schedule-kind , expression )
17440
17441 schedule-kind:
17442 static | dynamic | guided | runtime | auto
17443
17444 OpenMP 4.5:
17445 schedule ( schedule-modifier : schedule-kind )
17446 schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
17447
17448 schedule-modifier:
17449 simd
17450 monotonic
17451 nonmonotonic */
17452
17453static tree
17454c_parser_omp_clause_schedule (c_parser *parser, tree list)
17455{
17456 tree c, t;
17457 location_t loc = c_parser_peek_token (parser)->location;
17458 int modifiers = 0, nmodifiers = 0;
17459
17460 matching_parens parens;
17461 if (!parens.require_open (parser))
17462 return list;
17463
17464 c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
17465
17466 location_t comma = UNKNOWN_LOCATION;
17467 while (c_parser_next_token_is (parser, type: CPP_NAME))
17468 {
17469 tree kind = c_parser_peek_token (parser)->value;
17470 const char *p = IDENTIFIER_POINTER (kind);
17471 if (strcmp (s1: "simd", s2: p) == 0)
17472 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
17473 else if (strcmp (s1: "monotonic", s2: p) == 0)
17474 modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
17475 else if (strcmp (s1: "nonmonotonic", s2: p) == 0)
17476 modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
17477 else
17478 break;
17479 comma = UNKNOWN_LOCATION;
17480 c_parser_consume_token (parser);
17481 if (nmodifiers++ == 0
17482 && c_parser_next_token_is (parser, type: CPP_COMMA))
17483 {
17484 comma = c_parser_peek_token (parser)->location;
17485 c_parser_consume_token (parser);
17486 }
17487 else
17488 {
17489 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
17490 break;
17491 }
17492 }
17493 if (comma != UNKNOWN_LOCATION)
17494 error_at (comma, "expected %<:%>");
17495
17496 if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
17497 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
17498 == (OMP_CLAUSE_SCHEDULE_MONOTONIC
17499 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
17500 {
17501 error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
17502 "specified");
17503 modifiers = 0;
17504 }
17505
17506 if (c_parser_next_token_is (parser, type: CPP_NAME))
17507 {
17508 tree kind = c_parser_peek_token (parser)->value;
17509 const char *p = IDENTIFIER_POINTER (kind);
17510
17511 switch (p[0])
17512 {
17513 case 'd':
17514 if (strcmp (s1: "dynamic", s2: p) != 0)
17515 goto invalid_kind;
17516 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
17517 break;
17518
17519 case 'g':
17520 if (strcmp (s1: "guided", s2: p) != 0)
17521 goto invalid_kind;
17522 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
17523 break;
17524
17525 case 'r':
17526 if (strcmp (s1: "runtime", s2: p) != 0)
17527 goto invalid_kind;
17528 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
17529 break;
17530
17531 default:
17532 goto invalid_kind;
17533 }
17534 }
17535 else if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
17536 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
17537 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
17538 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
17539 else
17540 goto invalid_kind;
17541
17542 c_parser_consume_token (parser);
17543 if (c_parser_next_token_is (parser, type: CPP_COMMA))
17544 {
17545 location_t here;
17546 c_parser_consume_token (parser);
17547
17548 here = c_parser_peek_token (parser)->location;
17549 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17550 expr = convert_lvalue_to_rvalue (here, expr, false, true);
17551 t = expr.value;
17552 t = c_fully_fold (t, false, NULL);
17553
17554 if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
17555 error_at (here, "schedule %<runtime%> does not take "
17556 "a %<chunk_size%> parameter");
17557 else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
17558 error_at (here,
17559 "schedule %<auto%> does not take "
17560 "a %<chunk_size%> parameter");
17561 else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
17562 || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
17563 {
17564 /* Attempt to statically determine when the number isn't
17565 positive. */
17566 tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
17567 build_int_cst (TREE_TYPE (t), 0));
17568 protected_set_expr_location (s, loc);
17569 if (s == boolean_true_node)
17570 {
17571 warning_at (loc, OPT_Wopenmp,
17572 "chunk size value must be positive");
17573 t = integer_one_node;
17574 }
17575 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
17576 }
17577 else
17578 c_parser_error (parser, gmsgid: "expected integer expression");
17579
17580 parens.skip_until_found_close (parser);
17581 }
17582 else
17583 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
17584 msgid: "expected %<,%> or %<)%>");
17585
17586 OMP_CLAUSE_SCHEDULE_KIND (c)
17587 = (enum omp_clause_schedule_kind)
17588 (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
17589
17590 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule");
17591 OMP_CLAUSE_CHAIN (c) = list;
17592 return c;
17593
17594 invalid_kind:
17595 c_parser_error (parser, gmsgid: "invalid schedule kind");
17596 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
17597 return list;
17598}
17599
17600/* OpenMP 2.5:
17601 shared ( variable-list ) */
17602
17603static tree
17604c_parser_omp_clause_shared (c_parser *parser, tree list)
17605{
17606 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_SHARED, list);
17607}
17608
17609/* OpenMP 3.0:
17610 untied */
17611
17612static tree
17613c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17614{
17615 tree c;
17616
17617 /* FIXME: Should we allow duplicates? */
17618 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied");
17619
17620 c = build_omp_clause (c_parser_peek_token (parser)->location,
17621 OMP_CLAUSE_UNTIED);
17622 OMP_CLAUSE_CHAIN (c) = list;
17623
17624 return c;
17625}
17626
17627/* OpenMP 4.0:
17628 inbranch
17629 notinbranch */
17630
17631static tree
17632c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
17633 enum omp_clause_code code, tree list)
17634{
17635 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
17636
17637 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17638 OMP_CLAUSE_CHAIN (c) = list;
17639
17640 return c;
17641}
17642
17643/* OpenMP 4.0:
17644 parallel
17645 for
17646 sections
17647 taskgroup */
17648
17649static tree
17650c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
17651 enum omp_clause_code code, tree list)
17652{
17653 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17654 OMP_CLAUSE_CHAIN (c) = list;
17655
17656 return c;
17657}
17658
17659/* OpenMP 4.5:
17660 nogroup */
17661
17662static tree
17663c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17664{
17665 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup");
17666 tree c = build_omp_clause (c_parser_peek_token (parser)->location,
17667 OMP_CLAUSE_NOGROUP);
17668 OMP_CLAUSE_CHAIN (c) = list;
17669 return c;
17670}
17671
17672/* OpenMP 4.5:
17673 simd
17674 threads */
17675
17676static tree
17677c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
17678 enum omp_clause_code code, tree list)
17679{
17680 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
17681 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17682 OMP_CLAUSE_CHAIN (c) = list;
17683 return c;
17684}
17685
17686/* OpenMP 4.0:
17687 num_teams ( expression )
17688
17689 OpenMP 5.1:
17690 num_teams ( expression : expression ) */
17691
17692static tree
17693c_parser_omp_clause_num_teams (c_parser *parser, tree list)
17694{
17695 location_t num_teams_loc = c_parser_peek_token (parser)->location;
17696 matching_parens parens;
17697 if (parens.require_open (parser))
17698 {
17699 location_t upper_loc = c_parser_peek_token (parser)->location;
17700 location_t lower_loc = UNKNOWN_LOCATION;
17701 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17702 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
17703 tree c, upper = expr.value, lower = NULL_TREE;
17704 upper = c_fully_fold (upper, false, NULL);
17705
17706 if (c_parser_next_token_is (parser, type: CPP_COLON))
17707 {
17708 c_parser_consume_token (parser);
17709 lower_loc = upper_loc;
17710 lower = upper;
17711 upper_loc = c_parser_peek_token (parser)->location;
17712 expr = c_parser_expr_no_commas (parser, NULL);
17713 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
17714 upper = expr.value;
17715 upper = c_fully_fold (upper, false, NULL);
17716 }
17717
17718 parens.skip_until_found_close (parser);
17719
17720 if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
17721 || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
17722 {
17723 c_parser_error (parser, gmsgid: "expected integer expression");
17724 return list;
17725 }
17726
17727 /* Attempt to statically determine when the number isn't positive. */
17728 c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
17729 build_int_cst (TREE_TYPE (upper), 0));
17730 protected_set_expr_location (c, upper_loc);
17731 if (c == boolean_true_node)
17732 {
17733 warning_at (upper_loc, OPT_Wopenmp,
17734 "%<num_teams%> value must be positive");
17735 upper = integer_one_node;
17736 }
17737 if (lower)
17738 {
17739 c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
17740 build_int_cst (TREE_TYPE (lower), 0));
17741 protected_set_expr_location (c, lower_loc);
17742 if (c == boolean_true_node)
17743 {
17744 warning_at (lower_loc, OPT_Wopenmp,
17745 "%<num_teams%> value must be positive");
17746 lower = NULL_TREE;
17747 }
17748 else if (TREE_CODE (lower) == INTEGER_CST
17749 && TREE_CODE (upper) == INTEGER_CST
17750 && tree_int_cst_lt (t1: upper, t2: lower))
17751 {
17752 warning_at (lower_loc, OPT_Wopenmp,
17753 "%<num_teams%> lower bound %qE bigger than upper "
17754 "bound %qE", lower, upper);
17755 lower = NULL_TREE;
17756 }
17757 }
17758
17759 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, name: "num_teams");
17760
17761 c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
17762 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
17763 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
17764 OMP_CLAUSE_CHAIN (c) = list;
17765 list = c;
17766 }
17767
17768 return list;
17769}
17770
17771/* OpenMP 4.0:
17772 thread_limit ( expression ) */
17773
17774static tree
17775c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
17776{
17777 location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
17778 matching_parens parens;
17779 if (parens.require_open (parser))
17780 {
17781 location_t expr_loc = c_parser_peek_token (parser)->location;
17782 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17783 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17784 tree c, t = expr.value;
17785 t = c_fully_fold (t, false, NULL);
17786
17787 parens.skip_until_found_close (parser);
17788
17789 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17790 {
17791 c_parser_error (parser, gmsgid: "expected integer expression");
17792 return list;
17793 }
17794
17795 /* Attempt to statically determine when the number isn't positive. */
17796 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17797 build_int_cst (TREE_TYPE (t), 0));
17798 protected_set_expr_location (c, expr_loc);
17799 if (c == boolean_true_node)
17800 {
17801 warning_at (expr_loc, OPT_Wopenmp,
17802 "%<thread_limit%> value must be positive");
17803 t = integer_one_node;
17804 }
17805
17806 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT,
17807 name: "thread_limit");
17808
17809 c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
17810 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
17811 OMP_CLAUSE_CHAIN (c) = list;
17812 list = c;
17813 }
17814
17815 return list;
17816}
17817
17818/* OpenMP 4.0:
17819 aligned ( variable-list )
17820 aligned ( variable-list : constant-expression ) */
17821
17822static tree
17823c_parser_omp_clause_aligned (c_parser *parser, tree list)
17824{
17825 location_t clause_loc = c_parser_peek_token (parser)->location;
17826 tree nl, c;
17827
17828 matching_parens parens;
17829 if (!parens.require_open (parser))
17830 return list;
17831
17832 nl = c_parser_omp_variable_list (parser, clause_loc,
17833 kind: OMP_CLAUSE_ALIGNED, list);
17834
17835 if (c_parser_next_token_is (parser, type: CPP_COLON))
17836 {
17837 c_parser_consume_token (parser);
17838 location_t expr_loc = c_parser_peek_token (parser)->location;
17839 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17840 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17841 tree alignment = expr.value;
17842 alignment = c_fully_fold (alignment, false, NULL);
17843 if (TREE_CODE (alignment) != INTEGER_CST
17844 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
17845 || tree_int_cst_sgn (alignment) != 1)
17846 {
17847 error_at (clause_loc, "%<aligned%> clause alignment expression must "
17848 "be positive constant integer expression");
17849 alignment = NULL_TREE;
17850 }
17851
17852 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17853 OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
17854 }
17855
17856 parens.skip_until_found_close (parser);
17857 return nl;
17858}
17859
17860/* OpenMP 5.0:
17861 allocate ( variable-list )
17862 allocate ( expression : variable-list )
17863
17864 OpenMP 5.1:
17865 allocate ( allocator-modifier : variable-list )
17866 allocate ( allocator-modifier , allocator-modifier : variable-list )
17867
17868 allocator-modifier:
17869 allocator ( expression )
17870 align ( expression ) */
17871
17872static tree
17873c_parser_omp_clause_allocate (c_parser *parser, tree list)
17874{
17875 location_t clause_loc = c_parser_peek_token (parser)->location;
17876 tree nl, c;
17877 tree allocator = NULL_TREE;
17878 tree align = NULL_TREE;
17879
17880 matching_parens parens;
17881 if (!parens.require_open (parser))
17882 return list;
17883
17884 if ((c_parser_next_token_is_not (parser, type: CPP_NAME)
17885 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
17886 || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
17887 && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
17888 {
17889 bool has_modifiers = false;
17890 tree orig_type = NULL_TREE;
17891 if (c_parser_next_token_is (parser, type: CPP_NAME)
17892 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
17893 {
17894 unsigned int n = 3;
17895 const char *p
17896 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17897 if ((strcmp (s1: p, s2: "allocator") == 0 || strcmp (s1: p, s2: "align") == 0)
17898 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
17899 && (c_parser_peek_nth_token_raw (parser, n)->type
17900 == CPP_CLOSE_PAREN))
17901 {
17902 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17903 == CPP_COLON)
17904 has_modifiers = true;
17905 else if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17906 == CPP_COMMA
17907 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
17908 == CPP_NAME)
17909 && (c_parser_peek_nth_token_raw (parser, n: n + 3)->type
17910 == CPP_OPEN_PAREN))
17911 {
17912 c_token *tok = c_parser_peek_nth_token_raw (parser, n: n + 2);
17913 const char *q = IDENTIFIER_POINTER (tok->value);
17914 n += 4;
17915 if ((strcmp (s1: q, s2: "allocator") == 0
17916 || strcmp (s1: q, s2: "align") == 0)
17917 && c_parser_check_balanced_raw_token_sequence (parser,
17918 n: &n)
17919 && (c_parser_peek_nth_token_raw (parser, n)->type
17920 == CPP_CLOSE_PAREN)
17921 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17922 == CPP_COLON))
17923 has_modifiers = true;
17924 }
17925 }
17926 if (has_modifiers)
17927 {
17928 c_parser_consume_token (parser);
17929 matching_parens parens2;;
17930 parens2.require_open (parser);
17931 location_t expr_loc = c_parser_peek_token (parser)->location;
17932 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17933 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17934 if (expr.value == error_mark_node)
17935 ;
17936 else if (strcmp (s1: p, s2: "allocator") == 0)
17937 {
17938 allocator = expr.value;
17939 allocator = c_fully_fold (allocator, false, NULL);
17940 orig_type = expr.original_type
17941 ? expr.original_type : TREE_TYPE (allocator);
17942 orig_type = TYPE_MAIN_VARIANT (orig_type);
17943 }
17944 else
17945 {
17946 align = expr.value;
17947 align = c_fully_fold (align, false, NULL);
17948 }
17949 parens2.skip_until_found_close (parser);
17950 if (c_parser_next_token_is (parser, type: CPP_COMMA))
17951 {
17952 c_parser_consume_token (parser);
17953 c_token *tok = c_parser_peek_token (parser);
17954 const char *q = "";
17955 if (c_parser_next_token_is (parser, type: CPP_NAME))
17956 q = IDENTIFIER_POINTER (tok->value);
17957 if (strcmp (s1: q, s2: "allocator") != 0 && strcmp (s1: q, s2: "align") != 0)
17958 {
17959 c_parser_error (parser, gmsgid: "expected %<allocator%> or "
17960 "%<align%>");
17961 parens.skip_until_found_close (parser);
17962 return list;
17963 }
17964 else if (strcmp (s1: p, s2: q) == 0)
17965 {
17966 error_at (tok->location, "duplicate %qs modifier", p);
17967 parens.skip_until_found_close (parser);
17968 return list;
17969 }
17970 c_parser_consume_token (parser);
17971 if (!parens2.require_open (parser))
17972 {
17973 parens.skip_until_found_close (parser);
17974 return list;
17975 }
17976 expr_loc = c_parser_peek_token (parser)->location;
17977 expr = c_parser_expr_no_commas (parser, NULL);
17978 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
17979 true);
17980 if (strcmp (s1: q, s2: "allocator") == 0)
17981 {
17982 allocator = expr.value;
17983 allocator = c_fully_fold (allocator, false, NULL);
17984 orig_type = expr.original_type
17985 ? expr.original_type : TREE_TYPE (allocator);
17986 orig_type = TYPE_MAIN_VARIANT (orig_type);
17987 }
17988 else
17989 {
17990 align = expr.value;
17991 align = c_fully_fold (align, false, NULL);
17992 }
17993 parens2.skip_until_found_close (parser);
17994 }
17995 }
17996 }
17997 if (!has_modifiers)
17998 {
17999 location_t expr_loc = c_parser_peek_token (parser)->location;
18000 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18001 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18002 allocator = expr.value;
18003 allocator = c_fully_fold (allocator, false, NULL);
18004 orig_type = expr.original_type
18005 ? expr.original_type : TREE_TYPE (allocator);
18006 orig_type = TYPE_MAIN_VARIANT (orig_type);
18007 }
18008 if (allocator
18009 && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
18010 || TREE_CODE (orig_type) != ENUMERAL_TYPE
18011 || (TYPE_NAME (orig_type)
18012 != get_identifier ("omp_allocator_handle_t"))))
18013 {
18014 error_at (clause_loc, "%<allocate%> clause allocator expression "
18015 "has type %qT rather than "
18016 "%<omp_allocator_handle_t%>",
18017 TREE_TYPE (allocator));
18018 allocator = NULL_TREE;
18019 }
18020 if (align
18021 && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
18022 || !tree_fits_uhwi_p (align)
18023 || !integer_pow2p (align)))
18024 {
18025 error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
18026 "argument needs to be positive constant "
18027 "power of two integer expression");
18028 align = NULL_TREE;
18029 }
18030 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18031 {
18032 parens.skip_until_found_close (parser);
18033 return list;
18034 }
18035 }
18036
18037 nl = c_parser_omp_variable_list (parser, clause_loc,
18038 kind: OMP_CLAUSE_ALLOCATE, list);
18039
18040 if (allocator || align)
18041 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18042 {
18043 OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
18044 OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
18045 }
18046
18047 parens.skip_until_found_close (parser);
18048 return nl;
18049}
18050
18051/* OpenMP 4.0:
18052 linear ( variable-list )
18053 linear ( variable-list : expression )
18054
18055 OpenMP 4.5:
18056 linear ( modifier ( variable-list ) )
18057 linear ( modifier ( variable-list ) : expression )
18058
18059 modifier:
18060 val
18061
18062 OpenMP 5.2:
18063 linear ( variable-list : modifiers-list )
18064
18065 modifiers:
18066 val
18067 step ( expression ) */
18068
18069static tree
18070c_parser_omp_clause_linear (c_parser *parser, tree list)
18071{
18072 location_t clause_loc = c_parser_peek_token (parser)->location;
18073 tree nl, c, step;
18074 enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
18075 bool old_linear_modifier = false;
18076
18077 matching_parens parens;
18078 if (!parens.require_open (parser))
18079 return list;
18080
18081 if (c_parser_next_token_is (parser, type: CPP_NAME))
18082 {
18083 c_token *tok = c_parser_peek_token (parser);
18084 const char *p = IDENTIFIER_POINTER (tok->value);
18085 if (strcmp (s1: "val", s2: p) == 0)
18086 kind = OMP_CLAUSE_LINEAR_VAL;
18087 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
18088 kind = OMP_CLAUSE_LINEAR_DEFAULT;
18089 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
18090 {
18091 old_linear_modifier = true;
18092 c_parser_consume_token (parser);
18093 c_parser_consume_token (parser);
18094 }
18095 }
18096
18097 nl = c_parser_omp_variable_list (parser, clause_loc,
18098 kind: OMP_CLAUSE_LINEAR, list);
18099
18100 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
18101 parens.skip_until_found_close (parser);
18102
18103 if (c_parser_next_token_is (parser, type: CPP_COLON))
18104 {
18105 c_parser_consume_token (parser);
18106 location_t expr_loc = c_parser_peek_token (parser)->location;
18107 bool has_modifiers = false;
18108 if (kind == OMP_CLAUSE_LINEAR_DEFAULT
18109 && c_parser_next_token_is (parser, type: CPP_NAME))
18110 {
18111 c_token *tok = c_parser_peek_token (parser);
18112 const char *p = IDENTIFIER_POINTER (tok->value);
18113 unsigned int pos = 0;
18114 if (strcmp (s1: "val", s2: p) == 0)
18115 pos = 2;
18116 else if (strcmp (s1: "step", s2: p) == 0
18117 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
18118 {
18119 pos = 3;
18120 if (c_parser_check_balanced_raw_token_sequence (parser, n: &pos)
18121 && (c_parser_peek_nth_token_raw (parser, n: pos)->type
18122 == CPP_CLOSE_PAREN))
18123 ++pos;
18124 else
18125 pos = 0;
18126 }
18127 if (pos)
18128 {
18129 tok = c_parser_peek_nth_token_raw (parser, n: pos);
18130 if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
18131 has_modifiers = true;
18132 }
18133 }
18134 if (has_modifiers)
18135 {
18136 step = NULL_TREE;
18137 while (c_parser_next_token_is (parser, type: CPP_NAME))
18138 {
18139 c_token *tok = c_parser_peek_token (parser);
18140 const char *p = IDENTIFIER_POINTER (tok->value);
18141 if (strcmp (s1: "val", s2: p) == 0)
18142 {
18143 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
18144 error_at (tok->location, "multiple linear modifiers");
18145 kind = OMP_CLAUSE_LINEAR_DEFAULT;
18146 c_parser_consume_token (parser);
18147 }
18148 else if (strcmp (s1: "step", s2: p) == 0)
18149 {
18150 c_parser_consume_token (parser);
18151 matching_parens parens2;
18152 if (parens2.require_open (parser))
18153 {
18154 if (step)
18155 error_at (tok->location,
18156 "multiple %<step%> modifiers");
18157 expr_loc = c_parser_peek_token (parser)->location;
18158 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18159 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
18160 true);
18161 step = c_fully_fold (expr.value, false, NULL);
18162 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
18163 {
18164 error_at (clause_loc, "%<linear%> clause step "
18165 "expression must be integral");
18166 step = integer_one_node;
18167 }
18168 parens2.skip_until_found_close (parser);
18169 }
18170 else
18171 break;
18172 }
18173 else
18174 break;
18175 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18176 {
18177 c_parser_consume_token (parser);
18178 continue;
18179 }
18180 break;
18181 }
18182 if (!step)
18183 step = integer_one_node;
18184 }
18185 else
18186 {
18187 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18188 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18189 step = c_fully_fold (expr.value, false, NULL);
18190 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
18191 {
18192 error_at (clause_loc, "%<linear%> clause step expression must "
18193 "be integral");
18194 step = integer_one_node;
18195 }
18196 }
18197
18198 }
18199 else
18200 step = integer_one_node;
18201
18202 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18203 {
18204 OMP_CLAUSE_LINEAR_STEP (c) = step;
18205 OMP_CLAUSE_LINEAR_KIND (c) = kind;
18206 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
18207 }
18208
18209 parens.skip_until_found_close (parser);
18210 return nl;
18211}
18212
18213/* OpenMP 5.0:
18214 nontemporal ( variable-list ) */
18215
18216static tree
18217c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
18218{
18219 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_NONTEMPORAL, list);
18220}
18221
18222/* OpenMP 4.0:
18223 safelen ( constant-expression ) */
18224
18225static tree
18226c_parser_omp_clause_safelen (c_parser *parser, tree list)
18227{
18228 location_t clause_loc = c_parser_peek_token (parser)->location;
18229 tree c, t;
18230
18231 matching_parens parens;
18232 if (!parens.require_open (parser))
18233 return list;
18234
18235 location_t expr_loc = c_parser_peek_token (parser)->location;
18236 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18237 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18238 t = expr.value;
18239 t = c_fully_fold (t, false, NULL);
18240 if (TREE_CODE (t) != INTEGER_CST
18241 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
18242 || tree_int_cst_sgn (t) != 1)
18243 {
18244 error_at (clause_loc, "%<safelen%> clause expression must "
18245 "be positive constant integer expression");
18246 t = NULL_TREE;
18247 }
18248
18249 parens.skip_until_found_close (parser);
18250 if (t == NULL_TREE || t == error_mark_node)
18251 return list;
18252
18253 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen");
18254
18255 c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
18256 OMP_CLAUSE_SAFELEN_EXPR (c) = t;
18257 OMP_CLAUSE_CHAIN (c) = list;
18258 return c;
18259}
18260
18261/* OpenMP 4.0:
18262 simdlen ( constant-expression ) */
18263
18264static tree
18265c_parser_omp_clause_simdlen (c_parser *parser, tree list)
18266{
18267 location_t clause_loc = c_parser_peek_token (parser)->location;
18268 tree c, t;
18269
18270 matching_parens parens;
18271 if (!parens.require_open (parser))
18272 return list;
18273
18274 location_t expr_loc = c_parser_peek_token (parser)->location;
18275 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18276 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18277 t = expr.value;
18278 t = c_fully_fold (t, false, NULL);
18279 if (TREE_CODE (t) != INTEGER_CST
18280 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
18281 || tree_int_cst_sgn (t) != 1)
18282 {
18283 error_at (clause_loc, "%<simdlen%> clause expression must "
18284 "be positive constant integer expression");
18285 t = NULL_TREE;
18286 }
18287
18288 parens.skip_until_found_close (parser);
18289 if (t == NULL_TREE || t == error_mark_node)
18290 return list;
18291
18292 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen");
18293
18294 c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
18295 OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
18296 OMP_CLAUSE_CHAIN (c) = list;
18297 return c;
18298}
18299
18300/* OpenMP 4.5:
18301 vec:
18302 identifier [+/- integer]
18303 vec , identifier [+/- integer]
18304*/
18305
18306static tree
18307c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
18308 tree list, bool depend_p)
18309{
18310 tree vec = NULL;
18311 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
18312 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
18313 {
18314 c_parser_error (parser, gmsgid: "expected identifier");
18315 return list;
18316 }
18317
18318 if (!depend_p)
18319 {
18320 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18321 if (strcmp (s1: p, s2: "omp_cur_iteration") == 0
18322 && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
18323 && c_parser_peek_nth_token (parser, n: 3)->type == CPP_NUMBER
18324 && c_parser_peek_nth_token (parser, n: 4)->type == CPP_CLOSE_PAREN)
18325 {
18326 tree val = c_parser_peek_nth_token (parser, n: 3)->value;
18327 if (integer_onep (val))
18328 {
18329 c_parser_consume_token (parser);
18330 c_parser_consume_token (parser);
18331 c_parser_consume_token (parser);
18332 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18333 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
18334 OMP_CLAUSE_CHAIN (u) = list;
18335 return u;
18336 }
18337 }
18338 }
18339
18340
18341
18342 while (c_parser_next_token_is (parser, type: CPP_NAME)
18343 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
18344 {
18345 tree t = lookup_name (c_parser_peek_token (parser)->value);
18346 tree addend = NULL;
18347
18348 if (t == NULL_TREE)
18349 {
18350 undeclared_variable (c_parser_peek_token (parser)->location,
18351 c_parser_peek_token (parser)->value);
18352 t = error_mark_node;
18353 }
18354
18355 c_parser_consume_token (parser);
18356
18357 bool neg = false;
18358 if (c_parser_next_token_is (parser, type: CPP_MINUS))
18359 neg = true;
18360 else if (!c_parser_next_token_is (parser, type: CPP_PLUS))
18361 {
18362 addend = integer_zero_node;
18363 neg = false;
18364 goto add_to_vector;
18365 }
18366 c_parser_consume_token (parser);
18367
18368 if (c_parser_next_token_is_not (parser, type: CPP_NUMBER))
18369 {
18370 c_parser_error (parser, gmsgid: "expected integer");
18371 return list;
18372 }
18373
18374 addend = c_parser_peek_token (parser)->value;
18375 if (TREE_CODE (addend) != INTEGER_CST)
18376 {
18377 c_parser_error (parser, gmsgid: "expected integer");
18378 return list;
18379 }
18380 c_parser_consume_token (parser);
18381
18382 add_to_vector:
18383 if (t != error_mark_node)
18384 {
18385 vec = tree_cons (addend, t, vec);
18386 if (neg)
18387 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
18388 }
18389
18390 if (c_parser_next_token_is_not (parser, type: CPP_COMMA)
18391 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
18392 || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
18393 break;
18394
18395 c_parser_consume_token (parser);
18396 }
18397
18398 if (vec == NULL_TREE)
18399 return list;
18400
18401 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18402 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
18403 OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
18404 OMP_CLAUSE_DECL (u) = nreverse (vec);
18405 OMP_CLAUSE_CHAIN (u) = list;
18406 return u;
18407}
18408
18409/* OpenMP 5.0:
18410 iterators ( iterators-definition )
18411
18412 iterators-definition:
18413 iterator-specifier
18414 iterator-specifier , iterators-definition
18415
18416 iterator-specifier:
18417 identifier = range-specification
18418 iterator-type identifier = range-specification
18419
18420 range-specification:
18421 begin : end
18422 begin : end : step */
18423
18424static tree
18425c_parser_omp_iterators (c_parser *parser)
18426{
18427 tree ret = NULL_TREE, *last = &ret;
18428 c_parser_consume_token (parser);
18429
18430 push_scope ();
18431
18432 matching_parens parens;
18433 if (!parens.require_open (parser))
18434 return error_mark_node;
18435
18436 do
18437 {
18438 tree iter_type = NULL_TREE, type_expr = NULL_TREE;
18439 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
18440 {
18441 struct c_type_name *type = c_parser_type_name (parser);
18442 if (type != NULL)
18443 iter_type = groktypename (type, &type_expr, NULL);
18444 }
18445 if (iter_type == NULL_TREE)
18446 iter_type = integer_type_node;
18447
18448 location_t loc = c_parser_peek_token (parser)->location;
18449 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18450 {
18451 c_parser_error (parser, gmsgid: "expected identifier");
18452 break;
18453 }
18454
18455 tree id = c_parser_peek_token (parser)->value;
18456 c_parser_consume_token (parser);
18457
18458 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
18459 break;
18460
18461 location_t eloc = c_parser_peek_token (parser)->location;
18462 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18463 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
18464 tree begin = expr.value;
18465
18466 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18467 break;
18468
18469 eloc = c_parser_peek_token (parser)->location;
18470 expr = c_parser_expr_no_commas (parser, NULL);
18471 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
18472 tree end = expr.value;
18473
18474 tree step = integer_one_node;
18475 if (c_parser_next_token_is (parser, type: CPP_COLON))
18476 {
18477 c_parser_consume_token (parser);
18478 eloc = c_parser_peek_token (parser)->location;
18479 expr = c_parser_expr_no_commas (parser, NULL);
18480 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
18481 step = expr.value;
18482 }
18483
18484 tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
18485 DECL_ARTIFICIAL (iter_var) = 1;
18486 DECL_CONTEXT (iter_var) = current_function_decl;
18487 pushdecl (iter_var);
18488
18489 *last = make_tree_vec (6);
18490 TREE_VEC_ELT (*last, 0) = iter_var;
18491 TREE_VEC_ELT (*last, 1) = begin;
18492 TREE_VEC_ELT (*last, 2) = end;
18493 TREE_VEC_ELT (*last, 3) = step;
18494 last = &TREE_CHAIN (*last);
18495
18496 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18497 {
18498 c_parser_consume_token (parser);
18499 continue;
18500 }
18501 break;
18502 }
18503 while (1);
18504
18505 parens.skip_until_found_close (parser);
18506 return ret ? ret : error_mark_node;
18507}
18508
18509/* OpenMP 5.0:
18510 affinity ( [aff-modifier :] variable-list )
18511 aff-modifier:
18512 iterator ( iterators-definition ) */
18513
18514static tree
18515c_parser_omp_clause_affinity (c_parser *parser, tree list)
18516{
18517 location_t clause_loc = c_parser_peek_token (parser)->location;
18518 tree nl, iterators = NULL_TREE;
18519
18520 matching_parens parens;
18521 if (!parens.require_open (parser))
18522 return list;
18523
18524 if (c_parser_next_token_is (parser, type: CPP_NAME))
18525 {
18526 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18527 bool parse_iter = ((strcmp (s1: "iterator", s2: p) == 0)
18528 && (c_parser_peek_2nd_token (parser)->type
18529 == CPP_OPEN_PAREN));
18530 if (parse_iter)
18531 {
18532 unsigned n = 3;
18533 parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, n: &n)
18534 && (c_parser_peek_nth_token_raw (parser, n)->type
18535 == CPP_CLOSE_PAREN)
18536 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
18537 == CPP_COLON));
18538 }
18539 if (parse_iter)
18540 {
18541 iterators = c_parser_omp_iterators (parser);
18542 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18543 {
18544 if (iterators)
18545 pop_scope ();
18546 parens.skip_until_found_close (parser);
18547 return list;
18548 }
18549 }
18550 }
18551 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_AFFINITY,
18552 list);
18553 if (iterators)
18554 {
18555 tree block = pop_scope ();
18556 if (iterators != error_mark_node)
18557 {
18558 TREE_VEC_ELT (iterators, 5) = block;
18559 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18560 OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
18561 OMP_CLAUSE_DECL (c));
18562 }
18563 }
18564
18565 parens.skip_until_found_close (parser);
18566 return nl;
18567}
18568
18569
18570/* OpenMP 4.0:
18571 depend ( depend-kind: variable-list )
18572
18573 depend-kind:
18574 in | out | inout
18575
18576 OpenMP 4.5:
18577 depend ( source )
18578
18579 depend ( sink : vec )
18580
18581 OpenMP 5.0:
18582 depend ( depend-modifier , depend-kind: variable-list )
18583
18584 depend-kind:
18585 in | out | inout | mutexinoutset | depobj | inoutset
18586
18587 depend-modifier:
18588 iterator ( iterators-definition ) */
18589
18590static tree
18591c_parser_omp_clause_depend (c_parser *parser, tree list)
18592{
18593 location_t clause_loc = c_parser_peek_token (parser)->location;
18594 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
18595 enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
18596 tree nl, c, iterators = NULL_TREE;
18597
18598 matching_parens parens;
18599 if (!parens.require_open (parser))
18600 return list;
18601
18602 do
18603 {
18604 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
18605 goto invalid_kind;
18606
18607 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18608 if (strcmp (s1: "iterator", s2: p) == 0 && iterators == NULL_TREE)
18609 {
18610 iterators = c_parser_omp_iterators (parser);
18611 c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>");
18612 continue;
18613 }
18614 if (strcmp (s1: "in", s2: p) == 0)
18615 kind = OMP_CLAUSE_DEPEND_IN;
18616 else if (strcmp (s1: "inout", s2: p) == 0)
18617 kind = OMP_CLAUSE_DEPEND_INOUT;
18618 else if (strcmp (s1: "inoutset", s2: p) == 0)
18619 kind = OMP_CLAUSE_DEPEND_INOUTSET;
18620 else if (strcmp (s1: "mutexinoutset", s2: p) == 0)
18621 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
18622 else if (strcmp (s1: "out", s2: p) == 0)
18623 kind = OMP_CLAUSE_DEPEND_OUT;
18624 else if (strcmp (s1: "depobj", s2: p) == 0)
18625 kind = OMP_CLAUSE_DEPEND_DEPOBJ;
18626 else if (strcmp (s1: "sink", s2: p) == 0)
18627 dkind = OMP_CLAUSE_DOACROSS_SINK;
18628 else if (strcmp (s1: "source", s2: p) == 0)
18629 dkind = OMP_CLAUSE_DOACROSS_SOURCE;
18630 else
18631 goto invalid_kind;
18632 break;
18633 }
18634 while (1);
18635
18636 c_parser_consume_token (parser);
18637
18638 if (iterators
18639 && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
18640 || dkind == OMP_CLAUSE_DOACROSS_SINK))
18641 {
18642 pop_scope ();
18643 error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
18644 dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
18645 iterators = NULL_TREE;
18646 }
18647
18648 if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
18649 {
18650 c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18651 OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
18652 OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
18653 OMP_CLAUSE_DECL (c) = NULL_TREE;
18654 OMP_CLAUSE_CHAIN (c) = list;
18655 parens.skip_until_found_close (parser);
18656 return c;
18657 }
18658
18659 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18660 goto resync_fail;
18661
18662 if (dkind == OMP_CLAUSE_DOACROSS_SINK)
18663 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: true);
18664 else
18665 {
18666 nl = c_parser_omp_variable_list (parser, clause_loc,
18667 kind: OMP_CLAUSE_DEPEND, list);
18668
18669 if (iterators)
18670 {
18671 tree block = pop_scope ();
18672 if (iterators == error_mark_node)
18673 iterators = NULL_TREE;
18674 else
18675 TREE_VEC_ELT (iterators, 5) = block;
18676 }
18677
18678 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18679 {
18680 OMP_CLAUSE_DEPEND_KIND (c) = kind;
18681 if (iterators)
18682 OMP_CLAUSE_DECL (c)
18683 = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
18684 }
18685 }
18686
18687 parens.skip_until_found_close (parser);
18688 return nl;
18689
18690 invalid_kind:
18691 c_parser_error (parser, gmsgid: "invalid depend kind");
18692 resync_fail:
18693 parens.skip_until_found_close (parser);
18694 if (iterators)
18695 pop_scope ();
18696 return list;
18697}
18698
18699/* OpenMP 5.2:
18700 doacross ( source : )
18701 doacross ( source : omp_cur_iteration )
18702
18703 doacross ( sink : vec )
18704 doacross ( sink : omp_cur_iteration - logical_iteration ) */
18705
18706static tree
18707c_parser_omp_clause_doacross (c_parser *parser, tree list)
18708{
18709 location_t clause_loc = c_parser_peek_token (parser)->location;
18710 enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
18711 tree nl;
18712 const char *p;
18713
18714 matching_parens parens;
18715 if (!parens.require_open (parser))
18716 return list;
18717
18718 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
18719 goto invalid_kind;
18720
18721 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18722 if (strcmp (s1: "sink", s2: p) == 0)
18723 kind = OMP_CLAUSE_DOACROSS_SINK;
18724 else if (strcmp (s1: "source", s2: p) == 0)
18725 kind = OMP_CLAUSE_DOACROSS_SOURCE;
18726 else
18727 goto invalid_kind;
18728
18729 c_parser_consume_token (parser);
18730
18731 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18732 goto resync_fail;
18733
18734 if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
18735 {
18736 if (c_parser_next_token_is (parser, type: CPP_NAME)
18737 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
18738 s2: "omp_cur_iteration") == 0)
18739 c_parser_consume_token (parser);
18740 nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18741 OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
18742 OMP_CLAUSE_DECL (nl) = NULL_TREE;
18743 OMP_CLAUSE_CHAIN (nl) = list;
18744 }
18745 else
18746 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: false);
18747
18748 parens.skip_until_found_close (parser);
18749 return nl;
18750
18751 invalid_kind:
18752 c_parser_error (parser, gmsgid: "invalid doacross kind");
18753 resync_fail:
18754 parens.skip_until_found_close (parser);
18755 return list;
18756}
18757
18758/* OpenMP 4.0:
18759 map ( map-kind: variable-list )
18760 map ( variable-list )
18761
18762 map-kind:
18763 alloc | to | from | tofrom
18764
18765 OpenMP 4.5:
18766 map-kind:
18767 alloc | to | from | tofrom | release | delete
18768
18769 map ( always [,] map-kind: variable-list )
18770
18771 OpenMP 5.0:
18772 map ( [map-type-modifier[,] ...] map-kind: variable-list )
18773
18774 map-type-modifier:
18775 always | close */
18776
18777static tree
18778c_parser_omp_clause_map (c_parser *parser, tree list)
18779{
18780 location_t clause_loc = c_parser_peek_token (parser)->location;
18781 enum gomp_map_kind kind = GOMP_MAP_TOFROM;
18782 tree nl, c;
18783
18784 matching_parens parens;
18785 if (!parens.require_open (parser))
18786 return list;
18787
18788 int pos = 1;
18789 int map_kind_pos = 0;
18790 while (c_parser_peek_nth_token_raw (parser, n: pos)->type == CPP_NAME)
18791 {
18792 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COLON)
18793 {
18794 map_kind_pos = pos;
18795 break;
18796 }
18797
18798 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COMMA)
18799 pos++;
18800 pos++;
18801 }
18802
18803 int always_modifier = 0;
18804 int close_modifier = 0;
18805 int present_modifier = 0;
18806 for (int pos = 1; pos < map_kind_pos; ++pos)
18807 {
18808 c_token *tok = c_parser_peek_token (parser);
18809
18810 if (tok->type == CPP_COMMA)
18811 {
18812 c_parser_consume_token (parser);
18813 continue;
18814 }
18815
18816 const char *p = IDENTIFIER_POINTER (tok->value);
18817 if (strcmp (s1: "always", s2: p) == 0)
18818 {
18819 if (always_modifier)
18820 {
18821 c_parser_error (parser, gmsgid: "too many %<always%> modifiers");
18822 parens.skip_until_found_close (parser);
18823 return list;
18824 }
18825 always_modifier++;
18826 }
18827 else if (strcmp (s1: "close", s2: p) == 0)
18828 {
18829 if (close_modifier)
18830 {
18831 c_parser_error (parser, gmsgid: "too many %<close%> modifiers");
18832 parens.skip_until_found_close (parser);
18833 return list;
18834 }
18835 close_modifier++;
18836 }
18837 else if (strcmp (s1: "present", s2: p) == 0)
18838 {
18839 if (present_modifier)
18840 {
18841 c_parser_error (parser, gmsgid: "too many %<present%> modifiers");
18842 parens.skip_until_found_close (parser);
18843 return list;
18844 }
18845 present_modifier++;
18846 }
18847 else
18848 {
18849 c_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other "
18850 "than %<always%>, %<close%> or %<present%>");
18851 parens.skip_until_found_close (parser);
18852 return list;
18853 }
18854
18855 c_parser_consume_token (parser);
18856 }
18857
18858 if (c_parser_next_token_is (parser, type: CPP_NAME)
18859 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18860 {
18861 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18862 int always_present_modifier = always_modifier && present_modifier;
18863
18864 if (strcmp (s1: "alloc", s2: p) == 0)
18865 kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
18866 else if (strcmp (s1: "to", s2: p) == 0)
18867 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
18868 : present_modifier ? GOMP_MAP_PRESENT_TO
18869 : always_modifier ? GOMP_MAP_ALWAYS_TO
18870 : GOMP_MAP_TO);
18871 else if (strcmp (s1: "from", s2: p) == 0)
18872 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
18873 : present_modifier ? GOMP_MAP_PRESENT_FROM
18874 : always_modifier ? GOMP_MAP_ALWAYS_FROM
18875 : GOMP_MAP_FROM);
18876 else if (strcmp (s1: "tofrom", s2: p) == 0)
18877 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
18878 : present_modifier ? GOMP_MAP_PRESENT_TOFROM
18879 : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
18880 : GOMP_MAP_TOFROM);
18881 else if (strcmp (s1: "release", s2: p) == 0)
18882 kind = GOMP_MAP_RELEASE;
18883 else if (strcmp (s1: "delete", s2: p) == 0)
18884 kind = GOMP_MAP_DELETE;
18885 else
18886 {
18887 c_parser_error (parser, gmsgid: "invalid map kind");
18888 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18889 msgid: "expected %<)%>");
18890 return list;
18891 }
18892 c_parser_consume_token (parser);
18893 c_parser_consume_token (parser);
18894 }
18895
18896 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_MAP, list,
18897 map_lvalue: true);
18898
18899 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18900 OMP_CLAUSE_SET_MAP_KIND (c, kind);
18901
18902 parens.skip_until_found_close (parser);
18903 return nl;
18904}
18905
18906/* OpenMP 4.0:
18907 device ( expression )
18908
18909 OpenMP 5.0:
18910 device ( [device-modifier :] integer-expression )
18911
18912 device-modifier:
18913 ancestor | device_num */
18914
18915static tree
18916c_parser_omp_clause_device (c_parser *parser, tree list)
18917{
18918 location_t clause_loc = c_parser_peek_token (parser)->location;
18919 location_t expr_loc;
18920 c_expr expr;
18921 tree c, t;
18922 bool ancestor = false;
18923
18924 matching_parens parens;
18925 if (!parens.require_open (parser))
18926 return list;
18927
18928 if (c_parser_next_token_is (parser, type: CPP_NAME)
18929 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18930 {
18931 c_token *tok = c_parser_peek_token (parser);
18932 const char *p = IDENTIFIER_POINTER (tok->value);
18933 if (strcmp (s1: "ancestor", s2: p) == 0)
18934 {
18935 /* A requires directive with the reverse_offload clause must be
18936 specified. */
18937 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
18938 {
18939 error_at (tok->location, "%<ancestor%> device modifier not "
18940 "preceded by %<requires%> directive "
18941 "with %<reverse_offload%> clause");
18942 parens.skip_until_found_close (parser);
18943 return list;
18944 }
18945 ancestor = true;
18946 }
18947 else if (strcmp (s1: "device_num", s2: p) == 0)
18948 ;
18949 else
18950 {
18951 error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
18952 parens.skip_until_found_close (parser);
18953 return list;
18954 }
18955 c_parser_consume_token (parser);
18956 c_parser_consume_token (parser);
18957 }
18958
18959 expr_loc = c_parser_peek_token (parser)->location;
18960 expr = c_parser_expr_no_commas (parser, NULL);
18961 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18962 t = expr.value;
18963 t = c_fully_fold (t, false, NULL);
18964
18965 parens.skip_until_found_close (parser);
18966
18967 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18968 {
18969 c_parser_error (parser, gmsgid: "expected integer expression");
18970 return list;
18971 }
18972 if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
18973 {
18974 error_at (expr_loc, "the %<device%> clause expression must evaluate to "
18975 "%<1%>");
18976 return list;
18977 }
18978
18979 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, name: "device");
18980
18981 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
18982
18983 OMP_CLAUSE_DEVICE_ID (c) = t;
18984 OMP_CLAUSE_CHAIN (c) = list;
18985 OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
18986
18987 list = c;
18988 return list;
18989}
18990
18991/* OpenMP 4.0:
18992 dist_schedule ( static )
18993 dist_schedule ( static , expression ) */
18994
18995static tree
18996c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
18997{
18998 tree c, t = NULL_TREE;
18999 location_t loc = c_parser_peek_token (parser)->location;
19000
19001 matching_parens parens;
19002 if (!parens.require_open (parser))
19003 return list;
19004
19005 if (!c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
19006 {
19007 c_parser_error (parser, gmsgid: "invalid dist_schedule kind");
19008 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
19009 msgid: "expected %<)%>");
19010 return list;
19011 }
19012
19013 c_parser_consume_token (parser);
19014 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19015 {
19016 c_parser_consume_token (parser);
19017
19018 location_t expr_loc = c_parser_peek_token (parser)->location;
19019 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19020 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19021 t = expr.value;
19022 t = c_fully_fold (t, false, NULL);
19023 parens.skip_until_found_close (parser);
19024 }
19025 else
19026 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
19027 msgid: "expected %<,%> or %<)%>");
19028
19029 /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
19030 "dist_schedule"); */
19031 if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE))
19032 warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
19033 if (t == error_mark_node)
19034 return list;
19035
19036 c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
19037 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
19038 OMP_CLAUSE_CHAIN (c) = list;
19039 return c;
19040}
19041
19042/* OpenMP 4.0:
19043 proc_bind ( proc-bind-kind )
19044
19045 proc-bind-kind:
19046 primary | master | close | spread
19047 where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
19048
19049static tree
19050c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
19051{
19052 location_t clause_loc = c_parser_peek_token (parser)->location;
19053 enum omp_clause_proc_bind_kind kind;
19054 tree c;
19055
19056 matching_parens parens;
19057 if (!parens.require_open (parser))
19058 return list;
19059
19060 if (c_parser_next_token_is (parser, type: CPP_NAME))
19061 {
19062 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19063 if (strcmp (s1: "primary", s2: p) == 0)
19064 kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
19065 else if (strcmp (s1: "master", s2: p) == 0)
19066 kind = OMP_CLAUSE_PROC_BIND_MASTER;
19067 else if (strcmp (s1: "close", s2: p) == 0)
19068 kind = OMP_CLAUSE_PROC_BIND_CLOSE;
19069 else if (strcmp (s1: "spread", s2: p) == 0)
19070 kind = OMP_CLAUSE_PROC_BIND_SPREAD;
19071 else
19072 goto invalid_kind;
19073 }
19074 else
19075 goto invalid_kind;
19076
19077 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind");
19078 c_parser_consume_token (parser);
19079 parens.skip_until_found_close (parser);
19080 c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
19081 OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
19082 OMP_CLAUSE_CHAIN (c) = list;
19083 return c;
19084
19085 invalid_kind:
19086 c_parser_error (parser, gmsgid: "invalid proc_bind kind");
19087 parens.skip_until_found_close (parser);
19088 return list;
19089}
19090
19091/* OpenMP 5.0:
19092 device_type ( host | nohost | any ) */
19093
19094static tree
19095c_parser_omp_clause_device_type (c_parser *parser, tree list)
19096{
19097 location_t clause_loc = c_parser_peek_token (parser)->location;
19098 enum omp_clause_device_type_kind kind;
19099 tree c;
19100
19101 matching_parens parens;
19102 if (!parens.require_open (parser))
19103 return list;
19104
19105 if (c_parser_next_token_is (parser, type: CPP_NAME))
19106 {
19107 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19108 if (strcmp (s1: "host", s2: p) == 0)
19109 kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
19110 else if (strcmp (s1: "nohost", s2: p) == 0)
19111 kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
19112 else if (strcmp (s1: "any", s2: p) == 0)
19113 kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
19114 else
19115 goto invalid_kind;
19116 }
19117 else
19118 goto invalid_kind;
19119
19120 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE,
19121 name: "device_type");
19122 c_parser_consume_token (parser);
19123 parens.skip_until_found_close (parser);
19124 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
19125 OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
19126 OMP_CLAUSE_CHAIN (c) = list;
19127 return c;
19128
19129 invalid_kind:
19130 c_parser_error (parser, gmsgid: "expected %<host%>, %<nohost%> or %<any%>");
19131 parens.skip_until_found_close (parser);
19132 return list;
19133}
19134
19135/* OpenMP 4.0:
19136 from ( variable-list )
19137 to ( variable-list )
19138
19139 OpenMP 5.1:
19140 from ( [present :] variable-list )
19141 to ( [present :] variable-list ) */
19142
19143static tree
19144c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
19145 tree list)
19146{
19147 location_t loc = c_parser_peek_token (parser)->location;
19148 matching_parens parens;
19149 if (!parens.require_open (parser))
19150 return list;
19151
19152 bool present = false;
19153 c_token *token = c_parser_peek_token (parser);
19154
19155 if (token->type == CPP_NAME
19156 && strcmp (IDENTIFIER_POINTER (token->value), s2: "present") == 0
19157 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
19158 {
19159 present = true;
19160 c_parser_consume_token (parser);
19161 c_parser_consume_token (parser);
19162 }
19163
19164 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list);
19165 parens.skip_until_found_close (parser);
19166
19167 if (present)
19168 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19169 OMP_CLAUSE_MOTION_PRESENT (c) = 1;
19170
19171 return nl;
19172}
19173
19174/* OpenMP 4.0:
19175 uniform ( variable-list ) */
19176
19177static tree
19178c_parser_omp_clause_uniform (c_parser *parser, tree list)
19179{
19180 /* The clauses location. */
19181 location_t loc = c_parser_peek_token (parser)->location;
19182
19183 matching_parens parens;
19184 if (parens.require_open (parser))
19185 {
19186 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_UNIFORM,
19187 list);
19188 parens.skip_until_found_close (parser);
19189 }
19190 return list;
19191}
19192
19193/* OpenMP 5.0:
19194 detach ( event-handle ) */
19195
19196static tree
19197c_parser_omp_clause_detach (c_parser *parser, tree list)
19198{
19199 matching_parens parens;
19200 location_t clause_loc = c_parser_peek_token (parser)->location;
19201
19202 if (!parens.require_open (parser))
19203 return list;
19204
19205 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
19206 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
19207 {
19208 c_parser_error (parser, gmsgid: "expected identifier");
19209 parens.skip_until_found_close (parser);
19210 return list;
19211 }
19212
19213 tree t = lookup_name (c_parser_peek_token (parser)->value);
19214 if (t == NULL_TREE)
19215 {
19216 undeclared_variable (c_parser_peek_token (parser)->location,
19217 c_parser_peek_token (parser)->value);
19218 parens.skip_until_found_close (parser);
19219 return list;
19220 }
19221 c_parser_consume_token (parser);
19222
19223 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
19224 if (!INTEGRAL_TYPE_P (type)
19225 || TREE_CODE (type) != ENUMERAL_TYPE
19226 || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
19227 {
19228 error_at (clause_loc, "%<detach%> clause event handle "
19229 "has type %qT rather than "
19230 "%<omp_event_handle_t%>",
19231 type);
19232 parens.skip_until_found_close (parser);
19233 return list;
19234 }
19235
19236 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
19237 OMP_CLAUSE_DECL (u) = t;
19238 OMP_CLAUSE_CHAIN (u) = list;
19239 parens.skip_until_found_close (parser);
19240 return u;
19241}
19242
19243/* Parse all OpenACC clauses. The set clauses allowed by the directive
19244 is a bitmask in MASK. Return the list of clauses found. */
19245
19246static tree
19247c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
19248 const char *where, bool finish_p = true,
19249 bool target_p = false)
19250{
19251 tree clauses = NULL;
19252 bool first = true;
19253
19254 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
19255 {
19256 location_t here;
19257 pragma_omp_clause c_kind;
19258 const char *c_name;
19259 tree prev = clauses;
19260
19261 if (!first && c_parser_next_token_is (parser, type: CPP_COMMA))
19262 c_parser_consume_token (parser);
19263
19264 here = c_parser_peek_token (parser)->location;
19265 c_kind = c_parser_omp_clause_name (parser);
19266
19267 switch (c_kind)
19268 {
19269 case PRAGMA_OACC_CLAUSE_ASYNC:
19270 clauses = c_parser_oacc_clause_async (parser, list: clauses);
19271 c_name = "async";
19272 break;
19273 case PRAGMA_OACC_CLAUSE_AUTO:
19274 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO,
19275 list: clauses);
19276 c_name = "auto";
19277 break;
19278 case PRAGMA_OACC_CLAUSE_ATTACH:
19279 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19280 c_name = "attach";
19281 break;
19282 case PRAGMA_OACC_CLAUSE_COLLAPSE:
19283 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
19284 c_name = "collapse";
19285 break;
19286 case PRAGMA_OACC_CLAUSE_COPY:
19287 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19288 c_name = "copy";
19289 break;
19290 case PRAGMA_OACC_CLAUSE_COPYIN:
19291 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19292 c_name = "copyin";
19293 break;
19294 case PRAGMA_OACC_CLAUSE_COPYOUT:
19295 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19296 c_name = "copyout";
19297 break;
19298 case PRAGMA_OACC_CLAUSE_CREATE:
19299 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19300 c_name = "create";
19301 break;
19302 case PRAGMA_OACC_CLAUSE_DELETE:
19303 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19304 c_name = "delete";
19305 break;
19306 case PRAGMA_OMP_CLAUSE_DEFAULT:
19307 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: true);
19308 c_name = "default";
19309 break;
19310 case PRAGMA_OACC_CLAUSE_DETACH:
19311 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19312 c_name = "detach";
19313 break;
19314 case PRAGMA_OACC_CLAUSE_DEVICE:
19315 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19316 c_name = "device";
19317 break;
19318 case PRAGMA_OACC_CLAUSE_DEVICEPTR:
19319 clauses = c_parser_oacc_data_clause_deviceptr (parser, list: clauses);
19320 c_name = "deviceptr";
19321 break;
19322 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
19323 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19324 c_name = "device_resident";
19325 break;
19326 case PRAGMA_OACC_CLAUSE_FINALIZE:
19327 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE,
19328 list: clauses);
19329 c_name = "finalize";
19330 break;
19331 case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
19332 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
19333 c_name = "firstprivate";
19334 break;
19335 case PRAGMA_OACC_CLAUSE_GANG:
19336 c_name = "gang";
19337 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG,
19338 str: c_name, list: clauses);
19339 break;
19340 case PRAGMA_OACC_CLAUSE_HOST:
19341 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19342 c_name = "host";
19343 break;
19344 case PRAGMA_OACC_CLAUSE_IF:
19345 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: false);
19346 c_name = "if";
19347 break;
19348 case PRAGMA_OACC_CLAUSE_IF_PRESENT:
19349 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT,
19350 list: clauses);
19351 c_name = "if_present";
19352 break;
19353 case PRAGMA_OACC_CLAUSE_INDEPENDENT:
19354 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT,
19355 list: clauses);
19356 c_name = "independent";
19357 break;
19358 case PRAGMA_OACC_CLAUSE_LINK:
19359 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19360 c_name = "link";
19361 break;
19362 case PRAGMA_OACC_CLAUSE_NO_CREATE:
19363 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19364 c_name = "no_create";
19365 break;
19366 case PRAGMA_OACC_CLAUSE_NOHOST:
19367 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST,
19368 list: clauses);
19369 c_name = "nohost";
19370 break;
19371 case PRAGMA_OACC_CLAUSE_NUM_GANGS:
19372 clauses = c_parser_oacc_single_int_clause (parser,
19373 code: OMP_CLAUSE_NUM_GANGS,
19374 list: clauses);
19375 c_name = "num_gangs";
19376 break;
19377 case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
19378 clauses = c_parser_oacc_single_int_clause (parser,
19379 code: OMP_CLAUSE_NUM_WORKERS,
19380 list: clauses);
19381 c_name = "num_workers";
19382 break;
19383 case PRAGMA_OACC_CLAUSE_PRESENT:
19384 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19385 c_name = "present";
19386 break;
19387 case PRAGMA_OACC_CLAUSE_PRIVATE:
19388 clauses = c_parser_omp_clause_private (parser, list: clauses);
19389 c_name = "private";
19390 break;
19391 case PRAGMA_OACC_CLAUSE_REDUCTION:
19392 clauses
19393 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
19394 is_omp: false, list: clauses);
19395 c_name = "reduction";
19396 break;
19397 case PRAGMA_OACC_CLAUSE_SELF:
19398 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
19399 /* OpenACC compute construct */
19400 clauses = c_parser_oacc_compute_clause_self (parser, list: clauses);
19401 else
19402 /* OpenACC 'update' directive */
19403 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
19404 c_name = "self";
19405 break;
19406 case PRAGMA_OACC_CLAUSE_SEQ:
19407 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ,
19408 list: clauses);
19409 c_name = "seq";
19410 break;
19411 case PRAGMA_OACC_CLAUSE_TILE:
19412 clauses = c_parser_oacc_clause_tile (parser, list: clauses);
19413 c_name = "tile";
19414 break;
19415 case PRAGMA_OACC_CLAUSE_USE_DEVICE:
19416 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
19417 c_name = "use_device";
19418 break;
19419 case PRAGMA_OACC_CLAUSE_VECTOR:
19420 c_name = "vector";
19421 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_VECTOR,
19422 str: c_name, list: clauses);
19423 break;
19424 case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
19425 clauses = c_parser_oacc_single_int_clause (parser,
19426 code: OMP_CLAUSE_VECTOR_LENGTH,
19427 list: clauses);
19428 c_name = "vector_length";
19429 break;
19430 case PRAGMA_OACC_CLAUSE_WAIT:
19431 clauses = c_parser_oacc_clause_wait (parser, list: clauses);
19432 c_name = "wait";
19433 break;
19434 case PRAGMA_OACC_CLAUSE_WORKER:
19435 c_name = "worker";
19436 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_WORKER,
19437 str: c_name, list: clauses);
19438 break;
19439 default:
19440 c_parser_error (parser, gmsgid: "expected an OpenACC clause");
19441 goto saw_error;
19442 }
19443
19444 first = false;
19445
19446 if (((mask >> c_kind) & 1) == 0)
19447 {
19448 /* Remove the invalid clause(s) from the list to avoid
19449 confusing the rest of the compiler. */
19450 clauses = prev;
19451 error_at (here, "%qs is not valid for %qs", c_name, where);
19452 }
19453 }
19454
19455 saw_error:
19456 c_parser_skip_to_pragma_eol (parser);
19457
19458 if (finish_p)
19459 return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
19460 : C_ORT_ACC);
19461
19462 return clauses;
19463}
19464
19465/* Parse all OpenMP clauses. The set clauses allowed by the directive
19466 is a bitmask in MASK. Return the list of clauses found.
19467 FINISH_P set if c_finish_omp_clauses should be called.
19468 NESTED non-zero if clauses should be terminated by closing paren instead
19469 of end of pragma. If it is 2, additionally commas are required in between
19470 the clauses. */
19471
19472static tree
19473c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
19474 const char *where, bool finish_p = true,
19475 int nested = 0)
19476{
19477 tree clauses = NULL;
19478 bool first = true;
19479
19480 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
19481 {
19482 location_t here;
19483 pragma_omp_clause c_kind;
19484 const char *c_name;
19485 tree prev = clauses;
19486
19487 if (nested && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
19488 break;
19489
19490 if (!first || nested != 2)
19491 {
19492 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19493 c_parser_consume_token (parser);
19494 else if (nested == 2)
19495 error_at (c_parser_peek_token (parser)->location,
19496 "clauses in %<simd%> trait should be separated "
19497 "by %<,%>");
19498 }
19499
19500 here = c_parser_peek_token (parser)->location;
19501 c_kind = c_parser_omp_clause_name (parser);
19502
19503 switch (c_kind)
19504 {
19505 case PRAGMA_OMP_CLAUSE_BIND:
19506 clauses = c_parser_omp_clause_bind (parser, list: clauses);
19507 c_name = "bind";
19508 break;
19509 case PRAGMA_OMP_CLAUSE_COLLAPSE:
19510 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
19511 c_name = "collapse";
19512 break;
19513 case PRAGMA_OMP_CLAUSE_COPYIN:
19514 clauses = c_parser_omp_clause_copyin (parser, list: clauses);
19515 c_name = "copyin";
19516 break;
19517 case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
19518 clauses = c_parser_omp_clause_copyprivate (parser, list: clauses);
19519 c_name = "copyprivate";
19520 break;
19521 case PRAGMA_OMP_CLAUSE_DEFAULT:
19522 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: false);
19523 c_name = "default";
19524 break;
19525 case PRAGMA_OMP_CLAUSE_DETACH:
19526 clauses = c_parser_omp_clause_detach (parser, list: clauses);
19527 c_name = "detach";
19528 break;
19529 case PRAGMA_OMP_CLAUSE_FILTER:
19530 clauses = c_parser_omp_clause_filter (parser, list: clauses);
19531 c_name = "filter";
19532 break;
19533 case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
19534 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
19535 c_name = "firstprivate";
19536 break;
19537 case PRAGMA_OMP_CLAUSE_FINAL:
19538 clauses = c_parser_omp_clause_final (parser, list: clauses);
19539 c_name = "final";
19540 break;
19541 case PRAGMA_OMP_CLAUSE_GRAINSIZE:
19542 clauses = c_parser_omp_clause_grainsize (parser, list: clauses);
19543 c_name = "grainsize";
19544 break;
19545 case PRAGMA_OMP_CLAUSE_HINT:
19546 clauses = c_parser_omp_clause_hint (parser, list: clauses);
19547 c_name = "hint";
19548 break;
19549 case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
19550 clauses = c_parser_omp_clause_defaultmap (parser, list: clauses);
19551 c_name = "defaultmap";
19552 break;
19553 case PRAGMA_OMP_CLAUSE_IF:
19554 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: true);
19555 c_name = "if";
19556 break;
19557 case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
19558 clauses
19559 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION,
19560 is_omp: true, list: clauses);
19561 c_name = "in_reduction";
19562 break;
19563 case PRAGMA_OMP_CLAUSE_INDIRECT:
19564 clauses = c_parser_omp_clause_indirect (parser, list: clauses);
19565 c_name = "indirect";
19566 break;
19567 case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
19568 clauses = c_parser_omp_clause_lastprivate (parser, list: clauses);
19569 c_name = "lastprivate";
19570 break;
19571 case PRAGMA_OMP_CLAUSE_MERGEABLE:
19572 clauses = c_parser_omp_clause_mergeable (parser, list: clauses);
19573 c_name = "mergeable";
19574 break;
19575 case PRAGMA_OMP_CLAUSE_NOWAIT:
19576 clauses = c_parser_omp_clause_nowait (parser, list: clauses);
19577 c_name = "nowait";
19578 break;
19579 case PRAGMA_OMP_CLAUSE_NUM_TASKS:
19580 clauses = c_parser_omp_clause_num_tasks (parser, list: clauses);
19581 c_name = "num_tasks";
19582 break;
19583 case PRAGMA_OMP_CLAUSE_NUM_THREADS:
19584 clauses = c_parser_omp_clause_num_threads (parser, list: clauses);
19585 c_name = "num_threads";
19586 break;
19587 case PRAGMA_OMP_CLAUSE_ORDER:
19588 clauses = c_parser_omp_clause_order (parser, list: clauses);
19589 c_name = "order";
19590 break;
19591 case PRAGMA_OMP_CLAUSE_ORDERED:
19592 clauses = c_parser_omp_clause_ordered (parser, list: clauses);
19593 c_name = "ordered";
19594 break;
19595 case PRAGMA_OMP_CLAUSE_PRIORITY:
19596 clauses = c_parser_omp_clause_priority (parser, list: clauses);
19597 c_name = "priority";
19598 break;
19599 case PRAGMA_OMP_CLAUSE_PRIVATE:
19600 clauses = c_parser_omp_clause_private (parser, list: clauses);
19601 c_name = "private";
19602 break;
19603 case PRAGMA_OMP_CLAUSE_REDUCTION:
19604 clauses
19605 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
19606 is_omp: true, list: clauses);
19607 c_name = "reduction";
19608 break;
19609 case PRAGMA_OMP_CLAUSE_SCHEDULE:
19610 clauses = c_parser_omp_clause_schedule (parser, list: clauses);
19611 c_name = "schedule";
19612 break;
19613 case PRAGMA_OMP_CLAUSE_SHARED:
19614 clauses = c_parser_omp_clause_shared (parser, list: clauses);
19615 c_name = "shared";
19616 break;
19617 case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
19618 clauses
19619 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_TASK_REDUCTION,
19620 is_omp: true, list: clauses);
19621 c_name = "task_reduction";
19622 break;
19623 case PRAGMA_OMP_CLAUSE_UNTIED:
19624 clauses = c_parser_omp_clause_untied (parser, list: clauses);
19625 c_name = "untied";
19626 break;
19627 case PRAGMA_OMP_CLAUSE_INBRANCH:
19628 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH,
19629 list: clauses);
19630 c_name = "inbranch";
19631 break;
19632 case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
19633 clauses = c_parser_omp_clause_nontemporal (parser, list: clauses);
19634 c_name = "nontemporal";
19635 break;
19636 case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
19637 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_NOTINBRANCH,
19638 list: clauses);
19639 c_name = "notinbranch";
19640 break;
19641 case PRAGMA_OMP_CLAUSE_PARALLEL:
19642 clauses
19643 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL,
19644 list: clauses);
19645 c_name = "parallel";
19646 if (!first)
19647 {
19648 clause_not_first:
19649 error_at (here, "%qs must be the first clause of %qs",
19650 c_name, where);
19651 clauses = prev;
19652 }
19653 break;
19654 case PRAGMA_OMP_CLAUSE_FOR:
19655 clauses
19656 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR,
19657 list: clauses);
19658 c_name = "for";
19659 if (!first)
19660 goto clause_not_first;
19661 break;
19662 case PRAGMA_OMP_CLAUSE_SECTIONS:
19663 clauses
19664 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS,
19665 list: clauses);
19666 c_name = "sections";
19667 if (!first)
19668 goto clause_not_first;
19669 break;
19670 case PRAGMA_OMP_CLAUSE_TASKGROUP:
19671 clauses
19672 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP,
19673 list: clauses);
19674 c_name = "taskgroup";
19675 if (!first)
19676 goto clause_not_first;
19677 break;
19678 case PRAGMA_OMP_CLAUSE_LINK:
19679 clauses
19680 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_LINK, list: clauses);
19681 c_name = "link";
19682 break;
19683 case PRAGMA_OMP_CLAUSE_TO:
19684 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
19685 {
19686 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
19687 list: clauses);
19688 for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
19689 OMP_CLAUSE_ENTER_TO (c) = 1;
19690 clauses = nl;
19691 }
19692 else
19693 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO,
19694 list: clauses);
19695 c_name = "to";
19696 break;
19697 case PRAGMA_OMP_CLAUSE_FROM:
19698 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM,
19699 list: clauses);
19700 c_name = "from";
19701 break;
19702 case PRAGMA_OMP_CLAUSE_UNIFORM:
19703 clauses = c_parser_omp_clause_uniform (parser, list: clauses);
19704 c_name = "uniform";
19705 break;
19706 case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
19707 clauses = c_parser_omp_clause_num_teams (parser, list: clauses);
19708 c_name = "num_teams";
19709 break;
19710 case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
19711 clauses = c_parser_omp_clause_thread_limit (parser, list: clauses);
19712 c_name = "thread_limit";
19713 break;
19714 case PRAGMA_OMP_CLAUSE_ALIGNED:
19715 clauses = c_parser_omp_clause_aligned (parser, list: clauses);
19716 c_name = "aligned";
19717 break;
19718 case PRAGMA_OMP_CLAUSE_ALLOCATE:
19719 clauses = c_parser_omp_clause_allocate (parser, list: clauses);
19720 c_name = "allocate";
19721 break;
19722 case PRAGMA_OMP_CLAUSE_LINEAR:
19723 clauses = c_parser_omp_clause_linear (parser, list: clauses);
19724 c_name = "linear";
19725 break;
19726 case PRAGMA_OMP_CLAUSE_AFFINITY:
19727 clauses = c_parser_omp_clause_affinity (parser, list: clauses);
19728 c_name = "affinity";
19729 break;
19730 case PRAGMA_OMP_CLAUSE_DEPEND:
19731 clauses = c_parser_omp_clause_depend (parser, list: clauses);
19732 c_name = "depend";
19733 break;
19734 case PRAGMA_OMP_CLAUSE_DOACROSS:
19735 clauses = c_parser_omp_clause_doacross (parser, list: clauses);
19736 c_name = "doacross";
19737 break;
19738 case PRAGMA_OMP_CLAUSE_MAP:
19739 clauses = c_parser_omp_clause_map (parser, list: clauses);
19740 c_name = "map";
19741 break;
19742 case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
19743 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
19744 c_name = "use_device_ptr";
19745 break;
19746 case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
19747 clauses = c_parser_omp_clause_use_device_addr (parser, list: clauses);
19748 c_name = "use_device_addr";
19749 break;
19750 case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
19751 clauses = c_parser_omp_clause_has_device_addr (parser, list: clauses);
19752 c_name = "has_device_addr";
19753 break;
19754 case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
19755 clauses = c_parser_omp_clause_is_device_ptr (parser, list: clauses);
19756 c_name = "is_device_ptr";
19757 break;
19758 case PRAGMA_OMP_CLAUSE_DEVICE:
19759 clauses = c_parser_omp_clause_device (parser, list: clauses);
19760 c_name = "device";
19761 break;
19762 case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
19763 clauses = c_parser_omp_clause_dist_schedule (parser, list: clauses);
19764 c_name = "dist_schedule";
19765 break;
19766 case PRAGMA_OMP_CLAUSE_PROC_BIND:
19767 clauses = c_parser_omp_clause_proc_bind (parser, list: clauses);
19768 c_name = "proc_bind";
19769 break;
19770 case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
19771 clauses = c_parser_omp_clause_device_type (parser, list: clauses);
19772 c_name = "device_type";
19773 break;
19774 case PRAGMA_OMP_CLAUSE_SAFELEN:
19775 clauses = c_parser_omp_clause_safelen (parser, list: clauses);
19776 c_name = "safelen";
19777 break;
19778 case PRAGMA_OMP_CLAUSE_SIMDLEN:
19779 clauses = c_parser_omp_clause_simdlen (parser, list: clauses);
19780 c_name = "simdlen";
19781 break;
19782 case PRAGMA_OMP_CLAUSE_NOGROUP:
19783 clauses = c_parser_omp_clause_nogroup (parser, list: clauses);
19784 c_name = "nogroup";
19785 break;
19786 case PRAGMA_OMP_CLAUSE_THREADS:
19787 clauses
19788 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS,
19789 list: clauses);
19790 c_name = "threads";
19791 break;
19792 case PRAGMA_OMP_CLAUSE_SIMD:
19793 clauses
19794 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD,
19795 list: clauses);
19796 c_name = "simd";
19797 break;
19798 case PRAGMA_OMP_CLAUSE_ENTER:
19799 clauses
19800 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
19801 list: clauses);
19802 c_name = "enter";
19803 break;
19804 default:
19805 c_parser_error (parser, gmsgid: "expected an OpenMP clause");
19806 goto saw_error;
19807 }
19808
19809 first = false;
19810
19811 if (((mask >> c_kind) & 1) == 0)
19812 {
19813 /* Remove the invalid clause(s) from the list to avoid
19814 confusing the rest of the compiler. */
19815 clauses = prev;
19816 error_at (here, "%qs is not valid for %qs", c_name, where);
19817 }
19818 }
19819
19820 saw_error:
19821 if (!nested)
19822 c_parser_skip_to_pragma_eol (parser);
19823
19824 if (finish_p)
19825 {
19826 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
19827 return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
19828 return c_finish_omp_clauses (clauses, C_ORT_OMP);
19829 }
19830
19831 return clauses;
19832}
19833
19834/* OpenACC 2.0, OpenMP 2.5:
19835 structured-block:
19836 statement
19837
19838 In practice, we're also interested in adding the statement to an
19839 outer node. So it is convenient if we work around the fact that
19840 c_parser_statement calls add_stmt. */
19841
19842static tree
19843c_parser_omp_structured_block (c_parser *parser, bool *if_p)
19844{
19845 tree stmt = push_stmt_list ();
19846 parser->omp_attrs_forbidden_p = true;
19847 c_parser_statement (parser, if_p);
19848 return pop_stmt_list (stmt);
19849}
19850
19851/* OpenACC 2.0:
19852 # pragma acc cache (variable-list) new-line
19853
19854 OpenACC 2.7:
19855 # pragma acc cache (readonly: variable-list) new-line
19856
19857 LOC is the location of the #pragma token.
19858*/
19859
19860static tree
19861c_parser_oacc_cache (location_t loc, c_parser *parser)
19862{
19863 tree stmt, clauses = NULL_TREE;
19864 bool readonly = false;
19865 location_t open_loc = c_parser_peek_token (parser)->location;
19866 matching_parens parens;
19867 if (parens.require_open (parser))
19868 {
19869 c_token *token = c_parser_peek_token (parser);
19870 if (token->type == CPP_NAME
19871 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
19872 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
19873 {
19874 c_parser_consume_token (parser);
19875 c_parser_consume_token (parser);
19876 readonly = true;
19877 }
19878 clauses = c_parser_omp_variable_list (parser, clause_loc: open_loc,
19879 kind: OMP_CLAUSE__CACHE_, NULL_TREE);
19880 parens.skip_until_found_close (parser);
19881 }
19882
19883 if (readonly)
19884 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
19885 OMP_CLAUSE__CACHE__READONLY (c) = 1;
19886
19887 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
19888
19889 c_parser_skip_to_pragma_eol (parser);
19890
19891 stmt = make_node (OACC_CACHE);
19892 TREE_TYPE (stmt) = void_type_node;
19893 OACC_CACHE_CLAUSES (stmt) = clauses;
19894 SET_EXPR_LOCATION (stmt, loc);
19895 add_stmt (stmt);
19896
19897 return stmt;
19898}
19899
19900/* OpenACC 2.0:
19901 # pragma acc data oacc-data-clause[optseq] new-line
19902 structured-block
19903
19904 LOC is the location of the #pragma token.
19905*/
19906
19907#define OACC_DATA_CLAUSE_MASK \
19908 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19909 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19910 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19911 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19912 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19913 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
19914 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19915 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19916 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
19917 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
19918
19919static tree
19920c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
19921{
19922 tree stmt, clauses, block;
19923
19924 clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
19925 where: "#pragma acc data");
19926
19927 block = c_begin_omp_parallel ();
19928 add_stmt (c_parser_omp_structured_block (parser, if_p));
19929
19930 stmt = c_finish_oacc_data (loc, clauses, block);
19931
19932 return stmt;
19933}
19934
19935/* OpenACC 2.0:
19936 # pragma acc declare oacc-data-clause[optseq] new-line
19937*/
19938
19939#define OACC_DECLARE_CLAUSE_MASK \
19940 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19941 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19942 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19943 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19944 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19945 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
19946 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
19947 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
19948
19949static void
19950c_parser_oacc_declare (c_parser *parser)
19951{
19952 location_t pragma_loc = c_parser_peek_token (parser)->location;
19953 tree clauses, stmt, t, decl;
19954
19955 bool error = false;
19956
19957 c_parser_consume_pragma (parser);
19958
19959 clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
19960 where: "#pragma acc declare");
19961 if (!clauses)
19962 {
19963 error_at (pragma_loc,
19964 "no valid clauses specified in %<#pragma acc declare%>");
19965 return;
19966 }
19967
19968 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
19969 {
19970 location_t loc = OMP_CLAUSE_LOCATION (t);
19971 decl = OMP_CLAUSE_DECL (t);
19972 if (!DECL_P (decl))
19973 {
19974 error_at (loc, "array section in %<#pragma acc declare%>");
19975 error = true;
19976 continue;
19977 }
19978
19979 switch (OMP_CLAUSE_MAP_KIND (t))
19980 {
19981 case GOMP_MAP_FIRSTPRIVATE_POINTER:
19982 case GOMP_MAP_ALLOC:
19983 case GOMP_MAP_TO:
19984 case GOMP_MAP_FORCE_DEVICEPTR:
19985 case GOMP_MAP_DEVICE_RESIDENT:
19986 break;
19987
19988 case GOMP_MAP_LINK:
19989 if (!global_bindings_p ()
19990 && (TREE_STATIC (decl)
19991 || !DECL_EXTERNAL (decl)))
19992 {
19993 error_at (loc,
19994 "%qD must be a global variable in "
19995 "%<#pragma acc declare link%>",
19996 decl);
19997 error = true;
19998 continue;
19999 }
20000 break;
20001
20002 default:
20003 if (global_bindings_p ())
20004 {
20005 error_at (loc, "invalid OpenACC clause at file scope");
20006 error = true;
20007 continue;
20008 }
20009 if (DECL_EXTERNAL (decl))
20010 {
20011 error_at (loc,
20012 "invalid use of %<extern%> variable %qD "
20013 "in %<#pragma acc declare%>", decl);
20014 error = true;
20015 continue;
20016 }
20017 else if (TREE_PUBLIC (decl))
20018 {
20019 error_at (loc,
20020 "invalid use of %<global%> variable %qD "
20021 "in %<#pragma acc declare%>", decl);
20022 error = true;
20023 continue;
20024 }
20025 break;
20026 }
20027
20028 if (!c_check_in_current_scope (decl))
20029 {
20030 error_at (loc,
20031 "%qD must be a variable declared in the same scope as "
20032 "%<#pragma acc declare%>", decl);
20033 error = true;
20034 continue;
20035 }
20036
20037 if (lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (decl))
20038 || lookup_attribute (attr_name: "omp declare target link",
20039 DECL_ATTRIBUTES (decl)))
20040 {
20041 error_at (loc, "variable %qD used more than once with "
20042 "%<#pragma acc declare%>", decl);
20043 error = true;
20044 continue;
20045 }
20046
20047 if (!error)
20048 {
20049 tree id;
20050
20051 if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
20052 id = get_identifier ("omp declare target link");
20053 else
20054 id = get_identifier ("omp declare target");
20055
20056 DECL_ATTRIBUTES (decl)
20057 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
20058
20059 if (global_bindings_p ())
20060 {
20061 symtab_node *node = symtab_node::get (decl);
20062 if (node != NULL)
20063 {
20064 node->offloadable = 1;
20065 if (ENABLE_OFFLOADING)
20066 {
20067 g->have_offload = true;
20068 if (is_a <varpool_node *> (p: node))
20069 vec_safe_push (v&: offload_vars, obj: decl);
20070 }
20071 }
20072 }
20073 }
20074 }
20075
20076 if (error || global_bindings_p ())
20077 return;
20078
20079 stmt = make_node (OACC_DECLARE);
20080 TREE_TYPE (stmt) = void_type_node;
20081 OACC_DECLARE_CLAUSES (stmt) = clauses;
20082 SET_EXPR_LOCATION (stmt, pragma_loc);
20083
20084 add_stmt (stmt);
20085
20086 return;
20087}
20088
20089/* OpenACC 2.0:
20090 # pragma acc enter data oacc-enter-data-clause[optseq] new-line
20091
20092 or
20093
20094 # pragma acc exit data oacc-exit-data-clause[optseq] new-line
20095
20096
20097 LOC is the location of the #pragma token.
20098*/
20099
20100#define OACC_ENTER_DATA_CLAUSE_MASK \
20101 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20102 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20103 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
20104 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
20105 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
20106 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20107
20108#define OACC_EXIT_DATA_CLAUSE_MASK \
20109 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20110 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20111 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
20112 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
20113 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
20114 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
20115 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20116
20117static void
20118c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
20119{
20120 location_t loc = c_parser_peek_token (parser)->location;
20121 tree clauses, stmt;
20122 const char *p = "";
20123
20124 c_parser_consume_pragma (parser);
20125
20126 if (c_parser_next_token_is (parser, type: CPP_NAME))
20127 {
20128 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20129 c_parser_consume_token (parser);
20130 }
20131
20132 if (strcmp (s1: p, s2: "data") != 0)
20133 {
20134 error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
20135 enter ? "enter" : "exit");
20136 parser->error = true;
20137 c_parser_skip_to_pragma_eol (parser);
20138 return;
20139 }
20140
20141 if (enter)
20142 clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
20143 where: "#pragma acc enter data");
20144 else
20145 clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
20146 where: "#pragma acc exit data");
20147
20148 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
20149 {
20150 error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
20151 enter ? "enter" : "exit");
20152 return;
20153 }
20154
20155 stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
20156 TREE_TYPE (stmt) = void_type_node;
20157 OMP_STANDALONE_CLAUSES (stmt) = clauses;
20158 SET_EXPR_LOCATION (stmt, loc);
20159 add_stmt (stmt);
20160}
20161
20162
20163/* OpenACC 2.0:
20164 # pragma acc host_data oacc-data-clause[optseq] new-line
20165 structured-block
20166*/
20167
20168#define OACC_HOST_DATA_CLAUSE_MASK \
20169 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
20170 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20171 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
20172
20173static tree
20174c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
20175{
20176 tree stmt, clauses, block;
20177
20178 clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
20179 where: "#pragma acc host_data", finish_p: false);
20180 if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR))
20181 {
20182 error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
20183 return error_mark_node;
20184 }
20185 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
20186 block = c_begin_omp_parallel ();
20187 add_stmt (c_parser_omp_structured_block (parser, if_p));
20188 stmt = c_finish_oacc_host_data (loc, clauses, block);
20189 return stmt;
20190}
20191
20192
20193/* OpenACC 2.0:
20194
20195 # pragma acc loop oacc-loop-clause[optseq] new-line
20196 structured-block
20197
20198 LOC is the location of the #pragma token.
20199*/
20200
20201#define OACC_LOOP_CLAUSE_MASK \
20202 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
20203 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
20204 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
20205 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
20206 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
20207 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
20208 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
20209 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
20210 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
20211 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
20212static tree
20213c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
20214 omp_clause_mask mask, tree *cclauses, bool *if_p)
20215{
20216 bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
20217
20218 strcat (dest: p_name, src: " loop");
20219 mask |= OACC_LOOP_CLAUSE_MASK;
20220
20221 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
20222 /*finish_p=*/cclauses == NULL,
20223 /*target=*/target_p: is_parallel);
20224 if (cclauses)
20225 {
20226 clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
20227 if (*cclauses)
20228 *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
20229 if (clauses)
20230 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
20231 }
20232
20233 tree block = c_begin_compound_stmt (true);
20234 tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
20235 if_p);
20236 block = c_end_compound_stmt (loc, block, true);
20237 add_stmt (block);
20238
20239 return stmt;
20240}
20241
20242/* OpenACC 2.0:
20243 # pragma acc kernels oacc-kernels-clause[optseq] new-line
20244 structured-block
20245
20246 or
20247
20248 # pragma acc parallel oacc-parallel-clause[optseq] new-line
20249 structured-block
20250
20251 OpenACC 2.6:
20252
20253 # pragma acc serial oacc-serial-clause[optseq] new-line
20254 structured-block
20255
20256 LOC is the location of the #pragma token.
20257*/
20258
20259#define OACC_KERNELS_CLAUSE_MASK \
20260 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20261 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
20262 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
20263 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
20264 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
20265 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
20266 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
20267 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
20268 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20269 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
20270 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
20271 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
20272 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
20273 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
20274 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
20275 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20276
20277#define OACC_PARALLEL_CLAUSE_MASK \
20278 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20279 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
20280 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
20281 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
20282 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
20283 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
20284 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
20285 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
20286 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20287 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
20288 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
20289 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
20290 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
20291 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
20292 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
20293 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
20294 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
20295 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
20296 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20297
20298#define OACC_SERIAL_CLAUSE_MASK \
20299 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20300 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
20301 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
20302 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
20303 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
20304 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
20305 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
20306 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
20307 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20308 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
20309 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
20310 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
20311 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
20312 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
20313 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
20314 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20315
20316static tree
20317c_parser_oacc_compute (location_t loc, c_parser *parser,
20318 enum pragma_kind p_kind, char *p_name, bool *if_p)
20319{
20320 omp_clause_mask mask;
20321 enum tree_code code;
20322 switch (p_kind)
20323 {
20324 case PRAGMA_OACC_KERNELS:
20325 strcat (dest: p_name, src: " kernels");
20326 mask = OACC_KERNELS_CLAUSE_MASK;
20327 code = OACC_KERNELS;
20328 break;
20329 case PRAGMA_OACC_PARALLEL:
20330 strcat (dest: p_name, src: " parallel");
20331 mask = OACC_PARALLEL_CLAUSE_MASK;
20332 code = OACC_PARALLEL;
20333 break;
20334 case PRAGMA_OACC_SERIAL:
20335 strcat (dest: p_name, src: " serial");
20336 mask = OACC_SERIAL_CLAUSE_MASK;
20337 code = OACC_SERIAL;
20338 break;
20339 default:
20340 gcc_unreachable ();
20341 }
20342
20343 if (c_parser_next_token_is (parser, type: CPP_NAME))
20344 {
20345 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20346 if (strcmp (s1: p, s2: "loop") == 0)
20347 {
20348 c_parser_consume_token (parser);
20349 tree block = c_begin_omp_parallel ();
20350 tree clauses;
20351 c_parser_oacc_loop (loc, parser, p_name, mask, cclauses: &clauses, if_p);
20352 return c_finish_omp_construct (loc, code, block, clauses);
20353 }
20354 }
20355
20356 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
20357 /*finish_p=*/true,
20358 /*target=*/target_p: true);
20359
20360 tree block = c_begin_omp_parallel ();
20361 add_stmt (c_parser_omp_structured_block (parser, if_p));
20362
20363 return c_finish_omp_construct (loc, code, block, clauses);
20364}
20365
20366/* OpenACC 2.0:
20367 # pragma acc routine oacc-routine-clause[optseq] new-line
20368 function-definition
20369
20370 # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
20371*/
20372
20373#define OACC_ROUTINE_CLAUSE_MASK \
20374 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
20375 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
20376 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
20377 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
20378 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
20379
20380/* Parse an OpenACC routine directive. For named directives, we apply
20381 immediately to the named function. For unnamed ones we then parse
20382 a declaration or definition, which must be for a function. */
20383
20384static void
20385c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
20386{
20387 gcc_checking_assert (context == pragma_external);
20388
20389 oacc_routine_data data;
20390 data.error_seen = false;
20391 data.fndecl_seen = false;
20392 data.loc = c_parser_peek_token (parser)->location;
20393
20394 c_parser_consume_pragma (parser);
20395
20396 /* Look for optional '( name )'. */
20397 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
20398 {
20399 c_parser_consume_token (parser); /* '(' */
20400
20401 tree decl = NULL_TREE;
20402 c_token *name_token = c_parser_peek_token (parser);
20403 location_t name_loc = name_token->location;
20404 if (name_token->type == CPP_NAME
20405 && (name_token->id_kind == C_ID_ID
20406 || name_token->id_kind == C_ID_TYPENAME))
20407 {
20408 decl = lookup_name (name_token->value);
20409 if (!decl)
20410 error_at (name_loc,
20411 "%qE has not been declared", name_token->value);
20412 c_parser_consume_token (parser);
20413 }
20414 else
20415 c_parser_error (parser, gmsgid: "expected function name");
20416
20417 if (!decl
20418 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
20419 {
20420 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
20421 return;
20422 }
20423
20424 data.clauses
20425 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
20426 where: "#pragma acc routine");
20427 /* The clauses are in reverse order; fix that to make later diagnostic
20428 emission easier. */
20429 data.clauses = nreverse (data.clauses);
20430
20431 if (TREE_CODE (decl) != FUNCTION_DECL)
20432 {
20433 error_at (name_loc, "%qD does not refer to a function", decl);
20434 return;
20435 }
20436
20437 c_finish_oacc_routine (&data, decl, false);
20438 }
20439 else /* No optional '( name )'. */
20440 {
20441 data.clauses
20442 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
20443 where: "#pragma acc routine");
20444 /* The clauses are in reverse order; fix that to make later diagnostic
20445 emission easier. */
20446 data.clauses = nreverse (data.clauses);
20447
20448 /* Emit a helpful diagnostic if there's another pragma following this
20449 one. Also don't allow a static assertion declaration, as in the
20450 following we'll just parse a *single* "declaration or function
20451 definition", and the static assertion counts an one. */
20452 if (c_parser_next_token_is (parser, type: CPP_PRAGMA)
20453 || c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
20454 {
20455 error_at (data.loc,
20456 "%<#pragma acc routine%> not immediately followed by"
20457 " function declaration or definition");
20458 /* ..., and then just keep going. */
20459 return;
20460 }
20461
20462 /* We only have to consider the pragma_external case here. */
20463 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
20464 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
20465 {
20466 int ext = disable_extension_diagnostics ();
20467 do
20468 c_parser_consume_token (parser);
20469 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
20470 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
20471 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
20472 NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
20473 restore_extension_diagnostics (flags: ext);
20474 }
20475 else
20476 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
20477 NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
20478 }
20479}
20480
20481/* Finalize an OpenACC routine pragma, applying it to FNDECL.
20482 IS_DEFN is true if we're applying it to the definition. */
20483
20484static void
20485c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
20486 bool is_defn)
20487{
20488 /* Keep going if we're in error reporting mode. */
20489 if (data->error_seen
20490 || fndecl == error_mark_node)
20491 return;
20492
20493 if (data->fndecl_seen)
20494 {
20495 error_at (data->loc,
20496 "%<#pragma acc routine%> not immediately followed by"
20497 " a single function declaration or definition");
20498 data->error_seen = true;
20499 return;
20500 }
20501 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
20502 {
20503 error_at (data->loc,
20504 "%<#pragma acc routine%> not immediately followed by"
20505 " function declaration or definition");
20506 data->error_seen = true;
20507 return;
20508 }
20509
20510 int compatible
20511 = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
20512 "#pragma acc routine");
20513 if (compatible < 0)
20514 {
20515 data->error_seen = true;
20516 return;
20517 }
20518 if (compatible > 0)
20519 {
20520 }
20521 else
20522 {
20523 if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
20524 {
20525 error_at (data->loc,
20526 TREE_USED (fndecl)
20527 ? G_("%<#pragma acc routine%> must be applied before use")
20528 : G_("%<#pragma acc routine%> must be applied before"
20529 " definition"));
20530 data->error_seen = true;
20531 return;
20532 }
20533
20534 /* Set the routine's level of parallelism. */
20535 tree dims = oacc_build_routine_dims (clauses: data->clauses);
20536 oacc_replace_fn_attrib (fn: fndecl, dims);
20537
20538 /* Add an "omp declare target" attribute. */
20539 DECL_ATTRIBUTES (fndecl)
20540 = tree_cons (get_identifier ("omp declare target"),
20541 data->clauses, DECL_ATTRIBUTES (fndecl));
20542 }
20543
20544 /* Remember that we've used this "#pragma acc routine". */
20545 data->fndecl_seen = true;
20546}
20547
20548/* OpenACC 2.0:
20549 # pragma acc update oacc-update-clause[optseq] new-line
20550*/
20551
20552#define OACC_UPDATE_CLAUSE_MASK \
20553 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20554 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
20555 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
20556 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20557 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
20558 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
20559 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20560
20561static void
20562c_parser_oacc_update (c_parser *parser)
20563{
20564 location_t loc = c_parser_peek_token (parser)->location;
20565
20566 c_parser_consume_pragma (parser);
20567
20568 tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
20569 where: "#pragma acc update");
20570 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
20571 {
20572 error_at (loc,
20573 "%<#pragma acc update%> must contain at least one "
20574 "%<device%> or %<host%> or %<self%> clause");
20575 return;
20576 }
20577
20578 if (parser->error)
20579 return;
20580
20581 tree stmt = make_node (OACC_UPDATE);
20582 TREE_TYPE (stmt) = void_type_node;
20583 OACC_UPDATE_CLAUSES (stmt) = clauses;
20584 SET_EXPR_LOCATION (stmt, loc);
20585 add_stmt (stmt);
20586}
20587
20588/* OpenACC 2.0:
20589 # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
20590
20591 LOC is the location of the #pragma token.
20592*/
20593
20594#define OACC_WAIT_CLAUSE_MASK \
20595 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
20596
20597static tree
20598c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
20599{
20600 tree clauses, list = NULL_TREE, stmt = NULL_TREE;
20601
20602 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
20603 list = c_parser_oacc_wait_list (parser, clause_loc: loc, list);
20604
20605 strcpy (dest: p_name, src: " wait");
20606 clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, where: p_name);
20607 stmt = c_finish_oacc_wait (loc, list, clauses);
20608 add_stmt (stmt);
20609
20610 return stmt;
20611}
20612
20613struct c_omp_loc_tree
20614{
20615 location_t loc;
20616 tree var;
20617};
20618
20619/* Check whether the expression used in the allocator clause is declared or
20620 modified between the variable declaration and its allocate directive. */
20621static tree
20622c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
20623{
20624 tree var = ((struct c_omp_loc_tree *) data)->var;
20625 location_t loc = ((struct c_omp_loc_tree *) data)->loc;
20626 if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
20627 {
20628 if (linemap_location_before_p (set: line_table, DECL_SOURCE_LOCATION (var),
20629 DECL_SOURCE_LOCATION (*tp)))
20630 {
20631 error_at (loc, "variable %qD used in the %<allocator%> clause must "
20632 "be declared before %qD", *tp, var);
20633 inform (DECL_SOURCE_LOCATION (*tp), "declared here");
20634 inform (DECL_SOURCE_LOCATION (var),
20635 "to be allocated variable declared here");
20636 return *tp;
20637 }
20638 else
20639 {
20640 gcc_assert (cur_stmt_list
20641 && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
20642
20643 tree_stmt_iterator l = tsi_last (cur_stmt_list);
20644 while (!tsi_end_p (i: l))
20645 {
20646 if (linemap_location_before_p (set: line_table, EXPR_LOCATION (*l),
20647 DECL_SOURCE_LOCATION (var)))
20648 break;
20649 if (TREE_CODE (*l) == MODIFY_EXPR
20650 && TREE_OPERAND (*l, 0) == *tp)
20651 {
20652 error_at (loc,
20653 "variable %qD used in the %<allocator%> clause "
20654 "must not be modified between declaration of %qD "
20655 "and its %<allocate%> directive", *tp, var);
20656 inform (EXPR_LOCATION (*l), "modified here");
20657 inform (DECL_SOURCE_LOCATION (var),
20658 "to be allocated variable declared here");
20659 return *tp;
20660 }
20661 --l;
20662 }
20663 }
20664 }
20665 return NULL_TREE;
20666}
20667
20668/* OpenMP 5.x:
20669 # pragma omp allocate (list) clauses
20670
20671 OpenMP 5.0 clause:
20672 allocator (omp_allocator_handle_t expression)
20673
20674 OpenMP 5.1 additional clause:
20675 align (constant-expression)] */
20676
20677static void
20678c_parser_omp_allocate (c_parser *parser)
20679{
20680 tree alignment = NULL_TREE;
20681 tree allocator = NULL_TREE;
20682 c_parser_consume_pragma (parser);
20683 location_t loc = c_parser_peek_token (parser)->location;
20684 location_t allocator_loc = UNKNOWN_LOCATION;
20685 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE);
20686 do
20687 {
20688 if (c_parser_next_token_is (parser, type: CPP_COMMA)
20689 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
20690 c_parser_consume_token (parser);
20691 if (!c_parser_next_token_is (parser, type: CPP_NAME))
20692 break;
20693 matching_parens parens;
20694 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20695 c_parser_consume_token (parser);
20696 location_t expr_loc = c_parser_peek_token (parser)->location;
20697 if (strcmp (s1: "align", s2: p) != 0 && strcmp (s1: "allocator", s2: p) != 0)
20698 {
20699 error_at (c_parser_peek_token (parser)->location,
20700 "expected %<allocator%> or %<align%>");
20701 break;
20702 }
20703 if (!parens.require_open (parser))
20704 break;
20705
20706 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20707 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20708 expr_loc = c_parser_peek_token (parser)->location;
20709 if (expr.value == error_mark_node)
20710 ;
20711 else if (p[2] == 'i' && alignment)
20712 {
20713 error_at (expr_loc, "too many %qs clauses", "align");
20714 break;
20715 }
20716 else if (p[2] == 'i')
20717 {
20718 alignment = c_fully_fold (expr.value, false, NULL);
20719 if (TREE_CODE (alignment) != INTEGER_CST
20720 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
20721 || tree_int_cst_sgn (alignment) != 1
20722 || !integer_pow2p (alignment))
20723 {
20724 error_at (expr_loc, "%<align%> clause argument needs to be "
20725 "positive constant power of two integer "
20726 "expression");
20727 alignment = NULL_TREE;
20728 }
20729 }
20730 else if (allocator)
20731 {
20732 error_at (expr_loc, "too many %qs clauses", "allocator");
20733 break;
20734 }
20735 else
20736 {
20737 allocator = c_fully_fold (expr.value, false, NULL);
20738 allocator_loc = expr_loc;
20739 tree orig_type
20740 = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
20741 orig_type = TYPE_MAIN_VARIANT (orig_type);
20742 if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
20743 || TREE_CODE (orig_type) != ENUMERAL_TYPE
20744 || TYPE_NAME (orig_type)
20745 != get_identifier ("omp_allocator_handle_t"))
20746 {
20747 error_at (expr_loc,
20748 "%<allocator%> clause allocator expression has type "
20749 "%qT rather than %<omp_allocator_handle_t%>",
20750 TREE_TYPE (allocator));
20751 allocator = NULL_TREE;
20752 }
20753 }
20754 parens.skip_until_found_close (parser);
20755 } while (true);
20756 c_parser_skip_to_pragma_eol (parser);
20757
20758 c_mark_decl_jump_unsafe_in_current_scope ();
20759 for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
20760 {
20761 tree var = OMP_CLAUSE_DECL (c);
20762 if (TREE_CODE (var) == PARM_DECL)
20763 {
20764 error_at (OMP_CLAUSE_LOCATION (nl),
20765 "function parameter %qD may not appear as list item in an "
20766 "%<allocate%> directive", var);
20767 continue;
20768 }
20769 if (!c_check_in_current_scope (var))
20770 {
20771 error_at (OMP_CLAUSE_LOCATION (nl),
20772 "%<allocate%> directive must be in the same scope as %qD",
20773 var);
20774 inform (DECL_SOURCE_LOCATION (var), "declared here");
20775 continue;
20776 }
20777 if (lookup_attribute (attr_name: "omp allocate", DECL_ATTRIBUTES (var)))
20778 {
20779 error_at (OMP_CLAUSE_LOCATION (nl),
20780 "%qD already appeared as list item in an "
20781 "%<allocate%> directive", var);
20782 continue;
20783 }
20784 if (TREE_STATIC (var))
20785 {
20786 if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
20787 error_at (loc, "%<allocator%> clause required for "
20788 "static variable %qD", var);
20789 else if (allocator
20790 && (wi::to_widest (t: allocator) < 1
20791 || wi::to_widest (t: allocator) > 8))
20792 /* 8 = largest predefined memory allocator. */
20793 error_at (allocator_loc,
20794 "%<allocator%> clause requires a predefined allocator as "
20795 "%qD is static", var);
20796 else
20797 sorry_at (OMP_CLAUSE_LOCATION (nl),
20798 "%<#pragma omp allocate%> for static variables like "
20799 "%qD not yet supported", var);
20800 continue;
20801 }
20802 if (allocator)
20803 {
20804 struct c_omp_loc_tree data
20805 = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), .var: var};
20806 walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
20807 }
20808 DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
20809 build_tree_list (allocator, alignment),
20810 DECL_ATTRIBUTES (var));
20811 }
20812}
20813
20814/* OpenMP 2.5:
20815 # pragma omp atomic new-line
20816 expression-stmt
20817
20818 expression-stmt:
20819 x binop= expr | x++ | ++x | x-- | --x
20820 binop:
20821 +, *, -, /, &, ^, |, <<, >>
20822
20823 where x is an lvalue expression with scalar type.
20824
20825 OpenMP 3.1:
20826 # pragma omp atomic new-line
20827 update-stmt
20828
20829 # pragma omp atomic read new-line
20830 read-stmt
20831
20832 # pragma omp atomic write new-line
20833 write-stmt
20834
20835 # pragma omp atomic update new-line
20836 update-stmt
20837
20838 # pragma omp atomic capture new-line
20839 capture-stmt
20840
20841 # pragma omp atomic capture new-line
20842 capture-block
20843
20844 read-stmt:
20845 v = x
20846 write-stmt:
20847 x = expr
20848 update-stmt:
20849 expression-stmt | x = x binop expr
20850 capture-stmt:
20851 v = expression-stmt
20852 capture-block:
20853 { v = x; update-stmt; } | { update-stmt; v = x; }
20854
20855 OpenMP 4.0:
20856 update-stmt:
20857 expression-stmt | x = x binop expr | x = expr binop x
20858 capture-stmt:
20859 v = update-stmt
20860 capture-block:
20861 { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
20862
20863 OpenMP 5.1:
20864 # pragma omp atomic compare new-line
20865 conditional-update-atomic
20866
20867 # pragma omp atomic compare capture new-line
20868 conditional-update-capture-atomic
20869
20870 conditional-update-atomic:
20871 cond-expr-stmt | cond-update-stmt
20872 cond-expr-stmt:
20873 x = expr ordop x ? expr : x;
20874 x = x ordop expr ? expr : x;
20875 x = x == e ? d : x;
20876 cond-update-stmt:
20877 if (expr ordop x) { x = expr; }
20878 if (x ordop expr) { x = expr; }
20879 if (x == e) { x = d; }
20880 ordop:
20881 <, >
20882 conditional-update-capture-atomic:
20883 v = cond-expr-stmt
20884 { v = x; cond-expr-stmt }
20885 { cond-expr-stmt v = x; }
20886 { v = x; cond-update-stmt }
20887 { cond-update-stmt v = x; }
20888 if (x == e) { x = d; } else { v = x; }
20889 { r = x == e; if (r) { x = d; } }
20890 { r = x == e; if (r) { x = d; } else { v = x; } }
20891
20892 where x, r and v are lvalue expressions with scalar type,
20893 expr, e and d are expressions with scalar type and e might be
20894 the same as v.
20895
20896 LOC is the location of the #pragma token. */
20897
20898static void
20899c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
20900{
20901 tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
20902 tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
20903 tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
20904 enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
20905 enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
20906 struct c_expr expr;
20907 location_t eloc;
20908 bool structured_block = false;
20909 bool swapped = false;
20910 bool non_lvalue_p;
20911 tree clauses = NULL_TREE;
20912 bool capture = false;
20913 bool compare = false;
20914 bool weak = false;
20915 enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
20916 bool no_semicolon = false;
20917 bool extra_scope = false;
20918
20919 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
20920 {
20921 if (c_parser_next_token_is (parser, type: CPP_COMMA)
20922 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
20923 c_parser_consume_token (parser);
20924
20925 if (c_parser_next_token_is (parser, type: CPP_NAME))
20926 {
20927 const char *p
20928 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20929 location_t cloc = c_parser_peek_token (parser)->location;
20930 enum tree_code new_code = ERROR_MARK;
20931 enum omp_memory_order new_memory_order
20932 = OMP_MEMORY_ORDER_UNSPECIFIED;
20933 bool new_capture = false;
20934 bool new_compare = false;
20935 bool new_weak = false;
20936 enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
20937
20938 if (!strcmp (s1: p, s2: "read"))
20939 new_code = OMP_ATOMIC_READ;
20940 else if (!strcmp (s1: p, s2: "write"))
20941 new_code = NOP_EXPR;
20942 else if (!strcmp (s1: p, s2: "update"))
20943 new_code = OMP_ATOMIC;
20944 else if (openacc && !strcmp (s1: p, s2: "capture"))
20945 new_code = OMP_ATOMIC_CAPTURE_NEW;
20946 else if (openacc)
20947 {
20948 p = NULL;
20949 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
20950 "or %<capture%> clause");
20951 }
20952 else if (!strcmp (s1: p, s2: "capture"))
20953 new_capture = true;
20954 else if (!strcmp (s1: p, s2: "compare"))
20955 new_compare = true;
20956 else if (!strcmp (s1: p, s2: "weak"))
20957 new_weak = true;
20958 else if (!strcmp (s1: p, s2: "fail"))
20959 {
20960 matching_parens parens;
20961
20962 c_parser_consume_token (parser);
20963 if (!parens.require_open (parser))
20964 continue;
20965
20966 if (c_parser_next_token_is (parser, type: CPP_NAME))
20967 {
20968 const char *q
20969 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20970
20971 if (!strcmp (s1: q, s2: "seq_cst"))
20972 new_fail = OMP_MEMORY_ORDER_SEQ_CST;
20973 else if (!strcmp (s1: q, s2: "acquire"))
20974 new_fail = OMP_MEMORY_ORDER_ACQUIRE;
20975 else if (!strcmp (s1: q, s2: "relaxed"))
20976 new_fail = OMP_MEMORY_ORDER_RELAXED;
20977 }
20978
20979 if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
20980 {
20981 c_parser_consume_token (parser);
20982 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
20983 error_at (cloc, "too many %qs clauses", "fail");
20984 else
20985 fail = new_fail;
20986 }
20987 else
20988 c_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> "
20989 "or %<relaxed%>");
20990 parens.skip_until_found_close (parser);
20991 continue;
20992 }
20993 else if (!strcmp (s1: p, s2: "seq_cst"))
20994 new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
20995 else if (!strcmp (s1: p, s2: "acq_rel"))
20996 new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
20997 else if (!strcmp (s1: p, s2: "release"))
20998 new_memory_order = OMP_MEMORY_ORDER_RELEASE;
20999 else if (!strcmp (s1: p, s2: "acquire"))
21000 new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
21001 else if (!strcmp (s1: p, s2: "relaxed"))
21002 new_memory_order = OMP_MEMORY_ORDER_RELAXED;
21003 else if (!strcmp (s1: p, s2: "hint"))
21004 {
21005 c_parser_consume_token (parser);
21006 clauses = c_parser_omp_clause_hint (parser, list: clauses);
21007 continue;
21008 }
21009 else
21010 {
21011 p = NULL;
21012 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
21013 "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
21014 "%<seq_cst%>, %<acq_rel%>, %<release%>, "
21015 "%<relaxed%> or %<hint%> clause");
21016 }
21017 if (p)
21018 {
21019 if (new_code != ERROR_MARK)
21020 {
21021 /* OpenACC permits 'update capture'. */
21022 if (openacc
21023 && code == OMP_ATOMIC
21024 && new_code == OMP_ATOMIC_CAPTURE_NEW)
21025 code = new_code;
21026 else if (code != ERROR_MARK)
21027 error_at (cloc, "too many atomic clauses");
21028 else
21029 code = new_code;
21030 }
21031 else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
21032 {
21033 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
21034 error_at (cloc, "too many memory order clauses");
21035 else
21036 memory_order = new_memory_order;
21037 }
21038 else if (new_capture)
21039 {
21040 if (capture)
21041 error_at (cloc, "too many %qs clauses", "capture");
21042 else
21043 capture = true;
21044 }
21045 else if (new_compare)
21046 {
21047 if (compare)
21048 error_at (cloc, "too many %qs clauses", "compare");
21049 else
21050 compare = true;
21051 }
21052 else if (new_weak)
21053 {
21054 if (weak)
21055 error_at (cloc, "too many %qs clauses", "weak");
21056 else
21057 weak = true;
21058 }
21059 c_parser_consume_token (parser);
21060 continue;
21061 }
21062 }
21063 break;
21064 }
21065 c_parser_skip_to_pragma_eol (parser);
21066
21067 if (code == ERROR_MARK)
21068 code = OMP_ATOMIC;
21069 if (capture)
21070 {
21071 if (code != OMP_ATOMIC)
21072 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
21073 "clauses", "capture");
21074 else
21075 code = OMP_ATOMIC_CAPTURE_NEW;
21076 }
21077 if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
21078 {
21079 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
21080 "clauses", "compare");
21081 compare = false;
21082 }
21083 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
21084 {
21085 error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
21086 fail = OMP_MEMORY_ORDER_UNSPECIFIED;
21087 }
21088 if (weak && !compare)
21089 {
21090 error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
21091 weak = false;
21092 }
21093 if (openacc)
21094 memory_order = OMP_MEMORY_ORDER_RELAXED;
21095 else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
21096 {
21097 omp_requires_mask
21098 = (enum omp_requires) (omp_requires_mask
21099 | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
21100 switch ((enum omp_memory_order)
21101 (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
21102 {
21103 case OMP_MEMORY_ORDER_UNSPECIFIED:
21104 case OMP_MEMORY_ORDER_RELAXED:
21105 memory_order = OMP_MEMORY_ORDER_RELAXED;
21106 break;
21107 case OMP_MEMORY_ORDER_SEQ_CST:
21108 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
21109 break;
21110 case OMP_MEMORY_ORDER_ACQUIRE:
21111 if (code == NOP_EXPR) /* atomic write */
21112 {
21113 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
21114 "%<acquire%> clause implicitly provided by a "
21115 "%<requires%> directive");
21116 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
21117 }
21118 else
21119 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
21120 break;
21121 case OMP_MEMORY_ORDER_RELEASE:
21122 if (code == OMP_ATOMIC_READ)
21123 {
21124 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
21125 "%<release%> clause implicitly provided by a "
21126 "%<requires%> directive");
21127 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
21128 }
21129 else
21130 memory_order = OMP_MEMORY_ORDER_RELEASE;
21131 break;
21132 case OMP_MEMORY_ORDER_ACQ_REL:
21133 switch (code)
21134 {
21135 case OMP_ATOMIC_READ:
21136 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
21137 break;
21138 case NOP_EXPR: /* atomic write */
21139 memory_order = OMP_MEMORY_ORDER_RELEASE;
21140 break;
21141 default:
21142 memory_order = OMP_MEMORY_ORDER_ACQ_REL;
21143 break;
21144 }
21145 break;
21146 default:
21147 gcc_unreachable ();
21148 }
21149 }
21150 else
21151 switch (code)
21152 {
21153 case OMP_ATOMIC_READ:
21154 if (memory_order == OMP_MEMORY_ORDER_RELEASE)
21155 {
21156 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
21157 "%<release%> clause");
21158 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
21159 }
21160 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
21161 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
21162 break;
21163 case NOP_EXPR: /* atomic write */
21164 if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
21165 {
21166 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
21167 "%<acquire%> clause");
21168 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
21169 }
21170 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
21171 memory_order = OMP_MEMORY_ORDER_RELEASE;
21172 break;
21173 default:
21174 break;
21175 }
21176 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
21177 memory_order
21178 = (enum omp_memory_order) (memory_order
21179 | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
21180
21181 switch (code)
21182 {
21183 case OMP_ATOMIC_READ:
21184 case NOP_EXPR: /* atomic write */
21185 v = c_parser_cast_expression (parser, NULL).value;
21186 non_lvalue_p = !lvalue_p (v);
21187 v = c_fully_fold (v, false, NULL, true);
21188 if (v == error_mark_node)
21189 goto saw_error;
21190 if (non_lvalue_p)
21191 v = non_lvalue (v);
21192 loc = c_parser_peek_token (parser)->location;
21193 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
21194 goto saw_error;
21195 if (code == NOP_EXPR)
21196 {
21197 lhs = c_parser_expression (parser).value;
21198 lhs = c_fully_fold (lhs, false, NULL);
21199 if (lhs == error_mark_node)
21200 goto saw_error;
21201 }
21202 else
21203 {
21204 lhs = c_parser_cast_expression (parser, NULL).value;
21205 non_lvalue_p = !lvalue_p (lhs);
21206 lhs = c_fully_fold (lhs, false, NULL, true);
21207 if (lhs == error_mark_node)
21208 goto saw_error;
21209 if (non_lvalue_p)
21210 lhs = non_lvalue (lhs);
21211 }
21212 if (code == NOP_EXPR)
21213 {
21214 /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
21215 opcode. */
21216 code = OMP_ATOMIC;
21217 rhs = lhs;
21218 lhs = v;
21219 v = NULL_TREE;
21220 }
21221 goto done;
21222 case OMP_ATOMIC_CAPTURE_NEW:
21223 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
21224 {
21225 c_parser_consume_token (parser);
21226 structured_block = true;
21227 }
21228 else if (compare
21229 && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
21230 break;
21231 else
21232 {
21233 v = c_parser_cast_expression (parser, NULL).value;
21234 non_lvalue_p = !lvalue_p (v);
21235 v = c_fully_fold (v, false, NULL, true);
21236 if (v == error_mark_node)
21237 goto saw_error;
21238 if (non_lvalue_p)
21239 v = non_lvalue (v);
21240 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
21241 goto saw_error;
21242 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
21243 {
21244 eloc = c_parser_peek_token (parser)->location;
21245 error_at (eloc, "expected expression");
21246 goto saw_error;
21247 }
21248 }
21249 break;
21250 default:
21251 break;
21252 }
21253
21254 /* For structured_block case we don't know yet whether
21255 old or new x should be captured. */
21256restart:
21257 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
21258 {
21259 c_parser_consume_token (parser);
21260
21261 matching_parens parens;
21262 if (!parens.require_open (parser))
21263 goto saw_error;
21264 eloc = c_parser_peek_token (parser)->location;
21265 c_expr cmp_expr;
21266 if (r)
21267 {
21268 cmp_expr = c_parser_cast_expression (parser, NULL);
21269 cmp_expr = default_function_array_conversion (eloc, cmp_expr);
21270 }
21271 else
21272 cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
21273 parens.skip_until_found_close (parser);
21274 if (cmp_expr.value == error_mark_node)
21275 goto saw_error;
21276 if (r)
21277 {
21278 if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
21279 goto bad_if;
21280 cmp_expr.value = rhs1;
21281 rhs1 = NULL_TREE;
21282 gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
21283 }
21284 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
21285 ;
21286 else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
21287 {
21288 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
21289 "expected %<==%> comparison in %<if%> condition");
21290 goto saw_error;
21291 }
21292 else if (TREE_CODE (cmp_expr.value) != GT_EXPR
21293 && TREE_CODE (cmp_expr.value) != LT_EXPR)
21294 {
21295 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
21296 "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
21297 "condition");
21298 goto saw_error;
21299 }
21300 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
21301 goto saw_error;
21302
21303 extra_scope = true;
21304 eloc = c_parser_peek_token (parser)->location;
21305 expr = c_parser_cast_expression (parser, NULL);
21306 lhs = expr.value;
21307 expr = default_function_array_conversion (eloc, expr);
21308 unfolded_lhs = expr.value;
21309 lhs = c_fully_fold (lhs, false, NULL, true);
21310 orig_lhs = lhs;
21311 if (lhs == error_mark_node)
21312 goto saw_error;
21313 if (!lvalue_p (unfolded_lhs))
21314 lhs = non_lvalue (lhs);
21315 if (!c_parser_next_token_is (parser, type: CPP_EQ))
21316 {
21317 c_parser_error (parser, gmsgid: "expected %<=%>");
21318 goto saw_error;
21319 }
21320 c_parser_consume_token (parser);
21321 eloc = c_parser_peek_token (parser)->location;
21322 expr = c_parser_expr_no_commas (parser, NULL);
21323 rhs1 = expr.value;
21324
21325 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
21326 goto saw_error;
21327
21328 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
21329 goto saw_error;
21330
21331 extra_scope = false;
21332 no_semicolon = true;
21333
21334 if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
21335 {
21336 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
21337 {
21338 opcode = COND_EXPR;
21339 rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
21340 false, NULL, true);
21341 rhs1 = c_fully_fold (rhs1, false, NULL, true);
21342 }
21343 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
21344 {
21345 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
21346 ? MIN_EXPR : MAX_EXPR);
21347 rhs = c_fully_fold (rhs1, false, NULL, true);
21348 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
21349 false, NULL, true);
21350 }
21351 else
21352 goto bad_if;
21353 }
21354 else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
21355 goto bad_if;
21356 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
21357 && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
21358 {
21359 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
21360 ? MAX_EXPR : MIN_EXPR);
21361 rhs = c_fully_fold (rhs1, false, NULL, true);
21362 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
21363 false, NULL, true);
21364 }
21365 else
21366 {
21367 bad_if:
21368 c_parser_error (parser,
21369 gmsgid: "invalid form of %<#pragma omp atomic compare%>");
21370 goto saw_error;
21371 }
21372
21373 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
21374 {
21375 if (code != OMP_ATOMIC_CAPTURE_NEW
21376 || (structured_block && r == NULL_TREE)
21377 || TREE_CODE (cmp_expr.value) != EQ_EXPR)
21378 {
21379 eloc = c_parser_peek_token (parser)->location;
21380 error_at (eloc, "unexpected %<else%>");
21381 goto saw_error;
21382 }
21383
21384 c_parser_consume_token (parser);
21385
21386 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
21387 goto saw_error;
21388
21389 extra_scope = true;
21390 v = c_parser_cast_expression (parser, NULL).value;
21391 non_lvalue_p = !lvalue_p (v);
21392 v = c_fully_fold (v, false, NULL, true);
21393 if (v == error_mark_node)
21394 goto saw_error;
21395 if (non_lvalue_p)
21396 v = non_lvalue (v);
21397 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
21398 goto saw_error;
21399
21400 expr = c_parser_expr_no_commas (parser, NULL);
21401
21402 if (!c_tree_equal (expr.value, unfolded_lhs))
21403 goto bad_if;
21404
21405 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
21406 goto saw_error;
21407
21408 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
21409 goto saw_error;
21410
21411 extra_scope = false;
21412 code = OMP_ATOMIC_CAPTURE_OLD;
21413 if (r == NULL_TREE)
21414 /* Signal to c_finish_omp_atomic that in
21415 if (x == e) { x = d; } else { v = x; }
21416 case the store to v should be conditional. */
21417 r = void_list_node;
21418 }
21419 else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
21420 {
21421 c_parser_require_keyword (parser, keyword: RID_ELSE, msgid: "expected %<else%>");
21422 goto saw_error;
21423 }
21424 else if (code == OMP_ATOMIC_CAPTURE_NEW
21425 && r != NULL_TREE
21426 && v == NULL_TREE)
21427 code = OMP_ATOMIC;
21428 goto stmt_done;
21429 }
21430 eloc = c_parser_peek_token (parser)->location;
21431 expr = c_parser_cast_expression (parser, NULL);
21432 lhs = expr.value;
21433 expr = default_function_array_conversion (eloc, expr);
21434 unfolded_lhs = expr.value;
21435 lhs = c_fully_fold (lhs, false, NULL, true);
21436 orig_lhs = lhs;
21437 switch (TREE_CODE (lhs))
21438 {
21439 invalid_compare:
21440 error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
21441 /* FALLTHRU */
21442 case ERROR_MARK:
21443 saw_error:
21444 c_parser_skip_to_end_of_block_or_statement (parser);
21445 if (extra_scope && c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21446 c_parser_consume_token (parser);
21447 if (structured_block)
21448 {
21449 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21450 c_parser_consume_token (parser);
21451 else if (code == OMP_ATOMIC_CAPTURE_NEW)
21452 {
21453 c_parser_skip_to_end_of_block_or_statement (parser);
21454 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21455 c_parser_consume_token (parser);
21456 }
21457 }
21458 return;
21459
21460 case POSTINCREMENT_EXPR:
21461 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
21462 code = OMP_ATOMIC_CAPTURE_OLD;
21463 /* FALLTHROUGH */
21464 case PREINCREMENT_EXPR:
21465 lhs = TREE_OPERAND (lhs, 0);
21466 unfolded_lhs = NULL_TREE;
21467 opcode = PLUS_EXPR;
21468 rhs = integer_one_node;
21469 if (compare)
21470 goto invalid_compare;
21471 break;
21472
21473 case POSTDECREMENT_EXPR:
21474 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
21475 code = OMP_ATOMIC_CAPTURE_OLD;
21476 /* FALLTHROUGH */
21477 case PREDECREMENT_EXPR:
21478 lhs = TREE_OPERAND (lhs, 0);
21479 unfolded_lhs = NULL_TREE;
21480 opcode = MINUS_EXPR;
21481 rhs = integer_one_node;
21482 if (compare)
21483 goto invalid_compare;
21484 break;
21485
21486 case COMPOUND_EXPR:
21487 if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
21488 && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
21489 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
21490 && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
21491 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
21492 (TREE_OPERAND (lhs, 1), 0), 0))))
21493 /* Undo effects of boolean_increment for post {in,de}crement. */
21494 lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
21495 /* FALLTHRU */
21496 case MODIFY_EXPR:
21497 if (TREE_CODE (lhs) == MODIFY_EXPR
21498 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
21499 {
21500 /* Undo effects of boolean_increment. */
21501 if (integer_onep (TREE_OPERAND (lhs, 1)))
21502 {
21503 /* This is pre or post increment. */
21504 rhs = TREE_OPERAND (lhs, 1);
21505 lhs = TREE_OPERAND (lhs, 0);
21506 unfolded_lhs = NULL_TREE;
21507 opcode = NOP_EXPR;
21508 if (code == OMP_ATOMIC_CAPTURE_NEW
21509 && !structured_block
21510 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
21511 code = OMP_ATOMIC_CAPTURE_OLD;
21512 if (compare)
21513 goto invalid_compare;
21514 break;
21515 }
21516 if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
21517 && TREE_OPERAND (lhs, 0)
21518 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
21519 {
21520 /* This is pre or post decrement. */
21521 rhs = TREE_OPERAND (lhs, 1);
21522 lhs = TREE_OPERAND (lhs, 0);
21523 unfolded_lhs = NULL_TREE;
21524 opcode = NOP_EXPR;
21525 if (code == OMP_ATOMIC_CAPTURE_NEW
21526 && !structured_block
21527 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
21528 code = OMP_ATOMIC_CAPTURE_OLD;
21529 if (compare)
21530 goto invalid_compare;
21531 break;
21532 }
21533 }
21534 /* FALLTHRU */
21535 default:
21536 if (!lvalue_p (unfolded_lhs))
21537 lhs = non_lvalue (lhs);
21538 if (compare && !c_parser_next_token_is (parser, type: CPP_EQ))
21539 {
21540 c_parser_error (parser, gmsgid: "expected %<=%>");
21541 goto saw_error;
21542 }
21543 switch (c_parser_peek_token (parser)->type)
21544 {
21545 case CPP_MULT_EQ:
21546 opcode = MULT_EXPR;
21547 break;
21548 case CPP_DIV_EQ:
21549 opcode = TRUNC_DIV_EXPR;
21550 break;
21551 case CPP_PLUS_EQ:
21552 opcode = PLUS_EXPR;
21553 break;
21554 case CPP_MINUS_EQ:
21555 opcode = MINUS_EXPR;
21556 break;
21557 case CPP_LSHIFT_EQ:
21558 opcode = LSHIFT_EXPR;
21559 break;
21560 case CPP_RSHIFT_EQ:
21561 opcode = RSHIFT_EXPR;
21562 break;
21563 case CPP_AND_EQ:
21564 opcode = BIT_AND_EXPR;
21565 break;
21566 case CPP_OR_EQ:
21567 opcode = BIT_IOR_EXPR;
21568 break;
21569 case CPP_XOR_EQ:
21570 opcode = BIT_XOR_EXPR;
21571 break;
21572 case CPP_EQ:
21573 c_parser_consume_token (parser);
21574 eloc = c_parser_peek_token (parser)->location;
21575 expr = c_parser_expr_no_commas (parser, NULL, omp_atomic_lhs: unfolded_lhs);
21576 rhs1 = expr.value;
21577 switch (TREE_CODE (rhs1))
21578 {
21579 case MULT_EXPR:
21580 case TRUNC_DIV_EXPR:
21581 case RDIV_EXPR:
21582 case PLUS_EXPR:
21583 case MINUS_EXPR:
21584 case LSHIFT_EXPR:
21585 case RSHIFT_EXPR:
21586 case BIT_AND_EXPR:
21587 case BIT_IOR_EXPR:
21588 case BIT_XOR_EXPR:
21589 if (compare)
21590 break;
21591 if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
21592 {
21593 opcode = TREE_CODE (rhs1);
21594 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21595 true);
21596 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
21597 true);
21598 goto stmt_done;
21599 }
21600 if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
21601 {
21602 opcode = TREE_CODE (rhs1);
21603 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
21604 true);
21605 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21606 true);
21607 swapped = !commutative_tree_code (opcode);
21608 goto stmt_done;
21609 }
21610 break;
21611 case COND_EXPR:
21612 if (!compare)
21613 break;
21614 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
21615 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
21616 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
21617 break;
21618 if (!TREE_OPERAND (rhs1, 1))
21619 break;
21620 if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
21621 break;
21622 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
21623 unfolded_lhs))
21624 {
21625 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
21626 {
21627 opcode = COND_EXPR;
21628 rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21629 0), 1),
21630 false, NULL, true);
21631 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
21632 NULL, true);
21633 goto stmt_done;
21634 }
21635 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
21636 TREE_OPERAND (rhs1, 1)))
21637 {
21638 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
21639 ? MIN_EXPR : MAX_EXPR);
21640 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21641 true);
21642 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21643 0), 0),
21644 false, NULL, true);
21645 goto stmt_done;
21646 }
21647 }
21648 else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
21649 break;
21650 else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
21651 unfolded_lhs))
21652 {
21653 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
21654 TREE_OPERAND (rhs1, 1)))
21655 {
21656 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
21657 ? MAX_EXPR : MIN_EXPR);
21658 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21659 true);
21660 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21661 0), 1),
21662 false, NULL, true);
21663 goto stmt_done;
21664 }
21665 }
21666 break;
21667 case EQ_EXPR:
21668 if (!compare
21669 || code != OMP_ATOMIC_CAPTURE_NEW
21670 || !structured_block
21671 || v
21672 || r)
21673 break;
21674 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
21675 && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
21676 {
21677 r = lhs;
21678 lhs = NULL_TREE;
21679 c_parser_consume_token (parser);
21680 goto restart;
21681 }
21682 break;
21683 case ERROR_MARK:
21684 goto saw_error;
21685 default:
21686 break;
21687 }
21688 if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
21689 {
21690 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
21691 {
21692 code = OMP_ATOMIC_CAPTURE_OLD;
21693 v = lhs;
21694 lhs = NULL_TREE;
21695 expr = default_function_array_read_conversion (eloc, expr);
21696 unfolded_lhs1 = expr.value;
21697 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
21698 rhs1 = NULL_TREE;
21699 c_parser_consume_token (parser);
21700 goto restart;
21701 }
21702 if (structured_block && !compare)
21703 {
21704 opcode = NOP_EXPR;
21705 expr = default_function_array_read_conversion (eloc, expr);
21706 rhs = c_fully_fold (expr.value, false, NULL, true);
21707 rhs1 = NULL_TREE;
21708 goto stmt_done;
21709 }
21710 }
21711 c_parser_error (parser, gmsgid: "invalid form of %<#pragma omp atomic%>");
21712 goto saw_error;
21713 default:
21714 c_parser_error (parser,
21715 gmsgid: "invalid operator for %<#pragma omp atomic%>");
21716 goto saw_error;
21717 }
21718
21719 /* Arrange to pass the location of the assignment operator to
21720 c_finish_omp_atomic. */
21721 loc = c_parser_peek_token (parser)->location;
21722 c_parser_consume_token (parser);
21723 eloc = c_parser_peek_token (parser)->location;
21724 expr = c_parser_expression (parser);
21725 expr = default_function_array_read_conversion (eloc, expr);
21726 rhs = expr.value;
21727 rhs = c_fully_fold (rhs, false, NULL, true);
21728 break;
21729 }
21730stmt_done:
21731 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
21732 {
21733 if (!no_semicolon
21734 && !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
21735 goto saw_error;
21736 no_semicolon = false;
21737 v = c_parser_cast_expression (parser, NULL).value;
21738 non_lvalue_p = !lvalue_p (v);
21739 v = c_fully_fold (v, false, NULL, true);
21740 if (v == error_mark_node)
21741 goto saw_error;
21742 if (non_lvalue_p)
21743 v = non_lvalue (v);
21744 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
21745 goto saw_error;
21746 eloc = c_parser_peek_token (parser)->location;
21747 expr = c_parser_cast_expression (parser, NULL);
21748 lhs1 = expr.value;
21749 expr = default_function_array_read_conversion (eloc, expr);
21750 unfolded_lhs1 = expr.value;
21751 lhs1 = c_fully_fold (lhs1, false, NULL, true);
21752 if (lhs1 == error_mark_node)
21753 goto saw_error;
21754 if (!lvalue_p (unfolded_lhs1))
21755 lhs1 = non_lvalue (lhs1);
21756 }
21757 if (structured_block)
21758 {
21759 if (!no_semicolon)
21760 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21761 c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>");
21762 }
21763done:
21764 if (weak && opcode != COND_EXPR)
21765 {
21766 error_at (loc, "%<weak%> clause requires atomic equality comparison");
21767 weak = false;
21768 }
21769 if (unfolded_lhs && unfolded_lhs1
21770 && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
21771 {
21772 error ("%<#pragma omp atomic capture%> uses two different "
21773 "expressions for memory");
21774 stmt = error_mark_node;
21775 }
21776 else
21777 stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
21778 swapped, memory_order, weak);
21779 if (stmt != error_mark_node)
21780 add_stmt (stmt);
21781
21782 if (!structured_block && !no_semicolon)
21783 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21784}
21785
21786
21787/* OpenMP 2.5:
21788 # pragma omp barrier new-line
21789*/
21790
21791static void
21792c_parser_omp_barrier (c_parser *parser)
21793{
21794 location_t loc = c_parser_peek_token (parser)->location;
21795 c_parser_consume_pragma (parser);
21796 c_parser_skip_to_pragma_eol (parser);
21797
21798 c_finish_omp_barrier (loc);
21799}
21800
21801/* OpenMP 2.5:
21802 # pragma omp critical [(name)] new-line
21803 structured-block
21804
21805 OpenMP 4.5:
21806 # pragma omp critical [(name) [hint(expression)]] new-line
21807
21808 LOC is the location of the #pragma itself. */
21809
21810#define OMP_CRITICAL_CLAUSE_MASK \
21811 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
21812
21813static tree
21814c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
21815{
21816 tree stmt, name = NULL_TREE, clauses = NULL_TREE;
21817
21818 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
21819 {
21820 c_parser_consume_token (parser);
21821 if (c_parser_next_token_is (parser, type: CPP_NAME))
21822 {
21823 name = c_parser_peek_token (parser)->value;
21824 c_parser_consume_token (parser);
21825 c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
21826 }
21827 else
21828 c_parser_error (parser, gmsgid: "expected identifier");
21829
21830 if (c_parser_next_token_is (parser, type: CPP_COMMA)
21831 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
21832 c_parser_consume_token (parser);
21833 }
21834 clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
21835 where: "#pragma omp critical");
21836 stmt = c_parser_omp_structured_block (parser, if_p);
21837 return c_finish_omp_critical (loc, stmt, name, clauses);
21838}
21839
21840/* OpenMP 5.0:
21841 # pragma omp depobj ( depobj ) depobj-clause new-line
21842
21843 depobj-clause:
21844 depend (dependence-type : locator)
21845 destroy
21846 update (dependence-type)
21847
21848 OpenMP 5.2 additionally:
21849 destroy ( depobj )
21850
21851 dependence-type:
21852 in
21853 out
21854 inout
21855 mutexinout */
21856
21857static void
21858c_parser_omp_depobj (c_parser *parser)
21859{
21860 location_t loc = c_parser_peek_token (parser)->location;
21861 c_parser_consume_pragma (parser);
21862 matching_parens parens;
21863 if (!parens.require_open (parser))
21864 {
21865 c_parser_skip_to_pragma_eol (parser);
21866 return;
21867 }
21868
21869 tree depobj = c_parser_expr_no_commas (parser, NULL).value;
21870 if (depobj != error_mark_node)
21871 {
21872 if (!lvalue_p (depobj))
21873 {
21874 error_at (EXPR_LOC_OR_LOC (depobj, loc),
21875 "%<depobj%> expression is not lvalue expression");
21876 depobj = error_mark_node;
21877 }
21878 else
21879 {
21880 tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
21881 depobj, false);
21882 if (addr == error_mark_node)
21883 depobj = error_mark_node;
21884 else
21885 depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
21886 addr, RO_UNARY_STAR);
21887 }
21888 }
21889
21890 parens.skip_until_found_close (parser);
21891 tree clause = NULL_TREE;
21892 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
21893 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21894 c_parser_consume_token (parser);
21895 location_t c_loc = c_parser_peek_token (parser)->location;
21896 if (c_parser_next_token_is (parser, type: CPP_NAME))
21897 {
21898 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21899
21900 c_parser_consume_token (parser);
21901 if (!strcmp (s1: "depend", s2: p))
21902 {
21903 clause = c_parser_omp_clause_depend (parser, NULL_TREE);
21904 clause = c_finish_omp_clauses (clause, C_ORT_OMP);
21905 if (!clause)
21906 clause = error_mark_node;
21907 }
21908 else if (!strcmp (s1: "destroy", s2: p))
21909 {
21910 matching_parens c_parens;
21911 kind = OMP_CLAUSE_DEPEND_LAST;
21912 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
21913 && c_parens.require_open (parser))
21914 {
21915 tree destobj = c_parser_expr_no_commas (parser, NULL).value;
21916 if (!lvalue_p (destobj))
21917 error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
21918 "%<destroy%> expression is not lvalue expression");
21919 else if (depobj != error_mark_node
21920 && !operand_equal_p (destobj, depobj,
21921 flags: OEP_MATCH_SIDE_EFFECTS
21922 | OEP_LEXICOGRAPHIC))
21923 warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
21924 "the %<destroy%> expression %qE should be the same "
21925 "as the %<depobj%> argument %qE", destobj, depobj);
21926 c_parens.skip_until_found_close (parser);
21927 }
21928 }
21929 else if (!strcmp (s1: "update", s2: p))
21930 {
21931 matching_parens c_parens;
21932 if (c_parens.require_open (parser))
21933 {
21934 location_t c2_loc = c_parser_peek_token (parser)->location;
21935 if (c_parser_next_token_is (parser, type: CPP_NAME))
21936 {
21937 const char *p2
21938 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21939
21940 c_parser_consume_token (parser);
21941 if (!strcmp (s1: "in", s2: p2))
21942 kind = OMP_CLAUSE_DEPEND_IN;
21943 else if (!strcmp (s1: "out", s2: p2))
21944 kind = OMP_CLAUSE_DEPEND_OUT;
21945 else if (!strcmp (s1: "inout", s2: p2))
21946 kind = OMP_CLAUSE_DEPEND_INOUT;
21947 else if (!strcmp (s1: "mutexinoutset", s2: p2))
21948 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
21949 else if (!strcmp (s1: "inoutset", s2: p2))
21950 kind = OMP_CLAUSE_DEPEND_INOUTSET;
21951 }
21952 if (kind == OMP_CLAUSE_DEPEND_INVALID)
21953 {
21954 clause = error_mark_node;
21955 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
21956 "%<mutexinoutset%> or %<inoutset%>");
21957 }
21958 c_parens.skip_until_found_close (parser);
21959 }
21960 else
21961 clause = error_mark_node;
21962 }
21963 }
21964 if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
21965 {
21966 clause = error_mark_node;
21967 error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
21968 }
21969 c_parser_skip_to_pragma_eol (parser);
21970
21971 c_finish_omp_depobj (loc, depobj, kind, clause);
21972}
21973
21974
21975/* OpenMP 2.5:
21976 # pragma omp flush flush-vars[opt] new-line
21977
21978 flush-vars:
21979 ( variable-list )
21980
21981 OpenMP 5.0:
21982 # pragma omp flush memory-order-clause new-line */
21983
21984static void
21985c_parser_omp_flush (c_parser *parser)
21986{
21987 location_t loc = c_parser_peek_token (parser)->location;
21988 c_parser_consume_pragma (parser);
21989 enum memmodel mo = MEMMODEL_LAST;
21990 if (c_parser_next_token_is (parser, type: CPP_COMMA)
21991 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
21992 c_parser_consume_token (parser);
21993 if (c_parser_next_token_is (parser, type: CPP_NAME))
21994 {
21995 const char *p
21996 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21997
21998 if (!strcmp (s1: p, s2: "seq_cst"))
21999 mo = MEMMODEL_SEQ_CST;
22000 else if (!strcmp (s1: p, s2: "acq_rel"))
22001 mo = MEMMODEL_ACQ_REL;
22002 else if (!strcmp (s1: p, s2: "release"))
22003 mo = MEMMODEL_RELEASE;
22004 else if (!strcmp (s1: p, s2: "acquire"))
22005 mo = MEMMODEL_ACQUIRE;
22006 else
22007 error_at (c_parser_peek_token (parser)->location,
22008 "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
22009 "%<acquire%>");
22010 c_parser_consume_token (parser);
22011 }
22012 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
22013 {
22014 if (mo != MEMMODEL_LAST)
22015 error_at (c_parser_peek_token (parser)->location,
22016 "%<flush%> list specified together with memory order "
22017 "clause");
22018 c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
22019 }
22020 else if (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
22021 c_parser_error (parser, gmsgid: "expected %<(%> or end of line");
22022 c_parser_skip_to_pragma_eol (parser);
22023
22024 c_finish_omp_flush (loc, mo);
22025}
22026
22027/* Return true if next tokens contain a standard attribute that contains
22028 omp::directive (DIRECTIVE). */
22029
22030static bool
22031c_parser_omp_section_scan (c_parser *parser, const char *directive,
22032 bool tentative)
22033{
22034 if (!c_parser_nth_token_starts_std_attributes (parser, n: 1))
22035 return false;
22036 unsigned int n = 3;
22037 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
22038 return false;
22039 c_token *token = c_parser_peek_nth_token_raw (parser, n);
22040 if (token->type != CPP_CLOSE_SQUARE)
22041 return false;
22042 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
22043 if (token->type != CPP_CLOSE_SQUARE)
22044 return false;
22045 if (n < 9)
22046 return false;
22047 if (c_parser_peek_nth_token_raw (parser, n: 3)->type == CPP_NAME
22048 && c_parser_peek_nth_token_raw (parser, n: 4)->type == CPP_OPEN_PAREN
22049 && c_parser_peek_nth_token_raw (parser, n: 5)->type == CPP_NAME)
22050 {
22051 tree first = c_parser_peek_nth_token_raw (parser, n: 3)->value;
22052 tree second = c_parser_peek_nth_token_raw (parser, n: 5)->value;
22053 if (strcmp (IDENTIFIER_POINTER (first), s2: "directive")
22054 && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__"))
22055 return false;
22056 if (strcmp (IDENTIFIER_POINTER (second), s2: directive))
22057 return false;
22058 }
22059 if (tentative)
22060 return true;
22061 location_t first_loc = c_parser_peek_token (parser)->location;
22062 location_t last_loc = c_parser_peek_nth_token_raw (parser, n: n + 1)->location;
22063 location_t middle_loc = UNKNOWN_LOCATION;
22064 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
22065 bool seen = false;
22066 int cnt = 0;
22067 for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
22068 if (is_attribute_namespace_p (attr_ns: "omp", attr)
22069 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (attr)))
22070 {
22071 for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
22072 {
22073 tree d = TREE_VALUE (a);
22074 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
22075 c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
22076 cnt++;
22077 if (first->type == CPP_NAME
22078 && strcmp (IDENTIFIER_POINTER (first->value),
22079 s2: directive) == 0)
22080 {
22081 seen = true;
22082 if (middle_loc == UNKNOWN_LOCATION)
22083 middle_loc = first->location;
22084 }
22085 }
22086 }
22087 if (!seen)
22088 return false;
22089 if (cnt != 1 || TREE_CHAIN (std_attrs))
22090 {
22091 error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc),
22092 "%<[[omp::directive(%s)]]%> must be the only specified "
22093 "attribute on a statement", directive);
22094 return false;
22095 }
22096 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
22097 return true;
22098}
22099
22100/* Parse an OpenMP structured block sequence. KIND is the corresponding
22101 separating directive. */
22102
22103static tree
22104c_parser_omp_structured_block_sequence (c_parser *parser,
22105 enum pragma_kind kind)
22106{
22107 tree stmt = push_stmt_list ();
22108 c_parser_statement (parser, NULL);
22109 do
22110 {
22111 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
22112 break;
22113 if (c_parser_next_token_is (parser, type: CPP_EOF))
22114 break;
22115
22116 if (kind != PRAGMA_NONE
22117 && c_parser_peek_token (parser)->pragma_kind == kind)
22118 break;
22119
22120 if (kind != PRAGMA_NONE
22121 && c_parser_omp_section_scan (parser,
22122 directive: kind == PRAGMA_OMP_SCAN
22123 ? "scan" : "section", tentative: false))
22124 break;
22125
22126 c_parser_statement (parser, NULL);
22127 }
22128 while (1);
22129 return pop_stmt_list (stmt);
22130}
22131
22132/* OpenMP 5.0:
22133
22134 scan-loop-body:
22135 { structured-block scan-directive structured-block } */
22136
22137static void
22138c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
22139{
22140 tree substmt;
22141 location_t loc;
22142 tree clauses = NULL_TREE;
22143 bool found_scan = false;
22144
22145 loc = c_parser_peek_token (parser)->location;
22146 if (!open_brace_parsed
22147 && !c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
22148 {
22149 /* Avoid skipping until the end of the block. */
22150 parser->error = false;
22151 return;
22152 }
22153
22154 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
22155 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN);
22156 else
22157 {
22158 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
22159 "%<#pragma omp scan%> with zero preceding executable "
22160 "statements");
22161 substmt = build_empty_stmt (loc);
22162 }
22163 substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
22164 SET_EXPR_LOCATION (substmt, loc);
22165 add_stmt (substmt);
22166
22167 loc = c_parser_peek_token (parser)->location;
22168 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
22169 {
22170 enum omp_clause_code clause = OMP_CLAUSE_ERROR;
22171 found_scan = true;
22172
22173 c_parser_consume_pragma (parser);
22174
22175 if (c_parser_next_token_is (parser, type: CPP_COMMA))
22176 c_parser_consume_token (parser);
22177
22178 if (c_parser_next_token_is (parser, type: CPP_NAME))
22179 {
22180 const char *p
22181 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22182 if (strcmp (s1: p, s2: "inclusive") == 0)
22183 clause = OMP_CLAUSE_INCLUSIVE;
22184 else if (strcmp (s1: p, s2: "exclusive") == 0)
22185 clause = OMP_CLAUSE_EXCLUSIVE;
22186 }
22187 if (clause != OMP_CLAUSE_ERROR)
22188 {
22189 c_parser_consume_token (parser);
22190 clauses = c_parser_omp_var_list_parens (parser, kind: clause, NULL_TREE);
22191 }
22192 else
22193 c_parser_error (parser, gmsgid: "expected %<inclusive%> or "
22194 "%<exclusive%> clause");
22195 c_parser_skip_to_pragma_eol (parser);
22196 }
22197 else
22198 error ("expected %<#pragma omp scan%>");
22199
22200 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
22201 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
22202 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE);
22203 else
22204 {
22205 if (found_scan)
22206 warning_at (loc, OPT_Wopenmp,
22207 "%<#pragma omp scan%> with zero succeeding executable "
22208 "statements");
22209 substmt = build_empty_stmt (loc);
22210 }
22211 substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
22212 SET_EXPR_LOCATION (substmt, loc);
22213 add_stmt (substmt);
22214
22215 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
22216 msgid: "expected %<}%>");
22217}
22218
22219
22220/* This function parses a single level of a loop nest, invoking itself
22221 recursively if necessary.
22222
22223 loop-nest :: for (...) loop-body
22224 loop-body :: loop-nest
22225 | { [intervening-code] loop-body [intervening-code] }
22226 | final-loop-body
22227 intervening-code :: structured-block-sequence
22228 final-loop-body :: structured-block
22229
22230 For a collapsed loop nest, only a single OMP_FOR is built, pulling out
22231 all the iterator information from the inner loops into the
22232 parser->omp_for_parse_state structure.
22233
22234 The iterator decl, init, cond, and incr are stored in vectors.
22235
22236 Initialization code for iterator variables is collected into
22237 parser->omp_for_parse_state->pre_body and ends up inserted directly
22238 into the OMP_FOR structure. */
22239
22240static tree
22241c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
22242{
22243 tree decl, cond, incr, init;
22244 tree body = NULL_TREE;
22245 matching_parens parens;
22246 bool moreloops;
22247 unsigned char save_in_statement;
22248 tree loop_scope;
22249 location_t loc;
22250 struct omp_for_parse_data *omp_for_parse_state
22251 = parser->omp_for_parse_state;
22252 gcc_assert (omp_for_parse_state);
22253 int depth = omp_for_parse_state->depth;
22254
22255 /* We have already matched the FOR token but not consumed it yet. */
22256 loc = c_parser_peek_token (parser)->location;
22257 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
22258 c_parser_consume_token (parser);
22259
22260 /* Forbid break/continue in the loop initializer, condition, and
22261 increment expressions. */
22262 save_in_statement = in_statement;
22263 in_statement = IN_OMP_BLOCK;
22264
22265 /* We are not in intervening code now. */
22266 omp_for_parse_state->in_intervening_code = false;
22267
22268 if (!parens.require_open (parser))
22269 {
22270 omp_for_parse_state->fail = true;
22271 return NULL_TREE;
22272 }
22273
22274 /* An implicit scope block surrounds each level of FOR loop, for
22275 declarations of iteration variables at this loop depth. */
22276 loop_scope = c_begin_compound_stmt (true);
22277
22278 /* Parse the initialization declaration or expression. */
22279 if (c_parser_next_tokens_start_declaration (parser))
22280 {
22281 /* This is a declaration, which must be added to the pre_body code. */
22282 tree this_pre_body = push_stmt_list ();
22283 c_in_omp_for = true;
22284 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true);
22285 c_in_omp_for = false;
22286 this_pre_body = pop_stmt_list (this_pre_body);
22287 append_to_statement_list_force (this_pre_body,
22288 &(omp_for_parse_state->pre_body));
22289 decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
22290 if (decl == NULL)
22291 goto error_init;
22292 if (DECL_INITIAL (decl) == error_mark_node)
22293 decl = error_mark_node;
22294 init = decl;
22295 }
22296 else if (c_parser_next_token_is (parser, type: CPP_NAME)
22297 && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
22298 {
22299 struct c_expr decl_exp;
22300 struct c_expr init_exp;
22301 location_t init_loc;
22302
22303 decl_exp = c_parser_postfix_expression (parser);
22304 decl = decl_exp.value;
22305
22306 c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>");
22307
22308 init_loc = c_parser_peek_token (parser)->location;
22309 init_exp = c_parser_expr_no_commas (parser, NULL);
22310 init_exp = default_function_array_read_conversion (init_loc,
22311 init_exp);
22312 c_in_omp_for = true;
22313 init = build_modify_expr (init_loc, decl, decl_exp.original_type,
22314 NOP_EXPR, init_loc, init_exp.value,
22315 init_exp.original_type);
22316 c_in_omp_for = false;
22317 init = c_process_expr_stmt (init_loc, init);
22318
22319 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
22320 }
22321 else
22322 {
22323 error_init:
22324 c_parser_error (parser,
22325 gmsgid: "expected iteration declaration or initialization");
22326 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
22327 msgid: "expected %<)%>");
22328 omp_for_parse_state->fail = true;
22329 goto parse_next;
22330 }
22331
22332 /* Parse the loop condition. */
22333 cond = NULL_TREE;
22334 if (c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
22335 {
22336 location_t cond_loc = c_parser_peek_token (parser)->location;
22337 c_in_omp_for = true;
22338 struct c_expr cond_expr
22339 = c_parser_binary_expression (parser, NULL, NULL_TREE);
22340 c_in_omp_for = false;
22341
22342 cond = cond_expr.value;
22343 cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
22344 switch (cond_expr.original_code)
22345 {
22346 case GT_EXPR:
22347 case GE_EXPR:
22348 case LT_EXPR:
22349 case LE_EXPR:
22350 break;
22351 case NE_EXPR:
22352 if (omp_for_parse_state->code != OACC_LOOP)
22353 break;
22354 /* FALLTHRU. */
22355 default:
22356 /* Can't be cond = error_mark_node, because we want to preserve
22357 the location until c_finish_omp_for. */
22358 cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
22359 break;
22360 }
22361 protected_set_expr_location (cond, cond_loc);
22362 }
22363 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
22364
22365 /* Parse the increment expression. */
22366 incr = NULL_TREE;
22367 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
22368 {
22369 location_t incr_loc = c_parser_peek_token (parser)->location;
22370
22371 incr = c_process_expr_stmt (incr_loc,
22372 c_parser_expression (parser).value);
22373 }
22374 parens.skip_until_found_close (parser);
22375
22376 if (decl == NULL || decl == error_mark_node || init == error_mark_node)
22377 omp_for_parse_state->fail = true;
22378 else
22379 {
22380 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
22381 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
22382 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
22383 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
22384 }
22385
22386parse_next:
22387 moreloops = depth < omp_for_parse_state->count - 1;
22388 omp_for_parse_state->want_nested_loop = moreloops;
22389 if (moreloops && c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
22390 {
22391 omp_for_parse_state->depth++;
22392 body = c_parser_omp_loop_nest (parser, if_p);
22393 omp_for_parse_state->depth--;
22394 }
22395 else if (moreloops && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
22396 {
22397 /* This is the open brace in the loop-body grammar production. Rather
22398 than trying to special-case braces, just parse it as a compound
22399 statement and handle the nested loop-body case there. Note that
22400 when we see a further open brace inside the compound statement
22401 loop-body, we don't know whether it is the start of intervening
22402 code that is a compound statement, or a level of braces
22403 surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
22404 bit to ensure we have only one nested loop at each level. */
22405 omp_for_parse_state->in_intervening_code = true;
22406 body = c_parser_compound_statement (parser, NULL);
22407 omp_for_parse_state->in_intervening_code = false;
22408 if (omp_for_parse_state->want_nested_loop)
22409 {
22410 /* We have already parsed the whole loop body and not found a
22411 nested loop. */
22412 error_at (omp_for_parse_state->for_loc,
22413 "not enough nested loops");
22414 omp_for_parse_state->fail = true;
22415 }
22416 if_p = NULL;
22417 }
22418 else
22419 {
22420 /* This is the final-loop-body case in the grammar: we have
22421 something that is not a FOR and not an open brace. */
22422 if (moreloops)
22423 {
22424 /* If we were expecting a nested loop, give an error and mark
22425 that parsing has failed, and try to recover by parsing the
22426 body as regular code without further collapsing. */
22427 error_at (omp_for_parse_state->for_loc,
22428 "not enough nested loops");
22429 omp_for_parse_state->fail = true;
22430 }
22431 in_statement = IN_OMP_FOR;
22432 parser->omp_for_parse_state = NULL;
22433 body = push_stmt_list ();
22434 if (omp_for_parse_state->inscan)
22435 c_parser_omp_scan_loop_body (parser, open_brace_parsed: false);
22436 else
22437 add_stmt (c_parser_c99_block_statement (parser, if_p));
22438 body = pop_stmt_list (body);
22439 parser->omp_for_parse_state = omp_for_parse_state;
22440 }
22441 in_statement = save_in_statement;
22442 omp_for_parse_state->want_nested_loop = false;
22443 omp_for_parse_state->in_intervening_code = true;
22444
22445 /* Pop and return the implicit scope surrounding this level of loop.
22446 If the iteration variable at this depth was bound in the for loop,
22447 pull out and save the binding. Later in c_parser_omp_for_loop,
22448 these bindings will be moved to the scope surrounding the entire
22449 OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
22450 we have already resolved all references to the iteration variable
22451 in its true scope. */
22452 add_stmt (body);
22453 body = c_end_compound_stmt (loc, loop_scope, true);
22454 if (decl && TREE_CODE (body) == BIND_EXPR)
22455 {
22456 tree t = BIND_EXPR_VARS (body);
22457 tree prev = NULL_TREE, next = NULL_TREE;
22458 while (t)
22459 {
22460 next = DECL_CHAIN (t);
22461 if (t == decl)
22462 {
22463 if (prev)
22464 DECL_CHAIN (prev) = next;
22465 else
22466 {
22467 BIND_EXPR_VARS (body) = next;
22468 BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
22469 }
22470 DECL_CHAIN (t) = omp_for_parse_state->bindings;
22471 omp_for_parse_state->bindings = t;
22472 break;
22473 }
22474 else
22475 {
22476 prev = t;
22477 t = next;
22478 }
22479 }
22480 if (BIND_EXPR_VARS (body) == NULL_TREE)
22481 body = BIND_EXPR_BODY (body);
22482 }
22483
22484 return body;
22485}
22486
22487/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
22488 The real trick here is to determine the loop control variable early
22489 so that we can push a new decl if necessary to make it private.
22490 LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
22491 respectively. */
22492
22493static tree
22494c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
22495 tree clauses, tree *cclauses, bool *if_p)
22496{
22497 tree body, stmt, cl;
22498 tree ret = NULL_TREE;
22499 tree ordered_cl = NULL_TREE;
22500 int i, collapse = 1, ordered = 0, count;
22501 bool tiling = false;
22502 bool inscan = false;
22503 struct omp_for_parse_data data;
22504 struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
22505
22506 for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
22507 if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
22508 collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
22509 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
22510 {
22511 tiling = true;
22512 collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
22513 }
22514 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
22515 && OMP_CLAUSE_ORDERED_EXPR (cl))
22516 {
22517 ordered_cl = cl;
22518 ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
22519 }
22520 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
22521 && OMP_CLAUSE_REDUCTION_INSCAN (cl)
22522 && (code == OMP_SIMD || code == OMP_FOR))
22523 inscan = true;
22524
22525 if (ordered && ordered < collapse)
22526 {
22527 error_at (OMP_CLAUSE_LOCATION (ordered_cl),
22528 "%<ordered%> clause parameter is less than %<collapse%>");
22529 OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
22530 = build_int_cst (NULL_TREE, collapse);
22531 ordered = collapse;
22532 }
22533
22534 gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
22535 count = ordered ? ordered : collapse;
22536
22537 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
22538 {
22539 c_parser_error (parser, gmsgid: "for statement expected");
22540 return NULL;
22541 }
22542
22543 /* Initialize parse state for recursive descent. */
22544 data.declv = make_tree_vec (count);
22545 data.initv = make_tree_vec (count);
22546 data.condv = make_tree_vec (count);
22547 data.incrv = make_tree_vec (count);
22548 data.pre_body = NULL_TREE;;
22549 data.bindings = NULL_TREE;
22550 data.for_loc = c_parser_peek_token (parser)->location;
22551 data.count = count;
22552 data.depth = 0;
22553 data.want_nested_loop = true;
22554 data.ordered = ordered > 0;
22555 data.in_intervening_code = false;
22556 data.perfect_nesting_fail = false;
22557 data.fail = false;
22558 data.inscan = inscan;
22559 data.saw_intervening_code = false;
22560 data.code = code;
22561 parser->omp_for_parse_state = &data;
22562
22563 body = c_parser_omp_loop_nest (parser, if_p);
22564
22565 /* Add saved bindings for iteration variables that were declared in
22566 the nested for loop to the scope surrounding the entire loop. */
22567 for (tree t = data.bindings; t; )
22568 {
22569 tree n = TREE_CHAIN (t);
22570 TREE_CHAIN (t) = NULL_TREE;
22571 pushdecl (t);
22572 t = n;
22573 }
22574
22575 /* Only bother calling c_finish_omp_for if we haven't already generated
22576 an error from the initialization parsing. */
22577 if (!data.fail)
22578 {
22579 c_in_omp_for = true;
22580 stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
22581 data.condv, data.incrv,
22582 body, data.pre_body, true);
22583 c_in_omp_for = false;
22584
22585 /* Check for iterators appearing in lb, b or incr expressions. */
22586 if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
22587 stmt = NULL_TREE;
22588
22589 /* Check for errors involving lb/ub/incr expressions referencing
22590 variables declared in intervening code. */
22591 if (data.saw_intervening_code
22592 && !c_omp_check_loop_binding_exprs (stmt, NULL))
22593 stmt = NULL_TREE;
22594
22595 if (stmt)
22596 {
22597 add_stmt (stmt);
22598
22599 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
22600 {
22601 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
22602 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
22603 tree decl = TREE_OPERAND (init, 0);
22604 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
22605 gcc_assert (COMPARISON_CLASS_P (cond));
22606 gcc_assert (TREE_OPERAND (cond, 0) == decl);
22607
22608 tree op0 = TREE_OPERAND (init, 1);
22609 if (!OMP_FOR_NON_RECTANGULAR (stmt)
22610 || TREE_CODE (op0) != TREE_VEC)
22611 TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
22612 else
22613 {
22614 TREE_VEC_ELT (op0, 1)
22615 = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
22616 TREE_VEC_ELT (op0, 2)
22617 = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
22618 }
22619
22620 tree op1 = TREE_OPERAND (cond, 1);
22621 if (!OMP_FOR_NON_RECTANGULAR (stmt)
22622 || TREE_CODE (op1) != TREE_VEC)
22623 TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
22624 else
22625 {
22626 TREE_VEC_ELT (op1, 1)
22627 = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
22628 TREE_VEC_ELT (op1, 2)
22629 = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
22630 }
22631 }
22632
22633 if (cclauses != NULL
22634 && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
22635 {
22636 tree *c;
22637 for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
22638 if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
22639 && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
22640 c = &OMP_CLAUSE_CHAIN (*c);
22641 else
22642 {
22643 for (i = 0; i < count; i++)
22644 if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
22645 break;
22646 if (i == count)
22647 c = &OMP_CLAUSE_CHAIN (*c);
22648 else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
22649 {
22650 error_at (loc,
22651 "iteration variable %qD should not be firstprivate",
22652 OMP_CLAUSE_DECL (*c));
22653 *c = OMP_CLAUSE_CHAIN (*c);
22654 }
22655 else
22656 {
22657 /* Move lastprivate (decl) clause to
22658 OMP_FOR_CLAUSES. */
22659 tree l = *c;
22660 *c = OMP_CLAUSE_CHAIN (*c);
22661 if (code == OMP_SIMD)
22662 {
22663 OMP_CLAUSE_CHAIN (l)
22664 = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22665 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
22666 }
22667 else
22668 {
22669 OMP_CLAUSE_CHAIN (l) = clauses;
22670 clauses = l;
22671 }
22672 }
22673 }
22674 }
22675 OMP_FOR_CLAUSES (stmt) = clauses;
22676 }
22677 ret = stmt;
22678 }
22679
22680 parser->omp_for_parse_state = save_data;
22681 return ret;
22682}
22683
22684/* Helper function for OpenMP parsing, split clauses and call
22685 finish_omp_clauses on each of the set of clauses afterwards. */
22686
22687static void
22688omp_split_clauses (location_t loc, enum tree_code code,
22689 omp_clause_mask mask, tree clauses, tree *cclauses)
22690{
22691 int i;
22692 c_omp_split_clauses (loc, code, mask, clauses, cclauses);
22693 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
22694 if (cclauses[i])
22695 cclauses[i] = c_finish_omp_clauses (cclauses[i],
22696 i == C_OMP_CLAUSE_SPLIT_TARGET
22697 ? C_ORT_OMP_TARGET : C_ORT_OMP);
22698}
22699
22700/* OpenMP 5.0:
22701 #pragma omp loop loop-clause[optseq] new-line
22702 for-loop
22703
22704 LOC is the location of the #pragma token.
22705*/
22706
22707#define OMP_LOOP_CLAUSE_MASK \
22708 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22709 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22710 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22711 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22712 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
22713 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22714
22715static tree
22716c_parser_omp_loop (location_t loc, c_parser *parser,
22717 char *p_name, omp_clause_mask mask, tree *cclauses,
22718 bool *if_p)
22719{
22720 tree block, clauses, ret;
22721
22722 strcat (dest: p_name, src: " loop");
22723 mask |= OMP_LOOP_CLAUSE_MASK;
22724
22725 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22726 if (cclauses)
22727 {
22728 omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses);
22729 clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
22730 }
22731
22732 block = c_begin_compound_stmt (true);
22733 ret = c_parser_omp_for_loop (loc, parser, code: OMP_LOOP, clauses, cclauses, if_p);
22734 block = c_end_compound_stmt (loc, block, true);
22735 add_stmt (block);
22736
22737 return ret;
22738}
22739
22740/* OpenMP 4.0:
22741 #pragma omp simd simd-clause[optseq] new-line
22742 for-loop
22743
22744 LOC is the location of the #pragma token.
22745*/
22746
22747#define OMP_SIMD_CLAUSE_MASK \
22748 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
22749 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
22750 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
22751 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
22752 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22753 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22754 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22755 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22756 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
22757 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
22758 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22759
22760static tree
22761c_parser_omp_simd (location_t loc, c_parser *parser,
22762 char *p_name, omp_clause_mask mask, tree *cclauses,
22763 bool *if_p)
22764{
22765 tree block, clauses, ret;
22766
22767 strcat (dest: p_name, src: " simd");
22768 mask |= OMP_SIMD_CLAUSE_MASK;
22769
22770 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22771 if (cclauses)
22772 {
22773 omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses);
22774 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
22775 }
22776
22777 block = c_begin_compound_stmt (true);
22778 ret = c_parser_omp_for_loop (loc, parser, code: OMP_SIMD, clauses, cclauses, if_p);
22779 block = c_end_compound_stmt (loc, block, true);
22780 add_stmt (block);
22781
22782 return ret;
22783}
22784
22785/* OpenMP 2.5:
22786 #pragma omp for for-clause[optseq] new-line
22787 for-loop
22788
22789 OpenMP 4.0:
22790 #pragma omp for simd for-simd-clause[optseq] new-line
22791 for-loop
22792
22793 LOC is the location of the #pragma token.
22794*/
22795
22796#define OMP_FOR_CLAUSE_MASK \
22797 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22798 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22799 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22800 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
22801 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22802 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
22803 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
22804 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22805 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
22806 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22807 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22808
22809static tree
22810c_parser_omp_for (location_t loc, c_parser *parser,
22811 char *p_name, omp_clause_mask mask, tree *cclauses,
22812 bool *if_p)
22813{
22814 tree block, clauses, ret;
22815
22816 strcat (dest: p_name, src: " for");
22817 mask |= OMP_FOR_CLAUSE_MASK;
22818 /* parallel for{, simd} disallows nowait clause, but for
22819 target {teams distribute ,}parallel for{, simd} it should be accepted. */
22820 if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
22821 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
22822 /* Composite distribute parallel for{, simd} disallows ordered clause. */
22823 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
22824 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
22825
22826 if (c_parser_next_token_is (parser, type: CPP_NAME))
22827 {
22828 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22829
22830 if (strcmp (s1: p, s2: "simd") == 0)
22831 {
22832 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22833 if (cclauses == NULL)
22834 cclauses = cclauses_buf;
22835
22836 c_parser_consume_token (parser);
22837 if (!flag_openmp) /* flag_openmp_simd */
22838 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
22839 if_p);
22840 block = c_begin_compound_stmt (true);
22841 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
22842 block = c_end_compound_stmt (loc, block, true);
22843 if (ret == NULL_TREE)
22844 return ret;
22845 ret = make_node (OMP_FOR);
22846 TREE_TYPE (ret) = void_type_node;
22847 OMP_FOR_BODY (ret) = block;
22848 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22849 SET_EXPR_LOCATION (ret, loc);
22850 add_stmt (ret);
22851 return ret;
22852 }
22853 }
22854 if (!flag_openmp) /* flag_openmp_simd */
22855 {
22856 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22857 return NULL_TREE;
22858 }
22859
22860 /* Composite distribute parallel for disallows linear clause. */
22861 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
22862 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
22863
22864 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22865 if (cclauses)
22866 {
22867 omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses);
22868 clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22869 }
22870
22871 block = c_begin_compound_stmt (true);
22872 ret = c_parser_omp_for_loop (loc, parser, code: OMP_FOR, clauses, cclauses, if_p);
22873 block = c_end_compound_stmt (loc, block, true);
22874 add_stmt (block);
22875
22876 return ret;
22877}
22878
22879static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
22880 omp_clause_mask, tree *, bool *);
22881
22882/* OpenMP 2.5:
22883 # pragma omp master new-line
22884 structured-block
22885
22886 LOC is the location of the #pragma token.
22887*/
22888
22889static tree
22890c_parser_omp_master (location_t loc, c_parser *parser,
22891 char *p_name, omp_clause_mask mask, tree *cclauses,
22892 bool *if_p)
22893{
22894 tree block, clauses, ret;
22895
22896 strcat (dest: p_name, src: " master");
22897
22898 if (c_parser_next_token_is (parser, type: CPP_NAME))
22899 {
22900 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22901
22902 if (strcmp (s1: p, s2: "taskloop") == 0)
22903 {
22904 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22905 if (cclauses == NULL)
22906 cclauses = cclauses_buf;
22907
22908 c_parser_consume_token (parser);
22909 if (!flag_openmp) /* flag_openmp_simd */
22910 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22911 if_p);
22912 block = c_begin_compound_stmt (true);
22913 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22914 if_p);
22915 block = c_end_compound_stmt (loc, block, true);
22916 if (ret == NULL_TREE)
22917 return ret;
22918 ret = c_finish_omp_master (loc, block);
22919 OMP_MASTER_COMBINED (ret) = 1;
22920 return ret;
22921 }
22922 }
22923 if (!flag_openmp) /* flag_openmp_simd */
22924 {
22925 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22926 return NULL_TREE;
22927 }
22928
22929 if (cclauses)
22930 {
22931 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: false);
22932 omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses);
22933 }
22934 else
22935 c_parser_skip_to_pragma_eol (parser);
22936
22937 return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
22938 if_p));
22939}
22940
22941/* OpenMP 5.1:
22942 # pragma omp masked masked-clauses new-line
22943 structured-block
22944
22945 LOC is the location of the #pragma token.
22946*/
22947
22948#define OMP_MASKED_CLAUSE_MASK \
22949 (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
22950
22951static tree
22952c_parser_omp_masked (location_t loc, c_parser *parser,
22953 char *p_name, omp_clause_mask mask, tree *cclauses,
22954 bool *if_p)
22955{
22956 tree block, clauses, ret;
22957
22958 strcat (dest: p_name, src: " masked");
22959 mask |= OMP_MASKED_CLAUSE_MASK;
22960
22961 if (c_parser_next_token_is (parser, type: CPP_NAME))
22962 {
22963 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22964
22965 if (strcmp (s1: p, s2: "taskloop") == 0)
22966 {
22967 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22968 if (cclauses == NULL)
22969 cclauses = cclauses_buf;
22970
22971 c_parser_consume_token (parser);
22972 if (!flag_openmp) /* flag_openmp_simd */
22973 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22974 if_p);
22975 block = c_begin_compound_stmt (true);
22976 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22977 if_p);
22978 block = c_end_compound_stmt (loc, block, true);
22979 if (ret == NULL_TREE)
22980 return ret;
22981 ret = c_finish_omp_masked (loc, block,
22982 cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
22983 OMP_MASKED_COMBINED (ret) = 1;
22984 return ret;
22985 }
22986 }
22987 if (!flag_openmp) /* flag_openmp_simd */
22988 {
22989 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22990 return NULL_TREE;
22991 }
22992
22993 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22994 if (cclauses)
22995 {
22996 omp_split_clauses (loc, code: OMP_MASKED, mask, clauses, cclauses);
22997 clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
22998 }
22999
23000 return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
23001 if_p),
23002 clauses);
23003}
23004
23005/* OpenMP 2.5:
23006 # pragma omp ordered new-line
23007 structured-block
23008
23009 OpenMP 4.5:
23010 # pragma omp ordered ordered-clauses new-line
23011 structured-block
23012
23013 # pragma omp ordered depend-clauses new-line
23014
23015 OpenMP 5.2
23016 # pragma omp ordered doacross-clauses new-line */
23017
23018#define OMP_ORDERED_CLAUSE_MASK \
23019 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
23020 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
23021
23022#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
23023 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23024 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
23025
23026static bool
23027c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
23028 bool *if_p)
23029{
23030 location_t loc = c_parser_peek_token (parser)->location;
23031 c_parser_consume_pragma (parser);
23032
23033 if (context != pragma_stmt && context != pragma_compound)
23034 {
23035 c_parser_error (parser, gmsgid: "expected declaration specifiers");
23036 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23037 return false;
23038 }
23039
23040 int n = 1;
23041 if (c_parser_next_token_is (parser, type: CPP_COMMA))
23042 n = 2;
23043
23044 if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
23045 {
23046 const char *p
23047 = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
23048
23049 if (!strcmp (s1: "depend", s2: p) || !strcmp (s1: "doacross", s2: p))
23050 {
23051 if (!flag_openmp) /* flag_openmp_simd */
23052 {
23053 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23054 return false;
23055 }
23056 if (context == pragma_stmt)
23057 {
23058 error_at (loc,
23059 "%<#pragma omp ordered%> with %qs clause may "
23060 "only be used in compound statements", p);
23061 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23062 return true;
23063 }
23064
23065 tree clauses
23066 = c_parser_omp_all_clauses (parser,
23067 OMP_ORDERED_DEPEND_CLAUSE_MASK,
23068 where: "#pragma omp ordered");
23069 c_finish_omp_ordered (loc, clauses, NULL_TREE);
23070 return false;
23071 }
23072 }
23073
23074 tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
23075 where: "#pragma omp ordered");
23076
23077 if (!flag_openmp /* flag_openmp_simd */
23078 && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE)
23079 return false;
23080
23081 c_finish_omp_ordered (loc, clauses,
23082 c_parser_omp_structured_block (parser, if_p));
23083 return true;
23084}
23085
23086/* OpenMP 2.5:
23087
23088 section-scope:
23089 { section-sequence }
23090
23091 section-sequence:
23092 section-directive[opt] structured-block
23093 section-sequence section-directive structured-block
23094
23095 OpenMP 5.1 allows structured-block-sequence instead of structured-block.
23096
23097 SECTIONS_LOC is the location of the #pragma omp sections. */
23098
23099static tree
23100c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
23101{
23102 tree stmt, substmt;
23103 bool error_suppress = false;
23104 location_t loc;
23105
23106 loc = c_parser_peek_token (parser)->location;
23107 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
23108 {
23109 /* Avoid skipping until the end of the block. */
23110 parser->error = false;
23111 return NULL_TREE;
23112 }
23113
23114 stmt = push_stmt_list ();
23115
23116 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
23117 && !c_parser_omp_section_scan (parser, directive: "section", tentative: true))
23118 {
23119 substmt = c_parser_omp_structured_block_sequence (parser,
23120 kind: PRAGMA_OMP_SECTION);
23121 substmt = build1 (OMP_SECTION, void_type_node, substmt);
23122 SET_EXPR_LOCATION (substmt, loc);
23123 add_stmt (substmt);
23124 }
23125
23126 while (1)
23127 {
23128 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
23129 break;
23130 if (c_parser_next_token_is (parser, type: CPP_EOF))
23131 break;
23132
23133 loc = c_parser_peek_token (parser)->location;
23134 c_parser_omp_section_scan (parser, directive: "section", tentative: false);
23135 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
23136 {
23137 c_parser_consume_pragma (parser);
23138 c_parser_skip_to_pragma_eol (parser);
23139 error_suppress = false;
23140 }
23141 else if (!error_suppress)
23142 {
23143 error_at (loc, "expected %<#pragma omp section%> or %<}%>");
23144 error_suppress = true;
23145 }
23146
23147 substmt = c_parser_omp_structured_block_sequence (parser,
23148 kind: PRAGMA_OMP_SECTION);
23149 substmt = build1 (OMP_SECTION, void_type_node, substmt);
23150 SET_EXPR_LOCATION (substmt, loc);
23151 add_stmt (substmt);
23152 }
23153 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
23154 msgid: "expected %<#pragma omp section%> or %<}%>");
23155
23156 substmt = pop_stmt_list (stmt);
23157
23158 stmt = make_node (OMP_SECTIONS);
23159 SET_EXPR_LOCATION (stmt, sections_loc);
23160 TREE_TYPE (stmt) = void_type_node;
23161 OMP_SECTIONS_BODY (stmt) = substmt;
23162
23163 return add_stmt (stmt);
23164}
23165
23166/* OpenMP 2.5:
23167 # pragma omp sections sections-clause[optseq] newline
23168 sections-scope
23169
23170 LOC is the location of the #pragma token.
23171*/
23172
23173#define OMP_SECTIONS_CLAUSE_MASK \
23174 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23175 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23176 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
23177 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
23178 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23179 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23180
23181static tree
23182c_parser_omp_sections (location_t loc, c_parser *parser,
23183 char *p_name, omp_clause_mask mask, tree *cclauses)
23184{
23185 tree block, clauses, ret;
23186
23187 strcat (dest: p_name, src: " sections");
23188 mask |= OMP_SECTIONS_CLAUSE_MASK;
23189 if (cclauses)
23190 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
23191
23192 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23193 if (cclauses)
23194 {
23195 omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses);
23196 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
23197 }
23198
23199 block = c_begin_compound_stmt (true);
23200 ret = c_parser_omp_sections_scope (sections_loc: loc, parser);
23201 if (ret)
23202 OMP_SECTIONS_CLAUSES (ret) = clauses;
23203 block = c_end_compound_stmt (loc, block, true);
23204 add_stmt (block);
23205
23206 return ret;
23207}
23208
23209/* OpenMP 2.5:
23210 # pragma omp parallel parallel-clause[optseq] new-line
23211 structured-block
23212 # pragma omp parallel for parallel-for-clause[optseq] new-line
23213 structured-block
23214 # pragma omp parallel sections parallel-sections-clause[optseq] new-line
23215 structured-block
23216
23217 OpenMP 4.0:
23218 # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
23219 structured-block
23220
23221 LOC is the location of the #pragma token.
23222*/
23223
23224#define OMP_PARALLEL_CLAUSE_MASK \
23225 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23226 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23227 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23228 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
23229 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
23230 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
23231 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
23232 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
23233 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23234 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
23235
23236static tree
23237c_parser_omp_parallel (location_t loc, c_parser *parser,
23238 char *p_name, omp_clause_mask mask, tree *cclauses,
23239 bool *if_p)
23240{
23241 tree stmt, clauses, block;
23242
23243 strcat (dest: p_name, src: " parallel");
23244 mask |= OMP_PARALLEL_CLAUSE_MASK;
23245 /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
23246 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
23247 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
23248 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
23249
23250 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
23251 {
23252 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23253 if (cclauses == NULL)
23254 cclauses = cclauses_buf;
23255
23256 c_parser_consume_token (parser);
23257 if (!flag_openmp) /* flag_openmp_simd */
23258 return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
23259 block = c_begin_omp_parallel ();
23260 tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
23261 stmt
23262 = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
23263 block);
23264 if (ret == NULL_TREE)
23265 return ret;
23266 OMP_PARALLEL_COMBINED (stmt) = 1;
23267 return stmt;
23268 }
23269 /* When combined with distribute, parallel has to be followed by for.
23270 #pragma omp target parallel is allowed though. */
23271 else if (cclauses
23272 && (mask & (OMP_CLAUSE_MASK_1
23273 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
23274 {
23275 error_at (loc, "expected %<for%> after %qs", p_name);
23276 c_parser_skip_to_pragma_eol (parser);
23277 return NULL_TREE;
23278 }
23279 else if (c_parser_next_token_is (parser, type: CPP_NAME))
23280 {
23281 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23282 if (cclauses == NULL && strcmp (s1: p, s2: "masked") == 0)
23283 {
23284 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23285 cclauses = cclauses_buf;
23286
23287 c_parser_consume_token (parser);
23288 if (!flag_openmp) /* flag_openmp_simd */
23289 return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
23290 if_p);
23291 block = c_begin_omp_parallel ();
23292 tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
23293 if_p);
23294 stmt = c_finish_omp_parallel (loc,
23295 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
23296 block);
23297 if (ret == NULL)
23298 return ret;
23299 /* masked does have just filter clause, but during gimplification
23300 isn't represented by a gimplification omp context, so for
23301 #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
23302 so that
23303 #pragma omp parallel masked
23304 #pragma omp taskloop simd lastprivate (x)
23305 isn't confused with
23306 #pragma omp parallel masked taskloop simd lastprivate (x) */
23307 if (OMP_MASKED_COMBINED (ret))
23308 OMP_PARALLEL_COMBINED (stmt) = 1;
23309 return stmt;
23310 }
23311 else if (cclauses == NULL && strcmp (s1: p, s2: "master") == 0)
23312 {
23313 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23314 cclauses = cclauses_buf;
23315
23316 c_parser_consume_token (parser);
23317 if (!flag_openmp) /* flag_openmp_simd */
23318 return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
23319 if_p);
23320 block = c_begin_omp_parallel ();
23321 tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
23322 if_p);
23323 stmt = c_finish_omp_parallel (loc,
23324 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
23325 block);
23326 if (ret == NULL)
23327 return ret;
23328 /* master doesn't have any clauses and during gimplification
23329 isn't represented by a gimplification omp context, so for
23330 #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
23331 so that
23332 #pragma omp parallel master
23333 #pragma omp taskloop simd lastprivate (x)
23334 isn't confused with
23335 #pragma omp parallel master taskloop simd lastprivate (x) */
23336 if (OMP_MASTER_COMBINED (ret))
23337 OMP_PARALLEL_COMBINED (stmt) = 1;
23338 return stmt;
23339 }
23340 else if (strcmp (s1: p, s2: "loop") == 0)
23341 {
23342 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23343 if (cclauses == NULL)
23344 cclauses = cclauses_buf;
23345
23346 c_parser_consume_token (parser);
23347 if (!flag_openmp) /* flag_openmp_simd */
23348 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
23349 if_p);
23350 block = c_begin_omp_parallel ();
23351 tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
23352 if_p);
23353 stmt
23354 = c_finish_omp_parallel (loc,
23355 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
23356 block);
23357 if (ret == NULL_TREE)
23358 return ret;
23359 OMP_PARALLEL_COMBINED (stmt) = 1;
23360 return stmt;
23361 }
23362 else if (!flag_openmp) /* flag_openmp_simd */
23363 {
23364 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23365 return NULL_TREE;
23366 }
23367 else if (cclauses == NULL && strcmp (s1: p, s2: "sections") == 0)
23368 {
23369 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23370 cclauses = cclauses_buf;
23371
23372 c_parser_consume_token (parser);
23373 block = c_begin_omp_parallel ();
23374 c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
23375 stmt = c_finish_omp_parallel (loc,
23376 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
23377 block);
23378 OMP_PARALLEL_COMBINED (stmt) = 1;
23379 return stmt;
23380 }
23381 }
23382 else if (!flag_openmp) /* flag_openmp_simd */
23383 {
23384 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23385 return NULL_TREE;
23386 }
23387
23388 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23389 if (cclauses)
23390 {
23391 omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses);
23392 clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
23393 }
23394
23395 block = c_begin_omp_parallel ();
23396 parser->omp_attrs_forbidden_p = true;
23397 c_parser_statement (parser, if_p);
23398 stmt = c_finish_omp_parallel (loc, clauses, block);
23399
23400 return stmt;
23401}
23402
23403/* OpenMP 2.5:
23404 # pragma omp single single-clause[optseq] new-line
23405 structured-block
23406
23407 LOC is the location of the #pragma.
23408*/
23409
23410#define OMP_SINGLE_CLAUSE_MASK \
23411 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23412 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23413 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
23414 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23415 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23416
23417static tree
23418c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
23419{
23420 tree stmt = make_node (OMP_SINGLE);
23421 SET_EXPR_LOCATION (stmt, loc);
23422 TREE_TYPE (stmt) = void_type_node;
23423
23424 OMP_SINGLE_CLAUSES (stmt)
23425 = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
23426 where: "#pragma omp single");
23427 OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
23428
23429 return add_stmt (stmt);
23430}
23431
23432/* OpenMP 5.1:
23433 # pragma omp scope scope-clause[optseq] new-line
23434 structured-block
23435
23436 LOC is the location of the #pragma.
23437*/
23438
23439#define OMP_SCOPE_CLAUSE_MASK \
23440 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23441 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23442 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
23443 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23444 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23445
23446static tree
23447c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
23448{
23449 tree stmt = make_node (OMP_SCOPE);
23450 SET_EXPR_LOCATION (stmt, loc);
23451 TREE_TYPE (stmt) = void_type_node;
23452
23453 OMP_SCOPE_CLAUSES (stmt)
23454 = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
23455 where: "#pragma omp scope");
23456 OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
23457
23458 return add_stmt (stmt);
23459}
23460
23461/* OpenMP 3.0:
23462 # pragma omp task task-clause[optseq] new-line
23463
23464 LOC is the location of the #pragma.
23465*/
23466
23467#define OMP_TASK_CLAUSE_MASK \
23468 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23469 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
23470 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
23471 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23472 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23473 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
23474 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
23475 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
23476 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23477 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
23478 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23479 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
23480 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
23481 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
23482
23483static tree
23484c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
23485{
23486 tree clauses, block;
23487
23488 clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
23489 where: "#pragma omp task");
23490
23491 block = c_begin_omp_task ();
23492 parser->omp_attrs_forbidden_p = true;
23493 c_parser_statement (parser, if_p);
23494 return c_finish_omp_task (loc, clauses, block);
23495}
23496
23497/* OpenMP 3.0:
23498 # pragma omp taskwait new-line
23499
23500 OpenMP 5.0:
23501 # pragma omp taskwait taskwait-clause[optseq] new-line
23502*/
23503
23504#define OMP_TASKWAIT_CLAUSE_MASK \
23505 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23506 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23507
23508static void
23509c_parser_omp_taskwait (c_parser *parser)
23510{
23511 location_t loc = c_parser_peek_token (parser)->location;
23512 c_parser_consume_pragma (parser);
23513
23514 tree clauses
23515 = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
23516 where: "#pragma omp taskwait");
23517
23518 if (clauses)
23519 {
23520 tree stmt = make_node (OMP_TASK);
23521 TREE_TYPE (stmt) = void_node;
23522 OMP_TASK_CLAUSES (stmt) = clauses;
23523 OMP_TASK_BODY (stmt) = NULL_TREE;
23524 SET_EXPR_LOCATION (stmt, loc);
23525 add_stmt (stmt);
23526 }
23527 else
23528 c_finish_omp_taskwait (loc);
23529}
23530
23531/* OpenMP 3.1:
23532 # pragma omp taskyield new-line
23533*/
23534
23535static void
23536c_parser_omp_taskyield (c_parser *parser)
23537{
23538 location_t loc = c_parser_peek_token (parser)->location;
23539 c_parser_consume_pragma (parser);
23540 c_parser_skip_to_pragma_eol (parser);
23541
23542 c_finish_omp_taskyield (loc);
23543}
23544
23545/* OpenMP 4.0:
23546 # pragma omp taskgroup new-line
23547
23548 OpenMP 5.0:
23549 # pragma omp taskgroup taskgroup-clause[optseq] new-line
23550*/
23551
23552#define OMP_TASKGROUP_CLAUSE_MASK \
23553 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23554 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
23555
23556static tree
23557c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
23558{
23559 tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
23560 where: "#pragma omp taskgroup");
23561
23562 tree body = c_parser_omp_structured_block (parser, if_p);
23563 return c_finish_omp_taskgroup (loc, body, clauses);
23564}
23565
23566/* OpenMP 4.0:
23567 # pragma omp cancel cancel-clause[optseq] new-line
23568
23569 LOC is the location of the #pragma.
23570*/
23571
23572#define OMP_CANCEL_CLAUSE_MASK \
23573 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
23574 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
23575 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
23576 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
23577 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
23578
23579static void
23580c_parser_omp_cancel (c_parser *parser)
23581{
23582 location_t loc = c_parser_peek_token (parser)->location;
23583
23584 c_parser_consume_pragma (parser);
23585 tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
23586 where: "#pragma omp cancel");
23587
23588 c_finish_omp_cancel (loc, clauses);
23589}
23590
23591/* OpenMP 4.0:
23592 # pragma omp cancellation point cancelpt-clause[optseq] new-line
23593
23594 LOC is the location of the #pragma.
23595*/
23596
23597#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
23598 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
23599 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
23600 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
23601 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
23602
23603static bool
23604c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
23605{
23606 location_t loc = c_parser_peek_token (parser)->location;
23607 tree clauses;
23608 bool point_seen = false;
23609
23610 c_parser_consume_pragma (parser);
23611 if (c_parser_next_token_is (parser, type: CPP_NAME))
23612 {
23613 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23614 if (strcmp (s1: p, s2: "point") == 0)
23615 {
23616 c_parser_consume_token (parser);
23617 point_seen = true;
23618 }
23619 }
23620 if (!point_seen)
23621 {
23622 c_parser_error (parser, gmsgid: "expected %<point%>");
23623 c_parser_skip_to_pragma_eol (parser);
23624 return false;
23625 }
23626
23627 if (context != pragma_compound)
23628 {
23629 if (context == pragma_stmt)
23630 error_at (loc,
23631 "%<#pragma %s%> may only be used in compound statements",
23632 "omp cancellation point");
23633 else
23634 c_parser_error (parser, gmsgid: "expected declaration specifiers");
23635 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23636 return true;
23637 }
23638
23639 clauses
23640 = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
23641 where: "#pragma omp cancellation point");
23642
23643 c_finish_omp_cancellation_point (loc, clauses);
23644 return true;
23645}
23646
23647/* OpenMP 4.0:
23648 #pragma omp distribute distribute-clause[optseq] new-line
23649 for-loop */
23650
23651#define OMP_DISTRIBUTE_CLAUSE_MASK \
23652 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23653 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23654 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
23655 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
23656 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23657 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
23658 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
23659
23660static tree
23661c_parser_omp_distribute (location_t loc, c_parser *parser,
23662 char *p_name, omp_clause_mask mask, tree *cclauses,
23663 bool *if_p)
23664{
23665 tree clauses, block, ret;
23666
23667 strcat (dest: p_name, src: " distribute");
23668 mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
23669
23670 if (c_parser_next_token_is (parser, type: CPP_NAME))
23671 {
23672 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23673 bool simd = false;
23674 bool parallel = false;
23675
23676 if (strcmp (s1: p, s2: "simd") == 0)
23677 simd = true;
23678 else
23679 parallel = strcmp (s1: p, s2: "parallel") == 0;
23680 if (parallel || simd)
23681 {
23682 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23683 if (cclauses == NULL)
23684 cclauses = cclauses_buf;
23685 c_parser_consume_token (parser);
23686 if (!flag_openmp) /* flag_openmp_simd */
23687 {
23688 if (simd)
23689 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
23690 if_p);
23691 else
23692 return c_parser_omp_parallel (loc, parser, p_name, mask,
23693 cclauses, if_p);
23694 }
23695 block = c_begin_compound_stmt (true);
23696 if (simd)
23697 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
23698 if_p);
23699 else
23700 ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
23701 if_p);
23702 block = c_end_compound_stmt (loc, block, true);
23703 if (ret == NULL)
23704 return ret;
23705 ret = make_node (OMP_DISTRIBUTE);
23706 TREE_TYPE (ret) = void_type_node;
23707 OMP_FOR_BODY (ret) = block;
23708 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
23709 SET_EXPR_LOCATION (ret, loc);
23710 add_stmt (ret);
23711 return ret;
23712 }
23713 }
23714 if (!flag_openmp) /* flag_openmp_simd */
23715 {
23716 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23717 return NULL_TREE;
23718 }
23719
23720 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23721 if (cclauses)
23722 {
23723 omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses);
23724 clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
23725 }
23726
23727 block = c_begin_compound_stmt (true);
23728 ret = c_parser_omp_for_loop (loc, parser, code: OMP_DISTRIBUTE, clauses, NULL,
23729 if_p);
23730 block = c_end_compound_stmt (loc, block, true);
23731 add_stmt (block);
23732
23733 return ret;
23734}
23735
23736/* OpenMP 4.0:
23737 # pragma omp teams teams-clause[optseq] new-line
23738 structured-block */
23739
23740#define OMP_TEAMS_CLAUSE_MASK \
23741 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23742 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23743 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
23744 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
23745 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
23746 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
23747 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23748 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
23749
23750static tree
23751c_parser_omp_teams (location_t loc, c_parser *parser,
23752 char *p_name, omp_clause_mask mask, tree *cclauses,
23753 bool *if_p)
23754{
23755 tree clauses, block, ret;
23756
23757 strcat (dest: p_name, src: " teams");
23758 mask |= OMP_TEAMS_CLAUSE_MASK;
23759
23760 if (c_parser_next_token_is (parser, type: CPP_NAME))
23761 {
23762 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23763 if (strcmp (s1: p, s2: "distribute") == 0)
23764 {
23765 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23766 if (cclauses == NULL)
23767 cclauses = cclauses_buf;
23768
23769 c_parser_consume_token (parser);
23770 if (!flag_openmp) /* flag_openmp_simd */
23771 return c_parser_omp_distribute (loc, parser, p_name, mask,
23772 cclauses, if_p);
23773 block = c_begin_omp_parallel ();
23774 ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
23775 if_p);
23776 block = c_end_compound_stmt (loc, block, true);
23777 if (ret == NULL)
23778 return ret;
23779 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23780 ret = make_node (OMP_TEAMS);
23781 TREE_TYPE (ret) = void_type_node;
23782 OMP_TEAMS_CLAUSES (ret) = clauses;
23783 OMP_TEAMS_BODY (ret) = block;
23784 OMP_TEAMS_COMBINED (ret) = 1;
23785 SET_EXPR_LOCATION (ret, loc);
23786 return add_stmt (ret);
23787 }
23788 else if (strcmp (s1: p, s2: "loop") == 0)
23789 {
23790 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23791 if (cclauses == NULL)
23792 cclauses = cclauses_buf;
23793
23794 c_parser_consume_token (parser);
23795 if (!flag_openmp) /* flag_openmp_simd */
23796 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
23797 if_p);
23798 block = c_begin_omp_parallel ();
23799 ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
23800 block = c_end_compound_stmt (loc, block, true);
23801 if (ret == NULL)
23802 return ret;
23803 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23804 ret = make_node (OMP_TEAMS);
23805 TREE_TYPE (ret) = void_type_node;
23806 OMP_TEAMS_CLAUSES (ret) = clauses;
23807 OMP_TEAMS_BODY (ret) = block;
23808 OMP_TEAMS_COMBINED (ret) = 1;
23809 SET_EXPR_LOCATION (ret, loc);
23810 return add_stmt (ret);
23811 }
23812 }
23813 if (!flag_openmp) /* flag_openmp_simd */
23814 {
23815 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23816 return NULL_TREE;
23817 }
23818
23819 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23820 if (cclauses)
23821 {
23822 omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses);
23823 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23824 }
23825
23826 tree stmt = make_node (OMP_TEAMS);
23827 TREE_TYPE (stmt) = void_type_node;
23828 OMP_TEAMS_CLAUSES (stmt) = clauses;
23829 block = c_begin_omp_parallel ();
23830 add_stmt (c_parser_omp_structured_block (parser, if_p));
23831 OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
23832 SET_EXPR_LOCATION (stmt, loc);
23833
23834 return add_stmt (stmt);
23835}
23836
23837/* OpenMP 4.0:
23838 # pragma omp target data target-data-clause[optseq] new-line
23839 structured-block */
23840
23841#define OMP_TARGET_DATA_CLAUSE_MASK \
23842 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23843 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23844 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23845 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
23846 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
23847
23848static tree
23849c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
23850{
23851 if (flag_openmp)
23852 omp_requires_mask
23853 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23854
23855 tree clauses
23856 = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
23857 where: "#pragma omp target data");
23858 c_omp_adjust_map_clauses (clauses, false);
23859 int map_seen = 0;
23860 for (tree *pc = &clauses; *pc;)
23861 {
23862 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
23863 switch (OMP_CLAUSE_MAP_KIND (*pc))
23864 {
23865 case GOMP_MAP_TO:
23866 case GOMP_MAP_ALWAYS_TO:
23867 case GOMP_MAP_PRESENT_TO:
23868 case GOMP_MAP_ALWAYS_PRESENT_TO:
23869 case GOMP_MAP_FROM:
23870 case GOMP_MAP_ALWAYS_FROM:
23871 case GOMP_MAP_PRESENT_FROM:
23872 case GOMP_MAP_ALWAYS_PRESENT_FROM:
23873 case GOMP_MAP_TOFROM:
23874 case GOMP_MAP_ALWAYS_TOFROM:
23875 case GOMP_MAP_PRESENT_TOFROM:
23876 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
23877 case GOMP_MAP_ALLOC:
23878 case GOMP_MAP_PRESENT_ALLOC:
23879 map_seen = 3;
23880 break;
23881 case GOMP_MAP_FIRSTPRIVATE_POINTER:
23882 case GOMP_MAP_ALWAYS_POINTER:
23883 case GOMP_MAP_ATTACH_DETACH:
23884 case GOMP_MAP_ATTACH:
23885 break;
23886 default:
23887 map_seen |= 1;
23888 error_at (OMP_CLAUSE_LOCATION (*pc),
23889 "%<#pragma omp target data%> with map-type other "
23890 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
23891 "on %<map%> clause");
23892 *pc = OMP_CLAUSE_CHAIN (*pc);
23893 continue;
23894 }
23895 else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
23896 || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
23897 map_seen = 3;
23898 pc = &OMP_CLAUSE_CHAIN (*pc);
23899 }
23900
23901 if (map_seen != 3)
23902 {
23903 if (map_seen == 0)
23904 error_at (loc,
23905 "%<#pragma omp target data%> must contain at least "
23906 "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
23907 "clause");
23908 return NULL_TREE;
23909 }
23910
23911 tree stmt = make_node (OMP_TARGET_DATA);
23912 TREE_TYPE (stmt) = void_type_node;
23913 OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
23914 keep_next_level ();
23915 tree block = c_begin_compound_stmt (true);
23916 add_stmt (c_parser_omp_structured_block (parser, if_p));
23917 OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
23918
23919 SET_EXPR_LOCATION (stmt, loc);
23920 return add_stmt (stmt);
23921}
23922
23923/* OpenMP 4.0:
23924 # pragma omp target update target-update-clause[optseq] new-line */
23925
23926#define OMP_TARGET_UPDATE_CLAUSE_MASK \
23927 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
23928 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
23929 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23930 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23931 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23932 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23933
23934static bool
23935c_parser_omp_target_update (location_t loc, c_parser *parser,
23936 enum pragma_context context)
23937{
23938 if (context == pragma_stmt)
23939 {
23940 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
23941 "omp target update");
23942 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23943 return true;
23944 }
23945
23946 tree clauses
23947 = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
23948 where: "#pragma omp target update");
23949 if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE
23950 && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE)
23951 {
23952 error_at (loc,
23953 "%<#pragma omp target update%> must contain at least one "
23954 "%<from%> or %<to%> clauses");
23955 return false;
23956 }
23957
23958 if (flag_openmp)
23959 omp_requires_mask
23960 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23961
23962 tree stmt = make_node (OMP_TARGET_UPDATE);
23963 TREE_TYPE (stmt) = void_type_node;
23964 OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
23965 SET_EXPR_LOCATION (stmt, loc);
23966 add_stmt (stmt);
23967 return false;
23968}
23969
23970/* OpenMP 4.5:
23971 # pragma omp target enter data target-data-clause[optseq] new-line */
23972
23973#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
23974 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23975 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23976 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23977 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23978 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23979
23980static bool
23981c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
23982 enum pragma_context context)
23983{
23984 bool data_seen = false;
23985 if (c_parser_next_token_is (parser, type: CPP_NAME))
23986 {
23987 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23988 if (strcmp (s1: p, s2: "data") == 0)
23989 {
23990 c_parser_consume_token (parser);
23991 data_seen = true;
23992 }
23993 }
23994 if (!data_seen)
23995 {
23996 c_parser_error (parser, gmsgid: "expected %<data%>");
23997 c_parser_skip_to_pragma_eol (parser);
23998 return false;
23999 }
24000
24001 if (context == pragma_stmt)
24002 {
24003 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
24004 "omp target enter data");
24005 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24006 return true;
24007 }
24008
24009 if (flag_openmp)
24010 omp_requires_mask
24011 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
24012
24013 tree clauses
24014 = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
24015 where: "#pragma omp target enter data");
24016 c_omp_adjust_map_clauses (clauses, false);
24017 int map_seen = 0;
24018 for (tree *pc = &clauses; *pc;)
24019 {
24020 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
24021 switch (OMP_CLAUSE_MAP_KIND (*pc))
24022 {
24023 case GOMP_MAP_TO:
24024 case GOMP_MAP_ALWAYS_TO:
24025 case GOMP_MAP_PRESENT_TO:
24026 case GOMP_MAP_ALWAYS_PRESENT_TO:
24027 case GOMP_MAP_ALLOC:
24028 case GOMP_MAP_PRESENT_ALLOC:
24029 map_seen = 3;
24030 break;
24031 case GOMP_MAP_TOFROM:
24032 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
24033 map_seen = 3;
24034 break;
24035 case GOMP_MAP_ALWAYS_TOFROM:
24036 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
24037 map_seen = 3;
24038 break;
24039 case GOMP_MAP_PRESENT_TOFROM:
24040 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
24041 map_seen = 3;
24042 break;
24043 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
24044 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
24045 map_seen = 3;
24046 break;
24047 case GOMP_MAP_FIRSTPRIVATE_POINTER:
24048 case GOMP_MAP_ALWAYS_POINTER:
24049 case GOMP_MAP_ATTACH_DETACH:
24050 case GOMP_MAP_ATTACH:
24051 break;
24052 default:
24053 map_seen |= 1;
24054 error_at (OMP_CLAUSE_LOCATION (*pc),
24055 "%<#pragma omp target enter data%> with map-type other "
24056 "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
24057 *pc = OMP_CLAUSE_CHAIN (*pc);
24058 continue;
24059 }
24060 pc = &OMP_CLAUSE_CHAIN (*pc);
24061 }
24062
24063 if (map_seen != 3)
24064 {
24065 if (map_seen == 0)
24066 error_at (loc,
24067 "%<#pragma omp target enter data%> must contain at least "
24068 "one %<map%> clause");
24069 return true;
24070 }
24071
24072 tree stmt = make_node (OMP_TARGET_ENTER_DATA);
24073 TREE_TYPE (stmt) = void_type_node;
24074 OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
24075 SET_EXPR_LOCATION (stmt, loc);
24076 add_stmt (stmt);
24077 return true;
24078}
24079
24080/* OpenMP 4.5:
24081 # pragma omp target exit data target-data-clause[optseq] new-line */
24082
24083#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
24084 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
24085 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
24086 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
24087 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
24088 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
24089
24090static bool
24091c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
24092 enum pragma_context context)
24093{
24094 bool data_seen = false;
24095 if (c_parser_next_token_is (parser, type: CPP_NAME))
24096 {
24097 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24098 if (strcmp (s1: p, s2: "data") == 0)
24099 {
24100 c_parser_consume_token (parser);
24101 data_seen = true;
24102 }
24103 }
24104 if (!data_seen)
24105 {
24106 c_parser_error (parser, gmsgid: "expected %<data%>");
24107 c_parser_skip_to_pragma_eol (parser);
24108 return false;
24109 }
24110
24111 if (context == pragma_stmt)
24112 {
24113 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
24114 "omp target exit data");
24115 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24116 return true;
24117 }
24118
24119 if (flag_openmp)
24120 omp_requires_mask
24121 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
24122
24123 tree clauses
24124 = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
24125 where: "#pragma omp target exit data", finish_p: false);
24126 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
24127 c_omp_adjust_map_clauses (clauses, false);
24128 int map_seen = 0;
24129 for (tree *pc = &clauses; *pc;)
24130 {
24131 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
24132 switch (OMP_CLAUSE_MAP_KIND (*pc))
24133 {
24134 case GOMP_MAP_FROM:
24135 case GOMP_MAP_ALWAYS_FROM:
24136 case GOMP_MAP_PRESENT_FROM:
24137 case GOMP_MAP_ALWAYS_PRESENT_FROM:
24138 case GOMP_MAP_RELEASE:
24139 case GOMP_MAP_DELETE:
24140 map_seen = 3;
24141 break;
24142 case GOMP_MAP_TOFROM:
24143 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
24144 map_seen = 3;
24145 break;
24146 case GOMP_MAP_ALWAYS_TOFROM:
24147 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
24148 map_seen = 3;
24149 break;
24150 case GOMP_MAP_PRESENT_TOFROM:
24151 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
24152 map_seen = 3;
24153 break;
24154 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
24155 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
24156 map_seen = 3;
24157 break;
24158 case GOMP_MAP_FIRSTPRIVATE_POINTER:
24159 case GOMP_MAP_ALWAYS_POINTER:
24160 case GOMP_MAP_ATTACH_DETACH:
24161 case GOMP_MAP_DETACH:
24162 break;
24163 default:
24164 map_seen |= 1;
24165 error_at (OMP_CLAUSE_LOCATION (*pc),
24166 "%<#pragma omp target exit data%> with map-type other "
24167 "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
24168 "on %<map%> clause");
24169 *pc = OMP_CLAUSE_CHAIN (*pc);
24170 continue;
24171 }
24172 pc = &OMP_CLAUSE_CHAIN (*pc);
24173 }
24174
24175 if (map_seen != 3)
24176 {
24177 if (map_seen == 0)
24178 error_at (loc,
24179 "%<#pragma omp target exit data%> must contain at least one "
24180 "%<map%> clause");
24181 return true;
24182 }
24183
24184 tree stmt = make_node (OMP_TARGET_EXIT_DATA);
24185 TREE_TYPE (stmt) = void_type_node;
24186 OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
24187 SET_EXPR_LOCATION (stmt, loc);
24188 add_stmt (stmt);
24189 return true;
24190}
24191
24192/* OpenMP 4.0:
24193 # pragma omp target target-clause[optseq] new-line
24194 structured-block */
24195
24196#define OMP_TARGET_CLAUSE_MASK \
24197 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
24198 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
24199 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
24200 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
24201 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
24202 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24203 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
24204 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
24205 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
24206 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
24207 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
24208 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
24209 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
24210
24211static bool
24212c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
24213{
24214 location_t loc = c_parser_peek_token (parser)->location;
24215 c_parser_consume_pragma (parser);
24216 tree *pc = NULL, stmt, block;
24217
24218 if (context != pragma_stmt && context != pragma_compound)
24219 {
24220 c_parser_error (parser, gmsgid: "expected declaration specifiers");
24221 c_parser_skip_to_pragma_eol (parser);
24222 return false;
24223 }
24224
24225 if (flag_openmp)
24226 omp_requires_mask
24227 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
24228
24229 if (c_parser_next_token_is (parser, type: CPP_NAME))
24230 {
24231 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24232 enum tree_code ccode = ERROR_MARK;
24233
24234 if (strcmp (s1: p, s2: "teams") == 0)
24235 ccode = OMP_TEAMS;
24236 else if (strcmp (s1: p, s2: "parallel") == 0)
24237 ccode = OMP_PARALLEL;
24238 else if (strcmp (s1: p, s2: "simd") == 0)
24239 ccode = OMP_SIMD;
24240 if (ccode != ERROR_MARK)
24241 {
24242 tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
24243 char p_name[sizeof ("#pragma omp target teams distribute "
24244 "parallel for simd")];
24245
24246 c_parser_consume_token (parser);
24247 strcpy (dest: p_name, src: "#pragma omp target");
24248 if (!flag_openmp) /* flag_openmp_simd */
24249 {
24250 tree stmt;
24251 switch (ccode)
24252 {
24253 case OMP_TEAMS:
24254 stmt = c_parser_omp_teams (loc, parser, p_name,
24255 OMP_TARGET_CLAUSE_MASK,
24256 cclauses, if_p);
24257 break;
24258 case OMP_PARALLEL:
24259 stmt = c_parser_omp_parallel (loc, parser, p_name,
24260 OMP_TARGET_CLAUSE_MASK,
24261 cclauses, if_p);
24262 break;
24263 case OMP_SIMD:
24264 stmt = c_parser_omp_simd (loc, parser, p_name,
24265 OMP_TARGET_CLAUSE_MASK,
24266 cclauses, if_p);
24267 break;
24268 default:
24269 gcc_unreachable ();
24270 }
24271 return stmt != NULL_TREE;
24272 }
24273 keep_next_level ();
24274 tree block = c_begin_compound_stmt (true), ret;
24275 switch (ccode)
24276 {
24277 case OMP_TEAMS:
24278 ret = c_parser_omp_teams (loc, parser, p_name,
24279 OMP_TARGET_CLAUSE_MASK, cclauses,
24280 if_p);
24281 break;
24282 case OMP_PARALLEL:
24283 ret = c_parser_omp_parallel (loc, parser, p_name,
24284 OMP_TARGET_CLAUSE_MASK, cclauses,
24285 if_p);
24286 break;
24287 case OMP_SIMD:
24288 ret = c_parser_omp_simd (loc, parser, p_name,
24289 OMP_TARGET_CLAUSE_MASK, cclauses,
24290 if_p);
24291 break;
24292 default:
24293 gcc_unreachable ();
24294 }
24295 block = c_end_compound_stmt (loc, block, true);
24296 if (ret == NULL_TREE)
24297 return false;
24298 if (ccode == OMP_TEAMS)
24299 /* For combined target teams, ensure the num_teams and
24300 thread_limit clause expressions are evaluated on the host,
24301 before entering the target construct. */
24302 for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
24303 c; c = OMP_CLAUSE_CHAIN (c))
24304 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
24305 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
24306 for (int i = 0;
24307 i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
24308 if (OMP_CLAUSE_OPERAND (c, i)
24309 && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
24310 {
24311 tree expr = OMP_CLAUSE_OPERAND (c, i);
24312 tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
24313 expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
24314 expr, NULL_TREE, NULL_TREE);
24315 add_stmt (expr);
24316 OMP_CLAUSE_OPERAND (c, i) = expr;
24317 tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
24318 OMP_CLAUSE_FIRSTPRIVATE);
24319 OMP_CLAUSE_DECL (tc) = tmp;
24320 OMP_CLAUSE_CHAIN (tc)
24321 = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
24322 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
24323 }
24324 tree stmt = make_node (OMP_TARGET);
24325 TREE_TYPE (stmt) = void_type_node;
24326 OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
24327 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
24328 OMP_TARGET_BODY (stmt) = block;
24329 OMP_TARGET_COMBINED (stmt) = 1;
24330 SET_EXPR_LOCATION (stmt, loc);
24331 add_stmt (stmt);
24332 pc = &OMP_TARGET_CLAUSES (stmt);
24333 goto check_clauses;
24334 }
24335 else if (!flag_openmp) /* flag_openmp_simd */
24336 {
24337 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24338 return false;
24339 }
24340 else if (strcmp (s1: p, s2: "data") == 0)
24341 {
24342 c_parser_consume_token (parser);
24343 c_parser_omp_target_data (loc, parser, if_p);
24344 return true;
24345 }
24346 else if (strcmp (s1: p, s2: "enter") == 0)
24347 {
24348 c_parser_consume_token (parser);
24349 return c_parser_omp_target_enter_data (loc, parser, context);
24350 }
24351 else if (strcmp (s1: p, s2: "exit") == 0)
24352 {
24353 c_parser_consume_token (parser);
24354 return c_parser_omp_target_exit_data (loc, parser, context);
24355 }
24356 else if (strcmp (s1: p, s2: "update") == 0)
24357 {
24358 c_parser_consume_token (parser);
24359 return c_parser_omp_target_update (loc, parser, context);
24360 }
24361 }
24362 if (!flag_openmp) /* flag_openmp_simd */
24363 {
24364 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24365 return false;
24366 }
24367
24368 stmt = make_node (OMP_TARGET);
24369 TREE_TYPE (stmt) = void_type_node;
24370
24371 OMP_TARGET_CLAUSES (stmt)
24372 = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
24373 where: "#pragma omp target", finish_p: false);
24374 for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
24375 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
24376 {
24377 tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
24378 OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
24379 OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
24380 OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
24381 OMP_CLAUSE_CHAIN (c) = nc;
24382 }
24383 OMP_TARGET_CLAUSES (stmt)
24384 = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
24385 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
24386
24387 pc = &OMP_TARGET_CLAUSES (stmt);
24388 keep_next_level ();
24389 block = c_begin_compound_stmt (true);
24390 add_stmt (c_parser_omp_structured_block (parser, if_p));
24391 OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
24392
24393 SET_EXPR_LOCATION (stmt, loc);
24394 add_stmt (stmt);
24395
24396check_clauses:
24397 while (*pc)
24398 {
24399 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
24400 switch (OMP_CLAUSE_MAP_KIND (*pc))
24401 {
24402 case GOMP_MAP_TO:
24403 case GOMP_MAP_ALWAYS_TO:
24404 case GOMP_MAP_PRESENT_TO:
24405 case GOMP_MAP_ALWAYS_PRESENT_TO:
24406 case GOMP_MAP_FROM:
24407 case GOMP_MAP_ALWAYS_FROM:
24408 case GOMP_MAP_PRESENT_FROM:
24409 case GOMP_MAP_ALWAYS_PRESENT_FROM:
24410 case GOMP_MAP_TOFROM:
24411 case GOMP_MAP_ALWAYS_TOFROM:
24412 case GOMP_MAP_PRESENT_TOFROM:
24413 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
24414 case GOMP_MAP_ALLOC:
24415 case GOMP_MAP_PRESENT_ALLOC:
24416 case GOMP_MAP_FIRSTPRIVATE_POINTER:
24417 case GOMP_MAP_ALWAYS_POINTER:
24418 case GOMP_MAP_POINTER:
24419 case GOMP_MAP_ATTACH_DETACH:
24420 case GOMP_MAP_ATTACH:
24421 break;
24422 default:
24423 error_at (OMP_CLAUSE_LOCATION (*pc),
24424 "%<#pragma omp target%> with map-type other "
24425 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
24426 "on %<map%> clause");
24427 *pc = OMP_CLAUSE_CHAIN (*pc);
24428 continue;
24429 }
24430 pc = &OMP_CLAUSE_CHAIN (*pc);
24431 }
24432 cfun->has_omp_target = true;
24433 return true;
24434}
24435
24436/* OpenMP 4.0:
24437 # pragma omp declare simd declare-simd-clauses[optseq] new-line
24438
24439 OpenMP 5.0:
24440 # pragma omp declare variant (identifier) match(context-selector) new-line
24441 */
24442
24443#define OMP_DECLARE_SIMD_CLAUSE_MASK \
24444 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
24445 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24446 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
24447 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
24448 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
24449 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
24450
24451static void
24452c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
24453{
24454 c_token *token = c_parser_peek_token (parser);
24455 gcc_assert (token->type == CPP_NAME);
24456 tree kind = token->value;
24457 gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
24458 || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
24459
24460 auto_vec<c_token> clauses;
24461 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
24462 {
24463 c_token *token = c_parser_peek_token (parser);
24464 if (token->type == CPP_EOF)
24465 {
24466 c_parser_skip_to_pragma_eol (parser);
24467 return;
24468 }
24469 clauses.safe_push (obj: *token);
24470 c_parser_consume_token (parser);
24471 }
24472 clauses.safe_push (obj: *c_parser_peek_token (parser));
24473 c_parser_skip_to_pragma_eol (parser);
24474
24475 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
24476 {
24477 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
24478 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
24479 || c_parser_peek_2nd_token (parser)->value != kind)
24480 {
24481 error ("%<#pragma omp declare %s%> must be followed by "
24482 "function declaration or definition or another "
24483 "%<#pragma omp declare %s%>",
24484 IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
24485 return;
24486 }
24487 c_parser_consume_pragma (parser);
24488 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
24489 {
24490 c_token *token = c_parser_peek_token (parser);
24491 if (token->type == CPP_EOF)
24492 {
24493 c_parser_skip_to_pragma_eol (parser);
24494 return;
24495 }
24496 clauses.safe_push (obj: *token);
24497 c_parser_consume_token (parser);
24498 }
24499 clauses.safe_push (obj: *c_parser_peek_token (parser));
24500 c_parser_skip_to_pragma_eol (parser);
24501 }
24502
24503 /* Make sure nothing tries to read past the end of the tokens. */
24504 c_token eof_token;
24505 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
24506 eof_token.type = CPP_EOF;
24507 clauses.safe_push (obj: eof_token);
24508 clauses.safe_push (obj: eof_token);
24509
24510 switch (context)
24511 {
24512 case pragma_external:
24513 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24514 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
24515 {
24516 int ext = disable_extension_diagnostics ();
24517 do
24518 c_parser_consume_token (parser);
24519 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24520 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
24521 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
24522 NULL, omp_declare_simd_clauses: &clauses);
24523 restore_extension_diagnostics (flags: ext);
24524 }
24525 else
24526 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
24527 NULL, omp_declare_simd_clauses: &clauses);
24528 break;
24529 case pragma_struct:
24530 case pragma_param:
24531 case pragma_stmt:
24532 error ("%<#pragma omp declare %s%> must be followed by "
24533 "function declaration or definition",
24534 IDENTIFIER_POINTER (kind));
24535 break;
24536 case pragma_compound:
24537 bool have_std_attrs;
24538 tree std_attrs;
24539 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
24540 if (have_std_attrs)
24541 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24542 else
24543 std_attrs = NULL_TREE;
24544 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24545 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
24546 {
24547 int ext = disable_extension_diagnostics ();
24548 do
24549 c_parser_consume_token (parser);
24550 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24551 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
24552 if (c_parser_next_tokens_start_declaration (parser)
24553 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
24554 {
24555 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
24556 start_attr_ok: true, NULL, omp_declare_simd_clauses: &clauses,
24557 have_attrs: have_std_attrs, attrs: std_attrs);
24558 restore_extension_diagnostics (flags: ext);
24559 break;
24560 }
24561 restore_extension_diagnostics (flags: ext);
24562 }
24563 else if (c_parser_next_tokens_start_declaration (parser))
24564 {
24565 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
24566 NULL, omp_declare_simd_clauses: &clauses, have_attrs: have_std_attrs,
24567 attrs: std_attrs);
24568 break;
24569 }
24570 error ("%<#pragma omp declare %s%> must be followed by "
24571 "function declaration or definition",
24572 IDENTIFIER_POINTER (kind));
24573 break;
24574 default:
24575 gcc_unreachable ();
24576 }
24577}
24578
24579/* OpenMP 5.0:
24580
24581 trait-selector:
24582 trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
24583
24584 trait-score:
24585 score(score-expression)
24586
24587 Note that this function returns a list of trait selectors for the
24588 trait-selector-set SET. */
24589
24590static tree
24591c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
24592 tree parms)
24593{
24594 tree ret = NULL_TREE;
24595 do
24596 {
24597 tree selector;
24598 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24599 || c_parser_next_token_is (parser, type: CPP_NAME))
24600 selector = c_parser_peek_token (parser)->value;
24601 else
24602 {
24603 c_parser_error (parser, gmsgid: "expected trait selector name");
24604 return error_mark_node;
24605 }
24606 enum omp_ts_code sel
24607 = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
24608
24609 if (sel == OMP_TRAIT_INVALID)
24610 {
24611 /* Per the spec, "Implementations can ignore specified selectors
24612 that are not those described in this section"; however, we
24613 must record such selectors because they cause match failures. */
24614 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24615 "unknown selector %qs for context selector set %qs",
24616 IDENTIFIER_POINTER (selector), omp_tss_map[set]);
24617 c_parser_consume_token (parser);
24618 ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
24619 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24620 c_parser_balanced_token_sequence (parser);
24621 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24622 {
24623 c_parser_consume_token (parser);
24624 continue;
24625 }
24626 else
24627 break;
24628 }
24629
24630 c_parser_consume_token (parser);
24631
24632 tree properties = NULL_TREE;
24633 tree scoreval = NULL_TREE;
24634 enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
24635 bool allow_score = omp_ts_map[sel].allow_score;
24636 tree t;
24637
24638 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24639 {
24640 if (property_kind == OMP_TRAIT_PROPERTY_NONE)
24641 {
24642 error_at (c_parser_peek_token (parser)->location,
24643 "selector %qs does not accept any properties",
24644 IDENTIFIER_POINTER (selector));
24645 return error_mark_node;
24646 }
24647
24648 matching_parens parens;
24649 parens.require_open (parser);
24650
24651 c_token *token = c_parser_peek_token (parser);
24652 if (c_parser_next_token_is (parser, type: CPP_NAME)
24653 && strcmp (IDENTIFIER_POINTER (token->value), s2: "score") == 0
24654 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
24655 {
24656 c_parser_consume_token (parser);
24657
24658 matching_parens parens2;
24659 parens2.require_open (parser);
24660 tree score = c_parser_expr_no_commas (parser, NULL).value;
24661 parens2.skip_until_found_close (parser);
24662 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
24663 if (!allow_score)
24664 error_at (token->location,
24665 "%<score%> cannot be specified in traits "
24666 "in the %qs trait-selector-set",
24667 omp_tss_map[set]);
24668 else if (score != error_mark_node)
24669 {
24670 mark_exp_read (score);
24671 score = c_fully_fold (score, false, NULL);
24672 if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
24673 || TREE_CODE (score) != INTEGER_CST)
24674 error_at (token->location, "%<score%> argument must "
24675 "be constant integer expression");
24676 else if (tree_int_cst_sgn (score) < 0)
24677 error_at (token->location, "%<score%> argument must "
24678 "be non-negative");
24679 else
24680 scoreval = score;
24681 }
24682 token = c_parser_peek_token (parser);
24683 }
24684
24685 switch (property_kind)
24686 {
24687 case OMP_TRAIT_PROPERTY_ID:
24688 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24689 || c_parser_next_token_is (parser, type: CPP_NAME))
24690 {
24691 tree prop = c_parser_peek_token (parser)->value;
24692 c_parser_consume_token (parser);
24693 properties = make_trait_property (prop, NULL_TREE,
24694 properties);
24695 }
24696 else
24697 {
24698 c_parser_error (parser, gmsgid: "expected identifier");
24699 return error_mark_node;
24700 }
24701 break;
24702 case OMP_TRAIT_PROPERTY_NAME_LIST:
24703 do
24704 {
24705 tree prop = OMP_TP_NAMELIST_NODE;
24706 tree value = NULL_TREE;
24707 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24708 || c_parser_next_token_is (parser, type: CPP_NAME))
24709 {
24710 value = c_parser_peek_token (parser)->value;
24711 c_parser_consume_token (parser);
24712 }
24713 else if (c_parser_next_token_is (parser, type: CPP_STRING))
24714 value = c_parser_string_literal (parser, translate: false,
24715 wide_ok: false).value;
24716 else
24717 {
24718 c_parser_error (parser, gmsgid: "expected identifier or "
24719 "string literal");
24720 return error_mark_node;
24721 }
24722
24723 properties = make_trait_property (prop, value, properties);
24724
24725 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24726 c_parser_consume_token (parser);
24727 else
24728 break;
24729 }
24730 while (1);
24731 break;
24732 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
24733 case OMP_TRAIT_PROPERTY_BOOL_EXPR:
24734 t = c_parser_expr_no_commas (parser, NULL).value;
24735 if (t != error_mark_node)
24736 {
24737 mark_exp_read (t);
24738 t = c_fully_fold (t, false, NULL);
24739 /* FIXME: this is bogus, both device_num and
24740 condition selectors allow arbitrary expressions. */
24741 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
24742 || !tree_fits_shwi_p (t))
24743 error_at (token->location, "property must be "
24744 "constant integer expression");
24745 else
24746 properties = make_trait_property (NULL_TREE, t,
24747 properties);
24748 }
24749 else
24750 return error_mark_node;
24751 break;
24752 case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
24753 if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
24754 {
24755 if (parms == NULL_TREE)
24756 {
24757 error_at (token->location, "properties for %<simd%> "
24758 "selector may not be specified in "
24759 "%<metadirective%>");
24760 return error_mark_node;
24761 }
24762 tree c;
24763 c = c_parser_omp_all_clauses (parser,
24764 OMP_DECLARE_SIMD_CLAUSE_MASK,
24765 where: "simd", finish_p: true, nested: 2);
24766 c = c_omp_declare_simd_clauses_to_numbers (parms
24767 == error_mark_node
24768 ? NULL_TREE : parms,
24769 c);
24770 properties = c;
24771 }
24772 else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
24773 {
24774 /* FIXME: The "requires" selector was added in OpenMP 5.1.
24775 Currently only the now-deprecated syntax
24776 from OpenMP 5.0 is supported. */
24777 sorry_at (token->location,
24778 "%<requires%> selector is not supported yet");
24779 return error_mark_node;
24780 }
24781 else
24782 gcc_unreachable ();
24783 break;
24784 default:
24785 gcc_unreachable ();
24786 }
24787
24788 parens.skip_until_found_close (parser);
24789 properties = nreverse (properties);
24790 }
24791 else if (property_kind != OMP_TRAIT_PROPERTY_NONE
24792 && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
24793 && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
24794 {
24795 c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>");
24796 return error_mark_node;
24797 }
24798
24799 ret = make_trait_selector (sel, scoreval, properties, ret);
24800
24801 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24802 c_parser_consume_token (parser);
24803 else
24804 break;
24805 }
24806 while (1);
24807
24808 return nreverse (ret);
24809}
24810
24811/* OpenMP 5.0:
24812
24813 trait-set-selector[,trait-set-selector[,...]]
24814
24815 trait-set-selector:
24816 trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
24817
24818 trait-set-selector-name:
24819 constructor
24820 device
24821 implementation
24822 user */
24823
24824static tree
24825c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
24826{
24827 tree ret = NULL_TREE;
24828 do
24829 {
24830 const char *setp = "";
24831 if (c_parser_next_token_is (parser, type: CPP_NAME))
24832 setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24833 enum omp_tss_code set = omp_lookup_tss_code (setp);
24834
24835 if (set == OMP_TRAIT_SET_INVALID)
24836 {
24837 c_parser_error (parser, gmsgid: "expected context selector set name");
24838 return error_mark_node;
24839 }
24840
24841 c_parser_consume_token (parser);
24842
24843 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
24844 return error_mark_node;
24845
24846 matching_braces braces;
24847 if (!braces.require_open (parser))
24848 return error_mark_node;
24849
24850 tree selectors = c_parser_omp_context_selector (parser, set, parms);
24851 if (selectors == error_mark_node)
24852 ret = error_mark_node;
24853 else if (ret != error_mark_node)
24854 ret = make_trait_set_selector (set, selectors, ret);
24855
24856 braces.skip_until_found_close (parser);
24857
24858 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24859 c_parser_consume_token (parser);
24860 else
24861 break;
24862 }
24863 while (1);
24864
24865 if (ret == error_mark_node)
24866 return ret;
24867 return nreverse (ret);
24868}
24869
24870/* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
24871 that into "omp declare variant base" attribute. */
24872
24873static void
24874c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
24875{
24876 matching_parens parens;
24877 if (!parens.require_open (parser))
24878 {
24879 fail:
24880 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24881 return;
24882 }
24883
24884 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
24885 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
24886 {
24887 c_parser_error (parser, gmsgid: "expected identifier");
24888 goto fail;
24889 }
24890
24891 c_token *token = c_parser_peek_token (parser);
24892 tree variant = lookup_name (token->value);
24893
24894 if (variant == NULL_TREE)
24895 {
24896 undeclared_variable (token->location, token->value);
24897 variant = error_mark_node;
24898 }
24899
24900 c_parser_consume_token (parser);
24901
24902 parens.require_close (parser);
24903
24904 if (c_parser_next_token_is (parser, type: CPP_COMMA)
24905 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24906 c_parser_consume_token (parser);
24907
24908 const char *clause = "";
24909 location_t match_loc = c_parser_peek_token (parser)->location;
24910 if (c_parser_next_token_is (parser, type: CPP_NAME))
24911 clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24912 if (strcmp (s1: clause, s2: "match"))
24913 {
24914 c_parser_error (parser, gmsgid: "expected %<match%>");
24915 goto fail;
24916 }
24917
24918 c_parser_consume_token (parser);
24919
24920 if (!parens.require_open (parser))
24921 goto fail;
24922
24923 if (parms == NULL_TREE)
24924 parms = error_mark_node;
24925
24926 tree ctx = c_parser_omp_context_selector_specification (parser, parms);
24927 if (ctx == error_mark_node)
24928 goto fail;
24929 ctx = omp_check_context_selector (loc: match_loc, ctx);
24930 if (ctx != error_mark_node && variant != error_mark_node)
24931 {
24932 if (TREE_CODE (variant) != FUNCTION_DECL)
24933 {
24934 error_at (token->location, "variant %qD is not a function", variant);
24935 variant = error_mark_node;
24936 }
24937 else if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
24938 OMP_TRAIT_CONSTRUCT_SIMD)
24939 && !comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
24940 {
24941 error_at (token->location, "variant %qD and base %qD have "
24942 "incompatible types", variant, fndecl);
24943 variant = error_mark_node;
24944 }
24945 else if (fndecl_built_in_p (node: variant)
24946 && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24947 s2: "__builtin_", n: strlen (s: "__builtin_")) == 0
24948 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24949 s2: "__sync_", n: strlen (s: "__sync_")) == 0
24950 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24951 s2: "__atomic_", n: strlen (s: "__atomic_")) == 0))
24952 {
24953 error_at (token->location, "variant %qD is a built-in", variant);
24954 variant = error_mark_node;
24955 }
24956 if (variant != error_mark_node)
24957 {
24958 C_DECL_USED (variant) = 1;
24959 tree construct
24960 = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
24961 omp_mark_declare_variant (loc: match_loc, variant, construct);
24962 if (omp_context_selector_matches (ctx))
24963 {
24964 tree attr
24965 = tree_cons (get_identifier ("omp declare variant base"),
24966 build_tree_list (variant, ctx),
24967 DECL_ATTRIBUTES (fndecl));
24968 DECL_ATTRIBUTES (fndecl) = attr;
24969 }
24970 }
24971 }
24972
24973 parens.require_close (parser);
24974 c_parser_skip_to_pragma_eol (parser);
24975}
24976
24977/* Finalize #pragma omp declare simd or #pragma omp declare variant
24978 clauses after FNDECL has been parsed, and put that into "omp declare simd"
24979 or "omp declare variant base" attribute. */
24980
24981static void
24982c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
24983 vec<c_token> *pclauses)
24984{
24985 vec<c_token> &clauses = *pclauses;
24986
24987 /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
24988 indicates error has been reported and CPP_PRAGMA that
24989 c_finish_omp_declare_simd has already processed the tokens. */
24990 if (clauses.exists () && clauses[0].type == CPP_EOF)
24991 return;
24992 const char *kind = "simd";
24993 if (clauses.exists ()
24994 && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
24995 kind = IDENTIFIER_POINTER (clauses[0].value);
24996 gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
24997 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
24998 {
24999 error ("%<#pragma omp declare %s%> not immediately followed by "
25000 "a function declaration or definition", kind);
25001 clauses[0].type = CPP_EOF;
25002 return;
25003 }
25004 if (clauses.exists () && clauses[0].type != CPP_NAME)
25005 {
25006 error_at (DECL_SOURCE_LOCATION (fndecl),
25007 "%<#pragma omp declare %s%> not immediately followed by "
25008 "a single function declaration or definition", kind);
25009 clauses[0].type = CPP_EOF;
25010 return;
25011 }
25012
25013 if (parms == NULL_TREE)
25014 parms = DECL_ARGUMENTS (fndecl);
25015
25016 unsigned int tokens_avail = parser->tokens_avail;
25017 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
25018
25019 parser->tokens = clauses.address ();
25020 parser->tokens_avail = clauses.length ();
25021
25022 /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
25023 while (parser->tokens_avail > 3)
25024 {
25025 c_token *token = c_parser_peek_token (parser);
25026 gcc_assert (token->type == CPP_NAME);
25027 kind = IDENTIFIER_POINTER (token->value);
25028 c_parser_consume_token (parser);
25029 parser->in_pragma = true;
25030
25031 if (strcmp (s1: kind, s2: "simd") == 0)
25032 {
25033 tree c;
25034 c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
25035 where: "#pragma omp declare simd");
25036 c = c_omp_declare_simd_clauses_to_numbers (parms, c);
25037 if (c != NULL_TREE)
25038 c = tree_cons (NULL_TREE, c, NULL_TREE);
25039 c = build_tree_list (get_identifier ("omp declare simd"), c);
25040 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
25041 DECL_ATTRIBUTES (fndecl) = c;
25042 }
25043 else
25044 {
25045 gcc_assert (strcmp (kind, "variant") == 0);
25046 c_finish_omp_declare_variant (parser, fndecl, parms);
25047 }
25048 }
25049
25050 parser->tokens = &parser->tokens_buf[0];
25051 parser->tokens_avail = tokens_avail;
25052 if (clauses.exists ())
25053 clauses[0].type = CPP_PRAGMA;
25054}
25055
25056/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
25057 a threadprivate, groupprivate, allocate or declare target directive,
25058 return true and parse it for DECL. */
25059
25060bool
25061c_maybe_parse_omp_decl (tree decl, tree d)
25062{
25063 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
25064 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
25065 c_token *first = toks->address ();
25066 c_token *last = first + toks->length ();
25067 const char *directive[3] = {};
25068 for (int j = 0; j < 3; j++)
25069 {
25070 tree id = NULL_TREE;
25071 if (first + j == last)
25072 break;
25073 if (first[j].type == CPP_NAME)
25074 id = first[j].value;
25075 else if (first[j].type == CPP_KEYWORD)
25076 id = ridpointers[(int) first[j].keyword];
25077 else
25078 break;
25079 directive[j] = IDENTIFIER_POINTER (id);
25080 }
25081 const c_omp_directive *dir = NULL;
25082 if (directive[0])
25083 dir = c_omp_categorize_directive (directive[0], directive[1],
25084 directive[2]);
25085 if (dir == NULL)
25086 {
25087 error_at (first->location,
25088 "unknown OpenMP directive name in "
25089 "%qs attribute argument", "omp::decl");
25090 return false;
25091 }
25092 if (dir->id != PRAGMA_OMP_THREADPRIVATE
25093 /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
25094 && dir->id != PRAGMA_OMP_ALLOCATE
25095 && (dir->id != PRAGMA_OMP_DECLARE
25096 || strcmp (s1: directive[1], s2: "target") != 0))
25097 return false;
25098
25099 if (!flag_openmp && !dir->simd)
25100 return true;
25101
25102 c_parser *parser = the_parser;
25103 unsigned int tokens_avail = parser->tokens_avail;
25104 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
25105 toks = NULL;
25106 vec_safe_reserve (v&: toks, nelems: last - first + 2, exact: true);
25107 c_token tok = {};
25108 tok.type = CPP_PRAGMA;
25109 tok.keyword = RID_MAX;
25110 tok.pragma_kind = pragma_kind (dir->id);
25111 tok.location = first->location;
25112 toks->quick_push (obj: tok);
25113 while (++first < last)
25114 toks->quick_push (obj: *first);
25115 tok = {};
25116 tok.type = CPP_PRAGMA_EOL;
25117 tok.keyword = RID_MAX;
25118 tok.location = last[-1].location;
25119 toks->quick_push (obj: tok);
25120 tok = {};
25121 tok.type = CPP_EOF;
25122 tok.keyword = RID_MAX;
25123 tok.location = last[-1].location;
25124 tok.flags = tokens_avail;
25125 toks->quick_push (obj: tok);
25126 parser->in_omp_decl_attribute = decl;
25127 parser->tokens = toks->address ();
25128 parser->tokens_avail = toks->length ();
25129 parser->in_omp_attribute_pragma = toks;
25130 c_parser_pragma (parser, context: pragma_external, NULL);
25131 parser->in_omp_decl_attribute = NULL_TREE;
25132 return true;
25133}
25134
25135/* OpenMP 4.0:
25136 # pragma omp declare target new-line
25137 declarations and definitions
25138 # pragma omp end declare target new-line
25139
25140 OpenMP 4.5:
25141 # pragma omp declare target ( extended-list ) new-line
25142
25143 # pragma omp declare target declare-target-clauses[seq] new-line */
25144
25145#define OMP_DECLARE_TARGET_CLAUSE_MASK \
25146 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
25147 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
25148 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
25149 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
25150 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
25151
25152static void
25153c_parser_omp_declare_target (c_parser *parser)
25154{
25155 tree clauses = NULL_TREE;
25156 int device_type = 0;
25157 bool indirect = false;
25158 bool only_device_type_or_indirect = true;
25159 if (c_parser_next_token_is (parser, type: CPP_NAME)
25160 || (c_parser_next_token_is (parser, type: CPP_COMMA)
25161 && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
25162 clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
25163 where: "#pragma omp declare target");
25164 else if (parser->in_omp_decl_attribute
25165 || c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
25166 {
25167 clauses = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
25168 list: clauses);
25169 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
25170 c_parser_skip_to_pragma_eol (parser);
25171 }
25172 else
25173 {
25174 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
25175 c_parser_skip_to_pragma_eol (parser);
25176 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: -1, .indirect: 0 };
25177 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
25178 return;
25179 }
25180 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
25181 {
25182 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
25183 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
25184 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
25185 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
25186 }
25187 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
25188 {
25189 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
25190 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
25191 continue;
25192 tree t = OMP_CLAUSE_DECL (c), id;
25193 tree at1 = lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (t));
25194 tree at2 = lookup_attribute (attr_name: "omp declare target link",
25195 DECL_ATTRIBUTES (t));
25196 only_device_type_or_indirect = false;
25197 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
25198 {
25199 id = get_identifier ("omp declare target link");
25200 std::swap (a&: at1, b&: at2);
25201 }
25202 else
25203 id = get_identifier ("omp declare target");
25204 if (at2)
25205 {
25206 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
25207 error_at (OMP_CLAUSE_LOCATION (c),
25208 "%qD specified both in declare target %<link%> and %qs"
25209 " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
25210 else
25211 error_at (OMP_CLAUSE_LOCATION (c),
25212 "%qD specified both in declare target %<link%> and "
25213 "%<to%> or %<enter%> clauses", t);
25214 continue;
25215 }
25216 if (!at1)
25217 {
25218 DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
25219 if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
25220 continue;
25221
25222 symtab_node *node = symtab_node::get (decl: t);
25223 if (node != NULL)
25224 {
25225 node->offloadable = 1;
25226 if (ENABLE_OFFLOADING)
25227 {
25228 g->have_offload = true;
25229 if (is_a <varpool_node *> (p: node))
25230 vec_safe_push (v&: offload_vars, obj: t);
25231 }
25232 }
25233 }
25234 if (TREE_CODE (t) != FUNCTION_DECL)
25235 continue;
25236 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
25237 {
25238 tree at3 = lookup_attribute (attr_name: "omp declare target host",
25239 DECL_ATTRIBUTES (t));
25240 if (at3 == NULL_TREE)
25241 {
25242 id = get_identifier ("omp declare target host");
25243 DECL_ATTRIBUTES (t)
25244 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
25245 }
25246 }
25247 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
25248 {
25249 tree at3 = lookup_attribute (attr_name: "omp declare target nohost",
25250 DECL_ATTRIBUTES (t));
25251 if (at3 == NULL_TREE)
25252 {
25253 id = get_identifier ("omp declare target nohost");
25254 DECL_ATTRIBUTES (t)
25255 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
25256 }
25257 }
25258 if (indirect)
25259 {
25260 tree at4 = lookup_attribute (attr_name: "omp declare target indirect",
25261 DECL_ATTRIBUTES (t));
25262 if (at4 == NULL_TREE)
25263 {
25264 id = get_identifier ("omp declare target indirect");
25265 DECL_ATTRIBUTES (t)
25266 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
25267 }
25268 }
25269 }
25270 if ((device_type || indirect) && only_device_type_or_indirect)
25271 error_at (OMP_CLAUSE_LOCATION (clauses),
25272 "directive with only %<device_type%> or %<indirect%> clauses");
25273 if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
25274 error_at (OMP_CLAUSE_LOCATION (clauses),
25275 "%<device_type%> clause must specify 'any' when used with "
25276 "an %<indirect%> clause");
25277}
25278
25279/* OpenMP 5.1
25280 #pragma omp begin assumes clauses[optseq] new-line
25281
25282 #pragma omp begin declare target clauses[optseq] new-line */
25283
25284#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
25285 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
25286 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
25287
25288static void
25289c_parser_omp_begin (c_parser *parser)
25290{
25291 const char *p = "";
25292 c_parser_consume_pragma (parser);
25293 if (c_parser_next_token_is (parser, type: CPP_NAME))
25294 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25295 if (strcmp (s1: p, s2: "declare") == 0)
25296 {
25297 c_parser_consume_token (parser);
25298 p = "";
25299 if (c_parser_next_token_is (parser, type: CPP_NAME))
25300 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25301 if (strcmp (s1: p, s2: "target") == 0)
25302 {
25303 c_parser_consume_token (parser);
25304 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
25305 tree clauses
25306 = c_parser_omp_all_clauses (parser,
25307 OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
25308 where: "#pragma omp begin declare target");
25309 int device_type = 0;
25310 int indirect = 0;
25311 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
25312 {
25313 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
25314 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
25315 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
25316 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
25317 }
25318 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: device_type,
25319 .indirect: indirect };
25320 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
25321 }
25322 else
25323 {
25324 c_parser_error (parser, gmsgid: "expected %<target%>");
25325 c_parser_skip_to_pragma_eol (parser);
25326 }
25327 }
25328 else if (strcmp (s1: p, s2: "assumes") == 0)
25329 {
25330 c_parser_consume_token (parser);
25331 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
25332 c_parser_omp_assumption_clauses (parser, false);
25333 struct c_omp_begin_assumes_data a = { .attr_syntax: attr_syntax };
25334 vec_safe_push (v&: current_omp_begin_assumes, obj: a);
25335 }
25336 else
25337 {
25338 c_parser_error (parser, gmsgid: "expected %<declare target%> or %<assumes%>");
25339 c_parser_skip_to_pragma_eol (parser);
25340 }
25341}
25342
25343/* OpenMP 4.0
25344 #pragma omp end declare target
25345
25346 OpenMP 5.1
25347 #pragma omp end assumes */
25348
25349static void
25350c_parser_omp_end (c_parser *parser)
25351{
25352 location_t loc = c_parser_peek_token (parser)->location;
25353 const char *p = "";
25354 c_parser_consume_pragma (parser);
25355 if (c_parser_next_token_is (parser, type: CPP_NAME))
25356 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25357 if (strcmp (s1: p, s2: "declare") == 0)
25358 {
25359 c_parser_consume_token (parser);
25360 if (c_parser_next_token_is (parser, type: CPP_NAME)
25361 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
25362 s2: "target") == 0)
25363 c_parser_consume_token (parser);
25364 else
25365 {
25366 c_parser_error (parser, gmsgid: "expected %<target%>");
25367 c_parser_skip_to_pragma_eol (parser);
25368 return;
25369 }
25370 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
25371 c_parser_skip_to_pragma_eol (parser);
25372 if (!vec_safe_length (v: current_omp_declare_target_attribute))
25373 error_at (loc, "%<#pragma omp end declare target%> without "
25374 "corresponding %<#pragma omp declare target%> or "
25375 "%<#pragma omp begin declare target%>");
25376 else
25377 {
25378 c_omp_declare_target_attr
25379 a = current_omp_declare_target_attribute->pop ();
25380 if (a.attr_syntax != attr_syntax)
25381 {
25382 if (a.attr_syntax)
25383 error_at (loc,
25384 "%qs in attribute syntax terminated "
25385 "with %qs in pragma syntax",
25386 a.device_type >= 0 ? "begin declare target"
25387 : "declare target",
25388 "end declare target");
25389 else
25390 error_at (loc,
25391 "%qs in pragma syntax terminated "
25392 "with %qs in attribute syntax",
25393 a.device_type >= 0 ? "begin declare target"
25394 : "declare target",
25395 "end declare target");
25396 }
25397 }
25398 }
25399 else if (strcmp (s1: p, s2: "assumes") == 0)
25400 {
25401 c_parser_consume_token (parser);
25402 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
25403 c_parser_skip_to_pragma_eol (parser);
25404 if (!vec_safe_length (v: current_omp_begin_assumes))
25405 error_at (loc, "%qs without corresponding %qs",
25406 "#pragma omp end assumes", "#pragma omp begin assumes");
25407 else
25408 {
25409 c_omp_begin_assumes_data
25410 a = current_omp_begin_assumes->pop ();
25411 if (a.attr_syntax != attr_syntax)
25412 {
25413 if (a.attr_syntax)
25414 error_at (loc,
25415 "%qs in attribute syntax terminated "
25416 "with %qs in pragma syntax",
25417 "begin assumes", "end assumes");
25418 else
25419 error_at (loc,
25420 "%qs in pragma syntax terminated "
25421 "with %qs in attribute syntax",
25422 "begin assumes", "end assumes");
25423 }
25424 }
25425 }
25426 else
25427 {
25428 c_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>");
25429 c_parser_skip_to_pragma_eol (parser);
25430 }
25431}
25432
25433/* OpenMP 4.0
25434 #pragma omp declare reduction (reduction-id : typename-list : expression) \
25435 initializer-clause[opt] new-line
25436
25437 initializer-clause:
25438 initializer (omp_priv = initializer)
25439 initializer (function-name (argument-list)) */
25440
25441static void
25442c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
25443{
25444 unsigned int tokens_avail = 0, i;
25445 c_token *saved_tokens = NULL;
25446 vec<tree> types = vNULL;
25447 vec<c_token> clauses = vNULL;
25448 enum tree_code reduc_code = ERROR_MARK;
25449 tree reduc_id = NULL_TREE;
25450 tree type;
25451 location_t rloc = c_parser_peek_token (parser)->location;
25452
25453 if (context == pragma_struct || context == pragma_param)
25454 {
25455 error ("%<#pragma omp declare reduction%> not at file or block scope");
25456 goto fail;
25457 }
25458
25459 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
25460 goto fail;
25461
25462 switch (c_parser_peek_token (parser)->type)
25463 {
25464 case CPP_PLUS:
25465 reduc_code = PLUS_EXPR;
25466 break;
25467 case CPP_MULT:
25468 reduc_code = MULT_EXPR;
25469 break;
25470 case CPP_MINUS:
25471 reduc_code = MINUS_EXPR;
25472 break;
25473 case CPP_AND:
25474 reduc_code = BIT_AND_EXPR;
25475 break;
25476 case CPP_XOR:
25477 reduc_code = BIT_XOR_EXPR;
25478 break;
25479 case CPP_OR:
25480 reduc_code = BIT_IOR_EXPR;
25481 break;
25482 case CPP_AND_AND:
25483 reduc_code = TRUTH_ANDIF_EXPR;
25484 break;
25485 case CPP_OR_OR:
25486 reduc_code = TRUTH_ORIF_EXPR;
25487 break;
25488 case CPP_NAME:
25489 const char *p;
25490 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25491 if (strcmp (s1: p, s2: "min") == 0)
25492 {
25493 reduc_code = MIN_EXPR;
25494 break;
25495 }
25496 if (strcmp (s1: p, s2: "max") == 0)
25497 {
25498 reduc_code = MAX_EXPR;
25499 break;
25500 }
25501 reduc_id = c_parser_peek_token (parser)->value;
25502 break;
25503 default:
25504 c_parser_error (parser,
25505 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
25506 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
25507 goto fail;
25508 }
25509
25510 tree orig_reduc_id, reduc_decl;
25511 orig_reduc_id = reduc_id;
25512 reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
25513 reduc_decl = c_omp_reduction_decl (reduc_id);
25514 c_parser_consume_token (parser);
25515
25516 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
25517 goto fail;
25518
25519 while (true)
25520 {
25521 location_t loc = c_parser_peek_token (parser)->location;
25522 struct c_type_name *ctype = c_parser_type_name (parser);
25523 if (ctype != NULL)
25524 {
25525 type = groktypename (ctype, NULL, NULL);
25526 if (type == error_mark_node)
25527 ;
25528 else if ((INTEGRAL_TYPE_P (type)
25529 || SCALAR_FLOAT_TYPE_P (type)
25530 || TREE_CODE (type) == COMPLEX_TYPE)
25531 && orig_reduc_id == NULL_TREE)
25532 error_at (loc, "predeclared arithmetic type in "
25533 "%<#pragma omp declare reduction%>");
25534 else if (TREE_CODE (type) == FUNCTION_TYPE
25535 || TREE_CODE (type) == ARRAY_TYPE)
25536 error_at (loc, "function or array type in "
25537 "%<#pragma omp declare reduction%>");
25538 else if (TYPE_ATOMIC (type))
25539 error_at (loc, "%<_Atomic%> qualified type in "
25540 "%<#pragma omp declare reduction%>");
25541 else if (TYPE_QUALS_NO_ADDR_SPACE (type))
25542 error_at (loc, "const, volatile or restrict qualified type in "
25543 "%<#pragma omp declare reduction%>");
25544 else
25545 {
25546 tree t;
25547 for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
25548 if (comptypes (TREE_PURPOSE (t), type))
25549 {
25550 error_at (loc, "redeclaration of %qs "
25551 "%<#pragma omp declare reduction%> for "
25552 "type %qT",
25553 IDENTIFIER_POINTER (reduc_id)
25554 + sizeof ("omp declare reduction ") - 1,
25555 type);
25556 location_t ploc
25557 = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
25558 0));
25559 error_at (ploc, "previous %<#pragma omp declare "
25560 "reduction%>");
25561 break;
25562 }
25563 if (t == NULL_TREE)
25564 types.safe_push (obj: type);
25565 }
25566 if (c_parser_next_token_is (parser, type: CPP_COMMA))
25567 c_parser_consume_token (parser);
25568 else
25569 break;
25570 }
25571 else
25572 break;
25573 }
25574
25575 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>")
25576 || types.is_empty ())
25577 {
25578 fail:
25579 clauses.release ();
25580 types.release ();
25581 while (true)
25582 {
25583 c_token *token = c_parser_peek_token (parser);
25584 if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
25585 break;
25586 c_parser_consume_token (parser);
25587 }
25588 c_parser_skip_to_pragma_eol (parser);
25589 return;
25590 }
25591
25592 if (types.length () > 1)
25593 {
25594 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25595 {
25596 c_token *token = c_parser_peek_token (parser);
25597 if (token->type == CPP_EOF)
25598 goto fail;
25599 clauses.safe_push (obj: *token);
25600 c_parser_consume_token (parser);
25601 }
25602 clauses.safe_push (obj: *c_parser_peek_token (parser));
25603 c_parser_skip_to_pragma_eol (parser);
25604
25605 /* Make sure nothing tries to read past the end of the tokens. */
25606 c_token eof_token;
25607 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
25608 eof_token.type = CPP_EOF;
25609 clauses.safe_push (obj: eof_token);
25610 clauses.safe_push (obj: eof_token);
25611 }
25612
25613 int errs = errorcount;
25614 FOR_EACH_VEC_ELT (types, i, type)
25615 {
25616 saved_tokens = parser->tokens;
25617 tokens_avail = parser->tokens_avail;
25618 if (!clauses.is_empty ())
25619 {
25620 parser->tokens = clauses.address ();
25621 parser->tokens_avail = clauses.length ();
25622 parser->in_pragma = true;
25623 }
25624
25625 bool nested = current_function_decl != NULL_TREE;
25626 if (nested)
25627 c_push_function_context ();
25628 tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
25629 reduc_id, default_function_type);
25630 current_function_decl = fndecl;
25631 allocate_struct_function (fndecl, true);
25632 push_scope ();
25633 tree stmt = push_stmt_list ();
25634 /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
25635 warn about these. */
25636 tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
25637 get_identifier ("omp_out"), type);
25638 DECL_ARTIFICIAL (omp_out) = 1;
25639 DECL_CONTEXT (omp_out) = fndecl;
25640 pushdecl (omp_out);
25641 tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
25642 get_identifier ("omp_in"), type);
25643 DECL_ARTIFICIAL (omp_in) = 1;
25644 DECL_CONTEXT (omp_in) = fndecl;
25645 pushdecl (omp_in);
25646 struct c_expr combiner = c_parser_expression (parser);
25647 struct c_expr initializer;
25648 tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
25649 bool bad = false;
25650 initializer.set_error ();
25651 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
25652 bad = true;
25653 else if (c_parser_next_token_is (parser, type: CPP_COMMA)
25654 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25655 c_parser_consume_token (parser);
25656 if (!bad
25657 && (c_parser_next_token_is (parser, type: CPP_NAME)
25658 && strcmp (IDENTIFIER_POINTER
25659 (c_parser_peek_token (parser)->value),
25660 s2: "initializer") == 0))
25661 {
25662 c_parser_consume_token (parser);
25663 pop_scope ();
25664 push_scope ();
25665 omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
25666 get_identifier ("omp_priv"), type);
25667 DECL_ARTIFICIAL (omp_priv) = 1;
25668 DECL_INITIAL (omp_priv) = error_mark_node;
25669 DECL_CONTEXT (omp_priv) = fndecl;
25670 pushdecl (omp_priv);
25671 omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
25672 get_identifier ("omp_orig"), type);
25673 DECL_ARTIFICIAL (omp_orig) = 1;
25674 DECL_CONTEXT (omp_orig) = fndecl;
25675 pushdecl (omp_orig);
25676 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
25677 bad = true;
25678 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
25679 {
25680 c_parser_error (parser, gmsgid: "expected %<omp_priv%> or "
25681 "function-name");
25682 bad = true;
25683 }
25684 else if (strcmp (IDENTIFIER_POINTER
25685 (c_parser_peek_token (parser)->value),
25686 s2: "omp_priv") != 0)
25687 {
25688 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
25689 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
25690 {
25691 c_parser_error (parser, gmsgid: "expected function-name %<(%>");
25692 bad = true;
25693 }
25694 else
25695 initializer = c_parser_postfix_expression (parser);
25696 if (initializer.value
25697 && TREE_CODE (initializer.value) == CALL_EXPR)
25698 {
25699 int j;
25700 tree c = initializer.value;
25701 for (j = 0; j < call_expr_nargs (c); j++)
25702 {
25703 tree a = CALL_EXPR_ARG (c, j);
25704 STRIP_NOPS (a);
25705 if (TREE_CODE (a) == ADDR_EXPR
25706 && TREE_OPERAND (a, 0) == omp_priv)
25707 break;
25708 }
25709 if (j == call_expr_nargs (c))
25710 error ("one of the initializer call arguments should be "
25711 "%<&omp_priv%>");
25712 }
25713 }
25714 else
25715 {
25716 c_parser_consume_token (parser);
25717 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
25718 bad = true;
25719 else
25720 {
25721 tree st = push_stmt_list ();
25722 location_t loc = c_parser_peek_token (parser)->location;
25723 rich_location richloc (line_table, loc);
25724 start_init (omp_priv, NULL_TREE, false, false, &richloc);
25725 struct c_expr init = c_parser_initializer (parser, decl: omp_priv);
25726 finish_init ();
25727 finish_decl (omp_priv, loc, init.value,
25728 init.original_type, NULL_TREE);
25729 pop_stmt_list (st);
25730 }
25731 }
25732 if (!bad
25733 && !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
25734 bad = true;
25735 }
25736
25737 if (!bad)
25738 {
25739 c_parser_skip_to_pragma_eol (parser);
25740
25741 tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
25742 DECL_INITIAL (reduc_decl));
25743 DECL_INITIAL (reduc_decl) = t;
25744 DECL_SOURCE_LOCATION (omp_out) = rloc;
25745 TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
25746 TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
25747 TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
25748 walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
25749 &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
25750 if (omp_priv)
25751 {
25752 DECL_SOURCE_LOCATION (omp_priv) = rloc;
25753 TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
25754 TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
25755 TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
25756 walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
25757 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
25758 walk_tree (&DECL_INITIAL (omp_priv),
25759 c_check_omp_declare_reduction_r,
25760 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
25761 }
25762 }
25763
25764 pop_stmt_list (stmt);
25765 pop_scope ();
25766 if (cfun->language != NULL)
25767 {
25768 ggc_free (cfun->language);
25769 cfun->language = NULL;
25770 }
25771 set_cfun (NULL);
25772 current_function_decl = NULL_TREE;
25773 if (nested)
25774 c_pop_function_context ();
25775
25776 if (!clauses.is_empty ())
25777 {
25778 parser->tokens = saved_tokens;
25779 parser->tokens_avail = tokens_avail;
25780 }
25781 if (bad)
25782 goto fail;
25783 if (errs != errorcount)
25784 break;
25785 }
25786
25787 clauses.release ();
25788 types.release ();
25789}
25790
25791
25792/* OpenMP 4.0
25793 #pragma omp declare simd declare-simd-clauses[optseq] new-line
25794 #pragma omp declare reduction (reduction-id : typename-list : expression) \
25795 initializer-clause[opt] new-line
25796 #pragma omp declare target new-line
25797
25798 OpenMP 5.0
25799 #pragma omp declare variant (identifier) match (context-selector) */
25800
25801static bool
25802c_parser_omp_declare (c_parser *parser, enum pragma_context context)
25803{
25804 c_parser_consume_pragma (parser);
25805 if (c_parser_next_token_is (parser, type: CPP_NAME))
25806 {
25807 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25808 if (strcmp (s1: p, s2: "simd") == 0)
25809 {
25810 /* c_parser_consume_token (parser); done in
25811 c_parser_omp_declare_simd. */
25812 c_parser_omp_declare_simd (parser, context);
25813 return true;
25814 }
25815 if (strcmp (s1: p, s2: "reduction") == 0)
25816 {
25817 c_parser_consume_token (parser);
25818 c_parser_omp_declare_reduction (parser, context);
25819 return false;
25820 }
25821 if (!flag_openmp) /* flag_openmp_simd */
25822 {
25823 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25824 return false;
25825 }
25826 if (strcmp (s1: p, s2: "target") == 0)
25827 {
25828 c_parser_consume_token (parser);
25829 c_parser_omp_declare_target (parser);
25830 return false;
25831 }
25832 if (strcmp (s1: p, s2: "variant") == 0)
25833 {
25834 /* c_parser_consume_token (parser); done in
25835 c_parser_omp_declare_simd. */
25836 c_parser_omp_declare_simd (parser, context);
25837 return true;
25838 }
25839 }
25840
25841 c_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, "
25842 "%<target%> or %<variant%>");
25843 c_parser_skip_to_pragma_eol (parser);
25844 return false;
25845}
25846
25847/* OpenMP 5.0
25848 #pragma omp requires clauses[optseq] new-line */
25849
25850static void
25851c_parser_omp_requires (c_parser *parser)
25852{
25853 enum omp_requires new_req = (enum omp_requires) 0;
25854
25855 c_parser_consume_pragma (parser);
25856
25857 location_t loc = c_parser_peek_token (parser)->location;
25858 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25859 {
25860 if (c_parser_next_token_is (parser, type: CPP_COMMA)
25861 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25862 c_parser_consume_token (parser);
25863
25864 if (c_parser_next_token_is (parser, type: CPP_NAME))
25865 {
25866 const char *p
25867 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25868 location_t cloc = c_parser_peek_token (parser)->location;
25869 enum omp_requires this_req = (enum omp_requires) 0;
25870
25871 if (!strcmp (s1: p, s2: "unified_address"))
25872 this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
25873 else if (!strcmp (s1: p, s2: "unified_shared_memory"))
25874 this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
25875 else if (!strcmp (s1: p, s2: "dynamic_allocators"))
25876 this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
25877 else if (!strcmp (s1: p, s2: "reverse_offload"))
25878 this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
25879 else if (!strcmp (s1: p, s2: "atomic_default_mem_order"))
25880 {
25881 c_parser_consume_token (parser);
25882
25883 matching_parens parens;
25884 if (parens.require_open (parser))
25885 {
25886 if (c_parser_next_token_is (parser, type: CPP_NAME))
25887 {
25888 tree v = c_parser_peek_token (parser)->value;
25889 p = IDENTIFIER_POINTER (v);
25890
25891 if (!strcmp (s1: p, s2: "seq_cst"))
25892 this_req
25893 = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
25894 else if (!strcmp (s1: p, s2: "relaxed"))
25895 this_req
25896 = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
25897 else if (!strcmp (s1: p, s2: "release"))
25898 this_req
25899 = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
25900 else if (!strcmp (s1: p, s2: "acq_rel"))
25901 this_req
25902 = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
25903 else if (!strcmp (s1: p, s2: "acquire"))
25904 this_req
25905 = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
25906 }
25907 if (this_req == 0)
25908 {
25909 error_at (c_parser_peek_token (parser)->location,
25910 "expected %<acq_rel%>, %<acquire%>, "
25911 "%<relaxed%>, %<release%> or %<seq_cst%>");
25912 switch (c_parser_peek_token (parser)->type)
25913 {
25914 case CPP_EOF:
25915 case CPP_PRAGMA_EOL:
25916 case CPP_CLOSE_PAREN:
25917 break;
25918 default:
25919 if (c_parser_peek_2nd_token (parser)->type
25920 == CPP_CLOSE_PAREN)
25921 c_parser_consume_token (parser);
25922 break;
25923 }
25924 }
25925 else
25926 c_parser_consume_token (parser);
25927
25928 parens.skip_until_found_close (parser);
25929 if (this_req == 0)
25930 {
25931 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25932 return;
25933 }
25934 }
25935 p = NULL;
25936 }
25937 else
25938 {
25939 error_at (cloc, "expected %<unified_address%>, "
25940 "%<unified_shared_memory%>, "
25941 "%<dynamic_allocators%>, "
25942 "%<reverse_offload%> "
25943 "or %<atomic_default_mem_order%> clause");
25944 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25945 return;
25946 }
25947 if (p)
25948 c_parser_consume_token (parser);
25949 if (this_req)
25950 {
25951 if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25952 {
25953 if ((this_req & new_req) != 0)
25954 error_at (cloc, "too many %qs clauses", p);
25955 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
25956 && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
25957 error_at (cloc, "%qs clause used lexically after first "
25958 "target construct or offloading API", p);
25959 }
25960 else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25961 {
25962 error_at (cloc, "too many %qs clauses",
25963 "atomic_default_mem_order");
25964 this_req = (enum omp_requires) 0;
25965 }
25966 else if ((omp_requires_mask
25967 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25968 {
25969 error_at (cloc, "more than one %<atomic_default_mem_order%>"
25970 " clause in a single compilation unit");
25971 this_req
25972 = (enum omp_requires)
25973 (omp_requires_mask
25974 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
25975 }
25976 else if ((omp_requires_mask
25977 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
25978 error_at (cloc, "%<atomic_default_mem_order%> clause used "
25979 "lexically after first %<atomic%> construct "
25980 "without memory order clause");
25981 new_req = (enum omp_requires) (new_req | this_req);
25982 omp_requires_mask
25983 = (enum omp_requires) (omp_requires_mask | this_req);
25984 continue;
25985 }
25986 }
25987 break;
25988 }
25989 c_parser_skip_to_pragma_eol (parser);
25990
25991 if (new_req == 0)
25992 error_at (loc, "%<pragma omp requires%> requires at least one clause");
25993}
25994
25995/* Helper function for c_parser_omp_taskloop.
25996 Disallow zero sized or potentially zero sized task reductions. */
25997
25998static tree
25999c_finish_taskloop_clauses (tree clauses)
26000{
26001 tree *pc = &clauses;
26002 for (tree c = clauses; c; c = *pc)
26003 {
26004 bool remove = false;
26005 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
26006 {
26007 tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
26008 if (integer_zerop (TYPE_SIZE_UNIT (type)))
26009 {
26010 error_at (OMP_CLAUSE_LOCATION (c),
26011 "zero sized type %qT in %<reduction%> clause", type);
26012 remove = true;
26013 }
26014 else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
26015 {
26016 error_at (OMP_CLAUSE_LOCATION (c),
26017 "variable sized type %qT in %<reduction%> clause",
26018 type);
26019 remove = true;
26020 }
26021 }
26022 if (remove)
26023 *pc = OMP_CLAUSE_CHAIN (c);
26024 else
26025 pc = &OMP_CLAUSE_CHAIN (c);
26026 }
26027 return clauses;
26028}
26029
26030/* OpenMP 4.5:
26031 #pragma omp taskloop taskloop-clause[optseq] new-line
26032 for-loop
26033
26034 #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
26035 for-loop */
26036
26037#define OMP_TASKLOOP_CLAUSE_MASK \
26038 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26039 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26040 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26041 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26042 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
26043 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
26044 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
26045 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
26046 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
26047 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26048 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
26049 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
26050 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
26051 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
26052 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26053 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26054 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
26055
26056static tree
26057c_parser_omp_taskloop (location_t loc, c_parser *parser,
26058 char *p_name, omp_clause_mask mask, tree *cclauses,
26059 bool *if_p)
26060{
26061 tree clauses, block, ret;
26062
26063 strcat (dest: p_name, src: " taskloop");
26064 mask |= OMP_TASKLOOP_CLAUSE_MASK;
26065 /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
26066 clause. */
26067 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
26068 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
26069
26070 if (c_parser_next_token_is (parser, type: CPP_NAME))
26071 {
26072 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26073
26074 if (strcmp (s1: p, s2: "simd") == 0)
26075 {
26076 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26077 if (cclauses == NULL)
26078 cclauses = cclauses_buf;
26079 c_parser_consume_token (parser);
26080 if (!flag_openmp) /* flag_openmp_simd */
26081 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26082 if_p);
26083 block = c_begin_compound_stmt (true);
26084 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
26085 block = c_end_compound_stmt (loc, block, true);
26086 if (ret == NULL)
26087 return ret;
26088 ret = make_node (OMP_TASKLOOP);
26089 TREE_TYPE (ret) = void_type_node;
26090 OMP_FOR_BODY (ret) = block;
26091 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
26092 OMP_FOR_CLAUSES (ret)
26093 = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
26094 SET_EXPR_LOCATION (ret, loc);
26095 add_stmt (ret);
26096 return ret;
26097 }
26098 }
26099 if (!flag_openmp) /* flag_openmp_simd */
26100 {
26101 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26102 return NULL_TREE;
26103 }
26104
26105 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26106 if (cclauses)
26107 {
26108 omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses);
26109 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
26110 }
26111
26112 clauses = c_finish_taskloop_clauses (clauses);
26113 block = c_begin_compound_stmt (true);
26114 ret = c_parser_omp_for_loop (loc, parser, code: OMP_TASKLOOP, clauses, NULL, if_p);
26115 block = c_end_compound_stmt (loc, block, true);
26116 add_stmt (block);
26117
26118 return ret;
26119}
26120
26121/* OpenMP 5.1
26122 #pragma omp nothing new-line */
26123
26124static void
26125c_parser_omp_nothing (c_parser *parser)
26126{
26127 c_parser_consume_pragma (parser);
26128 c_parser_skip_to_pragma_eol (parser);
26129}
26130
26131/* OpenMP 5.1
26132 #pragma omp error clauses[optseq] new-line */
26133
26134static bool
26135c_parser_omp_error (c_parser *parser, enum pragma_context context)
26136{
26137 int at_compilation = -1;
26138 int severity_fatal = -1;
26139 tree message = NULL_TREE;
26140 bool bad = false;
26141 location_t loc = c_parser_peek_token (parser)->location;
26142
26143 c_parser_consume_pragma (parser);
26144
26145 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
26146 {
26147 if (c_parser_next_token_is (parser, type: CPP_COMMA)
26148 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
26149 c_parser_consume_token (parser);
26150
26151 if (!c_parser_next_token_is (parser, type: CPP_NAME))
26152 break;
26153
26154 const char *p
26155 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26156 location_t cloc = c_parser_peek_token (parser)->location;
26157 static const char *args[] = {
26158 "execution", "compilation", "warning", "fatal"
26159 };
26160 int *v = NULL;
26161 int idx = 0, n = -1;
26162 tree m = NULL_TREE;
26163
26164 if (!strcmp (s1: p, s2: "at"))
26165 v = &at_compilation;
26166 else if (!strcmp (s1: p, s2: "severity"))
26167 {
26168 v = &severity_fatal;
26169 idx += 2;
26170 }
26171 else if (strcmp (s1: p, s2: "message"))
26172 {
26173 error_at (cloc,
26174 "expected %<at%>, %<severity%> or %<message%> clause");
26175 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26176 return false;
26177 }
26178
26179 c_parser_consume_token (parser);
26180
26181 matching_parens parens;
26182 if (parens.require_open (parser))
26183 {
26184 if (v == NULL)
26185 {
26186 location_t expr_loc = c_parser_peek_token (parser)->location;
26187 c_expr expr = c_parser_expr_no_commas (parser, NULL);
26188 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
26189 m = convert (const_string_type_node, expr.value);
26190 m = c_fully_fold (m, false, NULL);
26191 }
26192 else
26193 {
26194 if (c_parser_next_token_is (parser, type: CPP_NAME))
26195 {
26196 tree val = c_parser_peek_token (parser)->value;
26197 const char *q = IDENTIFIER_POINTER (val);
26198
26199 if (!strcmp (s1: q, s2: args[idx]))
26200 n = 0;
26201 else if (!strcmp (s1: q, s2: args[idx + 1]))
26202 n = 1;
26203 }
26204 if (n == -1)
26205 {
26206 error_at (c_parser_peek_token (parser)->location,
26207 "expected %qs or %qs", args[idx], args[idx + 1]);
26208 bad = true;
26209 switch (c_parser_peek_token (parser)->type)
26210 {
26211 case CPP_EOF:
26212 case CPP_PRAGMA_EOL:
26213 case CPP_CLOSE_PAREN:
26214 break;
26215 default:
26216 if (c_parser_peek_2nd_token (parser)->type
26217 == CPP_CLOSE_PAREN)
26218 c_parser_consume_token (parser);
26219 break;
26220 }
26221 }
26222 else
26223 c_parser_consume_token (parser);
26224 }
26225
26226 parens.skip_until_found_close (parser);
26227
26228 if (v == NULL)
26229 {
26230 if (message)
26231 {
26232 error_at (cloc, "too many %qs clauses", p);
26233 bad = true;
26234 }
26235 else
26236 message = m;
26237 }
26238 else if (n != -1)
26239 {
26240 if (*v != -1)
26241 {
26242 error_at (cloc, "too many %qs clauses", p);
26243 bad = true;
26244 }
26245 else
26246 *v = n;
26247 }
26248 }
26249 else
26250 bad = true;
26251 }
26252 c_parser_skip_to_pragma_eol (parser);
26253 if (bad)
26254 return true;
26255
26256 if (at_compilation == -1)
26257 at_compilation = 1;
26258 if (severity_fatal == -1)
26259 severity_fatal = 1;
26260 if (!at_compilation)
26261 {
26262 if (context != pragma_compound)
26263 {
26264 error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
26265 "may only be used in compound statements");
26266 return true;
26267 }
26268 tree fndecl
26269 = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR
26270 : BUILT_IN_GOMP_WARNING);
26271 if (!message)
26272 message = build_zero_cst (const_string_type_node);
26273 tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
26274 build_all_ones_cst (size_type_node));
26275 add_stmt (stmt);
26276 return true;
26277 }
26278 const char *msg = NULL;
26279 if (message)
26280 {
26281 msg = c_getstr (message);
26282 if (msg == NULL)
26283 msg = _("<message unknown at compile time>");
26284 }
26285 if (msg)
26286 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
26287 "%<pragma omp error%> encountered: %s", msg);
26288 else
26289 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
26290 "%<pragma omp error%> encountered");
26291 return false;
26292}
26293
26294/* Assumption clauses:
26295 OpenMP 5.1
26296 absent (directive-name-list)
26297 contains (directive-name-list)
26298 holds (expression)
26299 no_openmp
26300 no_openmp_routines
26301 no_parallelism */
26302
26303static void
26304c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
26305{
26306 bool no_openmp = false;
26307 bool no_openmp_routines = false;
26308 bool no_parallelism = false;
26309 bitmap_head absent_head, contains_head;
26310
26311 bitmap_obstack_initialize (NULL);
26312 bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack);
26313 bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack);
26314
26315 if (c_parser_next_token_is (parser, type: CPP_PRAGMA_EOL))
26316 error_at (c_parser_peek_token (parser)->location,
26317 "expected at least one assumption clause");
26318
26319 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
26320 {
26321 if (c_parser_next_token_is (parser, type: CPP_COMMA)
26322 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
26323 c_parser_consume_token (parser);
26324
26325 if (!c_parser_next_token_is (parser, type: CPP_NAME))
26326 break;
26327
26328 const char *p
26329 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26330 location_t cloc = c_parser_peek_token (parser)->location;
26331
26332 if (!strcmp (s1: p, s2: "no_openmp"))
26333 {
26334 c_parser_consume_token (parser);
26335 if (no_openmp)
26336 error_at (cloc, "too many %qs clauses", "no_openmp");
26337 no_openmp = true;
26338 }
26339 else if (!strcmp (s1: p, s2: "no_openmp_routines"))
26340 {
26341 c_parser_consume_token (parser);
26342 if (no_openmp_routines)
26343 error_at (cloc, "too many %qs clauses", "no_openmp_routines");
26344 no_openmp_routines = true;
26345 }
26346 else if (!strcmp (s1: p, s2: "no_parallelism"))
26347 {
26348 c_parser_consume_token (parser);
26349 if (no_parallelism)
26350 error_at (cloc, "too many %qs clauses", "no_parallelism");
26351 no_parallelism = true;
26352 }
26353 else if (!strcmp (s1: p, s2: "holds"))
26354 {
26355 c_parser_consume_token (parser);
26356 matching_parens parens;
26357 if (parens.require_open (parser))
26358 {
26359 location_t eloc = c_parser_peek_token (parser)->location;
26360 c_expr expr = c_parser_expr_no_commas (parser, NULL);
26361 tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
26362 t = c_objc_common_truthvalue_conversion (eloc, t);
26363 t = c_fully_fold (t, false, NULL);
26364 if (is_assume && t != error_mark_node)
26365 {
26366 tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
26367 void_type_node, 1,
26368 t);
26369 add_stmt (fn);
26370 }
26371 parens.skip_until_found_close (parser);
26372 }
26373 }
26374 else if (!strcmp (s1: p, s2: "absent") || !strcmp (s1: p, s2: "contains"))
26375 {
26376 c_parser_consume_token (parser);
26377 matching_parens parens;
26378 if (parens.require_open (parser))
26379 {
26380 do
26381 {
26382 const char *directive[3] = {};
26383 int i;
26384 location_t dloc = c_parser_peek_token (parser)->location;
26385 for (i = 0; i < 3; i++)
26386 {
26387 tree id;
26388 if (c_parser_peek_nth_token (parser, n: i + 1)->type
26389 == CPP_NAME)
26390 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
26391 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
26392 != RID_MAX)
26393 {
26394 enum rid rid
26395 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
26396 id = ridpointers[rid];
26397 }
26398 else
26399 break;
26400 directive[i] = IDENTIFIER_POINTER (id);
26401 }
26402 if (i == 0)
26403 error_at (dloc, "expected directive name");
26404 else
26405 {
26406 const struct c_omp_directive *dir
26407 = c_omp_categorize_directive (directive[0],
26408 directive[1],
26409 directive[2]);
26410 if (dir == NULL
26411 || dir->kind == C_OMP_DIR_DECLARATIVE
26412 || dir->kind == C_OMP_DIR_INFORMATIONAL
26413 || dir->id == PRAGMA_OMP_END
26414 || (!dir->second && directive[1])
26415 || (!dir->third && directive[2]))
26416 error_at (dloc, "unknown OpenMP directive name in "
26417 "%qs clause argument", p);
26418 else
26419 {
26420 int id = dir - c_omp_directives;
26421 if (bitmap_bit_p (p[0] == 'a' ? &contains_head
26422 : &absent_head, id))
26423 error_at (dloc, "%<%s%s%s%s%s%> directive "
26424 "mentioned in both %<absent%> and "
26425 "%<contains%> clauses",
26426 directive[0],
26427 directive[1] ? " " : "",
26428 directive[1] ? directive[1] : "",
26429 directive[2] ? " " : "",
26430 directive[2] ? directive[2] : "");
26431 else if (!bitmap_set_bit (p[0] == 'a'
26432 ? &absent_head
26433 : &contains_head, id))
26434 error_at (dloc, "%<%s%s%s%s%s%> directive "
26435 "mentioned multiple times in %qs "
26436 "clauses",
26437 directive[0],
26438 directive[1] ? " " : "",
26439 directive[1] ? directive[1] : "",
26440 directive[2] ? " " : "",
26441 directive[2] ? directive[2] : "", p);
26442 }
26443 for (; i; --i)
26444 c_parser_consume_token (parser);
26445 }
26446 if (c_parser_next_token_is (parser, type: CPP_COMMA))
26447 c_parser_consume_token (parser);
26448 else
26449 break;
26450 }
26451 while (1);
26452 parens.skip_until_found_close (parser);
26453 }
26454 }
26455 else if (startswith (str: p, prefix: "ext_"))
26456 {
26457 warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
26458 c_parser_consume_token (parser);
26459 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
26460 {
26461 matching_parens parens;
26462 parens.consume_open (parser);
26463 c_parser_balanced_token_sequence (parser);
26464 parens.require_close (parser);
26465 }
26466 }
26467 else
26468 {
26469 c_parser_consume_token (parser);
26470 error_at (cloc, "expected assumption clause");
26471 break;
26472 }
26473 }
26474 c_parser_skip_to_pragma_eol (parser);
26475}
26476
26477/* OpenMP 5.1
26478 #pragma omp assume clauses[optseq] new-line */
26479
26480static void
26481c_parser_omp_assume (c_parser *parser, bool *if_p)
26482{
26483 c_parser_omp_assumption_clauses (parser, is_assume: true);
26484 add_stmt (c_parser_omp_structured_block (parser, if_p));
26485}
26486
26487/* OpenMP 5.1
26488 #pragma omp assumes clauses[optseq] new-line */
26489
26490static void
26491c_parser_omp_assumes (c_parser *parser)
26492{
26493 c_parser_consume_pragma (parser);
26494 c_parser_omp_assumption_clauses (parser, is_assume: false);
26495}
26496
26497/* Main entry point to parsing most OpenMP pragmas. */
26498
26499static void
26500c_parser_omp_construct (c_parser *parser, bool *if_p)
26501{
26502 enum pragma_kind p_kind;
26503 location_t loc;
26504 tree stmt;
26505 char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
26506 omp_clause_mask mask (0);
26507
26508 loc = c_parser_peek_token (parser)->location;
26509 p_kind = c_parser_peek_token (parser)->pragma_kind;
26510 c_parser_consume_pragma (parser);
26511
26512 switch (p_kind)
26513 {
26514 case PRAGMA_OACC_ATOMIC:
26515 c_parser_omp_atomic (loc, parser, openacc: true);
26516 return;
26517 case PRAGMA_OACC_CACHE:
26518 strcpy (dest: p_name, src: "#pragma acc");
26519 stmt = c_parser_oacc_cache (loc, parser);
26520 break;
26521 case PRAGMA_OACC_DATA:
26522 stmt = c_parser_oacc_data (loc, parser, if_p);
26523 break;
26524 case PRAGMA_OACC_HOST_DATA:
26525 stmt = c_parser_oacc_host_data (loc, parser, if_p);
26526 break;
26527 case PRAGMA_OACC_KERNELS:
26528 case PRAGMA_OACC_PARALLEL:
26529 case PRAGMA_OACC_SERIAL:
26530 strcpy (dest: p_name, src: "#pragma acc");
26531 stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
26532 break;
26533 case PRAGMA_OACC_LOOP:
26534 strcpy (dest: p_name, src: "#pragma acc");
26535 stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
26536 break;
26537 case PRAGMA_OACC_WAIT:
26538 strcpy (dest: p_name, src: "#pragma wait");
26539 stmt = c_parser_oacc_wait (loc, parser, p_name);
26540 break;
26541 case PRAGMA_OMP_ATOMIC:
26542 c_parser_omp_atomic (loc, parser, openacc: false);
26543 return;
26544 case PRAGMA_OMP_CRITICAL:
26545 stmt = c_parser_omp_critical (loc, parser, if_p);
26546 break;
26547 case PRAGMA_OMP_DISTRIBUTE:
26548 strcpy (dest: p_name, src: "#pragma omp");
26549 stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
26550 break;
26551 case PRAGMA_OMP_FOR:
26552 strcpy (dest: p_name, src: "#pragma omp");
26553 stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
26554 break;
26555 case PRAGMA_OMP_LOOP:
26556 strcpy (dest: p_name, src: "#pragma omp");
26557 stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
26558 break;
26559 case PRAGMA_OMP_MASKED:
26560 strcpy (dest: p_name, src: "#pragma omp");
26561 stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
26562 break;
26563 case PRAGMA_OMP_MASTER:
26564 strcpy (dest: p_name, src: "#pragma omp");
26565 stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
26566 break;
26567 case PRAGMA_OMP_PARALLEL:
26568 strcpy (dest: p_name, src: "#pragma omp");
26569 stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
26570 break;
26571 case PRAGMA_OMP_SCOPE:
26572 stmt = c_parser_omp_scope (loc, parser, if_p);
26573 break;
26574 case PRAGMA_OMP_SECTIONS:
26575 strcpy (dest: p_name, src: "#pragma omp");
26576 stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
26577 break;
26578 case PRAGMA_OMP_SIMD:
26579 strcpy (dest: p_name, src: "#pragma omp");
26580 stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
26581 break;
26582 case PRAGMA_OMP_SINGLE:
26583 stmt = c_parser_omp_single (loc, parser, if_p);
26584 break;
26585 case PRAGMA_OMP_TASK:
26586 stmt = c_parser_omp_task (loc, parser, if_p);
26587 break;
26588 case PRAGMA_OMP_TASKGROUP:
26589 stmt = c_parser_omp_taskgroup (loc, parser, if_p);
26590 break;
26591 case PRAGMA_OMP_TASKLOOP:
26592 strcpy (dest: p_name, src: "#pragma omp");
26593 stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
26594 break;
26595 case PRAGMA_OMP_TEAMS:
26596 strcpy (dest: p_name, src: "#pragma omp");
26597 stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
26598 break;
26599 case PRAGMA_OMP_ASSUME:
26600 c_parser_omp_assume (parser, if_p);
26601 return;
26602 default:
26603 gcc_unreachable ();
26604 }
26605
26606 if (stmt && stmt != error_mark_node)
26607 gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
26608}
26609
26610
26611/* OpenMP 2.5:
26612 # pragma omp threadprivate (variable-list) */
26613
26614static void
26615c_parser_omp_threadprivate (c_parser *parser)
26616{
26617 tree vars, t;
26618 location_t loc;
26619
26620 c_parser_consume_pragma (parser);
26621 loc = c_parser_peek_token (parser)->location;
26622 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
26623
26624 /* Mark every variable in VARS to be assigned thread local storage. */
26625 for (t = vars; t; t = TREE_CHAIN (t))
26626 {
26627 tree v = TREE_PURPOSE (t);
26628
26629 /* FIXME diagnostics: Ideally we should keep individual
26630 locations for all the variables in the var list to make the
26631 following errors more precise. Perhaps
26632 c_parser_omp_var_list_parens() should construct a list of
26633 locations to go along with the var list. */
26634
26635 /* If V had already been marked threadprivate, it doesn't matter
26636 whether it had been used prior to this point. */
26637 if (!VAR_P (v))
26638 error_at (loc, "%qD is not a variable", v);
26639 else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
26640 error_at (loc, "%qE declared %<threadprivate%> after first use", v);
26641 else if (! is_global_var (t: v))
26642 error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
26643 else if (TREE_TYPE (v) == error_mark_node)
26644 ;
26645 else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
26646 error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
26647 else
26648 {
26649 if (! DECL_THREAD_LOCAL_P (v))
26650 {
26651 set_decl_tls_model (v, decl_default_tls_model (v));
26652 /* If rtl has been already set for this var, call
26653 make_decl_rtl once again, so that encode_section_info
26654 has a chance to look at the new decl flags. */
26655 if (DECL_RTL_SET_P (v))
26656 make_decl_rtl (v);
26657 }
26658 C_DECL_THREADPRIVATE_P (v) = 1;
26659 }
26660 }
26661
26662 c_parser_skip_to_pragma_eol (parser);
26663}
26664
26665/* Parse a transaction attribute (GCC Extension).
26666
26667 transaction-attribute:
26668 gnu-attributes
26669 attribute-specifier
26670*/
26671
26672static tree
26673c_parser_transaction_attributes (c_parser *parser)
26674{
26675 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
26676 return c_parser_gnu_attributes (parser);
26677
26678 if (!c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
26679 return NULL_TREE;
26680 return c_parser_std_attribute_specifier (parser, for_tm: true);
26681}
26682
26683/* Parse a __transaction_atomic or __transaction_relaxed statement
26684 (GCC Extension).
26685
26686 transaction-statement:
26687 __transaction_atomic transaction-attribute[opt] compound-statement
26688 __transaction_relaxed compound-statement
26689
26690 Note that the only valid attribute is: "outer".
26691*/
26692
26693static tree
26694c_parser_transaction (c_parser *parser, enum rid keyword)
26695{
26696 unsigned int old_in = parser->in_transaction;
26697 unsigned int this_in = 1, new_in;
26698 location_t loc = c_parser_peek_token (parser)->location;
26699 tree stmt, attrs;
26700
26701 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
26702 || keyword == RID_TRANSACTION_RELAXED)
26703 && c_parser_next_token_is_keyword (parser, keyword));
26704 c_parser_consume_token (parser);
26705
26706 if (keyword == RID_TRANSACTION_RELAXED)
26707 this_in |= TM_STMT_ATTR_RELAXED;
26708 else
26709 {
26710 attrs = c_parser_transaction_attributes (parser);
26711 if (attrs)
26712 this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
26713 }
26714
26715 /* Keep track if we're in the lexical scope of an outer transaction. */
26716 new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
26717
26718 parser->in_transaction = new_in;
26719 stmt = c_parser_compound_statement (parser);
26720 parser->in_transaction = old_in;
26721
26722 if (flag_tm)
26723 stmt = c_finish_transaction (loc, stmt, this_in);
26724 else
26725 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
26726 "%<__transaction_atomic%> without transactional memory support enabled"
26727 : "%<__transaction_relaxed %> "
26728 "without transactional memory support enabled"));
26729
26730 return stmt;
26731}
26732
26733/* Parse a __transaction_atomic or __transaction_relaxed expression
26734 (GCC Extension).
26735
26736 transaction-expression:
26737 __transaction_atomic ( expression )
26738 __transaction_relaxed ( expression )
26739*/
26740
26741static struct c_expr
26742c_parser_transaction_expression (c_parser *parser, enum rid keyword)
26743{
26744 struct c_expr ret;
26745 unsigned int old_in = parser->in_transaction;
26746 unsigned int this_in = 1;
26747 location_t loc = c_parser_peek_token (parser)->location;
26748 tree attrs;
26749
26750 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
26751 || keyword == RID_TRANSACTION_RELAXED)
26752 && c_parser_next_token_is_keyword (parser, keyword));
26753 c_parser_consume_token (parser);
26754
26755 if (keyword == RID_TRANSACTION_RELAXED)
26756 this_in |= TM_STMT_ATTR_RELAXED;
26757 else
26758 {
26759 attrs = c_parser_transaction_attributes (parser);
26760 if (attrs)
26761 this_in |= parse_tm_stmt_attr (attrs, 0);
26762 }
26763
26764 parser->in_transaction = this_in;
26765 matching_parens parens;
26766 if (parens.require_open (parser))
26767 {
26768 tree expr = c_parser_expression (parser).value;
26769 ret.original_type = TREE_TYPE (expr);
26770 ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
26771 if (this_in & TM_STMT_ATTR_RELAXED)
26772 TRANSACTION_EXPR_RELAXED (ret.value) = 1;
26773 SET_EXPR_LOCATION (ret.value, loc);
26774 ret.original_code = TRANSACTION_EXPR;
26775 ret.m_decimal = 0;
26776 if (!parens.require_close (parser))
26777 {
26778 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
26779 goto error;
26780 }
26781 }
26782 else
26783 {
26784 error:
26785 ret.set_error ();
26786 ret.original_code = ERROR_MARK;
26787 ret.original_type = NULL;
26788 }
26789 parser->in_transaction = old_in;
26790
26791 if (!flag_tm)
26792 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
26793 "%<__transaction_atomic%> without transactional memory support enabled"
26794 : "%<__transaction_relaxed %> "
26795 "without transactional memory support enabled"));
26796
26797 set_c_expr_source_range (expr: &ret, start: loc, finish: loc);
26798
26799 return ret;
26800}
26801
26802/* Parse a __transaction_cancel statement (GCC Extension).
26803
26804 transaction-cancel-statement:
26805 __transaction_cancel transaction-attribute[opt] ;
26806
26807 Note that the only valid attribute is "outer".
26808*/
26809
26810static tree
26811c_parser_transaction_cancel (c_parser *parser)
26812{
26813 location_t loc = c_parser_peek_token (parser)->location;
26814 tree attrs;
26815 bool is_outer = false;
26816
26817 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
26818 c_parser_consume_token (parser);
26819
26820 attrs = c_parser_transaction_attributes (parser);
26821 if (attrs)
26822 is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
26823
26824 if (!flag_tm)
26825 {
26826 error_at (loc, "%<__transaction_cancel%> without "
26827 "transactional memory support enabled");
26828 goto ret_error;
26829 }
26830 else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
26831 {
26832 error_at (loc, "%<__transaction_cancel%> within a "
26833 "%<__transaction_relaxed%>");
26834 goto ret_error;
26835 }
26836 else if (is_outer)
26837 {
26838 if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
26839 && !is_tm_may_cancel_outer (current_function_decl))
26840 {
26841 error_at (loc, "outer %<__transaction_cancel%> not "
26842 "within outer %<__transaction_atomic%> or "
26843 "a %<transaction_may_cancel_outer%> function");
26844 goto ret_error;
26845 }
26846 }
26847 else if (parser->in_transaction == 0)
26848 {
26849 error_at (loc, "%<__transaction_cancel%> not within "
26850 "%<__transaction_atomic%>");
26851 goto ret_error;
26852 }
26853
26854 return add_stmt (build_tm_abort_call (loc, is_outer));
26855
26856 ret_error:
26857 return build1 (NOP_EXPR, void_type_node, error_mark_node);
26858}
26859
26860/* Parse a single source file. */
26861
26862void
26863c_parse_file (void)
26864{
26865 /* Use local storage to begin. If the first token is a pragma, parse it.
26866 If it is #pragma GCC pch_preprocess, then this will load a PCH file
26867 which will cause garbage collection. */
26868 c_parser tparser;
26869
26870 memset (s: &tparser, c: 0, n: sizeof tparser);
26871 tparser.translate_strings_p = true;
26872 tparser.tokens = &tparser.tokens_buf[0];
26873 the_parser = &tparser;
26874
26875 if (c_parser_peek_token (parser: &tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
26876 c_parser_pragma_pch_preprocess (parser: &tparser);
26877 else
26878 c_common_no_more_pch ();
26879
26880 the_parser = ggc_alloc<c_parser> ();
26881 *the_parser = tparser;
26882 if (tparser.tokens == &tparser.tokens_buf[0])
26883 the_parser->tokens = &the_parser->tokens_buf[0];
26884
26885 /* Initialize EH, if we've been told to do so. */
26886 if (flag_exceptions)
26887 using_eh_for_cleanups ();
26888
26889 c_parser_translation_unit (parser: the_parser);
26890 the_parser = NULL;
26891}
26892
26893void
26894c_init_preprocess (void)
26895{
26896 /* Create a parser for use by pragma_lex during preprocessing. */
26897 the_parser = ggc_alloc<c_parser> ();
26898 memset (s: the_parser, c: 0, n: sizeof (c_parser));
26899 the_parser->tokens = &the_parser->tokens_buf[0];
26900}
26901
26902/* Parse the body of a function declaration marked with "__RTL".
26903
26904 The RTL parser works on the level of characters read from a
26905 FILE *, whereas c_parser works at the level of tokens.
26906 Square this circle by consuming all of the tokens up to and
26907 including the closing brace, recording the start/end of the RTL
26908 fragment, and reopening the file and re-reading the relevant
26909 lines within the RTL parser.
26910
26911 This requires the opening and closing braces of the C function
26912 to be on separate lines from the RTL they wrap.
26913
26914 Take ownership of START_WITH_PASS, if non-NULL. */
26915
26916location_t
26917c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
26918{
26919 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
26920 {
26921 free (ptr: start_with_pass);
26922 return c_parser_peek_token (parser)->location;
26923 }
26924
26925 location_t start_loc = c_parser_peek_token (parser)->location;
26926
26927 /* Consume all tokens, up to the closing brace, handling
26928 matching pairs of braces in the rtl dump. */
26929 int num_open_braces = 1;
26930 while (1)
26931 {
26932 switch (c_parser_peek_token (parser)->type)
26933 {
26934 case CPP_OPEN_BRACE:
26935 num_open_braces++;
26936 break;
26937 case CPP_CLOSE_BRACE:
26938 if (--num_open_braces == 0)
26939 goto found_closing_brace;
26940 break;
26941 case CPP_EOF:
26942 error_at (start_loc, "no closing brace");
26943 free (ptr: start_with_pass);
26944 return c_parser_peek_token (parser)->location;
26945 default:
26946 break;
26947 }
26948 c_parser_consume_token (parser);
26949 }
26950
26951 found_closing_brace:
26952 /* At the closing brace; record its location. */
26953 location_t end_loc = c_parser_peek_token (parser)->location;
26954
26955 /* Consume the closing brace. */
26956 c_parser_consume_token (parser);
26957
26958 /* Invoke the RTL parser. */
26959 if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
26960 {
26961 free (ptr: start_with_pass);
26962 return end_loc;
26963 }
26964
26965 /* Run the backend on the cfun created above, transferring ownership of
26966 START_WITH_PASS. */
26967 run_rtl_passes (initial_pass_name: start_with_pass);
26968 return end_loc;
26969}
26970
26971#include "gt-c-c-parser.h"
26972

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