1/* Parser for C and Objective-C.
2 Copyright (C) 1987-2023 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 tree std_attrs = NULL_TREE;
3671 tree attrs;
3672 tree ident = NULL_TREE;
3673 tree fixed_underlying_type = NULL_TREE;
3674 location_t enum_loc;
3675 location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3676 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
3677 c_parser_consume_token (parser);
3678 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3679 if (have_std_attrs)
3680 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3681 attrs = c_parser_gnu_attributes (parser);
3682 enum_loc = c_parser_peek_token (parser)->location;
3683 /* Set the location in case we create a decl now. */
3684 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
3685 if (c_parser_next_token_is (parser, type: CPP_NAME))
3686 {
3687 ident = c_parser_peek_token (parser)->value;
3688 ident_loc = c_parser_peek_token (parser)->location;
3689 enum_loc = ident_loc;
3690 c_parser_consume_token (parser);
3691 }
3692 if (c_parser_next_token_is (parser, type: CPP_COLON)
3693 /* Distinguish an enum-type-specifier from a bit-field
3694 declaration of the form "enum e : constant-expression;". */
3695 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
3696 {
3697 pedwarn_c11 (enum_loc, opt: OPT_Wpedantic,
3698 "ISO C does not support specifying %<enum%> underlying "
3699 "types before C23");
3700 if (ident)
3701 {
3702 /* The tag is in scope during the enum-type-specifier (which
3703 may refer to the tag inside typeof). */
3704 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
3705 have_std_attrs, std_attrs, true);
3706 if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
3707 error_at (enum_loc, "%<enum%> declared both with and without "
3708 "fixed underlying type");
3709 }
3710 else
3711 {
3712 /* There must be an enum definition, so this initialization
3713 (to avoid possible warnings about uninitialized data)
3714 will be replaced later (either with the results of that
3715 definition, or with the results of error handling for the
3716 case of no tag and no definition). */
3717 ret.spec = NULL_TREE;
3718 ret.kind = ctsk_tagdef;
3719 ret.expr = NULL_TREE;
3720 ret.expr_const_operands = true;
3721 ret.has_enum_type_specifier = true;
3722 }
3723 c_parser_consume_token (parser);
3724 struct c_declspecs *specs = build_null_declspecs ();
3725 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: false, alignspec_ok: false, auto_type_ok: false,
3726 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_id);
3727 finish_declspecs (specs);
3728 if (specs->default_int_p)
3729 error_at (enum_loc, "no %<enum%> underlying type specified");
3730 else if (TREE_CODE (specs->type) != INTEGER_TYPE
3731 && TREE_CODE (specs->type) != BOOLEAN_TYPE)
3732 {
3733 error_at (enum_loc, "invalid %<enum%> underlying type");
3734 specs->type = integer_type_node;
3735 }
3736 else if (specs->restrict_p)
3737 error_at (enum_loc, "invalid use of %<restrict%>");
3738 fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
3739 if (ident)
3740 {
3741 /* The type specified must be consistent with any previously
3742 specified underlying type. If this is a newly declared
3743 type, it is now a complete type. */
3744 if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
3745 && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
3746 {
3747 TYPE_MIN_VALUE (ret.spec) =
3748 TYPE_MIN_VALUE (fixed_underlying_type);
3749 TYPE_MAX_VALUE (ret.spec) =
3750 TYPE_MAX_VALUE (fixed_underlying_type);
3751 TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
3752 SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
3753 TYPE_SIZE (ret.spec) = NULL_TREE;
3754 TYPE_PRECISION (ret.spec) =
3755 TYPE_PRECISION (fixed_underlying_type);
3756 ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
3757 layout_type (ret.spec);
3758 }
3759 else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
3760 && !comptypes (fixed_underlying_type,
3761 ENUM_UNDERLYING_TYPE (ret.spec)))
3762 {
3763 error_at (enum_loc, "%<enum%> underlying type incompatible with "
3764 "previous declaration");
3765 fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
3766 }
3767 }
3768 }
3769 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
3770 {
3771 /* Parse an enum definition. */
3772 struct c_enum_contents the_enum;
3773 tree type;
3774 tree postfix_attrs;
3775 /* We chain the enumerators in reverse order, then put them in
3776 forward order at the end. */
3777 tree values;
3778 timevar_push (tv: TV_PARSE_ENUM);
3779 type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type);
3780 values = NULL_TREE;
3781 c_parser_consume_token (parser);
3782 while (true)
3783 {
3784 tree enum_id;
3785 tree enum_value;
3786 tree enum_decl;
3787 bool seen_comma;
3788 c_token *token;
3789 location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3790 location_t decl_loc, value_loc;
3791 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
3792 {
3793 /* Give a nicer error for "enum {}". */
3794 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
3795 && !parser->error)
3796 {
3797 error_at (c_parser_peek_token (parser)->location,
3798 "empty enum is invalid");
3799 parser->error = true;
3800 }
3801 else
3802 c_parser_error (parser, gmsgid: "expected identifier");
3803 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
3804 values = error_mark_node;
3805 break;
3806 }
3807 token = c_parser_peek_token (parser);
3808 enum_id = token->value;
3809 /* Set the location in case we create a decl now. */
3810 c_parser_set_source_position_from_token (token);
3811 decl_loc = value_loc = token->location;
3812 c_parser_consume_token (parser);
3813 /* Parse any specified attributes. */
3814 tree std_attrs = NULL_TREE;
3815 if (c_parser_nth_token_starts_std_attributes (parser, 1))
3816 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3817 tree enum_attrs = chainon (std_attrs,
3818 c_parser_gnu_attributes (parser));
3819 if (c_parser_next_token_is (parser, type: CPP_EQ))
3820 {
3821 c_parser_consume_token (parser);
3822 value_loc = c_parser_peek_token (parser)->location;
3823 enum_value = convert_lvalue_to_rvalue (value_loc,
3824 (c_parser_expr_no_commas
3825 (parser, NULL)),
3826 true, true).value;
3827 }
3828 else
3829 enum_value = NULL_TREE;
3830 enum_decl = build_enumerator (decl_loc, value_loc,
3831 &the_enum, enum_id, enum_value);
3832 if (enum_attrs)
3833 decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
3834 TREE_CHAIN (enum_decl) = values;
3835 values = enum_decl;
3836 seen_comma = false;
3837 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3838 {
3839 comma_loc = c_parser_peek_token (parser)->location;
3840 seen_comma = true;
3841 c_parser_consume_token (parser);
3842 }
3843 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
3844 {
3845 if (seen_comma)
3846 pedwarn_c90 (comma_loc, opt: OPT_Wpedantic,
3847 "comma at end of enumerator list");
3848 c_parser_consume_token (parser);
3849 break;
3850 }
3851 if (!seen_comma)
3852 {
3853 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
3854 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
3855 values = error_mark_node;
3856 break;
3857 }
3858 }
3859 postfix_attrs = c_parser_gnu_attributes (parser);
3860 ret.spec = finish_enum (type, nreverse (values),
3861 chainon (std_attrs,
3862 chainon (attrs, postfix_attrs)));
3863 ret.kind = ctsk_tagdef;
3864 ret.expr = NULL_TREE;
3865 ret.expr_const_operands = true;
3866 ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
3867 timevar_pop (tv: TV_PARSE_ENUM);
3868 return ret;
3869 }
3870 else if (!ident)
3871 {
3872 c_parser_error (parser, gmsgid: "expected %<{%>");
3873 ret.spec = error_mark_node;
3874 ret.kind = ctsk_tagref;
3875 ret.expr = NULL_TREE;
3876 ret.expr_const_operands = true;
3877 ret.has_enum_type_specifier = false;
3878 return ret;
3879 }
3880 /* Attributes may only appear when the members are defined or in
3881 certain forward declarations (treat enum forward declarations in
3882 GNU C analogously to struct and union forward declarations in
3883 standard C). */
3884 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
3885 c_parser_error (parser, gmsgid: "expected %<;%>");
3886 if (fixed_underlying_type == NULL_TREE)
3887 {
3888 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
3889 std_attrs, false);
3890 /* In ISO C, enumerated types without a fixed underlying type
3891 can be referred to only if already defined. */
3892 if (pedantic && !COMPLETE_TYPE_P (ret.spec))
3893 {
3894 gcc_assert (ident);
3895 pedwarn (enum_loc, OPT_Wpedantic,
3896 "ISO C forbids forward references to %<enum%> types");
3897 }
3898 }
3899 return ret;
3900}
3901
3902/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
3903
3904 struct-or-union-specifier:
3905 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
3906 identifier[opt] { struct-contents } gnu-attributes[opt]
3907 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
3908 identifier
3909
3910 struct-contents:
3911 struct-declaration-list
3912
3913 struct-declaration-list:
3914 struct-declaration ;
3915 struct-declaration-list struct-declaration ;
3916
3917 GNU extensions:
3918
3919 struct-contents:
3920 empty
3921 struct-declaration
3922 struct-declaration-list struct-declaration
3923
3924 struct-declaration-list:
3925 struct-declaration-list ;
3926 ;
3927
3928 (Note that in the syntax here, unlike that in ISO C, the semicolons
3929 are included here rather than in struct-declaration, in order to
3930 describe the syntax with extra semicolons and missing semicolon at
3931 end.)
3932
3933 Objective-C:
3934
3935 struct-declaration-list:
3936 @defs ( class-name )
3937
3938 (Note this does not include a trailing semicolon, but can be
3939 followed by further declarations, and gets a pedwarn-if-pedantic
3940 when followed by a semicolon.) */
3941
3942static struct c_typespec
3943c_parser_struct_or_union_specifier (c_parser *parser)
3944{
3945 struct c_typespec ret;
3946 bool have_std_attrs;
3947 tree std_attrs = NULL_TREE;
3948 tree attrs;
3949 tree ident = NULL_TREE;
3950 location_t struct_loc;
3951 location_t ident_loc = UNKNOWN_LOCATION;
3952 enum tree_code code;
3953 switch (c_parser_peek_token (parser)->keyword)
3954 {
3955 case RID_STRUCT:
3956 code = RECORD_TYPE;
3957 break;
3958 case RID_UNION:
3959 code = UNION_TYPE;
3960 break;
3961 default:
3962 gcc_unreachable ();
3963 }
3964 struct_loc = c_parser_peek_token (parser)->location;
3965 c_parser_consume_token (parser);
3966 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3967 if (have_std_attrs)
3968 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3969 attrs = c_parser_gnu_attributes (parser);
3970
3971 /* Set the location in case we create a decl now. */
3972 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
3973
3974 if (c_parser_next_token_is (parser, type: CPP_NAME))
3975 {
3976 ident = c_parser_peek_token (parser)->value;
3977 ident_loc = c_parser_peek_token (parser)->location;
3978 struct_loc = ident_loc;
3979 c_parser_consume_token (parser);
3980 }
3981 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
3982 {
3983 /* Parse a struct or union definition. Start the scope of the
3984 tag before parsing components. */
3985 class c_struct_parse_info *struct_info;
3986 tree type = start_struct (struct_loc, code, ident, &struct_info);
3987 tree postfix_attrs;
3988 /* We chain the components in reverse order, then put them in
3989 forward order at the end. Each struct-declaration may
3990 declare multiple components (comma-separated), so we must use
3991 chainon to join them, although when parsing each
3992 struct-declaration we can use TREE_CHAIN directly.
3993
3994 The theory behind all this is that there will be more
3995 semicolon separated fields than comma separated fields, and
3996 so we'll be minimizing the number of node traversals required
3997 by chainon. */
3998 tree contents;
3999 tree expr = NULL;
4000 timevar_push (tv: TV_PARSE_STRUCT);
4001 contents = NULL_TREE;
4002 c_parser_consume_token (parser);
4003 /* Handle the Objective-C @defs construct,
4004 e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4005 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_DEFS))
4006 {
4007 tree name;
4008 gcc_assert (c_dialect_objc ());
4009 c_parser_consume_token (parser);
4010 matching_parens parens;
4011 if (!parens.require_open (parser))
4012 goto end_at_defs;
4013 if (c_parser_next_token_is (parser, type: CPP_NAME)
4014 && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4015 {
4016 name = c_parser_peek_token (parser)->value;
4017 c_parser_consume_token (parser);
4018 }
4019 else
4020 {
4021 c_parser_error (parser, gmsgid: "expected class name");
4022 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4023 goto end_at_defs;
4024 }
4025 parens.skip_until_found_close (parser);
4026 contents = nreverse (objc_get_class_ivars (name));
4027 }
4028 end_at_defs:
4029 /* Parse the struct-declarations and semicolons. Problems with
4030 semicolons are diagnosed here; empty structures are diagnosed
4031 elsewhere. */
4032 while (true)
4033 {
4034 tree decls;
4035 /* Parse any stray semicolon. */
4036 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4037 {
4038 location_t semicolon_loc
4039 = c_parser_peek_token (parser)->location;
4040 gcc_rich_location richloc (semicolon_loc);
4041 richloc.add_fixit_remove ();
4042 pedwarn (&richloc, OPT_Wpedantic,
4043 "extra semicolon in struct or union specified");
4044 c_parser_consume_token (parser);
4045 continue;
4046 }
4047 /* Stop if at the end of the struct or union contents. */
4048 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4049 {
4050 c_parser_consume_token (parser);
4051 break;
4052 }
4053 /* Accept #pragmas at struct scope. */
4054 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
4055 {
4056 c_parser_pragma (parser, pragma_struct, NULL);
4057 continue;
4058 }
4059 /* Parse some comma-separated declarations, but not the
4060 trailing semicolon if any. */
4061 decls = c_parser_struct_declaration (parser, &expr);
4062 contents = chainon (decls, contents);
4063 /* If no semicolon follows, either we have a parse error or
4064 are at the end of the struct or union and should
4065 pedwarn. */
4066 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4067 c_parser_consume_token (parser);
4068 else
4069 {
4070 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4071 pedwarn (c_parser_peek_token (parser)->location, 0,
4072 "no semicolon at end of struct or union");
4073 else if (parser->error
4074 || !c_parser_next_token_starts_declspecs (parser))
4075 {
4076 c_parser_error (parser, gmsgid: "expected %<;%>");
4077 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4078 break;
4079 }
4080
4081 /* If we come here, we have already emitted an error
4082 for an expected `;', identifier or `(', and we also
4083 recovered already. Go on with the next field. */
4084 }
4085 }
4086 postfix_attrs = c_parser_gnu_attributes (parser);
4087 ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4088 chainon (std_attrs,
4089 chainon (attrs, postfix_attrs)),
4090 struct_info);
4091 ret.kind = ctsk_tagdef;
4092 ret.expr = expr;
4093 ret.expr_const_operands = true;
4094 ret.has_enum_type_specifier = false;
4095 timevar_pop (tv: TV_PARSE_STRUCT);
4096 return ret;
4097 }
4098 else if (!ident)
4099 {
4100 c_parser_error (parser, gmsgid: "expected %<{%>");
4101 ret.spec = error_mark_node;
4102 ret.kind = ctsk_tagref;
4103 ret.expr = NULL_TREE;
4104 ret.expr_const_operands = true;
4105 ret.has_enum_type_specifier = false;
4106 return ret;
4107 }
4108 /* Attributes may only appear when the members are defined or in
4109 certain forward declarations. */
4110 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4111 c_parser_error (parser, gmsgid: "expected %<;%>");
4112 /* ??? Existing practice is that GNU attributes are ignored after
4113 the struct or union keyword when not defining the members. */
4114 ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4115 false);
4116 return ret;
4117}
4118
4119/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4120 *without* the trailing semicolon.
4121
4122 struct-declaration:
4123 attribute-specifier-sequence[opt] specifier-qualifier-list
4124 attribute-specifier-sequence[opt] struct-declarator-list
4125 static_assert-declaration-no-semi
4126
4127 specifier-qualifier-list:
4128 type-specifier specifier-qualifier-list[opt]
4129 type-qualifier specifier-qualifier-list[opt]
4130 alignment-specifier specifier-qualifier-list[opt]
4131 gnu-attributes specifier-qualifier-list[opt]
4132
4133 struct-declarator-list:
4134 struct-declarator
4135 struct-declarator-list , gnu-attributes[opt] struct-declarator
4136
4137 struct-declarator:
4138 declarator gnu-attributes[opt]
4139 declarator[opt] : constant-expression gnu-attributes[opt]
4140
4141 GNU extensions:
4142
4143 struct-declaration:
4144 __extension__ struct-declaration
4145 specifier-qualifier-list
4146
4147 Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4148 of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4149 any expression without commas in the syntax (assignment
4150 expressions, not just conditional expressions); assignment
4151 expressions will be diagnosed as non-constant. */
4152
4153static tree
4154c_parser_struct_declaration (c_parser *parser, tree *expr)
4155{
4156 struct c_declspecs *specs;
4157 tree prefix_attrs;
4158 tree all_prefix_attrs;
4159 tree decls;
4160 location_t decl_loc;
4161 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
4162 {
4163 int ext;
4164 tree decl;
4165 ext = disable_extension_diagnostics ();
4166 c_parser_consume_token (parser);
4167 decl = c_parser_struct_declaration (parser, expr);
4168 restore_extension_diagnostics (flags: ext);
4169 return decl;
4170 }
4171 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
4172 {
4173 c_parser_static_assert_declaration_no_semi (parser);
4174 return NULL_TREE;
4175 }
4176 specs = build_null_declspecs ();
4177 decl_loc = c_parser_peek_token (parser)->location;
4178 /* Strictly by the standard, we shouldn't allow _Alignas here,
4179 but it appears to have been intended to allow it there, so
4180 we're keeping it as it is until WG14 reaches a conclusion
4181 of N1731.
4182 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4183 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true,
4184 alignspec_ok: true, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: true, la: cla_nonabstract_decl);
4185 if (parser->error)
4186 return NULL_TREE;
4187 if (!specs->declspecs_seen_p)
4188 {
4189 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
4190 return NULL_TREE;
4191 }
4192 finish_declspecs (specs);
4193 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4194 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4195 {
4196 tree ret;
4197 if (specs->typespec_kind == ctsk_none)
4198 {
4199 pedwarn (decl_loc, OPT_Wpedantic,
4200 "ISO C forbids member declarations with no members");
4201 shadow_tag_warned (specs, pedantic);
4202 ret = NULL_TREE;
4203 }
4204 else
4205 {
4206 /* Support for unnamed structs or unions as members of
4207 structs or unions (which is [a] useful and [b] supports
4208 MS P-SDK). */
4209 tree attrs = NULL;
4210
4211 ret = grokfield (c_parser_peek_token (parser)->location,
4212 build_id_declarator (NULL_TREE), specs,
4213 NULL_TREE, &attrs, expr);
4214 if (ret)
4215 decl_attributes (&ret, attrs, 0);
4216 }
4217 return ret;
4218 }
4219
4220 /* Provide better error recovery. Note that a type name here is valid,
4221 and will be treated as a field name. */
4222 if (specs->typespec_kind == ctsk_tagdef
4223 && TREE_CODE (specs->type) != ENUMERAL_TYPE
4224 && c_parser_next_token_starts_declspecs (parser)
4225 && !c_parser_next_token_is (parser, type: CPP_NAME))
4226 {
4227 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
4228 parser->error = false;
4229 return NULL_TREE;
4230 }
4231
4232 pending_xref_error ();
4233 prefix_attrs = specs->attrs;
4234 all_prefix_attrs = prefix_attrs;
4235 specs->attrs = NULL_TREE;
4236 decls = NULL_TREE;
4237 while (true)
4238 {
4239 /* Declaring one or more declarators or un-named bit-fields. */
4240 struct c_declarator *declarator;
4241 bool dummy = false;
4242 if (c_parser_next_token_is (parser, type: CPP_COLON))
4243 declarator = build_id_declarator (NULL_TREE);
4244 else
4245 declarator = c_parser_declarator (parser,
4246 type_seen_p: specs->typespec_kind != ctsk_none,
4247 kind: C_DTR_NORMAL, seen_id: &dummy);
4248 if (declarator == NULL)
4249 {
4250 c_parser_skip_to_end_of_block_or_statement (parser);
4251 break;
4252 }
4253 if (c_parser_next_token_is (parser, type: CPP_COLON)
4254 || c_parser_next_token_is (parser, type: CPP_COMMA)
4255 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4256 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
4257 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4258 {
4259 tree postfix_attrs = NULL_TREE;
4260 tree width = NULL_TREE;
4261 tree d;
4262 if (c_parser_next_token_is (parser, type: CPP_COLON))
4263 {
4264 c_parser_consume_token (parser);
4265 location_t loc = c_parser_peek_token (parser)->location;
4266 width = convert_lvalue_to_rvalue (loc,
4267 (c_parser_expr_no_commas
4268 (parser, NULL)),
4269 true, true).value;
4270 }
4271 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4272 postfix_attrs = c_parser_gnu_attributes (parser);
4273 d = grokfield (c_parser_peek_token (parser)->location,
4274 declarator, specs, width, &all_prefix_attrs, expr);
4275 decl_attributes (&d, chainon (postfix_attrs,
4276 all_prefix_attrs), 0);
4277 DECL_CHAIN (d) = decls;
4278 decls = d;
4279 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4280 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4281 prefix_attrs);
4282 else
4283 all_prefix_attrs = prefix_attrs;
4284 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4285 c_parser_consume_token (parser);
4286 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4287 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4288 {
4289 /* Semicolon consumed in caller. */
4290 break;
4291 }
4292 else
4293 {
4294 c_parser_error (parser, gmsgid: "expected %<,%>, %<;%> or %<}%>");
4295 break;
4296 }
4297 }
4298 else
4299 {
4300 c_parser_error (parser,
4301 gmsgid: "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4302 "%<__attribute__%>");
4303 break;
4304 }
4305 }
4306 return decls;
4307}
4308
4309/* Parse a typeof specifier (a GNU extension adopted in C23).
4310
4311 typeof-specifier:
4312 typeof ( expression )
4313 typeof ( type-name )
4314 typeof_unqual ( expression )
4315 typeof_unqual ( type-name )
4316*/
4317
4318static struct c_typespec
4319c_parser_typeof_specifier (c_parser *parser)
4320{
4321 bool is_unqual;
4322 bool is_std;
4323 struct c_typespec ret;
4324 ret.kind = ctsk_typeof;
4325 ret.spec = error_mark_node;
4326 ret.expr = NULL_TREE;
4327 ret.expr_const_operands = true;
4328 ret.has_enum_type_specifier = false;
4329 if (c_parser_next_token_is_keyword (parser, keyword: RID_TYPEOF))
4330 {
4331 is_unqual = false;
4332 tree spelling = c_parser_peek_token (parser)->value;
4333 is_std = (flag_isoc23
4334 && strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof") == 0);
4335 }
4336 else
4337 {
4338 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4339 is_unqual = true;
4340 tree spelling = c_parser_peek_token (parser)->value;
4341 is_std = strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof_unqual") == 0;
4342 }
4343 c_parser_consume_token (parser);
4344 c_inhibit_evaluation_warnings++;
4345 in_typeof++;
4346 matching_parens parens;
4347 if (!parens.require_open (parser))
4348 {
4349 c_inhibit_evaluation_warnings--;
4350 in_typeof--;
4351 return ret;
4352 }
4353 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4354 {
4355 struct c_type_name *type = c_parser_type_name (parser);
4356 c_inhibit_evaluation_warnings--;
4357 in_typeof--;
4358 if (type != NULL)
4359 {
4360 ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4361 pop_maybe_used (c_type_variably_modified_p (t: ret.spec));
4362 }
4363 }
4364 else
4365 {
4366 bool was_vm;
4367 location_t here = c_parser_peek_token (parser)->location;
4368 struct c_expr expr = c_parser_expression (parser);
4369 c_inhibit_evaluation_warnings--;
4370 in_typeof--;
4371 if (TREE_CODE (expr.value) == COMPONENT_REF
4372 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4373 error_at (here, "%<typeof%> applied to a bit-field");
4374 mark_exp_read (expr.value);
4375 ret.spec = TREE_TYPE (expr.value);
4376 was_vm = c_type_variably_modified_p (t: ret.spec);
4377 /* This is returned with the type so that when the type is
4378 evaluated, this can be evaluated. */
4379 if (was_vm)
4380 ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4381 pop_maybe_used (was_vm);
4382 }
4383 parens.skip_until_found_close (parser);
4384 if (ret.spec != error_mark_node)
4385 {
4386 if (is_unqual && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4387 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4388 if (is_std)
4389 {
4390 /* In ISO C terms, _Noreturn is not part of the type of
4391 expressions such as &abort, but in GCC it is represented
4392 internally as a type qualifier. */
4393 if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4394 && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4395 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4396 else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4397 && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4398 ret.spec
4399 = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4400 }
4401 }
4402 return ret;
4403}
4404
4405/* Parse an alignment-specifier.
4406
4407 C11 6.7.5:
4408
4409 alignment-specifier:
4410 _Alignas ( type-name )
4411 _Alignas ( constant-expression )
4412*/
4413
4414static tree
4415c_parser_alignas_specifier (c_parser * parser)
4416{
4417 tree ret = error_mark_node;
4418 location_t loc = c_parser_peek_token (parser)->location;
4419 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4420 tree spelling = c_parser_peek_token (parser)->value;
4421 c_parser_consume_token (parser);
4422 if (flag_isoc99)
4423 pedwarn_c99 (loc, opt: OPT_Wpedantic,
4424 "ISO C99 does not support %qE", spelling);
4425 else
4426 pedwarn_c99 (loc, opt: OPT_Wpedantic,
4427 "ISO C90 does not support %qE", spelling);
4428 matching_parens parens;
4429 if (!parens.require_open (parser))
4430 return ret;
4431 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4432 {
4433 struct c_type_name *type = c_parser_type_name (parser);
4434 if (type != NULL)
4435 ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4436 false, true, 1);
4437 }
4438 else
4439 ret = convert_lvalue_to_rvalue (loc,
4440 c_parser_expr_no_commas (parser, NULL),
4441 true, true).value;
4442 parens.skip_until_found_close (parser);
4443 return ret;
4444}
4445
4446/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4447 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4448 a typedef name may be redeclared; otherwise it may not. KIND
4449 indicates which kind of declarator is wanted. Returns a valid
4450 declarator except in the case of a syntax error in which case NULL is
4451 returned. *SEEN_ID is set to true if an identifier being declared is
4452 seen; this is used to diagnose bad forms of abstract array declarators
4453 and to determine whether an identifier list is syntactically permitted.
4454
4455 declarator:
4456 pointer[opt] direct-declarator
4457
4458 direct-declarator:
4459 identifier
4460 ( gnu-attributes[opt] declarator )
4461 direct-declarator array-declarator
4462 direct-declarator ( parameter-type-list )
4463 direct-declarator ( identifier-list[opt] )
4464
4465 pointer:
4466 * type-qualifier-list[opt]
4467 * type-qualifier-list[opt] pointer
4468
4469 type-qualifier-list:
4470 type-qualifier
4471 gnu-attributes
4472 type-qualifier-list type-qualifier
4473 type-qualifier-list gnu-attributes
4474
4475 array-declarator:
4476 [ type-qualifier-list[opt] assignment-expression[opt] ]
4477 [ static type-qualifier-list[opt] assignment-expression ]
4478 [ type-qualifier-list static assignment-expression ]
4479 [ type-qualifier-list[opt] * ]
4480
4481 parameter-type-list:
4482 parameter-list
4483 parameter-list , ...
4484
4485 parameter-list:
4486 parameter-declaration
4487 parameter-list , parameter-declaration
4488
4489 parameter-declaration:
4490 declaration-specifiers declarator gnu-attributes[opt]
4491 declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4492
4493 identifier-list:
4494 identifier
4495 identifier-list , identifier
4496
4497 abstract-declarator:
4498 pointer
4499 pointer[opt] direct-abstract-declarator
4500
4501 direct-abstract-declarator:
4502 ( gnu-attributes[opt] abstract-declarator )
4503 direct-abstract-declarator[opt] array-declarator
4504 direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4505
4506 GNU extensions:
4507
4508 direct-declarator:
4509 direct-declarator ( parameter-forward-declarations
4510 parameter-type-list[opt] )
4511
4512 direct-abstract-declarator:
4513 direct-abstract-declarator[opt] ( parameter-forward-declarations
4514 parameter-type-list[opt] )
4515
4516 parameter-forward-declarations:
4517 parameter-list ;
4518 parameter-forward-declarations parameter-list ;
4519
4520 The uses of gnu-attributes shown above are GNU extensions.
4521
4522 Some forms of array declarator are not included in C99 in the
4523 syntax for abstract declarators; these are disallowed elsewhere.
4524 This may be a defect (DR#289).
4525
4526 This function also accepts an omitted abstract declarator as being
4527 an abstract declarator, although not part of the formal syntax. */
4528
4529struct c_declarator *
4530c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4531 bool *seen_id)
4532{
4533 /* Parse any initial pointer part. */
4534 if (c_parser_next_token_is (parser, type: CPP_MULT))
4535 {
4536 struct c_declspecs *quals_attrs = build_null_declspecs ();
4537 struct c_declarator *inner;
4538 c_parser_consume_token (parser);
4539 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4540 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: false, la: cla_prefer_id);
4541 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4542 if (inner == NULL)
4543 return NULL;
4544 else
4545 return make_pointer_declarator (quals_attrs, inner);
4546 }
4547 /* Now we have a direct declarator, direct abstract declarator or
4548 nothing (which counts as a direct abstract declarator here). */
4549 return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
4550}
4551
4552/* Parse a direct declarator or direct abstract declarator; arguments
4553 as c_parser_declarator. */
4554
4555static struct c_declarator *
4556c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4557 bool *seen_id)
4558{
4559 /* The direct declarator must start with an identifier (possibly
4560 omitted) or a parenthesized declarator (possibly abstract). In
4561 an ordinary declarator, initial parentheses must start a
4562 parenthesized declarator. In an abstract declarator or parameter
4563 declarator, they could start a parenthesized declarator or a
4564 parameter list. To tell which, the open parenthesis and any
4565 following gnu-attributes must be read. If a declaration
4566 specifier or standard attributes follow, then it is a parameter
4567 list; if the specifier is a typedef name, there might be an
4568 ambiguity about redeclaring it, which is resolved in the
4569 direction of treating it as a typedef name. If a close
4570 parenthesis follows, it is also an empty parameter list, as the
4571 syntax does not permit empty abstract declarators. Otherwise, it
4572 is a parenthesized declarator (in which case the analysis may be
4573 repeated inside it, recursively).
4574
4575 ??? There is an ambiguity in a parameter declaration "int
4576 (__attribute__((foo)) x)", where x is not a typedef name: it
4577 could be an abstract declarator for a function, or declare x with
4578 parentheses. The proper resolution of this ambiguity needs
4579 documenting. At present we follow an accident of the old
4580 parser's implementation, whereby the first parameter must have
4581 some declaration specifiers other than just gnu-attributes. Thus as
4582 a parameter declaration it is treated as a parenthesized
4583 parameter named x, and as an abstract declarator it is
4584 rejected.
4585
4586 ??? Also following the old parser, gnu-attributes inside an empty
4587 parameter list are ignored, making it a list not yielding a
4588 prototype, rather than giving an error or making it have one
4589 parameter with implicit type int.
4590
4591 ??? Also following the old parser, typedef names may be
4592 redeclared in declarators, but not Objective-C class names. */
4593
4594 if (kind != C_DTR_ABSTRACT
4595 && c_parser_next_token_is (parser, type: CPP_NAME)
4596 && ((type_seen_p
4597 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
4598 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
4599 || c_parser_peek_token (parser)->id_kind == C_ID_ID))
4600 {
4601 struct c_declarator *inner
4602 = build_id_declarator (c_parser_peek_token (parser)->value);
4603 *seen_id = true;
4604 inner->id_loc = c_parser_peek_token (parser)->location;
4605 c_parser_consume_token (parser);
4606 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4607 inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
4608 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4609 }
4610
4611 if (kind != C_DTR_NORMAL
4612 && c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
4613 && !c_parser_nth_token_starts_std_attributes (parser, 1))
4614 {
4615 struct c_declarator *inner = build_id_declarator (NULL_TREE);
4616 inner->id_loc = c_parser_peek_token (parser)->location;
4617 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4618 }
4619
4620 /* Either we are at the end of an abstract declarator, or we have
4621 parentheses. */
4622
4623 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
4624 {
4625 tree attrs;
4626 struct c_declarator *inner;
4627 c_parser_consume_token (parser);
4628 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4629 keyword: RID_ATTRIBUTE);
4630 attrs = c_parser_gnu_attributes (parser);
4631 if (kind != C_DTR_NORMAL
4632 && (c_parser_next_token_starts_declspecs (parser)
4633 || (!have_gnu_attrs
4634 && (c_parser_nth_token_starts_std_attributes (parser, 1)
4635 || c_parser_next_token_is (parser, type: CPP_ELLIPSIS)))
4636 || c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN)))
4637 {
4638 struct c_arg_info *args
4639 = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
4640 attrs, have_gnu_attrs);
4641 if (args == NULL)
4642 return NULL;
4643 else
4644 {
4645 inner = build_id_declarator (NULL_TREE);
4646 if (!(args->types
4647 && args->types != error_mark_node
4648 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4649 && c_parser_nth_token_starts_std_attributes (parser, 1))
4650 {
4651 tree std_attrs
4652 = c_parser_std_attribute_specifier_sequence (parser);
4653 if (std_attrs)
4654 inner = build_attrs_declarator (std_attrs, inner);
4655 }
4656 inner = build_function_declarator (args, inner);
4657 return c_parser_direct_declarator_inner (parser, *seen_id,
4658 inner);
4659 }
4660 }
4661 /* A parenthesized declarator. */
4662 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4663 if (inner != NULL && attrs != NULL)
4664 inner = build_attrs_declarator (attrs, inner);
4665 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4666 {
4667 c_parser_consume_token (parser);
4668 if (inner == NULL)
4669 return NULL;
4670 else
4671 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4672 }
4673 else
4674 {
4675 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4676 msgid: "expected %<)%>");
4677 return NULL;
4678 }
4679 }
4680 else
4681 {
4682 if (kind == C_DTR_NORMAL)
4683 {
4684 c_parser_error (parser, gmsgid: "expected identifier or %<(%>");
4685 return NULL;
4686 }
4687 else
4688 return build_id_declarator (NULL_TREE);
4689 }
4690}
4691
4692/* Parse part of a direct declarator or direct abstract declarator,
4693 given that some (in INNER) has already been parsed; ID_PRESENT is
4694 true if an identifier is present, false for an abstract
4695 declarator. */
4696
4697static struct c_declarator *
4698c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
4699 struct c_declarator *inner)
4700{
4701 /* Parse a sequence of array declarators and parameter lists. */
4702 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
4703 && !c_parser_nth_token_starts_std_attributes (parser, 1))
4704 {
4705 location_t brace_loc = c_parser_peek_token (parser)->location;
4706 struct c_declarator *declarator;
4707 struct c_declspecs *quals_attrs = build_null_declspecs ();
4708 bool static_seen;
4709 bool star_seen;
4710 struct c_expr dimen;
4711 dimen.value = NULL_TREE;
4712 dimen.original_code = ERROR_MARK;
4713 dimen.original_type = NULL_TREE;
4714 c_parser_consume_token (parser);
4715 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4716 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
4717 static_seen = c_parser_next_token_is_keyword (parser, keyword: RID_STATIC);
4718 if (static_seen)
4719 c_parser_consume_token (parser);
4720 if (static_seen && !quals_attrs->declspecs_seen_p)
4721 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4722 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
4723 if (!quals_attrs->declspecs_seen_p)
4724 quals_attrs = NULL;
4725 /* If "static" is present, there must be an array dimension.
4726 Otherwise, there may be a dimension, "*", or no
4727 dimension. */
4728 if (static_seen)
4729 {
4730 star_seen = false;
4731 dimen = c_parser_expr_no_commas (parser, NULL);
4732 }
4733 else
4734 {
4735 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
4736 {
4737 dimen.value = NULL_TREE;
4738 star_seen = false;
4739 }
4740 else if (c_parser_next_token_is (parser, type: CPP_MULT))
4741 {
4742 if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
4743 {
4744 dimen.value = NULL_TREE;
4745 star_seen = true;
4746 c_parser_consume_token (parser);
4747 }
4748 else
4749 {
4750 star_seen = false;
4751 dimen = c_parser_expr_no_commas (parser, NULL);
4752 }
4753 }
4754 else
4755 {
4756 star_seen = false;
4757 dimen = c_parser_expr_no_commas (parser, NULL);
4758 }
4759 }
4760 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
4761 c_parser_consume_token (parser);
4762 else
4763 {
4764 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
4765 msgid: "expected %<]%>");
4766 return NULL;
4767 }
4768 if (dimen.value)
4769 dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
4770 declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
4771 static_seen, star_seen);
4772 if (declarator == NULL)
4773 return NULL;
4774 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4775 {
4776 tree std_attrs
4777 = c_parser_std_attribute_specifier_sequence (parser);
4778 if (std_attrs)
4779 inner = build_attrs_declarator (std_attrs, inner);
4780 }
4781 inner = set_array_declarator_inner (declarator, inner);
4782 return c_parser_direct_declarator_inner (parser, id_present, inner);
4783 }
4784 else if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
4785 {
4786 tree attrs;
4787 struct c_arg_info *args;
4788 c_parser_consume_token (parser);
4789 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4790 keyword: RID_ATTRIBUTE);
4791 attrs = c_parser_gnu_attributes (parser);
4792 args = c_parser_parms_declarator (parser, id_present, attrs,
4793 have_gnu_attrs);
4794 if (args == NULL)
4795 return NULL;
4796 else
4797 {
4798 if (!(args->types
4799 && args->types != error_mark_node
4800 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4801 && c_parser_nth_token_starts_std_attributes (parser, 1))
4802 {
4803 tree std_attrs
4804 = c_parser_std_attribute_specifier_sequence (parser);
4805 if (std_attrs)
4806 inner = build_attrs_declarator (std_attrs, inner);
4807 }
4808 inner = build_function_declarator (args, inner);
4809 return c_parser_direct_declarator_inner (parser, id_present, inner);
4810 }
4811 }
4812 return inner;
4813}
4814
4815/* Parse a parameter list or identifier list, including the closing
4816 parenthesis but not the opening one. ATTRS are the gnu-attributes
4817 at the start of the list. ID_LIST_OK is true if an identifier list
4818 is acceptable; such a list must not have attributes at the start.
4819 HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
4820 attributes) were present (in which case standard attributes cannot
4821 occur). */
4822
4823static struct c_arg_info *
4824c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
4825 bool have_gnu_attrs)
4826{
4827 push_scope ();
4828 declare_parm_level ();
4829 /* If the list starts with an identifier, it is an identifier list.
4830 Otherwise, it is either a prototype list or an empty list. */
4831 if (id_list_ok
4832 && !attrs
4833 && c_parser_next_token_is (parser, type: CPP_NAME)
4834 && c_parser_peek_token (parser)->id_kind == C_ID_ID
4835
4836 /* Look ahead to detect typos in type names. */
4837 && c_parser_peek_2nd_token (parser)->type != CPP_NAME
4838 && c_parser_peek_2nd_token (parser)->type != CPP_MULT
4839 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
4840 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
4841 && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
4842 {
4843 tree list = NULL_TREE, *nextp = &list;
4844 while (c_parser_next_token_is (parser, type: CPP_NAME)
4845 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
4846 {
4847 *nextp = build_tree_list (NULL_TREE,
4848 c_parser_peek_token (parser)->value);
4849 nextp = & TREE_CHAIN (*nextp);
4850 c_parser_consume_token (parser);
4851 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
4852 break;
4853 c_parser_consume_token (parser);
4854 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4855 {
4856 c_parser_error (parser, gmsgid: "expected identifier");
4857 break;
4858 }
4859 }
4860 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4861 {
4862 struct c_arg_info *ret = build_arg_info ();
4863 ret->types = list;
4864 c_parser_consume_token (parser);
4865 pop_scope ();
4866 return ret;
4867 }
4868 else
4869 {
4870 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4871 msgid: "expected %<)%>");
4872 pop_scope ();
4873 return NULL;
4874 }
4875 }
4876 else
4877 {
4878 struct c_arg_info *ret
4879 = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
4880 pop_scope ();
4881 return ret;
4882 }
4883}
4884
4885/* Parse a parameter list (possibly empty), including the closing
4886 parenthesis but not the opening one. ATTRS are the gnu-attributes
4887 at the start of the list; if HAVE_GNU_ATTRS, there were some such
4888 attributes (possibly empty, in which case ATTRS is NULL_TREE),
4889 which means standard attributes cannot start the list. EXPR is
4890 NULL or an expression that needs to be evaluated for the side
4891 effects of array size expressions in the parameters. */
4892
4893static struct c_arg_info *
4894c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
4895 bool have_gnu_attrs)
4896{
4897 bool bad_parm = false;
4898
4899 /* ??? Following the old parser, forward parameter declarations may
4900 use abstract declarators, and if no real parameter declarations
4901 follow the forward declarations then this is not diagnosed. Also
4902 note as above that gnu-attributes are ignored as the only contents of
4903 the parentheses, or as the only contents after forward
4904 declarations. */
4905 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4906 {
4907 struct c_arg_info *ret = build_arg_info ();
4908 c_parser_consume_token (parser);
4909 return ret;
4910 }
4911 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS) && !have_gnu_attrs)
4912 {
4913 struct c_arg_info *ret = build_arg_info ();
4914
4915 ret->types = NULL_TREE;
4916 pedwarn_c11 (c_parser_peek_token (parser)->location, opt: OPT_Wpedantic,
4917 "ISO C requires a named argument before %<...%> "
4918 "before C23");
4919 c_parser_consume_token (parser);
4920 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4921 {
4922 ret->no_named_args_stdarg_p = true;
4923 c_parser_consume_token (parser);
4924 return ret;
4925 }
4926 else
4927 {
4928 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4929 msgid: "expected %<)%>");
4930 return NULL;
4931 }
4932 }
4933 /* Nonempty list of parameters, either terminated with semicolon
4934 (forward declarations; recurse) or with close parenthesis (normal
4935 function) or with ", ... )" (variadic function). */
4936 while (true)
4937 {
4938 /* Parse a parameter. */
4939 struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
4940 have_gnu_attrs);
4941 attrs = NULL_TREE;
4942 have_gnu_attrs = false;
4943 if (parm == NULL)
4944 bad_parm = true;
4945 else
4946 push_parm_decl (parm, &expr);
4947 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4948 {
4949 tree new_attrs;
4950 c_parser_consume_token (parser);
4951 mark_forward_parm_decls ();
4952 bool new_have_gnu_attrs
4953 = c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE);
4954 new_attrs = c_parser_gnu_attributes (parser);
4955 return c_parser_parms_list_declarator (parser, attrs: new_attrs, expr,
4956 have_gnu_attrs: new_have_gnu_attrs);
4957 }
4958 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4959 {
4960 c_parser_consume_token (parser);
4961 if (bad_parm)
4962 return NULL;
4963 else
4964 return get_parm_info (false, expr);
4965 }
4966 if (!c_parser_require (parser, type: CPP_COMMA,
4967 msgid: "expected %<;%>, %<,%> or %<)%>",
4968 UNKNOWN_LOCATION, type_is_unique: false))
4969 {
4970 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4971 return NULL;
4972 }
4973 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
4974 {
4975 c_parser_consume_token (parser);
4976 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4977 {
4978 c_parser_consume_token (parser);
4979 if (bad_parm)
4980 return NULL;
4981 else
4982 return get_parm_info (true, expr);
4983 }
4984 else
4985 {
4986 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4987 msgid: "expected %<)%>");
4988 return NULL;
4989 }
4990 }
4991 }
4992}
4993
4994/* Parse a parameter declaration. ATTRS are the gnu-attributes at the
4995 start of the declaration if it is the first parameter;
4996 HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
4997 empty) there. */
4998
4999static struct c_parm *
5000c_parser_parameter_declaration (c_parser *parser, tree attrs,
5001 bool have_gnu_attrs)
5002{
5003 struct c_declspecs *specs;
5004 struct c_declarator *declarator;
5005 tree prefix_attrs;
5006 tree postfix_attrs = NULL_TREE;
5007 bool dummy = false;
5008
5009 /* Accept #pragmas between parameter declarations. */
5010 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
5011 c_parser_pragma (parser, pragma_param, NULL);
5012
5013 if (!c_parser_next_token_starts_declspecs (parser)
5014 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5015 {
5016 c_token *token = c_parser_peek_token (parser);
5017 if (parser->error)
5018 return NULL;
5019 c_parser_set_source_position_from_token (token);
5020 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
5021 {
5022 auto_diagnostic_group d;
5023 name_hint hint = lookup_name_fuzzy (token->value,
5024 FUZZY_LOOKUP_TYPENAME,
5025 token->location);
5026 if (const char *suggestion = hint.suggestion ())
5027 {
5028 gcc_rich_location richloc (token->location);
5029 richloc.add_fixit_replace (new_content: suggestion);
5030 error_at (&richloc,
5031 "unknown type name %qE; did you mean %qs?",
5032 token->value, suggestion);
5033 }
5034 else
5035 error_at (token->location, "unknown type name %qE", token->value);
5036 parser->error = true;
5037 }
5038 /* ??? In some Objective-C cases '...' isn't applicable so there
5039 should be a different message. */
5040 else
5041 c_parser_error (parser,
5042 gmsgid: "expected declaration specifiers or %<...%>");
5043 c_parser_skip_to_end_of_parameter (parser);
5044 return NULL;
5045 }
5046
5047 location_t start_loc = c_parser_peek_token (parser)->location;
5048
5049 specs = build_null_declspecs ();
5050 if (attrs)
5051 {
5052 declspecs_add_attrs (input_location, specs, attrs);
5053 attrs = NULL_TREE;
5054 }
5055 c_parser_declspecs (parser, specs, scspec_ok: true, typespec_ok: true, start_attr_ok: true, alignspec_ok: true, auto_type_ok: false,
5056 start_std_attr_ok: !have_gnu_attrs, end_std_attr_ok: true, la: cla_nonabstract_decl);
5057 finish_declspecs (specs);
5058 pending_xref_error ();
5059 prefix_attrs = specs->attrs;
5060 specs->attrs = NULL_TREE;
5061 declarator = c_parser_declarator (parser,
5062 type_seen_p: specs->typespec_kind != ctsk_none,
5063 kind: C_DTR_PARM, seen_id: &dummy);
5064 if (declarator == NULL)
5065 {
5066 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
5067 return NULL;
5068 }
5069 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5070 postfix_attrs = c_parser_gnu_attributes (parser);
5071
5072 /* Generate a location for the parameter, ranging from the start of the
5073 initial token to the end of the final token.
5074
5075 If we have a identifier, then use it for the caret location, e.g.
5076
5077 extern int callee (int one, int (*two)(int, int), float three);
5078 ~~~~~~^~~~~~~~~~~~~~
5079
5080 otherwise, reuse the start location for the caret location e.g.:
5081
5082 extern int callee (int one, int (*)(int, int), float three);
5083 ^~~~~~~~~~~~~~~~~
5084 */
5085 location_t end_loc = parser->last_token_location;
5086
5087 /* Find any cdk_id declarator; determine if we have an identifier. */
5088 c_declarator *id_declarator = declarator;
5089 while (id_declarator && id_declarator->kind != cdk_id)
5090 id_declarator = id_declarator->declarator;
5091 location_t caret_loc = (id_declarator->u.id.id
5092 ? id_declarator->id_loc
5093 : start_loc);
5094 location_t param_loc = make_location (caret: caret_loc, start: start_loc, finish: end_loc);
5095
5096 return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5097 declarator, param_loc);
5098}
5099
5100/* Parse a string literal in an asm expression. It should not be
5101 translated, and wide string literals are an error although
5102 permitted by the syntax. This is a GNU extension.
5103
5104 asm-string-literal:
5105 string-literal
5106*/
5107
5108static tree
5109c_parser_asm_string_literal (c_parser *parser)
5110{
5111 tree str;
5112 int save_flag = warn_overlength_strings;
5113 warn_overlength_strings = 0;
5114 str = c_parser_string_literal (parser, false, false).value;
5115 warn_overlength_strings = save_flag;
5116 return str;
5117}
5118
5119/* Parse a simple asm expression. This is used in restricted
5120 contexts, where a full expression with inputs and outputs does not
5121 make sense. This is a GNU extension.
5122
5123 simple-asm-expr:
5124 asm ( asm-string-literal )
5125*/
5126
5127static tree
5128c_parser_simple_asm_expr (c_parser *parser)
5129{
5130 tree str;
5131 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5132 c_parser_consume_token (parser);
5133 matching_parens parens;
5134 if (!parens.require_open (parser))
5135 return NULL_TREE;
5136 str = c_parser_asm_string_literal (parser);
5137 if (!parens.require_close (parser))
5138 {
5139 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5140 return NULL_TREE;
5141 }
5142 return str;
5143}
5144
5145static tree
5146c_parser_gnu_attribute_any_word (c_parser *parser)
5147{
5148 tree attr_name = NULL_TREE;
5149
5150 if (c_parser_next_token_is (parser, type: CPP_KEYWORD))
5151 {
5152 /* ??? See comment above about what keywords are accepted here. */
5153 bool ok;
5154 switch (c_parser_peek_token (parser)->keyword)
5155 {
5156 case RID_STATIC:
5157 case RID_UNSIGNED:
5158 case RID_LONG:
5159 case RID_CONST:
5160 case RID_EXTERN:
5161 case RID_REGISTER:
5162 case RID_TYPEDEF:
5163 case RID_SHORT:
5164 case RID_INLINE:
5165 case RID_NORETURN:
5166 case RID_VOLATILE:
5167 case RID_SIGNED:
5168 case RID_AUTO:
5169 case RID_RESTRICT:
5170 case RID_COMPLEX:
5171 case RID_THREAD:
5172 case RID_INT:
5173 case RID_CHAR:
5174 case RID_FLOAT:
5175 case RID_DOUBLE:
5176 case RID_VOID:
5177 case RID_DFLOAT32:
5178 case RID_DFLOAT64:
5179 case RID_DFLOAT128:
5180 CASE_RID_FLOATN_NX:
5181 case RID_BOOL:
5182 case RID_BITINT:
5183 case RID_FRACT:
5184 case RID_ACCUM:
5185 case RID_SAT:
5186 case RID_TRANSACTION_ATOMIC:
5187 case RID_TRANSACTION_CANCEL:
5188 case RID_ATOMIC:
5189 case RID_AUTO_TYPE:
5190 case RID_CONSTEXPR:
5191 case RID_INT_N_0:
5192 case RID_INT_N_1:
5193 case RID_INT_N_2:
5194 case RID_INT_N_3:
5195 ok = true;
5196 break;
5197 default:
5198 ok = false;
5199 break;
5200 }
5201 if (!ok)
5202 return NULL_TREE;
5203
5204 /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5205 attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5206 }
5207 else if (c_parser_next_token_is (parser, type: CPP_NAME))
5208 attr_name = c_parser_peek_token (parser)->value;
5209
5210 return attr_name;
5211}
5212
5213/* Parse attribute arguments. This is a common form of syntax
5214 covering all currently valid GNU and standard attributes.
5215
5216 gnu-attribute-arguments:
5217 identifier
5218 identifier , nonempty-expr-list
5219 expr-list
5220
5221 where the "identifier" must not be declared as a type. ??? Why not
5222 allow identifiers declared as types to start the arguments? */
5223
5224static tree
5225c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5226 bool require_string, bool assume_attr,
5227 bool allow_empty_args)
5228{
5229 vec<tree, va_gc> *expr_list;
5230 tree attr_args;
5231 /* Parse the attribute contents. If they start with an
5232 identifier which is followed by a comma or close
5233 parenthesis, then the arguments start with that
5234 identifier; otherwise they are an expression list.
5235 In objective-c the identifier may be a classname. */
5236 if (c_parser_next_token_is (parser, type: CPP_NAME)
5237 && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5238 || (c_dialect_objc ()
5239 && c_parser_peek_token (parser)->id_kind
5240 == C_ID_CLASSNAME))
5241 && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5242 || (c_parser_peek_2nd_token (parser)->type
5243 == CPP_CLOSE_PAREN))
5244 && (takes_identifier
5245 || (c_dialect_objc ()
5246 && !assume_attr
5247 && c_parser_peek_token (parser)->id_kind
5248 == C_ID_CLASSNAME)))
5249 {
5250 tree arg1 = c_parser_peek_token (parser)->value;
5251 c_parser_consume_token (parser);
5252 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5253 attr_args = build_tree_list (NULL_TREE, arg1);
5254 else
5255 {
5256 tree tree_list;
5257 c_parser_consume_token (parser);
5258 expr_list = c_parser_expr_list (parser, false, true,
5259 NULL, NULL, NULL, NULL);
5260 tree_list = build_tree_list_vec (expr_list);
5261 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5262 release_tree_vector (expr_list);
5263 }
5264 }
5265 else
5266 {
5267 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5268 {
5269 if (!allow_empty_args)
5270 error_at (c_parser_peek_token (parser)->location,
5271 "parentheses must be omitted if "
5272 "attribute argument list is empty");
5273 attr_args = NULL_TREE;
5274 }
5275 else if (require_string)
5276 {
5277 /* The only valid argument for this attribute is a string
5278 literal. Handle this specially here to avoid accepting
5279 string literals with excess parentheses. */
5280 tree string = c_parser_string_literal (parser, false, true).value;
5281 attr_args = build_tree_list (NULL_TREE, string);
5282 }
5283 else if (assume_attr)
5284 {
5285 tree cond
5286 = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5287 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
5288 attr_args = build_tree_list (NULL_TREE, cond);
5289 else
5290 {
5291 tree tree_list;
5292 c_parser_consume_token (parser);
5293 expr_list = c_parser_expr_list (parser, false, true,
5294 NULL, NULL, NULL, NULL);
5295 tree_list = build_tree_list_vec (expr_list);
5296 attr_args = tree_cons (NULL_TREE, cond, tree_list);
5297 release_tree_vector (expr_list);
5298 }
5299 }
5300 else
5301 {
5302 expr_list = c_parser_expr_list (parser, false, true,
5303 NULL, NULL, NULL, NULL);
5304 attr_args = build_tree_list_vec (expr_list);
5305 release_tree_vector (expr_list);
5306 }
5307 }
5308 return attr_args;
5309}
5310
5311/* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5312
5313 gnu-attributes:
5314 empty
5315 gnu-attributes gnu-attribute
5316
5317 gnu-attribute:
5318 __attribute__ ( ( gnu-attribute-list ) )
5319
5320 gnu-attribute-list:
5321 gnu-attrib
5322 gnu-attribute_list , gnu-attrib
5323
5324 gnu-attrib:
5325 empty
5326 any-word
5327 any-word ( gnu-attribute-arguments )
5328
5329 where "any-word" may be any identifier (including one declared as a
5330 type), a reserved word storage class specifier, type specifier or
5331 type qualifier. ??? This still leaves out most reserved keywords
5332 (following the old parser), shouldn't we include them?
5333 When EXPECT_COMMA is true, expect the attribute to be preceded
5334 by a comma and fail if it isn't.
5335 When EMPTY_OK is true, allow and consume any number of consecutive
5336 commas with no attributes in between. */
5337
5338static tree
5339c_parser_gnu_attribute (c_parser *parser, tree attrs,
5340 bool expect_comma = false, bool empty_ok = true)
5341{
5342 bool comma_first = c_parser_next_token_is (parser, type: CPP_COMMA);
5343 if (!comma_first
5344 && !c_parser_next_token_is (parser, type: CPP_NAME)
5345 && !c_parser_next_token_is (parser, type: CPP_KEYWORD))
5346 return NULL_TREE;
5347
5348 while (c_parser_next_token_is (parser, type: CPP_COMMA))
5349 {
5350 c_parser_consume_token (parser);
5351 if (!empty_ok)
5352 return attrs;
5353 }
5354
5355 tree attr_name = c_parser_gnu_attribute_any_word (parser);
5356 if (attr_name == NULL_TREE)
5357 return NULL_TREE;
5358
5359 attr_name = canonicalize_attr_name (attr_name);
5360 c_parser_consume_token (parser);
5361
5362 tree attr;
5363 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5364 {
5365 if (expect_comma && !comma_first)
5366 {
5367 /* A comma is missing between the last attribute on the chain
5368 and this one. */
5369 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5370 msgid: "expected %<)%>");
5371 return error_mark_node;
5372 }
5373 attr = build_tree_list (attr_name, NULL_TREE);
5374 /* Add this attribute to the list. */
5375 attrs = chainon (attrs, attr);
5376 return attrs;
5377 }
5378 c_parser_consume_token (parser);
5379
5380 tree attr_args
5381 = c_parser_attribute_arguments (parser,
5382 takes_identifier: attribute_takes_identifier_p (attr_name),
5383 require_string: false,
5384 assume_attr: is_attribute_p (attr_name: "assume", ident: attr_name),
5385 allow_empty_args: true);
5386
5387 attr = build_tree_list (attr_name, attr_args);
5388 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5389 c_parser_consume_token (parser);
5390 else
5391 {
5392 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5393 msgid: "expected %<)%>");
5394 return error_mark_node;
5395 }
5396
5397 if (expect_comma && !comma_first)
5398 {
5399 /* A comma is missing between the last attribute on the chain
5400 and this one. */
5401 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5402 msgid: "expected %<)%>");
5403 return error_mark_node;
5404 }
5405
5406 /* Add this attribute to the list. */
5407 attrs = chainon (attrs, attr);
5408 return attrs;
5409}
5410
5411static tree
5412c_parser_gnu_attributes (c_parser *parser)
5413{
5414 tree attrs = NULL_TREE;
5415 while (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5416 {
5417 bool save_translate_strings_p = parser->translate_strings_p;
5418 parser->translate_strings_p = false;
5419 /* Consume the `__attribute__' keyword. */
5420 c_parser_consume_token (parser);
5421 /* Look for the two `(' tokens. */
5422 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5423 {
5424 parser->translate_strings_p = save_translate_strings_p;
5425 return attrs;
5426 }
5427 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5428 {
5429 parser->translate_strings_p = save_translate_strings_p;
5430 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5431 return attrs;
5432 }
5433 /* Parse the attribute list. Require a comma between successive
5434 (possibly empty) attributes. */
5435 for (bool expect_comma = false; ; expect_comma = true)
5436 {
5437 /* Parse a single attribute. */
5438 tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5439 if (attr == error_mark_node)
5440 return attrs;
5441 if (!attr)
5442 break;
5443 attrs = attr;
5444 }
5445
5446 /* Look for the two `)' tokens. */
5447 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5448 c_parser_consume_token (parser);
5449 else
5450 {
5451 parser->translate_strings_p = save_translate_strings_p;
5452 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5453 msgid: "expected %<)%>");
5454 return attrs;
5455 }
5456 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5457 c_parser_consume_token (parser);
5458 else
5459 {
5460 parser->translate_strings_p = save_translate_strings_p;
5461 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5462 msgid: "expected %<)%>");
5463 return attrs;
5464 }
5465 parser->translate_strings_p = save_translate_strings_p;
5466 }
5467
5468 return attrs;
5469}
5470
5471/* Parse an optional balanced token sequence.
5472
5473 balanced-token-sequence:
5474 balanced-token
5475 balanced-token-sequence balanced-token
5476
5477 balanced-token:
5478 ( balanced-token-sequence[opt] )
5479 [ balanced-token-sequence[opt] ]
5480 { balanced-token-sequence[opt] }
5481 any token other than ()[]{}
5482*/
5483
5484static void
5485c_parser_balanced_token_sequence (c_parser *parser)
5486{
5487 while (true)
5488 {
5489 c_token *token = c_parser_peek_token (parser);
5490 switch (token->type)
5491 {
5492 case CPP_OPEN_BRACE:
5493 {
5494 matching_braces braces;
5495 braces.consume_open (parser);
5496 c_parser_balanced_token_sequence (parser);
5497 braces.require_close (parser);
5498 break;
5499 }
5500
5501 case CPP_OPEN_PAREN:
5502 {
5503 matching_parens parens;
5504 parens.consume_open (parser);
5505 c_parser_balanced_token_sequence (parser);
5506 parens.require_close (parser);
5507 break;
5508 }
5509
5510 case CPP_OPEN_SQUARE:
5511 c_parser_consume_token (parser);
5512 c_parser_balanced_token_sequence (parser);
5513 c_parser_require (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5514 break;
5515
5516 case CPP_CLOSE_BRACE:
5517 case CPP_CLOSE_PAREN:
5518 case CPP_CLOSE_SQUARE:
5519 case CPP_EOF:
5520 return;
5521
5522 case CPP_PRAGMA:
5523 c_parser_consume_pragma (parser);
5524 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
5525 break;
5526
5527 default:
5528 c_parser_consume_token (parser);
5529 break;
5530 }
5531 }
5532}
5533
5534static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
5535 unsigned int *);
5536
5537/* Parse arguments of omp::directive or omp::decl attribute.
5538
5539 directive-name ,[opt] clause-list[opt]
5540
5541 For directive just remember the tokens in a vector for subsequent
5542 parsing. */
5543
5544static void
5545c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5546{
5547 unsigned int n = 1;
5548 c_token *first = c_parser_peek_token (parser);
5549 if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
5550 || (c_parser_peek_nth_token_raw (parser, n)->type
5551 != CPP_CLOSE_PAREN))
5552 {
5553 c_parser_balanced_token_sequence (parser);
5554 TREE_VALUE (attribute) = NULL_TREE;
5555 return;
5556 }
5557 if (n == 1)
5558 {
5559 error_at (first->location, "expected OpenMP directive name");
5560 TREE_VALUE (attribute) = NULL_TREE;
5561 return;
5562 }
5563 vec<c_token, va_gc> *v;
5564 vec_alloc (v, nelems: n - 1);
5565 for (--n; n; --n)
5566 {
5567 c_token *tok = c_parser_peek_token (parser);
5568 v->quick_push (obj: *tok);
5569 c_parser_consume_token (parser);
5570 }
5571 tree arg = make_node (C_TOKEN_VEC);
5572 C_TOKEN_VEC_TOKENS (arg) = v;
5573 if (decl_p)
5574 TREE_PUBLIC (arg) = 1;
5575 TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
5576}
5577
5578/* Parse arguments of omp::sequence attribute.
5579
5580 omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
5581
5582static void
5583c_parser_omp_sequence_args (c_parser *parser, tree attribute)
5584{
5585 do
5586 {
5587 c_token *token = c_parser_peek_token (parser);
5588 if (token->type == CPP_NAME
5589 && strcmp (IDENTIFIER_POINTER (token->value), s2: "omp") == 0
5590 && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
5591 {
5592 c_parser_consume_token (parser);
5593 c_parser_consume_token (parser);
5594 token = c_parser_peek_token (parser);
5595 }
5596 bool directive = false;
5597 const char *p;
5598 if (token->type != CPP_NAME)
5599 p = "";
5600 else
5601 p = IDENTIFIER_POINTER (token->value);
5602 if (strcmp (s1: p, s2: "directive") == 0)
5603 directive = true;
5604 else if (strcmp (s1: p, s2: "sequence") != 0)
5605 {
5606 error_at (token->location, "expected %<directive%> or %<sequence%>");
5607 unsigned nesting_depth = 0;
5608
5609 while (true)
5610 {
5611 /* Peek at the next token. */
5612 token = c_parser_peek_token (parser);
5613 /* If we've reached the token we want, consume it and stop. */
5614 if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
5615 && !nesting_depth)
5616 break;
5617 /* If we've run out of tokens, stop. */
5618 if (token->type == CPP_EOF)
5619 break;
5620 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
5621 break;
5622 if (token->type == CPP_OPEN_BRACE
5623 || token->type == CPP_OPEN_PAREN
5624 || token->type == CPP_OPEN_SQUARE)
5625 ++nesting_depth;
5626 else if (token->type == CPP_CLOSE_BRACE
5627 || token->type == CPP_CLOSE_PAREN
5628 || token->type == CPP_CLOSE_SQUARE)
5629 {
5630 if (nesting_depth-- == 0)
5631 break;
5632 }
5633 /* Consume this token. */
5634 c_parser_consume_token (parser);
5635 }
5636 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5637 break;
5638 c_parser_consume_token (parser);
5639 continue;
5640 }
5641 c_parser_consume_token (parser);
5642 matching_parens parens;
5643 if (parens.require_open (parser))
5644 {
5645 if (directive)
5646 c_parser_omp_directive_args (parser, attribute, decl_p: false);
5647 else
5648 c_parser_omp_sequence_args (parser, attribute);
5649 parens.skip_until_found_close (parser);
5650 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5651 break;
5652 c_parser_consume_token (parser);
5653 }
5654 else if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5655 break;
5656 else
5657 c_parser_consume_token (parser);
5658 }
5659 while (1);
5660}
5661
5662/* Parse standard (C23) attributes (including GNU attributes in the
5663 gnu:: namespace).
5664
5665 attribute-specifier-sequence:
5666 attribute-specifier-sequence[opt] attribute-specifier
5667
5668 attribute-specifier:
5669 [ [ attribute-list ] ]
5670
5671 attribute-list:
5672 attribute[opt]
5673 attribute-list, attribute[opt]
5674
5675 attribute:
5676 attribute-token attribute-argument-clause[opt]
5677
5678 attribute-token:
5679 standard-attribute
5680 attribute-prefixed-token
5681
5682 standard-attribute:
5683 identifier
5684
5685 attribute-prefixed-token:
5686 attribute-prefix :: identifier
5687
5688 attribute-prefix:
5689 identifier
5690
5691 attribute-argument-clause:
5692 ( balanced-token-sequence[opt] )
5693
5694 Keywords are accepted as identifiers for this purpose.
5695
5696 As an extension, we permit an attribute-specifier to be:
5697
5698 [ [ __extension__ attribute-list ] ]
5699
5700 Two colons are then accepted as a synonym for ::. No attempt is made
5701 to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
5702 indicates whether this relaxation is in effect. */
5703
5704static tree
5705c_parser_std_attribute (c_parser *parser, bool for_tm,
5706 bool loose_scope_p = false)
5707{
5708 c_token *token = c_parser_peek_token (parser);
5709 tree ns, name, attribute;
5710
5711 /* Parse the attribute-token. */
5712 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
5713 {
5714 c_parser_error (parser, gmsgid: "expected identifier");
5715 return error_mark_node;
5716 }
5717 name = canonicalize_attr_name (attr_name: token->value);
5718 c_parser_consume_token (parser);
5719 if (c_parser_next_token_is (parser, type: CPP_SCOPE)
5720 || (loose_scope_p
5721 && c_parser_next_token_is (parser, type: CPP_COLON)
5722 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
5723 {
5724 ns = name;
5725 if (c_parser_next_token_is (parser, type: CPP_COLON))
5726 c_parser_consume_token (parser);
5727 c_parser_consume_token (parser);
5728 token = c_parser_peek_token (parser);
5729 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
5730 {
5731 c_parser_error (parser, gmsgid: "expected identifier");
5732 return error_mark_node;
5733 }
5734 name = canonicalize_attr_name (attr_name: token->value);
5735 c_parser_consume_token (parser);
5736 }
5737 else
5738 ns = NULL_TREE;
5739 attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
5740
5741 /* Parse the arguments, if any. */
5742 const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
5743 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5744 {
5745 if ((flag_openmp || flag_openmp_simd)
5746 && ns
5747 && is_attribute_p (attr_name: "omp", ident: ns)
5748 && (is_attribute_p (attr_name: "directive", ident: name)
5749 || is_attribute_p (attr_name: "sequence", ident: name)
5750 || is_attribute_p (attr_name: "decl", ident: name)))
5751 {
5752 error ("%<omp::%E%> attribute requires argument", name);
5753 return error_mark_node;
5754 }
5755 goto out;
5756 }
5757 {
5758 location_t open_loc = c_parser_peek_token (parser)->location;
5759 matching_parens parens;
5760 parens.consume_open (parser);
5761 if ((as && as->max_length == 0)
5762 /* Special-case the transactional-memory attribute "outer",
5763 which is specially handled but not registered as an
5764 attribute, to avoid allowing arbitrary balanced token
5765 sequences as arguments. */
5766 || is_attribute_p (attr_name: "outer", ident: name))
5767 {
5768 error_at (open_loc, "%qE attribute does not take any arguments", name);
5769 parens.skip_until_found_close (parser);
5770 return error_mark_node;
5771 }
5772 /* If this is a fake attribute created to handle -Wno-attributes,
5773 we must skip parsing the arguments. */
5774 if (as && !attribute_ignored_p (as))
5775 {
5776 bool takes_identifier
5777 = (ns != NULL_TREE
5778 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
5779 && attribute_takes_identifier_p (name));
5780 bool require_string
5781 = (ns == NULL_TREE
5782 && (strcmp (IDENTIFIER_POINTER (name), s2: "deprecated") == 0
5783 || strcmp (IDENTIFIER_POINTER (name), s2: "nodiscard") == 0));
5784 bool assume_attr
5785 = (ns != NULL_TREE
5786 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
5787 && strcmp (IDENTIFIER_POINTER (name), s2: "assume") == 0);
5788 TREE_VALUE (attribute)
5789 = c_parser_attribute_arguments (parser, takes_identifier,
5790 require_string, assume_attr, allow_empty_args: false);
5791 }
5792 else
5793 {
5794 if ((flag_openmp || flag_openmp_simd)
5795 && ns
5796 && is_attribute_p (attr_name: "omp", ident: ns))
5797 {
5798 if (is_attribute_p (attr_name: "directive", ident: name))
5799 {
5800 c_parser_omp_directive_args (parser, attribute, decl_p: false);
5801 parens.skip_until_found_close (parser);
5802 return attribute;
5803 }
5804 else if (is_attribute_p (attr_name: "decl", ident: name))
5805 {
5806 TREE_VALUE (TREE_PURPOSE (attribute))
5807 = get_identifier ("directive");
5808 c_parser_omp_directive_args (parser, attribute, decl_p: true);
5809 parens.skip_until_found_close (parser);
5810 return attribute;
5811 }
5812 else if (is_attribute_p (attr_name: "sequence", ident: name))
5813 {
5814 TREE_VALUE (TREE_PURPOSE (attribute))
5815 = get_identifier ("directive");
5816 c_parser_omp_sequence_args (parser, attribute);
5817 parens.skip_until_found_close (parser);
5818 TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
5819 return attribute;
5820 }
5821 }
5822 c_parser_balanced_token_sequence (parser);
5823 }
5824 parens.require_close (parser);
5825 }
5826 out:
5827 if (ns == NULL_TREE && !for_tm && !as)
5828 {
5829 /* An attribute with standard syntax and no namespace specified
5830 is a constraint violation if it is not one of the known
5831 standard attributes. Diagnose it here with a pedwarn and
5832 then discard it to prevent a duplicate warning later. */
5833 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
5834 name);
5835 return error_mark_node;
5836 }
5837 return attribute;
5838}
5839
5840static tree
5841c_parser_std_attribute_list (c_parser *parser, bool for_tm,
5842 bool loose_scope_p = false)
5843{
5844 tree attributes = NULL_TREE;
5845 while (true)
5846 {
5847 c_token *token = c_parser_peek_token (parser);
5848 if (token->type == CPP_CLOSE_SQUARE)
5849 break;
5850 if (token->type == CPP_COMMA)
5851 {
5852 c_parser_consume_token (parser);
5853 continue;
5854 }
5855 tree attribute = c_parser_std_attribute (parser, for_tm, loose_scope_p);
5856 if (attribute != error_mark_node)
5857 {
5858 TREE_CHAIN (attribute) = attributes;
5859 attributes = attribute;
5860 }
5861 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5862 break;
5863 }
5864 return attributes;
5865}
5866
5867static tree
5868c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
5869{
5870 location_t loc = c_parser_peek_token (parser)->location;
5871 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
5872 return NULL_TREE;
5873 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
5874 {
5875 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5876 return NULL_TREE;
5877 }
5878 tree attributes;
5879 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
5880 {
5881 auto ext = disable_extension_diagnostics ();
5882 c_parser_consume_token (parser);
5883 attributes = c_parser_std_attribute_list (parser, for_tm, loose_scope_p: true);
5884 restore_extension_diagnostics (flags: ext);
5885 }
5886 else
5887 {
5888 if (!for_tm)
5889 pedwarn_c11 (loc, opt: OPT_Wpedantic,
5890 "ISO C does not support %<[[]]%> attributes before C23");
5891 attributes = c_parser_std_attribute_list (parser, for_tm);
5892 }
5893 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5894 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5895 return nreverse (attributes);
5896}
5897
5898/* Look past an optional balanced token sequence of raw look-ahead
5899 tokens starting with the *Nth token. *N is updated to point to the
5900 following token. Return true if such a sequence was found, false
5901 if the tokens parsed were not balanced. */
5902
5903static bool
5904c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
5905{
5906 while (true)
5907 {
5908 c_token *token = c_parser_peek_nth_token_raw (parser, n: *n);
5909 switch (token->type)
5910 {
5911 case CPP_OPEN_BRACE:
5912 {
5913 ++*n;
5914 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5915 {
5916 token = c_parser_peek_nth_token_raw (parser, n: *n);
5917 if (token->type == CPP_CLOSE_BRACE)
5918 ++*n;
5919 else
5920 return false;
5921 }
5922 else
5923 return false;
5924 break;
5925 }
5926
5927 case CPP_OPEN_PAREN:
5928 {
5929 ++*n;
5930 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5931 {
5932 token = c_parser_peek_nth_token_raw (parser, n: *n);
5933 if (token->type == CPP_CLOSE_PAREN)
5934 ++*n;
5935 else
5936 return false;
5937 }
5938 else
5939 return false;
5940 break;
5941 }
5942
5943 case CPP_OPEN_SQUARE:
5944 {
5945 ++*n;
5946 if (c_parser_check_balanced_raw_token_sequence (parser, n))
5947 {
5948 token = c_parser_peek_nth_token_raw (parser, n: *n);
5949 if (token->type == CPP_CLOSE_SQUARE)
5950 ++*n;
5951 else
5952 return false;
5953 }
5954 else
5955 return false;
5956 break;
5957 }
5958
5959 case CPP_CLOSE_BRACE:
5960 case CPP_CLOSE_PAREN:
5961 case CPP_CLOSE_SQUARE:
5962 case CPP_EOF:
5963 return true;
5964
5965 default:
5966 ++*n;
5967 break;
5968 }
5969 }
5970}
5971
5972/* Return whether standard attributes start with the Nth token. */
5973
5974static bool
5975c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
5976{
5977 if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
5978 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_OPEN_SQUARE))
5979 return false;
5980 /* In C, '[[' must start attributes. In Objective-C, we need to
5981 check whether '[[' is matched by ']]'. */
5982 if (!c_dialect_objc ())
5983 return true;
5984 n += 2;
5985 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
5986 return false;
5987 c_token *token = c_parser_peek_nth_token_raw (parser, n);
5988 if (token->type != CPP_CLOSE_SQUARE)
5989 return false;
5990 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
5991 return token->type == CPP_CLOSE_SQUARE;
5992}
5993
5994static tree
5995c_parser_std_attribute_specifier_sequence (c_parser *parser)
5996{
5997 tree attributes = NULL_TREE;
5998 do
5999 {
6000 tree attrs = c_parser_std_attribute_specifier (parser, for_tm: false);
6001 attributes = chainon (attributes, attrs);
6002 }
6003 while (c_parser_nth_token_starts_std_attributes (parser, n: 1));
6004 return attributes;
6005}
6006
6007/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6008 says whether alignment specifiers are OK (only in cases that might
6009 be the type name of a compound literal).
6010
6011 type-name:
6012 specifier-qualifier-list abstract-declarator[opt]
6013*/
6014
6015struct c_type_name *
6016c_parser_type_name (c_parser *parser, bool alignas_ok)
6017{
6018 struct c_declspecs *specs = build_null_declspecs ();
6019 struct c_declarator *declarator;
6020 struct c_type_name *ret;
6021 bool dummy = false;
6022 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true, alignspec_ok: alignas_ok, auto_type_ok: false,
6023 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_type);
6024 if (!specs->declspecs_seen_p)
6025 {
6026 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
6027 return NULL;
6028 }
6029 if (specs->type != error_mark_node)
6030 {
6031 pending_xref_error ();
6032 finish_declspecs (specs);
6033 }
6034 declarator = c_parser_declarator (parser,
6035 type_seen_p: specs->typespec_kind != ctsk_none,
6036 kind: C_DTR_ABSTRACT, seen_id: &dummy);
6037 if (declarator == NULL)
6038 return NULL;
6039 ret = XOBNEW (&parser_obstack, struct c_type_name);
6040 ret->specs = specs;
6041 ret->declarator = declarator;
6042 return ret;
6043}
6044
6045/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6046
6047 initializer:
6048 assignment-expression
6049 { initializer-list }
6050 { initializer-list , }
6051
6052 initializer-list:
6053 designation[opt] initializer
6054 initializer-list , designation[opt] initializer
6055
6056 designation:
6057 designator-list =
6058
6059 designator-list:
6060 designator
6061 designator-list designator
6062
6063 designator:
6064 array-designator
6065 . identifier
6066
6067 array-designator:
6068 [ constant-expression ]
6069
6070 GNU extensions:
6071
6072 initializer:
6073 { }
6074
6075 designation:
6076 array-designator
6077 identifier :
6078
6079 array-designator:
6080 [ constant-expression ... constant-expression ]
6081
6082 Any expression without commas is accepted in the syntax for the
6083 constant-expressions, with non-constant expressions rejected later.
6084
6085 DECL is the declaration we're parsing this initializer for.
6086
6087 This function is only used for top-level initializers; for nested
6088 ones, see c_parser_initval. */
6089
6090static struct c_expr
6091c_parser_initializer (c_parser *parser, tree decl)
6092{
6093 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
6094 return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
6095 else
6096 {
6097 struct c_expr ret;
6098 location_t loc = c_parser_peek_token (parser)->location;
6099 ret = c_parser_expr_no_commas (parser, NULL);
6100 if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6101 {
6102 error_at (loc,
6103 "variable-sized object may not be initialized except "
6104 "with an empty initializer");
6105 ret.set_error ();
6106 }
6107 /* This is handled mostly by gimplify.cc, but we have to deal with
6108 not warning about int x = x; as it is a GCC extension to turn off
6109 this warning but only if warn_init_self is zero. */
6110 if (VAR_P (decl)
6111 && !DECL_EXTERNAL (decl)
6112 && !TREE_STATIC (decl)
6113 && ret.value == decl
6114 && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), opt: OPT_Winit_self))
6115 suppress_warning (decl, OPT_Winit_self);
6116 if (TREE_CODE (ret.value) != STRING_CST
6117 && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6118 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6119 (ret.value))))
6120 ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6121 return ret;
6122 }
6123}
6124
6125/* The location of the last comma within the current initializer list,
6126 or UNKNOWN_LOCATION if not within one. */
6127
6128location_t last_init_list_comma;
6129
6130/* Parse a braced initializer list. TYPE is the type specified for a
6131 compound literal, and NULL_TREE for other initializers and for
6132 nested braced lists. NESTED_P is true for nested braced lists,
6133 false for the list of a compound literal or the list that is the
6134 top-level initializer in a declaration. DECL is the declaration for
6135 the top-level initializer for a declaration, otherwise NULL_TREE. */
6136
6137static struct c_expr
6138c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6139 struct obstack *outer_obstack, tree decl)
6140{
6141 struct c_expr ret;
6142 struct obstack braced_init_obstack;
6143 location_t brace_loc = c_parser_peek_token (parser)->location;
6144 gcc_obstack_init (&braced_init_obstack);
6145 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6146 matching_braces braces;
6147 braces.consume_open (parser);
6148 if (nested_p)
6149 {
6150 finish_implicit_inits (brace_loc, outer_obstack);
6151 push_init_level (brace_loc, 0, &braced_init_obstack);
6152 }
6153 else
6154 really_start_incremental_init (type);
6155 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6156 {
6157 pedwarn_c11 (brace_loc, opt: OPT_Wpedantic,
6158 "ISO C forbids empty initializer braces before C23");
6159 }
6160 else
6161 {
6162 if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6163 error_at (brace_loc,
6164 "variable-sized object may not be initialized except "
6165 "with an empty initializer");
6166 /* Parse a non-empty initializer list, possibly with a trailing
6167 comma. */
6168 while (true)
6169 {
6170 c_parser_initelt (parser, &braced_init_obstack);
6171 if (parser->error)
6172 break;
6173 if (c_parser_next_token_is (parser, type: CPP_COMMA))
6174 {
6175 last_init_list_comma = c_parser_peek_token (parser)->location;
6176 c_parser_consume_token (parser);
6177 }
6178 else
6179 break;
6180 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6181 break;
6182 }
6183 }
6184 c_token *next_tok = c_parser_peek_token (parser);
6185 if (next_tok->type != CPP_CLOSE_BRACE)
6186 {
6187 ret.set_error ();
6188 ret.original_code = ERROR_MARK;
6189 ret.original_type = NULL;
6190 braces.skip_until_found_close (parser);
6191 pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6192 obstack_free (&braced_init_obstack, NULL);
6193 return ret;
6194 }
6195 location_t close_loc = next_tok->location;
6196 c_parser_consume_token (parser);
6197 ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6198 obstack_free (&braced_init_obstack, NULL);
6199 set_c_expr_source_range (expr: &ret, start: brace_loc, finish: close_loc);
6200 return ret;
6201}
6202
6203/* Parse a nested initializer, including designators. */
6204
6205static void
6206c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6207{
6208 /* Parse any designator or designator list. A single array
6209 designator may have the subsequent "=" omitted in GNU C, but a
6210 longer list or a structure member designator may not. */
6211 if (c_parser_next_token_is (parser, type: CPP_NAME)
6212 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6213 {
6214 /* Old-style structure member designator. */
6215 set_init_label (c_parser_peek_token (parser)->location,
6216 c_parser_peek_token (parser)->value,
6217 c_parser_peek_token (parser)->location,
6218 braced_init_obstack);
6219 /* Use the colon as the error location. */
6220 pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6221 "obsolete use of designated initializer with %<:%>");
6222 c_parser_consume_token (parser);
6223 c_parser_consume_token (parser);
6224 }
6225 else
6226 {
6227 /* des_seen is 0 if there have been no designators, 1 if there
6228 has been a single array designator and 2 otherwise. */
6229 int des_seen = 0;
6230 /* Location of a designator. */
6231 location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6232 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
6233 || c_parser_next_token_is (parser, type: CPP_DOT))
6234 {
6235 int des_prev = des_seen;
6236 if (!des_seen)
6237 des_loc = c_parser_peek_token (parser)->location;
6238 if (des_seen < 2)
6239 des_seen++;
6240 if (c_parser_next_token_is (parser, type: CPP_DOT))
6241 {
6242 des_seen = 2;
6243 c_parser_consume_token (parser);
6244 if (c_parser_next_token_is (parser, type: CPP_NAME))
6245 {
6246 set_init_label (des_loc, c_parser_peek_token (parser)->value,
6247 c_parser_peek_token (parser)->location,
6248 braced_init_obstack);
6249 c_parser_consume_token (parser);
6250 }
6251 else
6252 {
6253 struct c_expr init;
6254 init.set_error ();
6255 init.original_code = ERROR_MARK;
6256 init.original_type = NULL;
6257 c_parser_error (parser, gmsgid: "expected identifier");
6258 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6259 process_init_element (input_location, init, false,
6260 braced_init_obstack);
6261 return;
6262 }
6263 }
6264 else
6265 {
6266 struct c_expr first_expr;
6267 tree first, second;
6268 location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6269 location_t array_index_loc = UNKNOWN_LOCATION;
6270 /* ??? Following the old parser, [ objc-receiver
6271 objc-message-args ] is accepted as an initializer,
6272 being distinguished from a designator by what follows
6273 the first assignment expression inside the square
6274 brackets, but after a first array designator a
6275 subsequent square bracket is for Objective-C taken to
6276 start an expression, using the obsolete form of
6277 designated initializer without '=', rather than
6278 possibly being a second level of designation: in LALR
6279 terms, the '[' is shifted rather than reducing
6280 designator to designator-list. */
6281 if (des_prev == 1 && c_dialect_objc ())
6282 {
6283 des_seen = des_prev;
6284 break;
6285 }
6286 if (des_prev == 0 && c_dialect_objc ())
6287 {
6288 /* This might be an array designator or an
6289 Objective-C message expression. If the former,
6290 continue parsing here; if the latter, parse the
6291 remainder of the initializer given the starting
6292 primary-expression. ??? It might make sense to
6293 distinguish when des_prev == 1 as well; see
6294 previous comment. */
6295 tree rec, args;
6296 struct c_expr mexpr;
6297 c_parser_consume_token (parser);
6298 if (c_parser_peek_token (parser)->type == CPP_NAME
6299 && ((c_parser_peek_token (parser)->id_kind
6300 == C_ID_TYPENAME)
6301 || (c_parser_peek_token (parser)->id_kind
6302 == C_ID_CLASSNAME)))
6303 {
6304 /* Type name receiver. */
6305 tree id = c_parser_peek_token (parser)->value;
6306 c_parser_consume_token (parser);
6307 rec = objc_get_class_reference (id);
6308 goto parse_message_args;
6309 }
6310 array_index_loc = c_parser_peek_token (parser)->location;
6311 first_expr = c_parser_expr_no_commas (parser, NULL);
6312 mark_exp_read (first_expr.value);
6313 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS)
6314 || c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6315 goto array_desig_after_first;
6316 first = first_expr.value;
6317 /* Expression receiver. So far only one part
6318 without commas has been parsed; there might be
6319 more of the expression. */
6320 rec = first;
6321 while (c_parser_next_token_is (parser, type: CPP_COMMA))
6322 {
6323 struct c_expr next;
6324 location_t comma_loc, exp_loc;
6325 comma_loc = c_parser_peek_token (parser)->location;
6326 c_parser_consume_token (parser);
6327 exp_loc = c_parser_peek_token (parser)->location;
6328 next = c_parser_expr_no_commas (parser, NULL);
6329 next = convert_lvalue_to_rvalue (exp_loc, next,
6330 true, true);
6331 rec = build_compound_expr (comma_loc, rec, next.value);
6332 }
6333 parse_message_args:
6334 /* Now parse the objc-message-args. */
6335 args = c_parser_objc_message_args (parser);
6336 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6337 msgid: "expected %<]%>");
6338 mexpr.value
6339 = objc_build_message_expr (rec, args);
6340 mexpr.original_code = ERROR_MARK;
6341 mexpr.original_type = NULL;
6342 mexpr.m_decimal = 0;
6343 /* Now parse and process the remainder of the
6344 initializer, starting with this message
6345 expression as a primary-expression. */
6346 c_parser_initval (parser, &mexpr, braced_init_obstack);
6347 return;
6348 }
6349 c_parser_consume_token (parser);
6350 array_index_loc = c_parser_peek_token (parser)->location;
6351 first_expr = c_parser_expr_no_commas (parser, NULL);
6352 mark_exp_read (first_expr.value);
6353 array_desig_after_first:
6354 first_expr = convert_lvalue_to_rvalue (array_index_loc,
6355 first_expr,
6356 true, true);
6357 first = first_expr.value;
6358 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
6359 {
6360 ellipsis_loc = c_parser_peek_token (parser)->location;
6361 c_parser_consume_token (parser);
6362 second = convert_lvalue_to_rvalue (ellipsis_loc,
6363 (c_parser_expr_no_commas
6364 (parser, NULL)),
6365 true, true).value;
6366 mark_exp_read (second);
6367 }
6368 else
6369 second = NULL_TREE;
6370 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6371 {
6372 c_parser_consume_token (parser);
6373 set_init_index (array_index_loc, first, second,
6374 braced_init_obstack);
6375 if (second)
6376 pedwarn (ellipsis_loc, OPT_Wpedantic,
6377 "ISO C forbids specifying range of elements to initialize");
6378 }
6379 else
6380 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6381 msgid: "expected %<]%>");
6382 }
6383 }
6384 if (des_seen >= 1)
6385 {
6386 if (c_parser_next_token_is (parser, type: CPP_EQ))
6387 {
6388 pedwarn_c90 (des_loc, opt: OPT_Wpedantic,
6389 "ISO C90 forbids specifying subobject "
6390 "to initialize");
6391 c_parser_consume_token (parser);
6392 }
6393 else
6394 {
6395 if (des_seen == 1)
6396 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6397 "obsolete use of designated initializer without %<=%>");
6398 else
6399 {
6400 struct c_expr init;
6401 init.set_error ();
6402 init.original_code = ERROR_MARK;
6403 init.original_type = NULL;
6404 c_parser_error (parser, gmsgid: "expected %<=%>");
6405 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6406 process_init_element (input_location, init, false,
6407 braced_init_obstack);
6408 return;
6409 }
6410 }
6411 }
6412 }
6413 c_parser_initval (parser, NULL, braced_init_obstack);
6414}
6415
6416/* Parse a nested initializer; as c_parser_initializer but parses
6417 initializers within braced lists, after any designators have been
6418 applied. If AFTER is not NULL then it is an Objective-C message
6419 expression which is the primary-expression starting the
6420 initializer. */
6421
6422static void
6423c_parser_initval (c_parser *parser, struct c_expr *after,
6424 struct obstack * braced_init_obstack)
6425{
6426 struct c_expr init;
6427 gcc_assert (!after || c_dialect_objc ());
6428 location_t loc = c_parser_peek_token (parser)->location;
6429
6430 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE) && !after)
6431 init = c_parser_braced_init (parser, NULL_TREE, nested_p: true,
6432 outer_obstack: braced_init_obstack, NULL_TREE);
6433 else
6434 {
6435 init = c_parser_expr_no_commas (parser, after);
6436 if (init.value != NULL_TREE
6437 && TREE_CODE (init.value) != STRING_CST
6438 && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6439 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6440 (init.value))))
6441 init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6442 }
6443 process_init_element (loc, init, false, braced_init_obstack);
6444}
6445
6446/* Parse a compound statement (possibly a function body) (C90 6.6.2,
6447 C99 6.8.2, C11 6.8.2, C23 6.8.2).
6448
6449 compound-statement:
6450 { block-item-list[opt] }
6451 { label-declarations block-item-list }
6452
6453 block-item-list:
6454 block-item
6455 block-item-list block-item
6456
6457 block-item:
6458 label
6459 nested-declaration
6460 statement
6461
6462 nested-declaration:
6463 declaration
6464
6465 GNU extensions:
6466
6467 compound-statement:
6468 { label-declarations block-item-list }
6469
6470 nested-declaration:
6471 __extension__ nested-declaration
6472 nested-function-definition
6473
6474 label-declarations:
6475 label-declaration
6476 label-declarations label-declaration
6477
6478 label-declaration:
6479 __label__ identifier-list ;
6480
6481 Allowing the mixing of declarations and code is new in C99. The
6482 GNU syntax also permits (not shown above) labels at the end of
6483 compound statements, which yield an error. We don't allow labels
6484 on declarations; this might seem like a natural extension, but
6485 there would be a conflict between gnu-attributes on the label and
6486 prefix gnu-attributes on the declaration. ??? The syntax follows the
6487 old parser in requiring something after label declarations.
6488 Although they are erroneous if the labels declared aren't defined,
6489 is it useful for the syntax to be this way?
6490
6491 OpenACC:
6492
6493 block-item:
6494 openacc-directive
6495
6496 openacc-directive:
6497 update-directive
6498
6499 OpenMP:
6500
6501 block-item:
6502 openmp-directive
6503
6504 openmp-directive:
6505 barrier-directive
6506 flush-directive
6507 taskwait-directive
6508 taskyield-directive
6509 cancel-directive
6510 cancellation-point-directive */
6511
6512static tree
6513c_parser_compound_statement (c_parser *parser, location_t *endlocp)
6514{
6515 tree stmt;
6516 location_t brace_loc;
6517 brace_loc = c_parser_peek_token (parser)->location;
6518 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
6519 {
6520 /* Ensure a scope is entered and left anyway to avoid confusion
6521 if we have just prepared to enter a function body. */
6522 stmt = c_begin_compound_stmt (true);
6523 c_end_compound_stmt (brace_loc, stmt, true);
6524 return error_mark_node;
6525 }
6526 stmt = c_begin_compound_stmt (true);
6527 location_t end_loc = c_parser_compound_statement_nostart (parser);
6528 if (endlocp)
6529 *endlocp = end_loc;
6530
6531 return c_end_compound_stmt (brace_loc, stmt, true);
6532}
6533
6534/* Diagnose errors related to imperfectly nested loops in an OMP
6535 loop construct. This function is called when such code is seen.
6536 Only issue one such diagnostic no matter how much invalid
6537 intervening code there is in the loop.
6538 FIXME: maybe the location associated with the diagnostic should
6539 be the current parser token instead of the location of the outer loop
6540 nest. */
6541
6542static void
6543check_omp_intervening_code (c_parser *parser)
6544{
6545 struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
6546 gcc_assert (omp_for_parse_state);
6547
6548 if (!omp_for_parse_state->in_intervening_code)
6549 return;
6550 omp_for_parse_state->saw_intervening_code = true;
6551
6552 /* Only diagnose errors related to perfect nesting once. */
6553 if (!omp_for_parse_state->perfect_nesting_fail)
6554 {
6555
6556 /* OpenACC does not (yet) permit intervening code, in
6557 addition to situations forbidden by the OpenMP spec. */
6558 if (omp_for_parse_state->code == OACC_LOOP)
6559 {
6560 error_at (omp_for_parse_state->for_loc,
6561 "inner loops must be perfectly nested in "
6562 "%<#pragma acc loop%>");
6563 omp_for_parse_state->perfect_nesting_fail = true;
6564 }
6565 else if (omp_for_parse_state->ordered)
6566 {
6567 error_at (omp_for_parse_state->for_loc,
6568 "inner loops must be perfectly nested with "
6569 "%<ordered%> clause");
6570 omp_for_parse_state->perfect_nesting_fail = true;
6571 }
6572 else if (omp_for_parse_state->inscan)
6573 {
6574 error_at (omp_for_parse_state->for_loc,
6575 "inner loops must be perfectly nested with "
6576 "%<reduction%> %<inscan%> clause");
6577 omp_for_parse_state->perfect_nesting_fail = true;
6578 }
6579 /* TODO: Also reject loops with TILE directive. */
6580 if (omp_for_parse_state->perfect_nesting_fail)
6581 omp_for_parse_state->fail = true;
6582 }
6583}
6584
6585/* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
6586 and add the statement to the current list. If SL is an empty statement
6587 list, do nothing. */
6588static void
6589add_structured_block_stmt (tree sl)
6590{
6591 if (TREE_CODE (sl) != STATEMENT_LIST
6592 || !tsi_end_p (i: tsi_start (t: sl)))
6593 add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
6594}
6595
6596struct c_omp_attribute_data
6597{
6598 vec<c_token, va_gc> *tokens;
6599 const c_omp_directive *dir;
6600 c_omp_directive_kind kind;
6601};
6602
6603/* Handle omp::directive and omp::sequence attributes in ATTRS
6604 (if any) at the start of a statement or in attribute-declaration. */
6605
6606static bool
6607c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
6608 bool *have_std_attrs)
6609{
6610 if (!flag_openmp && !flag_openmp_simd)
6611 return false;
6612
6613 auto_vec<c_omp_attribute_data, 16> vd;
6614 int cnt = 0;
6615 int tokens = 0;
6616 bool bad = false;
6617 for (tree *pa = &attrs; *pa; )
6618 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6619 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
6620 {
6621 cnt++;
6622 for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
6623 {
6624 tree d = TREE_VALUE (a);
6625 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
6626 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
6627 c_token *first = toks->address ();
6628 c_token *last = first + toks->length ();
6629 if (parser->omp_attrs_forbidden_p)
6630 {
6631 error_at (first->location,
6632 "mixing OpenMP directives with attribute and pragma "
6633 "syntax on the same statement");
6634 parser->omp_attrs_forbidden_p = false;
6635 bad = true;
6636 }
6637 else if (TREE_PUBLIC (d))
6638 {
6639 error_at (first->location,
6640 "OpenMP %<omp::decl%> attribute on a statement");
6641 bad = true;
6642 }
6643 const char *directive[3] = {};
6644 for (int i = 0; i < 3; i++)
6645 {
6646 tree id = NULL_TREE;
6647 if (first + i == last)
6648 break;
6649 if (first[i].type == CPP_NAME)
6650 id = first[i].value;
6651 else if (first[i].type == CPP_KEYWORD)
6652 id = ridpointers[(int) first[i].keyword];
6653 else
6654 break;
6655 directive[i] = IDENTIFIER_POINTER (id);
6656 }
6657 const c_omp_directive *dir = NULL;
6658 if (directive[0])
6659 dir = c_omp_categorize_directive (directive[0], directive[1],
6660 directive[2]);
6661 if (dir == NULL)
6662 {
6663 error_at (first->location,
6664 "unknown OpenMP directive name in %qs attribute "
6665 "argument",
6666 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
6667 continue;
6668 }
6669 c_omp_directive_kind kind = dir->kind;
6670 if (dir->id == PRAGMA_OMP_ORDERED)
6671 {
6672 /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
6673 depend/doacross clause. */
6674 if (directive[1]
6675 && (strcmp (s1: directive[1], s2: "depend") == 0
6676 || strcmp (s1: directive[1], s2: "doacross") == 0))
6677 kind = C_OMP_DIR_STANDALONE;
6678 else if (first + 2 < last
6679 && first[1].type == CPP_COMMA
6680 && first[2].type == CPP_NAME
6681 && (strcmp (IDENTIFIER_POINTER (first[2].value),
6682 s2: "depend") == 0
6683 || strcmp (IDENTIFIER_POINTER (first[2].value),
6684 s2: "doacross") == 0))
6685 kind = C_OMP_DIR_STANDALONE;
6686 }
6687 else if (dir->id == PRAGMA_OMP_ERROR)
6688 {
6689 /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
6690 int paren_depth = 0;
6691 for (int i = 1; first + i < last; i++)
6692 if (first[i].type == CPP_OPEN_PAREN)
6693 paren_depth++;
6694 else if (first[i].type == CPP_CLOSE_PAREN)
6695 paren_depth--;
6696 else if (paren_depth == 0
6697 && first + i + 2 < last
6698 && first[i].type == CPP_NAME
6699 && first[i + 1].type == CPP_OPEN_PAREN
6700 && first[i + 2].type == CPP_NAME
6701 && !strcmp (IDENTIFIER_POINTER (first[i].value),
6702 s2: "at")
6703 && !strcmp (IDENTIFIER_POINTER (first[i
6704 + 2].value),
6705 s2: "execution"))
6706 {
6707 kind = C_OMP_DIR_STANDALONE;
6708 break;
6709 }
6710 }
6711 c_omp_attribute_data v = { .tokens: toks, .dir: dir, .kind: kind };
6712 vd.safe_push (obj: v);
6713 if (flag_openmp || dir->simd)
6714 tokens += (last - first) + 1;
6715 }
6716 c_omp_attribute_data v = {};
6717 vd.safe_push (obj: v);
6718 *pa = TREE_CHAIN (*pa);
6719 }
6720 else
6721 pa = &TREE_CHAIN (*pa);
6722
6723 if (bad)
6724 {
6725 fail:
6726 if (have_std_attrs && attrs == NULL)
6727 *have_std_attrs = false;
6728 return false;
6729 }
6730
6731 unsigned int i;
6732 c_omp_attribute_data *v;
6733 c_omp_attribute_data *construct_seen = nullptr;
6734 c_omp_attribute_data *standalone_seen = nullptr;
6735 c_omp_attribute_data *prev_standalone_seen = nullptr;
6736 FOR_EACH_VEC_ELT (vd, i, v)
6737 if (v->tokens)
6738 {
6739 if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
6740 construct_seen = v;
6741 else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
6742 standalone_seen = v;
6743 }
6744 else
6745 {
6746 if (standalone_seen && !prev_standalone_seen)
6747 {
6748 prev_standalone_seen = standalone_seen;
6749 standalone_seen = nullptr;
6750 }
6751 }
6752
6753 if (cnt > 1 && construct_seen)
6754 {
6755 error_at ((*construct_seen->tokens)[0].location,
6756 "OpenMP construct among %<omp::directive%> attributes"
6757 " requires all %<omp::directive%> attributes on the"
6758 " same statement to be in the same %<omp::sequence%>");
6759 goto fail;
6760 }
6761 if (cnt > 1 && standalone_seen && prev_standalone_seen)
6762 {
6763 error_at ((*standalone_seen->tokens)[0].location,
6764 "multiple OpenMP standalone directives among"
6765 " %<omp::directive%> attributes must be all within the"
6766 " same %<omp::sequence%>");
6767 goto fail;
6768 }
6769
6770 if (prev_standalone_seen)
6771 standalone_seen = prev_standalone_seen;
6772 if (standalone_seen
6773 && !c_parser_next_token_is (parser, type: CPP_SEMICOLON))
6774 {
6775 error_at (standalone_seen->tokens->address ()->location,
6776 "standalone OpenMP directives in %<omp::directive%> attribute"
6777 " can only appear on an empty statement");
6778 goto fail;
6779 }
6780 if (cnt && c_parser_next_token_is (parser, type: CPP_PRAGMA))
6781 {
6782 c_token *token = c_parser_peek_token (parser);
6783 enum pragma_kind kind = token->pragma_kind;
6784 if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
6785 {
6786 error_at (token->location,
6787 "mixing OpenMP directives with attribute and pragma "
6788 "syntax on the same statement");
6789 goto fail;
6790 }
6791 }
6792
6793 if (!tokens)
6794 return false;
6795
6796 unsigned int tokens_avail = parser->tokens_avail;
6797 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
6798
6799 tokens++;
6800 vec<c_token, va_gc> *toks = NULL;
6801 vec_safe_reserve (v&: toks, nelems: tokens, exact: true);
6802 FOR_EACH_VEC_ELT (vd, i, v)
6803 {
6804 if (!v->tokens)
6805 continue;
6806 if (!flag_openmp && !v->dir->simd)
6807 continue;
6808 c_token *first = v->tokens->address ();
6809 c_token *last = first + v->tokens->length ();
6810 c_token tok = {};
6811 tok.type = CPP_PRAGMA;
6812 tok.keyword = RID_MAX;
6813 tok.pragma_kind = pragma_kind (v->dir->id);
6814 tok.location = first->location;
6815 toks->quick_push (obj: tok);
6816 while (++first < last)
6817 toks->quick_push (obj: *first);
6818 tok = {};
6819 tok.type = CPP_PRAGMA_EOL;
6820 tok.keyword = RID_MAX;
6821 tok.location = last[-1].location;
6822 toks->quick_push (obj: tok);
6823 }
6824
6825 c_token tok = {};
6826 tok.type = CPP_EOF;
6827 tok.keyword = RID_MAX;
6828 tok.location = toks->last ().location;
6829 tok.flags = tokens_avail;
6830 toks->quick_push (obj: tok);
6831
6832 parser->tokens = toks->address ();
6833 parser->tokens_avail = tokens;
6834 parser->in_omp_attribute_pragma = toks;
6835 return true;
6836}
6837
6838/* Handle omp::directive and omp::sequence attributes in ATTRS
6839 (if any) at the start or after declaration-id of a declaration. */
6840
6841static void
6842c_parser_handle_directive_omp_attributes (tree &attrs,
6843 vec<c_token> *&pragma_clauses,
6844 vec<c_token> *attr_clauses)
6845{
6846 if (!flag_openmp && !flag_openmp_simd)
6847 return;
6848
6849 for (tree *pa = &attrs; *pa; )
6850 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6851 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
6852 {
6853 int cnt = 0;
6854 for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
6855 {
6856 tree a = *pa2;
6857 tree d = TREE_VALUE (a);
6858 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
6859 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
6860 c_token *first = toks->address ();
6861 c_token *last = first + toks->length ();
6862 const char *directive[3] = {};
6863 for (int i = 0; i < 3; i++)
6864 {
6865 tree id = NULL_TREE;
6866 if (first + i == last)
6867 break;
6868 if (first[i].type == CPP_NAME)
6869 id = first[i].value;
6870 else if (first[i].type == CPP_KEYWORD)
6871 id = ridpointers[(int) first[i].keyword];
6872 else
6873 break;
6874 directive[i] = IDENTIFIER_POINTER (id);
6875 }
6876 const c_omp_directive *dir = NULL;
6877 if (directive[0])
6878 dir = c_omp_categorize_directive (directive[0], directive[1],
6879 directive[2]);
6880 if (dir == NULL)
6881 {
6882 error_at (first->location,
6883 "unknown OpenMP directive name in "
6884 "%qs attribute argument",
6885 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
6886 *pa2 = TREE_CHAIN (a);
6887 }
6888 else if (dir->id == PRAGMA_OMP_DECLARE
6889 && (strcmp (s1: directive[1], s2: "simd") == 0
6890 || strcmp (s1: directive[1], s2: "variant") == 0))
6891 {
6892 if (pragma_clauses)
6893 {
6894 error_at (first->location,
6895 "mixing OpenMP directives with attribute and "
6896 "pragma syntax on the same declaration");
6897 for (pa = &attrs; *pa; )
6898 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
6899 && is_attribute_p (attr_name: "directive",
6900 ident: get_attribute_name (*pa)))
6901 *pa = TREE_CHAIN (*pa);
6902 else
6903 pa = &TREE_CHAIN (*pa);
6904 return;
6905 }
6906 ++cnt;
6907 attr_clauses->reserve (nelems: attr_clauses->length ()
6908 + toks->length () + 2);
6909 for (++first; first < last; ++first)
6910 attr_clauses->quick_push (obj: *first);
6911 c_token tok = {};
6912 tok.type = CPP_PRAGMA_EOL;
6913 tok.keyword = RID_MAX;
6914 tok.location = last[-1].location;
6915 attr_clauses->quick_push (obj: tok);
6916 *pa2 = TREE_CHAIN (a);
6917 }
6918 else
6919 pa2 = &TREE_CHAIN (a);
6920 }
6921 if (cnt && TREE_VALUE (*pa) == NULL_TREE)
6922 *pa = TREE_CHAIN (*pa);
6923 else
6924 pa = &TREE_CHAIN (*pa);
6925 }
6926 else
6927 pa = &TREE_CHAIN (*pa);
6928 if (attr_clauses->length ())
6929 {
6930 c_token tok = {};
6931 tok.type = CPP_EOF;
6932 tok.keyword = RID_MAX;
6933 tok.location = attr_clauses->last ().location;
6934 attr_clauses->quick_push (obj: tok);
6935 attr_clauses->quick_push (obj: tok);
6936 pragma_clauses = attr_clauses;
6937 }
6938}
6939
6940/* Parse a compound statement except for the opening brace. This is
6941 used for parsing both compound statements and statement expressions
6942 (which follow different paths to handling the opening). */
6943
6944static location_t
6945c_parser_compound_statement_nostart (c_parser *parser)
6946{
6947 bool last_stmt = false;
6948 bool last_label = false;
6949 bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
6950 location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6951 struct omp_for_parse_data *omp_for_parse_state
6952 = parser->omp_for_parse_state;
6953 bool in_omp_loop_block
6954 = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
6955 tree sl = NULL_TREE;
6956
6957 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6958 {
6959 location_t endloc = c_parser_peek_token (parser)->location;
6960 add_debug_begin_stmt (loc: endloc);
6961 c_parser_consume_token (parser);
6962 return endloc;
6963 }
6964
6965 /* If we're parsing a {} sequence in an OMP_FOR body, start a
6966 statement list for intervening code. */
6967 if (in_omp_loop_block)
6968 sl = push_stmt_list ();
6969
6970 mark_valid_location_for_stdc_pragma (true);
6971 if (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
6972 {
6973 /* Read zero or more forward-declarations for labels that nested
6974 functions can jump to. */
6975 mark_valid_location_for_stdc_pragma (false);
6976 if (in_omp_loop_block)
6977 check_omp_intervening_code (parser);
6978 while (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
6979 {
6980 label_loc = c_parser_peek_token (parser)->location;
6981 c_parser_consume_token (parser);
6982 /* Any identifiers, including those declared as type names,
6983 are OK here. */
6984 while (true)
6985 {
6986 tree label;
6987 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
6988 {
6989 c_parser_error (parser, gmsgid: "expected identifier");
6990 break;
6991 }
6992 label
6993 = declare_label (c_parser_peek_token (parser)->value);
6994 C_DECLARED_LABEL_FLAG (label) = 1;
6995 add_stmt (build_stmt (label_loc, DECL_EXPR, label));
6996 c_parser_consume_token (parser);
6997 if (c_parser_next_token_is (parser, type: CPP_COMMA))
6998 c_parser_consume_token (parser);
6999 else
7000 break;
7001 }
7002 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7003 }
7004 pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7005 }
7006 /* We must now have at least one statement, label or declaration. */
7007 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7008 {
7009 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7010 c_parser_error (parser, gmsgid: "expected declaration or statement");
7011 location_t endloc = c_parser_peek_token (parser)->location;
7012 c_parser_consume_token (parser);
7013 return endloc;
7014 }
7015 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_BRACE))
7016 {
7017 location_t loc = c_parser_peek_token (parser)->location;
7018 loc = expansion_point_location_if_in_system_header (loc);
7019
7020 bool want_nested_loop = (omp_for_parse_state
7021 ? omp_for_parse_state->want_nested_loop
7022 : false);
7023
7024 /* First take care of special cases for OpenMP "canonical loop
7025 nest form", that do not allow standard attributes, labels, or
7026 __extension__ before the nested statement. */
7027 if (in_omp_loop_block && !last_label)
7028 {
7029 if (want_nested_loop
7030 && c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
7031 {
7032 /* Found the next nested loop. If there were intervening
7033 code statements collected before now, wrap them in an
7034 OMP_STRUCTURED_BLOCK node, and start a new structured
7035 block to hold statements that may come after the FOR. */
7036 gcc_assert (sl);
7037 add_structured_block_stmt (sl: pop_stmt_list (sl));
7038 omp_for_parse_state->depth++;
7039 add_stmt (c_parser_omp_loop_nest (parser, NULL));
7040 omp_for_parse_state->depth--;
7041 sl = push_stmt_list ();
7042 parser->error = false;
7043 continue;
7044 }
7045 else if (want_nested_loop
7046 && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7047 {
7048 /* If this nested compound statement contains the nested loop,
7049 we need to separate the other statements in the current
7050 statement into separate blocks of intervening code. If
7051 there's no nested loop, it's all part of the same
7052 chunk of intervening code. */
7053 tree pre_sl = pop_stmt_list (sl);
7054 tree nested_sl = push_stmt_list ();
7055 mark_valid_location_for_stdc_pragma (false);
7056 c_parser_statement_after_labels (parser, NULL);
7057 nested_sl = pop_stmt_list (nested_sl);
7058 if (omp_for_parse_state->want_nested_loop)
7059 {
7060 /* This block didn't contain a loop-nest, so it's
7061 all part of the same chunk of intervening code. */
7062 check_omp_intervening_code (parser);
7063 sl = push_stmt_list ();
7064 add_stmt (pre_sl);
7065 add_stmt (nested_sl);
7066 }
7067 else
7068 {
7069 /* It contains the nested loop. */
7070 add_structured_block_stmt (sl: pre_sl);
7071 add_stmt (nested_sl);
7072 sl = push_stmt_list ();
7073 }
7074 parser->error = false;
7075 continue;
7076 }
7077 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7078 {
7079 /* Prior to implementing the OpenMP 5.1 syntax for canonical
7080 loop form, GCC used to accept an empty statements that
7081 would now be flagged as intervening code. Continue to
7082 do that, as an extension. */
7083 /* FIXME: Maybe issue a warning or something here? */
7084 c_parser_consume_token (parser);
7085 continue;
7086 }
7087 }
7088
7089 /* Standard attributes may start a label, statement or declaration. */
7090 bool have_std_attrs
7091 = c_parser_nth_token_starts_std_attributes (parser, n: 1);
7092 tree std_attrs = NULL_TREE;
7093 if (have_std_attrs)
7094 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7095 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7096 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7097 || (c_parser_next_token_is (parser, type: CPP_NAME)
7098 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7099 {
7100 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7101 label_loc = c_parser_peek_2nd_token (parser)->location;
7102 else
7103 label_loc = c_parser_peek_token (parser)->location;
7104 last_label = true;
7105 last_stmt = false;
7106 mark_valid_location_for_stdc_pragma (false);
7107 if (in_omp_loop_block)
7108 check_omp_intervening_code (parser);
7109 c_parser_label (parser, std_attrs);
7110 }
7111 else if (c_parser_next_tokens_start_declaration (parser)
7112 || (have_std_attrs
7113 && !c_parser_handle_statement_omp_attributes
7114 (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7115 && c_parser_next_token_is (parser, type: CPP_SEMICOLON)
7116 && (have_std_attrs = true)))
7117 {
7118 if (last_label)
7119 pedwarn_c11 (c_parser_peek_token (parser)->location, opt: OPT_Wpedantic,
7120 "a label can only be part of a statement and "
7121 "a declaration is not a statement");
7122 /* It's unlikely we'll see a nested loop in a declaration in
7123 intervening code in an OMP loop, but disallow it anyway. */
7124 if (in_omp_loop_block)
7125 {
7126 check_omp_intervening_code (parser);
7127 omp_for_parse_state->want_nested_loop = false;
7128 }
7129 mark_valid_location_for_stdc_pragma (false);
7130 bool fallthru_attr_p = false;
7131 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: !have_std_attrs,
7132 empty_ok: true, nested: true, start_attr_ok: true, NULL,
7133 NULL, have_attrs: have_std_attrs, attrs: std_attrs,
7134 NULL, fallthru_attr_p: &fallthru_attr_p);
7135
7136 if (in_omp_loop_block)
7137 omp_for_parse_state->want_nested_loop = want_nested_loop;
7138 if (last_stmt && !fallthru_attr_p)
7139 pedwarn_c90 (loc, opt: OPT_Wdeclaration_after_statement,
7140 "ISO C90 forbids mixed declarations and code");
7141 last_stmt = fallthru_attr_p;
7142 last_label = false;
7143 }
7144 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
7145 {
7146 /* __extension__ can start a declaration, but is also an
7147 unary operator that can start an expression. Consume all
7148 but the last of a possible series of __extension__ to
7149 determine which. If standard attributes have already
7150 been seen, it must start a statement, not a declaration,
7151 but standard attributes starting a declaration may appear
7152 after __extension__. */
7153 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7154 && (c_parser_peek_2nd_token (parser)->keyword
7155 == RID_EXTENSION))
7156 c_parser_consume_token (parser);
7157 if (!have_std_attrs
7158 && (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
7159 || c_parser_nth_token_starts_std_attributes (parser, n: 2)))
7160 {
7161 int ext;
7162 ext = disable_extension_diagnostics ();
7163 c_parser_consume_token (parser);
7164 last_label = false;
7165 /* It's unlikely we'll see a nested loop in a declaration in
7166 intervening code in an OMP loop, but disallow it anyway. */
7167 if (in_omp_loop_block)
7168 {
7169 check_omp_intervening_code (parser);
7170 omp_for_parse_state->want_nested_loop = false;
7171 }
7172 mark_valid_location_for_stdc_pragma (false);
7173 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
7174 start_attr_ok: true);
7175 if (in_omp_loop_block)
7176 omp_for_parse_state->want_nested_loop = want_nested_loop;
7177 /* Following the old parser, __extension__ does not
7178 disable this diagnostic. */
7179 restore_extension_diagnostics (flags: ext);
7180 if (last_stmt)
7181 pedwarn_c90 (loc, opt: OPT_Wdeclaration_after_statement,
7182 "ISO C90 forbids mixed declarations and code");
7183 last_stmt = false;
7184 }
7185 else
7186 goto statement;
7187 }
7188 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
7189 {
7190 if (have_std_attrs && !parser->in_omp_attribute_pragma)
7191 c_parser_error (parser, gmsgid: "expected declaration or statement");
7192 else if (std_attrs)
7193 c_warn_unused_attributes (std_attrs);
7194 /* External pragmas, and some omp pragmas, are not associated
7195 with regular c code, and so are not to be considered statements
7196 syntactically. This ensures that the user doesn't put them
7197 places that would turn into syntax errors if the directive
7198 were ignored. */
7199 if (omp_for_parse_state)
7200 omp_for_parse_state->want_nested_loop = false;
7201 if (c_parser_pragma (parser,
7202 last_label ? pragma_stmt : pragma_compound,
7203 NULL))
7204 {
7205 last_label = false;
7206 last_stmt = true;
7207 if (omp_for_parse_state)
7208 check_omp_intervening_code (parser);
7209 }
7210 if (omp_for_parse_state)
7211 omp_for_parse_state->want_nested_loop = want_nested_loop;
7212 }
7213 else if (c_parser_next_token_is (parser, type: CPP_EOF))
7214 {
7215 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7216 c_parser_error (parser, gmsgid: "expected declaration or statement");
7217 return c_parser_peek_token (parser)->location;
7218 }
7219 else if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7220 {
7221 if (parser->in_if_block)
7222 {
7223 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7224 error_at (loc, "expected %<}%> before %<else%>");
7225 return c_parser_peek_token (parser)->location;
7226 }
7227 else
7228 {
7229 error_at (loc, "%<else%> without a previous %<if%>");
7230 c_parser_consume_token (parser);
7231 continue;
7232 }
7233 }
7234 else
7235 {
7236 statement:
7237 c_warn_unused_attributes (std_attrs);
7238 last_label = false;
7239 last_stmt = true;
7240 mark_valid_location_for_stdc_pragma (false);
7241 if (!omp_for_parse_state)
7242 c_parser_statement_after_labels (parser, NULL);
7243 else
7244 {
7245 /* In canonical loop nest form, nested loops can only appear
7246 directly, or in a directly nested compound statement. We
7247 already took care of those cases above, so now we have
7248 something else. This statement and everything inside
7249 it must be intervening code. */
7250 omp_for_parse_state->want_nested_loop = false;
7251 check_omp_intervening_code (parser);
7252 c_parser_statement_after_labels (parser, NULL);
7253 omp_for_parse_state->want_nested_loop = want_nested_loop;
7254 }
7255 }
7256
7257 parser->error = false;
7258 }
7259 if (last_label)
7260 pedwarn_c11 (label_loc, opt: OPT_Wpedantic, "label at end of compound statement");
7261 location_t endloc = c_parser_peek_token (parser)->location;
7262 c_parser_consume_token (parser);
7263
7264 /* Restore the value we started with. */
7265 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7266
7267 /* Package leftover intervening code, or the whole contents of the
7268 compound statement if we were looking for a nested loop in an OMP_FOR
7269 construct and didn't find one. */
7270 if (sl)
7271 {
7272 sl = pop_stmt_list (sl);
7273 if (omp_for_parse_state->want_nested_loop)
7274 add_stmt (sl);
7275 else
7276 add_structured_block_stmt (sl);
7277 }
7278 return endloc;
7279}
7280
7281/* Parse all consecutive labels, possibly preceded by standard
7282 attributes. In this context, a statement is required, not a
7283 declaration, so attributes must be followed by a statement that is
7284 not just a semicolon. */
7285
7286static void
7287c_parser_all_labels (c_parser *parser)
7288{
7289 bool have_std_attrs;
7290 tree std_attrs = NULL;
7291 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1)))
7292 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7293 while (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7294 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7295 || (c_parser_next_token_is (parser, type: CPP_NAME)
7296 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7297 {
7298 c_parser_label (parser, std_attrs);
7299 std_attrs = NULL;
7300 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
7301 n: 1)))
7302 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7303 }
7304 if (std_attrs
7305 && (!c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7306 || std_attrs))
7307 {
7308 if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7309 c_parser_error (parser, gmsgid: "expected statement");
7310 c_warn_unused_attributes (std_attrs);
7311 }
7312 else if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7313 c_parser_error (parser, gmsgid: "expected statement");
7314}
7315
7316/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
7317
7318 label:
7319 identifier : gnu-attributes[opt]
7320 case constant-expression :
7321 default :
7322
7323 GNU extensions:
7324
7325 label:
7326 case constant-expression ... constant-expression :
7327
7328 The use of gnu-attributes on labels is a GNU extension. The syntax in
7329 GNU C accepts any expressions without commas, non-constant
7330 expressions being rejected later. Any standard
7331 attribute-specifier-sequence before the first label has been parsed
7332 in the caller, to distinguish statements from declarations. Any
7333 attribute-specifier-sequence after the label is parsed in this
7334 function. */
7335static void
7336c_parser_label (c_parser *parser, tree std_attrs)
7337{
7338 location_t loc1 = c_parser_peek_token (parser)->location;
7339 tree label = NULL_TREE;
7340
7341 /* Remember whether this case or a user-defined label is allowed to fall
7342 through to. */
7343 bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
7344
7345 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7346 {
7347 tree exp1, exp2;
7348 c_parser_consume_token (parser);
7349 exp1 = convert_lvalue_to_rvalue (loc1,
7350 c_parser_expr_no_commas (parser, NULL),
7351 true, true).value;
7352 if (c_parser_next_token_is (parser, type: CPP_COLON))
7353 {
7354 c_parser_consume_token (parser);
7355 label = do_case (loc1, exp1, NULL_TREE, std_attrs);
7356 }
7357 else if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
7358 {
7359 c_parser_consume_token (parser);
7360 exp2 = convert_lvalue_to_rvalue (loc1,
7361 c_parser_expr_no_commas (parser,
7362 NULL),
7363 true, true).value;
7364 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7365 label = do_case (loc1, exp1, exp2, std_attrs);
7366 }
7367 else
7368 c_parser_error (parser, gmsgid: "expected %<:%> or %<...%>");
7369 }
7370 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
7371 {
7372 c_parser_consume_token (parser);
7373 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7374 label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
7375 }
7376 else
7377 {
7378 tree name = c_parser_peek_token (parser)->value;
7379 tree tlab;
7380 tree attrs;
7381 location_t loc2 = c_parser_peek_token (parser)->location;
7382 gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
7383 c_parser_consume_token (parser);
7384 gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
7385 c_parser_consume_token (parser);
7386 attrs = c_parser_gnu_attributes (parser);
7387 tlab = define_label (loc2, name);
7388 if (tlab)
7389 {
7390 decl_attributes (&tlab, attrs, 0);
7391 decl_attributes (&tlab, std_attrs, 0);
7392 label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
7393 }
7394 if (attrs
7395 && c_parser_next_tokens_start_declaration (parser))
7396 warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
7397 " label and declaration appertains to the label");
7398 }
7399 if (label)
7400 {
7401 if (TREE_CODE (label) == LABEL_EXPR)
7402 FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
7403 else
7404 FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
7405 }
7406}
7407
7408/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
7409
7410 statement:
7411 labeled-statement
7412 attribute-specifier-sequence[opt] compound-statement
7413 expression-statement
7414 attribute-specifier-sequence[opt] selection-statement
7415 attribute-specifier-sequence[opt] iteration-statement
7416 attribute-specifier-sequence[opt] jump-statement
7417
7418 labeled-statement:
7419 attribute-specifier-sequence[opt] label statement
7420
7421 expression-statement:
7422 expression[opt] ;
7423 attribute-specifier-sequence expression ;
7424
7425 selection-statement:
7426 if-statement
7427 switch-statement
7428
7429 iteration-statement:
7430 while-statement
7431 do-statement
7432 for-statement
7433
7434 jump-statement:
7435 goto identifier ;
7436 continue ;
7437 break ;
7438 return expression[opt] ;
7439
7440 GNU extensions:
7441
7442 statement:
7443 attribute-specifier-sequence[opt] asm-statement
7444
7445 jump-statement:
7446 goto * expression ;
7447
7448 expression-statement:
7449 gnu-attributes ;
7450
7451 Objective-C:
7452
7453 statement:
7454 attribute-specifier-sequence[opt] objc-throw-statement
7455 attribute-specifier-sequence[opt] objc-try-catch-statement
7456 attribute-specifier-sequence[opt] objc-synchronized-statement
7457
7458 objc-throw-statement:
7459 @throw expression ;
7460 @throw ;
7461
7462 OpenACC:
7463
7464 statement:
7465 attribute-specifier-sequence[opt] openacc-construct
7466
7467 openacc-construct:
7468 parallel-construct
7469 kernels-construct
7470 data-construct
7471 loop-construct
7472
7473 parallel-construct:
7474 parallel-directive structured-block
7475
7476 kernels-construct:
7477 kernels-directive structured-block
7478
7479 data-construct:
7480 data-directive structured-block
7481
7482 loop-construct:
7483 loop-directive structured-block
7484
7485 OpenMP:
7486
7487 statement:
7488 attribute-specifier-sequence[opt] openmp-construct
7489
7490 openmp-construct:
7491 parallel-construct
7492 for-construct
7493 simd-construct
7494 for-simd-construct
7495 sections-construct
7496 single-construct
7497 parallel-for-construct
7498 parallel-for-simd-construct
7499 parallel-sections-construct
7500 master-construct
7501 critical-construct
7502 atomic-construct
7503 ordered-construct
7504
7505 parallel-construct:
7506 parallel-directive structured-block
7507
7508 for-construct:
7509 for-directive iteration-statement
7510
7511 simd-construct:
7512 simd-directive iteration-statements
7513
7514 for-simd-construct:
7515 for-simd-directive iteration-statements
7516
7517 sections-construct:
7518 sections-directive section-scope
7519
7520 single-construct:
7521 single-directive structured-block
7522
7523 parallel-for-construct:
7524 parallel-for-directive iteration-statement
7525
7526 parallel-for-simd-construct:
7527 parallel-for-simd-directive iteration-statement
7528
7529 parallel-sections-construct:
7530 parallel-sections-directive section-scope
7531
7532 master-construct:
7533 master-directive structured-block
7534
7535 critical-construct:
7536 critical-directive structured-block
7537
7538 atomic-construct:
7539 atomic-directive expression-statement
7540
7541 ordered-construct:
7542 ordered-directive structured-block
7543
7544 Transactional Memory:
7545
7546 statement:
7547 attribute-specifier-sequence[opt] transaction-statement
7548 attribute-specifier-sequence[opt] transaction-cancel-statement
7549
7550 IF_P is used to track whether there's a (possibly labeled) if statement
7551 which is not enclosed in braces and has an else clause. This is used to
7552 implement -Wparentheses. */
7553
7554static void
7555c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
7556{
7557 c_parser_all_labels (parser);
7558 if (loc_after_labels)
7559 *loc_after_labels = c_parser_peek_token (parser)->location;
7560 parser->omp_attrs_forbidden_p = false;
7561 c_parser_statement_after_labels (parser, if_p, NULL);
7562}
7563
7564/* Parse a statement, other than a labeled statement. CHAIN is a vector
7565 of if-else-if conditions. All labels and standard attributes have
7566 been parsed in the caller.
7567
7568 IF_P is used to track whether there's a (possibly labeled) if statement
7569 which is not enclosed in braces and has an else clause. This is used to
7570 implement -Wparentheses. */
7571
7572static void
7573c_parser_statement_after_labels (c_parser *parser, bool *if_p,
7574 vec<tree> *chain)
7575{
7576 location_t loc = c_parser_peek_token (parser)->location;
7577 tree stmt = NULL_TREE;
7578 bool in_if_block = parser->in_if_block;
7579 parser->in_if_block = false;
7580 if (if_p != NULL)
7581 *if_p = false;
7582
7583 if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
7584 add_debug_begin_stmt (loc);
7585
7586 restart:
7587 switch (c_parser_peek_token (parser)->type)
7588 {
7589 case CPP_OPEN_BRACE:
7590 add_stmt (c_parser_compound_statement (parser));
7591 break;
7592 case CPP_KEYWORD:
7593 switch (c_parser_peek_token (parser)->keyword)
7594 {
7595 case RID_IF:
7596 c_parser_if_statement (parser, if_p, chain);
7597 break;
7598 case RID_SWITCH:
7599 c_parser_switch_statement (parser, if_p);
7600 break;
7601 case RID_WHILE:
7602 c_parser_while_statement (parser, false, 0, false, if_p);
7603 break;
7604 case RID_DO:
7605 c_parser_do_statement (parser, false, 0, false);
7606 break;
7607 case RID_FOR:
7608 c_parser_for_statement (parser, false, 0, false, if_p);
7609 break;
7610 case RID_GOTO:
7611 c_parser_consume_token (parser);
7612 if (c_parser_next_token_is (parser, type: CPP_NAME))
7613 {
7614 stmt = c_finish_goto_label (loc,
7615 c_parser_peek_token (parser)->value);
7616 c_parser_consume_token (parser);
7617 }
7618 else if (c_parser_next_token_is (parser, type: CPP_MULT))
7619 {
7620 struct c_expr val;
7621
7622 c_parser_consume_token (parser);
7623 val = c_parser_expression (parser);
7624 val = convert_lvalue_to_rvalue (loc, val, false, true);
7625 stmt = c_finish_goto_ptr (loc, val);
7626 }
7627 else
7628 c_parser_error (parser, gmsgid: "expected identifier or %<*%>");
7629 goto expect_semicolon;
7630 case RID_CONTINUE:
7631 c_parser_consume_token (parser);
7632 stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false);
7633 goto expect_semicolon;
7634 case RID_BREAK:
7635 c_parser_consume_token (parser);
7636 stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true);
7637 goto expect_semicolon;
7638 case RID_RETURN:
7639 c_parser_consume_token (parser);
7640 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7641 {
7642 stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
7643 c_parser_consume_token (parser);
7644 }
7645 else
7646 {
7647 location_t xloc = c_parser_peek_token (parser)->location;
7648 struct c_expr expr = c_parser_expression_conv (parser);
7649 mark_exp_read (expr.value);
7650 stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
7651 expr.value, expr.original_type);
7652 goto expect_semicolon;
7653 }
7654 break;
7655 case RID_ASM:
7656 stmt = c_parser_asm_statement (parser);
7657 break;
7658 case RID_TRANSACTION_ATOMIC:
7659 case RID_TRANSACTION_RELAXED:
7660 stmt = c_parser_transaction (parser,
7661 c_parser_peek_token (parser)->keyword);
7662 break;
7663 case RID_TRANSACTION_CANCEL:
7664 stmt = c_parser_transaction_cancel (parser);
7665 goto expect_semicolon;
7666 case RID_AT_THROW:
7667 gcc_assert (c_dialect_objc ());
7668 c_parser_consume_token (parser);
7669 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7670 {
7671 stmt = objc_build_throw_stmt (loc, NULL_TREE);
7672 c_parser_consume_token (parser);
7673 }
7674 else
7675 {
7676 struct c_expr expr = c_parser_expression (parser);
7677 expr = convert_lvalue_to_rvalue (loc, expr, false, false);
7678 expr.value = c_fully_fold (expr.value, false, NULL);
7679 stmt = objc_build_throw_stmt (loc, expr.value);
7680 goto expect_semicolon;
7681 }
7682 break;
7683 case RID_AT_TRY:
7684 gcc_assert (c_dialect_objc ());
7685 c_parser_objc_try_catch_finally_statement (parser);
7686 break;
7687 case RID_AT_SYNCHRONIZED:
7688 gcc_assert (c_dialect_objc ());
7689 c_parser_objc_synchronized_statement (parser);
7690 break;
7691 case RID_ATTRIBUTE:
7692 {
7693 /* Allow '__attribute__((fallthrough));' or
7694 '__attribute__((assume(cond)));'. */
7695 tree attrs = c_parser_gnu_attributes (parser);
7696 bool has_assume = lookup_attribute (attr_name: "assume", list: attrs);
7697 if (has_assume)
7698 {
7699 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7700 attrs = handle_assume_attribute (here: loc, attrs, nested: true);
7701 else
7702 {
7703 warning_at (loc, OPT_Wattributes,
7704 "%<assume%> attribute not followed by %<;%>");
7705 has_assume = false;
7706 }
7707 }
7708 if (attribute_fallthrough_p (attrs))
7709 {
7710 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7711 {
7712 tree fn = build_call_expr_internal_loc (loc,
7713 IFN_FALLTHROUGH,
7714 void_type_node, 0);
7715 add_stmt (fn);
7716 /* Eat the ';'. */
7717 c_parser_consume_token (parser);
7718 }
7719 else
7720 warning_at (loc, OPT_Wattributes,
7721 "%<fallthrough%> attribute not followed "
7722 "by %<;%>");
7723 }
7724 else if (has_assume)
7725 /* Eat the ';'. */
7726 c_parser_consume_token (parser);
7727 else if (attrs != NULL_TREE)
7728 warning_at (loc, OPT_Wattributes,
7729 "only attribute %<fallthrough%> or %<assume%> can "
7730 "be applied to a null statement");
7731 break;
7732 }
7733 default:
7734 goto expr_stmt;
7735 }
7736 break;
7737 case CPP_SEMICOLON:
7738 c_parser_consume_token (parser);
7739 break;
7740 case CPP_CLOSE_PAREN:
7741 case CPP_CLOSE_SQUARE:
7742 /* Avoid infinite loop in error recovery:
7743 c_parser_skip_until_found stops at a closing nesting
7744 delimiter without consuming it, but here we need to consume
7745 it to proceed further. */
7746 c_parser_error (parser, gmsgid: "expected statement");
7747 c_parser_consume_token (parser);
7748 break;
7749 case CPP_PRAGMA:
7750 if (!c_parser_pragma (parser, pragma_stmt, if_p))
7751 goto restart;
7752 break;
7753 default:
7754 expr_stmt:
7755 stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
7756 expect_semicolon:
7757 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7758 break;
7759 }
7760 /* Two cases cannot and do not have line numbers associated: If stmt
7761 is degenerate, such as "2;", then stmt is an INTEGER_CST, which
7762 cannot hold line numbers. But that's OK because the statement
7763 will either be changed to a MODIFY_EXPR during gimplification of
7764 the statement expr, or discarded. If stmt was compound, but
7765 without new variables, we will have skipped the creation of a
7766 BIND and will have a bare STATEMENT_LIST. But that's OK because
7767 (recursively) all of the component statements should already have
7768 line numbers assigned. ??? Can we discard no-op statements
7769 earlier? */
7770 if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
7771 protected_set_expr_location (stmt, loc);
7772
7773 parser->in_if_block = in_if_block;
7774}
7775
7776/* Parse the condition from an if, do, while or for statements. */
7777
7778static tree
7779c_parser_condition (c_parser *parser)
7780{
7781 location_t loc = c_parser_peek_token (parser)->location;
7782 tree cond;
7783 cond = c_parser_expression_conv (parser).value;
7784 cond = c_objc_common_truthvalue_conversion (loc, cond);
7785 cond = c_fully_fold (cond, false, NULL);
7786 if (warn_sequence_point)
7787 verify_sequence_points (cond);
7788 return cond;
7789}
7790
7791/* Parse a parenthesized condition from an if, do or while statement.
7792
7793 condition:
7794 ( expression )
7795*/
7796static tree
7797c_parser_paren_condition (c_parser *parser)
7798{
7799 tree cond;
7800 matching_parens parens;
7801 if (!parens.require_open (parser))
7802 return error_mark_node;
7803 cond = c_parser_condition (parser);
7804 parens.skip_until_found_close (parser);
7805 return cond;
7806}
7807
7808/* Parse a statement which is a block in C99.
7809
7810 IF_P is used to track whether there's a (possibly labeled) if statement
7811 which is not enclosed in braces and has an else clause. This is used to
7812 implement -Wparentheses. */
7813
7814static tree
7815c_parser_c99_block_statement (c_parser *parser, bool *if_p,
7816 location_t *loc_after_labels)
7817{
7818 tree block = c_begin_compound_stmt (flag_isoc99);
7819 location_t loc = c_parser_peek_token (parser)->location;
7820 c_parser_statement (parser, if_p, loc_after_labels);
7821 return c_end_compound_stmt (loc, block, flag_isoc99);
7822}
7823
7824/* Parse the body of an if statement. This is just parsing a
7825 statement but (a) it is a block in C99, (b) we track whether the
7826 body is an if statement for the sake of -Wparentheses warnings, (c)
7827 we handle an empty body specially for the sake of -Wempty-body
7828 warnings, and (d) we call parser_compound_statement directly
7829 because c_parser_statement_after_labels resets
7830 parser->in_if_block.
7831
7832 IF_P is used to track whether there's a (possibly labeled) if statement
7833 which is not enclosed in braces and has an else clause. This is used to
7834 implement -Wparentheses. */
7835
7836static tree
7837c_parser_if_body (c_parser *parser, bool *if_p,
7838 const token_indent_info &if_tinfo)
7839{
7840 tree block = c_begin_compound_stmt (flag_isoc99);
7841 location_t body_loc = c_parser_peek_token (parser)->location;
7842 location_t body_loc_after_labels = UNKNOWN_LOCATION;
7843 token_indent_info body_tinfo
7844 = get_token_indent_info (token: c_parser_peek_token (parser));
7845
7846 c_parser_all_labels (parser);
7847 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7848 {
7849 location_t loc = c_parser_peek_token (parser)->location;
7850 add_stmt (build_empty_stmt (loc));
7851 c_parser_consume_token (parser);
7852 if (!c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7853 warning_at (loc, OPT_Wempty_body,
7854 "suggest braces around empty body in an %<if%> statement");
7855 }
7856 else if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7857 add_stmt (c_parser_compound_statement (parser));
7858 else
7859 {
7860 body_loc_after_labels = c_parser_peek_token (parser)->location;
7861 c_parser_statement_after_labels (parser, if_p);
7862 }
7863
7864 token_indent_info next_tinfo
7865 = get_token_indent_info (token: c_parser_peek_token (parser));
7866 warn_for_misleading_indentation (guard_tinfo: if_tinfo, body_tinfo, next_tinfo);
7867 if (body_loc_after_labels != UNKNOWN_LOCATION
7868 && next_tinfo.type != CPP_SEMICOLON)
7869 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
7870 if_tinfo.location, RID_IF);
7871
7872 return c_end_compound_stmt (body_loc, block, flag_isoc99);
7873}
7874
7875/* Parse the else body of an if statement. This is just parsing a
7876 statement but (a) it is a block in C99, (b) we handle an empty body
7877 specially for the sake of -Wempty-body warnings. CHAIN is a vector
7878 of if-else-if conditions. */
7879
7880static tree
7881c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
7882 vec<tree> *chain)
7883{
7884 location_t body_loc = c_parser_peek_token (parser)->location;
7885 tree block = c_begin_compound_stmt (flag_isoc99);
7886 token_indent_info body_tinfo
7887 = get_token_indent_info (token: c_parser_peek_token (parser));
7888 location_t body_loc_after_labels = UNKNOWN_LOCATION;
7889
7890 c_parser_all_labels (parser);
7891 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7892 {
7893 location_t loc = c_parser_peek_token (parser)->location;
7894 warning_at (loc,
7895 OPT_Wempty_body,
7896 "suggest braces around empty body in an %<else%> statement");
7897 add_stmt (build_empty_stmt (loc));
7898 c_parser_consume_token (parser);
7899 }
7900 else
7901 {
7902 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7903 body_loc_after_labels = c_parser_peek_token (parser)->location;
7904 c_parser_statement_after_labels (parser, NULL, chain);
7905 }
7906
7907 token_indent_info next_tinfo
7908 = get_token_indent_info (token: c_parser_peek_token (parser));
7909 warn_for_misleading_indentation (guard_tinfo: else_tinfo, body_tinfo, next_tinfo);
7910 if (body_loc_after_labels != UNKNOWN_LOCATION
7911 && next_tinfo.type != CPP_SEMICOLON)
7912 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
7913 else_tinfo.location, RID_ELSE);
7914
7915 return c_end_compound_stmt (body_loc, block, flag_isoc99);
7916}
7917
7918/* We might need to reclassify any previously-lexed identifier, e.g.
7919 when we've left a for loop with an if-statement without else in the
7920 body - we might have used a wrong scope for the token. See PR67784. */
7921
7922static void
7923c_parser_maybe_reclassify_token (c_parser *parser)
7924{
7925 if (c_parser_next_token_is (parser, type: CPP_NAME))
7926 {
7927 c_token *token = c_parser_peek_token (parser);
7928
7929 if (token->id_kind != C_ID_CLASSNAME)
7930 {
7931 tree decl = lookup_name (token->value);
7932
7933 token->id_kind = C_ID_ID;
7934 if (decl)
7935 {
7936 if (TREE_CODE (decl) == TYPE_DECL)
7937 token->id_kind = C_ID_TYPENAME;
7938 }
7939 else if (c_dialect_objc ())
7940 {
7941 tree objc_interface_decl = objc_is_class_name (token->value);
7942 /* Objective-C class names are in the same namespace as
7943 variables and typedefs, and hence are shadowed by local
7944 declarations. */
7945 if (objc_interface_decl)
7946 {
7947 token->value = objc_interface_decl;
7948 token->id_kind = C_ID_CLASSNAME;
7949 }
7950 }
7951 }
7952 }
7953}
7954
7955/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
7956
7957 if-statement:
7958 if ( expression ) statement
7959 if ( expression ) statement else statement
7960
7961 CHAIN is a vector of if-else-if conditions.
7962 IF_P is used to track whether there's a (possibly labeled) if statement
7963 which is not enclosed in braces and has an else clause. This is used to
7964 implement -Wparentheses. */
7965
7966static void
7967c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
7968{
7969 tree block;
7970 location_t loc;
7971 tree cond;
7972 bool nested_if = false;
7973 tree first_body, second_body;
7974 bool in_if_block;
7975
7976 gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
7977 token_indent_info if_tinfo
7978 = get_token_indent_info (token: c_parser_peek_token (parser));
7979 c_parser_consume_token (parser);
7980 block = c_begin_compound_stmt (flag_isoc99);
7981 loc = c_parser_peek_token (parser)->location;
7982 cond = c_parser_paren_condition (parser);
7983 in_if_block = parser->in_if_block;
7984 parser->in_if_block = true;
7985 first_body = c_parser_if_body (parser, if_p: &nested_if, if_tinfo);
7986 parser->in_if_block = in_if_block;
7987
7988 if (warn_duplicated_cond)
7989 warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
7990
7991 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7992 {
7993 token_indent_info else_tinfo
7994 = get_token_indent_info (token: c_parser_peek_token (parser));
7995 c_parser_consume_token (parser);
7996 if (warn_duplicated_cond)
7997 {
7998 if (c_parser_next_token_is_keyword (parser, keyword: RID_IF)
7999 && chain == NULL)
8000 {
8001 /* We've got "if (COND) else if (COND2)". Start the
8002 condition chain and add COND as the first element. */
8003 chain = new vec<tree> ();
8004 if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8005 chain->safe_push (obj: cond);
8006 }
8007 else if (!c_parser_next_token_is_keyword (parser, keyword: RID_IF))
8008 /* This is if-else without subsequent if. Zap the condition
8009 chain; we would have already warned at this point. */
8010 vec_free (v&: chain);
8011 }
8012 second_body = c_parser_else_body (parser, else_tinfo, chain);
8013 /* Set IF_P to true to indicate that this if statement has an
8014 else clause. This may trigger the Wparentheses warning
8015 below when we get back up to the parent if statement. */
8016 if (if_p != NULL)
8017 *if_p = true;
8018 }
8019 else
8020 {
8021 second_body = NULL_TREE;
8022
8023 /* Diagnose an ambiguous else if if-then-else is nested inside
8024 if-then. */
8025 if (nested_if)
8026 warning_at (loc, OPT_Wdangling_else,
8027 "suggest explicit braces to avoid ambiguous %<else%>");
8028
8029 if (warn_duplicated_cond)
8030 /* This if statement does not have an else clause. We don't
8031 need the condition chain anymore. */
8032 vec_free (v&: chain);
8033 }
8034 c_finish_if_stmt (loc, cond, first_body, second_body);
8035 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8036
8037 c_parser_maybe_reclassify_token (parser);
8038}
8039
8040/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8041
8042 switch-statement:
8043 switch (expression) statement
8044*/
8045
8046static void
8047c_parser_switch_statement (c_parser *parser, bool *if_p)
8048{
8049 struct c_expr ce;
8050 tree block, expr, body;
8051 unsigned char save_in_statement;
8052 location_t switch_loc = c_parser_peek_token (parser)->location;
8053 location_t switch_cond_loc;
8054 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8055 c_parser_consume_token (parser);
8056 block = c_begin_compound_stmt (flag_isoc99);
8057 bool explicit_cast_p = false;
8058 matching_parens parens;
8059 if (parens.require_open (parser))
8060 {
8061 switch_cond_loc = c_parser_peek_token (parser)->location;
8062 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
8063 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
8064 explicit_cast_p = true;
8065 ce = c_parser_expression (parser);
8066 ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8067 expr = ce.value;
8068 /* ??? expr has no valid location? */
8069 parens.skip_until_found_close (parser);
8070 }
8071 else
8072 {
8073 switch_cond_loc = UNKNOWN_LOCATION;
8074 expr = error_mark_node;
8075 ce.original_type = error_mark_node;
8076 }
8077 c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p);
8078 save_in_statement = in_statement;
8079 in_statement |= IN_SWITCH_STMT;
8080 location_t loc_after_labels;
8081 bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8082 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8083 location_t next_loc = c_parser_peek_token (parser)->location;
8084 if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8085 warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8086 RID_SWITCH);
8087 c_finish_switch (body, ce.original_type);
8088 in_statement = save_in_statement;
8089 add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8090 c_parser_maybe_reclassify_token (parser);
8091}
8092
8093/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8094
8095 while-statement:
8096 while (expression) statement
8097
8098 IF_P is used to track whether there's a (possibly labeled) if statement
8099 which is not enclosed in braces and has an else clause. This is used to
8100 implement -Wparentheses. */
8101
8102static void
8103c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8104 bool novector, bool *if_p)
8105{
8106 tree block, cond, body;
8107 unsigned char save_in_statement;
8108 location_t loc;
8109 gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8110 token_indent_info while_tinfo
8111 = get_token_indent_info (token: c_parser_peek_token (parser));
8112
8113 if (parser->omp_for_parse_state)
8114 {
8115 error_at (c_parser_peek_token (parser)->location,
8116 "loop not permitted in intervening code in OpenMP loop body");
8117 parser->omp_for_parse_state->fail = true;
8118 }
8119
8120 c_parser_consume_token (parser);
8121 block = c_begin_compound_stmt (flag_isoc99);
8122 loc = c_parser_peek_token (parser)->location;
8123 cond = c_parser_paren_condition (parser);
8124 if (ivdep && cond != error_mark_node)
8125 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8126 build_int_cst (integer_type_node,
8127 annot_expr_ivdep_kind),
8128 integer_zero_node);
8129 if (unroll && cond != error_mark_node)
8130 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8131 build_int_cst (integer_type_node,
8132 annot_expr_unroll_kind),
8133 build_int_cst (integer_type_node, unroll));
8134 if (novector && cond != error_mark_node)
8135 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8136 build_int_cst (integer_type_node,
8137 annot_expr_no_vector_kind),
8138 integer_zero_node);
8139 save_in_statement = in_statement;
8140 in_statement = IN_ITERATION_STMT;
8141
8142 token_indent_info body_tinfo
8143 = get_token_indent_info (token: c_parser_peek_token (parser));
8144
8145 location_t loc_after_labels;
8146 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
8147 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8148 add_stmt (build_stmt (loc, WHILE_STMT, cond, body));
8149 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8150 c_parser_maybe_reclassify_token (parser);
8151
8152 token_indent_info next_tinfo
8153 = get_token_indent_info (token: c_parser_peek_token (parser));
8154 warn_for_misleading_indentation (guard_tinfo: while_tinfo, body_tinfo, next_tinfo);
8155
8156 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8157 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8158 while_tinfo.location, RID_WHILE);
8159
8160 in_statement = save_in_statement;
8161}
8162
8163/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8164
8165 do-statement:
8166 do statement while ( expression ) ;
8167*/
8168
8169static void
8170c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8171 bool novector)
8172{
8173 tree block, cond, body;
8174 unsigned char save_in_statement;
8175 location_t loc;
8176 gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
8177
8178 if (parser->omp_for_parse_state)
8179 {
8180 error_at (c_parser_peek_token (parser)->location,
8181 "loop not permitted in intervening code in OpenMP loop body");
8182 parser->omp_for_parse_state->fail = true;
8183 }
8184
8185 c_parser_consume_token (parser);
8186 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8187 warning_at (c_parser_peek_token (parser)->location,
8188 OPT_Wempty_body,
8189 "suggest braces around empty body in %<do%> statement");
8190 block = c_begin_compound_stmt (flag_isoc99);
8191 loc = c_parser_peek_token (parser)->location;
8192 save_in_statement = in_statement;
8193 in_statement = IN_ITERATION_STMT;
8194 body = c_parser_c99_block_statement (parser, NULL);
8195 c_parser_require_keyword (parser, keyword: RID_WHILE, msgid: "expected %<while%>");
8196 in_statement = save_in_statement;
8197 cond = c_parser_paren_condition (parser);
8198 if (ivdep && cond != error_mark_node)
8199 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8200 build_int_cst (integer_type_node,
8201 annot_expr_ivdep_kind),
8202 integer_zero_node);
8203 if (unroll && cond != error_mark_node)
8204 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8205 build_int_cst (integer_type_node,
8206 annot_expr_unroll_kind),
8207 build_int_cst (integer_type_node, unroll));
8208 if (novector && cond != error_mark_node)
8209 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8210 build_int_cst (integer_type_node,
8211 annot_expr_no_vector_kind),
8212 integer_zero_node);
8213 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
8214 c_parser_skip_to_end_of_block_or_statement (parser);
8215
8216 add_stmt (build_stmt (loc, DO_STMT, cond, body));
8217 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8218}
8219
8220/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8221
8222 for-statement:
8223 for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
8224 for ( nested-declaration expression[opt] ; expression[opt] ) statement
8225
8226 The form with a declaration is new in C99.
8227
8228 ??? In accordance with the old parser, the declaration may be a
8229 nested function, which is then rejected in check_for_loop_decls,
8230 but does it make any sense for this to be included in the grammar?
8231 Note in particular that the nested function does not include a
8232 trailing ';', whereas the "declaration" production includes one.
8233 Also, can we reject bad declarations earlier and cheaper than
8234 check_for_loop_decls?
8235
8236 In Objective-C, there are two additional variants:
8237
8238 foreach-statement:
8239 for ( expression in expresssion ) statement
8240 for ( declaration in expression ) statement
8241
8242 This is inconsistent with C, because the second variant is allowed
8243 even if c99 is not enabled.
8244
8245 The rest of the comment documents these Objective-C foreach-statement.
8246
8247 Here is the canonical example of the first variant:
8248 for (object in array) { do something with object }
8249 we call the first expression ("object") the "object_expression" and
8250 the second expression ("array") the "collection_expression".
8251 object_expression must be an lvalue of type "id" (a generic Objective-C
8252 object) because the loop works by assigning to object_expression the
8253 various objects from the collection_expression. collection_expression
8254 must evaluate to something of type "id" which responds to the method
8255 countByEnumeratingWithState:objects:count:.
8256
8257 The canonical example of the second variant is:
8258 for (id object in array) { do something with object }
8259 which is completely equivalent to
8260 {
8261 id object;
8262 for (object in array) { do something with object }
8263 }
8264 Note that initizializing 'object' in some way (eg, "for ((object =
8265 xxx) in array) { do something with object }") is possibly
8266 technically valid, but completely pointless as 'object' will be
8267 assigned to something else as soon as the loop starts. We should
8268 most likely reject it (TODO).
8269
8270 The beginning of the Objective-C foreach-statement looks exactly
8271 like the beginning of the for-statement, and we can tell it is a
8272 foreach-statement only because the initial declaration or
8273 expression is terminated by 'in' instead of ';'.
8274
8275 IF_P is used to track whether there's a (possibly labeled) if statement
8276 which is not enclosed in braces and has an else clause. This is used to
8277 implement -Wparentheses. */
8278
8279static void
8280c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8281 bool novector, bool *if_p)
8282{
8283 tree block, cond, incr, body;
8284 unsigned char save_in_statement;
8285 tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
8286 /* The following are only used when parsing an ObjC foreach statement. */
8287 tree object_expression;
8288 /* Silence the bogus uninitialized warning. */
8289 tree collection_expression = NULL;
8290 location_t loc = c_parser_peek_token (parser)->location;
8291 location_t for_loc = loc;
8292 bool is_foreach_statement = false;
8293 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
8294 token_indent_info for_tinfo
8295 = get_token_indent_info (token: c_parser_peek_token (parser));
8296
8297 if (parser->omp_for_parse_state)
8298 {
8299 error_at (for_loc,
8300 "loop not permitted in intervening code in OpenMP loop body");
8301 parser->omp_for_parse_state->fail = true;
8302 }
8303
8304 c_parser_consume_token (parser);
8305 /* Open a compound statement in Objective-C as well, just in case this is
8306 as foreach expression. */
8307 block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
8308 cond = error_mark_node;
8309 incr = error_mark_node;
8310 matching_parens parens;
8311 if (parens.require_open (parser))
8312 {
8313 /* Parse the initialization declaration or expression. */
8314 object_expression = error_mark_node;
8315 parser->objc_could_be_foreach_context = c_dialect_objc ();
8316 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8317 {
8318 parser->objc_could_be_foreach_context = false;
8319 c_parser_consume_token (parser);
8320 c_finish_expr_stmt (loc, NULL_TREE);
8321 }
8322 else if (c_parser_next_tokens_start_declaration (parser)
8323 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
8324 {
8325 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
8326 objc_foreach_object_declaration: &object_expression);
8327 parser->objc_could_be_foreach_context = false;
8328
8329 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8330 {
8331 c_parser_consume_token (parser);
8332 is_foreach_statement = true;
8333 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
8334 c_parser_error (parser, gmsgid: "multiple iterating variables in "
8335 "fast enumeration");
8336 }
8337 else
8338 check_for_loop_decls (for_loc, flag_isoc99);
8339 }
8340 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
8341 {
8342 /* __extension__ can start a declaration, but is also an
8343 unary operator that can start an expression. Consume all
8344 but the last of a possible series of __extension__ to
8345 determine which. */
8346 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
8347 && (c_parser_peek_2nd_token (parser)->keyword
8348 == RID_EXTENSION))
8349 c_parser_consume_token (parser);
8350 if (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
8351 || c_parser_nth_token_starts_std_attributes (parser, n: 2))
8352 {
8353 int ext;
8354 ext = disable_extension_diagnostics ();
8355 c_parser_consume_token (parser);
8356 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
8357 start_attr_ok: true, objc_foreach_object_declaration: &object_expression);
8358 parser->objc_could_be_foreach_context = false;
8359
8360 restore_extension_diagnostics (flags: ext);
8361 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8362 {
8363 c_parser_consume_token (parser);
8364 is_foreach_statement = true;
8365 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
8366 c_parser_error (parser, gmsgid: "multiple iterating variables in "
8367 "fast enumeration");
8368 }
8369 else
8370 check_for_loop_decls (for_loc, flag_isoc99);
8371 }
8372 else
8373 goto init_expr;
8374 }
8375 else
8376 {
8377 init_expr:
8378 {
8379 struct c_expr ce;
8380 tree init_expression;
8381 ce = c_parser_expression (parser);
8382 init_expression = ce.value;
8383 parser->objc_could_be_foreach_context = false;
8384 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
8385 {
8386 c_parser_consume_token (parser);
8387 is_foreach_statement = true;
8388 if (! lvalue_p (init_expression))
8389 c_parser_error (parser, gmsgid: "invalid iterating variable in "
8390 "fast enumeration");
8391 object_expression
8392 = c_fully_fold (init_expression, false, NULL);
8393 }
8394 else
8395 {
8396 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
8397 init_expression = ce.value;
8398 c_finish_expr_stmt (loc, init_expression);
8399 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
8400 msgid: "expected %<;%>");
8401 }
8402 }
8403 }
8404 /* Parse the loop condition. In the case of a foreach
8405 statement, there is no loop condition. */
8406 gcc_assert (!parser->objc_could_be_foreach_context);
8407 if (!is_foreach_statement)
8408 {
8409 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8410 {
8411 if (ivdep)
8412 {
8413 c_parser_error (parser, gmsgid: "missing loop condition in loop "
8414 "with %<GCC ivdep%> pragma");
8415 cond = error_mark_node;
8416 }
8417 else if (unroll)
8418 {
8419 c_parser_error (parser, gmsgid: "missing loop condition in loop "
8420 "with %<GCC unroll%> pragma");
8421 cond = error_mark_node;
8422 }
8423 else
8424 {
8425 c_parser_consume_token (parser);
8426 cond = NULL_TREE;
8427 }
8428 }
8429 else
8430 {
8431 cond = c_parser_condition (parser);
8432 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
8433 msgid: "expected %<;%>");
8434 }
8435 if (ivdep && cond != error_mark_node)
8436 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8437 build_int_cst (integer_type_node,
8438 annot_expr_ivdep_kind),
8439 integer_zero_node);
8440 if (unroll && cond != error_mark_node)
8441 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8442 build_int_cst (integer_type_node,
8443 annot_expr_unroll_kind),
8444 build_int_cst (integer_type_node, unroll));
8445 if (novector && cond != error_mark_node)
8446 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8447 build_int_cst (integer_type_node,
8448 annot_expr_no_vector_kind),
8449 integer_zero_node);
8450 }
8451 /* Parse the increment expression (the third expression in a
8452 for-statement). In the case of a foreach-statement, this is
8453 the expression that follows the 'in'. */
8454 loc = c_parser_peek_token (parser)->location;
8455 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
8456 {
8457 if (is_foreach_statement)
8458 {
8459 c_parser_error (parser,
8460 gmsgid: "missing collection in fast enumeration");
8461 collection_expression = error_mark_node;
8462 }
8463 else
8464 incr = c_process_expr_stmt (loc, NULL_TREE);
8465 }
8466 else
8467 {
8468 if (is_foreach_statement)
8469 collection_expression
8470 = c_fully_fold (c_parser_expression (parser).value, false, NULL);
8471 else
8472 {
8473 struct c_expr ce = c_parser_expression (parser);
8474 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
8475 incr = c_process_expr_stmt (loc, ce.value);
8476 }
8477 }
8478 parens.skip_until_found_close (parser);
8479 }
8480 save_in_statement = in_statement;
8481 if (is_foreach_statement)
8482 {
8483 in_statement = IN_OBJC_FOREACH;
8484 save_objc_foreach_break_label = objc_foreach_break_label;
8485 save_objc_foreach_continue_label = objc_foreach_continue_label;
8486 objc_foreach_break_label = create_artificial_label (loc);
8487 objc_foreach_continue_label = create_artificial_label (loc);
8488 }
8489 else
8490 in_statement = IN_ITERATION_STMT;
8491
8492 token_indent_info body_tinfo
8493 = get_token_indent_info (token: c_parser_peek_token (parser));
8494
8495 location_t loc_after_labels;
8496 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
8497 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8498
8499 if (is_foreach_statement)
8500 objc_finish_foreach_loop (for_loc, object_expression,
8501 collection_expression, body,
8502 objc_foreach_break_label,
8503 objc_foreach_continue_label);
8504 else
8505 add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
8506 body, NULL_TREE));
8507 add_stmt (c_end_compound_stmt (for_loc, block,
8508 flag_isoc99 || c_dialect_objc ()));
8509 c_parser_maybe_reclassify_token (parser);
8510
8511 token_indent_info next_tinfo
8512 = get_token_indent_info (token: c_parser_peek_token (parser));
8513 warn_for_misleading_indentation (guard_tinfo: for_tinfo, body_tinfo, next_tinfo);
8514
8515 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8516 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8517 for_tinfo.location, RID_FOR);
8518
8519 in_statement = save_in_statement;
8520 if (is_foreach_statement)
8521 {
8522 objc_foreach_break_label = save_objc_foreach_break_label;
8523 objc_foreach_continue_label = save_objc_foreach_continue_label;
8524 }
8525}
8526
8527/* Parse an asm statement, a GNU extension. This is a full-blown asm
8528 statement with inputs, outputs, clobbers, and volatile, inline, and goto
8529 tags allowed.
8530
8531 asm-qualifier:
8532 volatile
8533 inline
8534 goto
8535
8536 asm-qualifier-list:
8537 asm-qualifier-list asm-qualifier
8538 asm-qualifier
8539
8540 asm-statement:
8541 asm asm-qualifier-list[opt] ( asm-argument ) ;
8542
8543 asm-argument:
8544 asm-string-literal
8545 asm-string-literal : asm-operands[opt]
8546 asm-string-literal : asm-operands[opt] : asm-operands[opt]
8547 asm-string-literal : asm-operands[opt] : asm-operands[opt] \
8548 : asm-clobbers[opt]
8549 asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
8550 : asm-goto-operands
8551
8552 The form with asm-goto-operands is valid if and only if the
8553 asm-qualifier-list contains goto, and is the only allowed form in that case.
8554 Duplicate asm-qualifiers are not allowed.
8555
8556 The :: token is considered equivalent to two consecutive : tokens. */
8557
8558static tree
8559c_parser_asm_statement (c_parser *parser)
8560{
8561 tree str, outputs, inputs, clobbers, labels, ret;
8562 bool simple;
8563 location_t asm_loc = c_parser_peek_token (parser)->location;
8564 int section, nsections;
8565
8566 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
8567 c_parser_consume_token (parser);
8568
8569 /* Handle the asm-qualifier-list. */
8570 location_t volatile_loc = UNKNOWN_LOCATION;
8571 location_t inline_loc = UNKNOWN_LOCATION;
8572 location_t goto_loc = UNKNOWN_LOCATION;
8573 for (;;)
8574 {
8575 c_token *token = c_parser_peek_token (parser);
8576 location_t loc = token->location;
8577 switch (token->keyword)
8578 {
8579 case RID_VOLATILE:
8580 if (volatile_loc)
8581 {
8582 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8583 inform (volatile_loc, "first seen here");
8584 }
8585 else
8586 volatile_loc = loc;
8587 c_parser_consume_token (parser);
8588 continue;
8589
8590 case RID_INLINE:
8591 if (inline_loc)
8592 {
8593 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8594 inform (inline_loc, "first seen here");
8595 }
8596 else
8597 inline_loc = loc;
8598 c_parser_consume_token (parser);
8599 continue;
8600
8601 case RID_GOTO:
8602 if (goto_loc)
8603 {
8604 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
8605 inform (goto_loc, "first seen here");
8606 }
8607 else
8608 goto_loc = loc;
8609 c_parser_consume_token (parser);
8610 continue;
8611
8612 case RID_CONST:
8613 case RID_RESTRICT:
8614 error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
8615 c_parser_consume_token (parser);
8616 continue;
8617
8618 default:
8619 break;
8620 }
8621 break;
8622 }
8623
8624 bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
8625 bool is_inline = (inline_loc != UNKNOWN_LOCATION);
8626 bool is_goto = (goto_loc != UNKNOWN_LOCATION);
8627
8628 ret = NULL;
8629
8630 matching_parens parens;
8631 if (!parens.require_open (parser))
8632 goto error;
8633
8634 str = c_parser_asm_string_literal (parser);
8635 if (str == NULL_TREE)
8636 goto error_close_paren;
8637
8638 simple = true;
8639 outputs = NULL_TREE;
8640 inputs = NULL_TREE;
8641 clobbers = NULL_TREE;
8642 labels = NULL_TREE;
8643
8644 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
8645 goto done_asm;
8646
8647 /* Parse each colon-delimited section of operands. */
8648 nsections = 3 + is_goto;
8649 for (section = 0; section < nsections; ++section)
8650 {
8651 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
8652 {
8653 ++section;
8654 if (section == nsections)
8655 {
8656 c_parser_error (parser, gmsgid: "expected %<)%>");
8657 goto error_close_paren;
8658 }
8659 c_parser_consume_token (parser);
8660 }
8661 else if (!c_parser_require (parser, type: CPP_COLON,
8662 msgid: is_goto
8663 ? G_("expected %<:%>")
8664 : G_("expected %<:%> or %<)%>"),
8665 UNKNOWN_LOCATION, type_is_unique: is_goto))
8666 goto error_close_paren;
8667
8668 /* Once past any colon, we're no longer a simple asm. */
8669 simple = false;
8670
8671 if ((!c_parser_next_token_is (parser, type: CPP_COLON)
8672 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
8673 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
8674 || section == 3)
8675 switch (section)
8676 {
8677 case 0:
8678 outputs = c_parser_asm_operands (parser);
8679 break;
8680 case 1:
8681 inputs = c_parser_asm_operands (parser);
8682 break;
8683 case 2:
8684 clobbers = c_parser_asm_clobbers (parser);
8685 break;
8686 case 3:
8687 labels = c_parser_asm_goto_operands (parser);
8688 break;
8689 default:
8690 gcc_unreachable ();
8691 }
8692
8693 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
8694 goto done_asm;
8695 }
8696
8697 done_asm:
8698 if (!parens.require_close (parser))
8699 {
8700 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8701 goto error;
8702 }
8703
8704 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
8705 c_parser_skip_to_end_of_block_or_statement (parser);
8706
8707 ret = build_asm_stmt (is_volatile,
8708 build_asm_expr (asm_loc, str, outputs, inputs,
8709 clobbers, labels, simple, is_inline));
8710
8711 error:
8712 return ret;
8713
8714 error_close_paren:
8715 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8716 goto error;
8717}
8718
8719/* Parse asm operands, a GNU extension.
8720
8721 asm-operands:
8722 asm-operand
8723 asm-operands , asm-operand
8724
8725 asm-operand:
8726 asm-string-literal ( expression )
8727 [ identifier ] asm-string-literal ( expression )
8728*/
8729
8730static tree
8731c_parser_asm_operands (c_parser *parser)
8732{
8733 tree list = NULL_TREE;
8734 while (true)
8735 {
8736 tree name, str;
8737 struct c_expr expr;
8738 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
8739 {
8740 c_parser_consume_token (parser);
8741 if (c_parser_next_token_is (parser, type: CPP_NAME))
8742 {
8743 tree id = c_parser_peek_token (parser)->value;
8744 c_parser_consume_token (parser);
8745 name = build_string (IDENTIFIER_LENGTH (id),
8746 IDENTIFIER_POINTER (id));
8747 }
8748 else
8749 {
8750 c_parser_error (parser, gmsgid: "expected identifier");
8751 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, NULL);
8752 return NULL_TREE;
8753 }
8754 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
8755 msgid: "expected %<]%>");
8756 }
8757 else
8758 name = NULL_TREE;
8759 str = c_parser_asm_string_literal (parser);
8760 if (str == NULL_TREE)
8761 return NULL_TREE;
8762 matching_parens parens;
8763 if (!parens.require_open (parser))
8764 return NULL_TREE;
8765 expr = c_parser_expression (parser);
8766 mark_exp_read (expr.value);
8767 if (!parens.require_close (parser))
8768 {
8769 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
8770 return NULL_TREE;
8771 }
8772 list = chainon (list, build_tree_list (build_tree_list (name, str),
8773 expr.value));
8774 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8775 c_parser_consume_token (parser);
8776 else
8777 break;
8778 }
8779 return list;
8780}
8781
8782/* Parse asm clobbers, a GNU extension.
8783
8784 asm-clobbers:
8785 asm-string-literal
8786 asm-clobbers , asm-string-literal
8787*/
8788
8789static tree
8790c_parser_asm_clobbers (c_parser *parser)
8791{
8792 tree list = NULL_TREE;
8793 while (true)
8794 {
8795 tree str = c_parser_asm_string_literal (parser);
8796 if (str)
8797 list = tree_cons (NULL_TREE, str, list);
8798 else
8799 return NULL_TREE;
8800 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8801 c_parser_consume_token (parser);
8802 else
8803 break;
8804 }
8805 return list;
8806}
8807
8808/* Parse asm goto labels, a GNU extension.
8809
8810 asm-goto-operands:
8811 identifier
8812 asm-goto-operands , identifier
8813*/
8814
8815static tree
8816c_parser_asm_goto_operands (c_parser *parser)
8817{
8818 tree list = NULL_TREE;
8819 while (true)
8820 {
8821 tree name, label;
8822
8823 if (c_parser_next_token_is (parser, type: CPP_NAME))
8824 {
8825 c_token *tok = c_parser_peek_token (parser);
8826 name = tok->value;
8827 label = lookup_label_for_goto (tok->location, name);
8828 c_parser_consume_token (parser);
8829 TREE_USED (label) = 1;
8830 }
8831 else
8832 {
8833 c_parser_error (parser, gmsgid: "expected identifier");
8834 return NULL_TREE;
8835 }
8836
8837 name = build_string (IDENTIFIER_LENGTH (name),
8838 IDENTIFIER_POINTER (name));
8839 list = tree_cons (name, label, list);
8840 if (c_parser_next_token_is (parser, type: CPP_COMMA))
8841 c_parser_consume_token (parser);
8842 else
8843 return nreverse (list);
8844 }
8845}
8846
8847/* Parse a possibly concatenated sequence of string literals.
8848 TRANSLATE says whether to translate them to the execution character
8849 set; WIDE_OK says whether any kind of prefixed string literal is
8850 permitted in this context. This code is based on that in
8851 lex_string. */
8852
8853struct c_expr
8854c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
8855{
8856 struct c_expr ret;
8857 size_t count;
8858 struct obstack str_ob;
8859 struct obstack loc_ob;
8860 cpp_string str, istr, *strs;
8861 c_token *tok;
8862 location_t loc, last_tok_loc;
8863 enum cpp_ttype type;
8864 tree value, string_tree;
8865
8866 tok = c_parser_peek_token (parser);
8867 loc = tok->location;
8868 last_tok_loc = linemap_resolve_location (line_table, loc,
8869 lrk: LRK_MACRO_DEFINITION_LOCATION,
8870 NULL);
8871 type = tok->type;
8872 switch (type)
8873 {
8874 case CPP_STRING:
8875 case CPP_WSTRING:
8876 case CPP_STRING16:
8877 case CPP_STRING32:
8878 case CPP_UTF8STRING:
8879 string_tree = tok->value;
8880 break;
8881
8882 default:
8883 c_parser_error (parser, gmsgid: "expected string literal");
8884 ret.set_error ();
8885 ret.value = NULL_TREE;
8886 ret.original_code = ERROR_MARK;
8887 ret.original_type = NULL_TREE;
8888 return ret;
8889 }
8890
8891 /* Try to avoid the overhead of creating and destroying an obstack
8892 for the common case of just one string. */
8893 switch (c_parser_peek_2nd_token (parser)->type)
8894 {
8895 default:
8896 c_parser_consume_token (parser);
8897 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
8898 str.len = TREE_STRING_LENGTH (string_tree);
8899 count = 1;
8900 strs = &str;
8901 break;
8902
8903 case CPP_STRING:
8904 case CPP_WSTRING:
8905 case CPP_STRING16:
8906 case CPP_STRING32:
8907 case CPP_UTF8STRING:
8908 gcc_obstack_init (&str_ob);
8909 gcc_obstack_init (&loc_ob);
8910 count = 0;
8911 do
8912 {
8913 c_parser_consume_token (parser);
8914 count++;
8915 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
8916 str.len = TREE_STRING_LENGTH (string_tree);
8917 if (type != tok->type)
8918 {
8919 if (type == CPP_STRING)
8920 type = tok->type;
8921 else if (tok->type != CPP_STRING)
8922 error ("unsupported non-standard concatenation "
8923 "of string literals");
8924 }
8925 obstack_grow (&str_ob, &str, sizeof (cpp_string));
8926 obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
8927 tok = c_parser_peek_token (parser);
8928 string_tree = tok->value;
8929 last_tok_loc
8930 = linemap_resolve_location (line_table, loc: tok->location,
8931 lrk: LRK_MACRO_DEFINITION_LOCATION, NULL);
8932 }
8933 while (tok->type == CPP_STRING
8934 || tok->type == CPP_WSTRING
8935 || tok->type == CPP_STRING16
8936 || tok->type == CPP_STRING32
8937 || tok->type == CPP_UTF8STRING);
8938 strs = (cpp_string *) obstack_finish (&str_ob);
8939 }
8940
8941 if (count > 1 && !in_system_header_at (loc: input_location))
8942 warning (OPT_Wtraditional,
8943 "traditional C rejects string constant concatenation");
8944
8945 if ((type == CPP_STRING || wide_ok)
8946 && ((translate
8947 ? cpp_interpret_string : cpp_interpret_string_notranslate)
8948 (parse_in, strs, count, &istr, type)))
8949 {
8950 value = build_string (istr.len, (const char *) istr.text);
8951 free (CONST_CAST (unsigned char *, istr.text));
8952 if (count > 1)
8953 {
8954 location_t *locs = (location_t *) obstack_finish (&loc_ob);
8955 gcc_assert (g_string_concat_db);
8956 g_string_concat_db->record_string_concatenation (num: count, locs);
8957 }
8958 }
8959 else
8960 {
8961 if (type != CPP_STRING && !wide_ok)
8962 {
8963 error_at (loc, "a wide string is invalid in this context");
8964 type = CPP_STRING;
8965 }
8966 /* Callers cannot generally handle error_mark_node in this
8967 context, so return the empty string instead. An error has
8968 been issued, either above or from cpp_interpret_string. */
8969 switch (type)
8970 {
8971 default:
8972 case CPP_STRING:
8973 case CPP_UTF8STRING:
8974 if (type == CPP_UTF8STRING && flag_char8_t)
8975 {
8976 value = build_string (TYPE_PRECISION (char8_type_node)
8977 / TYPE_PRECISION (char_type_node),
8978 ""); /* char8_t is 8 bits */
8979 }
8980 else
8981 value = build_string (1, "");
8982 break;
8983 case CPP_STRING16:
8984 value = build_string (TYPE_PRECISION (char16_type_node)
8985 / TYPE_PRECISION (char_type_node),
8986 "\0"); /* char16_t is 16 bits */
8987 break;
8988 case CPP_STRING32:
8989 value = build_string (TYPE_PRECISION (char32_type_node)
8990 / TYPE_PRECISION (char_type_node),
8991 "\0\0\0"); /* char32_t is 32 bits */
8992 break;
8993 case CPP_WSTRING:
8994 value = build_string (TYPE_PRECISION (wchar_type_node)
8995 / TYPE_PRECISION (char_type_node),
8996 "\0\0\0"); /* widest supported wchar_t
8997 is 32 bits */
8998 break;
8999 }
9000 }
9001
9002 switch (type)
9003 {
9004 default:
9005 case CPP_STRING:
9006 TREE_TYPE (value) = char_array_type_node;
9007 break;
9008 case CPP_UTF8STRING:
9009 if (flag_char8_t)
9010 TREE_TYPE (value) = char8_array_type_node;
9011 else
9012 TREE_TYPE (value) = char_array_type_node;
9013 break;
9014 case CPP_STRING16:
9015 TREE_TYPE (value) = char16_array_type_node;
9016 break;
9017 case CPP_STRING32:
9018 TREE_TYPE (value) = char32_array_type_node;
9019 break;
9020 case CPP_WSTRING:
9021 TREE_TYPE (value) = wchar_array_type_node;
9022 }
9023 value = fix_string_type (value);
9024
9025 if (count > 1)
9026 {
9027 obstack_free (&str_ob, 0);
9028 obstack_free (&loc_ob, 0);
9029 }
9030
9031 ret.value = value;
9032 ret.original_code = STRING_CST;
9033 ret.original_type = NULL_TREE;
9034 set_c_expr_source_range (expr: &ret, src_range: get_range_from_loc (set: line_table, loc));
9035 ret.m_decimal = 0;
9036 parser->seen_string_literal = true;
9037 return ret;
9038}
9039
9040/* Parse an expression other than a compound expression; that is, an
9041 assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9042 AFTER is not NULL then it is an Objective-C message expression which
9043 is the primary-expression starting the expression as an initializer.
9044
9045 assignment-expression:
9046 conditional-expression
9047 unary-expression assignment-operator assignment-expression
9048
9049 assignment-operator: one of
9050 = *= /= %= += -= <<= >>= &= ^= |=
9051
9052 In GNU C we accept any conditional expression on the LHS and
9053 diagnose the invalid lvalue rather than producing a syntax
9054 error. */
9055
9056static struct c_expr
9057c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
9058 tree omp_atomic_lhs)
9059{
9060 struct c_expr lhs, rhs, ret;
9061 enum tree_code code;
9062 location_t op_location, exp_location;
9063 bool save_in_omp_for = c_in_omp_for;
9064 c_in_omp_for = false;
9065 gcc_assert (!after || c_dialect_objc ());
9066 lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
9067 op_location = c_parser_peek_token (parser)->location;
9068 switch (c_parser_peek_token (parser)->type)
9069 {
9070 case CPP_EQ:
9071 code = NOP_EXPR;
9072 break;
9073 case CPP_MULT_EQ:
9074 code = MULT_EXPR;
9075 break;
9076 case CPP_DIV_EQ:
9077 code = TRUNC_DIV_EXPR;
9078 break;
9079 case CPP_MOD_EQ:
9080 code = TRUNC_MOD_EXPR;
9081 break;
9082 case CPP_PLUS_EQ:
9083 code = PLUS_EXPR;
9084 break;
9085 case CPP_MINUS_EQ:
9086 code = MINUS_EXPR;
9087 break;
9088 case CPP_LSHIFT_EQ:
9089 code = LSHIFT_EXPR;
9090 break;
9091 case CPP_RSHIFT_EQ:
9092 code = RSHIFT_EXPR;
9093 break;
9094 case CPP_AND_EQ:
9095 code = BIT_AND_EXPR;
9096 break;
9097 case CPP_XOR_EQ:
9098 code = BIT_XOR_EXPR;
9099 break;
9100 case CPP_OR_EQ:
9101 code = BIT_IOR_EXPR;
9102 break;
9103 default:
9104 c_in_omp_for = save_in_omp_for;
9105 return lhs;
9106 }
9107 c_parser_consume_token (parser);
9108 exp_location = c_parser_peek_token (parser)->location;
9109 rhs = c_parser_expr_no_commas (parser, NULL);
9110 rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
9111
9112 ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
9113 code, exp_location, rhs.value,
9114 rhs.original_type);
9115 ret.m_decimal = 0;
9116 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
9117 if (code == NOP_EXPR)
9118 ret.original_code = MODIFY_EXPR;
9119 else
9120 {
9121 suppress_warning (ret.value, OPT_Wparentheses);
9122 ret.original_code = ERROR_MARK;
9123 }
9124 ret.original_type = NULL;
9125 c_in_omp_for = save_in_omp_for;
9126 return ret;
9127}
9128
9129/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
9130 AFTER is not NULL then it is an Objective-C message expression which is
9131 the primary-expression starting the expression as an initializer.
9132
9133 conditional-expression:
9134 logical-OR-expression
9135 logical-OR-expression ? expression : conditional-expression
9136
9137 GNU extensions:
9138
9139 conditional-expression:
9140 logical-OR-expression ? : conditional-expression
9141*/
9142
9143static struct c_expr
9144c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
9145 tree omp_atomic_lhs)
9146{
9147 struct c_expr cond, exp1, exp2, ret;
9148 location_t start, cond_loc, colon_loc;
9149
9150 gcc_assert (!after || c_dialect_objc ());
9151
9152 cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
9153
9154 if (c_parser_next_token_is_not (parser, type: CPP_QUERY))
9155 return cond;
9156 if (cond.value != error_mark_node)
9157 start = cond.get_start ();
9158 else
9159 start = UNKNOWN_LOCATION;
9160 cond_loc = c_parser_peek_token (parser)->location;
9161 cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
9162 c_parser_consume_token (parser);
9163 if (c_parser_next_token_is (parser, type: CPP_COLON))
9164 {
9165 tree eptype = NULL_TREE;
9166
9167 location_t middle_loc = c_parser_peek_token (parser)->location;
9168 pedwarn (middle_loc, OPT_Wpedantic,
9169 "ISO C forbids omitting the middle term of a %<?:%> expression");
9170 if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
9171 {
9172 eptype = TREE_TYPE (cond.value);
9173 cond.value = TREE_OPERAND (cond.value, 0);
9174 }
9175 tree e = cond.value;
9176 while (TREE_CODE (e) == COMPOUND_EXPR)
9177 e = TREE_OPERAND (e, 1);
9178 warn_for_omitted_condop (middle_loc, e);
9179 /* Make sure first operand is calculated only once. */
9180 exp1.value = save_expr (default_conversion (cond.value));
9181 if (eptype)
9182 exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
9183 exp1.original_type = NULL;
9184 exp1.src_range = cond.src_range;
9185 cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
9186 c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
9187 }
9188 else
9189 {
9190 cond.value
9191 = c_objc_common_truthvalue_conversion
9192 (cond_loc, default_conversion (cond.value));
9193 c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
9194 exp1 = c_parser_expression_conv (parser);
9195 mark_exp_read (exp1.value);
9196 c_inhibit_evaluation_warnings +=
9197 ((cond.value == truthvalue_true_node)
9198 - (cond.value == truthvalue_false_node));
9199 }
9200
9201 colon_loc = c_parser_peek_token (parser)->location;
9202 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
9203 {
9204 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
9205 ret.set_error ();
9206 ret.original_code = ERROR_MARK;
9207 ret.original_type = NULL;
9208 return ret;
9209 }
9210 {
9211 location_t exp2_loc = c_parser_peek_token (parser)->location;
9212 exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
9213 exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
9214 }
9215 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
9216 location_t loc1 = make_location (caret: exp1.get_start (), src_range: exp1.src_range);
9217 location_t loc2 = make_location (caret: exp2.get_start (), src_range: exp2.src_range);
9218 if (UNLIKELY (omp_atomic_lhs != NULL)
9219 && (TREE_CODE (cond.value) == GT_EXPR
9220 || TREE_CODE (cond.value) == LT_EXPR
9221 || TREE_CODE (cond.value) == EQ_EXPR)
9222 && c_tree_equal (exp2.value, omp_atomic_lhs)
9223 && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
9224 || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
9225 ret.value = build3_loc (loc: colon_loc, code: COND_EXPR, TREE_TYPE (omp_atomic_lhs),
9226 arg0: cond.value, arg1: exp1.value, arg2: exp2.value);
9227 else
9228 ret.value
9229 = build_conditional_expr (colon_loc, cond.value,
9230 cond.original_code == C_MAYBE_CONST_EXPR,
9231 exp1.value, exp1.original_type, loc1,
9232 exp2.value, exp2.original_type, loc2);
9233 ret.original_code = ERROR_MARK;
9234 if (exp1.value == error_mark_node || exp2.value == error_mark_node)
9235 ret.original_type = NULL;
9236 else
9237 {
9238 tree t1, t2;
9239
9240 /* If both sides are enum type, the default conversion will have
9241 made the type of the result be an integer type. We want to
9242 remember the enum types we started with. */
9243 t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
9244 t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
9245 ret.original_type = ((t1 != error_mark_node
9246 && t2 != error_mark_node
9247 && (TYPE_MAIN_VARIANT (t1)
9248 == TYPE_MAIN_VARIANT (t2)))
9249 ? t1
9250 : NULL);
9251 }
9252 set_c_expr_source_range (expr: &ret, start, finish: exp2.get_finish ());
9253 ret.m_decimal = 0;
9254 return ret;
9255}
9256
9257/* Parse a binary expression; that is, a logical-OR-expression (C90
9258 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
9259 NULL then it is an Objective-C message expression which is the
9260 primary-expression starting the expression as an initializer.
9261
9262 OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
9263 when it should be the unfolded lhs. In a valid OpenMP source,
9264 one of the operands of the toplevel binary expression must be equal
9265 to it. In that case, just return a build2 created binary operation
9266 rather than result of parser_build_binary_op.
9267
9268 multiplicative-expression:
9269 cast-expression
9270 multiplicative-expression * cast-expression
9271 multiplicative-expression / cast-expression
9272 multiplicative-expression % cast-expression
9273
9274 additive-expression:
9275 multiplicative-expression
9276 additive-expression + multiplicative-expression
9277 additive-expression - multiplicative-expression
9278
9279 shift-expression:
9280 additive-expression
9281 shift-expression << additive-expression
9282 shift-expression >> additive-expression
9283
9284 relational-expression:
9285 shift-expression
9286 relational-expression < shift-expression
9287 relational-expression > shift-expression
9288 relational-expression <= shift-expression
9289 relational-expression >= shift-expression
9290
9291 equality-expression:
9292 relational-expression
9293 equality-expression == relational-expression
9294 equality-expression != relational-expression
9295
9296 AND-expression:
9297 equality-expression
9298 AND-expression & equality-expression
9299
9300 exclusive-OR-expression:
9301 AND-expression
9302 exclusive-OR-expression ^ AND-expression
9303
9304 inclusive-OR-expression:
9305 exclusive-OR-expression
9306 inclusive-OR-expression | exclusive-OR-expression
9307
9308 logical-AND-expression:
9309 inclusive-OR-expression
9310 logical-AND-expression && inclusive-OR-expression
9311
9312 logical-OR-expression:
9313 logical-AND-expression
9314 logical-OR-expression || logical-AND-expression
9315*/
9316
9317static struct c_expr
9318c_parser_binary_expression (c_parser *parser, struct c_expr *after,
9319 tree omp_atomic_lhs)
9320{
9321 /* A binary expression is parsed using operator-precedence parsing,
9322 with the operands being cast expressions. All the binary
9323 operators are left-associative. Thus a binary expression is of
9324 form:
9325
9326 E0 op1 E1 op2 E2 ...
9327
9328 which we represent on a stack. On the stack, the precedence
9329 levels are strictly increasing. When a new operator is
9330 encountered of higher precedence than that at the top of the
9331 stack, it is pushed; its LHS is the top expression, and its RHS
9332 is everything parsed until it is popped. When a new operator is
9333 encountered with precedence less than or equal to that at the top
9334 of the stack, triples E[i-1] op[i] E[i] are popped and replaced
9335 by the result of the operation until the operator at the top of
9336 the stack has lower precedence than the new operator or there is
9337 only one element on the stack; then the top expression is the LHS
9338 of the new operator. In the case of logical AND and OR
9339 expressions, we also need to adjust c_inhibit_evaluation_warnings
9340 as appropriate when the operators are pushed and popped. */
9341
9342 struct {
9343 /* The expression at this stack level. */
9344 struct c_expr expr;
9345 /* The precedence of the operator on its left, PREC_NONE at the
9346 bottom of the stack. */
9347 enum c_parser_prec prec;
9348 /* The operation on its left. */
9349 enum tree_code op;
9350 /* The source location of this operation. */
9351 location_t loc;
9352 /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
9353 tree sizeof_arg;
9354 } stack[NUM_PRECS];
9355 int sp;
9356 /* Location of the binary operator. */
9357 location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
9358#define POP \
9359 do { \
9360 switch (stack[sp].op) \
9361 { \
9362 case TRUTH_ANDIF_EXPR: \
9363 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
9364 == truthvalue_false_node); \
9365 break; \
9366 case TRUTH_ORIF_EXPR: \
9367 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
9368 == truthvalue_true_node); \
9369 break; \
9370 case TRUNC_DIV_EXPR: \
9371 if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
9372 || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
9373 && (stack[sp].expr.original_code == SIZEOF_EXPR \
9374 || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
9375 { \
9376 tree type0 = stack[sp - 1].sizeof_arg; \
9377 tree type1 = stack[sp].sizeof_arg; \
9378 tree first_arg = type0; \
9379 if (!TYPE_P (type0)) \
9380 type0 = TREE_TYPE (type0); \
9381 if (!TYPE_P (type1)) \
9382 type1 = TREE_TYPE (type1); \
9383 if (POINTER_TYPE_P (type0) \
9384 && comptypes (TREE_TYPE (type0), type1) \
9385 && !(TREE_CODE (first_arg) == PARM_DECL \
9386 && C_ARRAY_PARAMETER (first_arg) \
9387 && warn_sizeof_array_argument)) \
9388 { \
9389 auto_diagnostic_group d; \
9390 if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
9391 "division %<sizeof (%T) / sizeof (%T)%> " \
9392 "does not compute the number of array " \
9393 "elements", \
9394 type0, type1)) \
9395 if (DECL_P (first_arg)) \
9396 inform (DECL_SOURCE_LOCATION (first_arg), \
9397 "first %<sizeof%> operand was declared here"); \
9398 } \
9399 else if (TREE_CODE (type0) == ARRAY_TYPE \
9400 && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
9401 && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
9402 maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
9403 stack[sp].sizeof_arg, type1); \
9404 } \
9405 break; \
9406 default: \
9407 break; \
9408 } \
9409 stack[sp - 1].expr \
9410 = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
9411 stack[sp - 1].expr, true, true); \
9412 stack[sp].expr \
9413 = convert_lvalue_to_rvalue (stack[sp].loc, \
9414 stack[sp].expr, true, true); \
9415 if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
9416 && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
9417 && ((1 << stack[sp].prec) \
9418 & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
9419 | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
9420 | (1 << PREC_ADD) | (1 << PREC_MULT) \
9421 | (1 << PREC_EQ)))) \
9422 || ((c_parser_next_token_is (parser, CPP_QUERY) \
9423 || (omp_atomic_lhs == void_list_node \
9424 && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
9425 && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
9426 && stack[sp].op != TRUNC_MOD_EXPR \
9427 && stack[sp].op != GE_EXPR \
9428 && stack[sp].op != LE_EXPR \
9429 && stack[sp].op != NE_EXPR \
9430 && stack[0].expr.value != error_mark_node \
9431 && stack[1].expr.value != error_mark_node \
9432 && (omp_atomic_lhs == void_list_node \
9433 || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
9434 || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
9435 || (stack[sp].op == EQ_EXPR \
9436 && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
9437 { \
9438 tree t = make_node (stack[1].op); \
9439 TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
9440 TREE_OPERAND (t, 0) = stack[0].expr.value; \
9441 TREE_OPERAND (t, 1) = stack[1].expr.value; \
9442 stack[0].expr.value = t; \
9443 stack[0].expr.m_decimal = 0; \
9444 } \
9445 else \
9446 stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
9447 stack[sp].op, \
9448 stack[sp - 1].expr, \
9449 stack[sp].expr); \
9450 sp--; \
9451 } while (0)
9452 gcc_assert (!after || c_dialect_objc ());
9453 stack[0].loc = c_parser_peek_token (parser)->location;
9454 stack[0].expr = c_parser_cast_expression (parser, after);
9455 stack[0].prec = PREC_NONE;
9456 stack[0].sizeof_arg = c_last_sizeof_arg;
9457 sp = 0;
9458 while (true)
9459 {
9460 enum c_parser_prec oprec;
9461 enum tree_code ocode;
9462 source_range src_range;
9463 if (parser->error)
9464 goto out;
9465 switch (c_parser_peek_token (parser)->type)
9466 {
9467 case CPP_MULT:
9468 oprec = PREC_MULT;
9469 ocode = MULT_EXPR;
9470 break;
9471 case CPP_DIV:
9472 oprec = PREC_MULT;
9473 ocode = TRUNC_DIV_EXPR;
9474 break;
9475 case CPP_MOD:
9476 oprec = PREC_MULT;
9477 ocode = TRUNC_MOD_EXPR;
9478 break;
9479 case CPP_PLUS:
9480 oprec = PREC_ADD;
9481 ocode = PLUS_EXPR;
9482 break;
9483 case CPP_MINUS:
9484 oprec = PREC_ADD;
9485 ocode = MINUS_EXPR;
9486 break;
9487 case CPP_LSHIFT:
9488 oprec = PREC_SHIFT;
9489 ocode = LSHIFT_EXPR;
9490 break;
9491 case CPP_RSHIFT:
9492 oprec = PREC_SHIFT;
9493 ocode = RSHIFT_EXPR;
9494 break;
9495 case CPP_LESS:
9496 oprec = PREC_REL;
9497 ocode = LT_EXPR;
9498 break;
9499 case CPP_GREATER:
9500 oprec = PREC_REL;
9501 ocode = GT_EXPR;
9502 break;
9503 case CPP_LESS_EQ:
9504 oprec = PREC_REL;
9505 ocode = LE_EXPR;
9506 break;
9507 case CPP_GREATER_EQ:
9508 oprec = PREC_REL;
9509 ocode = GE_EXPR;
9510 break;
9511 case CPP_EQ_EQ:
9512 oprec = PREC_EQ;
9513 ocode = EQ_EXPR;
9514 break;
9515 case CPP_NOT_EQ:
9516 oprec = PREC_EQ;
9517 ocode = NE_EXPR;
9518 break;
9519 case CPP_AND:
9520 oprec = PREC_BITAND;
9521 ocode = BIT_AND_EXPR;
9522 break;
9523 case CPP_XOR:
9524 oprec = PREC_BITXOR;
9525 ocode = BIT_XOR_EXPR;
9526 break;
9527 case CPP_OR:
9528 oprec = PREC_BITOR;
9529 ocode = BIT_IOR_EXPR;
9530 break;
9531 case CPP_AND_AND:
9532 oprec = PREC_LOGAND;
9533 ocode = TRUTH_ANDIF_EXPR;
9534 break;
9535 case CPP_OR_OR:
9536 oprec = PREC_LOGOR;
9537 ocode = TRUTH_ORIF_EXPR;
9538 break;
9539 default:
9540 /* Not a binary operator, so end of the binary
9541 expression. */
9542 goto out;
9543 }
9544 binary_loc = c_parser_peek_token (parser)->location;
9545 while (oprec <= stack[sp].prec)
9546 POP;
9547 c_parser_consume_token (parser);
9548 switch (ocode)
9549 {
9550 case TRUTH_ANDIF_EXPR:
9551 src_range = stack[sp].expr.src_range;
9552 stack[sp].expr
9553 = convert_lvalue_to_rvalue (stack[sp].loc,
9554 stack[sp].expr, true, true);
9555 stack[sp].expr.value = c_objc_common_truthvalue_conversion
9556 (stack[sp].loc, default_conversion (stack[sp].expr.value));
9557 c_inhibit_evaluation_warnings += (stack[sp].expr.value
9558 == truthvalue_false_node);
9559 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
9560 break;
9561 case TRUTH_ORIF_EXPR:
9562 src_range = stack[sp].expr.src_range;
9563 stack[sp].expr
9564 = convert_lvalue_to_rvalue (stack[sp].loc,
9565 stack[sp].expr, true, true);
9566 stack[sp].expr.value = c_objc_common_truthvalue_conversion
9567 (stack[sp].loc, default_conversion (stack[sp].expr.value));
9568 c_inhibit_evaluation_warnings += (stack[sp].expr.value
9569 == truthvalue_true_node);
9570 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
9571 break;
9572 default:
9573 break;
9574 }
9575 sp++;
9576 stack[sp].loc = binary_loc;
9577 stack[sp].expr = c_parser_cast_expression (parser, NULL);
9578 stack[sp].prec = oprec;
9579 stack[sp].op = ocode;
9580 stack[sp].sizeof_arg = c_last_sizeof_arg;
9581 }
9582 out:
9583 while (sp > 0)
9584 POP;
9585 return stack[0].expr;
9586#undef POP
9587}
9588
9589/* Parse any storage class specifiers after an open parenthesis in a
9590 context where a compound literal is permitted. */
9591
9592static struct c_declspecs *
9593c_parser_compound_literal_scspecs (c_parser *parser)
9594{
9595 bool seen_scspec = false;
9596 struct c_declspecs *specs = build_null_declspecs ();
9597 while (c_parser_next_token_is (parser, type: CPP_KEYWORD))
9598 {
9599 switch (c_parser_peek_token (parser)->keyword)
9600 {
9601 case RID_CONSTEXPR:
9602 case RID_REGISTER:
9603 case RID_STATIC:
9604 case RID_THREAD:
9605 seen_scspec = true;
9606 declspecs_add_scspec (c_parser_peek_token (parser)->location,
9607 specs, c_parser_peek_token (parser)->value);
9608 c_parser_consume_token (parser);
9609 break;
9610 default:
9611 goto out;
9612 }
9613 }
9614 out:
9615 return seen_scspec ? specs : NULL;
9616}
9617
9618/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
9619 is not NULL then it is an Objective-C message expression which is the
9620 primary-expression starting the expression as an initializer.
9621
9622 cast-expression:
9623 unary-expression
9624 ( type-name ) unary-expression
9625*/
9626
9627static struct c_expr
9628c_parser_cast_expression (c_parser *parser, struct c_expr *after)
9629{
9630 location_t cast_loc = c_parser_peek_token (parser)->location;
9631 gcc_assert (!after || c_dialect_objc ());
9632 if (after)
9633 return c_parser_postfix_expression_after_primary (parser,
9634 loc: cast_loc, *after);
9635 /* If the expression begins with a parenthesized type name, it may
9636 be either a cast or a compound literal; we need to see whether
9637 the next character is '{' to tell the difference. If not, it is
9638 an unary expression. Full detection of unknown typenames here
9639 would require a 3-token lookahead. */
9640 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9641 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9642 {
9643 struct c_declspecs *scspecs;
9644 struct c_type_name *type_name;
9645 struct c_expr ret;
9646 struct c_expr expr;
9647 matching_parens parens;
9648 parens.consume_open (parser);
9649 scspecs = c_parser_compound_literal_scspecs (parser);
9650 type_name = c_parser_type_name (parser, alignas_ok: true);
9651 parens.skip_until_found_close (parser);
9652 if (type_name == NULL)
9653 {
9654 ret.set_error ();
9655 ret.original_code = ERROR_MARK;
9656 ret.original_type = NULL;
9657 return ret;
9658 }
9659
9660 /* Save casted types in the function's used types hash table. */
9661 used_types_insert (type_name->specs->type);
9662
9663 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9664 return c_parser_postfix_expression_after_paren_type (parser, scspecs,
9665 type_name,
9666 cast_loc);
9667 if (scspecs)
9668 error_at (cast_loc, "storage class specifier in cast");
9669 if (type_name->specs->alignas_p)
9670 error_at (type_name->specs->locations[cdw_alignas],
9671 "alignment specified for type name in cast");
9672 {
9673 location_t expr_loc = c_parser_peek_token (parser)->location;
9674 expr = c_parser_cast_expression (parser, NULL);
9675 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
9676 }
9677 ret.value = c_cast_expr (cast_loc, type_name, expr.value);
9678 if (ret.value && expr.value)
9679 set_c_expr_source_range (expr: &ret, start: cast_loc, finish: expr.get_finish ());
9680 ret.original_code = ERROR_MARK;
9681 ret.original_type = NULL;
9682 ret.m_decimal = 0;
9683 return ret;
9684 }
9685 else
9686 return c_parser_unary_expression (parser);
9687}
9688
9689/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
9690
9691 unary-expression:
9692 postfix-expression
9693 ++ unary-expression
9694 -- unary-expression
9695 unary-operator cast-expression
9696 sizeof unary-expression
9697 sizeof ( type-name )
9698
9699 unary-operator: one of
9700 & * + - ~ !
9701
9702 GNU extensions:
9703
9704 unary-expression:
9705 __alignof__ unary-expression
9706 __alignof__ ( type-name )
9707 && identifier
9708
9709 (C11 permits _Alignof with type names only.)
9710
9711 unary-operator: one of
9712 __extension__ __real__ __imag__
9713
9714 Transactional Memory:
9715
9716 unary-expression:
9717 transaction-expression
9718
9719 In addition, the GNU syntax treats ++ and -- as unary operators, so
9720 they may be applied to cast expressions with errors for non-lvalues
9721 given later. */
9722
9723static struct c_expr
9724c_parser_unary_expression (c_parser *parser)
9725{
9726 int ext;
9727 struct c_expr ret, op;
9728 location_t op_loc = c_parser_peek_token (parser)->location;
9729 location_t exp_loc;
9730 location_t finish;
9731 ret.original_code = ERROR_MARK;
9732 ret.original_type = NULL;
9733 switch (c_parser_peek_token (parser)->type)
9734 {
9735 case CPP_PLUS_PLUS:
9736 c_parser_consume_token (parser);
9737 exp_loc = c_parser_peek_token (parser)->location;
9738 op = c_parser_cast_expression (parser, NULL);
9739
9740 op = default_function_array_read_conversion (exp_loc, op);
9741 return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
9742 case CPP_MINUS_MINUS:
9743 c_parser_consume_token (parser);
9744 exp_loc = c_parser_peek_token (parser)->location;
9745 op = c_parser_cast_expression (parser, NULL);
9746
9747 op = default_function_array_read_conversion (exp_loc, op);
9748 return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
9749 case CPP_AND:
9750 c_parser_consume_token (parser);
9751 op = c_parser_cast_expression (parser, NULL);
9752 mark_exp_read (op.value);
9753 return parser_build_unary_op (op_loc, ADDR_EXPR, op);
9754 case CPP_MULT:
9755 {
9756 c_parser_consume_token (parser);
9757 exp_loc = c_parser_peek_token (parser)->location;
9758 op = c_parser_cast_expression (parser, NULL);
9759 finish = op.get_finish ();
9760 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9761 location_t combined_loc = make_location (caret: op_loc, start: op_loc, finish);
9762 ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
9763 ret.src_range.m_start = op_loc;
9764 ret.src_range.m_finish = finish;
9765 ret.m_decimal = 0;
9766 return ret;
9767 }
9768 case CPP_PLUS:
9769 if (!c_dialect_objc () && !in_system_header_at (loc: input_location))
9770 warning_at (op_loc,
9771 OPT_Wtraditional,
9772 "traditional C rejects the unary plus operator");
9773 c_parser_consume_token (parser);
9774 exp_loc = c_parser_peek_token (parser)->location;
9775 op = c_parser_cast_expression (parser, NULL);
9776 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9777 return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
9778 case CPP_MINUS:
9779 c_parser_consume_token (parser);
9780 exp_loc = c_parser_peek_token (parser)->location;
9781 op = c_parser_cast_expression (parser, NULL);
9782 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9783 return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
9784 case CPP_COMPL:
9785 c_parser_consume_token (parser);
9786 exp_loc = c_parser_peek_token (parser)->location;
9787 op = c_parser_cast_expression (parser, NULL);
9788 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9789 return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
9790 case CPP_NOT:
9791 c_parser_consume_token (parser);
9792 exp_loc = c_parser_peek_token (parser)->location;
9793 op = c_parser_cast_expression (parser, NULL);
9794 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
9795 return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
9796 case CPP_AND_AND:
9797 /* Refer to the address of a label as a pointer. */
9798 c_parser_consume_token (parser);
9799 if (c_parser_next_token_is (parser, type: CPP_NAME))
9800 {
9801 ret.value = finish_label_address_expr
9802 (c_parser_peek_token (parser)->value, op_loc);
9803 set_c_expr_source_range (expr: &ret, start: op_loc,
9804 finish: c_parser_peek_token (parser)->get_finish ());
9805 c_parser_consume_token (parser);
9806 }
9807 else
9808 {
9809 c_parser_error (parser, gmsgid: "expected identifier");
9810 ret.set_error ();
9811 }
9812 return ret;
9813 case CPP_KEYWORD:
9814 switch (c_parser_peek_token (parser)->keyword)
9815 {
9816 case RID_SIZEOF:
9817 return c_parser_sizeof_expression (parser);
9818 case RID_ALIGNOF:
9819 return c_parser_alignof_expression (parser);
9820 case RID_BUILTIN_HAS_ATTRIBUTE:
9821 return c_parser_has_attribute_expression (parser);
9822 case RID_EXTENSION:
9823 c_parser_consume_token (parser);
9824 ext = disable_extension_diagnostics ();
9825 ret = c_parser_cast_expression (parser, NULL);
9826 restore_extension_diagnostics (flags: ext);
9827 return ret;
9828 case RID_REALPART:
9829 c_parser_consume_token (parser);
9830 exp_loc = c_parser_peek_token (parser)->location;
9831 op = c_parser_cast_expression (parser, NULL);
9832 op = default_function_array_conversion (exp_loc, op);
9833 return parser_build_unary_op (op_loc, REALPART_EXPR, op);
9834 case RID_IMAGPART:
9835 c_parser_consume_token (parser);
9836 exp_loc = c_parser_peek_token (parser)->location;
9837 op = c_parser_cast_expression (parser, NULL);
9838 op = default_function_array_conversion (exp_loc, op);
9839 return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
9840 case RID_TRANSACTION_ATOMIC:
9841 case RID_TRANSACTION_RELAXED:
9842 return c_parser_transaction_expression (parser,
9843 c_parser_peek_token (parser)->keyword);
9844 default:
9845 return c_parser_postfix_expression (parser);
9846 }
9847 default:
9848 return c_parser_postfix_expression (parser);
9849 }
9850}
9851
9852/* Parse a sizeof expression. */
9853
9854static struct c_expr
9855c_parser_sizeof_expression (c_parser *parser)
9856{
9857 struct c_expr expr;
9858 struct c_expr result;
9859 location_t expr_loc;
9860 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
9861
9862 location_t start;
9863 location_t finish = UNKNOWN_LOCATION;
9864
9865 start = c_parser_peek_token (parser)->location;
9866
9867 c_parser_consume_token (parser);
9868 c_inhibit_evaluation_warnings++;
9869 in_sizeof++;
9870 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9871 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9872 {
9873 /* Either sizeof ( type-name ) or sizeof unary-expression
9874 starting with a compound literal. */
9875 struct c_declspecs *scspecs;
9876 struct c_type_name *type_name;
9877 matching_parens parens;
9878 parens.consume_open (parser);
9879 expr_loc = c_parser_peek_token (parser)->location;
9880 scspecs = c_parser_compound_literal_scspecs (parser);
9881 type_name = c_parser_type_name (parser, alignas_ok: true);
9882 parens.skip_until_found_close (parser);
9883 finish = parser->tokens_buf[0].location;
9884 if (type_name == NULL)
9885 {
9886 struct c_expr ret;
9887 c_inhibit_evaluation_warnings--;
9888 in_sizeof--;
9889 ret.set_error ();
9890 ret.original_code = ERROR_MARK;
9891 ret.original_type = NULL;
9892 return ret;
9893 }
9894 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9895 {
9896 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
9897 type_name,
9898 expr_loc);
9899 finish = expr.get_finish ();
9900 goto sizeof_expr;
9901 }
9902 /* sizeof ( type-name ). */
9903 if (scspecs)
9904 error_at (expr_loc, "storage class specifier in %<sizeof%>");
9905 if (type_name->specs->alignas_p)
9906 error_at (type_name->specs->locations[cdw_alignas],
9907 "alignment specified for type name in %<sizeof%>");
9908 c_inhibit_evaluation_warnings--;
9909 in_sizeof--;
9910 result = c_expr_sizeof_type (expr_loc, type_name);
9911 }
9912 else
9913 {
9914 expr_loc = c_parser_peek_token (parser)->location;
9915 expr = c_parser_unary_expression (parser);
9916 finish = expr.get_finish ();
9917 sizeof_expr:
9918 c_inhibit_evaluation_warnings--;
9919 in_sizeof--;
9920 mark_exp_read (expr.value);
9921 if (TREE_CODE (expr.value) == COMPONENT_REF
9922 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
9923 error_at (expr_loc, "%<sizeof%> applied to a bit-field");
9924 result = c_expr_sizeof_expr (expr_loc, expr);
9925 }
9926 if (finish == UNKNOWN_LOCATION)
9927 finish = start;
9928 set_c_expr_source_range (expr: &result, start, finish);
9929 return result;
9930}
9931
9932/* Parse an alignof expression. */
9933
9934static struct c_expr
9935c_parser_alignof_expression (c_parser *parser)
9936{
9937 struct c_expr expr;
9938 location_t start_loc = c_parser_peek_token (parser)->location;
9939 location_t end_loc;
9940 tree alignof_spelling = c_parser_peek_token (parser)->value;
9941 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
9942 bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
9943 s2: "_Alignof") == 0
9944 || strcmp (IDENTIFIER_POINTER (alignof_spelling),
9945 s2: "alignof") == 0);
9946 /* A diagnostic is not required for the use of this identifier in
9947 the implementation namespace; only diagnose it for the C11 or C23
9948 spelling because of existing code using the other spellings. */
9949 if (is_c11_alignof)
9950 {
9951 if (flag_isoc99)
9952 pedwarn_c99 (start_loc, opt: OPT_Wpedantic, "ISO C99 does not support %qE",
9953 alignof_spelling);
9954 else
9955 pedwarn_c99 (start_loc, opt: OPT_Wpedantic, "ISO C90 does not support %qE",
9956 alignof_spelling);
9957 }
9958 c_parser_consume_token (parser);
9959 c_inhibit_evaluation_warnings++;
9960 in_alignof++;
9961 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
9962 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
9963 {
9964 /* Either __alignof__ ( type-name ) or __alignof__
9965 unary-expression starting with a compound literal. */
9966 location_t loc;
9967 struct c_declspecs *scspecs;
9968 struct c_type_name *type_name;
9969 struct c_expr ret;
9970 matching_parens parens;
9971 parens.consume_open (parser);
9972 loc = c_parser_peek_token (parser)->location;
9973 scspecs = c_parser_compound_literal_scspecs (parser);
9974 type_name = c_parser_type_name (parser, alignas_ok: true);
9975 end_loc = c_parser_peek_token (parser)->location;
9976 parens.skip_until_found_close (parser);
9977 if (type_name == NULL)
9978 {
9979 struct c_expr ret;
9980 c_inhibit_evaluation_warnings--;
9981 in_alignof--;
9982 ret.set_error ();
9983 ret.original_code = ERROR_MARK;
9984 ret.original_type = NULL;
9985 return ret;
9986 }
9987 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
9988 {
9989 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
9990 type_name,
9991 loc);
9992 goto alignof_expr;
9993 }
9994 /* alignof ( type-name ). */
9995 if (scspecs)
9996 error_at (loc, "storage class specifier in %qE", alignof_spelling);
9997 if (type_name->specs->alignas_p)
9998 error_at (type_name->specs->locations[cdw_alignas],
9999 "alignment specified for type name in %qE",
10000 alignof_spelling);
10001 c_inhibit_evaluation_warnings--;
10002 in_alignof--;
10003 ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
10004 NULL, NULL),
10005 false, is_c11_alignof, 1);
10006 ret.original_code = ERROR_MARK;
10007 ret.original_type = NULL;
10008 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10009 ret.m_decimal = 0;
10010 return ret;
10011 }
10012 else
10013 {
10014 struct c_expr ret;
10015 expr = c_parser_unary_expression (parser);
10016 end_loc = expr.src_range.m_finish;
10017 alignof_expr:
10018 mark_exp_read (expr.value);
10019 c_inhibit_evaluation_warnings--;
10020 in_alignof--;
10021 if (is_c11_alignof)
10022 pedwarn (start_loc,
10023 OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
10024 alignof_spelling);
10025 ret.value = c_alignof_expr (start_loc, expr.value);
10026 ret.original_code = ERROR_MARK;
10027 ret.original_type = NULL;
10028 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10029 ret.m_decimal = 0;
10030 return ret;
10031 }
10032}
10033
10034/* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
10035 expression. */
10036
10037static struct c_expr
10038c_parser_has_attribute_expression (c_parser *parser)
10039{
10040 gcc_assert (c_parser_next_token_is_keyword (parser,
10041 RID_BUILTIN_HAS_ATTRIBUTE));
10042 location_t start = c_parser_peek_token (parser)->location;
10043 c_parser_consume_token (parser);
10044
10045 c_inhibit_evaluation_warnings++;
10046
10047 matching_parens parens;
10048 if (!parens.require_open (parser))
10049 {
10050 c_inhibit_evaluation_warnings--;
10051 in_typeof--;
10052
10053 struct c_expr result;
10054 result.set_error ();
10055 result.original_code = ERROR_MARK;
10056 result.original_type = NULL;
10057 return result;
10058 }
10059
10060 /* Treat the type argument the same way as in typeof for the purposes
10061 of warnings. FIXME: Generalize this so the warning refers to
10062 __builtin_has_attribute rather than typeof. */
10063 in_typeof++;
10064
10065 /* The first operand: one of DECL, EXPR, or TYPE. */
10066 tree oper = NULL_TREE;
10067 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
10068 {
10069 struct c_type_name *tname = c_parser_type_name (parser);
10070 in_typeof--;
10071 if (tname)
10072 {
10073 oper = groktypename (tname, NULL, NULL);
10074 pop_maybe_used (c_type_variably_modified_p (t: oper));
10075 }
10076 }
10077 else
10078 {
10079 struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
10080 c_inhibit_evaluation_warnings--;
10081 in_typeof--;
10082 if (cexpr.value != error_mark_node)
10083 {
10084 mark_exp_read (cexpr.value);
10085 oper = cexpr.value;
10086 tree etype = TREE_TYPE (oper);
10087 bool was_vm = c_type_variably_modified_p (t: etype);
10088 /* This is returned with the type so that when the type is
10089 evaluated, this can be evaluated. */
10090 if (was_vm)
10091 oper = c_fully_fold (oper, false, NULL);
10092 pop_maybe_used (was_vm);
10093 }
10094 }
10095
10096 struct c_expr result;
10097 result.original_code = ERROR_MARK;
10098 result.original_type = NULL;
10099
10100 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10101 {
10102 /* Consume the closing parenthesis if that's the next token
10103 in the likely case the built-in was invoked with fewer
10104 than two arguments. */
10105 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10106 c_parser_consume_token (parser);
10107 c_inhibit_evaluation_warnings--;
10108 result.set_error ();
10109 return result;
10110 }
10111
10112 bool save_translate_strings_p = parser->translate_strings_p;
10113
10114 location_t atloc = c_parser_peek_token (parser)->location;
10115 /* Parse a single attribute. Require no leading comma and do not
10116 allow empty attributes. */
10117 tree attr = c_parser_gnu_attribute (parser, NULL_TREE, expect_comma: false, empty_ok: false);
10118
10119 parser->translate_strings_p = save_translate_strings_p;
10120
10121 location_t finish = c_parser_peek_token (parser)->location;
10122 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10123 c_parser_consume_token (parser);
10124 else
10125 {
10126 c_parser_error (parser, gmsgid: "expected identifier");
10127 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10128
10129 result.set_error ();
10130 return result;
10131 }
10132
10133 if (!attr)
10134 {
10135 error_at (atloc, "expected identifier");
10136 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10137 msgid: "expected %<)%>");
10138 result.set_error ();
10139 return result;
10140 }
10141
10142 result.original_code = INTEGER_CST;
10143 result.original_type = boolean_type_node;
10144
10145 if (has_attribute (atloc, oper, attr, default_conversion))
10146 result.value = boolean_true_node;
10147 else
10148 result.value = boolean_false_node;
10149
10150 set_c_expr_source_range (expr: &result, start, finish);
10151 result.m_decimal = 0;
10152 return result;
10153}
10154
10155/* Helper function to read arguments of builtins which are interfaces
10156 for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
10157 others. The name of the builtin is passed using BNAME parameter.
10158 Function returns true if there were no errors while parsing and
10159 stores the arguments in CEXPR_LIST. If it returns true,
10160 *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
10161 parenthesis. */
10162static bool
10163c_parser_get_builtin_args (c_parser *parser, const char *bname,
10164 vec<c_expr_t, va_gc> **ret_cexpr_list,
10165 bool choose_expr_p,
10166 location_t *out_close_paren_loc)
10167{
10168 location_t loc = c_parser_peek_token (parser)->location;
10169 vec<c_expr_t, va_gc> *cexpr_list;
10170 c_expr_t expr;
10171 bool saved_force_folding_builtin_constant_p;
10172
10173 *ret_cexpr_list = NULL;
10174 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
10175 {
10176 error_at (loc, "cannot take address of %qs", bname);
10177 return false;
10178 }
10179
10180 c_parser_consume_token (parser);
10181
10182 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10183 {
10184 *out_close_paren_loc = c_parser_peek_token (parser)->location;
10185 c_parser_consume_token (parser);
10186 return true;
10187 }
10188
10189 saved_force_folding_builtin_constant_p
10190 = force_folding_builtin_constant_p;
10191 force_folding_builtin_constant_p |= choose_expr_p;
10192 expr = c_parser_expr_no_commas (parser, NULL);
10193 force_folding_builtin_constant_p
10194 = saved_force_folding_builtin_constant_p;
10195 vec_alloc (v&: cexpr_list, nelems: 1);
10196 vec_safe_push (v&: cexpr_list, obj: expr);
10197 while (c_parser_next_token_is (parser, type: CPP_COMMA))
10198 {
10199 c_parser_consume_token (parser);
10200 expr = c_parser_expr_no_commas (parser, NULL);
10201 vec_safe_push (v&: cexpr_list, obj: expr);
10202 }
10203
10204 *out_close_paren_loc = c_parser_peek_token (parser)->location;
10205 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
10206 return false;
10207
10208 *ret_cexpr_list = cexpr_list;
10209 return true;
10210}
10211
10212/* This represents a single generic-association. */
10213
10214struct c_generic_association
10215{
10216 /* The location of the starting token of the type. */
10217 location_t type_location;
10218 /* The association's type, or NULL_TREE for 'default'. */
10219 tree type;
10220 /* The association's expression. */
10221 struct c_expr expression;
10222};
10223
10224/* Parse a generic-selection. (C11 6.5.1.1).
10225
10226 generic-selection:
10227 _Generic ( assignment-expression , generic-assoc-list )
10228
10229 generic-assoc-list:
10230 generic-association
10231 generic-assoc-list , generic-association
10232
10233 generic-association:
10234 type-name : assignment-expression
10235 default : assignment-expression
10236*/
10237
10238static struct c_expr
10239c_parser_generic_selection (c_parser *parser)
10240{
10241 struct c_expr selector, error_expr;
10242 tree selector_type;
10243 struct c_generic_association matched_assoc;
10244 int match_found = -1;
10245 location_t generic_loc, selector_loc;
10246
10247 error_expr.original_code = ERROR_MARK;
10248 error_expr.original_type = NULL;
10249 error_expr.set_error ();
10250 matched_assoc.type_location = UNKNOWN_LOCATION;
10251 matched_assoc.type = NULL_TREE;
10252 matched_assoc.expression = error_expr;
10253
10254 gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
10255 generic_loc = c_parser_peek_token (parser)->location;
10256 c_parser_consume_token (parser);
10257 if (flag_isoc99)
10258 pedwarn_c99 (generic_loc, opt: OPT_Wpedantic,
10259 "ISO C99 does not support %<_Generic%>");
10260 else
10261 pedwarn_c99 (generic_loc, opt: OPT_Wpedantic,
10262 "ISO C90 does not support %<_Generic%>");
10263
10264 matching_parens parens;
10265 if (!parens.require_open (parser))
10266 return error_expr;
10267
10268 c_inhibit_evaluation_warnings++;
10269 selector_loc = c_parser_peek_token (parser)->location;
10270 selector = c_parser_expr_no_commas (parser, NULL);
10271 selector = default_function_array_conversion (selector_loc, selector);
10272 c_inhibit_evaluation_warnings--;
10273
10274 if (selector.value == error_mark_node)
10275 {
10276 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10277 return selector;
10278 }
10279 mark_exp_read (selector.value);
10280 selector_type = TREE_TYPE (selector.value);
10281 /* In ISO C terms, rvalues (including the controlling expression of
10282 _Generic) do not have qualified types. */
10283 if (TREE_CODE (selector_type) != ARRAY_TYPE)
10284 selector_type = TYPE_MAIN_VARIANT (selector_type);
10285 /* In ISO C terms, _Noreturn is not part of the type of expressions
10286 such as &abort, but in GCC it is represented internally as a type
10287 qualifier. */
10288 if (FUNCTION_POINTER_TYPE_P (selector_type)
10289 && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
10290 selector_type
10291 = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
10292
10293 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10294 {
10295 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10296 return error_expr;
10297 }
10298
10299 auto_vec<c_generic_association> associations;
10300 while (1)
10301 {
10302 struct c_generic_association assoc, *iter;
10303 unsigned int ix;
10304 c_token *token = c_parser_peek_token (parser);
10305
10306 assoc.type_location = token->location;
10307 if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
10308 {
10309 c_parser_consume_token (parser);
10310 assoc.type = NULL_TREE;
10311 }
10312 else
10313 {
10314 struct c_type_name *type_name;
10315
10316 type_name = c_parser_type_name (parser);
10317 if (type_name == NULL)
10318 {
10319 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10320 return error_expr;
10321 }
10322 assoc.type = groktypename (type_name, NULL, NULL);
10323 if (assoc.type == error_mark_node)
10324 {
10325 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10326 return error_expr;
10327 }
10328
10329 if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
10330 error_at (assoc.type_location,
10331 "%<_Generic%> association has function type");
10332 else if (!COMPLETE_TYPE_P (assoc.type))
10333 error_at (assoc.type_location,
10334 "%<_Generic%> association has incomplete type");
10335
10336 if (c_type_variably_modified_p (t: assoc.type))
10337 error_at (assoc.type_location,
10338 "%<_Generic%> association has "
10339 "variable length type");
10340 }
10341
10342 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
10343 {
10344 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10345 return error_expr;
10346 }
10347
10348 bool match = assoc.type == NULL_TREE
10349 || comptypes (assoc.type, selector_type);
10350
10351 if (!match)
10352 c_inhibit_evaluation_warnings++;
10353
10354 assoc.expression = c_parser_expr_no_commas (parser, NULL);
10355
10356 if (!match)
10357 c_inhibit_evaluation_warnings--;
10358
10359 if (assoc.expression.value == error_mark_node)
10360 {
10361 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10362 return error_expr;
10363 }
10364
10365 for (ix = 0; associations.iterate (ix, ptr: &iter); ++ix)
10366 {
10367 if (assoc.type == NULL_TREE)
10368 {
10369 if (iter->type == NULL_TREE)
10370 {
10371 error_at (assoc.type_location,
10372 "duplicate %<default%> case in %<_Generic%>");
10373 inform (iter->type_location, "original %<default%> is here");
10374 }
10375 }
10376 else if (iter->type != NULL_TREE)
10377 {
10378 if (comptypes (assoc.type, iter->type))
10379 {
10380 error_at (assoc.type_location,
10381 "%<_Generic%> specifies two compatible types");
10382 inform (iter->type_location, "compatible type is here");
10383 }
10384 }
10385 }
10386
10387 if (assoc.type == NULL_TREE)
10388 {
10389 if (match_found < 0)
10390 {
10391 matched_assoc = assoc;
10392 match_found = associations.length ();
10393 }
10394 }
10395 else if (match)
10396 {
10397 if (match_found < 0 || matched_assoc.type == NULL_TREE)
10398 {
10399 matched_assoc = assoc;
10400 match_found = associations.length ();
10401 }
10402 else
10403 {
10404 error_at (assoc.type_location,
10405 "%<_Generic%> selector matches multiple associations");
10406 inform (matched_assoc.type_location,
10407 "other match is here");
10408 }
10409 }
10410
10411 associations.safe_push (obj: assoc);
10412
10413 if (c_parser_peek_token (parser)->type != CPP_COMMA)
10414 break;
10415 c_parser_consume_token (parser);
10416 }
10417
10418 unsigned int ix;
10419 struct c_generic_association *iter;
10420 FOR_EACH_VEC_ELT (associations, ix, iter)
10421 if (ix != (unsigned) match_found)
10422 mark_exp_read (iter->expression.value);
10423
10424 if (!parens.require_close (parser))
10425 {
10426 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10427 return error_expr;
10428 }
10429
10430 if (match_found < 0)
10431 {
10432 error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
10433 "compatible with any association",
10434 selector_type);
10435 return error_expr;
10436 }
10437
10438 return matched_assoc.expression;
10439}
10440
10441/* Check the validity of a function pointer argument *EXPR (argument
10442 position POS) to __builtin_tgmath. Return the number of function
10443 arguments if possibly valid; return 0 having reported an error if
10444 not valid. */
10445
10446static unsigned int
10447check_tgmath_function (c_expr *expr, unsigned int pos)
10448{
10449 tree type = TREE_TYPE (expr->value);
10450 if (!FUNCTION_POINTER_TYPE_P (type))
10451 {
10452 error_at (expr->get_location (),
10453 "argument %u of %<__builtin_tgmath%> is not a function pointer",
10454 pos);
10455 return 0;
10456 }
10457 type = TREE_TYPE (type);
10458 if (!prototype_p (type))
10459 {
10460 error_at (expr->get_location (),
10461 "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
10462 return 0;
10463 }
10464 if (stdarg_p (type))
10465 {
10466 error_at (expr->get_location (),
10467 "argument %u of %<__builtin_tgmath%> has variable arguments",
10468 pos);
10469 return 0;
10470 }
10471 unsigned int nargs = 0;
10472 function_args_iterator iter;
10473 tree t;
10474 FOREACH_FUNCTION_ARGS (type, t, iter)
10475 {
10476 if (t == void_type_node)
10477 break;
10478 nargs++;
10479 }
10480 if (nargs == 0)
10481 {
10482 error_at (expr->get_location (),
10483 "argument %u of %<__builtin_tgmath%> has no arguments", pos);
10484 return 0;
10485 }
10486 return nargs;
10487}
10488
10489/* Ways in which a parameter or return value of a type-generic macro
10490 may vary between the different functions the macro may call. */
10491enum tgmath_parm_kind
10492 {
10493 tgmath_fixed, tgmath_real, tgmath_complex
10494 };
10495
10496/* Helper function for c_parser_postfix_expression. Parse predefined
10497 identifiers. */
10498
10499static struct c_expr
10500c_parser_predefined_identifier (c_parser *parser)
10501{
10502 location_t loc = c_parser_peek_token (parser)->location;
10503 switch (c_parser_peek_token (parser)->keyword)
10504 {
10505 case RID_FUNCTION_NAME:
10506 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
10507 "identifier", "__FUNCTION__");
10508 break;
10509 case RID_PRETTY_FUNCTION_NAME:
10510 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
10511 "identifier", "__PRETTY_FUNCTION__");
10512 break;
10513 case RID_C99_FUNCTION_NAME:
10514 pedwarn_c90 (loc, opt: OPT_Wpedantic, "ISO C90 does not support "
10515 "%<__func__%> predefined identifier");
10516 break;
10517 default:
10518 gcc_unreachable ();
10519 }
10520
10521 struct c_expr expr;
10522 expr.original_code = ERROR_MARK;
10523 expr.original_type = NULL;
10524 expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
10525 c_parser_peek_token (parser)->value);
10526 set_c_expr_source_range (expr: &expr, start: loc, finish: loc);
10527 expr.m_decimal = 0;
10528 c_parser_consume_token (parser);
10529 return expr;
10530}
10531
10532/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
10533 C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
10534 call c_parser_postfix_expression_after_paren_type on encountering them.
10535
10536 postfix-expression:
10537 primary-expression
10538 postfix-expression [ expression ]
10539 postfix-expression ( argument-expression-list[opt] )
10540 postfix-expression . identifier
10541 postfix-expression -> identifier
10542 postfix-expression ++
10543 postfix-expression --
10544 ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
10545 ( storage-class-specifiers[opt] type-name ) { initializer-list , }
10546
10547 argument-expression-list:
10548 argument-expression
10549 argument-expression-list , argument-expression
10550
10551 primary-expression:
10552 identifier
10553 constant
10554 string-literal
10555 ( expression )
10556 generic-selection
10557
10558 GNU extensions:
10559
10560 primary-expression:
10561 __func__
10562 (treated as a keyword in GNU C)
10563 __FUNCTION__
10564 __PRETTY_FUNCTION__
10565 ( compound-statement )
10566 __builtin_va_arg ( assignment-expression , type-name )
10567 __builtin_offsetof ( type-name , offsetof-member-designator )
10568 __builtin_choose_expr ( assignment-expression ,
10569 assignment-expression ,
10570 assignment-expression )
10571 __builtin_types_compatible_p ( type-name , type-name )
10572 __builtin_tgmath ( expr-list )
10573 __builtin_complex ( assignment-expression , assignment-expression )
10574 __builtin_shuffle ( assignment-expression , assignment-expression )
10575 __builtin_shuffle ( assignment-expression ,
10576 assignment-expression ,
10577 assignment-expression, )
10578 __builtin_convertvector ( assignment-expression , type-name )
10579 __builtin_assoc_barrier ( assignment-expression )
10580
10581 offsetof-member-designator:
10582 identifier
10583 offsetof-member-designator . identifier
10584 offsetof-member-designator [ expression ]
10585
10586 Objective-C:
10587
10588 primary-expression:
10589 [ objc-receiver objc-message-args ]
10590 @selector ( objc-selector-arg )
10591 @protocol ( identifier )
10592 @encode ( type-name )
10593 objc-string-literal
10594 Classname . identifier
10595*/
10596
10597static struct c_expr
10598c_parser_postfix_expression (c_parser *parser)
10599{
10600 struct c_expr expr, e1;
10601 struct c_type_name *t1, *t2;
10602 location_t loc = c_parser_peek_token (parser)->location;
10603 source_range tok_range = c_parser_peek_token (parser)->get_range ();
10604 expr.original_code = ERROR_MARK;
10605 expr.original_type = NULL;
10606 expr.m_decimal = 0;
10607 switch (c_parser_peek_token (parser)->type)
10608 {
10609 case CPP_NUMBER:
10610 expr.value = c_parser_peek_token (parser)->value;
10611 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10612 loc = c_parser_peek_token (parser)->location;
10613 expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
10614 c_parser_consume_token (parser);
10615 if (TREE_CODE (expr.value) == FIXED_CST
10616 && !targetm.fixed_point_supported_p ())
10617 {
10618 error_at (loc, "fixed-point types not supported for this target");
10619 expr.set_error ();
10620 }
10621 break;
10622 case CPP_CHAR:
10623 case CPP_CHAR16:
10624 case CPP_CHAR32:
10625 case CPP_UTF8CHAR:
10626 case CPP_WCHAR:
10627 expr.value = c_parser_peek_token (parser)->value;
10628 /* For the purpose of warning when a pointer is compared with
10629 a zero character constant. */
10630 expr.original_type = char_type_node;
10631 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10632 c_parser_consume_token (parser);
10633 break;
10634 case CPP_STRING:
10635 case CPP_STRING16:
10636 case CPP_STRING32:
10637 case CPP_WSTRING:
10638 case CPP_UTF8STRING:
10639 expr = c_parser_string_literal (parser, translate: parser->translate_strings_p,
10640 wide_ok: true);
10641 break;
10642 case CPP_OBJC_STRING:
10643 gcc_assert (c_dialect_objc ());
10644 expr.value
10645 = objc_build_string_object (c_parser_peek_token (parser)->value);
10646 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10647 c_parser_consume_token (parser);
10648 break;
10649 case CPP_NAME:
10650 switch (c_parser_peek_token (parser)->id_kind)
10651 {
10652 case C_ID_ID:
10653 {
10654 tree id = c_parser_peek_token (parser)->value;
10655 c_parser_consume_token (parser);
10656 expr.value = build_external_ref (loc, id,
10657 (c_parser_peek_token (parser)->type
10658 == CPP_OPEN_PAREN),
10659 &expr.original_type);
10660 set_c_expr_source_range (expr: &expr, src_range: tok_range);
10661 break;
10662 }
10663 case C_ID_CLASSNAME:
10664 {
10665 /* Here we parse the Objective-C 2.0 Class.name dot
10666 syntax. */
10667 tree class_name = c_parser_peek_token (parser)->value;
10668 tree component;
10669 c_parser_consume_token (parser);
10670 gcc_assert (c_dialect_objc ());
10671 if (!c_parser_require (parser, type: CPP_DOT, msgid: "expected %<.%>"))
10672 {
10673 expr.set_error ();
10674 break;
10675 }
10676 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
10677 {
10678 c_parser_error (parser, gmsgid: "expected identifier");
10679 expr.set_error ();
10680 break;
10681 }
10682 c_token *component_tok = c_parser_peek_token (parser);
10683 component = component_tok->value;
10684 location_t end_loc = component_tok->get_finish ();
10685 c_parser_consume_token (parser);
10686 expr.value = objc_build_class_component_ref (class_name,
10687 component);
10688 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
10689 break;
10690 }
10691 default:
10692 c_parser_error (parser, gmsgid: "expected expression");
10693 expr.set_error ();
10694 break;
10695 }
10696 break;
10697 case CPP_OPEN_PAREN:
10698 /* A parenthesized expression, statement expression or compound
10699 literal. */
10700 if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
10701 {
10702 /* A statement expression. */
10703 tree stmt;
10704 location_t brace_loc;
10705 c_parser_consume_token (parser);
10706 brace_loc = c_parser_peek_token (parser)->location;
10707 c_parser_consume_token (parser);
10708 /* If we've not yet started the current function's statement list,
10709 or we're in the parameter scope of an old-style function
10710 declaration, statement expressions are not allowed. */
10711 if (!building_stmt_list_p () || old_style_parameter_scope ())
10712 {
10713 error_at (loc, "braced-group within expression allowed "
10714 "only inside a function");
10715 parser->error = true;
10716 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
10717 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10718 expr.set_error ();
10719 break;
10720 }
10721 stmt = c_begin_stmt_expr ();
10722 c_parser_compound_statement_nostart (parser);
10723 location_t close_loc = c_parser_peek_token (parser)->location;
10724 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10725 msgid: "expected %<)%>");
10726 pedwarn (loc, OPT_Wpedantic,
10727 "ISO C forbids braced-groups within expressions");
10728 expr.value = c_finish_stmt_expr (brace_loc, stmt);
10729 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
10730 mark_exp_read (expr.value);
10731 }
10732 else
10733 {
10734 /* A parenthesized expression. */
10735 location_t loc_open_paren = c_parser_peek_token (parser)->location;
10736 c_parser_consume_token (parser);
10737 expr = c_parser_expression (parser);
10738 if (TREE_CODE (expr.value) == MODIFY_EXPR)
10739 suppress_warning (expr.value, OPT_Wparentheses);
10740 if (expr.original_code != C_MAYBE_CONST_EXPR
10741 && expr.original_code != SIZEOF_EXPR)
10742 expr.original_code = ERROR_MARK;
10743 /* Remember that we saw ( ) around the sizeof. */
10744 if (expr.original_code == SIZEOF_EXPR)
10745 expr.original_code = PAREN_SIZEOF_EXPR;
10746 /* Don't change EXPR.ORIGINAL_TYPE. */
10747 location_t loc_close_paren = c_parser_peek_token (parser)->location;
10748 set_c_expr_source_range (expr: &expr, start: loc_open_paren, finish: loc_close_paren);
10749 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10750 msgid: "expected %<)%>", matching_location: loc_open_paren);
10751 }
10752 break;
10753 case CPP_KEYWORD:
10754 switch (c_parser_peek_token (parser)->keyword)
10755 {
10756 case RID_FUNCTION_NAME:
10757 case RID_PRETTY_FUNCTION_NAME:
10758 case RID_C99_FUNCTION_NAME:
10759 expr = c_parser_predefined_identifier (parser);
10760 break;
10761 case RID_VA_ARG:
10762 {
10763 location_t start_loc = loc;
10764 c_parser_consume_token (parser);
10765 matching_parens parens;
10766 if (!parens.require_open (parser))
10767 {
10768 expr.set_error ();
10769 break;
10770 }
10771 e1 = c_parser_expr_no_commas (parser, NULL);
10772 mark_exp_read (e1.value);
10773 e1.value = c_fully_fold (e1.value, false, NULL);
10774 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10775 {
10776 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10777 expr.set_error ();
10778 break;
10779 }
10780 loc = c_parser_peek_token (parser)->location;
10781 t1 = c_parser_type_name (parser);
10782 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
10783 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10784 msgid: "expected %<)%>");
10785 if (t1 == NULL)
10786 {
10787 expr.set_error ();
10788 }
10789 else
10790 {
10791 tree type_expr = NULL_TREE;
10792 expr.value = c_build_va_arg (start_loc, e1.value, loc,
10793 groktypename (t1, &type_expr, NULL));
10794 if (type_expr)
10795 {
10796 expr.value = build2 (C_MAYBE_CONST_EXPR,
10797 TREE_TYPE (expr.value), type_expr,
10798 expr.value);
10799 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
10800 }
10801 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
10802 }
10803 }
10804 break;
10805 case RID_OFFSETOF:
10806 {
10807 c_parser_consume_token (parser);
10808 matching_parens parens;
10809 if (!parens.require_open (parser))
10810 {
10811 expr.set_error ();
10812 break;
10813 }
10814 t1 = c_parser_type_name (parser);
10815 if (t1 == NULL)
10816 parser->error = true;
10817 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10818 gcc_assert (parser->error);
10819 if (parser->error)
10820 {
10821 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10822 expr.set_error ();
10823 break;
10824 }
10825 tree type = groktypename (t1, NULL, NULL);
10826 tree offsetof_ref;
10827 if (type == error_mark_node)
10828 offsetof_ref = error_mark_node;
10829 else
10830 {
10831 offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
10832 SET_EXPR_LOCATION (offsetof_ref, loc);
10833 }
10834 /* Parse the second argument to __builtin_offsetof. We
10835 must have one identifier, and beyond that we want to
10836 accept sub structure and sub array references. */
10837 if (c_parser_next_token_is (parser, type: CPP_NAME))
10838 {
10839 c_token *comp_tok = c_parser_peek_token (parser);
10840 offsetof_ref
10841 = build_component_ref (loc, offsetof_ref, comp_tok->value,
10842 comp_tok->location, UNKNOWN_LOCATION);
10843 c_parser_consume_token (parser);
10844 while (c_parser_next_token_is (parser, type: CPP_DOT)
10845 || c_parser_next_token_is (parser,
10846 type: CPP_OPEN_SQUARE)
10847 || c_parser_next_token_is (parser,
10848 type: CPP_DEREF))
10849 {
10850 if (c_parser_next_token_is (parser, type: CPP_DEREF))
10851 {
10852 loc = c_parser_peek_token (parser)->location;
10853 offsetof_ref = build_array_ref (loc,
10854 offsetof_ref,
10855 integer_zero_node);
10856 goto do_dot;
10857 }
10858 else if (c_parser_next_token_is (parser, type: CPP_DOT))
10859 {
10860 do_dot:
10861 c_parser_consume_token (parser);
10862 if (c_parser_next_token_is_not (parser,
10863 type: CPP_NAME))
10864 {
10865 c_parser_error (parser, gmsgid: "expected identifier");
10866 break;
10867 }
10868 c_token *comp_tok = c_parser_peek_token (parser);
10869 offsetof_ref
10870 = build_component_ref (loc, offsetof_ref,
10871 comp_tok->value,
10872 comp_tok->location,
10873 UNKNOWN_LOCATION);
10874 c_parser_consume_token (parser);
10875 }
10876 else
10877 {
10878 struct c_expr ce;
10879 tree idx;
10880 loc = c_parser_peek_token (parser)->location;
10881 c_parser_consume_token (parser);
10882 ce = c_parser_expression (parser);
10883 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
10884 idx = ce.value;
10885 idx = c_fully_fold (idx, false, NULL);
10886 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
10887 msgid: "expected %<]%>");
10888 offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
10889 }
10890 }
10891 }
10892 else
10893 c_parser_error (parser, gmsgid: "expected identifier");
10894 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
10895 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10896 msgid: "expected %<)%>");
10897 expr.value = fold_offsetof (offsetof_ref);
10898 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
10899 }
10900 break;
10901 case RID_CHOOSE_EXPR:
10902 {
10903 vec<c_expr_t, va_gc> *cexpr_list;
10904 c_expr_t *e1_p, *e2_p, *e3_p;
10905 tree c;
10906 location_t close_paren_loc;
10907
10908 c_parser_consume_token (parser);
10909 if (!c_parser_get_builtin_args (parser,
10910 bname: "__builtin_choose_expr",
10911 ret_cexpr_list: &cexpr_list, choose_expr_p: true,
10912 out_close_paren_loc: &close_paren_loc))
10913 {
10914 expr.set_error ();
10915 break;
10916 }
10917
10918 if (vec_safe_length (v: cexpr_list) != 3)
10919 {
10920 error_at (loc, "wrong number of arguments to "
10921 "%<__builtin_choose_expr%>");
10922 expr.set_error ();
10923 break;
10924 }
10925
10926 e1_p = &(*cexpr_list)[0];
10927 e2_p = &(*cexpr_list)[1];
10928 e3_p = &(*cexpr_list)[2];
10929
10930 c = e1_p->value;
10931 mark_exp_read (e2_p->value);
10932 mark_exp_read (e3_p->value);
10933 if (TREE_CODE (c) != INTEGER_CST
10934 || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
10935 error_at (loc,
10936 "first argument to %<__builtin_choose_expr%> not"
10937 " a constant");
10938 constant_expression_warning (c);
10939 expr = integer_zerop (c) ? *e3_p : *e2_p;
10940 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
10941 break;
10942 }
10943 case RID_TYPES_COMPATIBLE_P:
10944 {
10945 c_parser_consume_token (parser);
10946 matching_parens parens;
10947 if (!parens.require_open (parser))
10948 {
10949 expr.set_error ();
10950 break;
10951 }
10952 t1 = c_parser_type_name (parser);
10953 if (t1 == NULL)
10954 {
10955 expr.set_error ();
10956 break;
10957 }
10958 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10959 {
10960 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10961 expr.set_error ();
10962 break;
10963 }
10964 t2 = c_parser_type_name (parser);
10965 if (t2 == NULL)
10966 {
10967 expr.set_error ();
10968 break;
10969 }
10970 location_t close_paren_loc = c_parser_peek_token (parser)->location;
10971 parens.skip_until_found_close (parser);
10972 tree e1, e2;
10973 e1 = groktypename (t1, NULL, NULL);
10974 e2 = groktypename (t2, NULL, NULL);
10975 if (e1 == error_mark_node || e2 == error_mark_node)
10976 {
10977 expr.set_error ();
10978 break;
10979 }
10980
10981 e1 = TYPE_MAIN_VARIANT (e1);
10982 e2 = TYPE_MAIN_VARIANT (e2);
10983
10984 expr.value
10985 = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
10986 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
10987 }
10988 break;
10989 case RID_BUILTIN_TGMATH:
10990 {
10991 vec<c_expr_t, va_gc> *cexpr_list;
10992 location_t close_paren_loc;
10993
10994 c_parser_consume_token (parser);
10995 if (!c_parser_get_builtin_args (parser,
10996 bname: "__builtin_tgmath",
10997 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
10998 out_close_paren_loc: &close_paren_loc))
10999 {
11000 expr.set_error ();
11001 break;
11002 }
11003
11004 if (vec_safe_length (v: cexpr_list) < 3)
11005 {
11006 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11007 expr.set_error ();
11008 break;
11009 }
11010
11011 unsigned int i;
11012 c_expr_t *p;
11013 FOR_EACH_VEC_ELT (*cexpr_list, i, p)
11014 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11015 unsigned int nargs = check_tgmath_function (expr: &(*cexpr_list)[0], pos: 1);
11016 if (nargs == 0)
11017 {
11018 expr.set_error ();
11019 break;
11020 }
11021 if (vec_safe_length (v: cexpr_list) < nargs)
11022 {
11023 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11024 expr.set_error ();
11025 break;
11026 }
11027 unsigned int num_functions = vec_safe_length (v: cexpr_list) - nargs;
11028 if (num_functions < 2)
11029 {
11030 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
11031 expr.set_error ();
11032 break;
11033 }
11034
11035 /* The first NUM_FUNCTIONS expressions are the function
11036 pointers. The remaining NARGS expressions are the
11037 arguments that are to be passed to one of those
11038 functions, chosen following <tgmath.h> rules. */
11039 for (unsigned int j = 1; j < num_functions; j++)
11040 {
11041 unsigned int this_nargs
11042 = check_tgmath_function (expr: &(*cexpr_list)[j], pos: j + 1);
11043 if (this_nargs == 0)
11044 {
11045 expr.set_error ();
11046 goto out;
11047 }
11048 if (this_nargs != nargs)
11049 {
11050 error_at ((*cexpr_list)[j].get_location (),
11051 "argument %u of %<__builtin_tgmath%> has "
11052 "wrong number of arguments", j + 1);
11053 expr.set_error ();
11054 goto out;
11055 }
11056 }
11057
11058 /* The functions all have the same number of arguments.
11059 Determine whether arguments and return types vary in
11060 ways permitted for <tgmath.h> functions. */
11061 /* The first entry in each of these vectors is for the
11062 return type, subsequent entries for parameter
11063 types. */
11064 auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
11065 auto_vec<tree> parm_first (nargs + 1);
11066 auto_vec<bool> parm_complex (nargs + 1);
11067 auto_vec<bool> parm_varies (nargs + 1);
11068 tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
11069 tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
11070 parm_first.quick_push (obj: first_ret);
11071 parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
11072 parm_varies.quick_push (obj: false);
11073 function_args_iterator iter;
11074 tree t;
11075 unsigned int argpos;
11076 FOREACH_FUNCTION_ARGS (first_type, t, iter)
11077 {
11078 if (t == void_type_node)
11079 break;
11080 parm_first.quick_push (TYPE_MAIN_VARIANT (t));
11081 parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
11082 parm_varies.quick_push (obj: false);
11083 }
11084 for (unsigned int j = 1; j < num_functions; j++)
11085 {
11086 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11087 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
11088 if (ret != parm_first[0])
11089 {
11090 parm_varies[0] = true;
11091 if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
11092 && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
11093 {
11094 error_at ((*cexpr_list)[0].get_location (),
11095 "invalid type-generic return type for "
11096 "argument %u of %<__builtin_tgmath%>",
11097 1);
11098 expr.set_error ();
11099 goto out;
11100 }
11101 if (!SCALAR_FLOAT_TYPE_P (ret)
11102 && !COMPLEX_FLOAT_TYPE_P (ret))
11103 {
11104 error_at ((*cexpr_list)[j].get_location (),
11105 "invalid type-generic return type for "
11106 "argument %u of %<__builtin_tgmath%>",
11107 j + 1);
11108 expr.set_error ();
11109 goto out;
11110 }
11111 }
11112 if (TREE_CODE (ret) == COMPLEX_TYPE)
11113 parm_complex[0] = true;
11114 argpos = 1;
11115 FOREACH_FUNCTION_ARGS (type, t, iter)
11116 {
11117 if (t == void_type_node)
11118 break;
11119 t = TYPE_MAIN_VARIANT (t);
11120 if (t != parm_first[argpos])
11121 {
11122 parm_varies[argpos] = true;
11123 if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
11124 && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
11125 {
11126 error_at ((*cexpr_list)[0].get_location (),
11127 "invalid type-generic type for "
11128 "argument %u of argument %u of "
11129 "%<__builtin_tgmath%>", argpos, 1);
11130 expr.set_error ();
11131 goto out;
11132 }
11133 if (!SCALAR_FLOAT_TYPE_P (t)
11134 && !COMPLEX_FLOAT_TYPE_P (t))
11135 {
11136 error_at ((*cexpr_list)[j].get_location (),
11137 "invalid type-generic type for "
11138 "argument %u of argument %u of "
11139 "%<__builtin_tgmath%>", argpos, j + 1);
11140 expr.set_error ();
11141 goto out;
11142 }
11143 }
11144 if (TREE_CODE (t) == COMPLEX_TYPE)
11145 parm_complex[argpos] = true;
11146 argpos++;
11147 }
11148 }
11149 enum tgmath_parm_kind max_variation = tgmath_fixed;
11150 for (unsigned int j = 0; j <= nargs; j++)
11151 {
11152 enum tgmath_parm_kind this_kind;
11153 if (parm_varies[j])
11154 {
11155 if (parm_complex[j])
11156 max_variation = this_kind = tgmath_complex;
11157 else
11158 {
11159 this_kind = tgmath_real;
11160 if (max_variation != tgmath_complex)
11161 max_variation = tgmath_real;
11162 }
11163 }
11164 else
11165 this_kind = tgmath_fixed;
11166 parm_kind.quick_push (obj: this_kind);
11167 }
11168 if (max_variation == tgmath_fixed)
11169 {
11170 error_at (loc, "function arguments of %<__builtin_tgmath%> "
11171 "all have the same type");
11172 expr.set_error ();
11173 break;
11174 }
11175
11176 /* Identify a parameter (not the return type) that varies,
11177 including with complex types if any variation includes
11178 complex types; there must be at least one such
11179 parameter. */
11180 unsigned int tgarg = 0;
11181 for (unsigned int j = 1; j <= nargs; j++)
11182 if (parm_kind[j] == max_variation)
11183 {
11184 tgarg = j;
11185 break;
11186 }
11187 if (tgarg == 0)
11188 {
11189 error_at (loc, "function arguments of %<__builtin_tgmath%> "
11190 "lack type-generic parameter");
11191 expr.set_error ();
11192 break;
11193 }
11194
11195 /* Determine the type of the relevant parameter for each
11196 function. */
11197 auto_vec<tree> tg_type (num_functions);
11198 for (unsigned int j = 0; j < num_functions; j++)
11199 {
11200 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11201 argpos = 1;
11202 FOREACH_FUNCTION_ARGS (type, t, iter)
11203 {
11204 if (argpos == tgarg)
11205 {
11206 tg_type.quick_push (TYPE_MAIN_VARIANT (t));
11207 break;
11208 }
11209 argpos++;
11210 }
11211 }
11212
11213 /* Verify that the corresponding types are different for
11214 all the listed functions. Also determine whether all
11215 the types are complex, whether all the types are
11216 standard or binary, and whether all the types are
11217 decimal. */
11218 bool all_complex = true;
11219 bool all_binary = true;
11220 bool all_decimal = true;
11221 hash_set<tree> tg_types;
11222 FOR_EACH_VEC_ELT (tg_type, i, t)
11223 {
11224 if (TREE_CODE (t) == COMPLEX_TYPE)
11225 all_decimal = false;
11226 else
11227 {
11228 all_complex = false;
11229 if (DECIMAL_FLOAT_TYPE_P (t))
11230 all_binary = false;
11231 else
11232 all_decimal = false;
11233 }
11234 if (tg_types.add (k: t))
11235 {
11236 error_at ((*cexpr_list)[i].get_location (),
11237 "duplicate type-generic parameter type for "
11238 "function argument %u of %<__builtin_tgmath%>",
11239 i + 1);
11240 expr.set_error ();
11241 goto out;
11242 }
11243 }
11244
11245 /* Verify that other parameters and the return type whose
11246 types vary have their types varying in the correct
11247 way. */
11248 for (unsigned int j = 0; j < num_functions; j++)
11249 {
11250 tree exp_type = tg_type[j];
11251 tree exp_real_type = exp_type;
11252 if (TREE_CODE (exp_type) == COMPLEX_TYPE)
11253 exp_real_type = TREE_TYPE (exp_type);
11254 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
11255 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
11256 if ((parm_kind[0] == tgmath_complex && ret != exp_type)
11257 || (parm_kind[0] == tgmath_real && ret != exp_real_type))
11258 {
11259 error_at ((*cexpr_list)[j].get_location (),
11260 "bad return type for function argument %u "
11261 "of %<__builtin_tgmath%>", j + 1);
11262 expr.set_error ();
11263 goto out;
11264 }
11265 argpos = 1;
11266 FOREACH_FUNCTION_ARGS (type, t, iter)
11267 {
11268 if (t == void_type_node)
11269 break;
11270 t = TYPE_MAIN_VARIANT (t);
11271 if ((parm_kind[argpos] == tgmath_complex
11272 && t != exp_type)
11273 || (parm_kind[argpos] == tgmath_real
11274 && t != exp_real_type))
11275 {
11276 error_at ((*cexpr_list)[j].get_location (),
11277 "bad type for argument %u of "
11278 "function argument %u of "
11279 "%<__builtin_tgmath%>", argpos, j + 1);
11280 expr.set_error ();
11281 goto out;
11282 }
11283 argpos++;
11284 }
11285 }
11286
11287 /* The functions listed are a valid set of functions for a
11288 <tgmath.h> macro to select between. Identify the
11289 matching function, if any. First, the argument types
11290 must be combined following <tgmath.h> rules. Integer
11291 types are treated as _Decimal64 if any type-generic
11292 argument is decimal, or if the only alternatives for
11293 type-generic arguments are of decimal types, and are
11294 otherwise treated as _Float32x (or _Complex _Float32x
11295 for complex integer types) if any type-generic argument
11296 has _FloatNx type, otherwise as double (or _Complex
11297 double for complex integer types). After that
11298 adjustment, types are combined following the usual
11299 arithmetic conversions. If the function only accepts
11300 complex arguments, a complex type is produced. */
11301 bool arg_complex = all_complex;
11302 bool arg_binary = all_binary;
11303 bool arg_int_decimal = all_decimal;
11304 bool arg_int_floatnx = false;
11305 for (unsigned int j = 1; j <= nargs; j++)
11306 {
11307 if (parm_kind[j] == tgmath_fixed)
11308 continue;
11309 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
11310 tree type = TREE_TYPE (ce->value);
11311 if (!INTEGRAL_TYPE_P (type)
11312 && !SCALAR_FLOAT_TYPE_P (type)
11313 && TREE_CODE (type) != COMPLEX_TYPE)
11314 {
11315 error_at (ce->get_location (),
11316 "invalid type of argument %u of type-generic "
11317 "function", j);
11318 expr.set_error ();
11319 goto out;
11320 }
11321 if (DECIMAL_FLOAT_TYPE_P (type))
11322 {
11323 arg_int_decimal = true;
11324 if (all_complex)
11325 {
11326 error_at (ce->get_location (),
11327 "decimal floating-point argument %u to "
11328 "complex-only type-generic function", j);
11329 expr.set_error ();
11330 goto out;
11331 }
11332 else if (all_binary)
11333 {
11334 error_at (ce->get_location (),
11335 "decimal floating-point argument %u to "
11336 "binary-only type-generic function", j);
11337 expr.set_error ();
11338 goto out;
11339 }
11340 else if (arg_complex)
11341 {
11342 error_at (ce->get_location (),
11343 "both complex and decimal floating-point "
11344 "arguments to type-generic function");
11345 expr.set_error ();
11346 goto out;
11347 }
11348 else if (arg_binary)
11349 {
11350 error_at (ce->get_location (),
11351 "both binary and decimal floating-point "
11352 "arguments to type-generic function");
11353 expr.set_error ();
11354 goto out;
11355 }
11356 }
11357 else if (TREE_CODE (type) == COMPLEX_TYPE)
11358 {
11359 arg_complex = true;
11360 if (COMPLEX_FLOAT_TYPE_P (type))
11361 arg_binary = true;
11362 if (all_decimal)
11363 {
11364 error_at (ce->get_location (),
11365 "complex argument %u to "
11366 "decimal-only type-generic function", j);
11367 expr.set_error ();
11368 goto out;
11369 }
11370 else if (arg_int_decimal)
11371 {
11372 error_at (ce->get_location (),
11373 "both complex and decimal floating-point "
11374 "arguments to type-generic function");
11375 expr.set_error ();
11376 goto out;
11377 }
11378 }
11379 else if (SCALAR_FLOAT_TYPE_P (type))
11380 {
11381 arg_binary = true;
11382 if (all_decimal)
11383 {
11384 error_at (ce->get_location (),
11385 "binary argument %u to "
11386 "decimal-only type-generic function", j);
11387 expr.set_error ();
11388 goto out;
11389 }
11390 else if (arg_int_decimal)
11391 {
11392 error_at (ce->get_location (),
11393 "both binary and decimal floating-point "
11394 "arguments to type-generic function");
11395 expr.set_error ();
11396 goto out;
11397 }
11398 }
11399 tree rtype = TYPE_MAIN_VARIANT (type);
11400 if (TREE_CODE (rtype) == COMPLEX_TYPE)
11401 rtype = TREE_TYPE (rtype);
11402 if (SCALAR_FLOAT_TYPE_P (rtype))
11403 for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
11404 if (rtype == FLOATNX_TYPE_NODE (j))
11405 {
11406 arg_int_floatnx = true;
11407 break;
11408 }
11409 }
11410 tree arg_real = NULL_TREE;
11411 for (unsigned int j = 1; j <= nargs; j++)
11412 {
11413 if (parm_kind[j] == tgmath_fixed)
11414 continue;
11415 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
11416 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
11417 if (TREE_CODE (type) == COMPLEX_TYPE)
11418 type = TREE_TYPE (type);
11419 if (INTEGRAL_TYPE_P (type))
11420 type = (arg_int_decimal
11421 ? dfloat64_type_node
11422 : arg_int_floatnx
11423 ? float32x_type_node
11424 : double_type_node);
11425 if (arg_real == NULL_TREE)
11426 arg_real = type;
11427 else
11428 arg_real = common_type (arg_real, type);
11429 if (arg_real == error_mark_node)
11430 {
11431 expr.set_error ();
11432 goto out;
11433 }
11434 }
11435 tree arg_type = (arg_complex
11436 ? build_complex_type (arg_real)
11437 : arg_real);
11438
11439 /* Look for a function to call with type-generic parameter
11440 type ARG_TYPE. */
11441 c_expr_t *fn = NULL;
11442 for (unsigned int j = 0; j < num_functions; j++)
11443 {
11444 if (tg_type[j] == arg_type)
11445 {
11446 fn = &(*cexpr_list)[j];
11447 break;
11448 }
11449 }
11450 if (fn == NULL
11451 && parm_kind[0] == tgmath_fixed
11452 && SCALAR_FLOAT_TYPE_P (parm_first[0]))
11453 {
11454 /* Presume this is a macro that rounds its result to a
11455 narrower type, and look for the first function with
11456 at least the range and precision of the argument
11457 type. */
11458 for (unsigned int j = 0; j < num_functions; j++)
11459 {
11460 if (arg_complex
11461 != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
11462 continue;
11463 tree real_tg_type = (arg_complex
11464 ? TREE_TYPE (tg_type[j])
11465 : tg_type[j]);
11466 if (DECIMAL_FLOAT_TYPE_P (arg_real)
11467 != DECIMAL_FLOAT_TYPE_P (real_tg_type))
11468 continue;
11469 scalar_float_mode arg_mode
11470 = SCALAR_FLOAT_TYPE_MODE (arg_real);
11471 scalar_float_mode tg_mode
11472 = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
11473 const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
11474 const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
11475 if (arg_fmt->b == tg_fmt->b
11476 && arg_fmt->p <= tg_fmt->p
11477 && arg_fmt->emax <= tg_fmt->emax
11478 && (arg_fmt->emin - arg_fmt->p
11479 >= tg_fmt->emin - tg_fmt->p))
11480 {
11481 fn = &(*cexpr_list)[j];
11482 break;
11483 }
11484 }
11485 }
11486 if (fn == NULL)
11487 {
11488 error_at (loc, "no matching function for type-generic call");
11489 expr.set_error ();
11490 break;
11491 }
11492
11493 /* Construct a call to FN. */
11494 vec<tree, va_gc> *args;
11495 vec_alloc (v&: args, nelems: nargs);
11496 vec<tree, va_gc> *origtypes;
11497 vec_alloc (v&: origtypes, nelems: nargs);
11498 auto_vec<location_t> arg_loc (nargs);
11499 for (unsigned int j = 0; j < nargs; j++)
11500 {
11501 c_expr_t *ce = &(*cexpr_list)[num_functions + j];
11502 args->quick_push (obj: ce->value);
11503 arg_loc.quick_push (obj: ce->get_location ());
11504 origtypes->quick_push (obj: ce->original_type);
11505 }
11506 expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
11507 args, origtypes);
11508 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11509 break;
11510 }
11511 case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
11512 {
11513 vec<c_expr_t, va_gc> *cexpr_list;
11514 c_expr_t *e2_p;
11515 tree chain_value;
11516 location_t close_paren_loc;
11517
11518 c_parser_consume_token (parser);
11519 if (!c_parser_get_builtin_args (parser,
11520 bname: "__builtin_call_with_static_chain",
11521 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11522 out_close_paren_loc: &close_paren_loc))
11523 {
11524 expr.set_error ();
11525 break;
11526 }
11527 if (vec_safe_length (v: cexpr_list) != 2)
11528 {
11529 error_at (loc, "wrong number of arguments to "
11530 "%<__builtin_call_with_static_chain%>");
11531 expr.set_error ();
11532 break;
11533 }
11534
11535 expr = (*cexpr_list)[0];
11536 e2_p = &(*cexpr_list)[1];
11537 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
11538 chain_value = e2_p->value;
11539 mark_exp_read (chain_value);
11540
11541 if (TREE_CODE (expr.value) != CALL_EXPR)
11542 error_at (loc, "first argument to "
11543 "%<__builtin_call_with_static_chain%> "
11544 "must be a call expression");
11545 else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
11546 error_at (loc, "second argument to "
11547 "%<__builtin_call_with_static_chain%> "
11548 "must be a pointer type");
11549 else
11550 CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
11551 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11552 break;
11553 }
11554 case RID_BUILTIN_COMPLEX:
11555 {
11556 vec<c_expr_t, va_gc> *cexpr_list;
11557 c_expr_t *e1_p, *e2_p;
11558 location_t close_paren_loc;
11559
11560 c_parser_consume_token (parser);
11561 if (!c_parser_get_builtin_args (parser,
11562 bname: "__builtin_complex",
11563 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11564 out_close_paren_loc: &close_paren_loc))
11565 {
11566 expr.set_error ();
11567 break;
11568 }
11569
11570 if (vec_safe_length (v: cexpr_list) != 2)
11571 {
11572 error_at (loc, "wrong number of arguments to "
11573 "%<__builtin_complex%>");
11574 expr.set_error ();
11575 break;
11576 }
11577
11578 e1_p = &(*cexpr_list)[0];
11579 e2_p = &(*cexpr_list)[1];
11580
11581 *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
11582 if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
11583 e1_p->value = convert (TREE_TYPE (e1_p->value),
11584 TREE_OPERAND (e1_p->value, 0));
11585 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
11586 if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
11587 e2_p->value = convert (TREE_TYPE (e2_p->value),
11588 TREE_OPERAND (e2_p->value, 0));
11589 if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
11590 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
11591 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
11592 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
11593 {
11594 error_at (loc, "%<__builtin_complex%> operand "
11595 "not of real binary floating-point type");
11596 expr.set_error ();
11597 break;
11598 }
11599 if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
11600 != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
11601 {
11602 error_at (loc,
11603 "%<__builtin_complex%> operands of different types");
11604 expr.set_error ();
11605 break;
11606 }
11607 pedwarn_c90 (loc, opt: OPT_Wpedantic,
11608 "ISO C90 does not support complex types");
11609 expr.value = build2_loc (loc, code: COMPLEX_EXPR,
11610 type: build_complex_type
11611 (TYPE_MAIN_VARIANT
11612 (TREE_TYPE (e1_p->value))),
11613 arg0: e1_p->value, arg1: e2_p->value);
11614 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11615 break;
11616 }
11617 case RID_BUILTIN_SHUFFLE:
11618 {
11619 vec<c_expr_t, va_gc> *cexpr_list;
11620 unsigned int i;
11621 c_expr_t *p;
11622 location_t close_paren_loc;
11623
11624 c_parser_consume_token (parser);
11625 if (!c_parser_get_builtin_args (parser,
11626 bname: "__builtin_shuffle",
11627 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11628 out_close_paren_loc: &close_paren_loc))
11629 {
11630 expr.set_error ();
11631 break;
11632 }
11633
11634 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
11635 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11636
11637 if (vec_safe_length (v: cexpr_list) == 2)
11638 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
11639 NULL_TREE,
11640 (*cexpr_list)[1].value);
11641
11642 else if (vec_safe_length (v: cexpr_list) == 3)
11643 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
11644 (*cexpr_list)[1].value,
11645 (*cexpr_list)[2].value);
11646 else
11647 {
11648 error_at (loc, "wrong number of arguments to "
11649 "%<__builtin_shuffle%>");
11650 expr.set_error ();
11651 }
11652 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11653 break;
11654 }
11655 case RID_BUILTIN_SHUFFLEVECTOR:
11656 {
11657 vec<c_expr_t, va_gc> *cexpr_list;
11658 unsigned int i;
11659 c_expr_t *p;
11660 location_t close_paren_loc;
11661
11662 c_parser_consume_token (parser);
11663 if (!c_parser_get_builtin_args (parser,
11664 bname: "__builtin_shufflevector",
11665 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
11666 out_close_paren_loc: &close_paren_loc))
11667 {
11668 expr.set_error ();
11669 break;
11670 }
11671
11672 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
11673 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
11674
11675 if (vec_safe_length (v: cexpr_list) < 3)
11676 {
11677 error_at (loc, "wrong number of arguments to "
11678 "%<__builtin_shuffle%>");
11679 expr.set_error ();
11680 }
11681 else
11682 {
11683 auto_vec<tree, 16> mask;
11684 for (i = 2; i < cexpr_list->length (); ++i)
11685 mask.safe_push (obj: (*cexpr_list)[i].value);
11686 expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
11687 (*cexpr_list)[1].value,
11688 mask);
11689 }
11690 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11691 break;
11692 }
11693 case RID_BUILTIN_CONVERTVECTOR:
11694 {
11695 location_t start_loc = loc;
11696 c_parser_consume_token (parser);
11697 matching_parens parens;
11698 if (!parens.require_open (parser))
11699 {
11700 expr.set_error ();
11701 break;
11702 }
11703 e1 = c_parser_expr_no_commas (parser, NULL);
11704 mark_exp_read (e1.value);
11705 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11706 {
11707 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11708 expr.set_error ();
11709 break;
11710 }
11711 loc = c_parser_peek_token (parser)->location;
11712 t1 = c_parser_type_name (parser);
11713 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11714 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11715 msgid: "expected %<)%>");
11716 if (t1 == NULL)
11717 expr.set_error ();
11718 else
11719 {
11720 tree type_expr = NULL_TREE;
11721 expr.value = c_build_vec_convert (start_loc, e1.value, loc,
11722 groktypename (t1, &type_expr,
11723 NULL));
11724 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11725 }
11726 }
11727 break;
11728 case RID_BUILTIN_ASSOC_BARRIER:
11729 {
11730 location_t start_loc = loc;
11731 c_parser_consume_token (parser);
11732 matching_parens parens;
11733 if (!parens.require_open (parser))
11734 {
11735 expr.set_error ();
11736 break;
11737 }
11738 e1 = c_parser_expr_no_commas (parser, NULL);
11739 mark_exp_read (e1.value);
11740 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11741 parens.skip_until_found_close (parser);
11742 expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
11743 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11744 }
11745 break;
11746 case RID_AT_SELECTOR:
11747 {
11748 gcc_assert (c_dialect_objc ());
11749 c_parser_consume_token (parser);
11750 matching_parens parens;
11751 if (!parens.require_open (parser))
11752 {
11753 expr.set_error ();
11754 break;
11755 }
11756 tree sel = c_parser_objc_selector_arg (parser);
11757 location_t close_loc = c_parser_peek_token (parser)->location;
11758 parens.skip_until_found_close (parser);
11759 expr.value = objc_build_selector_expr (loc, sel);
11760 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11761 }
11762 break;
11763 case RID_AT_PROTOCOL:
11764 {
11765 gcc_assert (c_dialect_objc ());
11766 c_parser_consume_token (parser);
11767 matching_parens parens;
11768 if (!parens.require_open (parser))
11769 {
11770 expr.set_error ();
11771 break;
11772 }
11773 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
11774 {
11775 c_parser_error (parser, gmsgid: "expected identifier");
11776 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11777 expr.set_error ();
11778 break;
11779 }
11780 tree id = c_parser_peek_token (parser)->value;
11781 c_parser_consume_token (parser);
11782 location_t close_loc = c_parser_peek_token (parser)->location;
11783 parens.skip_until_found_close (parser);
11784 expr.value = objc_build_protocol_expr (id);
11785 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11786 }
11787 break;
11788 case RID_AT_ENCODE:
11789 {
11790 /* Extension to support C-structures in the archiver. */
11791 gcc_assert (c_dialect_objc ());
11792 c_parser_consume_token (parser);
11793 matching_parens parens;
11794 if (!parens.require_open (parser))
11795 {
11796 expr.set_error ();
11797 break;
11798 }
11799 t1 = c_parser_type_name (parser);
11800 if (t1 == NULL)
11801 {
11802 expr.set_error ();
11803 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11804 break;
11805 }
11806 location_t close_loc = c_parser_peek_token (parser)->location;
11807 parens.skip_until_found_close (parser);
11808 tree type = groktypename (t1, NULL, NULL);
11809 expr.value = objc_build_encode_expr (type);
11810 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11811 }
11812 break;
11813 case RID_GENERIC:
11814 expr = c_parser_generic_selection (parser);
11815 break;
11816 case RID_OMP_ALL_MEMORY:
11817 gcc_assert (flag_openmp);
11818 c_parser_consume_token (parser);
11819 error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
11820 "%<depend%> clause");
11821 expr.set_error ();
11822 break;
11823 /* C23 'nullptr' literal. */
11824 case RID_NULLPTR:
11825 c_parser_consume_token (parser);
11826 expr.value = nullptr_node;
11827 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11828 pedwarn_c11 (loc, opt: OPT_Wpedantic,
11829 "ISO C does not support %qs before C23", "nullptr");
11830 break;
11831 case RID_TRUE:
11832 c_parser_consume_token (parser);
11833 expr.value = boolean_true_node;
11834 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11835 break;
11836 case RID_FALSE:
11837 c_parser_consume_token (parser);
11838 expr.value = boolean_false_node;
11839 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11840 break;
11841 default:
11842 c_parser_error (parser, gmsgid: "expected expression");
11843 expr.set_error ();
11844 break;
11845 }
11846 break;
11847 case CPP_OPEN_SQUARE:
11848 if (c_dialect_objc ())
11849 {
11850 tree receiver, args;
11851 c_parser_consume_token (parser);
11852 receiver = c_parser_objc_receiver (parser);
11853 args = c_parser_objc_message_args (parser);
11854 location_t close_loc = c_parser_peek_token (parser)->location;
11855 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
11856 msgid: "expected %<]%>");
11857 expr.value = objc_build_message_expr (receiver, args);
11858 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11859 break;
11860 }
11861 /* Else fall through to report error. */
11862 /* FALLTHRU */
11863 default:
11864 c_parser_error (parser, gmsgid: "expected expression");
11865 expr.set_error ();
11866 break;
11867 }
11868 out:
11869 return c_parser_postfix_expression_after_primary
11870 (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
11871}
11872
11873/* Parse a postfix expression after a parenthesized type name: the
11874 brace-enclosed initializer of a compound literal, possibly followed
11875 by some postfix operators. This is separate because it is not
11876 possible to tell until after the type name whether a cast
11877 expression has a cast or a compound literal, or whether the operand
11878 of sizeof is a parenthesized type name or starts with a compound
11879 literal. TYPE_LOC is the location where TYPE_NAME starts--the
11880 location of the first token after the parentheses around the type
11881 name. */
11882
11883static struct c_expr
11884c_parser_postfix_expression_after_paren_type (c_parser *parser,
11885 struct c_declspecs *scspecs,
11886 struct c_type_name *type_name,
11887 location_t type_loc)
11888{
11889 tree type;
11890 struct c_expr init;
11891 bool non_const;
11892 struct c_expr expr;
11893 location_t start_loc;
11894 tree type_expr = NULL_TREE;
11895 bool type_expr_const = true;
11896 bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
11897 unsigned int underspec_state = 0;
11898 check_compound_literal_type (type_loc, type_name);
11899 rich_location richloc (line_table, type_loc);
11900 start_loc = c_parser_peek_token (parser)->location;
11901 if (constexpr_p)
11902 {
11903 underspec_state = start_underspecified_init (start_loc, NULL_TREE);
11904 /* A constexpr compound literal is subject to the constraints on
11905 underspecified declarations, which may not declare tags or
11906 members or structures or unions; it is undefined behavior to
11907 declare the members of an enumeration. Where the structure,
11908 union or enumeration type is declared within the compound
11909 literal initializer, this is diagnosed elsewhere as a result
11910 of the above call to start_underspecified_init. Diagnose
11911 here the case of declaring such a type in the type specifiers
11912 of the compound literal. */
11913 switch (type_name->specs->typespec_kind)
11914 {
11915 case ctsk_tagfirstref:
11916 case ctsk_tagfirstref_attrs:
11917 error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
11918 type_name->specs->type);
11919 break;
11920
11921 case ctsk_tagdef:
11922 error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
11923 type_name->specs->type);
11924 break;
11925
11926 default:
11927 break;
11928 }
11929 }
11930 start_init (NULL_TREE, NULL,
11931 (global_bindings_p ()
11932 || (scspecs && scspecs->storage_class == csc_static)
11933 || constexpr_p), constexpr_p, &richloc);
11934 type = groktypename (type_name, &type_expr, &type_expr_const);
11935 if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
11936 {
11937 error_at (type_loc, "compound literal has variable size");
11938 type = error_mark_node;
11939 }
11940 else if (TREE_CODE (type) == FUNCTION_TYPE)
11941 {
11942 error_at (type_loc, "compound literal has function type");
11943 type = error_mark_node;
11944 }
11945 if (constexpr_p && type != error_mark_node)
11946 {
11947 tree type_no_array = strip_array_types (type);
11948 /* The type of a constexpr object must not be variably modified
11949 (which applies to all compound literals), volatile, atomic or
11950 restrict qualified or have a member with such a qualifier.
11951 const qualification is implicitly added. */
11952 if (TYPE_QUALS (type_no_array)
11953 & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
11954 error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
11955 else if (RECORD_OR_UNION_TYPE_P (type_no_array)
11956 && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
11957 error_at (type_loc, "invalid qualifiers for field of "
11958 "%<constexpr%> object");
11959 type = c_build_qualified_type (type,
11960 (TYPE_QUALS (type_no_array)
11961 | TYPE_QUAL_CONST));
11962 }
11963 init = c_parser_braced_init (parser, type, nested_p: false, NULL, NULL_TREE);
11964 if (constexpr_p)
11965 finish_underspecified_init (NULL_TREE, underspec_state);
11966 finish_init ();
11967 maybe_warn_string_init (type_loc, type, init);
11968
11969 if (type != error_mark_node
11970 && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
11971 && current_function_decl)
11972 {
11973 error ("compound literal qualified by address-space qualifier");
11974 type = error_mark_node;
11975 }
11976
11977 if (!pedwarn_c90 (start_loc, opt: OPT_Wpedantic,
11978 "ISO C90 forbids compound literals") && scspecs)
11979 pedwarn_c11 (start_loc, opt: OPT_Wpedantic,
11980 "ISO C forbids storage class specifiers in compound literals "
11981 "before C23");
11982 non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
11983 ? CONSTRUCTOR_NON_CONST (init.value)
11984 : init.original_code == C_MAYBE_CONST_EXPR);
11985 non_const |= !type_expr_const;
11986 unsigned int alignas_align = 0;
11987 if (type != error_mark_node
11988 && type_name->specs->align_log != -1)
11989 {
11990 alignas_align = 1U << type_name->specs->align_log;
11991 if (alignas_align < min_align_of_type (type))
11992 {
11993 error_at (type_name->specs->locations[cdw_alignas],
11994 "%<_Alignas%> specifiers cannot reduce "
11995 "alignment of compound literal");
11996 alignas_align = 0;
11997 }
11998 }
11999 expr.value = build_compound_literal (start_loc, type, init.value, non_const,
12000 alignas_align, scspecs);
12001 set_c_expr_source_range (expr: &expr, src_range: init.src_range);
12002 expr.m_decimal = 0;
12003 expr.original_code = ERROR_MARK;
12004 expr.original_type = NULL;
12005 if (type != error_mark_node
12006 && expr.value != error_mark_node
12007 && type_expr)
12008 {
12009 if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
12010 {
12011 gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
12012 C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
12013 }
12014 else
12015 {
12016 gcc_assert (!non_const);
12017 expr.value = build2 (C_MAYBE_CONST_EXPR, type,
12018 type_expr, expr.value);
12019 }
12020 }
12021 return c_parser_postfix_expression_after_primary (parser, loc: start_loc, expr);
12022}
12023
12024/* Callback function for sizeof_pointer_memaccess_warning to compare
12025 types. */
12026
12027static bool
12028sizeof_ptr_memacc_comptypes (tree type1, tree type2)
12029{
12030 return comptypes (type1, type2) == 1;
12031}
12032
12033/* Warn for patterns where abs-like function appears to be used incorrectly,
12034 gracefully ignore any non-abs-like function. The warning location should
12035 be LOC. FNDECL is the declaration of called function, it must be a
12036 BUILT_IN_NORMAL function. ARG is the first and only argument of the
12037 call. */
12038
12039static void
12040warn_for_abs (location_t loc, tree fndecl, tree arg)
12041{
12042 /* Avoid warning in unreachable subexpressions. */
12043 if (c_inhibit_evaluation_warnings)
12044 return;
12045
12046 tree atype = TREE_TYPE (arg);
12047
12048 /* Casts from pointers (and thus arrays and fndecls) will generate
12049 -Wint-conversion warnings. Most other wrong types hopefully lead to type
12050 mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
12051 types and possibly other exotic types. */
12052 if (!INTEGRAL_TYPE_P (atype)
12053 && !SCALAR_FLOAT_TYPE_P (atype)
12054 && TREE_CODE (atype) != COMPLEX_TYPE)
12055 return;
12056
12057 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
12058
12059 switch (fcode)
12060 {
12061 case BUILT_IN_ABS:
12062 case BUILT_IN_LABS:
12063 case BUILT_IN_LLABS:
12064 case BUILT_IN_IMAXABS:
12065 if (!INTEGRAL_TYPE_P (atype))
12066 {
12067 if (SCALAR_FLOAT_TYPE_P (atype))
12068 warning_at (loc, OPT_Wabsolute_value,
12069 "using integer absolute value function %qD when "
12070 "argument is of floating-point type %qT",
12071 fndecl, atype);
12072 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12073 warning_at (loc, OPT_Wabsolute_value,
12074 "using integer absolute value function %qD when "
12075 "argument is of complex type %qT", fndecl, atype);
12076 else
12077 gcc_unreachable ();
12078 return;
12079 }
12080 if (TYPE_UNSIGNED (atype))
12081 warning_at (loc, OPT_Wabsolute_value,
12082 "taking the absolute value of unsigned type %qT "
12083 "has no effect", atype);
12084 break;
12085
12086 CASE_FLT_FN (BUILT_IN_FABS):
12087 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
12088 if (!SCALAR_FLOAT_TYPE_P (atype)
12089 || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
12090 {
12091 if (INTEGRAL_TYPE_P (atype))
12092 warning_at (loc, OPT_Wabsolute_value,
12093 "using floating-point absolute value function %qD "
12094 "when argument is of integer type %qT", fndecl, atype);
12095 else if (DECIMAL_FLOAT_TYPE_P (atype))
12096 warning_at (loc, OPT_Wabsolute_value,
12097 "using floating-point absolute value function %qD "
12098 "when argument is of decimal floating-point type %qT",
12099 fndecl, atype);
12100 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12101 warning_at (loc, OPT_Wabsolute_value,
12102 "using floating-point absolute value function %qD when "
12103 "argument is of complex type %qT", fndecl, atype);
12104 else
12105 gcc_unreachable ();
12106 return;
12107 }
12108 break;
12109
12110 CASE_FLT_FN (BUILT_IN_CABS):
12111 if (TREE_CODE (atype) != COMPLEX_TYPE)
12112 {
12113 if (INTEGRAL_TYPE_P (atype))
12114 warning_at (loc, OPT_Wabsolute_value,
12115 "using complex absolute value function %qD when "
12116 "argument is of integer type %qT", fndecl, atype);
12117 else if (SCALAR_FLOAT_TYPE_P (atype))
12118 warning_at (loc, OPT_Wabsolute_value,
12119 "using complex absolute value function %qD when "
12120 "argument is of floating-point type %qT",
12121 fndecl, atype);
12122 else
12123 gcc_unreachable ();
12124
12125 return;
12126 }
12127 break;
12128
12129 case BUILT_IN_FABSD32:
12130 case BUILT_IN_FABSD64:
12131 case BUILT_IN_FABSD128:
12132 if (!DECIMAL_FLOAT_TYPE_P (atype))
12133 {
12134 if (INTEGRAL_TYPE_P (atype))
12135 warning_at (loc, OPT_Wabsolute_value,
12136 "using decimal floating-point absolute value "
12137 "function %qD when argument is of integer type %qT",
12138 fndecl, atype);
12139 else if (SCALAR_FLOAT_TYPE_P (atype))
12140 warning_at (loc, OPT_Wabsolute_value,
12141 "using decimal floating-point absolute value "
12142 "function %qD when argument is of floating-point "
12143 "type %qT", fndecl, atype);
12144 else if (TREE_CODE (atype) == COMPLEX_TYPE)
12145 warning_at (loc, OPT_Wabsolute_value,
12146 "using decimal floating-point absolute value "
12147 "function %qD when argument is of complex type %qT",
12148 fndecl, atype);
12149 else
12150 gcc_unreachable ();
12151 return;
12152 }
12153 break;
12154
12155 default:
12156 return;
12157 }
12158
12159 if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12160 return;
12161
12162 tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
12163 if (TREE_CODE (atype) == COMPLEX_TYPE)
12164 {
12165 gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
12166 atype = TREE_TYPE (atype);
12167 ftype = TREE_TYPE (ftype);
12168 }
12169
12170 if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
12171 warning_at (loc, OPT_Wabsolute_value,
12172 "absolute value function %qD given an argument of type %qT "
12173 "but has parameter of type %qT which may cause truncation "
12174 "of value", fndecl, atype, ftype);
12175}
12176
12177
12178/* Parse a postfix expression after the initial primary or compound
12179 literal; that is, parse a series of postfix operators.
12180
12181 EXPR_LOC is the location of the primary expression. */
12182
12183static struct c_expr
12184c_parser_postfix_expression_after_primary (c_parser *parser,
12185 location_t expr_loc,
12186 struct c_expr expr)
12187{
12188 struct c_expr orig_expr;
12189 tree ident, idx;
12190 location_t sizeof_arg_loc[3], comp_loc;
12191 tree sizeof_arg[3];
12192 unsigned int literal_zero_mask;
12193 unsigned int i;
12194 vec<tree, va_gc> *exprlist;
12195 vec<tree, va_gc> *origtypes = NULL;
12196 vec<location_t> arg_loc = vNULL;
12197 location_t start;
12198 location_t finish;
12199
12200 while (true)
12201 {
12202 location_t op_loc = c_parser_peek_token (parser)->location;
12203 switch (c_parser_peek_token (parser)->type)
12204 {
12205 case CPP_OPEN_SQUARE:
12206 /* Array reference. */
12207 c_parser_consume_token (parser);
12208 idx = c_parser_expression (parser).value;
12209 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
12210 msgid: "expected %<]%>");
12211 start = expr.get_start ();
12212 finish = parser->tokens_buf[0].location;
12213 expr.value = build_array_ref (op_loc, expr.value, idx);
12214 set_c_expr_source_range (expr: &expr, start, finish);
12215 expr.original_code = ERROR_MARK;
12216 expr.original_type = NULL;
12217 expr.m_decimal = 0;
12218 break;
12219 case CPP_OPEN_PAREN:
12220 /* Function call. */
12221 {
12222 matching_parens parens;
12223 parens.consume_open (parser);
12224 for (i = 0; i < 3; i++)
12225 {
12226 sizeof_arg[i] = NULL_TREE;
12227 sizeof_arg_loc[i] = UNKNOWN_LOCATION;
12228 }
12229 literal_zero_mask = 0;
12230 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
12231 exprlist = NULL;
12232 else if (TREE_CODE (expr.value) == FUNCTION_DECL
12233 && fndecl_built_in_p (node: expr.value, name1: BUILT_IN_CLASSIFY_TYPE)
12234 && c_parser_next_tokens_start_typename (parser,
12235 la: cla_prefer_id))
12236 {
12237 /* __builtin_classify_type (type) */
12238 c_inhibit_evaluation_warnings++;
12239 in_alignof++;
12240 struct c_type_name *type = c_parser_type_name (parser);
12241 c_inhibit_evaluation_warnings--;
12242 in_alignof--;
12243 struct c_typespec ret;
12244 ret.expr = NULL_TREE;
12245 ret.spec = error_mark_node;
12246 ret.expr_const_operands = false;
12247 if (type != NULL)
12248 ret.spec = groktypename (type, &ret.expr,
12249 &ret.expr_const_operands);
12250 parens.skip_until_found_close (parser);
12251 expr.value = build_int_cst (integer_type_node,
12252 type_to_class (ret.spec));
12253 break;
12254 }
12255 else
12256 exprlist = c_parser_expr_list (parser, true, false, &origtypes,
12257 sizeof_arg_loc, sizeof_arg,
12258 &arg_loc, &literal_zero_mask);
12259 parens.skip_until_found_close (parser);
12260 }
12261 orig_expr = expr;
12262 mark_exp_read (expr.value);
12263 if (warn_sizeof_pointer_memaccess)
12264 sizeof_pointer_memaccess_warning (sizeof_arg_loc,
12265 expr.value, exprlist,
12266 sizeof_arg,
12267 sizeof_ptr_memacc_comptypes);
12268 if (TREE_CODE (expr.value) == FUNCTION_DECL)
12269 {
12270 if (fndecl_built_in_p (node: expr.value, name1: BUILT_IN_MEMSET)
12271 && vec_safe_length (v: exprlist) == 3)
12272 {
12273 tree arg0 = (*exprlist)[0];
12274 tree arg2 = (*exprlist)[2];
12275 warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
12276 }
12277 if (warn_absolute_value
12278 && fndecl_built_in_p (node: expr.value, klass: BUILT_IN_NORMAL)
12279 && vec_safe_length (v: exprlist) == 1)
12280 warn_for_abs (loc: expr_loc, fndecl: expr.value, arg: (*exprlist)[0]);
12281 if (parser->omp_for_parse_state
12282 && parser->omp_for_parse_state->in_intervening_code
12283 && omp_runtime_api_call (fndecl: expr.value))
12284 {
12285 error_at (expr_loc, "calls to the OpenMP runtime API are "
12286 "not permitted in intervening code");
12287 parser->omp_for_parse_state->fail = true;
12288 }
12289 }
12290
12291 start = expr.get_start ();
12292 finish = parser->tokens_buf[0].get_finish ();
12293 expr.value
12294 = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
12295 exprlist, origtypes);
12296 set_c_expr_source_range (expr: &expr, start, finish);
12297 expr.m_decimal = 0;
12298
12299 expr.original_code = ERROR_MARK;
12300 if (TREE_CODE (expr.value) == INTEGER_CST
12301 && TREE_CODE (orig_expr.value) == FUNCTION_DECL
12302 && fndecl_built_in_p (node: orig_expr.value, name1: BUILT_IN_CONSTANT_P))
12303 expr.original_code = C_MAYBE_CONST_EXPR;
12304 expr.original_type = NULL;
12305 if (exprlist)
12306 {
12307 release_tree_vector (exprlist);
12308 release_tree_vector (origtypes);
12309 }
12310 arg_loc.release ();
12311 break;
12312 case CPP_DOT:
12313 /* Structure element reference. */
12314 c_parser_consume_token (parser);
12315 expr = default_function_array_conversion (expr_loc, expr);
12316 if (c_parser_next_token_is (parser, type: CPP_NAME))
12317 {
12318 c_token *comp_tok = c_parser_peek_token (parser);
12319 ident = comp_tok->value;
12320 comp_loc = comp_tok->location;
12321 }
12322 else
12323 {
12324 c_parser_error (parser, gmsgid: "expected identifier");
12325 expr.set_error ();
12326 expr.original_code = ERROR_MARK;
12327 expr.original_type = NULL;
12328 return expr;
12329 }
12330 start = expr.get_start ();
12331 finish = c_parser_peek_token (parser)->get_finish ();
12332 c_parser_consume_token (parser);
12333 expr.value = build_component_ref (op_loc, expr.value, ident,
12334 comp_loc, UNKNOWN_LOCATION);
12335 set_c_expr_source_range (expr: &expr, start, finish);
12336 expr.original_code = ERROR_MARK;
12337 if (TREE_CODE (expr.value) != COMPONENT_REF)
12338 expr.original_type = NULL;
12339 else
12340 {
12341 /* Remember the original type of a bitfield. */
12342 tree field = TREE_OPERAND (expr.value, 1);
12343 if (TREE_CODE (field) != FIELD_DECL)
12344 expr.original_type = NULL;
12345 else
12346 expr.original_type = DECL_BIT_FIELD_TYPE (field);
12347 }
12348 expr.m_decimal = 0;
12349 break;
12350 case CPP_DEREF:
12351 /* Structure element reference. */
12352 c_parser_consume_token (parser);
12353 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
12354 if (c_parser_next_token_is (parser, type: CPP_NAME))
12355 {
12356 c_token *comp_tok = c_parser_peek_token (parser);
12357 ident = comp_tok->value;
12358 comp_loc = comp_tok->location;
12359 }
12360 else
12361 {
12362 c_parser_error (parser, gmsgid: "expected identifier");
12363 expr.set_error ();
12364 expr.original_code = ERROR_MARK;
12365 expr.original_type = NULL;
12366 return expr;
12367 }
12368 start = expr.get_start ();
12369 finish = c_parser_peek_token (parser)->get_finish ();
12370 c_parser_consume_token (parser);
12371 expr.value = build_component_ref (op_loc,
12372 build_indirect_ref (op_loc,
12373 expr.value,
12374 RO_ARROW),
12375 ident, comp_loc,
12376 expr.get_location ());
12377 set_c_expr_source_range (expr: &expr, start, finish);
12378 expr.original_code = ERROR_MARK;
12379 if (TREE_CODE (expr.value) != COMPONENT_REF)
12380 expr.original_type = NULL;
12381 else
12382 {
12383 /* Remember the original type of a bitfield. */
12384 tree field = TREE_OPERAND (expr.value, 1);
12385 if (TREE_CODE (field) != FIELD_DECL)
12386 expr.original_type = NULL;
12387 else
12388 expr.original_type = DECL_BIT_FIELD_TYPE (field);
12389 }
12390 expr.m_decimal = 0;
12391 break;
12392 case CPP_PLUS_PLUS:
12393 /* Postincrement. */
12394 start = expr.get_start ();
12395 finish = c_parser_peek_token (parser)->get_finish ();
12396 c_parser_consume_token (parser);
12397 expr = default_function_array_read_conversion (expr_loc, expr);
12398 expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
12399 expr.value, false);
12400 set_c_expr_source_range (expr: &expr, start, finish);
12401 expr.original_code = ERROR_MARK;
12402 expr.original_type = NULL;
12403 break;
12404 case CPP_MINUS_MINUS:
12405 /* Postdecrement. */
12406 start = expr.get_start ();
12407 finish = c_parser_peek_token (parser)->get_finish ();
12408 c_parser_consume_token (parser);
12409 expr = default_function_array_read_conversion (expr_loc, expr);
12410 expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
12411 expr.value, false);
12412 set_c_expr_source_range (expr: &expr, start, finish);
12413 expr.original_code = ERROR_MARK;
12414 expr.original_type = NULL;
12415 break;
12416 default:
12417 return expr;
12418 }
12419 }
12420}
12421
12422/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
12423
12424 expression:
12425 assignment-expression
12426 expression , assignment-expression
12427*/
12428
12429static struct c_expr
12430c_parser_expression (c_parser *parser)
12431{
12432 location_t tloc = c_parser_peek_token (parser)->location;
12433 struct c_expr expr;
12434 expr = c_parser_expr_no_commas (parser, NULL);
12435 if (c_parser_next_token_is (parser, type: CPP_COMMA))
12436 expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
12437 while (c_parser_next_token_is (parser, type: CPP_COMMA))
12438 {
12439 struct c_expr next;
12440 tree lhsval;
12441 location_t loc = c_parser_peek_token (parser)->location;
12442 location_t expr_loc;
12443 c_parser_consume_token (parser);
12444 expr_loc = c_parser_peek_token (parser)->location;
12445 lhsval = expr.value;
12446 while (TREE_CODE (lhsval) == COMPOUND_EXPR
12447 || TREE_CODE (lhsval) == NOP_EXPR)
12448 {
12449 if (TREE_CODE (lhsval) == COMPOUND_EXPR)
12450 lhsval = TREE_OPERAND (lhsval, 1);
12451 else
12452 lhsval = TREE_OPERAND (lhsval, 0);
12453 }
12454 if (DECL_P (lhsval) || handled_component_p (t: lhsval))
12455 mark_exp_read (lhsval);
12456 next = c_parser_expr_no_commas (parser, NULL);
12457 next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
12458 expr.value = build_compound_expr (loc, expr.value, next.value);
12459 expr.original_code = COMPOUND_EXPR;
12460 expr.original_type = next.original_type;
12461 expr.m_decimal = 0;
12462 }
12463 return expr;
12464}
12465
12466/* Parse an expression and convert functions or arrays to pointers and
12467 lvalues to rvalues. */
12468
12469static struct c_expr
12470c_parser_expression_conv (c_parser *parser)
12471{
12472 struct c_expr expr;
12473 location_t loc = c_parser_peek_token (parser)->location;
12474 expr = c_parser_expression (parser);
12475 expr = convert_lvalue_to_rvalue (loc, expr, true, false);
12476 return expr;
12477}
12478
12479/* Helper function of c_parser_expr_list. Check if IDXth (0 based)
12480 argument is a literal zero alone and if so, set it in literal_zero_mask. */
12481
12482static inline void
12483c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
12484 unsigned int idx)
12485{
12486 if (idx >= HOST_BITS_PER_INT)
12487 return;
12488
12489 c_token *tok = c_parser_peek_token (parser);
12490 switch (tok->type)
12491 {
12492 case CPP_NUMBER:
12493 case CPP_CHAR:
12494 case CPP_WCHAR:
12495 case CPP_CHAR16:
12496 case CPP_CHAR32:
12497 case CPP_UTF8CHAR:
12498 /* If a parameter is literal zero alone, remember it
12499 for -Wmemset-transposed-args warning. */
12500 if (integer_zerop (tok->value)
12501 && !TREE_OVERFLOW (tok->value)
12502 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
12503 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
12504 *literal_zero_mask |= 1U << idx;
12505 default:
12506 break;
12507 }
12508}
12509
12510/* Parse a non-empty list of expressions. If CONVERT_P, convert
12511 functions and arrays to pointers and lvalues to rvalues. If
12512 FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
12513 locations of function arguments into this vector.
12514
12515 nonempty-expr-list:
12516 assignment-expression
12517 nonempty-expr-list , assignment-expression
12518*/
12519
12520static vec<tree, va_gc> *
12521c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
12522 vec<tree, va_gc> **p_orig_types,
12523 location_t *sizeof_arg_loc, tree *sizeof_arg,
12524 vec<location_t> *locations,
12525 unsigned int *literal_zero_mask)
12526{
12527 vec<tree, va_gc> *ret;
12528 vec<tree, va_gc> *orig_types;
12529 struct c_expr expr;
12530 unsigned int idx = 0;
12531
12532 ret = make_tree_vector ();
12533 if (p_orig_types == NULL)
12534 orig_types = NULL;
12535 else
12536 orig_types = make_tree_vector ();
12537
12538 if (literal_zero_mask)
12539 c_parser_check_literal_zero (parser, literal_zero_mask, idx: 0);
12540 expr = c_parser_expr_no_commas (parser, NULL);
12541 if (convert_p)
12542 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
12543 if (fold_p)
12544 expr.value = c_fully_fold (expr.value, false, NULL);
12545 ret->quick_push (obj: expr.value);
12546 if (orig_types)
12547 orig_types->quick_push (obj: expr.original_type);
12548 if (locations)
12549 locations->safe_push (obj: expr.get_location ());
12550 if (sizeof_arg != NULL
12551 && (expr.original_code == SIZEOF_EXPR
12552 || expr.original_code == PAREN_SIZEOF_EXPR))
12553 {
12554 sizeof_arg[0] = c_last_sizeof_arg;
12555 sizeof_arg_loc[0] = c_last_sizeof_loc;
12556 }
12557 while (c_parser_next_token_is (parser, type: CPP_COMMA))
12558 {
12559 c_parser_consume_token (parser);
12560 if (literal_zero_mask)
12561 c_parser_check_literal_zero (parser, literal_zero_mask, idx: idx + 1);
12562 expr = c_parser_expr_no_commas (parser, NULL);
12563 if (convert_p)
12564 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
12565 true);
12566 if (fold_p)
12567 expr.value = c_fully_fold (expr.value, false, NULL);
12568 vec_safe_push (v&: ret, obj: expr.value);
12569 if (orig_types)
12570 vec_safe_push (v&: orig_types, obj: expr.original_type);
12571 if (locations)
12572 locations->safe_push (obj: expr.get_location ());
12573 if (++idx < 3
12574 && sizeof_arg != NULL
12575 && (expr.original_code == SIZEOF_EXPR
12576 || expr.original_code == PAREN_SIZEOF_EXPR))
12577 {
12578 sizeof_arg[idx] = c_last_sizeof_arg;
12579 sizeof_arg_loc[idx] = c_last_sizeof_loc;
12580 }
12581 }
12582 if (orig_types)
12583 *p_orig_types = orig_types;
12584 return ret;
12585}
12586
12587/* Parse Objective-C-specific constructs. */
12588
12589/* Parse an objc-class-definition.
12590
12591 objc-class-definition:
12592 @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
12593 objc-class-instance-variables[opt] objc-methodprotolist @end
12594 @implementation identifier objc-superclass[opt]
12595 objc-class-instance-variables[opt]
12596 @interface identifier ( identifier ) objc-protocol-refs[opt]
12597 objc-methodprotolist @end
12598 @interface identifier ( ) objc-protocol-refs[opt]
12599 objc-methodprotolist @end
12600 @implementation identifier ( identifier )
12601
12602 objc-superclass:
12603 : identifier
12604
12605 "@interface identifier (" must start "@interface identifier (
12606 identifier ) ...": objc-methodprotolist in the first production may
12607 not start with a parenthesized identifier as a declarator of a data
12608 definition with no declaration specifiers if the objc-superclass,
12609 objc-protocol-refs and objc-class-instance-variables are omitted. */
12610
12611static void
12612c_parser_objc_class_definition (c_parser *parser, tree attributes)
12613{
12614 bool iface_p;
12615 tree id1;
12616 tree superclass;
12617 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_INTERFACE))
12618 iface_p = true;
12619 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_IMPLEMENTATION))
12620 iface_p = false;
12621 else
12622 gcc_unreachable ();
12623
12624 c_parser_consume_token (parser);
12625 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12626 {
12627 c_parser_error (parser, gmsgid: "expected identifier");
12628 return;
12629 }
12630 id1 = c_parser_peek_token (parser)->value;
12631 location_t loc1 = c_parser_peek_token (parser)->location;
12632 c_parser_consume_token (parser);
12633 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
12634 {
12635 /* We have a category or class extension. */
12636 tree id2;
12637 tree proto = NULL_TREE;
12638 matching_parens parens;
12639 parens.consume_open (parser);
12640 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12641 {
12642 if (iface_p && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
12643 {
12644 /* We have a class extension. */
12645 id2 = NULL_TREE;
12646 }
12647 else
12648 {
12649 c_parser_error (parser, gmsgid: "expected identifier or %<)%>");
12650 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12651 return;
12652 }
12653 }
12654 else
12655 {
12656 id2 = c_parser_peek_token (parser)->value;
12657 c_parser_consume_token (parser);
12658 }
12659 parens.skip_until_found_close (parser);
12660 if (!iface_p)
12661 {
12662 objc_start_category_implementation (id1, id2);
12663 return;
12664 }
12665 if (c_parser_next_token_is (parser, type: CPP_LESS))
12666 proto = c_parser_objc_protocol_refs (parser);
12667 objc_start_category_interface (id1, id2, proto, attributes);
12668 c_parser_objc_methodprotolist (parser);
12669 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
12670 objc_finish_interface ();
12671 return;
12672 }
12673 if (c_parser_next_token_is (parser, type: CPP_COLON))
12674 {
12675 c_parser_consume_token (parser);
12676 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12677 {
12678 c_parser_error (parser, gmsgid: "expected identifier");
12679 return;
12680 }
12681 superclass = c_parser_peek_token (parser)->value;
12682 c_parser_consume_token (parser);
12683 }
12684 else
12685 superclass = NULL_TREE;
12686 if (iface_p)
12687 {
12688 tree proto = NULL_TREE;
12689 if (c_parser_next_token_is (parser, type: CPP_LESS))
12690 proto = c_parser_objc_protocol_refs (parser);
12691 objc_start_class_interface (id1, loc1, superclass, proto, attributes);
12692 }
12693 else
12694 objc_start_class_implementation (id1, superclass);
12695 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
12696 c_parser_objc_class_instance_variables (parser);
12697 if (iface_p)
12698 {
12699 objc_continue_interface ();
12700 c_parser_objc_methodprotolist (parser);
12701 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
12702 objc_finish_interface ();
12703 }
12704 else
12705 {
12706 objc_continue_implementation ();
12707 return;
12708 }
12709}
12710
12711/* Parse objc-class-instance-variables.
12712
12713 objc-class-instance-variables:
12714 { objc-instance-variable-decl-list[opt] }
12715
12716 objc-instance-variable-decl-list:
12717 objc-visibility-spec
12718 objc-instance-variable-decl ;
12719 ;
12720 objc-instance-variable-decl-list objc-visibility-spec
12721 objc-instance-variable-decl-list objc-instance-variable-decl ;
12722 objc-instance-variable-decl-list ;
12723
12724 objc-visibility-spec:
12725 @private
12726 @protected
12727 @public
12728
12729 objc-instance-variable-decl:
12730 struct-declaration
12731*/
12732
12733static void
12734c_parser_objc_class_instance_variables (c_parser *parser)
12735{
12736 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
12737 c_parser_consume_token (parser);
12738 while (c_parser_next_token_is_not (parser, type: CPP_EOF))
12739 {
12740 tree decls;
12741 /* Parse any stray semicolon. */
12742 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
12743 {
12744 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
12745 "extra semicolon");
12746 c_parser_consume_token (parser);
12747 continue;
12748 }
12749 /* Stop if at the end of the instance variables. */
12750 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
12751 {
12752 c_parser_consume_token (parser);
12753 break;
12754 }
12755 /* Parse any objc-visibility-spec. */
12756 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PRIVATE))
12757 {
12758 c_parser_consume_token (parser);
12759 objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
12760 continue;
12761 }
12762 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROTECTED))
12763 {
12764 c_parser_consume_token (parser);
12765 objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
12766 continue;
12767 }
12768 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PUBLIC))
12769 {
12770 c_parser_consume_token (parser);
12771 objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
12772 continue;
12773 }
12774 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PACKAGE))
12775 {
12776 c_parser_consume_token (parser);
12777 objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
12778 continue;
12779 }
12780 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
12781 {
12782 c_parser_pragma (parser, pragma_external, NULL);
12783 continue;
12784 }
12785
12786 /* Parse some comma-separated declarations. */
12787 decls = c_parser_struct_declaration (parser, NULL);
12788 if (decls == NULL)
12789 {
12790 /* There is a syntax error. We want to skip the offending
12791 tokens up to the next ';' (included) or '}'
12792 (excluded). */
12793
12794 /* First, skip manually a ')' or ']'. This is because they
12795 reduce the nesting level, so c_parser_skip_until_found()
12796 wouldn't be able to skip past them. */
12797 c_token *token = c_parser_peek_token (parser);
12798 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
12799 c_parser_consume_token (parser);
12800
12801 /* Then, do the standard skipping. */
12802 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
12803
12804 /* We hopefully recovered. Start normal parsing again. */
12805 parser->error = false;
12806 continue;
12807 }
12808 else
12809 {
12810 /* Comma-separated instance variables are chained together
12811 in reverse order; add them one by one. */
12812 tree ivar = nreverse (decls);
12813 for (; ivar; ivar = DECL_CHAIN (ivar))
12814 objc_add_instance_variable (copy_node (ivar));
12815 }
12816 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
12817 }
12818}
12819
12820/* Parse an objc-class-declaration.
12821
12822 objc-class-declaration:
12823 @class identifier-list ;
12824*/
12825
12826static void
12827c_parser_objc_class_declaration (c_parser *parser)
12828{
12829 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
12830 c_parser_consume_token (parser);
12831 /* Any identifiers, including those declared as type names, are OK
12832 here. */
12833 while (true)
12834 {
12835 tree id;
12836 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12837 {
12838 c_parser_error (parser, gmsgid: "expected identifier");
12839 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
12840 parser->error = false;
12841 return;
12842 }
12843 id = c_parser_peek_token (parser)->value;
12844 objc_declare_class (id);
12845 c_parser_consume_token (parser);
12846 if (c_parser_next_token_is (parser, type: CPP_COMMA))
12847 c_parser_consume_token (parser);
12848 else
12849 break;
12850 }
12851 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
12852}
12853
12854/* Parse an objc-alias-declaration.
12855
12856 objc-alias-declaration:
12857 @compatibility_alias identifier identifier ;
12858*/
12859
12860static void
12861c_parser_objc_alias_declaration (c_parser *parser)
12862{
12863 tree id1, id2;
12864 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
12865 c_parser_consume_token (parser);
12866 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12867 {
12868 c_parser_error (parser, gmsgid: "expected identifier");
12869 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
12870 return;
12871 }
12872 id1 = c_parser_peek_token (parser)->value;
12873 c_parser_consume_token (parser);
12874 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12875 {
12876 c_parser_error (parser, gmsgid: "expected identifier");
12877 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
12878 return;
12879 }
12880 id2 = c_parser_peek_token (parser)->value;
12881 c_parser_consume_token (parser);
12882 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
12883 objc_declare_alias (id1, id2);
12884}
12885
12886/* Parse an objc-protocol-definition.
12887
12888 objc-protocol-definition:
12889 @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
12890 @protocol identifier-list ;
12891
12892 "@protocol identifier ;" should be resolved as "@protocol
12893 identifier-list ;": objc-methodprotolist may not start with a
12894 semicolon in the first alternative if objc-protocol-refs are
12895 omitted. */
12896
12897static void
12898c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
12899{
12900 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
12901
12902 c_parser_consume_token (parser);
12903 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12904 {
12905 c_parser_error (parser, gmsgid: "expected identifier");
12906 return;
12907 }
12908 if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
12909 || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
12910 {
12911 /* Any identifiers, including those declared as type names, are
12912 OK here. */
12913 while (true)
12914 {
12915 tree id;
12916 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
12917 {
12918 c_parser_error (parser, gmsgid: "expected identifier");
12919 break;
12920 }
12921 id = c_parser_peek_token (parser)->value;
12922 objc_declare_protocol (id, attributes);
12923 c_parser_consume_token (parser);
12924 if (c_parser_next_token_is (parser, type: CPP_COMMA))
12925 c_parser_consume_token (parser);
12926 else
12927 break;
12928 }
12929 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
12930 }
12931 else
12932 {
12933 tree id = c_parser_peek_token (parser)->value;
12934 tree proto = NULL_TREE;
12935 c_parser_consume_token (parser);
12936 if (c_parser_next_token_is (parser, type: CPP_LESS))
12937 proto = c_parser_objc_protocol_refs (parser);
12938 parser->objc_pq_context = true;
12939 objc_start_protocol (id, proto, attributes);
12940 c_parser_objc_methodprotolist (parser);
12941 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
12942 parser->objc_pq_context = false;
12943 objc_finish_interface ();
12944 }
12945}
12946
12947/* Parse an objc-method-type.
12948
12949 objc-method-type:
12950 +
12951 -
12952
12953 Return true if it is a class method (+) and false if it is
12954 an instance method (-).
12955*/
12956static inline bool
12957c_parser_objc_method_type (c_parser *parser)
12958{
12959 switch (c_parser_peek_token (parser)->type)
12960 {
12961 case CPP_PLUS:
12962 c_parser_consume_token (parser);
12963 return true;
12964 case CPP_MINUS:
12965 c_parser_consume_token (parser);
12966 return false;
12967 default:
12968 gcc_unreachable ();
12969 }
12970}
12971
12972/* Parse an objc-method-definition.
12973
12974 objc-method-definition:
12975 objc-method-type objc-method-decl ;[opt] compound-statement
12976*/
12977
12978static void
12979c_parser_objc_method_definition (c_parser *parser)
12980{
12981 bool is_class_method = c_parser_objc_method_type (parser);
12982 tree decl, attributes = NULL_TREE, expr = NULL_TREE;
12983 parser->objc_pq_context = true;
12984 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
12985 &expr);
12986 if (decl == error_mark_node)
12987 return; /* Bail here. */
12988
12989 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
12990 {
12991 c_parser_consume_token (parser);
12992 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
12993 "extra semicolon in method definition specified");
12994 }
12995
12996 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
12997 {
12998 c_parser_error (parser, gmsgid: "expected %<{%>");
12999 return;
13000 }
13001
13002 parser->objc_pq_context = false;
13003 if (objc_start_method_definition (is_class_method, decl, attributes, expr))
13004 {
13005 add_stmt (c_parser_compound_statement (parser));
13006 objc_finish_method_definition (current_function_decl);
13007 }
13008 else
13009 {
13010 /* This code is executed when we find a method definition
13011 outside of an @implementation context (or invalid for other
13012 reasons). Parse the method (to keep going) but do not emit
13013 any code.
13014 */
13015 c_parser_compound_statement (parser);
13016 }
13017}
13018
13019/* Parse an objc-methodprotolist.
13020
13021 objc-methodprotolist:
13022 empty
13023 objc-methodprotolist objc-methodproto
13024 objc-methodprotolist declaration
13025 objc-methodprotolist ;
13026 @optional
13027 @required
13028
13029 The declaration is a data definition, which may be missing
13030 declaration specifiers under the same rules and diagnostics as
13031 other data definitions outside functions, and the stray semicolon
13032 is diagnosed the same way as a stray semicolon outside a
13033 function. */
13034
13035static void
13036c_parser_objc_methodprotolist (c_parser *parser)
13037{
13038 while (true)
13039 {
13040 /* The list is terminated by @end. */
13041 switch (c_parser_peek_token (parser)->type)
13042 {
13043 case CPP_SEMICOLON:
13044 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
13045 "ISO C does not allow extra %<;%> outside of a function");
13046 c_parser_consume_token (parser);
13047 break;
13048 case CPP_PLUS:
13049 case CPP_MINUS:
13050 c_parser_objc_methodproto (parser);
13051 break;
13052 case CPP_PRAGMA:
13053 c_parser_pragma (parser, pragma_external, NULL);
13054 break;
13055 case CPP_EOF:
13056 return;
13057 default:
13058 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_END))
13059 return;
13060 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROPERTY))
13061 c_parser_objc_at_property_declaration (parser);
13062 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_OPTIONAL))
13063 {
13064 objc_set_method_opt (true);
13065 c_parser_consume_token (parser);
13066 }
13067 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_REQUIRED))
13068 {
13069 objc_set_method_opt (false);
13070 c_parser_consume_token (parser);
13071 }
13072 else
13073 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: true,
13074 nested: false, start_attr_ok: true);
13075 break;
13076 }
13077 }
13078}
13079
13080/* Parse an objc-methodproto.
13081
13082 objc-methodproto:
13083 objc-method-type objc-method-decl ;
13084*/
13085
13086static void
13087c_parser_objc_methodproto (c_parser *parser)
13088{
13089 bool is_class_method = c_parser_objc_method_type (parser);
13090 tree decl, attributes = NULL_TREE;
13091
13092 /* Remember protocol qualifiers in prototypes. */
13093 parser->objc_pq_context = true;
13094 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
13095 NULL);
13096 /* Forget protocol qualifiers now. */
13097 parser->objc_pq_context = false;
13098
13099 /* Do not allow the presence of attributes to hide an erroneous
13100 method implementation in the interface section. */
13101 if (!c_parser_next_token_is (parser, type: CPP_SEMICOLON))
13102 {
13103 c_parser_error (parser, gmsgid: "expected %<;%>");
13104 return;
13105 }
13106
13107 if (decl != error_mark_node)
13108 objc_add_method_declaration (is_class_method, decl, attributes);
13109
13110 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13111}
13112
13113/* If we are at a position that method attributes may be present, check that
13114 there are not any parsed already (a syntax error) and then collect any
13115 specified at the current location. Finally, if new attributes were present,
13116 check that the next token is legal ( ';' for decls and '{' for defs). */
13117
13118static bool
13119c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
13120{
13121 bool bad = false;
13122 if (*attributes)
13123 {
13124 c_parser_error (parser,
13125 gmsgid: "method attributes must be specified at the end only");
13126 *attributes = NULL_TREE;
13127 bad = true;
13128 }
13129
13130 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
13131 *attributes = c_parser_gnu_attributes (parser);
13132
13133 /* If there were no attributes here, just report any earlier error. */
13134 if (*attributes == NULL_TREE || bad)
13135 return bad;
13136
13137 /* If the attributes are followed by a ; or {, then just report any earlier
13138 error. */
13139 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
13140 || c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
13141 return bad;
13142
13143 /* We've got attributes, but not at the end. */
13144 c_parser_error (parser,
13145 gmsgid: "expected %<;%> or %<{%> after method attribute definition");
13146 return true;
13147}
13148
13149/* Parse an objc-method-decl.
13150
13151 objc-method-decl:
13152 ( objc-type-name ) objc-selector
13153 objc-selector
13154 ( objc-type-name ) objc-keyword-selector objc-optparmlist
13155 objc-keyword-selector objc-optparmlist
13156 gnu-attributes
13157
13158 objc-keyword-selector:
13159 objc-keyword-decl
13160 objc-keyword-selector objc-keyword-decl
13161
13162 objc-keyword-decl:
13163 objc-selector : ( objc-type-name ) identifier
13164 objc-selector : identifier
13165 : ( objc-type-name ) identifier
13166 : identifier
13167
13168 objc-optparmlist:
13169 objc-optparms objc-optellipsis
13170
13171 objc-optparms:
13172 empty
13173 objc-opt-parms , parameter-declaration
13174
13175 objc-optellipsis:
13176 empty
13177 , ...
13178*/
13179
13180static tree
13181c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
13182 tree *attributes, tree *expr)
13183{
13184 tree type = NULL_TREE;
13185 tree sel;
13186 tree parms = NULL_TREE;
13187 bool ellipsis = false;
13188 bool attr_err = false;
13189
13190 *attributes = NULL_TREE;
13191 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
13192 {
13193 matching_parens parens;
13194 parens.consume_open (parser);
13195 type = c_parser_objc_type_name (parser);
13196 parens.skip_until_found_close (parser);
13197 }
13198 sel = c_parser_objc_selector (parser);
13199 /* If there is no selector, or a colon follows, we have an
13200 objc-keyword-selector. If there is a selector, and a colon does
13201 not follow, that selector ends the objc-method-decl. */
13202 if (!sel || c_parser_next_token_is (parser, type: CPP_COLON))
13203 {
13204 tree tsel = sel;
13205 tree list = NULL_TREE;
13206 while (true)
13207 {
13208 tree atype = NULL_TREE, id, keyworddecl;
13209 tree param_attr = NULL_TREE;
13210 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
13211 break;
13212 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
13213 {
13214 c_parser_consume_token (parser);
13215 atype = c_parser_objc_type_name (parser);
13216 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
13217 msgid: "expected %<)%>");
13218 }
13219 /* New ObjC allows attributes on method parameters. */
13220 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
13221 param_attr = c_parser_gnu_attributes (parser);
13222 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13223 {
13224 c_parser_error (parser, gmsgid: "expected identifier");
13225 return error_mark_node;
13226 }
13227 id = c_parser_peek_token (parser)->value;
13228 c_parser_consume_token (parser);
13229 keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
13230 list = chainon (list, keyworddecl);
13231 tsel = c_parser_objc_selector (parser);
13232 if (!tsel && c_parser_next_token_is_not (parser, type: CPP_COLON))
13233 break;
13234 }
13235
13236 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
13237
13238 /* Parse the optional parameter list. Optional Objective-C
13239 method parameters follow the C syntax, and may include '...'
13240 to denote a variable number of arguments. */
13241 parms = make_node (TREE_LIST);
13242 while (c_parser_next_token_is (parser, type: CPP_COMMA))
13243 {
13244 struct c_parm *parm;
13245 c_parser_consume_token (parser);
13246 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
13247 {
13248 ellipsis = true;
13249 c_parser_consume_token (parser);
13250 attr_err |= c_parser_objc_maybe_method_attributes
13251 (parser, attributes) ;
13252 break;
13253 }
13254 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
13255 if (parm == NULL)
13256 break;
13257 parms = chainon (parms,
13258 build_tree_list (NULL_TREE, grokparm (parm, expr)));
13259 }
13260 sel = list;
13261 }
13262 else
13263 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
13264
13265 if (sel == NULL)
13266 {
13267 c_parser_error (parser, gmsgid: "objective-c method declaration is expected");
13268 return error_mark_node;
13269 }
13270
13271 if (attr_err)
13272 return error_mark_node;
13273
13274 return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
13275}
13276
13277/* Parse an objc-type-name.
13278
13279 objc-type-name:
13280 objc-type-qualifiers[opt] type-name
13281 objc-type-qualifiers[opt]
13282
13283 objc-type-qualifiers:
13284 objc-type-qualifier
13285 objc-type-qualifiers objc-type-qualifier
13286
13287 objc-type-qualifier: one of
13288 in out inout bycopy byref oneway
13289*/
13290
13291static tree
13292c_parser_objc_type_name (c_parser *parser)
13293{
13294 tree quals = NULL_TREE;
13295 struct c_type_name *type_name = NULL;
13296 tree type = NULL_TREE;
13297 while (true)
13298 {
13299 c_token *token = c_parser_peek_token (parser);
13300 if (token->type == CPP_KEYWORD
13301 && (token->keyword == RID_IN
13302 || token->keyword == RID_OUT
13303 || token->keyword == RID_INOUT
13304 || token->keyword == RID_BYCOPY
13305 || token->keyword == RID_BYREF
13306 || token->keyword == RID_ONEWAY))
13307 {
13308 quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
13309 c_parser_consume_token (parser);
13310 }
13311 else
13312 break;
13313 }
13314 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
13315 type_name = c_parser_type_name (parser);
13316 if (type_name)
13317 type = groktypename (type_name, NULL, NULL);
13318
13319 /* If the type is unknown, and error has already been produced and
13320 we need to recover from the error. In that case, use NULL_TREE
13321 for the type, as if no type had been specified; this will use the
13322 default type ('id') which is good for error recovery. */
13323 if (type == error_mark_node)
13324 type = NULL_TREE;
13325
13326 return build_tree_list (quals, type);
13327}
13328
13329/* Parse objc-protocol-refs.
13330
13331 objc-protocol-refs:
13332 < identifier-list >
13333*/
13334
13335static tree
13336c_parser_objc_protocol_refs (c_parser *parser)
13337{
13338 tree list = NULL_TREE;
13339 gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
13340 c_parser_consume_token (parser);
13341 /* Any identifiers, including those declared as type names, are OK
13342 here. */
13343 while (true)
13344 {
13345 tree id;
13346 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13347 {
13348 c_parser_error (parser, gmsgid: "expected identifier");
13349 break;
13350 }
13351 id = c_parser_peek_token (parser)->value;
13352 list = chainon (list, build_tree_list (NULL_TREE, id));
13353 c_parser_consume_token (parser);
13354 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13355 c_parser_consume_token (parser);
13356 else
13357 break;
13358 }
13359 c_parser_require (parser, type: CPP_GREATER, msgid: "expected %<>%>");
13360 return list;
13361}
13362
13363/* Parse an objc-try-catch-finally-statement.
13364
13365 objc-try-catch-finally-statement:
13366 @try compound-statement objc-catch-list[opt]
13367 @try compound-statement objc-catch-list[opt] @finally compound-statement
13368
13369 objc-catch-list:
13370 @catch ( objc-catch-parameter-declaration ) compound-statement
13371 objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
13372
13373 objc-catch-parameter-declaration:
13374 parameter-declaration
13375 '...'
13376
13377 where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
13378
13379 PS: This function is identical to cp_parser_objc_try_catch_finally_statement
13380 for C++. Keep them in sync. */
13381
13382static void
13383c_parser_objc_try_catch_finally_statement (c_parser *parser)
13384{
13385 location_t location;
13386 tree stmt;
13387
13388 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
13389 c_parser_consume_token (parser);
13390 location = c_parser_peek_token (parser)->location;
13391 objc_maybe_warn_exceptions (location);
13392 stmt = c_parser_compound_statement (parser);
13393 objc_begin_try_stmt (location, stmt);
13394
13395 while (c_parser_next_token_is_keyword (parser, keyword: RID_AT_CATCH))
13396 {
13397 struct c_parm *parm;
13398 tree parameter_declaration = error_mark_node;
13399 bool seen_open_paren = false;
13400
13401 c_parser_consume_token (parser);
13402 matching_parens parens;
13403 if (!parens.require_open (parser))
13404 seen_open_paren = true;
13405 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
13406 {
13407 /* We have "@catch (...)" (where the '...' are literally
13408 what is in the code). Skip the '...'.
13409 parameter_declaration is set to NULL_TREE, and
13410 objc_being_catch_clauses() knows that that means
13411 '...'. */
13412 c_parser_consume_token (parser);
13413 parameter_declaration = NULL_TREE;
13414 }
13415 else
13416 {
13417 /* We have "@catch (NSException *exception)" or something
13418 like that. Parse the parameter declaration. */
13419 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
13420 if (parm == NULL)
13421 parameter_declaration = error_mark_node;
13422 else
13423 parameter_declaration = grokparm (parm, NULL);
13424 }
13425 if (seen_open_paren)
13426 parens.require_close (parser);
13427 else
13428 {
13429 /* If there was no open parenthesis, we are recovering from
13430 an error, and we are trying to figure out what mistake
13431 the user has made. */
13432
13433 /* If there is an immediate closing parenthesis, the user
13434 probably forgot the opening one (ie, they typed "@catch
13435 NSException *e)". Parse the closing parenthesis and keep
13436 going. */
13437 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
13438 c_parser_consume_token (parser);
13439
13440 /* If these is no immediate closing parenthesis, the user
13441 probably doesn't know that parenthesis are required at
13442 all (ie, they typed "@catch NSException *e"). So, just
13443 forget about the closing parenthesis and keep going. */
13444 }
13445 objc_begin_catch_clause (parameter_declaration);
13446 if (c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
13447 c_parser_compound_statement_nostart (parser);
13448 objc_finish_catch_clause ();
13449 }
13450 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_FINALLY))
13451 {
13452 c_parser_consume_token (parser);
13453 location = c_parser_peek_token (parser)->location;
13454 stmt = c_parser_compound_statement (parser);
13455 objc_build_finally_clause (location, stmt);
13456 }
13457 objc_finish_try_stmt ();
13458}
13459
13460/* Parse an objc-synchronized-statement.
13461
13462 objc-synchronized-statement:
13463 @synchronized ( expression ) compound-statement
13464*/
13465
13466static void
13467c_parser_objc_synchronized_statement (c_parser *parser)
13468{
13469 location_t loc;
13470 tree expr, stmt;
13471 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
13472 c_parser_consume_token (parser);
13473 loc = c_parser_peek_token (parser)->location;
13474 objc_maybe_warn_exceptions (loc);
13475 matching_parens parens;
13476 if (parens.require_open (parser))
13477 {
13478 struct c_expr ce = c_parser_expression (parser);
13479 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
13480 expr = ce.value;
13481 expr = c_fully_fold (expr, false, NULL);
13482 parens.skip_until_found_close (parser);
13483 }
13484 else
13485 expr = error_mark_node;
13486 stmt = c_parser_compound_statement (parser);
13487 objc_build_synchronized (loc, expr, stmt);
13488}
13489
13490/* Parse an objc-selector; return NULL_TREE without an error if the
13491 next token is not an objc-selector.
13492
13493 objc-selector:
13494 identifier
13495 one of
13496 enum struct union if else while do for switch case default
13497 break continue return goto asm sizeof typeof typeof_unqual __alignof
13498 unsigned long const short volatile signed restrict _Complex
13499 in out inout bycopy byref oneway int char float double void _Bool
13500 _Atomic
13501
13502 ??? Why this selection of keywords but not, for example, storage
13503 class specifiers? */
13504
13505static tree
13506c_parser_objc_selector (c_parser *parser)
13507{
13508 c_token *token = c_parser_peek_token (parser);
13509 tree value = token->value;
13510 if (token->type == CPP_NAME)
13511 {
13512 c_parser_consume_token (parser);
13513 return value;
13514 }
13515 if (token->type != CPP_KEYWORD)
13516 return NULL_TREE;
13517 switch (token->keyword)
13518 {
13519 case RID_ENUM:
13520 case RID_STRUCT:
13521 case RID_UNION:
13522 case RID_IF:
13523 case RID_ELSE:
13524 case RID_WHILE:
13525 case RID_DO:
13526 case RID_FOR:
13527 case RID_SWITCH:
13528 case RID_CASE:
13529 case RID_DEFAULT:
13530 case RID_BREAK:
13531 case RID_CONTINUE:
13532 case RID_RETURN:
13533 case RID_GOTO:
13534 case RID_ASM:
13535 case RID_SIZEOF:
13536 case RID_TYPEOF:
13537 case RID_TYPEOF_UNQUAL:
13538 case RID_ALIGNOF:
13539 case RID_UNSIGNED:
13540 case RID_LONG:
13541 case RID_CONST:
13542 case RID_SHORT:
13543 case RID_VOLATILE:
13544 case RID_SIGNED:
13545 case RID_RESTRICT:
13546 case RID_COMPLEX:
13547 case RID_IN:
13548 case RID_OUT:
13549 case RID_INOUT:
13550 case RID_BYCOPY:
13551 case RID_BYREF:
13552 case RID_ONEWAY:
13553 case RID_INT:
13554 case RID_CHAR:
13555 case RID_FLOAT:
13556 case RID_DOUBLE:
13557 CASE_RID_FLOATN_NX:
13558 case RID_VOID:
13559 case RID_BOOL:
13560 case RID_ATOMIC:
13561 case RID_AUTO_TYPE:
13562 case RID_INT_N_0:
13563 case RID_INT_N_1:
13564 case RID_INT_N_2:
13565 case RID_INT_N_3:
13566 c_parser_consume_token (parser);
13567 return value;
13568 default:
13569 return NULL_TREE;
13570 }
13571}
13572
13573/* Parse an objc-selector-arg.
13574
13575 objc-selector-arg:
13576 objc-selector
13577 objc-keywordname-list
13578
13579 objc-keywordname-list:
13580 objc-keywordname
13581 objc-keywordname-list objc-keywordname
13582
13583 objc-keywordname:
13584 objc-selector :
13585 :
13586*/
13587
13588static tree
13589c_parser_objc_selector_arg (c_parser *parser)
13590{
13591 tree sel = c_parser_objc_selector (parser);
13592 tree list = NULL_TREE;
13593 if (sel
13594 && c_parser_next_token_is_not (parser, type: CPP_COLON)
13595 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
13596 return sel;
13597 while (true)
13598 {
13599 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
13600 {
13601 c_parser_consume_token (parser);
13602 list = chainon (list, build_tree_list (sel, NULL_TREE));
13603 list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
13604 }
13605 else
13606 {
13607 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
13608 return list;
13609 list = chainon (list, build_tree_list (sel, NULL_TREE));
13610 }
13611 sel = c_parser_objc_selector (parser);
13612 if (!sel
13613 && c_parser_next_token_is_not (parser, type: CPP_COLON)
13614 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
13615 break;
13616 }
13617 return list;
13618}
13619
13620/* Parse an objc-receiver.
13621
13622 objc-receiver:
13623 expression
13624 class-name
13625 type-name
13626*/
13627
13628static tree
13629c_parser_objc_receiver (c_parser *parser)
13630{
13631 location_t loc = c_parser_peek_token (parser)->location;
13632
13633 if (c_parser_peek_token (parser)->type == CPP_NAME
13634 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
13635 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
13636 {
13637 tree id = c_parser_peek_token (parser)->value;
13638 c_parser_consume_token (parser);
13639 return objc_get_class_reference (id);
13640 }
13641 struct c_expr ce = c_parser_expression (parser);
13642 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
13643 return c_fully_fold (ce.value, false, NULL);
13644}
13645
13646/* Parse objc-message-args.
13647
13648 objc-message-args:
13649 objc-selector
13650 objc-keywordarg-list
13651
13652 objc-keywordarg-list:
13653 objc-keywordarg
13654 objc-keywordarg-list objc-keywordarg
13655
13656 objc-keywordarg:
13657 objc-selector : objc-keywordexpr
13658 : objc-keywordexpr
13659*/
13660
13661static tree
13662c_parser_objc_message_args (c_parser *parser)
13663{
13664 tree sel = c_parser_objc_selector (parser);
13665 tree list = NULL_TREE;
13666 if (sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
13667 return sel;
13668 while (true)
13669 {
13670 tree keywordexpr;
13671 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
13672 return error_mark_node;
13673 keywordexpr = c_parser_objc_keywordexpr (parser);
13674 list = chainon (list, build_tree_list (sel, keywordexpr));
13675 sel = c_parser_objc_selector (parser);
13676 if (!sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
13677 break;
13678 }
13679 return list;
13680}
13681
13682/* Parse an objc-keywordexpr.
13683
13684 objc-keywordexpr:
13685 nonempty-expr-list
13686*/
13687
13688static tree
13689c_parser_objc_keywordexpr (c_parser *parser)
13690{
13691 tree ret;
13692 vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, convert_p: true, fold_p: true,
13693 NULL, NULL, NULL, NULL);
13694 if (vec_safe_length (v: expr_list) == 1)
13695 {
13696 /* Just return the expression, remove a level of
13697 indirection. */
13698 ret = (*expr_list)[0];
13699 }
13700 else
13701 {
13702 /* We have a comma expression, we will collapse later. */
13703 ret = build_tree_list_vec (expr_list);
13704 }
13705 release_tree_vector (expr_list);
13706 return ret;
13707}
13708
13709/* A check, needed in several places, that ObjC interface, implementation or
13710 method definitions are not prefixed by incorrect items. */
13711static bool
13712c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
13713 struct c_declspecs *specs)
13714{
13715 if (!specs->declspecs_seen_p || specs->non_sc_seen_p
13716 || specs->typespec_kind != ctsk_none)
13717 {
13718 c_parser_error (parser,
13719 gmsgid: "no type or storage class may be specified here,");
13720 c_parser_skip_to_end_of_block_or_statement (parser);
13721 return true;
13722 }
13723 return false;
13724}
13725
13726/* Parse an Objective-C @property declaration. The syntax is:
13727
13728 objc-property-declaration:
13729 '@property' objc-property-attributes[opt] struct-declaration ;
13730
13731 objc-property-attributes:
13732 '(' objc-property-attribute-list ')'
13733
13734 objc-property-attribute-list:
13735 objc-property-attribute
13736 objc-property-attribute-list, objc-property-attribute
13737
13738 objc-property-attribute
13739 'getter' = identifier
13740 'setter' = identifier
13741 'readonly'
13742 'readwrite'
13743 'assign'
13744 'retain'
13745 'copy'
13746 'nonatomic'
13747
13748 For example:
13749 @property NSString *name;
13750 @property (readonly) id object;
13751 @property (retain, nonatomic, getter=getTheName) id name;
13752 @property int a, b, c;
13753
13754 PS: This function is identical to cp_parser_objc_at_propery_declaration
13755 for C++. Keep them in sync. */
13756static void
13757c_parser_objc_at_property_declaration (c_parser *parser)
13758{
13759 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
13760 location_t loc = c_parser_peek_token (parser)->location;
13761 c_parser_consume_token (parser); /* Eat '@property'. */
13762
13763 /* Parse the optional attribute list.
13764
13765 A list of parsed, but not verified, attributes. */
13766 vec<property_attribute_info *> prop_attr_list = vNULL;
13767
13768 bool syntax_error = false;
13769 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
13770 {
13771 matching_parens parens;
13772
13773 location_t attr_start = c_parser_peek_token (parser)->location;
13774 /* Eat the '(' */
13775 parens.consume_open (parser);
13776
13777 /* Property attribute keywords are valid now. */
13778 parser->objc_property_attr_context = true;
13779
13780 /* Allow @property (), with a warning. */
13781 location_t attr_end = c_parser_peek_token (parser)->location;
13782
13783 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
13784 {
13785 location_t attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
13786 warning_at (attr_comb, OPT_Wattributes,
13787 "empty property attribute list");
13788 }
13789 else
13790 while (true)
13791 {
13792 c_token *token = c_parser_peek_token (parser);
13793 attr_start = token->location;
13794 attr_end = get_finish (loc: token->location);
13795 location_t attr_comb = make_location (caret: attr_start, start: attr_start,
13796 finish: attr_end);
13797
13798 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
13799 {
13800 warning_at (attr_comb, OPT_Wattributes,
13801 "missing property attribute");
13802 if (token->type == CPP_CLOSE_PAREN)
13803 break;
13804 c_parser_consume_token (parser);
13805 continue;
13806 }
13807
13808 tree attr_name = NULL_TREE;
13809 enum rid keyword = RID_MAX; /* Not a valid property attribute. */
13810 bool add_at = false;
13811 if (token->type == CPP_KEYWORD)
13812 {
13813 keyword = token->keyword;
13814 if (OBJC_IS_AT_KEYWORD (keyword))
13815 {
13816 /* For '@' keywords the token value has the keyword,
13817 prepend the '@' for diagnostics. */
13818 attr_name = token->value;
13819 add_at = true;
13820 }
13821 else
13822 attr_name = ridpointers[(int)keyword];
13823 }
13824 else if (token->type == CPP_NAME)
13825 attr_name = token->value;
13826 c_parser_consume_token (parser);
13827
13828 enum objc_property_attribute_kind prop_kind
13829 = objc_prop_attr_kind_for_rid (keyword);
13830 property_attribute_info *prop
13831 = new property_attribute_info (attr_name, attr_comb, prop_kind);
13832 prop_attr_list.safe_push (obj: prop);
13833
13834 tree meth_name;
13835 switch (prop->prop_kind)
13836 {
13837 default: break;
13838 case OBJC_PROPERTY_ATTR_UNKNOWN:
13839 if (attr_name)
13840 error_at (attr_comb, "unknown property attribute %<%s%s%>",
13841 add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
13842 else
13843 error_at (attr_comb, "unknown property attribute");
13844 prop->parse_error = syntax_error = true;
13845 break;
13846
13847 case OBJC_PROPERTY_ATTR_GETTER:
13848 case OBJC_PROPERTY_ATTR_SETTER:
13849 if (c_parser_next_token_is_not (parser, type: CPP_EQ))
13850 {
13851 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
13852 error_at (attr_comb, "expected %<=%> after Objective-C %qE",
13853 attr_name);
13854 prop->parse_error = syntax_error = true;
13855 break;
13856 }
13857 token = c_parser_peek_token (parser);
13858 attr_end = token->location;
13859 c_parser_consume_token (parser); /* eat the = */
13860 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13861 {
13862 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
13863 error_at (attr_comb, "expected %qE selector name",
13864 attr_name);
13865 prop->parse_error = syntax_error = true;
13866 break;
13867 }
13868 /* Get the end of the method name, and consume the name. */
13869 token = c_parser_peek_token (parser);
13870 attr_end = get_finish (loc: token->location);
13871 meth_name = token->value;
13872 c_parser_consume_token (parser);
13873 if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
13874 {
13875 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
13876 {
13877 attr_comb = make_location (caret: attr_end, start: attr_start,
13878 finish: attr_end);
13879 error_at (attr_comb, "setter method names must"
13880 " terminate with %<:%>");
13881 prop->parse_error = syntax_error = true;
13882 }
13883 else
13884 {
13885 attr_end = get_finish (loc: c_parser_peek_token
13886 (parser)->location);
13887 c_parser_consume_token (parser);
13888 }
13889 attr_comb = make_location (caret: attr_start, start: attr_start,
13890 finish: attr_end);
13891 }
13892 else
13893 attr_comb = make_location (caret: attr_start, start: attr_start,
13894 finish: attr_end);
13895 prop->ident = meth_name;
13896 /* Updated location including all that was successfully
13897 parsed. */
13898 prop->prop_loc = attr_comb;
13899 break;
13900 }
13901
13902 /* If we see a comma here, then keep going - even if we already
13903 saw a syntax error. For simple mistakes e.g. (asign, getter=x)
13904 this makes a more useful output and avoid spurious warnings about
13905 missing attributes that are, in fact, specified after the one with
13906 the syntax error. */
13907 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13908 c_parser_consume_token (parser);
13909 else
13910 break;
13911 }
13912 parser->objc_property_attr_context = false;
13913
13914 if (syntax_error && c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
13915 /* We don't really want to chew the whole of the file looking for a
13916 matching closing parenthesis, so we will try to read the decl and
13917 let the error handling for that close out the statement. */
13918 ;
13919 else
13920 syntax_error = false, parens.skip_until_found_close (parser);
13921 }
13922
13923 /* 'properties' is the list of properties that we read. Usually a
13924 single one, but maybe more (eg, in "@property int a, b, c;" there
13925 are three). */
13926 tree properties = c_parser_struct_declaration (parser, NULL);
13927
13928 if (properties == error_mark_node)
13929 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13930 else
13931 {
13932 if (properties == NULL_TREE)
13933 c_parser_error (parser, gmsgid: "expected identifier");
13934 else
13935 {
13936 /* Comma-separated properties are chained together in reverse order;
13937 add them one by one. */
13938 properties = nreverse (properties);
13939 for (; properties; properties = TREE_CHAIN (properties))
13940 objc_add_property_declaration (loc, copy_node (properties),
13941 prop_attr_list);
13942 }
13943 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
13944 }
13945
13946 while (!prop_attr_list.is_empty())
13947 delete prop_attr_list.pop ();
13948 prop_attr_list.release ();
13949 parser->error = false;
13950}
13951
13952/* Parse an Objective-C @synthesize declaration. The syntax is:
13953
13954 objc-synthesize-declaration:
13955 @synthesize objc-synthesize-identifier-list ;
13956
13957 objc-synthesize-identifier-list:
13958 objc-synthesize-identifier
13959 objc-synthesize-identifier-list, objc-synthesize-identifier
13960
13961 objc-synthesize-identifier
13962 identifier
13963 identifier = identifier
13964
13965 For example:
13966 @synthesize MyProperty;
13967 @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
13968
13969 PS: This function is identical to cp_parser_objc_at_synthesize_declaration
13970 for C++. Keep them in sync.
13971*/
13972static void
13973c_parser_objc_at_synthesize_declaration (c_parser *parser)
13974{
13975 tree list = NULL_TREE;
13976 location_t loc;
13977 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
13978 loc = c_parser_peek_token (parser)->location;
13979
13980 c_parser_consume_token (parser);
13981 while (true)
13982 {
13983 tree property, ivar;
13984 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13985 {
13986 c_parser_error (parser, gmsgid: "expected identifier");
13987 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
13988 /* Once we find the semicolon, we can resume normal parsing.
13989 We have to reset parser->error manually because
13990 c_parser_skip_until_found() won't reset it for us if the
13991 next token is precisely a semicolon. */
13992 parser->error = false;
13993 return;
13994 }
13995 property = c_parser_peek_token (parser)->value;
13996 c_parser_consume_token (parser);
13997 if (c_parser_next_token_is (parser, type: CPP_EQ))
13998 {
13999 c_parser_consume_token (parser);
14000 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14001 {
14002 c_parser_error (parser, gmsgid: "expected identifier");
14003 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14004 parser->error = false;
14005 return;
14006 }
14007 ivar = c_parser_peek_token (parser)->value;
14008 c_parser_consume_token (parser);
14009 }
14010 else
14011 ivar = NULL_TREE;
14012 list = chainon (list, build_tree_list (ivar, property));
14013 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14014 c_parser_consume_token (parser);
14015 else
14016 break;
14017 }
14018 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14019 objc_add_synthesize_declaration (loc, list);
14020}
14021
14022/* Parse an Objective-C @dynamic declaration. The syntax is:
14023
14024 objc-dynamic-declaration:
14025 @dynamic identifier-list ;
14026
14027 For example:
14028 @dynamic MyProperty;
14029 @dynamic MyProperty, AnotherProperty;
14030
14031 PS: This function is identical to cp_parser_objc_at_dynamic_declaration
14032 for C++. Keep them in sync.
14033*/
14034static void
14035c_parser_objc_at_dynamic_declaration (c_parser *parser)
14036{
14037 tree list = NULL_TREE;
14038 location_t loc;
14039 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
14040 loc = c_parser_peek_token (parser)->location;
14041
14042 c_parser_consume_token (parser);
14043 while (true)
14044 {
14045 tree property;
14046 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14047 {
14048 c_parser_error (parser, gmsgid: "expected identifier");
14049 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14050 parser->error = false;
14051 return;
14052 }
14053 property = c_parser_peek_token (parser)->value;
14054 list = chainon (list, build_tree_list (NULL_TREE, property));
14055 c_parser_consume_token (parser);
14056 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14057 c_parser_consume_token (parser);
14058 else
14059 break;
14060 }
14061 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14062 objc_add_dynamic_declaration (loc, list);
14063}
14064
14065
14066/* Parse a pragma GCC ivdep. */
14067
14068static bool
14069c_parse_pragma_ivdep (c_parser *parser)
14070{
14071 c_parser_consume_pragma (parser);
14072 c_parser_skip_to_pragma_eol (parser);
14073 return true;
14074}
14075
14076/* Parse a pragma GCC novector. */
14077
14078static bool
14079c_parse_pragma_novector (c_parser *parser)
14080{
14081 c_parser_consume_pragma (parser);
14082 c_parser_skip_to_pragma_eol (parser);
14083 return true;
14084}
14085
14086/* Parse a pragma GCC unroll. */
14087
14088static unsigned short
14089c_parser_pragma_unroll (c_parser *parser)
14090{
14091 unsigned short unroll;
14092 c_parser_consume_pragma (parser);
14093 location_t location = c_parser_peek_token (parser)->location;
14094 tree expr = c_parser_expr_no_commas (parser, NULL).value;
14095 mark_exp_read (expr);
14096 expr = c_fully_fold (expr, false, NULL);
14097 HOST_WIDE_INT lunroll = 0;
14098 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
14099 || TREE_CODE (expr) != INTEGER_CST
14100 || (lunroll = tree_to_shwi (expr)) < 0
14101 || lunroll >= USHRT_MAX)
14102 {
14103 error_at (location, "%<#pragma GCC unroll%> requires an"
14104 " assignment-expression that evaluates to a non-negative"
14105 " integral constant less than %u", USHRT_MAX);
14106 unroll = 0;
14107 }
14108 else
14109 {
14110 unroll = (unsigned short)lunroll;
14111 if (unroll == 0)
14112 unroll = 1;
14113 }
14114
14115 c_parser_skip_to_pragma_eol (parser);
14116 return unroll;
14117}
14118
14119/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
14120 should be considered, statements. ALLOW_STMT is true if we're within
14121 the context of a function and such pragmas are to be allowed. Returns
14122 true if we actually parsed such a pragma. */
14123
14124static bool
14125c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
14126{
14127 unsigned int id;
14128 const char *construct = NULL;
14129
14130 input_location = c_parser_peek_token (parser)->location;
14131 id = c_parser_peek_token (parser)->pragma_kind;
14132 gcc_assert (id != PRAGMA_NONE);
14133 if (parser->omp_for_parse_state
14134 && parser->omp_for_parse_state->in_intervening_code
14135 && id >= PRAGMA_OMP__START_
14136 && id <= PRAGMA_OMP__LAST_)
14137 {
14138 error_at (input_location,
14139 "intervening code must not contain OpenMP directives");
14140 parser->omp_for_parse_state->fail = true;
14141 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14142 return false;
14143 }
14144
14145 switch (id)
14146 {
14147 case PRAGMA_OACC_DECLARE:
14148 c_parser_oacc_declare (parser);
14149 return false;
14150
14151 case PRAGMA_OACC_ENTER_DATA:
14152 if (context != pragma_compound)
14153 {
14154 construct = "acc enter data";
14155 in_compound:
14156 if (context == pragma_stmt)
14157 {
14158 error_at (c_parser_peek_token (parser)->location,
14159 "%<#pragma %s%> may only be used in compound "
14160 "statements", construct);
14161 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14162 return true;
14163 }
14164 goto bad_stmt;
14165 }
14166 c_parser_oacc_enter_exit_data (parser, true);
14167 return false;
14168
14169 case PRAGMA_OACC_EXIT_DATA:
14170 if (context != pragma_compound)
14171 {
14172 construct = "acc exit data";
14173 goto in_compound;
14174 }
14175 c_parser_oacc_enter_exit_data (parser, false);
14176 return false;
14177
14178 case PRAGMA_OACC_ROUTINE:
14179 if (context != pragma_external)
14180 {
14181 error_at (c_parser_peek_token (parser)->location,
14182 "%<#pragma acc routine%> must be at file scope");
14183 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14184 return false;
14185 }
14186 c_parser_oacc_routine (parser, context);
14187 return false;
14188
14189 case PRAGMA_OACC_UPDATE:
14190 if (context != pragma_compound)
14191 {
14192 construct = "acc update";
14193 goto in_compound;
14194 }
14195 c_parser_oacc_update (parser);
14196 return false;
14197
14198 case PRAGMA_OMP_BARRIER:
14199 if (context != pragma_compound)
14200 {
14201 construct = "omp barrier";
14202 goto in_compound;
14203 }
14204 c_parser_omp_barrier (parser);
14205 return false;
14206
14207 case PRAGMA_OMP_DEPOBJ:
14208 if (context != pragma_compound)
14209 {
14210 construct = "omp depobj";
14211 goto in_compound;
14212 }
14213 c_parser_omp_depobj (parser);
14214 return false;
14215
14216 case PRAGMA_OMP_FLUSH:
14217 if (context != pragma_compound)
14218 {
14219 construct = "omp flush";
14220 goto in_compound;
14221 }
14222 c_parser_omp_flush (parser);
14223 return false;
14224
14225 case PRAGMA_OMP_TASKWAIT:
14226 if (context != pragma_compound)
14227 {
14228 construct = "omp taskwait";
14229 goto in_compound;
14230 }
14231 c_parser_omp_taskwait (parser);
14232 return false;
14233
14234 case PRAGMA_OMP_TASKYIELD:
14235 if (context != pragma_compound)
14236 {
14237 construct = "omp taskyield";
14238 goto in_compound;
14239 }
14240 c_parser_omp_taskyield (parser);
14241 return false;
14242
14243 case PRAGMA_OMP_CANCEL:
14244 if (context != pragma_compound)
14245 {
14246 construct = "omp cancel";
14247 goto in_compound;
14248 }
14249 c_parser_omp_cancel (parser);
14250 return false;
14251
14252 case PRAGMA_OMP_CANCELLATION_POINT:
14253 return c_parser_omp_cancellation_point (parser, context);
14254
14255 case PRAGMA_OMP_THREADPRIVATE:
14256 c_parser_omp_threadprivate (parser);
14257 return false;
14258
14259 case PRAGMA_OMP_TARGET:
14260 return c_parser_omp_target (parser, context, if_p);
14261
14262 case PRAGMA_OMP_BEGIN:
14263 c_parser_omp_begin (parser);
14264 return false;
14265
14266 case PRAGMA_OMP_END:
14267 c_parser_omp_end (parser);
14268 return false;
14269
14270 case PRAGMA_OMP_SCAN:
14271 error_at (c_parser_peek_token (parser)->location,
14272 "%<#pragma omp scan%> may only be used in "
14273 "a loop construct with %<inscan%> %<reduction%> clause");
14274 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14275 return false;
14276
14277 case PRAGMA_OMP_SECTION:
14278 error_at (c_parser_peek_token (parser)->location,
14279 "%<#pragma omp section%> may only be used in "
14280 "%<#pragma omp sections%> construct");
14281 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14282 return false;
14283
14284 case PRAGMA_OMP_DECLARE:
14285 return c_parser_omp_declare (parser, context);
14286
14287 case PRAGMA_OMP_REQUIRES:
14288 if (context != pragma_external)
14289 {
14290 error_at (c_parser_peek_token (parser)->location,
14291 "%<#pragma %s%> may only be used at file scope",
14292 "omp requires");
14293 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14294 return false;
14295 }
14296 c_parser_omp_requires (parser);
14297 return false;
14298
14299 case PRAGMA_OMP_ALLOCATE:
14300 c_parser_omp_allocate (parser);
14301 return false;
14302
14303 case PRAGMA_OMP_ASSUMES:
14304 if (context != pragma_external)
14305 {
14306 error_at (c_parser_peek_token (parser)->location,
14307 "%<#pragma %s%> may only be used at file scope",
14308 "omp assumes");
14309 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14310 return false;
14311 }
14312 c_parser_omp_assumes (parser);
14313 return false;
14314
14315 case PRAGMA_OMP_NOTHING:
14316 c_parser_omp_nothing (parser);
14317 return false;
14318
14319 case PRAGMA_OMP_ERROR:
14320 return c_parser_omp_error (parser, context);
14321
14322 case PRAGMA_OMP_ORDERED:
14323 return c_parser_omp_ordered (parser, context, if_p);
14324
14325 case PRAGMA_NOVECTOR:
14326 case PRAGMA_UNROLL:
14327 case PRAGMA_IVDEP:
14328 {
14329 bool novector = false;
14330 unsigned short unroll = 0;
14331 bool ivdep = false;
14332
14333 switch (id)
14334 {
14335 case PRAGMA_NOVECTOR:
14336 novector = c_parse_pragma_novector (parser);
14337 break;
14338 case PRAGMA_UNROLL:
14339 unroll = c_parser_pragma_unroll (parser);
14340 break;
14341 case PRAGMA_IVDEP:
14342 ivdep = c_parse_pragma_ivdep (parser);
14343 break;
14344 default:
14345 gcc_unreachable ();
14346 }
14347
14348 c_token *tok = c_parser_peek_token (parser);
14349 bool has_more = tok->type == CPP_PRAGMA;
14350 while (has_more)
14351 {
14352 switch (tok->pragma_kind)
14353 {
14354 case PRAGMA_IVDEP:
14355 ivdep = c_parse_pragma_ivdep (parser);
14356 break;
14357 case PRAGMA_UNROLL:
14358 unroll = c_parser_pragma_unroll (parser);
14359 break;
14360 case PRAGMA_NOVECTOR:
14361 novector = c_parse_pragma_novector (parser);
14362 break;
14363 default:
14364 has_more = false;
14365 break;
14366 }
14367 tok = c_parser_peek_token (parser);
14368 has_more = has_more && tok->type == CPP_PRAGMA;
14369 }
14370 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR)
14371 && !c_parser_next_token_is_keyword (parser, keyword: RID_WHILE)
14372 && !c_parser_next_token_is_keyword (parser, keyword: RID_DO))
14373 {
14374 c_parser_error (parser, gmsgid: "for, while or do statement expected");
14375 return false;
14376 }
14377 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
14378 c_parser_for_statement (parser, ivdep, unroll, novector, if_p);
14379 else if (c_parser_next_token_is_keyword (parser, keyword: RID_WHILE))
14380 c_parser_while_statement (parser, ivdep, unroll, novector, if_p);
14381 else
14382 c_parser_do_statement (parser, ivdep, unroll, novector);
14383 }
14384 return true;
14385
14386 case PRAGMA_GCC_PCH_PREPROCESS:
14387 c_parser_error (parser, gmsgid: "%<#pragma GCC pch_preprocess%> must be first");
14388 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14389 return false;
14390
14391 case PRAGMA_OACC_WAIT:
14392 if (context != pragma_compound)
14393 {
14394 construct = "acc wait";
14395 goto in_compound;
14396 }
14397 /* FALL THROUGH. */
14398
14399 default:
14400 if (id < PRAGMA_FIRST_EXTERNAL)
14401 {
14402 if (context != pragma_stmt && context != pragma_compound)
14403 {
14404 bad_stmt:
14405 c_parser_error (parser, gmsgid: "expected declaration specifiers");
14406 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
14407 return false;
14408 }
14409 c_parser_omp_construct (parser, if_p);
14410 return true;
14411 }
14412 break;
14413 }
14414
14415 c_parser_consume_pragma (parser);
14416 c_invoke_pragma_handler (id);
14417
14418 /* Skip to EOL, but suppress any error message. Those will have been
14419 generated by the handler routine through calling error, as opposed
14420 to calling c_parser_error. */
14421 parser->error = true;
14422 c_parser_skip_to_pragma_eol (parser);
14423
14424 return false;
14425}
14426
14427/* The interface the pragma parsers have to the lexer. */
14428
14429enum cpp_ttype
14430pragma_lex (tree *value, location_t *loc)
14431{
14432 c_token *tok = c_parser_peek_token (parser: the_parser);
14433 enum cpp_ttype ret = tok->type;
14434
14435 *value = tok->value;
14436 if (loc)
14437 *loc = tok->location;
14438
14439 if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
14440 ret = CPP_EOF;
14441 else if (ret == CPP_STRING)
14442 *value = c_parser_string_literal (parser: the_parser, translate: false, wide_ok: false).value;
14443 else
14444 {
14445 if (ret == CPP_KEYWORD)
14446 ret = CPP_NAME;
14447 c_parser_consume_token (parser: the_parser);
14448 }
14449
14450 return ret;
14451}
14452
14453void
14454pragma_lex_discard_to_eol ()
14455{
14456 cpp_ttype type;
14457 do
14458 {
14459 type = c_parser_peek_token (parser: the_parser)->type;
14460 gcc_assert (type != CPP_EOF);
14461 c_parser_consume_token (parser: the_parser);
14462 } while (type != CPP_PRAGMA_EOL);
14463}
14464
14465static void
14466c_parser_pragma_pch_preprocess (c_parser *parser)
14467{
14468 tree name = NULL;
14469
14470 parser->lex_joined_string = true;
14471 c_parser_consume_pragma (parser);
14472 if (c_parser_next_token_is (parser, type: CPP_STRING))
14473 {
14474 name = c_parser_peek_token (parser)->value;
14475 c_parser_consume_token (parser);
14476 }
14477 else
14478 c_parser_error (parser, gmsgid: "expected string literal");
14479 c_parser_skip_to_pragma_eol (parser);
14480 parser->lex_joined_string = false;
14481
14482 if (name)
14483 c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name));
14484}
14485
14486/* OpenACC and OpenMP parsing routines. */
14487
14488/* Returns name of the next clause.
14489 If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
14490 the token is not consumed. Otherwise appropriate pragma_omp_clause is
14491 returned and the token is consumed. */
14492
14493static pragma_omp_clause
14494c_parser_omp_clause_name (c_parser *parser)
14495{
14496 pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
14497
14498 if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
14499 result = PRAGMA_OACC_CLAUSE_AUTO;
14500 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IF))
14501 result = PRAGMA_OMP_CLAUSE_IF;
14502 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
14503 result = PRAGMA_OMP_CLAUSE_DEFAULT;
14504 else if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
14505 result = PRAGMA_OMP_CLAUSE_FOR;
14506 else if (c_parser_next_token_is (parser, type: CPP_NAME))
14507 {
14508 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
14509
14510 switch (p[0])
14511 {
14512 case 'a':
14513 if (!strcmp (s1: "affinity", s2: p))
14514 result = PRAGMA_OMP_CLAUSE_AFFINITY;
14515 else if (!strcmp (s1: "aligned", s2: p))
14516 result = PRAGMA_OMP_CLAUSE_ALIGNED;
14517 else if (!strcmp (s1: "allocate", s2: p))
14518 result = PRAGMA_OMP_CLAUSE_ALLOCATE;
14519 else if (!strcmp (s1: "async", s2: p))
14520 result = PRAGMA_OACC_CLAUSE_ASYNC;
14521 else if (!strcmp (s1: "attach", s2: p))
14522 result = PRAGMA_OACC_CLAUSE_ATTACH;
14523 break;
14524 case 'b':
14525 if (!strcmp (s1: "bind", s2: p))
14526 result = PRAGMA_OMP_CLAUSE_BIND;
14527 break;
14528 case 'c':
14529 if (!strcmp (s1: "collapse", s2: p))
14530 result = PRAGMA_OMP_CLAUSE_COLLAPSE;
14531 else if (!strcmp (s1: "copy", s2: p))
14532 result = PRAGMA_OACC_CLAUSE_COPY;
14533 else if (!strcmp (s1: "copyin", s2: p))
14534 result = PRAGMA_OMP_CLAUSE_COPYIN;
14535 else if (!strcmp (s1: "copyout", s2: p))
14536 result = PRAGMA_OACC_CLAUSE_COPYOUT;
14537 else if (!strcmp (s1: "copyprivate", s2: p))
14538 result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
14539 else if (!strcmp (s1: "create", s2: p))
14540 result = PRAGMA_OACC_CLAUSE_CREATE;
14541 break;
14542 case 'd':
14543 if (!strcmp (s1: "defaultmap", s2: p))
14544 result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
14545 else if (!strcmp (s1: "delete", s2: p))
14546 result = PRAGMA_OACC_CLAUSE_DELETE;
14547 else if (!strcmp (s1: "depend", s2: p))
14548 result = PRAGMA_OMP_CLAUSE_DEPEND;
14549 else if (!strcmp (s1: "detach", s2: p))
14550 result = PRAGMA_OACC_CLAUSE_DETACH;
14551 else if (!strcmp (s1: "device", s2: p))
14552 result = PRAGMA_OMP_CLAUSE_DEVICE;
14553 else if (!strcmp (s1: "deviceptr", s2: p))
14554 result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
14555 else if (!strcmp (s1: "device_resident", s2: p))
14556 result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
14557 else if (!strcmp (s1: "device_type", s2: p))
14558 result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
14559 else if (!strcmp (s1: "dist_schedule", s2: p))
14560 result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
14561 else if (!strcmp (s1: "doacross", s2: p))
14562 result = PRAGMA_OMP_CLAUSE_DOACROSS;
14563 break;
14564 case 'e':
14565 if (!strcmp (s1: "enter", s2: p))
14566 result = PRAGMA_OMP_CLAUSE_ENTER;
14567 break;
14568 case 'f':
14569 if (!strcmp (s1: "filter", s2: p))
14570 result = PRAGMA_OMP_CLAUSE_FILTER;
14571 else if (!strcmp (s1: "final", s2: p))
14572 result = PRAGMA_OMP_CLAUSE_FINAL;
14573 else if (!strcmp (s1: "finalize", s2: p))
14574 result = PRAGMA_OACC_CLAUSE_FINALIZE;
14575 else if (!strcmp (s1: "firstprivate", s2: p))
14576 result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
14577 else if (!strcmp (s1: "from", s2: p))
14578 result = PRAGMA_OMP_CLAUSE_FROM;
14579 break;
14580 case 'g':
14581 if (!strcmp (s1: "gang", s2: p))
14582 result = PRAGMA_OACC_CLAUSE_GANG;
14583 else if (!strcmp (s1: "grainsize", s2: p))
14584 result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
14585 break;
14586 case 'h':
14587 if (!strcmp (s1: "has_device_addr", s2: p))
14588 result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
14589 else if (!strcmp (s1: "hint", s2: p))
14590 result = PRAGMA_OMP_CLAUSE_HINT;
14591 else if (!strcmp (s1: "host", s2: p))
14592 result = PRAGMA_OACC_CLAUSE_HOST;
14593 break;
14594 case 'i':
14595 if (!strcmp (s1: "if_present", s2: p))
14596 result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
14597 else if (!strcmp (s1: "in_reduction", s2: p))
14598 result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
14599 else if (!strcmp (s1: "inbranch", s2: p))
14600 result = PRAGMA_OMP_CLAUSE_INBRANCH;
14601 else if (!strcmp (s1: "indirect", s2: p))
14602 result = PRAGMA_OMP_CLAUSE_INDIRECT;
14603 else if (!strcmp (s1: "independent", s2: p))
14604 result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
14605 else if (!strcmp (s1: "is_device_ptr", s2: p))
14606 result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
14607 break;
14608 case 'l':
14609 if (!strcmp (s1: "lastprivate", s2: p))
14610 result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
14611 else if (!strcmp (s1: "linear", s2: p))
14612 result = PRAGMA_OMP_CLAUSE_LINEAR;
14613 else if (!strcmp (s1: "link", s2: p))
14614 result = PRAGMA_OMP_CLAUSE_LINK;
14615 break;
14616 case 'm':
14617 if (!strcmp (s1: "map", s2: p))
14618 result = PRAGMA_OMP_CLAUSE_MAP;
14619 else if (!strcmp (s1: "mergeable", s2: p))
14620 result = PRAGMA_OMP_CLAUSE_MERGEABLE;
14621 break;
14622 case 'n':
14623 if (!strcmp (s1: "no_create", s2: p))
14624 result = PRAGMA_OACC_CLAUSE_NO_CREATE;
14625 else if (!strcmp (s1: "nogroup", s2: p))
14626 result = PRAGMA_OMP_CLAUSE_NOGROUP;
14627 else if (!strcmp (s1: "nohost", s2: p))
14628 result = PRAGMA_OACC_CLAUSE_NOHOST;
14629 else if (!strcmp (s1: "nontemporal", s2: p))
14630 result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
14631 else if (!strcmp (s1: "notinbranch", s2: p))
14632 result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
14633 else if (!strcmp (s1: "nowait", s2: p))
14634 result = PRAGMA_OMP_CLAUSE_NOWAIT;
14635 else if (!strcmp (s1: "num_gangs", s2: p))
14636 result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
14637 else if (!strcmp (s1: "num_tasks", s2: p))
14638 result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
14639 else if (!strcmp (s1: "num_teams", s2: p))
14640 result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
14641 else if (!strcmp (s1: "num_threads", s2: p))
14642 result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
14643 else if (!strcmp (s1: "num_workers", s2: p))
14644 result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
14645 break;
14646 case 'o':
14647 if (!strcmp (s1: "ordered", s2: p))
14648 result = PRAGMA_OMP_CLAUSE_ORDERED;
14649 else if (!strcmp (s1: "order", s2: p))
14650 result = PRAGMA_OMP_CLAUSE_ORDER;
14651 break;
14652 case 'p':
14653 if (!strcmp (s1: "parallel", s2: p))
14654 result = PRAGMA_OMP_CLAUSE_PARALLEL;
14655 else if (!strcmp (s1: "present", s2: p))
14656 result = PRAGMA_OACC_CLAUSE_PRESENT;
14657 /* As of OpenACC 2.5, these are now aliases of the non-present_or
14658 clauses. */
14659 else if (!strcmp (s1: "present_or_copy", s2: p)
14660 || !strcmp (s1: "pcopy", s2: p))
14661 result = PRAGMA_OACC_CLAUSE_COPY;
14662 else if (!strcmp (s1: "present_or_copyin", s2: p)
14663 || !strcmp (s1: "pcopyin", s2: p))
14664 result = PRAGMA_OACC_CLAUSE_COPYIN;
14665 else if (!strcmp (s1: "present_or_copyout", s2: p)
14666 || !strcmp (s1: "pcopyout", s2: p))
14667 result = PRAGMA_OACC_CLAUSE_COPYOUT;
14668 else if (!strcmp (s1: "present_or_create", s2: p)
14669 || !strcmp (s1: "pcreate", s2: p))
14670 result = PRAGMA_OACC_CLAUSE_CREATE;
14671 else if (!strcmp (s1: "priority", s2: p))
14672 result = PRAGMA_OMP_CLAUSE_PRIORITY;
14673 else if (!strcmp (s1: "private", s2: p))
14674 result = PRAGMA_OMP_CLAUSE_PRIVATE;
14675 else if (!strcmp (s1: "proc_bind", s2: p))
14676 result = PRAGMA_OMP_CLAUSE_PROC_BIND;
14677 break;
14678 case 'r':
14679 if (!strcmp (s1: "reduction", s2: p))
14680 result = PRAGMA_OMP_CLAUSE_REDUCTION;
14681 break;
14682 case 's':
14683 if (!strcmp (s1: "safelen", s2: p))
14684 result = PRAGMA_OMP_CLAUSE_SAFELEN;
14685 else if (!strcmp (s1: "schedule", s2: p))
14686 result = PRAGMA_OMP_CLAUSE_SCHEDULE;
14687 else if (!strcmp (s1: "sections", s2: p))
14688 result = PRAGMA_OMP_CLAUSE_SECTIONS;
14689 else if (!strcmp (s1: "self", s2: p))
14690 result = PRAGMA_OACC_CLAUSE_SELF;
14691 else if (!strcmp (s1: "seq", s2: p))
14692 result = PRAGMA_OACC_CLAUSE_SEQ;
14693 else if (!strcmp (s1: "shared", s2: p))
14694 result = PRAGMA_OMP_CLAUSE_SHARED;
14695 else if (!strcmp (s1: "simd", s2: p))
14696 result = PRAGMA_OMP_CLAUSE_SIMD;
14697 else if (!strcmp (s1: "simdlen", s2: p))
14698 result = PRAGMA_OMP_CLAUSE_SIMDLEN;
14699 break;
14700 case 't':
14701 if (!strcmp (s1: "task_reduction", s2: p))
14702 result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
14703 else if (!strcmp (s1: "taskgroup", s2: p))
14704 result = PRAGMA_OMP_CLAUSE_TASKGROUP;
14705 else if (!strcmp (s1: "thread_limit", s2: p))
14706 result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
14707 else if (!strcmp (s1: "threads", s2: p))
14708 result = PRAGMA_OMP_CLAUSE_THREADS;
14709 else if (!strcmp (s1: "tile", s2: p))
14710 result = PRAGMA_OACC_CLAUSE_TILE;
14711 else if (!strcmp (s1: "to", s2: p))
14712 result = PRAGMA_OMP_CLAUSE_TO;
14713 break;
14714 case 'u':
14715 if (!strcmp (s1: "uniform", s2: p))
14716 result = PRAGMA_OMP_CLAUSE_UNIFORM;
14717 else if (!strcmp (s1: "untied", s2: p))
14718 result = PRAGMA_OMP_CLAUSE_UNTIED;
14719 else if (!strcmp (s1: "use_device", s2: p))
14720 result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
14721 else if (!strcmp (s1: "use_device_addr", s2: p))
14722 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
14723 else if (!strcmp (s1: "use_device_ptr", s2: p))
14724 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
14725 break;
14726 case 'v':
14727 if (!strcmp (s1: "vector", s2: p))
14728 result = PRAGMA_OACC_CLAUSE_VECTOR;
14729 else if (!strcmp (s1: "vector_length", s2: p))
14730 result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
14731 break;
14732 case 'w':
14733 if (!strcmp (s1: "wait", s2: p))
14734 result = PRAGMA_OACC_CLAUSE_WAIT;
14735 else if (!strcmp (s1: "worker", s2: p))
14736 result = PRAGMA_OACC_CLAUSE_WORKER;
14737 break;
14738 }
14739 }
14740
14741 if (result != PRAGMA_OMP_CLAUSE_NONE)
14742 c_parser_consume_token (parser);
14743
14744 return result;
14745}
14746
14747/* Validate that a clause of the given type does not already exist. */
14748
14749static void
14750check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
14751 const char *name)
14752{
14753 if (tree c = omp_find_clause (clauses, kind: code))
14754 error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
14755}
14756
14757/* OpenACC 2.0
14758 Parse wait clause or wait directive parameters. */
14759
14760static tree
14761c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
14762{
14763 vec<tree, va_gc> *args;
14764 tree t, args_tree;
14765
14766 matching_parens parens;
14767 if (!parens.require_open (parser))
14768 return list;
14769
14770 args = c_parser_expr_list (parser, convert_p: false, fold_p: true, NULL, NULL, NULL, NULL);
14771 args_tree = build_tree_list_vec (args);
14772
14773 for (t = args_tree; t; t = TREE_CHAIN (t))
14774 {
14775 tree targ = TREE_VALUE (t);
14776
14777 if (targ != error_mark_node)
14778 {
14779 if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
14780 {
14781 c_parser_error (parser, gmsgid: "expression must be integral");
14782 targ = error_mark_node;
14783 }
14784 else
14785 {
14786 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
14787
14788 OMP_CLAUSE_DECL (c) = targ;
14789 OMP_CLAUSE_CHAIN (c) = list;
14790 list = c;
14791 }
14792 }
14793 }
14794
14795 release_tree_vector (args);
14796 parens.require_close (parser);
14797 return list;
14798}
14799
14800/* OpenACC 2.0, OpenMP 2.5:
14801 variable-list:
14802 identifier
14803 variable-list , identifier
14804
14805 If KIND is nonzero, create the appropriate node and install the
14806 decl in OMP_CLAUSE_DECL and add the node to the head of the list.
14807 If KIND is nonzero, CLAUSE_LOC is the location of the clause.
14808
14809 If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
14810 return the list created.
14811
14812 The optional ALLOW_DEREF argument is true if list items can use the deref
14813 (->) operator. */
14814
14815struct omp_dim
14816{
14817 tree low_bound, length;
14818 location_t loc;
14819 bool no_colon;
14820 omp_dim (tree lb, tree len, location_t lo, bool nc)
14821 : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
14822};
14823
14824static tree
14825c_parser_omp_variable_list (c_parser *parser,
14826 location_t clause_loc,
14827 enum omp_clause_code kind, tree list,
14828 bool allow_deref = false)
14829{
14830 auto_vec<omp_dim> dims;
14831 bool array_section_p;
14832 auto_vec<c_token> tokens;
14833 unsigned int tokens_avail = 0;
14834 c_token *saved_tokens = NULL;
14835 bool first = true;
14836
14837 while (1)
14838 {
14839 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
14840 {
14841 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
14842 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
14843 {
14844 struct c_expr expr;
14845 if (kind == OMP_CLAUSE_DEPEND
14846 && c_parser_next_token_is_keyword (parser,
14847 keyword: RID_OMP_ALL_MEMORY)
14848 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14849 || (c_parser_peek_2nd_token (parser)->type
14850 == CPP_CLOSE_PAREN)))
14851 {
14852 expr.value = ridpointers[RID_OMP_ALL_MEMORY];
14853 c_parser_consume_token (parser);
14854 }
14855 else
14856 expr = c_parser_expr_no_commas (parser, NULL);
14857 if (expr.value != error_mark_node)
14858 {
14859 tree u = build_omp_clause (clause_loc, kind);
14860 OMP_CLAUSE_DECL (u) = expr.value;
14861 OMP_CLAUSE_CHAIN (u) = list;
14862 list = u;
14863 }
14864
14865 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
14866 break;
14867
14868 c_parser_consume_token (parser);
14869 first = false;
14870 continue;
14871 }
14872
14873 tokens.truncate (size: 0);
14874 unsigned int nesting_depth = 0;
14875 while (1)
14876 {
14877 c_token *token = c_parser_peek_token (parser);
14878 switch (token->type)
14879 {
14880 case CPP_EOF:
14881 case CPP_PRAGMA_EOL:
14882 break;
14883 case CPP_OPEN_BRACE:
14884 case CPP_OPEN_PAREN:
14885 case CPP_OPEN_SQUARE:
14886 ++nesting_depth;
14887 goto add;
14888 case CPP_CLOSE_BRACE:
14889 case CPP_CLOSE_PAREN:
14890 case CPP_CLOSE_SQUARE:
14891 if (nesting_depth-- == 0)
14892 break;
14893 goto add;
14894 case CPP_COMMA:
14895 if (nesting_depth == 0)
14896 break;
14897 goto add;
14898 default:
14899 add:
14900 tokens.safe_push (obj: *token);
14901 c_parser_consume_token (parser);
14902 continue;
14903 }
14904 break;
14905 }
14906
14907 /* Make sure nothing tries to read past the end of the tokens. */
14908 c_token eof_token;
14909 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
14910 eof_token.type = CPP_EOF;
14911 tokens.safe_push (obj: eof_token);
14912 tokens.safe_push (obj: eof_token);
14913
14914 saved_tokens = parser->tokens;
14915 tokens_avail = parser->tokens_avail;
14916 parser->tokens = tokens.address ();
14917 parser->tokens_avail = tokens.length ();
14918 }
14919
14920 tree t = NULL_TREE;
14921
14922 if (c_parser_next_token_is (parser, type: CPP_NAME)
14923 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
14924 {
14925 t = lookup_name (c_parser_peek_token (parser)->value);
14926
14927 if (t == NULL_TREE)
14928 {
14929 undeclared_variable (c_parser_peek_token (parser)->location,
14930 c_parser_peek_token (parser)->value);
14931 t = error_mark_node;
14932 }
14933
14934 c_parser_consume_token (parser);
14935 }
14936 else if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
14937 && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
14938 || (c_parser_peek_token (parser)->keyword
14939 == RID_PRETTY_FUNCTION_NAME)
14940 || (c_parser_peek_token (parser)->keyword
14941 == RID_C99_FUNCTION_NAME)))
14942 t = c_parser_predefined_identifier (parser).value;
14943 else
14944 {
14945 if (first)
14946 c_parser_error (parser, gmsgid: "expected identifier");
14947 break;
14948 }
14949
14950 if (t == error_mark_node)
14951 ;
14952 else if (kind != 0)
14953 {
14954 switch (kind)
14955 {
14956 case OMP_CLAUSE__CACHE_:
14957 /* The OpenACC cache directive explicitly only allows "array
14958 elements or subarrays". */
14959 if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
14960 {
14961 c_parser_error (parser, gmsgid: "expected %<[%>");
14962 t = error_mark_node;
14963 break;
14964 }
14965 /* FALLTHROUGH */
14966 case OMP_CLAUSE_MAP:
14967 case OMP_CLAUSE_FROM:
14968 case OMP_CLAUSE_TO:
14969 start_component_ref:
14970 while (c_parser_next_token_is (parser, type: CPP_DOT)
14971 || (allow_deref
14972 && c_parser_next_token_is (parser, type: CPP_DEREF)))
14973 {
14974 location_t op_loc = c_parser_peek_token (parser)->location;
14975 location_t arrow_loc = UNKNOWN_LOCATION;
14976 if (c_parser_next_token_is (parser, type: CPP_DEREF))
14977 {
14978 c_expr t_expr;
14979 t_expr.value = t;
14980 t_expr.original_code = ERROR_MARK;
14981 t_expr.original_type = NULL;
14982 set_c_expr_source_range (expr: &t_expr, start: op_loc, finish: op_loc);
14983 t_expr.m_decimal = 0;
14984 t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
14985 true, false);
14986 t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
14987 arrow_loc = t_expr.get_location ();
14988 }
14989 c_parser_consume_token (parser);
14990 if (!c_parser_next_token_is (parser, type: CPP_NAME))
14991 {
14992 c_parser_error (parser, gmsgid: "expected identifier");
14993 t = error_mark_node;
14994 break;
14995 }
14996
14997 c_token *comp_tok = c_parser_peek_token (parser);
14998 tree ident = comp_tok->value;
14999 location_t comp_loc = comp_tok->location;
15000 c_parser_consume_token (parser);
15001 t = build_component_ref (op_loc, t, ident, comp_loc,
15002 arrow_loc);
15003 }
15004 /* FALLTHROUGH */
15005 case OMP_CLAUSE_AFFINITY:
15006 case OMP_CLAUSE_DEPEND:
15007 case OMP_CLAUSE_REDUCTION:
15008 case OMP_CLAUSE_IN_REDUCTION:
15009 case OMP_CLAUSE_TASK_REDUCTION:
15010 case OMP_CLAUSE_HAS_DEVICE_ADDR:
15011 array_section_p = false;
15012 dims.truncate (size: 0);
15013 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
15014 {
15015 location_t loc = UNKNOWN_LOCATION;
15016 tree low_bound = NULL_TREE, length = NULL_TREE;
15017 bool no_colon = false;
15018
15019 c_parser_consume_token (parser);
15020 if (!c_parser_next_token_is (parser, type: CPP_COLON))
15021 {
15022 location_t expr_loc
15023 = c_parser_peek_token (parser)->location;
15024 c_expr expr = c_parser_expression (parser);
15025 expr = convert_lvalue_to_rvalue (expr_loc, expr,
15026 false, true);
15027 low_bound = expr.value;
15028 loc = expr_loc;
15029 }
15030 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
15031 {
15032 length = integer_one_node;
15033 no_colon = true;
15034 }
15035 else
15036 {
15037 /* Look for `:'. */
15038 if (!c_parser_require (parser, type: CPP_COLON,
15039 msgid: "expected %<:%>"))
15040 {
15041 t = error_mark_node;
15042 break;
15043 }
15044 array_section_p = true;
15045 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
15046 {
15047 location_t expr_loc
15048 = c_parser_peek_token (parser)->location;
15049 c_expr expr = c_parser_expression (parser);
15050 expr = convert_lvalue_to_rvalue (expr_loc, expr,
15051 false, true);
15052 length = expr.value;
15053 }
15054 }
15055 /* Look for the closing `]'. */
15056 if (!c_parser_require (parser, type: CPP_CLOSE_SQUARE,
15057 msgid: "expected %<]%>"))
15058 {
15059 t = error_mark_node;
15060 break;
15061 }
15062
15063 dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon));
15064 }
15065
15066 if (t != error_mark_node)
15067 {
15068 if ((kind == OMP_CLAUSE_MAP
15069 || kind == OMP_CLAUSE_FROM
15070 || kind == OMP_CLAUSE_TO)
15071 && !array_section_p
15072 && (c_parser_next_token_is (parser, type: CPP_DOT)
15073 || (allow_deref
15074 && c_parser_next_token_is (parser,
15075 type: CPP_DEREF))))
15076 {
15077 for (unsigned i = 0; i < dims.length (); i++)
15078 {
15079 gcc_assert (dims[i].length == integer_one_node);
15080 t = build_array_ref (dims[i].loc,
15081 t, dims[i].low_bound);
15082 }
15083 goto start_component_ref;
15084 }
15085 else
15086 for (unsigned i = 0; i < dims.length (); i++)
15087 t = tree_cons (dims[i].low_bound, dims[i].length, t);
15088 }
15089
15090 if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
15091 && t != error_mark_node
15092 && parser->tokens_avail != 2)
15093 {
15094 if (array_section_p)
15095 {
15096 error_at (c_parser_peek_token (parser)->location,
15097 "expected %<)%> or %<,%>");
15098 t = error_mark_node;
15099 }
15100 else
15101 {
15102 parser->tokens = tokens.address ();
15103 parser->tokens_avail = tokens.length ();
15104
15105 t = c_parser_expr_no_commas (parser, NULL).value;
15106 if (t != error_mark_node && parser->tokens_avail != 2)
15107 {
15108 error_at (c_parser_peek_token (parser)->location,
15109 "expected %<)%> or %<,%>");
15110 t = error_mark_node;
15111 }
15112 }
15113 }
15114 break;
15115 default:
15116 break;
15117 }
15118
15119 if (t != error_mark_node)
15120 {
15121 tree u = build_omp_clause (clause_loc, kind);
15122 OMP_CLAUSE_DECL (u) = t;
15123 OMP_CLAUSE_CHAIN (u) = list;
15124 list = u;
15125 }
15126 }
15127 else
15128 list = tree_cons (t, NULL_TREE, list);
15129
15130 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
15131 {
15132 parser->tokens = saved_tokens;
15133 parser->tokens_avail = tokens_avail;
15134 }
15135 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
15136 break;
15137
15138 c_parser_consume_token (parser);
15139 first = false;
15140 }
15141
15142 return list;
15143}
15144
15145/* Similarly, but expect leading and trailing parenthesis. This is a very
15146 common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
15147 argument is true if list items can use the deref (->) operator. */
15148
15149static tree
15150c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
15151 tree list, bool allow_deref = false)
15152{
15153 /* The clauses location. */
15154 location_t loc = c_parser_peek_token (parser)->location;
15155
15156 if (parser->in_omp_decl_attribute)
15157 {
15158 if (kind)
15159 {
15160 tree u = build_omp_clause (loc, kind);
15161 OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
15162 OMP_CLAUSE_CHAIN (u) = list;
15163 return u;
15164 }
15165 else
15166 return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
15167 }
15168
15169 matching_parens parens;
15170 if (parens.require_open (parser))
15171 {
15172 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list, allow_deref);
15173 parens.skip_until_found_close (parser);
15174 }
15175 return list;
15176}
15177
15178/* OpenACC 2.0:
15179 copy ( variable-list )
15180 copyin ( variable-list )
15181 copyout ( variable-list )
15182 create ( variable-list )
15183 delete ( variable-list )
15184 present ( variable-list )
15185
15186 OpenACC 2.6:
15187 no_create ( variable-list )
15188 attach ( variable-list )
15189 detach ( variable-list ) */
15190
15191static tree
15192c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
15193 tree list)
15194{
15195 enum gomp_map_kind kind;
15196 switch (c_kind)
15197 {
15198 case PRAGMA_OACC_CLAUSE_ATTACH:
15199 kind = GOMP_MAP_ATTACH;
15200 break;
15201 case PRAGMA_OACC_CLAUSE_COPY:
15202 kind = GOMP_MAP_TOFROM;
15203 break;
15204 case PRAGMA_OACC_CLAUSE_COPYIN:
15205 kind = GOMP_MAP_TO;
15206 break;
15207 case PRAGMA_OACC_CLAUSE_COPYOUT:
15208 kind = GOMP_MAP_FROM;
15209 break;
15210 case PRAGMA_OACC_CLAUSE_CREATE:
15211 kind = GOMP_MAP_ALLOC;
15212 break;
15213 case PRAGMA_OACC_CLAUSE_DELETE:
15214 kind = GOMP_MAP_RELEASE;
15215 break;
15216 case PRAGMA_OACC_CLAUSE_DETACH:
15217 kind = GOMP_MAP_DETACH;
15218 break;
15219 case PRAGMA_OACC_CLAUSE_DEVICE:
15220 kind = GOMP_MAP_FORCE_TO;
15221 break;
15222 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
15223 kind = GOMP_MAP_DEVICE_RESIDENT;
15224 break;
15225 case PRAGMA_OACC_CLAUSE_LINK:
15226 kind = GOMP_MAP_LINK;
15227 break;
15228 case PRAGMA_OACC_CLAUSE_NO_CREATE:
15229 kind = GOMP_MAP_IF_PRESENT;
15230 break;
15231 case PRAGMA_OACC_CLAUSE_PRESENT:
15232 kind = GOMP_MAP_FORCE_PRESENT;
15233 break;
15234 case PRAGMA_OACC_CLAUSE_SELF:
15235 /* "The 'host' clause is a synonym for the 'self' clause." */
15236 case PRAGMA_OACC_CLAUSE_HOST:
15237 kind = GOMP_MAP_FORCE_FROM;
15238 break;
15239 default:
15240 gcc_unreachable ();
15241 }
15242 tree nl, c;
15243 nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_MAP, list, allow_deref: true);
15244
15245 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
15246 OMP_CLAUSE_SET_MAP_KIND (c, kind);
15247
15248 return nl;
15249}
15250
15251/* OpenACC 2.0:
15252 deviceptr ( variable-list ) */
15253
15254static tree
15255c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
15256{
15257 location_t loc = c_parser_peek_token (parser)->location;
15258 tree vars, t;
15259
15260 /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
15261 c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
15262 variable-list must only allow for pointer variables. */
15263 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
15264 for (t = vars; t && t; t = TREE_CHAIN (t))
15265 {
15266 tree v = TREE_PURPOSE (t);
15267
15268 /* FIXME diagnostics: Ideally we should keep individual
15269 locations for all the variables in the var list to make the
15270 following errors more precise. Perhaps
15271 c_parser_omp_var_list_parens() should construct a list of
15272 locations to go along with the var list. */
15273
15274 if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
15275 error_at (loc, "%qD is not a variable", v);
15276 else if (TREE_TYPE (v) == error_mark_node)
15277 ;
15278 else if (!POINTER_TYPE_P (TREE_TYPE (v)))
15279 error_at (loc, "%qD is not a pointer variable", v);
15280
15281 tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
15282 OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
15283 OMP_CLAUSE_DECL (u) = v;
15284 OMP_CLAUSE_CHAIN (u) = list;
15285 list = u;
15286 }
15287
15288 return list;
15289}
15290
15291/* OpenACC 2.0, OpenMP 3.0:
15292 collapse ( constant-expression ) */
15293
15294static tree
15295c_parser_omp_clause_collapse (c_parser *parser, tree list)
15296{
15297 tree c, num = error_mark_node;
15298 HOST_WIDE_INT n;
15299 location_t loc;
15300
15301 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
15302 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
15303
15304 loc = c_parser_peek_token (parser)->location;
15305 matching_parens parens;
15306 if (parens.require_open (parser))
15307 {
15308 num = c_parser_expr_no_commas (parser, NULL).value;
15309 parens.skip_until_found_close (parser);
15310 }
15311 if (num == error_mark_node)
15312 return list;
15313 mark_exp_read (num);
15314 num = c_fully_fold (num, false, NULL);
15315 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
15316 || !tree_fits_shwi_p (num)
15317 || (n = tree_to_shwi (num)) <= 0
15318 || (int) n != n)
15319 {
15320 error_at (loc,
15321 "collapse argument needs positive constant integer expression");
15322 return list;
15323 }
15324 c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
15325 OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
15326 OMP_CLAUSE_CHAIN (c) = list;
15327 return c;
15328}
15329
15330/* OpenMP 2.5:
15331 copyin ( variable-list ) */
15332
15333static tree
15334c_parser_omp_clause_copyin (c_parser *parser, tree list)
15335{
15336 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYIN, list);
15337}
15338
15339/* OpenMP 2.5:
15340 copyprivate ( variable-list ) */
15341
15342static tree
15343c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
15344{
15345 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYPRIVATE, list);
15346}
15347
15348/* OpenMP 2.5:
15349 default ( none | shared )
15350
15351 OpenMP 5.1:
15352 default ( private | firstprivate )
15353
15354 OpenACC:
15355 default ( none | present ) */
15356
15357static tree
15358c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
15359{
15360 enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
15361 location_t loc = c_parser_peek_token (parser)->location;
15362 tree c;
15363
15364 matching_parens parens;
15365 if (!parens.require_open (parser))
15366 return list;
15367 if (c_parser_next_token_is (parser, type: CPP_NAME))
15368 {
15369 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
15370
15371 switch (p[0])
15372 {
15373 case 'n':
15374 if (strcmp (s1: "none", s2: p) != 0)
15375 goto invalid_kind;
15376 kind = OMP_CLAUSE_DEFAULT_NONE;
15377 break;
15378
15379 case 'p':
15380 if (is_oacc)
15381 {
15382 if (strcmp (s1: "present", s2: p) != 0)
15383 goto invalid_kind;
15384 kind = OMP_CLAUSE_DEFAULT_PRESENT;
15385 }
15386 else
15387 {
15388 if (strcmp (s1: "private", s2: p) != 0)
15389 goto invalid_kind;
15390 kind = OMP_CLAUSE_DEFAULT_PRIVATE;
15391 }
15392 break;
15393
15394 case 'f':
15395 if (strcmp (s1: "firstprivate", s2: p) != 0 || is_oacc)
15396 goto invalid_kind;
15397 kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
15398 break;
15399
15400 case 's':
15401 if (strcmp (s1: "shared", s2: p) != 0 || is_oacc)
15402 goto invalid_kind;
15403 kind = OMP_CLAUSE_DEFAULT_SHARED;
15404 break;
15405
15406 default:
15407 goto invalid_kind;
15408 }
15409
15410 c_parser_consume_token (parser);
15411 }
15412 else
15413 {
15414 invalid_kind:
15415 if (is_oacc)
15416 c_parser_error (parser, gmsgid: "expected %<none%> or %<present%>");
15417 else
15418 c_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, "
15419 "%<private%> or %<firstprivate%>");
15420 }
15421 parens.skip_until_found_close (parser);
15422
15423 if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
15424 return list;
15425
15426 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default");
15427 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
15428 OMP_CLAUSE_CHAIN (c) = list;
15429 OMP_CLAUSE_DEFAULT_KIND (c) = kind;
15430
15431 return c;
15432}
15433
15434/* OpenMP 2.5:
15435 firstprivate ( variable-list ) */
15436
15437static tree
15438c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
15439{
15440 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, list);
15441}
15442
15443/* OpenMP 3.1:
15444 final ( expression ) */
15445
15446static tree
15447c_parser_omp_clause_final (c_parser *parser, tree list)
15448{
15449 location_t loc = c_parser_peek_token (parser)->location;
15450 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15451 {
15452 matching_parens parens;
15453 tree t, c;
15454 if (!parens.require_open (parser))
15455 t = error_mark_node;
15456 else
15457 {
15458 location_t eloc = c_parser_peek_token (parser)->location;
15459 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15460 t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
15461 t = c_objc_common_truthvalue_conversion (eloc, t);
15462 t = c_fully_fold (t, false, NULL);
15463 parens.skip_until_found_close (parser);
15464 }
15465
15466 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final");
15467
15468 c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
15469 OMP_CLAUSE_FINAL_EXPR (c) = t;
15470 OMP_CLAUSE_CHAIN (c) = list;
15471 list = c;
15472 }
15473 else
15474 c_parser_error (parser, gmsgid: "expected %<(%>");
15475
15476 return list;
15477}
15478
15479/* OpenMP 5.1:
15480 indirect [( expression )]
15481*/
15482
15483static tree
15484c_parser_omp_clause_indirect (c_parser *parser, tree list)
15485{
15486 location_t location = c_parser_peek_token (parser)->location;
15487 tree t;
15488
15489 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
15490 {
15491 matching_parens parens;
15492 if (!parens.require_open (parser))
15493 return list;
15494
15495 location_t loc = c_parser_peek_token (parser)->location;
15496 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15497 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
15498 t = c_objc_common_truthvalue_conversion (loc, expr.value);
15499 t = c_fully_fold (t, false, NULL);
15500 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
15501 || TREE_CODE (t) != INTEGER_CST)
15502 {
15503 c_parser_error (parser, gmsgid: "expected constant logical expression");
15504 return list;
15505 }
15506 parens.skip_until_found_close (parser);
15507 }
15508 else
15509 t = integer_one_node;
15510
15511 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect");
15512
15513 tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
15514 OMP_CLAUSE_INDIRECT_EXPR (c) = t;
15515 OMP_CLAUSE_CHAIN (c) = list;
15516
15517 return c;
15518}
15519
15520/* OpenACC, OpenMP 2.5:
15521 if ( expression )
15522
15523 OpenMP 4.5:
15524 if ( directive-name-modifier : expression )
15525
15526 directive-name-modifier:
15527 parallel | task | taskloop | target data | target | target update
15528 | target enter data | target exit data
15529
15530 OpenMP 5.0:
15531 directive-name-modifier:
15532 ... | simd | cancel */
15533
15534static tree
15535c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
15536{
15537 location_t location = c_parser_peek_token (parser)->location;
15538 enum tree_code if_modifier = ERROR_MARK;
15539
15540 matching_parens parens;
15541 if (!parens.require_open (parser))
15542 return list;
15543
15544 if (is_omp && c_parser_next_token_is (parser, type: CPP_NAME))
15545 {
15546 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
15547 int n = 2;
15548 if (strcmp (s1: p, s2: "cancel") == 0)
15549 if_modifier = VOID_CST;
15550 else if (strcmp (s1: p, s2: "parallel") == 0)
15551 if_modifier = OMP_PARALLEL;
15552 else if (strcmp (s1: p, s2: "simd") == 0)
15553 if_modifier = OMP_SIMD;
15554 else if (strcmp (s1: p, s2: "task") == 0)
15555 if_modifier = OMP_TASK;
15556 else if (strcmp (s1: p, s2: "taskloop") == 0)
15557 if_modifier = OMP_TASKLOOP;
15558 else if (strcmp (s1: p, s2: "target") == 0)
15559 {
15560 if_modifier = OMP_TARGET;
15561 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
15562 {
15563 p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
15564 if (strcmp (s1: "data", s2: p) == 0)
15565 if_modifier = OMP_TARGET_DATA;
15566 else if (strcmp (s1: "update", s2: p) == 0)
15567 if_modifier = OMP_TARGET_UPDATE;
15568 else if (strcmp (s1: "enter", s2: p) == 0)
15569 if_modifier = OMP_TARGET_ENTER_DATA;
15570 else if (strcmp (s1: "exit", s2: p) == 0)
15571 if_modifier = OMP_TARGET_EXIT_DATA;
15572 if (if_modifier != OMP_TARGET)
15573 {
15574 n = 3;
15575 c_parser_consume_token (parser);
15576 }
15577 else
15578 {
15579 location_t loc = c_parser_peek_2nd_token (parser)->location;
15580 error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
15581 "or %<exit%>");
15582 if_modifier = ERROR_MARK;
15583 }
15584 if (if_modifier == OMP_TARGET_ENTER_DATA
15585 || if_modifier == OMP_TARGET_EXIT_DATA)
15586 {
15587 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
15588 {
15589 p = IDENTIFIER_POINTER
15590 (c_parser_peek_2nd_token (parser)->value);
15591 if (strcmp (s1: "data", s2: p) == 0)
15592 n = 4;
15593 }
15594 if (n == 4)
15595 c_parser_consume_token (parser);
15596 else
15597 {
15598 location_t loc
15599 = c_parser_peek_2nd_token (parser)->location;
15600 error_at (loc, "expected %<data%>");
15601 if_modifier = ERROR_MARK;
15602 }
15603 }
15604 }
15605 }
15606 if (if_modifier != ERROR_MARK)
15607 {
15608 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
15609 {
15610 c_parser_consume_token (parser);
15611 c_parser_consume_token (parser);
15612 }
15613 else
15614 {
15615 if (n > 2)
15616 {
15617 location_t loc = c_parser_peek_2nd_token (parser)->location;
15618 error_at (loc, "expected %<:%>");
15619 }
15620 if_modifier = ERROR_MARK;
15621 }
15622 }
15623 }
15624
15625 location_t loc = c_parser_peek_token (parser)->location;
15626 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15627 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
15628 tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
15629 t = c_fully_fold (t, false, NULL);
15630 parens.skip_until_found_close (parser);
15631
15632 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
15633 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
15634 {
15635 if (if_modifier != ERROR_MARK
15636 && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
15637 {
15638 const char *p = NULL;
15639 switch (if_modifier)
15640 {
15641 case VOID_CST: p = "cancel"; break;
15642 case OMP_PARALLEL: p = "parallel"; break;
15643 case OMP_SIMD: p = "simd"; break;
15644 case OMP_TASK: p = "task"; break;
15645 case OMP_TASKLOOP: p = "taskloop"; break;
15646 case OMP_TARGET_DATA: p = "target data"; break;
15647 case OMP_TARGET: p = "target"; break;
15648 case OMP_TARGET_UPDATE: p = "target update"; break;
15649 case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
15650 case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
15651 default: gcc_unreachable ();
15652 }
15653 error_at (location, "too many %<if%> clauses with %qs modifier",
15654 p);
15655 return list;
15656 }
15657 else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
15658 {
15659 if (!is_omp)
15660 error_at (location, "too many %<if%> clauses");
15661 else
15662 error_at (location, "too many %<if%> clauses without modifier");
15663 return list;
15664 }
15665 else if (if_modifier == ERROR_MARK
15666 || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
15667 {
15668 error_at (location, "if any %<if%> clause has modifier, then all "
15669 "%<if%> clauses have to use modifier");
15670 return list;
15671 }
15672 }
15673
15674 c = build_omp_clause (location, OMP_CLAUSE_IF);
15675 OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
15676 OMP_CLAUSE_IF_EXPR (c) = t;
15677 OMP_CLAUSE_CHAIN (c) = list;
15678 return c;
15679}
15680
15681/* OpenMP 2.5:
15682 lastprivate ( variable-list )
15683
15684 OpenMP 5.0:
15685 lastprivate ( [ lastprivate-modifier : ] variable-list ) */
15686
15687static tree
15688c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
15689{
15690 /* The clauses location. */
15691 location_t loc = c_parser_peek_token (parser)->location;
15692
15693 if (c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
15694 {
15695 bool conditional = false;
15696 if (c_parser_next_token_is (parser, type: CPP_NAME)
15697 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
15698 {
15699 const char *p
15700 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
15701 if (strcmp (s1: p, s2: "conditional") == 0)
15702 {
15703 conditional = true;
15704 c_parser_consume_token (parser);
15705 c_parser_consume_token (parser);
15706 }
15707 }
15708 tree nlist = c_parser_omp_variable_list (parser, clause_loc: loc,
15709 kind: OMP_CLAUSE_LASTPRIVATE, list);
15710 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
15711 if (conditional)
15712 for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
15713 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
15714 return nlist;
15715 }
15716 return list;
15717}
15718
15719/* OpenMP 3.1:
15720 mergeable */
15721
15722static tree
15723c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
15724{
15725 tree c;
15726
15727 /* FIXME: Should we allow duplicates? */
15728 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable");
15729
15730 c = build_omp_clause (c_parser_peek_token (parser)->location,
15731 OMP_CLAUSE_MERGEABLE);
15732 OMP_CLAUSE_CHAIN (c) = list;
15733
15734 return c;
15735}
15736
15737/* OpenMP 2.5:
15738 nowait */
15739
15740static tree
15741c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
15742{
15743 tree c;
15744 location_t loc = c_parser_peek_token (parser)->location;
15745
15746 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait");
15747
15748 c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
15749 OMP_CLAUSE_CHAIN (c) = list;
15750 return c;
15751}
15752
15753/* OpenMP 2.5:
15754 num_threads ( expression ) */
15755
15756static tree
15757c_parser_omp_clause_num_threads (c_parser *parser, tree list)
15758{
15759 location_t num_threads_loc = c_parser_peek_token (parser)->location;
15760 matching_parens parens;
15761 if (parens.require_open (parser))
15762 {
15763 location_t expr_loc = c_parser_peek_token (parser)->location;
15764 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15765 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
15766 tree c, t = expr.value;
15767 t = c_fully_fold (t, false, NULL);
15768
15769 parens.skip_until_found_close (parser);
15770
15771 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
15772 {
15773 c_parser_error (parser, gmsgid: "expected integer expression");
15774 return list;
15775 }
15776
15777 /* Attempt to statically determine when the number isn't positive. */
15778 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
15779 build_int_cst (TREE_TYPE (t), 0));
15780 protected_set_expr_location (c, expr_loc);
15781 if (c == boolean_true_node)
15782 {
15783 warning_at (expr_loc, 0,
15784 "%<num_threads%> value must be positive");
15785 t = integer_one_node;
15786 }
15787
15788 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, name: "num_threads");
15789
15790 c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
15791 OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
15792 OMP_CLAUSE_CHAIN (c) = list;
15793 list = c;
15794 }
15795
15796 return list;
15797}
15798
15799/* OpenMP 4.5:
15800 num_tasks ( expression )
15801
15802 OpenMP 5.1:
15803 num_tasks ( strict : expression ) */
15804
15805static tree
15806c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
15807{
15808 location_t num_tasks_loc = c_parser_peek_token (parser)->location;
15809 matching_parens parens;
15810 if (parens.require_open (parser))
15811 {
15812 bool strict = false;
15813 if (c_parser_next_token_is (parser, type: CPP_NAME)
15814 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
15815 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
15816 s2: "strict") == 0)
15817 {
15818 strict = true;
15819 c_parser_consume_token (parser);
15820 c_parser_consume_token (parser);
15821 }
15822
15823 location_t expr_loc = c_parser_peek_token (parser)->location;
15824 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15825 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
15826 tree c, t = expr.value;
15827 t = c_fully_fold (t, false, NULL);
15828
15829 parens.skip_until_found_close (parser);
15830
15831 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
15832 {
15833 c_parser_error (parser, gmsgid: "expected integer expression");
15834 return list;
15835 }
15836
15837 /* Attempt to statically determine when the number isn't positive. */
15838 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
15839 build_int_cst (TREE_TYPE (t), 0));
15840 if (CAN_HAVE_LOCATION_P (c))
15841 SET_EXPR_LOCATION (c, expr_loc);
15842 if (c == boolean_true_node)
15843 {
15844 warning_at (expr_loc, 0, "%<num_tasks%> value must be positive");
15845 t = integer_one_node;
15846 }
15847
15848 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, name: "num_tasks");
15849
15850 c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
15851 OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
15852 OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
15853 OMP_CLAUSE_CHAIN (c) = list;
15854 list = c;
15855 }
15856
15857 return list;
15858}
15859
15860/* OpenMP 4.5:
15861 grainsize ( expression )
15862
15863 OpenMP 5.1:
15864 grainsize ( strict : expression ) */
15865
15866static tree
15867c_parser_omp_clause_grainsize (c_parser *parser, tree list)
15868{
15869 location_t grainsize_loc = c_parser_peek_token (parser)->location;
15870 matching_parens parens;
15871 if (parens.require_open (parser))
15872 {
15873 bool strict = false;
15874 if (c_parser_next_token_is (parser, type: CPP_NAME)
15875 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
15876 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
15877 s2: "strict") == 0)
15878 {
15879 strict = true;
15880 c_parser_consume_token (parser);
15881 c_parser_consume_token (parser);
15882 }
15883
15884 location_t expr_loc = c_parser_peek_token (parser)->location;
15885 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15886 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
15887 tree c, t = expr.value;
15888 t = c_fully_fold (t, false, NULL);
15889
15890 parens.skip_until_found_close (parser);
15891
15892 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
15893 {
15894 c_parser_error (parser, gmsgid: "expected integer expression");
15895 return list;
15896 }
15897
15898 /* Attempt to statically determine when the number isn't positive. */
15899 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
15900 build_int_cst (TREE_TYPE (t), 0));
15901 if (CAN_HAVE_LOCATION_P (c))
15902 SET_EXPR_LOCATION (c, expr_loc);
15903 if (c == boolean_true_node)
15904 {
15905 warning_at (expr_loc, 0, "%<grainsize%> value must be positive");
15906 t = integer_one_node;
15907 }
15908
15909 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, name: "grainsize");
15910
15911 c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
15912 OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
15913 OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
15914 OMP_CLAUSE_CHAIN (c) = list;
15915 list = c;
15916 }
15917
15918 return list;
15919}
15920
15921/* OpenMP 4.5:
15922 priority ( expression ) */
15923
15924static tree
15925c_parser_omp_clause_priority (c_parser *parser, tree list)
15926{
15927 location_t priority_loc = c_parser_peek_token (parser)->location;
15928 matching_parens parens;
15929 if (parens.require_open (parser))
15930 {
15931 location_t expr_loc = c_parser_peek_token (parser)->location;
15932 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15933 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
15934 tree c, t = expr.value;
15935 t = c_fully_fold (t, false, NULL);
15936
15937 parens.skip_until_found_close (parser);
15938
15939 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
15940 {
15941 c_parser_error (parser, gmsgid: "expected integer expression");
15942 return list;
15943 }
15944
15945 /* Attempt to statically determine when the number isn't
15946 non-negative. */
15947 c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
15948 build_int_cst (TREE_TYPE (t), 0));
15949 if (CAN_HAVE_LOCATION_P (c))
15950 SET_EXPR_LOCATION (c, expr_loc);
15951 if (c == boolean_true_node)
15952 {
15953 warning_at (expr_loc, 0, "%<priority%> value must be non-negative");
15954 t = integer_one_node;
15955 }
15956
15957 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, name: "priority");
15958
15959 c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
15960 OMP_CLAUSE_PRIORITY_EXPR (c) = t;
15961 OMP_CLAUSE_CHAIN (c) = list;
15962 list = c;
15963 }
15964
15965 return list;
15966}
15967
15968/* OpenMP 4.5:
15969 hint ( expression ) */
15970
15971static tree
15972c_parser_omp_clause_hint (c_parser *parser, tree list)
15973{
15974 location_t hint_loc = c_parser_peek_token (parser)->location;
15975 matching_parens parens;
15976 if (parens.require_open (parser))
15977 {
15978 location_t expr_loc = c_parser_peek_token (parser)->location;
15979 c_expr expr = c_parser_expr_no_commas (parser, NULL);
15980 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
15981 tree c, t = expr.value;
15982 t = c_fully_fold (t, false, NULL);
15983 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
15984 || TREE_CODE (t) != INTEGER_CST
15985 || tree_int_cst_sgn (t) == -1)
15986 {
15987 c_parser_error (parser, gmsgid: "expected constant integer expression "
15988 "with valid sync-hint value");
15989 return list;
15990 }
15991 parens.skip_until_found_close (parser);
15992 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint");
15993
15994 c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
15995 OMP_CLAUSE_HINT_EXPR (c) = t;
15996 OMP_CLAUSE_CHAIN (c) = list;
15997 list = c;
15998 }
15999
16000 return list;
16001}
16002
16003/* OpenMP 5.1:
16004 filter ( integer-expression ) */
16005
16006static tree
16007c_parser_omp_clause_filter (c_parser *parser, tree list)
16008{
16009 location_t hint_loc = c_parser_peek_token (parser)->location;
16010 matching_parens parens;
16011 if (parens.require_open (parser))
16012 {
16013 location_t expr_loc = c_parser_peek_token (parser)->location;
16014 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16015 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16016 tree c, t = expr.value;
16017 t = c_fully_fold (t, false, NULL);
16018 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16019 {
16020 c_parser_error (parser, gmsgid: "expected integer expression");
16021 return list;
16022 }
16023 parens.skip_until_found_close (parser);
16024 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter");
16025
16026 c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
16027 OMP_CLAUSE_FILTER_EXPR (c) = t;
16028 OMP_CLAUSE_CHAIN (c) = list;
16029 list = c;
16030 }
16031
16032 return list;
16033}
16034
16035/* OpenMP 4.5:
16036 defaultmap ( tofrom : scalar )
16037
16038 OpenMP 5.0:
16039 defaultmap ( implicit-behavior [ : variable-category ] ) */
16040
16041static tree
16042c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
16043{
16044 location_t loc = c_parser_peek_token (parser)->location;
16045 tree c;
16046 const char *p;
16047 enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
16048 enum omp_clause_defaultmap_kind category
16049 = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
16050
16051 matching_parens parens;
16052 if (!parens.require_open (parser))
16053 return list;
16054 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
16055 p = "default";
16056 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
16057 {
16058 invalid_behavior:
16059 c_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, "
16060 "%<tofrom%>, %<firstprivate%>, %<none%> "
16061 "or %<default%>");
16062 goto out_err;
16063 }
16064 else
16065 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16066
16067 switch (p[0])
16068 {
16069 case 'a':
16070 if (strcmp (s1: "alloc", s2: p) == 0)
16071 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
16072 else
16073 goto invalid_behavior;
16074 break;
16075
16076 case 'd':
16077 if (strcmp (s1: "default", s2: p) == 0)
16078 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
16079 else
16080 goto invalid_behavior;
16081 break;
16082
16083 case 'f':
16084 if (strcmp (s1: "firstprivate", s2: p) == 0)
16085 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
16086 else if (strcmp (s1: "from", s2: p) == 0)
16087 behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
16088 else
16089 goto invalid_behavior;
16090 break;
16091
16092 case 'n':
16093 if (strcmp (s1: "none", s2: p) == 0)
16094 behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
16095 else
16096 goto invalid_behavior;
16097 break;
16098
16099 case 'p':
16100 if (strcmp (s1: "present", s2: p) == 0)
16101 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
16102 else
16103 goto invalid_behavior;
16104 break;
16105
16106 case 't':
16107 if (strcmp (s1: "tofrom", s2: p) == 0)
16108 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
16109 else if (strcmp (s1: "to", s2: p) == 0)
16110 behavior = OMP_CLAUSE_DEFAULTMAP_TO;
16111 else
16112 goto invalid_behavior;
16113 break;
16114
16115 default:
16116 goto invalid_behavior;
16117 }
16118 c_parser_consume_token (parser);
16119
16120 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
16121 {
16122 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
16123 goto out_err;
16124 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16125 {
16126 invalid_category:
16127 c_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, "
16128 "%<pointer%> or %<all%>");
16129 goto out_err;
16130 }
16131 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16132 switch (p[0])
16133 {
16134 case 'a':
16135 if (strcmp (s1: "aggregate", s2: p) == 0)
16136 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
16137 else if (strcmp (s1: "all", s2: p) == 0)
16138 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
16139 else
16140 goto invalid_category;
16141 break;
16142
16143 case 'p':
16144 if (strcmp (s1: "pointer", s2: p) == 0)
16145 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
16146 else
16147 goto invalid_category;
16148 break;
16149
16150 case 's':
16151 if (strcmp (s1: "scalar", s2: p) == 0)
16152 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
16153 else
16154 goto invalid_category;
16155 break;
16156
16157 default:
16158 goto invalid_category;
16159 }
16160
16161 c_parser_consume_token (parser);
16162 }
16163 parens.skip_until_found_close (parser);
16164
16165 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
16166 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
16167 && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
16168 || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
16169 || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
16170 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16171 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
16172 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16173 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
16174 {
16175 enum omp_clause_defaultmap_kind cat = category;
16176 location_t loc = OMP_CLAUSE_LOCATION (c);
16177 if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
16178 || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
16179 && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
16180 != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
16181 cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
16182 p = NULL;
16183 switch (cat)
16184 {
16185 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
16186 p = NULL;
16187 break;
16188 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
16189 p = "all";
16190 break;
16191 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
16192 p = "aggregate";
16193 break;
16194 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
16195 p = "pointer";
16196 break;
16197 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
16198 p = "scalar";
16199 break;
16200 default:
16201 gcc_unreachable ();
16202 }
16203 if (p)
16204 error_at (loc, "too many %<defaultmap%> clauses with %qs category",
16205 p);
16206 else
16207 error_at (loc, "too many %<defaultmap%> clauses with unspecified "
16208 "category");
16209 break;
16210 }
16211
16212 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
16213 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
16214 OMP_CLAUSE_CHAIN (c) = list;
16215 return c;
16216
16217 out_err:
16218 parens.skip_until_found_close (parser);
16219 return list;
16220}
16221
16222/* OpenACC 2.0:
16223 use_device ( variable-list )
16224
16225 OpenMP 4.5:
16226 use_device_ptr ( variable-list ) */
16227
16228static tree
16229c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
16230{
16231 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR,
16232 list);
16233}
16234
16235/* OpenMP 5.0:
16236 use_device_addr ( variable-list ) */
16237
16238static tree
16239c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
16240{
16241 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR,
16242 list);
16243}
16244
16245/* OpenMP 5.1:
16246 has_device_addr ( variable-list ) */
16247
16248static tree
16249c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
16250{
16251 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR,
16252 list);
16253}
16254
16255/* OpenMP 4.5:
16256 is_device_ptr ( variable-list ) */
16257
16258static tree
16259c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
16260{
16261 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, list);
16262}
16263
16264/* OpenACC:
16265 num_gangs ( expression )
16266 num_workers ( expression )
16267 vector_length ( expression ) */
16268
16269static tree
16270c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
16271 tree list)
16272{
16273 location_t loc = c_parser_peek_token (parser)->location;
16274
16275 matching_parens parens;
16276 if (!parens.require_open (parser))
16277 return list;
16278
16279 location_t expr_loc = c_parser_peek_token (parser)->location;
16280 c_expr expr = c_parser_expression (parser);
16281 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
16282 tree c, t = expr.value;
16283 t = c_fully_fold (t, false, NULL);
16284
16285 parens.skip_until_found_close (parser);
16286
16287 if (t == error_mark_node)
16288 return list;
16289 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16290 {
16291 error_at (expr_loc, "%qs expression must be integral",
16292 omp_clause_code_name[code]);
16293 return list;
16294 }
16295
16296 /* Attempt to statically determine when the number isn't positive. */
16297 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
16298 build_int_cst (TREE_TYPE (t), 0));
16299 protected_set_expr_location (c, expr_loc);
16300 if (c == boolean_true_node)
16301 {
16302 warning_at (expr_loc, 0,
16303 "%qs value must be positive",
16304 omp_clause_code_name[code]);
16305 t = integer_one_node;
16306 }
16307
16308 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
16309
16310 c = build_omp_clause (loc, code);
16311 OMP_CLAUSE_OPERAND (c, 0) = t;
16312 OMP_CLAUSE_CHAIN (c) = list;
16313 return c;
16314}
16315
16316/* OpenACC:
16317
16318 gang [( gang-arg-list )]
16319 worker [( [num:] int-expr )]
16320 vector [( [length:] int-expr )]
16321
16322 where gang-arg is one of:
16323
16324 [num:] int-expr
16325 static: size-expr
16326
16327 and size-expr may be:
16328
16329 *
16330 int-expr
16331*/
16332
16333static tree
16334c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
16335 omp_clause_code kind,
16336 const char *str, tree list)
16337{
16338 const char *id = "num";
16339 tree ops[2] = { NULL_TREE, NULL_TREE }, c;
16340
16341 if (kind == OMP_CLAUSE_VECTOR)
16342 id = "length";
16343
16344 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
16345 {
16346 c_parser_consume_token (parser);
16347
16348 do
16349 {
16350 c_token *next = c_parser_peek_token (parser);
16351 int idx = 0;
16352
16353 /* Gang static argument. */
16354 if (kind == OMP_CLAUSE_GANG
16355 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
16356 {
16357 c_parser_consume_token (parser);
16358
16359 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
16360 goto cleanup_error;
16361
16362 idx = 1;
16363 if (ops[idx] != NULL_TREE)
16364 {
16365 c_parser_error (parser, gmsgid: "too many %<static%> arguments");
16366 goto cleanup_error;
16367 }
16368
16369 /* Check for the '*' argument. */
16370 if (c_parser_next_token_is (parser, type: CPP_MULT)
16371 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16372 || c_parser_peek_2nd_token (parser)->type
16373 == CPP_CLOSE_PAREN))
16374 {
16375 c_parser_consume_token (parser);
16376 ops[idx] = integer_minus_one_node;
16377
16378 if (c_parser_next_token_is (parser, type: CPP_COMMA))
16379 {
16380 c_parser_consume_token (parser);
16381 continue;
16382 }
16383 else
16384 break;
16385 }
16386 }
16387 /* Worker num: argument and vector length: arguments. */
16388 else if (c_parser_next_token_is (parser, type: CPP_NAME)
16389 && strcmp (s1: id, IDENTIFIER_POINTER (next->value)) == 0
16390 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16391 {
16392 c_parser_consume_token (parser); /* id */
16393 c_parser_consume_token (parser); /* ':' */
16394 }
16395
16396 /* Now collect the actual argument. */
16397 if (ops[idx] != NULL_TREE)
16398 {
16399 c_parser_error (parser, gmsgid: "unexpected argument");
16400 goto cleanup_error;
16401 }
16402
16403 location_t expr_loc = c_parser_peek_token (parser)->location;
16404 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
16405 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
16406 tree expr = cexpr.value;
16407 if (expr == error_mark_node)
16408 goto cleanup_error;
16409
16410 expr = c_fully_fold (expr, false, NULL);
16411
16412 /* Attempt to statically determine when the number isn't a
16413 positive integer. */
16414
16415 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
16416 {
16417 c_parser_error (parser, gmsgid: "expected integer expression");
16418 return list;
16419 }
16420
16421 tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
16422 build_int_cst (TREE_TYPE (expr), 0));
16423 if (c == boolean_true_node)
16424 {
16425 warning_at (loc, 0,
16426 "%qs value must be positive", str);
16427 expr = integer_one_node;
16428 }
16429
16430 ops[idx] = expr;
16431
16432 if (kind == OMP_CLAUSE_GANG
16433 && c_parser_next_token_is (parser, type: CPP_COMMA))
16434 {
16435 c_parser_consume_token (parser);
16436 continue;
16437 }
16438 break;
16439 }
16440 while (1);
16441
16442 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
16443 goto cleanup_error;
16444 }
16445
16446 check_no_duplicate_clause (clauses: list, code: kind, name: str);
16447
16448 c = build_omp_clause (loc, kind);
16449
16450 if (ops[1])
16451 OMP_CLAUSE_OPERAND (c, 1) = ops[1];
16452
16453 OMP_CLAUSE_OPERAND (c, 0) = ops[0];
16454 OMP_CLAUSE_CHAIN (c) = list;
16455
16456 return c;
16457
16458 cleanup_error:
16459 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
16460 return list;
16461}
16462
16463/* OpenACC 2.5:
16464 auto
16465 finalize
16466 independent
16467 nohost
16468 seq */
16469
16470static tree
16471c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
16472 tree list)
16473{
16474 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
16475
16476 tree c = build_omp_clause (loc, code);
16477 OMP_CLAUSE_CHAIN (c) = list;
16478
16479 return c;
16480}
16481
16482/* OpenACC:
16483 async [( int-expr )] */
16484
16485static tree
16486c_parser_oacc_clause_async (c_parser *parser, tree list)
16487{
16488 tree c, t;
16489 location_t loc = c_parser_peek_token (parser)->location;
16490
16491 t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
16492
16493 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
16494 {
16495 c_parser_consume_token (parser);
16496
16497 t = c_parser_expr_no_commas (parser, NULL).value;
16498 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
16499 c_parser_error (parser, gmsgid: "expected integer expression");
16500 else if (t == error_mark_node
16501 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
16502 return list;
16503 }
16504 else
16505 t = c_fully_fold (t, false, NULL);
16506
16507 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async");
16508
16509 c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
16510 OMP_CLAUSE_ASYNC_EXPR (c) = t;
16511 OMP_CLAUSE_CHAIN (c) = list;
16512 list = c;
16513
16514 return list;
16515}
16516
16517/* OpenACC 2.0:
16518 tile ( size-expr-list ) */
16519
16520static tree
16521c_parser_oacc_clause_tile (c_parser *parser, tree list)
16522{
16523 tree c, expr = error_mark_node;
16524 location_t loc;
16525 tree tile = NULL_TREE;
16526
16527 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
16528 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
16529
16530 loc = c_parser_peek_token (parser)->location;
16531 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
16532 return list;
16533
16534 do
16535 {
16536 if (tile && !c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
16537 return list;
16538
16539 if (c_parser_next_token_is (parser, type: CPP_MULT)
16540 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16541 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
16542 {
16543 c_parser_consume_token (parser);
16544 expr = integer_zero_node;
16545 }
16546 else
16547 {
16548 location_t expr_loc = c_parser_peek_token (parser)->location;
16549 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
16550 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
16551 expr = cexpr.value;
16552
16553 if (expr == error_mark_node)
16554 {
16555 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
16556 msgid: "expected %<)%>");
16557 return list;
16558 }
16559
16560 expr = c_fully_fold (expr, false, NULL);
16561
16562 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
16563 || !tree_fits_shwi_p (expr)
16564 || tree_to_shwi (expr) <= 0)
16565 {
16566 error_at (expr_loc, "%<tile%> argument needs positive"
16567 " integral constant");
16568 expr = integer_zero_node;
16569 }
16570 }
16571
16572 tile = tree_cons (NULL_TREE, expr, tile);
16573 }
16574 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN));
16575
16576 /* Consume the trailing ')'. */
16577 c_parser_consume_token (parser);
16578
16579 c = build_omp_clause (loc, OMP_CLAUSE_TILE);
16580 tile = nreverse (tile);
16581 OMP_CLAUSE_TILE_LIST (c) = tile;
16582 OMP_CLAUSE_CHAIN (c) = list;
16583 return c;
16584}
16585
16586/* OpenACC:
16587 wait [( int-expr-list )] */
16588
16589static tree
16590c_parser_oacc_clause_wait (c_parser *parser, tree list)
16591{
16592 location_t clause_loc = c_parser_peek_token (parser)->location;
16593
16594 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
16595 list = c_parser_oacc_wait_list (parser, clause_loc, list);
16596 else
16597 {
16598 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16599
16600 OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
16601 OMP_CLAUSE_CHAIN (c) = list;
16602 list = c;
16603 }
16604
16605 return list;
16606}
16607
16608/* OpenACC 2.7:
16609 self [( expression )] */
16610
16611static tree
16612c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
16613{
16614 tree t;
16615 location_t location = c_parser_peek_token (parser)->location;
16616 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
16617 {
16618 matching_parens parens;
16619 parens.consume_open (parser);
16620
16621 location_t loc = c_parser_peek_token (parser)->location;
16622 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16623 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
16624 t = c_objc_common_truthvalue_conversion (loc, expr.value);
16625 t = c_fully_fold (t, false, NULL);
16626 parens.skip_until_found_close (parser);
16627 }
16628 else
16629 t = truthvalue_true_node;
16630
16631 for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
16632 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
16633 {
16634 error_at (location, "too many %<self%> clauses");
16635 return list;
16636 }
16637
16638 tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
16639 OMP_CLAUSE_SELF_EXPR (c) = t;
16640 OMP_CLAUSE_CHAIN (c) = list;
16641 return c;
16642}
16643
16644/* OpenMP 5.0:
16645 order ( concurrent )
16646
16647 OpenMP 5.1:
16648 order ( order-modifier : concurrent )
16649
16650 order-modifier:
16651 reproducible
16652 unconstrained */
16653
16654static tree
16655c_parser_omp_clause_order (c_parser *parser, tree list)
16656{
16657 location_t loc = c_parser_peek_token (parser)->location;
16658 tree c;
16659 const char *p;
16660 bool unconstrained = false;
16661 bool reproducible = false;
16662
16663 matching_parens parens;
16664 if (!parens.require_open (parser))
16665 return list;
16666 if (c_parser_next_token_is (parser, type: CPP_NAME)
16667 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16668 {
16669 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16670 if (strcmp (s1: p, s2: "unconstrained") == 0)
16671 unconstrained = true;
16672 else if (strcmp (s1: p, s2: "reproducible") == 0)
16673 reproducible = true;
16674 else
16675 {
16676 c_parser_error (parser, gmsgid: "expected %<reproducible%> or "
16677 "%<unconstrained%>");
16678 goto out_err;
16679 }
16680 c_parser_consume_token (parser);
16681 c_parser_consume_token (parser);
16682 }
16683 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16684 {
16685 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
16686 goto out_err;
16687 }
16688 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16689 if (strcmp (s1: p, s2: "concurrent") != 0)
16690 {
16691 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
16692 goto out_err;
16693 }
16694 c_parser_consume_token (parser);
16695 parens.skip_until_found_close (parser);
16696 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order");
16697 c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
16698 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
16699 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
16700 OMP_CLAUSE_CHAIN (c) = list;
16701 return c;
16702
16703 out_err:
16704 parens.skip_until_found_close (parser);
16705 return list;
16706}
16707
16708
16709/* OpenMP 5.0:
16710 bind ( teams | parallel | thread ) */
16711
16712static tree
16713c_parser_omp_clause_bind (c_parser *parser, tree list)
16714{
16715 location_t loc = c_parser_peek_token (parser)->location;
16716 tree c;
16717 const char *p;
16718 enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
16719
16720 matching_parens parens;
16721 if (!parens.require_open (parser))
16722 return list;
16723 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16724 {
16725 invalid:
16726 c_parser_error (parser,
16727 gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>");
16728 parens.skip_until_found_close (parser);
16729 return list;
16730 }
16731 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16732 if (strcmp (s1: p, s2: "teams") == 0)
16733 kind = OMP_CLAUSE_BIND_TEAMS;
16734 else if (strcmp (s1: p, s2: "parallel") == 0)
16735 kind = OMP_CLAUSE_BIND_PARALLEL;
16736 else if (strcmp (s1: p, s2: "thread") != 0)
16737 goto invalid;
16738 c_parser_consume_token (parser);
16739 parens.skip_until_found_close (parser);
16740 /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
16741 c = build_omp_clause (loc, OMP_CLAUSE_BIND);
16742 OMP_CLAUSE_BIND_KIND (c) = kind;
16743 OMP_CLAUSE_CHAIN (c) = list;
16744 return c;
16745}
16746
16747
16748/* OpenMP 2.5:
16749 ordered
16750
16751 OpenMP 4.5:
16752 ordered ( constant-expression ) */
16753
16754static tree
16755c_parser_omp_clause_ordered (c_parser *parser, tree list)
16756{
16757 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, name: "ordered");
16758
16759 tree c, num = NULL_TREE;
16760 HOST_WIDE_INT n;
16761 location_t loc = c_parser_peek_token (parser)->location;
16762 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
16763 {
16764 matching_parens parens;
16765 parens.consume_open (parser);
16766 num = c_parser_expr_no_commas (parser, NULL).value;
16767 parens.skip_until_found_close (parser);
16768 }
16769 if (num == error_mark_node)
16770 return list;
16771 if (num)
16772 {
16773 mark_exp_read (num);
16774 num = c_fully_fold (num, false, NULL);
16775 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
16776 || !tree_fits_shwi_p (num)
16777 || (n = tree_to_shwi (num)) <= 0
16778 || (int) n != n)
16779 {
16780 error_at (loc, "ordered argument needs positive "
16781 "constant integer expression");
16782 return list;
16783 }
16784 }
16785 c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
16786 OMP_CLAUSE_ORDERED_EXPR (c) = num;
16787 OMP_CLAUSE_CHAIN (c) = list;
16788 return c;
16789}
16790
16791/* OpenMP 2.5:
16792 private ( variable-list ) */
16793
16794static tree
16795c_parser_omp_clause_private (c_parser *parser, tree list)
16796{
16797 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_PRIVATE, list);
16798}
16799
16800/* OpenMP 2.5:
16801 reduction ( reduction-operator : variable-list )
16802
16803 reduction-operator:
16804 One of: + * - & ^ | && ||
16805
16806 OpenMP 3.1:
16807
16808 reduction-operator:
16809 One of: + * - & ^ | && || max min
16810
16811 OpenMP 4.0:
16812
16813 reduction-operator:
16814 One of: + * - & ^ | && ||
16815 identifier
16816
16817 OpenMP 5.0:
16818 reduction ( reduction-modifier, reduction-operator : variable-list )
16819 in_reduction ( reduction-operator : variable-list )
16820 task_reduction ( reduction-operator : variable-list ) */
16821
16822static tree
16823c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
16824 bool is_omp, tree list)
16825{
16826 location_t clause_loc = c_parser_peek_token (parser)->location;
16827 matching_parens parens;
16828 if (parens.require_open (parser))
16829 {
16830 bool task = false;
16831 bool inscan = false;
16832 enum tree_code code = ERROR_MARK;
16833 tree reduc_id = NULL_TREE;
16834
16835 if (kind == OMP_CLAUSE_REDUCTION && is_omp)
16836 {
16837 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
16838 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
16839 {
16840 c_parser_consume_token (parser);
16841 c_parser_consume_token (parser);
16842 }
16843 else if (c_parser_next_token_is (parser, type: CPP_NAME)
16844 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
16845 {
16846 const char *p
16847 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16848 if (strcmp (s1: p, s2: "task") == 0)
16849 task = true;
16850 else if (strcmp (s1: p, s2: "inscan") == 0)
16851 inscan = true;
16852 if (task || inscan)
16853 {
16854 c_parser_consume_token (parser);
16855 c_parser_consume_token (parser);
16856 }
16857 }
16858 }
16859
16860 switch (c_parser_peek_token (parser)->type)
16861 {
16862 case CPP_PLUS:
16863 code = PLUS_EXPR;
16864 break;
16865 case CPP_MULT:
16866 code = MULT_EXPR;
16867 break;
16868 case CPP_MINUS:
16869 code = MINUS_EXPR;
16870 break;
16871 case CPP_AND:
16872 code = BIT_AND_EXPR;
16873 break;
16874 case CPP_XOR:
16875 code = BIT_XOR_EXPR;
16876 break;
16877 case CPP_OR:
16878 code = BIT_IOR_EXPR;
16879 break;
16880 case CPP_AND_AND:
16881 code = TRUTH_ANDIF_EXPR;
16882 break;
16883 case CPP_OR_OR:
16884 code = TRUTH_ORIF_EXPR;
16885 break;
16886 case CPP_NAME:
16887 {
16888 const char *p
16889 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16890 if (strcmp (s1: p, s2: "min") == 0)
16891 {
16892 code = MIN_EXPR;
16893 break;
16894 }
16895 if (strcmp (s1: p, s2: "max") == 0)
16896 {
16897 code = MAX_EXPR;
16898 break;
16899 }
16900 reduc_id = c_parser_peek_token (parser)->value;
16901 break;
16902 }
16903 default:
16904 c_parser_error (parser,
16905 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
16906 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
16907 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
16908 return list;
16909 }
16910 c_parser_consume_token (parser);
16911 reduc_id = c_omp_reduction_id (code, reduc_id);
16912 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
16913 {
16914 tree nl, c;
16915
16916 nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
16917 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
16918 {
16919 tree d = OMP_CLAUSE_DECL (c), type;
16920 if (TREE_CODE (d) != TREE_LIST)
16921 type = TREE_TYPE (d);
16922 else
16923 {
16924 int cnt = 0;
16925 tree t;
16926 for (t = d; TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
16927 cnt++;
16928 type = TREE_TYPE (t);
16929 while (cnt > 0)
16930 {
16931 if (TREE_CODE (type) != POINTER_TYPE
16932 && TREE_CODE (type) != ARRAY_TYPE)
16933 break;
16934 type = TREE_TYPE (type);
16935 cnt--;
16936 }
16937 }
16938 while (TREE_CODE (type) == ARRAY_TYPE)
16939 type = TREE_TYPE (type);
16940 OMP_CLAUSE_REDUCTION_CODE (c) = code;
16941 if (task)
16942 OMP_CLAUSE_REDUCTION_TASK (c) = 1;
16943 else if (inscan)
16944 OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
16945 if (code == ERROR_MARK
16946 || !(INTEGRAL_TYPE_P (type)
16947 || SCALAR_FLOAT_TYPE_P (type)
16948 || TREE_CODE (type) == COMPLEX_TYPE))
16949 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
16950 = c_omp_reduction_lookup (reduc_id,
16951 TYPE_MAIN_VARIANT (type));
16952 }
16953
16954 list = nl;
16955 }
16956 parens.skip_until_found_close (parser);
16957 }
16958 return list;
16959}
16960
16961/* OpenMP 2.5:
16962 schedule ( schedule-kind )
16963 schedule ( schedule-kind , expression )
16964
16965 schedule-kind:
16966 static | dynamic | guided | runtime | auto
16967
16968 OpenMP 4.5:
16969 schedule ( schedule-modifier : schedule-kind )
16970 schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
16971
16972 schedule-modifier:
16973 simd
16974 monotonic
16975 nonmonotonic */
16976
16977static tree
16978c_parser_omp_clause_schedule (c_parser *parser, tree list)
16979{
16980 tree c, t;
16981 location_t loc = c_parser_peek_token (parser)->location;
16982 int modifiers = 0, nmodifiers = 0;
16983
16984 matching_parens parens;
16985 if (!parens.require_open (parser))
16986 return list;
16987
16988 c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
16989
16990 location_t comma = UNKNOWN_LOCATION;
16991 while (c_parser_next_token_is (parser, type: CPP_NAME))
16992 {
16993 tree kind = c_parser_peek_token (parser)->value;
16994 const char *p = IDENTIFIER_POINTER (kind);
16995 if (strcmp (s1: "simd", s2: p) == 0)
16996 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
16997 else if (strcmp (s1: "monotonic", s2: p) == 0)
16998 modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
16999 else if (strcmp (s1: "nonmonotonic", s2: p) == 0)
17000 modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
17001 else
17002 break;
17003 comma = UNKNOWN_LOCATION;
17004 c_parser_consume_token (parser);
17005 if (nmodifiers++ == 0
17006 && c_parser_next_token_is (parser, type: CPP_COMMA))
17007 {
17008 comma = c_parser_peek_token (parser)->location;
17009 c_parser_consume_token (parser);
17010 }
17011 else
17012 {
17013 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
17014 break;
17015 }
17016 }
17017 if (comma != UNKNOWN_LOCATION)
17018 error_at (comma, "expected %<:%>");
17019
17020 if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
17021 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
17022 == (OMP_CLAUSE_SCHEDULE_MONOTONIC
17023 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
17024 {
17025 error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
17026 "specified");
17027 modifiers = 0;
17028 }
17029
17030 if (c_parser_next_token_is (parser, type: CPP_NAME))
17031 {
17032 tree kind = c_parser_peek_token (parser)->value;
17033 const char *p = IDENTIFIER_POINTER (kind);
17034
17035 switch (p[0])
17036 {
17037 case 'd':
17038 if (strcmp (s1: "dynamic", s2: p) != 0)
17039 goto invalid_kind;
17040 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
17041 break;
17042
17043 case 'g':
17044 if (strcmp (s1: "guided", s2: p) != 0)
17045 goto invalid_kind;
17046 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
17047 break;
17048
17049 case 'r':
17050 if (strcmp (s1: "runtime", s2: p) != 0)
17051 goto invalid_kind;
17052 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
17053 break;
17054
17055 default:
17056 goto invalid_kind;
17057 }
17058 }
17059 else if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
17060 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
17061 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
17062 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
17063 else
17064 goto invalid_kind;
17065
17066 c_parser_consume_token (parser);
17067 if (c_parser_next_token_is (parser, type: CPP_COMMA))
17068 {
17069 location_t here;
17070 c_parser_consume_token (parser);
17071
17072 here = c_parser_peek_token (parser)->location;
17073 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17074 expr = convert_lvalue_to_rvalue (here, expr, false, true);
17075 t = expr.value;
17076 t = c_fully_fold (t, false, NULL);
17077
17078 if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
17079 error_at (here, "schedule %<runtime%> does not take "
17080 "a %<chunk_size%> parameter");
17081 else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
17082 error_at (here,
17083 "schedule %<auto%> does not take "
17084 "a %<chunk_size%> parameter");
17085 else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
17086 || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
17087 {
17088 /* Attempt to statically determine when the number isn't
17089 positive. */
17090 tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
17091 build_int_cst (TREE_TYPE (t), 0));
17092 protected_set_expr_location (s, loc);
17093 if (s == boolean_true_node)
17094 {
17095 warning_at (loc, 0,
17096 "chunk size value must be positive");
17097 t = integer_one_node;
17098 }
17099 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
17100 }
17101 else
17102 c_parser_error (parser, gmsgid: "expected integer expression");
17103
17104 parens.skip_until_found_close (parser);
17105 }
17106 else
17107 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
17108 msgid: "expected %<,%> or %<)%>");
17109
17110 OMP_CLAUSE_SCHEDULE_KIND (c)
17111 = (enum omp_clause_schedule_kind)
17112 (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
17113
17114 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule");
17115 OMP_CLAUSE_CHAIN (c) = list;
17116 return c;
17117
17118 invalid_kind:
17119 c_parser_error (parser, gmsgid: "invalid schedule kind");
17120 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
17121 return list;
17122}
17123
17124/* OpenMP 2.5:
17125 shared ( variable-list ) */
17126
17127static tree
17128c_parser_omp_clause_shared (c_parser *parser, tree list)
17129{
17130 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_SHARED, list);
17131}
17132
17133/* OpenMP 3.0:
17134 untied */
17135
17136static tree
17137c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17138{
17139 tree c;
17140
17141 /* FIXME: Should we allow duplicates? */
17142 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied");
17143
17144 c = build_omp_clause (c_parser_peek_token (parser)->location,
17145 OMP_CLAUSE_UNTIED);
17146 OMP_CLAUSE_CHAIN (c) = list;
17147
17148 return c;
17149}
17150
17151/* OpenMP 4.0:
17152 inbranch
17153 notinbranch */
17154
17155static tree
17156c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
17157 enum omp_clause_code code, tree list)
17158{
17159 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
17160
17161 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17162 OMP_CLAUSE_CHAIN (c) = list;
17163
17164 return c;
17165}
17166
17167/* OpenMP 4.0:
17168 parallel
17169 for
17170 sections
17171 taskgroup */
17172
17173static tree
17174c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
17175 enum omp_clause_code code, tree list)
17176{
17177 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17178 OMP_CLAUSE_CHAIN (c) = list;
17179
17180 return c;
17181}
17182
17183/* OpenMP 4.5:
17184 nogroup */
17185
17186static tree
17187c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17188{
17189 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup");
17190 tree c = build_omp_clause (c_parser_peek_token (parser)->location,
17191 OMP_CLAUSE_NOGROUP);
17192 OMP_CLAUSE_CHAIN (c) = list;
17193 return c;
17194}
17195
17196/* OpenMP 4.5:
17197 simd
17198 threads */
17199
17200static tree
17201c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
17202 enum omp_clause_code code, tree list)
17203{
17204 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
17205 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
17206 OMP_CLAUSE_CHAIN (c) = list;
17207 return c;
17208}
17209
17210/* OpenMP 4.0:
17211 num_teams ( expression )
17212
17213 OpenMP 5.1:
17214 num_teams ( expression : expression ) */
17215
17216static tree
17217c_parser_omp_clause_num_teams (c_parser *parser, tree list)
17218{
17219 location_t num_teams_loc = c_parser_peek_token (parser)->location;
17220 matching_parens parens;
17221 if (parens.require_open (parser))
17222 {
17223 location_t upper_loc = c_parser_peek_token (parser)->location;
17224 location_t lower_loc = UNKNOWN_LOCATION;
17225 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17226 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
17227 tree c, upper = expr.value, lower = NULL_TREE;
17228 upper = c_fully_fold (upper, false, NULL);
17229
17230 if (c_parser_next_token_is (parser, type: CPP_COLON))
17231 {
17232 c_parser_consume_token (parser);
17233 lower_loc = upper_loc;
17234 lower = upper;
17235 upper_loc = c_parser_peek_token (parser)->location;
17236 expr = c_parser_expr_no_commas (parser, NULL);
17237 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
17238 upper = expr.value;
17239 upper = c_fully_fold (upper, false, NULL);
17240 }
17241
17242 parens.skip_until_found_close (parser);
17243
17244 if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
17245 || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
17246 {
17247 c_parser_error (parser, gmsgid: "expected integer expression");
17248 return list;
17249 }
17250
17251 /* Attempt to statically determine when the number isn't positive. */
17252 c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
17253 build_int_cst (TREE_TYPE (upper), 0));
17254 protected_set_expr_location (c, upper_loc);
17255 if (c == boolean_true_node)
17256 {
17257 warning_at (upper_loc, 0, "%<num_teams%> value must be positive");
17258 upper = integer_one_node;
17259 }
17260 if (lower)
17261 {
17262 c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
17263 build_int_cst (TREE_TYPE (lower), 0));
17264 protected_set_expr_location (c, lower_loc);
17265 if (c == boolean_true_node)
17266 {
17267 warning_at (lower_loc, 0, "%<num_teams%> value must be positive");
17268 lower = NULL_TREE;
17269 }
17270 else if (TREE_CODE (lower) == INTEGER_CST
17271 && TREE_CODE (upper) == INTEGER_CST
17272 && tree_int_cst_lt (t1: upper, t2: lower))
17273 {
17274 warning_at (lower_loc, 0, "%<num_teams%> lower bound %qE bigger "
17275 "than upper bound %qE", lower, upper);
17276 lower = NULL_TREE;
17277 }
17278 }
17279
17280 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, name: "num_teams");
17281
17282 c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
17283 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
17284 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
17285 OMP_CLAUSE_CHAIN (c) = list;
17286 list = c;
17287 }
17288
17289 return list;
17290}
17291
17292/* OpenMP 4.0:
17293 thread_limit ( expression ) */
17294
17295static tree
17296c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
17297{
17298 location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
17299 matching_parens parens;
17300 if (parens.require_open (parser))
17301 {
17302 location_t expr_loc = c_parser_peek_token (parser)->location;
17303 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17304 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17305 tree c, t = expr.value;
17306 t = c_fully_fold (t, false, NULL);
17307
17308 parens.skip_until_found_close (parser);
17309
17310 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17311 {
17312 c_parser_error (parser, gmsgid: "expected integer expression");
17313 return list;
17314 }
17315
17316 /* Attempt to statically determine when the number isn't positive. */
17317 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17318 build_int_cst (TREE_TYPE (t), 0));
17319 protected_set_expr_location (c, expr_loc);
17320 if (c == boolean_true_node)
17321 {
17322 warning_at (expr_loc, 0, "%<thread_limit%> value must be positive");
17323 t = integer_one_node;
17324 }
17325
17326 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT,
17327 name: "thread_limit");
17328
17329 c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
17330 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
17331 OMP_CLAUSE_CHAIN (c) = list;
17332 list = c;
17333 }
17334
17335 return list;
17336}
17337
17338/* OpenMP 4.0:
17339 aligned ( variable-list )
17340 aligned ( variable-list : constant-expression ) */
17341
17342static tree
17343c_parser_omp_clause_aligned (c_parser *parser, tree list)
17344{
17345 location_t clause_loc = c_parser_peek_token (parser)->location;
17346 tree nl, c;
17347
17348 matching_parens parens;
17349 if (!parens.require_open (parser))
17350 return list;
17351
17352 nl = c_parser_omp_variable_list (parser, clause_loc,
17353 kind: OMP_CLAUSE_ALIGNED, list);
17354
17355 if (c_parser_next_token_is (parser, type: CPP_COLON))
17356 {
17357 c_parser_consume_token (parser);
17358 location_t expr_loc = c_parser_peek_token (parser)->location;
17359 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17360 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17361 tree alignment = expr.value;
17362 alignment = c_fully_fold (alignment, false, NULL);
17363 if (TREE_CODE (alignment) != INTEGER_CST
17364 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
17365 || tree_int_cst_sgn (alignment) != 1)
17366 {
17367 error_at (clause_loc, "%<aligned%> clause alignment expression must "
17368 "be positive constant integer expression");
17369 alignment = NULL_TREE;
17370 }
17371
17372 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17373 OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
17374 }
17375
17376 parens.skip_until_found_close (parser);
17377 return nl;
17378}
17379
17380/* OpenMP 5.0:
17381 allocate ( variable-list )
17382 allocate ( expression : variable-list )
17383
17384 OpenMP 5.1:
17385 allocate ( allocator-modifier : variable-list )
17386 allocate ( allocator-modifier , allocator-modifier : variable-list )
17387
17388 allocator-modifier:
17389 allocator ( expression )
17390 align ( expression ) */
17391
17392static tree
17393c_parser_omp_clause_allocate (c_parser *parser, tree list)
17394{
17395 location_t clause_loc = c_parser_peek_token (parser)->location;
17396 tree nl, c;
17397 tree allocator = NULL_TREE;
17398 tree align = NULL_TREE;
17399
17400 matching_parens parens;
17401 if (!parens.require_open (parser))
17402 return list;
17403
17404 if ((c_parser_next_token_is_not (parser, type: CPP_NAME)
17405 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
17406 || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
17407 && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
17408 {
17409 bool has_modifiers = false;
17410 tree orig_type = NULL_TREE;
17411 if (c_parser_next_token_is (parser, type: CPP_NAME)
17412 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
17413 {
17414 unsigned int n = 3;
17415 const char *p
17416 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17417 if ((strcmp (s1: p, s2: "allocator") == 0 || strcmp (s1: p, s2: "align") == 0)
17418 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
17419 && (c_parser_peek_nth_token_raw (parser, n)->type
17420 == CPP_CLOSE_PAREN))
17421 {
17422 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17423 == CPP_COLON)
17424 has_modifiers = true;
17425 else if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17426 == CPP_COMMA
17427 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
17428 == CPP_NAME)
17429 && (c_parser_peek_nth_token_raw (parser, n: n + 3)->type
17430 == CPP_OPEN_PAREN))
17431 {
17432 c_token *tok = c_parser_peek_nth_token_raw (parser, n: n + 2);
17433 const char *q = IDENTIFIER_POINTER (tok->value);
17434 n += 4;
17435 if ((strcmp (s1: q, s2: "allocator") == 0
17436 || strcmp (s1: q, s2: "align") == 0)
17437 && c_parser_check_balanced_raw_token_sequence (parser,
17438 n: &n)
17439 && (c_parser_peek_nth_token_raw (parser, n)->type
17440 == CPP_CLOSE_PAREN)
17441 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
17442 == CPP_COLON))
17443 has_modifiers = true;
17444 }
17445 }
17446 if (has_modifiers)
17447 {
17448 c_parser_consume_token (parser);
17449 matching_parens parens2;;
17450 parens2.require_open (parser);
17451 location_t expr_loc = c_parser_peek_token (parser)->location;
17452 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17453 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17454 if (expr.value == error_mark_node)
17455 ;
17456 else if (strcmp (s1: p, s2: "allocator") == 0)
17457 {
17458 allocator = expr.value;
17459 allocator = c_fully_fold (allocator, false, NULL);
17460 orig_type = expr.original_type
17461 ? expr.original_type : TREE_TYPE (allocator);
17462 orig_type = TYPE_MAIN_VARIANT (orig_type);
17463 }
17464 else
17465 {
17466 align = expr.value;
17467 align = c_fully_fold (align, false, NULL);
17468 }
17469 parens2.skip_until_found_close (parser);
17470 if (c_parser_next_token_is (parser, type: CPP_COMMA))
17471 {
17472 c_parser_consume_token (parser);
17473 c_token *tok = c_parser_peek_token (parser);
17474 const char *q = "";
17475 if (c_parser_next_token_is (parser, type: CPP_NAME))
17476 q = IDENTIFIER_POINTER (tok->value);
17477 if (strcmp (s1: q, s2: "allocator") != 0 && strcmp (s1: q, s2: "align") != 0)
17478 {
17479 c_parser_error (parser, gmsgid: "expected %<allocator%> or "
17480 "%<align%>");
17481 parens.skip_until_found_close (parser);
17482 return list;
17483 }
17484 else if (strcmp (s1: p, s2: q) == 0)
17485 {
17486 error_at (tok->location, "duplicate %qs modifier", p);
17487 parens.skip_until_found_close (parser);
17488 return list;
17489 }
17490 c_parser_consume_token (parser);
17491 if (!parens2.require_open (parser))
17492 {
17493 parens.skip_until_found_close (parser);
17494 return list;
17495 }
17496 expr_loc = c_parser_peek_token (parser)->location;
17497 expr = c_parser_expr_no_commas (parser, NULL);
17498 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
17499 true);
17500 if (strcmp (s1: q, s2: "allocator") == 0)
17501 {
17502 allocator = expr.value;
17503 allocator = c_fully_fold (allocator, false, NULL);
17504 orig_type = expr.original_type
17505 ? expr.original_type : TREE_TYPE (allocator);
17506 orig_type = TYPE_MAIN_VARIANT (orig_type);
17507 }
17508 else
17509 {
17510 align = expr.value;
17511 align = c_fully_fold (align, false, NULL);
17512 }
17513 parens2.skip_until_found_close (parser);
17514 }
17515 }
17516 }
17517 if (!has_modifiers)
17518 {
17519 location_t expr_loc = c_parser_peek_token (parser)->location;
17520 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17521 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17522 allocator = expr.value;
17523 allocator = c_fully_fold (allocator, false, NULL);
17524 orig_type = expr.original_type
17525 ? expr.original_type : TREE_TYPE (allocator);
17526 orig_type = TYPE_MAIN_VARIANT (orig_type);
17527 }
17528 if (allocator
17529 && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
17530 || TREE_CODE (orig_type) != ENUMERAL_TYPE
17531 || (TYPE_NAME (orig_type)
17532 != get_identifier ("omp_allocator_handle_t"))))
17533 {
17534 error_at (clause_loc, "%<allocate%> clause allocator expression "
17535 "has type %qT rather than "
17536 "%<omp_allocator_handle_t%>",
17537 TREE_TYPE (allocator));
17538 allocator = NULL_TREE;
17539 }
17540 if (align
17541 && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
17542 || !tree_fits_uhwi_p (align)
17543 || !integer_pow2p (align)))
17544 {
17545 error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
17546 "argument needs to be positive constant "
17547 "power of two integer expression");
17548 align = NULL_TREE;
17549 }
17550 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
17551 {
17552 parens.skip_until_found_close (parser);
17553 return list;
17554 }
17555 }
17556
17557 nl = c_parser_omp_variable_list (parser, clause_loc,
17558 kind: OMP_CLAUSE_ALLOCATE, list);
17559
17560 if (allocator || align)
17561 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17562 {
17563 OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
17564 OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
17565 }
17566
17567 parens.skip_until_found_close (parser);
17568 return nl;
17569}
17570
17571/* OpenMP 4.0:
17572 linear ( variable-list )
17573 linear ( variable-list : expression )
17574
17575 OpenMP 4.5:
17576 linear ( modifier ( variable-list ) )
17577 linear ( modifier ( variable-list ) : expression )
17578
17579 modifier:
17580 val
17581
17582 OpenMP 5.2:
17583 linear ( variable-list : modifiers-list )
17584
17585 modifiers:
17586 val
17587 step ( expression ) */
17588
17589static tree
17590c_parser_omp_clause_linear (c_parser *parser, tree list)
17591{
17592 location_t clause_loc = c_parser_peek_token (parser)->location;
17593 tree nl, c, step;
17594 enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
17595 bool old_linear_modifier = false;
17596
17597 matching_parens parens;
17598 if (!parens.require_open (parser))
17599 return list;
17600
17601 if (c_parser_next_token_is (parser, type: CPP_NAME))
17602 {
17603 c_token *tok = c_parser_peek_token (parser);
17604 const char *p = IDENTIFIER_POINTER (tok->value);
17605 if (strcmp (s1: "val", s2: p) == 0)
17606 kind = OMP_CLAUSE_LINEAR_VAL;
17607 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
17608 kind = OMP_CLAUSE_LINEAR_DEFAULT;
17609 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
17610 {
17611 old_linear_modifier = true;
17612 c_parser_consume_token (parser);
17613 c_parser_consume_token (parser);
17614 }
17615 }
17616
17617 nl = c_parser_omp_variable_list (parser, clause_loc,
17618 kind: OMP_CLAUSE_LINEAR, list);
17619
17620 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
17621 parens.skip_until_found_close (parser);
17622
17623 if (c_parser_next_token_is (parser, type: CPP_COLON))
17624 {
17625 c_parser_consume_token (parser);
17626 location_t expr_loc = c_parser_peek_token (parser)->location;
17627 bool has_modifiers = false;
17628 if (kind == OMP_CLAUSE_LINEAR_DEFAULT
17629 && c_parser_next_token_is (parser, type: CPP_NAME))
17630 {
17631 c_token *tok = c_parser_peek_token (parser);
17632 const char *p = IDENTIFIER_POINTER (tok->value);
17633 unsigned int pos = 0;
17634 if (strcmp (s1: "val", s2: p) == 0)
17635 pos = 2;
17636 else if (strcmp (s1: "step", s2: p) == 0
17637 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
17638 {
17639 pos = 3;
17640 if (c_parser_check_balanced_raw_token_sequence (parser, n: &pos)
17641 && (c_parser_peek_nth_token_raw (parser, n: pos)->type
17642 == CPP_CLOSE_PAREN))
17643 ++pos;
17644 else
17645 pos = 0;
17646 }
17647 if (pos)
17648 {
17649 tok = c_parser_peek_nth_token_raw (parser, n: pos);
17650 if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
17651 has_modifiers = true;
17652 }
17653 }
17654 if (has_modifiers)
17655 {
17656 step = NULL_TREE;
17657 while (c_parser_next_token_is (parser, type: CPP_NAME))
17658 {
17659 c_token *tok = c_parser_peek_token (parser);
17660 const char *p = IDENTIFIER_POINTER (tok->value);
17661 if (strcmp (s1: "val", s2: p) == 0)
17662 {
17663 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
17664 error_at (tok->location, "multiple linear modifiers");
17665 kind = OMP_CLAUSE_LINEAR_DEFAULT;
17666 c_parser_consume_token (parser);
17667 }
17668 else if (strcmp (s1: "step", s2: p) == 0)
17669 {
17670 c_parser_consume_token (parser);
17671 matching_parens parens2;
17672 if (parens2.require_open (parser))
17673 {
17674 if (step)
17675 error_at (tok->location,
17676 "multiple %<step%> modifiers");
17677 expr_loc = c_parser_peek_token (parser)->location;
17678 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17679 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
17680 true);
17681 step = c_fully_fold (expr.value, false, NULL);
17682 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
17683 {
17684 error_at (clause_loc, "%<linear%> clause step "
17685 "expression must be integral");
17686 step = integer_one_node;
17687 }
17688 parens2.skip_until_found_close (parser);
17689 }
17690 else
17691 break;
17692 }
17693 else
17694 break;
17695 if (c_parser_next_token_is (parser, type: CPP_COMMA))
17696 {
17697 c_parser_consume_token (parser);
17698 continue;
17699 }
17700 break;
17701 }
17702 if (!step)
17703 step = integer_one_node;
17704 }
17705 else
17706 {
17707 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17708 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17709 step = c_fully_fold (expr.value, false, NULL);
17710 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
17711 {
17712 error_at (clause_loc, "%<linear%> clause step expression must "
17713 "be integral");
17714 step = integer_one_node;
17715 }
17716 }
17717
17718 }
17719 else
17720 step = integer_one_node;
17721
17722 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17723 {
17724 OMP_CLAUSE_LINEAR_STEP (c) = step;
17725 OMP_CLAUSE_LINEAR_KIND (c) = kind;
17726 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
17727 }
17728
17729 parens.skip_until_found_close (parser);
17730 return nl;
17731}
17732
17733/* OpenMP 5.0:
17734 nontemporal ( variable-list ) */
17735
17736static tree
17737c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
17738{
17739 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_NONTEMPORAL, list);
17740}
17741
17742/* OpenMP 4.0:
17743 safelen ( constant-expression ) */
17744
17745static tree
17746c_parser_omp_clause_safelen (c_parser *parser, tree list)
17747{
17748 location_t clause_loc = c_parser_peek_token (parser)->location;
17749 tree c, t;
17750
17751 matching_parens parens;
17752 if (!parens.require_open (parser))
17753 return list;
17754
17755 location_t expr_loc = c_parser_peek_token (parser)->location;
17756 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17757 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17758 t = expr.value;
17759 t = c_fully_fold (t, false, NULL);
17760 if (TREE_CODE (t) != INTEGER_CST
17761 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
17762 || tree_int_cst_sgn (t) != 1)
17763 {
17764 error_at (clause_loc, "%<safelen%> clause expression must "
17765 "be positive constant integer expression");
17766 t = NULL_TREE;
17767 }
17768
17769 parens.skip_until_found_close (parser);
17770 if (t == NULL_TREE || t == error_mark_node)
17771 return list;
17772
17773 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen");
17774
17775 c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
17776 OMP_CLAUSE_SAFELEN_EXPR (c) = t;
17777 OMP_CLAUSE_CHAIN (c) = list;
17778 return c;
17779}
17780
17781/* OpenMP 4.0:
17782 simdlen ( constant-expression ) */
17783
17784static tree
17785c_parser_omp_clause_simdlen (c_parser *parser, tree list)
17786{
17787 location_t clause_loc = c_parser_peek_token (parser)->location;
17788 tree c, t;
17789
17790 matching_parens parens;
17791 if (!parens.require_open (parser))
17792 return list;
17793
17794 location_t expr_loc = c_parser_peek_token (parser)->location;
17795 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17796 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17797 t = expr.value;
17798 t = c_fully_fold (t, false, NULL);
17799 if (TREE_CODE (t) != INTEGER_CST
17800 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
17801 || tree_int_cst_sgn (t) != 1)
17802 {
17803 error_at (clause_loc, "%<simdlen%> clause expression must "
17804 "be positive constant integer expression");
17805 t = NULL_TREE;
17806 }
17807
17808 parens.skip_until_found_close (parser);
17809 if (t == NULL_TREE || t == error_mark_node)
17810 return list;
17811
17812 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen");
17813
17814 c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
17815 OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
17816 OMP_CLAUSE_CHAIN (c) = list;
17817 return c;
17818}
17819
17820/* OpenMP 4.5:
17821 vec:
17822 identifier [+/- integer]
17823 vec , identifier [+/- integer]
17824*/
17825
17826static tree
17827c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
17828 tree list, bool depend_p)
17829{
17830 tree vec = NULL;
17831 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
17832 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
17833 {
17834 c_parser_error (parser, gmsgid: "expected identifier");
17835 return list;
17836 }
17837
17838 if (!depend_p)
17839 {
17840 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17841 if (strcmp (s1: p, s2: "omp_cur_iteration") == 0
17842 && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
17843 && c_parser_peek_nth_token (parser, n: 3)->type == CPP_NUMBER
17844 && c_parser_peek_nth_token (parser, n: 4)->type == CPP_CLOSE_PAREN)
17845 {
17846 tree val = c_parser_peek_nth_token (parser, n: 3)->value;
17847 if (integer_onep (val))
17848 {
17849 c_parser_consume_token (parser);
17850 c_parser_consume_token (parser);
17851 c_parser_consume_token (parser);
17852 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
17853 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
17854 OMP_CLAUSE_CHAIN (u) = list;
17855 return u;
17856 }
17857 }
17858 }
17859
17860
17861
17862 while (c_parser_next_token_is (parser, type: CPP_NAME)
17863 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
17864 {
17865 tree t = lookup_name (c_parser_peek_token (parser)->value);
17866 tree addend = NULL;
17867
17868 if (t == NULL_TREE)
17869 {
17870 undeclared_variable (c_parser_peek_token (parser)->location,
17871 c_parser_peek_token (parser)->value);
17872 t = error_mark_node;
17873 }
17874
17875 c_parser_consume_token (parser);
17876
17877 bool neg = false;
17878 if (c_parser_next_token_is (parser, type: CPP_MINUS))
17879 neg = true;
17880 else if (!c_parser_next_token_is (parser, type: CPP_PLUS))
17881 {
17882 addend = integer_zero_node;
17883 neg = false;
17884 goto add_to_vector;
17885 }
17886 c_parser_consume_token (parser);
17887
17888 if (c_parser_next_token_is_not (parser, type: CPP_NUMBER))
17889 {
17890 c_parser_error (parser, gmsgid: "expected integer");
17891 return list;
17892 }
17893
17894 addend = c_parser_peek_token (parser)->value;
17895 if (TREE_CODE (addend) != INTEGER_CST)
17896 {
17897 c_parser_error (parser, gmsgid: "expected integer");
17898 return list;
17899 }
17900 c_parser_consume_token (parser);
17901
17902 add_to_vector:
17903 if (t != error_mark_node)
17904 {
17905 vec = tree_cons (addend, t, vec);
17906 if (neg)
17907 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
17908 }
17909
17910 if (c_parser_next_token_is_not (parser, type: CPP_COMMA)
17911 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
17912 || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
17913 break;
17914
17915 c_parser_consume_token (parser);
17916 }
17917
17918 if (vec == NULL_TREE)
17919 return list;
17920
17921 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
17922 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
17923 OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
17924 OMP_CLAUSE_DECL (u) = nreverse (vec);
17925 OMP_CLAUSE_CHAIN (u) = list;
17926 return u;
17927}
17928
17929/* OpenMP 5.0:
17930 iterators ( iterators-definition )
17931
17932 iterators-definition:
17933 iterator-specifier
17934 iterator-specifier , iterators-definition
17935
17936 iterator-specifier:
17937 identifier = range-specification
17938 iterator-type identifier = range-specification
17939
17940 range-specification:
17941 begin : end
17942 begin : end : step */
17943
17944static tree
17945c_parser_omp_iterators (c_parser *parser)
17946{
17947 tree ret = NULL_TREE, *last = &ret;
17948 c_parser_consume_token (parser);
17949
17950 push_scope ();
17951
17952 matching_parens parens;
17953 if (!parens.require_open (parser))
17954 return error_mark_node;
17955
17956 do
17957 {
17958 tree iter_type = NULL_TREE, type_expr = NULL_TREE;
17959 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
17960 {
17961 struct c_type_name *type = c_parser_type_name (parser);
17962 if (type != NULL)
17963 iter_type = groktypename (type, &type_expr, NULL);
17964 }
17965 if (iter_type == NULL_TREE)
17966 iter_type = integer_type_node;
17967
17968 location_t loc = c_parser_peek_token (parser)->location;
17969 if (!c_parser_next_token_is (parser, type: CPP_NAME))
17970 {
17971 c_parser_error (parser, gmsgid: "expected identifier");
17972 break;
17973 }
17974
17975 tree id = c_parser_peek_token (parser)->value;
17976 c_parser_consume_token (parser);
17977
17978 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
17979 break;
17980
17981 location_t eloc = c_parser_peek_token (parser)->location;
17982 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17983 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
17984 tree begin = expr.value;
17985
17986 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
17987 break;
17988
17989 eloc = c_parser_peek_token (parser)->location;
17990 expr = c_parser_expr_no_commas (parser, NULL);
17991 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
17992 tree end = expr.value;
17993
17994 tree step = integer_one_node;
17995 if (c_parser_next_token_is (parser, type: CPP_COLON))
17996 {
17997 c_parser_consume_token (parser);
17998 eloc = c_parser_peek_token (parser)->location;
17999 expr = c_parser_expr_no_commas (parser, NULL);
18000 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
18001 step = expr.value;
18002 }
18003
18004 tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
18005 DECL_ARTIFICIAL (iter_var) = 1;
18006 DECL_CONTEXT (iter_var) = current_function_decl;
18007 pushdecl (iter_var);
18008
18009 *last = make_tree_vec (6);
18010 TREE_VEC_ELT (*last, 0) = iter_var;
18011 TREE_VEC_ELT (*last, 1) = begin;
18012 TREE_VEC_ELT (*last, 2) = end;
18013 TREE_VEC_ELT (*last, 3) = step;
18014 last = &TREE_CHAIN (*last);
18015
18016 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18017 {
18018 c_parser_consume_token (parser);
18019 continue;
18020 }
18021 break;
18022 }
18023 while (1);
18024
18025 parens.skip_until_found_close (parser);
18026 return ret ? ret : error_mark_node;
18027}
18028
18029/* OpenMP 5.0:
18030 affinity ( [aff-modifier :] variable-list )
18031 aff-modifier:
18032 iterator ( iterators-definition ) */
18033
18034static tree
18035c_parser_omp_clause_affinity (c_parser *parser, tree list)
18036{
18037 location_t clause_loc = c_parser_peek_token (parser)->location;
18038 tree nl, iterators = NULL_TREE;
18039
18040 matching_parens parens;
18041 if (!parens.require_open (parser))
18042 return list;
18043
18044 if (c_parser_next_token_is (parser, type: CPP_NAME))
18045 {
18046 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18047 bool parse_iter = ((strcmp (s1: "iterator", s2: p) == 0)
18048 && (c_parser_peek_2nd_token (parser)->type
18049 == CPP_OPEN_PAREN));
18050 if (parse_iter)
18051 {
18052 unsigned n = 3;
18053 parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, n: &n)
18054 && (c_parser_peek_nth_token_raw (parser, n)->type
18055 == CPP_CLOSE_PAREN)
18056 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
18057 == CPP_COLON));
18058 }
18059 if (parse_iter)
18060 {
18061 iterators = c_parser_omp_iterators (parser);
18062 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18063 {
18064 if (iterators)
18065 pop_scope ();
18066 parens.skip_until_found_close (parser);
18067 return list;
18068 }
18069 }
18070 }
18071 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_AFFINITY,
18072 list);
18073 if (iterators)
18074 {
18075 tree block = pop_scope ();
18076 if (iterators != error_mark_node)
18077 {
18078 TREE_VEC_ELT (iterators, 5) = block;
18079 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18080 OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
18081 OMP_CLAUSE_DECL (c));
18082 }
18083 }
18084
18085 parens.skip_until_found_close (parser);
18086 return nl;
18087}
18088
18089
18090/* OpenMP 4.0:
18091 depend ( depend-kind: variable-list )
18092
18093 depend-kind:
18094 in | out | inout
18095
18096 OpenMP 4.5:
18097 depend ( source )
18098
18099 depend ( sink : vec )
18100
18101 OpenMP 5.0:
18102 depend ( depend-modifier , depend-kind: variable-list )
18103
18104 depend-kind:
18105 in | out | inout | mutexinoutset | depobj | inoutset
18106
18107 depend-modifier:
18108 iterator ( iterators-definition ) */
18109
18110static tree
18111c_parser_omp_clause_depend (c_parser *parser, tree list)
18112{
18113 location_t clause_loc = c_parser_peek_token (parser)->location;
18114 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
18115 enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
18116 tree nl, c, iterators = NULL_TREE;
18117
18118 matching_parens parens;
18119 if (!parens.require_open (parser))
18120 return list;
18121
18122 do
18123 {
18124 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
18125 goto invalid_kind;
18126
18127 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18128 if (strcmp (s1: "iterator", s2: p) == 0 && iterators == NULL_TREE)
18129 {
18130 iterators = c_parser_omp_iterators (parser);
18131 c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>");
18132 continue;
18133 }
18134 if (strcmp (s1: "in", s2: p) == 0)
18135 kind = OMP_CLAUSE_DEPEND_IN;
18136 else if (strcmp (s1: "inout", s2: p) == 0)
18137 kind = OMP_CLAUSE_DEPEND_INOUT;
18138 else if (strcmp (s1: "inoutset", s2: p) == 0)
18139 kind = OMP_CLAUSE_DEPEND_INOUTSET;
18140 else if (strcmp (s1: "mutexinoutset", s2: p) == 0)
18141 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
18142 else if (strcmp (s1: "out", s2: p) == 0)
18143 kind = OMP_CLAUSE_DEPEND_OUT;
18144 else if (strcmp (s1: "depobj", s2: p) == 0)
18145 kind = OMP_CLAUSE_DEPEND_DEPOBJ;
18146 else if (strcmp (s1: "sink", s2: p) == 0)
18147 dkind = OMP_CLAUSE_DOACROSS_SINK;
18148 else if (strcmp (s1: "source", s2: p) == 0)
18149 dkind = OMP_CLAUSE_DOACROSS_SOURCE;
18150 else
18151 goto invalid_kind;
18152 break;
18153 }
18154 while (1);
18155
18156 c_parser_consume_token (parser);
18157
18158 if (iterators
18159 && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
18160 || dkind == OMP_CLAUSE_DOACROSS_SINK))
18161 {
18162 pop_scope ();
18163 error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
18164 dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
18165 iterators = NULL_TREE;
18166 }
18167
18168 if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
18169 {
18170 c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18171 OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
18172 OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
18173 OMP_CLAUSE_DECL (c) = NULL_TREE;
18174 OMP_CLAUSE_CHAIN (c) = list;
18175 parens.skip_until_found_close (parser);
18176 return c;
18177 }
18178
18179 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18180 goto resync_fail;
18181
18182 if (dkind == OMP_CLAUSE_DOACROSS_SINK)
18183 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: true);
18184 else
18185 {
18186 nl = c_parser_omp_variable_list (parser, clause_loc,
18187 kind: OMP_CLAUSE_DEPEND, list);
18188
18189 if (iterators)
18190 {
18191 tree block = pop_scope ();
18192 if (iterators == error_mark_node)
18193 iterators = NULL_TREE;
18194 else
18195 TREE_VEC_ELT (iterators, 5) = block;
18196 }
18197
18198 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18199 {
18200 OMP_CLAUSE_DEPEND_KIND (c) = kind;
18201 if (iterators)
18202 OMP_CLAUSE_DECL (c)
18203 = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
18204 }
18205 }
18206
18207 parens.skip_until_found_close (parser);
18208 return nl;
18209
18210 invalid_kind:
18211 c_parser_error (parser, gmsgid: "invalid depend kind");
18212 resync_fail:
18213 parens.skip_until_found_close (parser);
18214 if (iterators)
18215 pop_scope ();
18216 return list;
18217}
18218
18219/* OpenMP 5.2:
18220 doacross ( source : )
18221 doacross ( source : omp_cur_iteration )
18222
18223 doacross ( sink : vec )
18224 doacross ( sink : omp_cur_iteration - logical_iteration ) */
18225
18226static tree
18227c_parser_omp_clause_doacross (c_parser *parser, tree list)
18228{
18229 location_t clause_loc = c_parser_peek_token (parser)->location;
18230 enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
18231 tree nl;
18232 const char *p;
18233
18234 matching_parens parens;
18235 if (!parens.require_open (parser))
18236 return list;
18237
18238 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
18239 goto invalid_kind;
18240
18241 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18242 if (strcmp (s1: "sink", s2: p) == 0)
18243 kind = OMP_CLAUSE_DOACROSS_SINK;
18244 else if (strcmp (s1: "source", s2: p) == 0)
18245 kind = OMP_CLAUSE_DOACROSS_SOURCE;
18246 else
18247 goto invalid_kind;
18248
18249 c_parser_consume_token (parser);
18250
18251 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18252 goto resync_fail;
18253
18254 if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
18255 {
18256 if (c_parser_next_token_is (parser, type: CPP_NAME)
18257 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
18258 s2: "omp_cur_iteration") == 0)
18259 c_parser_consume_token (parser);
18260 nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
18261 OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
18262 OMP_CLAUSE_DECL (nl) = NULL_TREE;
18263 OMP_CLAUSE_CHAIN (nl) = list;
18264 }
18265 else
18266 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: false);
18267
18268 parens.skip_until_found_close (parser);
18269 return nl;
18270
18271 invalid_kind:
18272 c_parser_error (parser, gmsgid: "invalid doacross kind");
18273 resync_fail:
18274 parens.skip_until_found_close (parser);
18275 return list;
18276}
18277
18278/* OpenMP 4.0:
18279 map ( map-kind: variable-list )
18280 map ( variable-list )
18281
18282 map-kind:
18283 alloc | to | from | tofrom
18284
18285 OpenMP 4.5:
18286 map-kind:
18287 alloc | to | from | tofrom | release | delete
18288
18289 map ( always [,] map-kind: variable-list )
18290
18291 OpenMP 5.0:
18292 map ( [map-type-modifier[,] ...] map-kind: variable-list )
18293
18294 map-type-modifier:
18295 always | close */
18296
18297static tree
18298c_parser_omp_clause_map (c_parser *parser, tree list)
18299{
18300 location_t clause_loc = c_parser_peek_token (parser)->location;
18301 enum gomp_map_kind kind = GOMP_MAP_TOFROM;
18302 tree nl, c;
18303
18304 matching_parens parens;
18305 if (!parens.require_open (parser))
18306 return list;
18307
18308 int pos = 1;
18309 int map_kind_pos = 0;
18310 while (c_parser_peek_nth_token_raw (parser, n: pos)->type == CPP_NAME)
18311 {
18312 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COLON)
18313 {
18314 map_kind_pos = pos;
18315 break;
18316 }
18317
18318 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COMMA)
18319 pos++;
18320 pos++;
18321 }
18322
18323 int always_modifier = 0;
18324 int close_modifier = 0;
18325 int present_modifier = 0;
18326 for (int pos = 1; pos < map_kind_pos; ++pos)
18327 {
18328 c_token *tok = c_parser_peek_token (parser);
18329
18330 if (tok->type == CPP_COMMA)
18331 {
18332 c_parser_consume_token (parser);
18333 continue;
18334 }
18335
18336 const char *p = IDENTIFIER_POINTER (tok->value);
18337 if (strcmp (s1: "always", s2: p) == 0)
18338 {
18339 if (always_modifier)
18340 {
18341 c_parser_error (parser, gmsgid: "too many %<always%> modifiers");
18342 parens.skip_until_found_close (parser);
18343 return list;
18344 }
18345 always_modifier++;
18346 }
18347 else if (strcmp (s1: "close", s2: p) == 0)
18348 {
18349 if (close_modifier)
18350 {
18351 c_parser_error (parser, gmsgid: "too many %<close%> modifiers");
18352 parens.skip_until_found_close (parser);
18353 return list;
18354 }
18355 close_modifier++;
18356 }
18357 else if (strcmp (s1: "present", s2: p) == 0)
18358 {
18359 if (present_modifier)
18360 {
18361 c_parser_error (parser, gmsgid: "too many %<present%> modifiers");
18362 parens.skip_until_found_close (parser);
18363 return list;
18364 }
18365 present_modifier++;
18366 }
18367 else
18368 {
18369 c_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other "
18370 "than %<always%>, %<close%> or %<present%>");
18371 parens.skip_until_found_close (parser);
18372 return list;
18373 }
18374
18375 c_parser_consume_token (parser);
18376 }
18377
18378 if (c_parser_next_token_is (parser, type: CPP_NAME)
18379 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18380 {
18381 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18382 int always_present_modifier = always_modifier && present_modifier;
18383
18384 if (strcmp (s1: "alloc", s2: p) == 0)
18385 kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
18386 else if (strcmp (s1: "to", s2: p) == 0)
18387 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
18388 : present_modifier ? GOMP_MAP_PRESENT_TO
18389 : always_modifier ? GOMP_MAP_ALWAYS_TO
18390 : GOMP_MAP_TO);
18391 else if (strcmp (s1: "from", s2: p) == 0)
18392 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
18393 : present_modifier ? GOMP_MAP_PRESENT_FROM
18394 : always_modifier ? GOMP_MAP_ALWAYS_FROM
18395 : GOMP_MAP_FROM);
18396 else if (strcmp (s1: "tofrom", s2: p) == 0)
18397 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
18398 : present_modifier ? GOMP_MAP_PRESENT_TOFROM
18399 : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
18400 : GOMP_MAP_TOFROM);
18401 else if (strcmp (s1: "release", s2: p) == 0)
18402 kind = GOMP_MAP_RELEASE;
18403 else if (strcmp (s1: "delete", s2: p) == 0)
18404 kind = GOMP_MAP_DELETE;
18405 else
18406 {
18407 c_parser_error (parser, gmsgid: "invalid map kind");
18408 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18409 msgid: "expected %<)%>");
18410 return list;
18411 }
18412 c_parser_consume_token (parser);
18413 c_parser_consume_token (parser);
18414 }
18415
18416 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_MAP, list,
18417 allow_deref: true);
18418
18419 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18420 OMP_CLAUSE_SET_MAP_KIND (c, kind);
18421
18422 parens.skip_until_found_close (parser);
18423 return nl;
18424}
18425
18426/* OpenMP 4.0:
18427 device ( expression )
18428
18429 OpenMP 5.0:
18430 device ( [device-modifier :] integer-expression )
18431
18432 device-modifier:
18433 ancestor | device_num */
18434
18435static tree
18436c_parser_omp_clause_device (c_parser *parser, tree list)
18437{
18438 location_t clause_loc = c_parser_peek_token (parser)->location;
18439 location_t expr_loc;
18440 c_expr expr;
18441 tree c, t;
18442 bool ancestor = false;
18443
18444 matching_parens parens;
18445 if (!parens.require_open (parser))
18446 return list;
18447
18448 if (c_parser_next_token_is (parser, type: CPP_NAME)
18449 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18450 {
18451 c_token *tok = c_parser_peek_token (parser);
18452 const char *p = IDENTIFIER_POINTER (tok->value);
18453 if (strcmp (s1: "ancestor", s2: p) == 0)
18454 {
18455 /* A requires directive with the reverse_offload clause must be
18456 specified. */
18457 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
18458 {
18459 error_at (tok->location, "%<ancestor%> device modifier not "
18460 "preceded by %<requires%> directive "
18461 "with %<reverse_offload%> clause");
18462 parens.skip_until_found_close (parser);
18463 return list;
18464 }
18465 ancestor = true;
18466 }
18467 else if (strcmp (s1: "device_num", s2: p) == 0)
18468 ;
18469 else
18470 {
18471 error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
18472 parens.skip_until_found_close (parser);
18473 return list;
18474 }
18475 c_parser_consume_token (parser);
18476 c_parser_consume_token (parser);
18477 }
18478
18479 expr_loc = c_parser_peek_token (parser)->location;
18480 expr = c_parser_expr_no_commas (parser, NULL);
18481 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18482 t = expr.value;
18483 t = c_fully_fold (t, false, NULL);
18484
18485 parens.skip_until_found_close (parser);
18486
18487 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18488 {
18489 c_parser_error (parser, gmsgid: "expected integer expression");
18490 return list;
18491 }
18492 if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
18493 {
18494 error_at (expr_loc, "the %<device%> clause expression must evaluate to "
18495 "%<1%>");
18496 return list;
18497 }
18498
18499 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, name: "device");
18500
18501 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
18502
18503 OMP_CLAUSE_DEVICE_ID (c) = t;
18504 OMP_CLAUSE_CHAIN (c) = list;
18505 OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
18506
18507 list = c;
18508 return list;
18509}
18510
18511/* OpenMP 4.0:
18512 dist_schedule ( static )
18513 dist_schedule ( static , expression ) */
18514
18515static tree
18516c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
18517{
18518 tree c, t = NULL_TREE;
18519 location_t loc = c_parser_peek_token (parser)->location;
18520
18521 matching_parens parens;
18522 if (!parens.require_open (parser))
18523 return list;
18524
18525 if (!c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
18526 {
18527 c_parser_error (parser, gmsgid: "invalid dist_schedule kind");
18528 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18529 msgid: "expected %<)%>");
18530 return list;
18531 }
18532
18533 c_parser_consume_token (parser);
18534 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18535 {
18536 c_parser_consume_token (parser);
18537
18538 location_t expr_loc = c_parser_peek_token (parser)->location;
18539 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18540 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18541 t = expr.value;
18542 t = c_fully_fold (t, false, NULL);
18543 parens.skip_until_found_close (parser);
18544 }
18545 else
18546 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18547 msgid: "expected %<,%> or %<)%>");
18548
18549 /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
18550 "dist_schedule"); */
18551 if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE))
18552 warning_at (loc, 0, "too many %qs clauses", "dist_schedule");
18553 if (t == error_mark_node)
18554 return list;
18555
18556 c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
18557 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
18558 OMP_CLAUSE_CHAIN (c) = list;
18559 return c;
18560}
18561
18562/* OpenMP 4.0:
18563 proc_bind ( proc-bind-kind )
18564
18565 proc-bind-kind:
18566 primary | master | close | spread
18567 where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
18568
18569static tree
18570c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
18571{
18572 location_t clause_loc = c_parser_peek_token (parser)->location;
18573 enum omp_clause_proc_bind_kind kind;
18574 tree c;
18575
18576 matching_parens parens;
18577 if (!parens.require_open (parser))
18578 return list;
18579
18580 if (c_parser_next_token_is (parser, type: CPP_NAME))
18581 {
18582 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18583 if (strcmp (s1: "primary", s2: p) == 0)
18584 kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
18585 else if (strcmp (s1: "master", s2: p) == 0)
18586 kind = OMP_CLAUSE_PROC_BIND_MASTER;
18587 else if (strcmp (s1: "close", s2: p) == 0)
18588 kind = OMP_CLAUSE_PROC_BIND_CLOSE;
18589 else if (strcmp (s1: "spread", s2: p) == 0)
18590 kind = OMP_CLAUSE_PROC_BIND_SPREAD;
18591 else
18592 goto invalid_kind;
18593 }
18594 else
18595 goto invalid_kind;
18596
18597 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind");
18598 c_parser_consume_token (parser);
18599 parens.skip_until_found_close (parser);
18600 c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
18601 OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
18602 OMP_CLAUSE_CHAIN (c) = list;
18603 return c;
18604
18605 invalid_kind:
18606 c_parser_error (parser, gmsgid: "invalid proc_bind kind");
18607 parens.skip_until_found_close (parser);
18608 return list;
18609}
18610
18611/* OpenMP 5.0:
18612 device_type ( host | nohost | any ) */
18613
18614static tree
18615c_parser_omp_clause_device_type (c_parser *parser, tree list)
18616{
18617 location_t clause_loc = c_parser_peek_token (parser)->location;
18618 enum omp_clause_device_type_kind kind;
18619 tree c;
18620
18621 matching_parens parens;
18622 if (!parens.require_open (parser))
18623 return list;
18624
18625 if (c_parser_next_token_is (parser, type: CPP_NAME))
18626 {
18627 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18628 if (strcmp (s1: "host", s2: p) == 0)
18629 kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
18630 else if (strcmp (s1: "nohost", s2: p) == 0)
18631 kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
18632 else if (strcmp (s1: "any", s2: p) == 0)
18633 kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
18634 else
18635 goto invalid_kind;
18636 }
18637 else
18638 goto invalid_kind;
18639
18640 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE,
18641 name: "device_type");
18642 c_parser_consume_token (parser);
18643 parens.skip_until_found_close (parser);
18644 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
18645 OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
18646 OMP_CLAUSE_CHAIN (c) = list;
18647 return c;
18648
18649 invalid_kind:
18650 c_parser_error (parser, gmsgid: "expected %<host%>, %<nohost%> or %<any%>");
18651 parens.skip_until_found_close (parser);
18652 return list;
18653}
18654
18655/* OpenMP 4.0:
18656 from ( variable-list )
18657 to ( variable-list )
18658
18659 OpenMP 5.1:
18660 from ( [present :] variable-list )
18661 to ( [present :] variable-list ) */
18662
18663static tree
18664c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
18665 tree list)
18666{
18667 location_t loc = c_parser_peek_token (parser)->location;
18668 matching_parens parens;
18669 if (!parens.require_open (parser))
18670 return list;
18671
18672 bool present = false;
18673 c_token *token = c_parser_peek_token (parser);
18674
18675 if (token->type == CPP_NAME
18676 && strcmp (IDENTIFIER_POINTER (token->value), s2: "present") == 0
18677 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18678 {
18679 present = true;
18680 c_parser_consume_token (parser);
18681 c_parser_consume_token (parser);
18682 }
18683
18684 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list);
18685 parens.skip_until_found_close (parser);
18686
18687 if (present)
18688 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18689 OMP_CLAUSE_MOTION_PRESENT (c) = 1;
18690
18691 return nl;
18692}
18693
18694/* OpenMP 4.0:
18695 uniform ( variable-list ) */
18696
18697static tree
18698c_parser_omp_clause_uniform (c_parser *parser, tree list)
18699{
18700 /* The clauses location. */
18701 location_t loc = c_parser_peek_token (parser)->location;
18702
18703 matching_parens parens;
18704 if (parens.require_open (parser))
18705 {
18706 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_UNIFORM,
18707 list);
18708 parens.skip_until_found_close (parser);
18709 }
18710 return list;
18711}
18712
18713/* OpenMP 5.0:
18714 detach ( event-handle ) */
18715
18716static tree
18717c_parser_omp_clause_detach (c_parser *parser, tree list)
18718{
18719 matching_parens parens;
18720 location_t clause_loc = c_parser_peek_token (parser)->location;
18721
18722 if (!parens.require_open (parser))
18723 return list;
18724
18725 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
18726 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
18727 {
18728 c_parser_error (parser, gmsgid: "expected identifier");
18729 parens.skip_until_found_close (parser);
18730 return list;
18731 }
18732
18733 tree t = lookup_name (c_parser_peek_token (parser)->value);
18734 if (t == NULL_TREE)
18735 {
18736 undeclared_variable (c_parser_peek_token (parser)->location,
18737 c_parser_peek_token (parser)->value);
18738 parens.skip_until_found_close (parser);
18739 return list;
18740 }
18741 c_parser_consume_token (parser);
18742
18743 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
18744 if (!INTEGRAL_TYPE_P (type)
18745 || TREE_CODE (type) != ENUMERAL_TYPE
18746 || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
18747 {
18748 error_at (clause_loc, "%<detach%> clause event handle "
18749 "has type %qT rather than "
18750 "%<omp_event_handle_t%>",
18751 type);
18752 parens.skip_until_found_close (parser);
18753 return list;
18754 }
18755
18756 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
18757 OMP_CLAUSE_DECL (u) = t;
18758 OMP_CLAUSE_CHAIN (u) = list;
18759 parens.skip_until_found_close (parser);
18760 return u;
18761}
18762
18763/* Parse all OpenACC clauses. The set clauses allowed by the directive
18764 is a bitmask in MASK. Return the list of clauses found. */
18765
18766static tree
18767c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
18768 const char *where, bool finish_p = true)
18769{
18770 tree clauses = NULL;
18771 bool first = true;
18772
18773 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
18774 {
18775 location_t here;
18776 pragma_omp_clause c_kind;
18777 const char *c_name;
18778 tree prev = clauses;
18779
18780 if (!first && c_parser_next_token_is (parser, type: CPP_COMMA))
18781 c_parser_consume_token (parser);
18782
18783 here = c_parser_peek_token (parser)->location;
18784 c_kind = c_parser_omp_clause_name (parser);
18785
18786 switch (c_kind)
18787 {
18788 case PRAGMA_OACC_CLAUSE_ASYNC:
18789 clauses = c_parser_oacc_clause_async (parser, list: clauses);
18790 c_name = "async";
18791 break;
18792 case PRAGMA_OACC_CLAUSE_AUTO:
18793 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO,
18794 list: clauses);
18795 c_name = "auto";
18796 break;
18797 case PRAGMA_OACC_CLAUSE_ATTACH:
18798 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18799 c_name = "attach";
18800 break;
18801 case PRAGMA_OACC_CLAUSE_COLLAPSE:
18802 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
18803 c_name = "collapse";
18804 break;
18805 case PRAGMA_OACC_CLAUSE_COPY:
18806 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18807 c_name = "copy";
18808 break;
18809 case PRAGMA_OACC_CLAUSE_COPYIN:
18810 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18811 c_name = "copyin";
18812 break;
18813 case PRAGMA_OACC_CLAUSE_COPYOUT:
18814 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18815 c_name = "copyout";
18816 break;
18817 case PRAGMA_OACC_CLAUSE_CREATE:
18818 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18819 c_name = "create";
18820 break;
18821 case PRAGMA_OACC_CLAUSE_DELETE:
18822 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18823 c_name = "delete";
18824 break;
18825 case PRAGMA_OMP_CLAUSE_DEFAULT:
18826 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: true);
18827 c_name = "default";
18828 break;
18829 case PRAGMA_OACC_CLAUSE_DETACH:
18830 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18831 c_name = "detach";
18832 break;
18833 case PRAGMA_OACC_CLAUSE_DEVICE:
18834 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18835 c_name = "device";
18836 break;
18837 case PRAGMA_OACC_CLAUSE_DEVICEPTR:
18838 clauses = c_parser_oacc_data_clause_deviceptr (parser, list: clauses);
18839 c_name = "deviceptr";
18840 break;
18841 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
18842 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18843 c_name = "device_resident";
18844 break;
18845 case PRAGMA_OACC_CLAUSE_FINALIZE:
18846 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE,
18847 list: clauses);
18848 c_name = "finalize";
18849 break;
18850 case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
18851 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
18852 c_name = "firstprivate";
18853 break;
18854 case PRAGMA_OACC_CLAUSE_GANG:
18855 c_name = "gang";
18856 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG,
18857 str: c_name, list: clauses);
18858 break;
18859 case PRAGMA_OACC_CLAUSE_HOST:
18860 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18861 c_name = "host";
18862 break;
18863 case PRAGMA_OACC_CLAUSE_IF:
18864 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: false);
18865 c_name = "if";
18866 break;
18867 case PRAGMA_OACC_CLAUSE_IF_PRESENT:
18868 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT,
18869 list: clauses);
18870 c_name = "if_present";
18871 break;
18872 case PRAGMA_OACC_CLAUSE_INDEPENDENT:
18873 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT,
18874 list: clauses);
18875 c_name = "independent";
18876 break;
18877 case PRAGMA_OACC_CLAUSE_LINK:
18878 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18879 c_name = "link";
18880 break;
18881 case PRAGMA_OACC_CLAUSE_NO_CREATE:
18882 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18883 c_name = "no_create";
18884 break;
18885 case PRAGMA_OACC_CLAUSE_NOHOST:
18886 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST,
18887 list: clauses);
18888 c_name = "nohost";
18889 break;
18890 case PRAGMA_OACC_CLAUSE_NUM_GANGS:
18891 clauses = c_parser_oacc_single_int_clause (parser,
18892 code: OMP_CLAUSE_NUM_GANGS,
18893 list: clauses);
18894 c_name = "num_gangs";
18895 break;
18896 case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
18897 clauses = c_parser_oacc_single_int_clause (parser,
18898 code: OMP_CLAUSE_NUM_WORKERS,
18899 list: clauses);
18900 c_name = "num_workers";
18901 break;
18902 case PRAGMA_OACC_CLAUSE_PRESENT:
18903 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18904 c_name = "present";
18905 break;
18906 case PRAGMA_OACC_CLAUSE_PRIVATE:
18907 clauses = c_parser_omp_clause_private (parser, list: clauses);
18908 c_name = "private";
18909 break;
18910 case PRAGMA_OACC_CLAUSE_REDUCTION:
18911 clauses
18912 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
18913 is_omp: false, list: clauses);
18914 c_name = "reduction";
18915 break;
18916 case PRAGMA_OACC_CLAUSE_SELF:
18917 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
18918 /* OpenACC compute construct */
18919 clauses = c_parser_oacc_compute_clause_self (parser, list: clauses);
18920 else
18921 /* OpenACC 'update' directive */
18922 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
18923 c_name = "self";
18924 break;
18925 case PRAGMA_OACC_CLAUSE_SEQ:
18926 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ,
18927 list: clauses);
18928 c_name = "seq";
18929 break;
18930 case PRAGMA_OACC_CLAUSE_TILE:
18931 clauses = c_parser_oacc_clause_tile (parser, list: clauses);
18932 c_name = "tile";
18933 break;
18934 case PRAGMA_OACC_CLAUSE_USE_DEVICE:
18935 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
18936 c_name = "use_device";
18937 break;
18938 case PRAGMA_OACC_CLAUSE_VECTOR:
18939 c_name = "vector";
18940 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_VECTOR,
18941 str: c_name, list: clauses);
18942 break;
18943 case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
18944 clauses = c_parser_oacc_single_int_clause (parser,
18945 code: OMP_CLAUSE_VECTOR_LENGTH,
18946 list: clauses);
18947 c_name = "vector_length";
18948 break;
18949 case PRAGMA_OACC_CLAUSE_WAIT:
18950 clauses = c_parser_oacc_clause_wait (parser, list: clauses);
18951 c_name = "wait";
18952 break;
18953 case PRAGMA_OACC_CLAUSE_WORKER:
18954 c_name = "worker";
18955 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_WORKER,
18956 str: c_name, list: clauses);
18957 break;
18958 default:
18959 c_parser_error (parser, gmsgid: "expected an OpenACC clause");
18960 goto saw_error;
18961 }
18962
18963 first = false;
18964
18965 if (((mask >> c_kind) & 1) == 0)
18966 {
18967 /* Remove the invalid clause(s) from the list to avoid
18968 confusing the rest of the compiler. */
18969 clauses = prev;
18970 error_at (here, "%qs is not valid for %qs", c_name, where);
18971 }
18972 }
18973
18974 saw_error:
18975 c_parser_skip_to_pragma_eol (parser);
18976
18977 if (finish_p)
18978 return c_finish_omp_clauses (clauses, C_ORT_ACC);
18979
18980 return clauses;
18981}
18982
18983/* Parse all OpenMP clauses. The set clauses allowed by the directive
18984 is a bitmask in MASK. Return the list of clauses found.
18985 FINISH_P set if c_finish_omp_clauses should be called.
18986 NESTED non-zero if clauses should be terminated by closing paren instead
18987 of end of pragma. If it is 2, additionally commas are required in between
18988 the clauses. */
18989
18990static tree
18991c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
18992 const char *where, bool finish_p = true,
18993 int nested = 0)
18994{
18995 tree clauses = NULL;
18996 bool first = true;
18997
18998 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
18999 {
19000 location_t here;
19001 pragma_omp_clause c_kind;
19002 const char *c_name;
19003 tree prev = clauses;
19004
19005 if (nested && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
19006 break;
19007
19008 if (!first || nested != 2)
19009 {
19010 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19011 c_parser_consume_token (parser);
19012 else if (nested == 2)
19013 error_at (c_parser_peek_token (parser)->location,
19014 "clauses in %<simd%> trait should be separated "
19015 "by %<,%>");
19016 }
19017
19018 here = c_parser_peek_token (parser)->location;
19019 c_kind = c_parser_omp_clause_name (parser);
19020
19021 switch (c_kind)
19022 {
19023 case PRAGMA_OMP_CLAUSE_BIND:
19024 clauses = c_parser_omp_clause_bind (parser, list: clauses);
19025 c_name = "bind";
19026 break;
19027 case PRAGMA_OMP_CLAUSE_COLLAPSE:
19028 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
19029 c_name = "collapse";
19030 break;
19031 case PRAGMA_OMP_CLAUSE_COPYIN:
19032 clauses = c_parser_omp_clause_copyin (parser, list: clauses);
19033 c_name = "copyin";
19034 break;
19035 case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
19036 clauses = c_parser_omp_clause_copyprivate (parser, list: clauses);
19037 c_name = "copyprivate";
19038 break;
19039 case PRAGMA_OMP_CLAUSE_DEFAULT:
19040 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: false);
19041 c_name = "default";
19042 break;
19043 case PRAGMA_OMP_CLAUSE_DETACH:
19044 clauses = c_parser_omp_clause_detach (parser, list: clauses);
19045 c_name = "detach";
19046 break;
19047 case PRAGMA_OMP_CLAUSE_FILTER:
19048 clauses = c_parser_omp_clause_filter (parser, list: clauses);
19049 c_name = "filter";
19050 break;
19051 case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
19052 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
19053 c_name = "firstprivate";
19054 break;
19055 case PRAGMA_OMP_CLAUSE_FINAL:
19056 clauses = c_parser_omp_clause_final (parser, list: clauses);
19057 c_name = "final";
19058 break;
19059 case PRAGMA_OMP_CLAUSE_GRAINSIZE:
19060 clauses = c_parser_omp_clause_grainsize (parser, list: clauses);
19061 c_name = "grainsize";
19062 break;
19063 case PRAGMA_OMP_CLAUSE_HINT:
19064 clauses = c_parser_omp_clause_hint (parser, list: clauses);
19065 c_name = "hint";
19066 break;
19067 case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
19068 clauses = c_parser_omp_clause_defaultmap (parser, list: clauses);
19069 c_name = "defaultmap";
19070 break;
19071 case PRAGMA_OMP_CLAUSE_IF:
19072 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: true);
19073 c_name = "if";
19074 break;
19075 case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
19076 clauses
19077 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION,
19078 is_omp: true, list: clauses);
19079 c_name = "in_reduction";
19080 break;
19081 case PRAGMA_OMP_CLAUSE_INDIRECT:
19082 clauses = c_parser_omp_clause_indirect (parser, list: clauses);
19083 c_name = "indirect";
19084 break;
19085 case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
19086 clauses = c_parser_omp_clause_lastprivate (parser, list: clauses);
19087 c_name = "lastprivate";
19088 break;
19089 case PRAGMA_OMP_CLAUSE_MERGEABLE:
19090 clauses = c_parser_omp_clause_mergeable (parser, list: clauses);
19091 c_name = "mergeable";
19092 break;
19093 case PRAGMA_OMP_CLAUSE_NOWAIT:
19094 clauses = c_parser_omp_clause_nowait (parser, list: clauses);
19095 c_name = "nowait";
19096 break;
19097 case PRAGMA_OMP_CLAUSE_NUM_TASKS:
19098 clauses = c_parser_omp_clause_num_tasks (parser, list: clauses);
19099 c_name = "num_tasks";
19100 break;
19101 case PRAGMA_OMP_CLAUSE_NUM_THREADS:
19102 clauses = c_parser_omp_clause_num_threads (parser, list: clauses);
19103 c_name = "num_threads";
19104 break;
19105 case PRAGMA_OMP_CLAUSE_ORDER:
19106 clauses = c_parser_omp_clause_order (parser, list: clauses);
19107 c_name = "order";
19108 break;
19109 case PRAGMA_OMP_CLAUSE_ORDERED:
19110 clauses = c_parser_omp_clause_ordered (parser, list: clauses);
19111 c_name = "ordered";
19112 break;
19113 case PRAGMA_OMP_CLAUSE_PRIORITY:
19114 clauses = c_parser_omp_clause_priority (parser, list: clauses);
19115 c_name = "priority";
19116 break;
19117 case PRAGMA_OMP_CLAUSE_PRIVATE:
19118 clauses = c_parser_omp_clause_private (parser, list: clauses);
19119 c_name = "private";
19120 break;
19121 case PRAGMA_OMP_CLAUSE_REDUCTION:
19122 clauses
19123 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
19124 is_omp: true, list: clauses);
19125 c_name = "reduction";
19126 break;
19127 case PRAGMA_OMP_CLAUSE_SCHEDULE:
19128 clauses = c_parser_omp_clause_schedule (parser, list: clauses);
19129 c_name = "schedule";
19130 break;
19131 case PRAGMA_OMP_CLAUSE_SHARED:
19132 clauses = c_parser_omp_clause_shared (parser, list: clauses);
19133 c_name = "shared";
19134 break;
19135 case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
19136 clauses
19137 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_TASK_REDUCTION,
19138 is_omp: true, list: clauses);
19139 c_name = "task_reduction";
19140 break;
19141 case PRAGMA_OMP_CLAUSE_UNTIED:
19142 clauses = c_parser_omp_clause_untied (parser, list: clauses);
19143 c_name = "untied";
19144 break;
19145 case PRAGMA_OMP_CLAUSE_INBRANCH:
19146 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH,
19147 list: clauses);
19148 c_name = "inbranch";
19149 break;
19150 case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
19151 clauses = c_parser_omp_clause_nontemporal (parser, list: clauses);
19152 c_name = "nontemporal";
19153 break;
19154 case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
19155 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_NOTINBRANCH,
19156 list: clauses);
19157 c_name = "notinbranch";
19158 break;
19159 case PRAGMA_OMP_CLAUSE_PARALLEL:
19160 clauses
19161 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL,
19162 list: clauses);
19163 c_name = "parallel";
19164 if (!first)
19165 {
19166 clause_not_first:
19167 error_at (here, "%qs must be the first clause of %qs",
19168 c_name, where);
19169 clauses = prev;
19170 }
19171 break;
19172 case PRAGMA_OMP_CLAUSE_FOR:
19173 clauses
19174 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR,
19175 list: clauses);
19176 c_name = "for";
19177 if (!first)
19178 goto clause_not_first;
19179 break;
19180 case PRAGMA_OMP_CLAUSE_SECTIONS:
19181 clauses
19182 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS,
19183 list: clauses);
19184 c_name = "sections";
19185 if (!first)
19186 goto clause_not_first;
19187 break;
19188 case PRAGMA_OMP_CLAUSE_TASKGROUP:
19189 clauses
19190 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP,
19191 list: clauses);
19192 c_name = "taskgroup";
19193 if (!first)
19194 goto clause_not_first;
19195 break;
19196 case PRAGMA_OMP_CLAUSE_LINK:
19197 clauses
19198 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_LINK, list: clauses);
19199 c_name = "link";
19200 break;
19201 case PRAGMA_OMP_CLAUSE_TO:
19202 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
19203 {
19204 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
19205 list: clauses);
19206 for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
19207 OMP_CLAUSE_ENTER_TO (c) = 1;
19208 clauses = nl;
19209 }
19210 else
19211 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO,
19212 list: clauses);
19213 c_name = "to";
19214 break;
19215 case PRAGMA_OMP_CLAUSE_FROM:
19216 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM,
19217 list: clauses);
19218 c_name = "from";
19219 break;
19220 case PRAGMA_OMP_CLAUSE_UNIFORM:
19221 clauses = c_parser_omp_clause_uniform (parser, list: clauses);
19222 c_name = "uniform";
19223 break;
19224 case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
19225 clauses = c_parser_omp_clause_num_teams (parser, list: clauses);
19226 c_name = "num_teams";
19227 break;
19228 case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
19229 clauses = c_parser_omp_clause_thread_limit (parser, list: clauses);
19230 c_name = "thread_limit";
19231 break;
19232 case PRAGMA_OMP_CLAUSE_ALIGNED:
19233 clauses = c_parser_omp_clause_aligned (parser, list: clauses);
19234 c_name = "aligned";
19235 break;
19236 case PRAGMA_OMP_CLAUSE_ALLOCATE:
19237 clauses = c_parser_omp_clause_allocate (parser, list: clauses);
19238 c_name = "allocate";
19239 break;
19240 case PRAGMA_OMP_CLAUSE_LINEAR:
19241 clauses = c_parser_omp_clause_linear (parser, list: clauses);
19242 c_name = "linear";
19243 break;
19244 case PRAGMA_OMP_CLAUSE_AFFINITY:
19245 clauses = c_parser_omp_clause_affinity (parser, list: clauses);
19246 c_name = "affinity";
19247 break;
19248 case PRAGMA_OMP_CLAUSE_DEPEND:
19249 clauses = c_parser_omp_clause_depend (parser, list: clauses);
19250 c_name = "depend";
19251 break;
19252 case PRAGMA_OMP_CLAUSE_DOACROSS:
19253 clauses = c_parser_omp_clause_doacross (parser, list: clauses);
19254 c_name = "doacross";
19255 break;
19256 case PRAGMA_OMP_CLAUSE_MAP:
19257 clauses = c_parser_omp_clause_map (parser, list: clauses);
19258 c_name = "map";
19259 break;
19260 case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
19261 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
19262 c_name = "use_device_ptr";
19263 break;
19264 case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
19265 clauses = c_parser_omp_clause_use_device_addr (parser, list: clauses);
19266 c_name = "use_device_addr";
19267 break;
19268 case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
19269 clauses = c_parser_omp_clause_has_device_addr (parser, list: clauses);
19270 c_name = "has_device_addr";
19271 break;
19272 case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
19273 clauses = c_parser_omp_clause_is_device_ptr (parser, list: clauses);
19274 c_name = "is_device_ptr";
19275 break;
19276 case PRAGMA_OMP_CLAUSE_DEVICE:
19277 clauses = c_parser_omp_clause_device (parser, list: clauses);
19278 c_name = "device";
19279 break;
19280 case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
19281 clauses = c_parser_omp_clause_dist_schedule (parser, list: clauses);
19282 c_name = "dist_schedule";
19283 break;
19284 case PRAGMA_OMP_CLAUSE_PROC_BIND:
19285 clauses = c_parser_omp_clause_proc_bind (parser, list: clauses);
19286 c_name = "proc_bind";
19287 break;
19288 case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
19289 clauses = c_parser_omp_clause_device_type (parser, list: clauses);
19290 c_name = "device_type";
19291 break;
19292 case PRAGMA_OMP_CLAUSE_SAFELEN:
19293 clauses = c_parser_omp_clause_safelen (parser, list: clauses);
19294 c_name = "safelen";
19295 break;
19296 case PRAGMA_OMP_CLAUSE_SIMDLEN:
19297 clauses = c_parser_omp_clause_simdlen (parser, list: clauses);
19298 c_name = "simdlen";
19299 break;
19300 case PRAGMA_OMP_CLAUSE_NOGROUP:
19301 clauses = c_parser_omp_clause_nogroup (parser, list: clauses);
19302 c_name = "nogroup";
19303 break;
19304 case PRAGMA_OMP_CLAUSE_THREADS:
19305 clauses
19306 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS,
19307 list: clauses);
19308 c_name = "threads";
19309 break;
19310 case PRAGMA_OMP_CLAUSE_SIMD:
19311 clauses
19312 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD,
19313 list: clauses);
19314 c_name = "simd";
19315 break;
19316 case PRAGMA_OMP_CLAUSE_ENTER:
19317 clauses
19318 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
19319 list: clauses);
19320 c_name = "enter";
19321 break;
19322 default:
19323 c_parser_error (parser, gmsgid: "expected an OpenMP clause");
19324 goto saw_error;
19325 }
19326
19327 first = false;
19328
19329 if (((mask >> c_kind) & 1) == 0)
19330 {
19331 /* Remove the invalid clause(s) from the list to avoid
19332 confusing the rest of the compiler. */
19333 clauses = prev;
19334 error_at (here, "%qs is not valid for %qs", c_name, where);
19335 }
19336 }
19337
19338 saw_error:
19339 if (!nested)
19340 c_parser_skip_to_pragma_eol (parser);
19341
19342 if (finish_p)
19343 {
19344 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
19345 return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
19346 return c_finish_omp_clauses (clauses, C_ORT_OMP);
19347 }
19348
19349 return clauses;
19350}
19351
19352/* OpenACC 2.0, OpenMP 2.5:
19353 structured-block:
19354 statement
19355
19356 In practice, we're also interested in adding the statement to an
19357 outer node. So it is convenient if we work around the fact that
19358 c_parser_statement calls add_stmt. */
19359
19360static tree
19361c_parser_omp_structured_block (c_parser *parser, bool *if_p)
19362{
19363 tree stmt = push_stmt_list ();
19364 parser->omp_attrs_forbidden_p = true;
19365 c_parser_statement (parser, if_p);
19366 return pop_stmt_list (stmt);
19367}
19368
19369/* OpenACC 2.0:
19370 # pragma acc cache (variable-list) new-line
19371
19372 LOC is the location of the #pragma token.
19373*/
19374
19375static tree
19376c_parser_oacc_cache (location_t loc, c_parser *parser)
19377{
19378 tree stmt, clauses;
19379
19380 clauses = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE__CACHE_, NULL);
19381 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
19382
19383 c_parser_skip_to_pragma_eol (parser);
19384
19385 stmt = make_node (OACC_CACHE);
19386 TREE_TYPE (stmt) = void_type_node;
19387 OACC_CACHE_CLAUSES (stmt) = clauses;
19388 SET_EXPR_LOCATION (stmt, loc);
19389 add_stmt (stmt);
19390
19391 return stmt;
19392}
19393
19394/* OpenACC 2.0:
19395 # pragma acc data oacc-data-clause[optseq] new-line
19396 structured-block
19397
19398 LOC is the location of the #pragma token.
19399*/
19400
19401#define OACC_DATA_CLAUSE_MASK \
19402 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19403 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19404 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19405 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19406 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19407 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
19408 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19409 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19410 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
19411 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
19412
19413static tree
19414c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
19415{
19416 tree stmt, clauses, block;
19417
19418 clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
19419 where: "#pragma acc data");
19420
19421 block = c_begin_omp_parallel ();
19422 add_stmt (c_parser_omp_structured_block (parser, if_p));
19423
19424 stmt = c_finish_oacc_data (loc, clauses, block);
19425
19426 return stmt;
19427}
19428
19429/* OpenACC 2.0:
19430 # pragma acc declare oacc-data-clause[optseq] new-line
19431*/
19432
19433#define OACC_DECLARE_CLAUSE_MASK \
19434 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19435 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19436 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19437 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19438 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19439 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
19440 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
19441 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
19442
19443static void
19444c_parser_oacc_declare (c_parser *parser)
19445{
19446 location_t pragma_loc = c_parser_peek_token (parser)->location;
19447 tree clauses, stmt, t, decl;
19448
19449 bool error = false;
19450
19451 c_parser_consume_pragma (parser);
19452
19453 clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
19454 where: "#pragma acc declare");
19455 if (!clauses)
19456 {
19457 error_at (pragma_loc,
19458 "no valid clauses specified in %<#pragma acc declare%>");
19459 return;
19460 }
19461
19462 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
19463 {
19464 location_t loc = OMP_CLAUSE_LOCATION (t);
19465 decl = OMP_CLAUSE_DECL (t);
19466 if (!DECL_P (decl))
19467 {
19468 error_at (loc, "array section in %<#pragma acc declare%>");
19469 error = true;
19470 continue;
19471 }
19472
19473 switch (OMP_CLAUSE_MAP_KIND (t))
19474 {
19475 case GOMP_MAP_FIRSTPRIVATE_POINTER:
19476 case GOMP_MAP_ALLOC:
19477 case GOMP_MAP_TO:
19478 case GOMP_MAP_FORCE_DEVICEPTR:
19479 case GOMP_MAP_DEVICE_RESIDENT:
19480 break;
19481
19482 case GOMP_MAP_LINK:
19483 if (!global_bindings_p ()
19484 && (TREE_STATIC (decl)
19485 || !DECL_EXTERNAL (decl)))
19486 {
19487 error_at (loc,
19488 "%qD must be a global variable in "
19489 "%<#pragma acc declare link%>",
19490 decl);
19491 error = true;
19492 continue;
19493 }
19494 break;
19495
19496 default:
19497 if (global_bindings_p ())
19498 {
19499 error_at (loc, "invalid OpenACC clause at file scope");
19500 error = true;
19501 continue;
19502 }
19503 if (DECL_EXTERNAL (decl))
19504 {
19505 error_at (loc,
19506 "invalid use of %<extern%> variable %qD "
19507 "in %<#pragma acc declare%>", decl);
19508 error = true;
19509 continue;
19510 }
19511 else if (TREE_PUBLIC (decl))
19512 {
19513 error_at (loc,
19514 "invalid use of %<global%> variable %qD "
19515 "in %<#pragma acc declare%>", decl);
19516 error = true;
19517 continue;
19518 }
19519 break;
19520 }
19521
19522 if (!c_check_in_current_scope (decl))
19523 {
19524 error_at (loc,
19525 "%qD must be a variable declared in the same scope as "
19526 "%<#pragma acc declare%>", decl);
19527 error = true;
19528 continue;
19529 }
19530
19531 if (lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (decl))
19532 || lookup_attribute (attr_name: "omp declare target link",
19533 DECL_ATTRIBUTES (decl)))
19534 {
19535 error_at (loc, "variable %qD used more than once with "
19536 "%<#pragma acc declare%>", decl);
19537 error = true;
19538 continue;
19539 }
19540
19541 if (!error)
19542 {
19543 tree id;
19544
19545 if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
19546 id = get_identifier ("omp declare target link");
19547 else
19548 id = get_identifier ("omp declare target");
19549
19550 DECL_ATTRIBUTES (decl)
19551 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
19552
19553 if (global_bindings_p ())
19554 {
19555 symtab_node *node = symtab_node::get (decl);
19556 if (node != NULL)
19557 {
19558 node->offloadable = 1;
19559 if (ENABLE_OFFLOADING)
19560 {
19561 g->have_offload = true;
19562 if (is_a <varpool_node *> (p: node))
19563 vec_safe_push (v&: offload_vars, obj: decl);
19564 }
19565 }
19566 }
19567 }
19568 }
19569
19570 if (error || global_bindings_p ())
19571 return;
19572
19573 stmt = make_node (OACC_DECLARE);
19574 TREE_TYPE (stmt) = void_type_node;
19575 OACC_DECLARE_CLAUSES (stmt) = clauses;
19576 SET_EXPR_LOCATION (stmt, pragma_loc);
19577
19578 add_stmt (stmt);
19579
19580 return;
19581}
19582
19583/* OpenACC 2.0:
19584 # pragma acc enter data oacc-enter-data-clause[optseq] new-line
19585
19586 or
19587
19588 # pragma acc exit data oacc-exit-data-clause[optseq] new-line
19589
19590
19591 LOC is the location of the #pragma token.
19592*/
19593
19594#define OACC_ENTER_DATA_CLAUSE_MASK \
19595 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19596 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
19597 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19598 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19599 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19600 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
19601
19602#define OACC_EXIT_DATA_CLAUSE_MASK \
19603 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19604 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
19605 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19606 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
19607 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
19608 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
19609 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
19610
19611static void
19612c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
19613{
19614 location_t loc = c_parser_peek_token (parser)->location;
19615 tree clauses, stmt;
19616 const char *p = "";
19617
19618 c_parser_consume_pragma (parser);
19619
19620 if (c_parser_next_token_is (parser, type: CPP_NAME))
19621 {
19622 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19623 c_parser_consume_token (parser);
19624 }
19625
19626 if (strcmp (s1: p, s2: "data") != 0)
19627 {
19628 error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
19629 enter ? "enter" : "exit");
19630 parser->error = true;
19631 c_parser_skip_to_pragma_eol (parser);
19632 return;
19633 }
19634
19635 if (enter)
19636 clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
19637 where: "#pragma acc enter data");
19638 else
19639 clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
19640 where: "#pragma acc exit data");
19641
19642 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
19643 {
19644 error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
19645 enter ? "enter" : "exit");
19646 return;
19647 }
19648
19649 stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
19650 TREE_TYPE (stmt) = void_type_node;
19651 OMP_STANDALONE_CLAUSES (stmt) = clauses;
19652 SET_EXPR_LOCATION (stmt, loc);
19653 add_stmt (stmt);
19654}
19655
19656
19657/* OpenACC 2.0:
19658 # pragma acc host_data oacc-data-clause[optseq] new-line
19659 structured-block
19660*/
19661
19662#define OACC_HOST_DATA_CLAUSE_MASK \
19663 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
19664 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19665 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
19666
19667static tree
19668c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
19669{
19670 tree stmt, clauses, block;
19671
19672 clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
19673 where: "#pragma acc host_data", finish_p: false);
19674 if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR))
19675 {
19676 error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
19677 return error_mark_node;
19678 }
19679 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
19680 block = c_begin_omp_parallel ();
19681 add_stmt (c_parser_omp_structured_block (parser, if_p));
19682 stmt = c_finish_oacc_host_data (loc, clauses, block);
19683 return stmt;
19684}
19685
19686
19687/* OpenACC 2.0:
19688
19689 # pragma acc loop oacc-loop-clause[optseq] new-line
19690 structured-block
19691
19692 LOC is the location of the #pragma token.
19693*/
19694
19695#define OACC_LOOP_CLAUSE_MASK \
19696 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
19697 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
19698 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
19699 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
19700 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
19701 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
19702 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
19703 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
19704 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
19705 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
19706static tree
19707c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
19708 omp_clause_mask mask, tree *cclauses, bool *if_p)
19709{
19710 bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
19711
19712 strcat (dest: p_name, src: " loop");
19713 mask |= OACC_LOOP_CLAUSE_MASK;
19714
19715 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
19716 finish_p: cclauses == NULL);
19717 if (cclauses)
19718 {
19719 clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
19720 if (*cclauses)
19721 *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC);
19722 if (clauses)
19723 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
19724 }
19725
19726 tree block = c_begin_compound_stmt (true);
19727 tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
19728 if_p);
19729 block = c_end_compound_stmt (loc, block, true);
19730 add_stmt (block);
19731
19732 return stmt;
19733}
19734
19735/* OpenACC 2.0:
19736 # pragma acc kernels oacc-kernels-clause[optseq] new-line
19737 structured-block
19738
19739 or
19740
19741 # pragma acc parallel oacc-parallel-clause[optseq] new-line
19742 structured-block
19743
19744 OpenACC 2.6:
19745
19746 # pragma acc serial oacc-serial-clause[optseq] new-line
19747 structured-block
19748
19749 LOC is the location of the #pragma token.
19750*/
19751
19752#define OACC_KERNELS_CLAUSE_MASK \
19753 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
19754 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19755 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19756 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19757 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19758 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19759 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
19760 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19761 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19762 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
19763 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
19764 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
19765 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
19766 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
19767 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
19768 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
19769
19770#define OACC_PARALLEL_CLAUSE_MASK \
19771 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
19772 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19773 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19774 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19775 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19776 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19777 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
19778 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19779 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19780 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
19781 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
19782 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
19783 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
19784 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
19785 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
19786 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
19787 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
19788 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
19789 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
19790
19791#define OACC_SERIAL_CLAUSE_MASK \
19792 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
19793 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
19794 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
19795 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
19796 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
19797 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
19798 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
19799 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
19800 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
19801 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
19802 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
19803 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
19804 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
19805 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
19806 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
19807 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
19808
19809static tree
19810c_parser_oacc_compute (location_t loc, c_parser *parser,
19811 enum pragma_kind p_kind, char *p_name, bool *if_p)
19812{
19813 omp_clause_mask mask;
19814 enum tree_code code;
19815 switch (p_kind)
19816 {
19817 case PRAGMA_OACC_KERNELS:
19818 strcat (dest: p_name, src: " kernels");
19819 mask = OACC_KERNELS_CLAUSE_MASK;
19820 code = OACC_KERNELS;
19821 break;
19822 case PRAGMA_OACC_PARALLEL:
19823 strcat (dest: p_name, src: " parallel");
19824 mask = OACC_PARALLEL_CLAUSE_MASK;
19825 code = OACC_PARALLEL;
19826 break;
19827 case PRAGMA_OACC_SERIAL:
19828 strcat (dest: p_name, src: " serial");
19829 mask = OACC_SERIAL_CLAUSE_MASK;
19830 code = OACC_SERIAL;
19831 break;
19832 default:
19833 gcc_unreachable ();
19834 }
19835
19836 if (c_parser_next_token_is (parser, type: CPP_NAME))
19837 {
19838 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19839 if (strcmp (s1: p, s2: "loop") == 0)
19840 {
19841 c_parser_consume_token (parser);
19842 tree block = c_begin_omp_parallel ();
19843 tree clauses;
19844 c_parser_oacc_loop (loc, parser, p_name, mask, cclauses: &clauses, if_p);
19845 return c_finish_omp_construct (loc, code, block, clauses);
19846 }
19847 }
19848
19849 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name);
19850
19851 tree block = c_begin_omp_parallel ();
19852 add_stmt (c_parser_omp_structured_block (parser, if_p));
19853
19854 return c_finish_omp_construct (loc, code, block, clauses);
19855}
19856
19857/* OpenACC 2.0:
19858 # pragma acc routine oacc-routine-clause[optseq] new-line
19859 function-definition
19860
19861 # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
19862*/
19863
19864#define OACC_ROUTINE_CLAUSE_MASK \
19865 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
19866 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
19867 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
19868 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
19869 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
19870
19871/* Parse an OpenACC routine directive. For named directives, we apply
19872 immediately to the named function. For unnamed ones we then parse
19873 a declaration or definition, which must be for a function. */
19874
19875static void
19876c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
19877{
19878 gcc_checking_assert (context == pragma_external);
19879
19880 oacc_routine_data data;
19881 data.error_seen = false;
19882 data.fndecl_seen = false;
19883 data.loc = c_parser_peek_token (parser)->location;
19884
19885 c_parser_consume_pragma (parser);
19886
19887 /* Look for optional '( name )'. */
19888 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
19889 {
19890 c_parser_consume_token (parser); /* '(' */
19891
19892 tree decl = NULL_TREE;
19893 c_token *name_token = c_parser_peek_token (parser);
19894 location_t name_loc = name_token->location;
19895 if (name_token->type == CPP_NAME
19896 && (name_token->id_kind == C_ID_ID
19897 || name_token->id_kind == C_ID_TYPENAME))
19898 {
19899 decl = lookup_name (name_token->value);
19900 if (!decl)
19901 error_at (name_loc,
19902 "%qE has not been declared", name_token->value);
19903 c_parser_consume_token (parser);
19904 }
19905 else
19906 c_parser_error (parser, gmsgid: "expected function name");
19907
19908 if (!decl
19909 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
19910 {
19911 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
19912 return;
19913 }
19914
19915 data.clauses
19916 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
19917 where: "#pragma acc routine");
19918 /* The clauses are in reverse order; fix that to make later diagnostic
19919 emission easier. */
19920 data.clauses = nreverse (data.clauses);
19921
19922 if (TREE_CODE (decl) != FUNCTION_DECL)
19923 {
19924 error_at (name_loc, "%qD does not refer to a function", decl);
19925 return;
19926 }
19927
19928 c_finish_oacc_routine (&data, decl, false);
19929 }
19930 else /* No optional '( name )'. */
19931 {
19932 data.clauses
19933 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
19934 where: "#pragma acc routine");
19935 /* The clauses are in reverse order; fix that to make later diagnostic
19936 emission easier. */
19937 data.clauses = nreverse (data.clauses);
19938
19939 /* Emit a helpful diagnostic if there's another pragma following this
19940 one. Also don't allow a static assertion declaration, as in the
19941 following we'll just parse a *single* "declaration or function
19942 definition", and the static assertion counts an one. */
19943 if (c_parser_next_token_is (parser, type: CPP_PRAGMA)
19944 || c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
19945 {
19946 error_at (data.loc,
19947 "%<#pragma acc routine%> not immediately followed by"
19948 " function declaration or definition");
19949 /* ..., and then just keep going. */
19950 return;
19951 }
19952
19953 /* We only have to consider the pragma_external case here. */
19954 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
19955 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
19956 {
19957 int ext = disable_extension_diagnostics ();
19958 do
19959 c_parser_consume_token (parser);
19960 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
19961 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
19962 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
19963 NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
19964 restore_extension_diagnostics (flags: ext);
19965 }
19966 else
19967 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
19968 NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
19969 }
19970}
19971
19972/* Finalize an OpenACC routine pragma, applying it to FNDECL.
19973 IS_DEFN is true if we're applying it to the definition. */
19974
19975static void
19976c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
19977 bool is_defn)
19978{
19979 /* Keep going if we're in error reporting mode. */
19980 if (data->error_seen
19981 || fndecl == error_mark_node)
19982 return;
19983
19984 if (data->fndecl_seen)
19985 {
19986 error_at (data->loc,
19987 "%<#pragma acc routine%> not immediately followed by"
19988 " a single function declaration or definition");
19989 data->error_seen = true;
19990 return;
19991 }
19992 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
19993 {
19994 error_at (data->loc,
19995 "%<#pragma acc routine%> not immediately followed by"
19996 " function declaration or definition");
19997 data->error_seen = true;
19998 return;
19999 }
20000
20001 int compatible
20002 = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
20003 "#pragma acc routine");
20004 if (compatible < 0)
20005 {
20006 data->error_seen = true;
20007 return;
20008 }
20009 if (compatible > 0)
20010 {
20011 }
20012 else
20013 {
20014 if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
20015 {
20016 error_at (data->loc,
20017 TREE_USED (fndecl)
20018 ? G_("%<#pragma acc routine%> must be applied before use")
20019 : G_("%<#pragma acc routine%> must be applied before"
20020 " definition"));
20021 data->error_seen = true;
20022 return;
20023 }
20024
20025 /* Set the routine's level of parallelism. */
20026 tree dims = oacc_build_routine_dims (clauses: data->clauses);
20027 oacc_replace_fn_attrib (fn: fndecl, dims);
20028
20029 /* Add an "omp declare target" attribute. */
20030 DECL_ATTRIBUTES (fndecl)
20031 = tree_cons (get_identifier ("omp declare target"),
20032 data->clauses, DECL_ATTRIBUTES (fndecl));
20033 }
20034
20035 /* Remember that we've used this "#pragma acc routine". */
20036 data->fndecl_seen = true;
20037}
20038
20039/* OpenACC 2.0:
20040 # pragma acc update oacc-update-clause[optseq] new-line
20041*/
20042
20043#define OACC_UPDATE_CLAUSE_MASK \
20044 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
20045 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
20046 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
20047 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
20048 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
20049 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
20050 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
20051
20052static void
20053c_parser_oacc_update (c_parser *parser)
20054{
20055 location_t loc = c_parser_peek_token (parser)->location;
20056
20057 c_parser_consume_pragma (parser);
20058
20059 tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
20060 where: "#pragma acc update");
20061 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
20062 {
20063 error_at (loc,
20064 "%<#pragma acc update%> must contain at least one "
20065 "%<device%> or %<host%> or %<self%> clause");
20066 return;
20067 }
20068
20069 if (parser->error)
20070 return;
20071
20072 tree stmt = make_node (OACC_UPDATE);
20073 TREE_TYPE (stmt) = void_type_node;
20074 OACC_UPDATE_CLAUSES (stmt) = clauses;
20075 SET_EXPR_LOCATION (stmt, loc);
20076 add_stmt (stmt);
20077}
20078
20079/* OpenACC 2.0:
20080 # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
20081
20082 LOC is the location of the #pragma token.
20083*/
20084
20085#define OACC_WAIT_CLAUSE_MASK \
20086 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
20087
20088static tree
20089c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
20090{
20091 tree clauses, list = NULL_TREE, stmt = NULL_TREE;
20092
20093 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
20094 list = c_parser_oacc_wait_list (parser, clause_loc: loc, list);
20095
20096 strcpy (dest: p_name, src: " wait");
20097 clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, where: p_name);
20098 stmt = c_finish_oacc_wait (loc, list, clauses);
20099 add_stmt (stmt);
20100
20101 return stmt;
20102}
20103
20104struct c_omp_loc_tree
20105{
20106 location_t loc;
20107 tree var;
20108};
20109
20110/* Check whether the expression used in the allocator clause is declared or
20111 modified between the variable declaration and its allocate directive. */
20112static tree
20113c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
20114{
20115 tree var = ((struct c_omp_loc_tree *) data)->var;
20116 location_t loc = ((struct c_omp_loc_tree *) data)->loc;
20117 if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
20118 {
20119 if (linemap_location_before_p (set: line_table, DECL_SOURCE_LOCATION (var),
20120 DECL_SOURCE_LOCATION (*tp)))
20121 {
20122 error_at (loc, "variable %qD used in the %<allocator%> clause must "
20123 "be declared before %qD", *tp, var);
20124 inform (DECL_SOURCE_LOCATION (*tp), "declared here");
20125 inform (DECL_SOURCE_LOCATION (var),
20126 "to be allocated variable declared here");
20127 return *tp;
20128 }
20129 else
20130 {
20131 gcc_assert (cur_stmt_list
20132 && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
20133
20134 tree_stmt_iterator l = tsi_last (cur_stmt_list);
20135 while (!tsi_end_p (i: l))
20136 {
20137 if (linemap_location_before_p (set: line_table, EXPR_LOCATION (*l),
20138 DECL_SOURCE_LOCATION (var)))
20139 break;
20140 if (TREE_CODE (*l) == MODIFY_EXPR
20141 && TREE_OPERAND (*l, 0) == *tp)
20142 {
20143 error_at (loc,
20144 "variable %qD used in the %<allocator%> clause "
20145 "must not be modified between declaration of %qD "
20146 "and its %<allocate%> directive", *tp, var);
20147 inform (EXPR_LOCATION (*l), "modified here");
20148 inform (DECL_SOURCE_LOCATION (var),
20149 "to be allocated variable declared here");
20150 return *tp;
20151 }
20152 --l;
20153 }
20154 }
20155 }
20156 return NULL_TREE;
20157}
20158
20159/* OpenMP 5.x:
20160 # pragma omp allocate (list) clauses
20161
20162 OpenMP 5.0 clause:
20163 allocator (omp_allocator_handle_t expression)
20164
20165 OpenMP 5.1 additional clause:
20166 align (constant-expression)] */
20167
20168static void
20169c_parser_omp_allocate (c_parser *parser)
20170{
20171 tree alignment = NULL_TREE;
20172 tree allocator = NULL_TREE;
20173 c_parser_consume_pragma (parser);
20174 location_t loc = c_parser_peek_token (parser)->location;
20175 location_t allocator_loc = UNKNOWN_LOCATION;
20176 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE);
20177 do
20178 {
20179 if (c_parser_next_token_is (parser, type: CPP_COMMA)
20180 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
20181 c_parser_consume_token (parser);
20182 if (!c_parser_next_token_is (parser, type: CPP_NAME))
20183 break;
20184 matching_parens parens;
20185 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20186 c_parser_consume_token (parser);
20187 location_t expr_loc = c_parser_peek_token (parser)->location;
20188 if (strcmp (s1: "align", s2: p) != 0 && strcmp (s1: "allocator", s2: p) != 0)
20189 {
20190 error_at (c_parser_peek_token (parser)->location,
20191 "expected %<allocator%> or %<align%>");
20192 break;
20193 }
20194 if (!parens.require_open (parser))
20195 break;
20196
20197 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20198 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20199 expr_loc = c_parser_peek_token (parser)->location;
20200 if (expr.value == error_mark_node)
20201 ;
20202 else if (p[2] == 'i' && alignment)
20203 {
20204 error_at (expr_loc, "too many %qs clauses", "align");
20205 break;
20206 }
20207 else if (p[2] == 'i')
20208 {
20209 alignment = c_fully_fold (expr.value, false, NULL);
20210 if (TREE_CODE (alignment) != INTEGER_CST
20211 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
20212 || tree_int_cst_sgn (alignment) != 1
20213 || !integer_pow2p (alignment))
20214 {
20215 error_at (expr_loc, "%<align%> clause argument needs to be "
20216 "positive constant power of two integer "
20217 "expression");
20218 alignment = NULL_TREE;
20219 }
20220 }
20221 else if (allocator)
20222 {
20223 error_at (expr_loc, "too many %qs clauses", "allocator");
20224 break;
20225 }
20226 else
20227 {
20228 allocator = c_fully_fold (expr.value, false, NULL);
20229 allocator_loc = expr_loc;
20230 tree orig_type
20231 = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
20232 orig_type = TYPE_MAIN_VARIANT (orig_type);
20233 if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
20234 || TREE_CODE (orig_type) != ENUMERAL_TYPE
20235 || TYPE_NAME (orig_type)
20236 != get_identifier ("omp_allocator_handle_t"))
20237 {
20238 error_at (expr_loc,
20239 "%<allocator%> clause allocator expression has type "
20240 "%qT rather than %<omp_allocator_handle_t%>",
20241 TREE_TYPE (allocator));
20242 allocator = NULL_TREE;
20243 }
20244 }
20245 parens.skip_until_found_close (parser);
20246 } while (true);
20247 c_parser_skip_to_pragma_eol (parser);
20248
20249 c_mark_decl_jump_unsafe_in_current_scope ();
20250 for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
20251 {
20252 tree var = OMP_CLAUSE_DECL (c);
20253 if (TREE_CODE (var) == PARM_DECL)
20254 {
20255 error_at (OMP_CLAUSE_LOCATION (nl),
20256 "function parameter %qD may not appear as list item in an "
20257 "%<allocate%> directive", var);
20258 continue;
20259 }
20260 if (!c_check_in_current_scope (var))
20261 {
20262 error_at (OMP_CLAUSE_LOCATION (nl),
20263 "%<allocate%> directive must be in the same scope as %qD",
20264 var);
20265 inform (DECL_SOURCE_LOCATION (var), "declared here");
20266 continue;
20267 }
20268 if (lookup_attribute (attr_name: "omp allocate", DECL_ATTRIBUTES (var)))
20269 {
20270 error_at (OMP_CLAUSE_LOCATION (nl),
20271 "%qD already appeared as list item in an "
20272 "%<allocate%> directive", var);
20273 continue;
20274 }
20275 if (TREE_STATIC (var))
20276 {
20277 if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
20278 error_at (loc, "%<allocator%> clause required for "
20279 "static variable %qD", var);
20280 else if (allocator
20281 && (wi::to_widest (t: allocator) < 1
20282 || wi::to_widest (t: allocator) > 8))
20283 /* 8 = largest predefined memory allocator. */
20284 error_at (allocator_loc,
20285 "%<allocator%> clause requires a predefined allocator as "
20286 "%qD is static", var);
20287 else
20288 sorry_at (OMP_CLAUSE_LOCATION (nl),
20289 "%<#pragma omp allocate%> for static variables like "
20290 "%qD not yet supported", var);
20291 continue;
20292 }
20293 if (allocator)
20294 {
20295 struct c_omp_loc_tree data
20296 = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), .var: var};
20297 walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
20298 }
20299 DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
20300 build_tree_list (allocator, alignment),
20301 DECL_ATTRIBUTES (var));
20302 }
20303}
20304
20305/* OpenMP 2.5:
20306 # pragma omp atomic new-line
20307 expression-stmt
20308
20309 expression-stmt:
20310 x binop= expr | x++ | ++x | x-- | --x
20311 binop:
20312 +, *, -, /, &, ^, |, <<, >>
20313
20314 where x is an lvalue expression with scalar type.
20315
20316 OpenMP 3.1:
20317 # pragma omp atomic new-line
20318 update-stmt
20319
20320 # pragma omp atomic read new-line
20321 read-stmt
20322
20323 # pragma omp atomic write new-line
20324 write-stmt
20325
20326 # pragma omp atomic update new-line
20327 update-stmt
20328
20329 # pragma omp atomic capture new-line
20330 capture-stmt
20331
20332 # pragma omp atomic capture new-line
20333 capture-block
20334
20335 read-stmt:
20336 v = x
20337 write-stmt:
20338 x = expr
20339 update-stmt:
20340 expression-stmt | x = x binop expr
20341 capture-stmt:
20342 v = expression-stmt
20343 capture-block:
20344 { v = x; update-stmt; } | { update-stmt; v = x; }
20345
20346 OpenMP 4.0:
20347 update-stmt:
20348 expression-stmt | x = x binop expr | x = expr binop x
20349 capture-stmt:
20350 v = update-stmt
20351 capture-block:
20352 { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
20353
20354 OpenMP 5.1:
20355 # pragma omp atomic compare new-line
20356 conditional-update-atomic
20357
20358 # pragma omp atomic compare capture new-line
20359 conditional-update-capture-atomic
20360
20361 conditional-update-atomic:
20362 cond-expr-stmt | cond-update-stmt
20363 cond-expr-stmt:
20364 x = expr ordop x ? expr : x;
20365 x = x ordop expr ? expr : x;
20366 x = x == e ? d : x;
20367 cond-update-stmt:
20368 if (expr ordop x) { x = expr; }
20369 if (x ordop expr) { x = expr; }
20370 if (x == e) { x = d; }
20371 ordop:
20372 <, >
20373 conditional-update-capture-atomic:
20374 v = cond-expr-stmt
20375 { v = x; cond-expr-stmt }
20376 { cond-expr-stmt v = x; }
20377 { v = x; cond-update-stmt }
20378 { cond-update-stmt v = x; }
20379 if (x == e) { x = d; } else { v = x; }
20380 { r = x == e; if (r) { x = d; } }
20381 { r = x == e; if (r) { x = d; } else { v = x; } }
20382
20383 where x, r and v are lvalue expressions with scalar type,
20384 expr, e and d are expressions with scalar type and e might be
20385 the same as v.
20386
20387 LOC is the location of the #pragma token. */
20388
20389static void
20390c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
20391{
20392 tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
20393 tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
20394 tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
20395 enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
20396 enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
20397 struct c_expr expr;
20398 location_t eloc;
20399 bool structured_block = false;
20400 bool swapped = false;
20401 bool non_lvalue_p;
20402 tree clauses = NULL_TREE;
20403 bool capture = false;
20404 bool compare = false;
20405 bool weak = false;
20406 enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
20407 bool no_semicolon = false;
20408 bool extra_scope = false;
20409
20410 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
20411 {
20412 if (c_parser_next_token_is (parser, type: CPP_COMMA)
20413 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
20414 c_parser_consume_token (parser);
20415
20416 if (c_parser_next_token_is (parser, type: CPP_NAME))
20417 {
20418 const char *p
20419 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20420 location_t cloc = c_parser_peek_token (parser)->location;
20421 enum tree_code new_code = ERROR_MARK;
20422 enum omp_memory_order new_memory_order
20423 = OMP_MEMORY_ORDER_UNSPECIFIED;
20424 bool new_capture = false;
20425 bool new_compare = false;
20426 bool new_weak = false;
20427 enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
20428
20429 if (!strcmp (s1: p, s2: "read"))
20430 new_code = OMP_ATOMIC_READ;
20431 else if (!strcmp (s1: p, s2: "write"))
20432 new_code = NOP_EXPR;
20433 else if (!strcmp (s1: p, s2: "update"))
20434 new_code = OMP_ATOMIC;
20435 else if (openacc && !strcmp (s1: p, s2: "capture"))
20436 new_code = OMP_ATOMIC_CAPTURE_NEW;
20437 else if (openacc)
20438 {
20439 p = NULL;
20440 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
20441 "or %<capture%> clause");
20442 }
20443 else if (!strcmp (s1: p, s2: "capture"))
20444 new_capture = true;
20445 else if (!strcmp (s1: p, s2: "compare"))
20446 new_compare = true;
20447 else if (!strcmp (s1: p, s2: "weak"))
20448 new_weak = true;
20449 else if (!strcmp (s1: p, s2: "fail"))
20450 {
20451 matching_parens parens;
20452
20453 c_parser_consume_token (parser);
20454 if (!parens.require_open (parser))
20455 continue;
20456
20457 if (c_parser_next_token_is (parser, type: CPP_NAME))
20458 {
20459 const char *q
20460 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20461
20462 if (!strcmp (s1: q, s2: "seq_cst"))
20463 new_fail = OMP_MEMORY_ORDER_SEQ_CST;
20464 else if (!strcmp (s1: q, s2: "acquire"))
20465 new_fail = OMP_MEMORY_ORDER_ACQUIRE;
20466 else if (!strcmp (s1: q, s2: "relaxed"))
20467 new_fail = OMP_MEMORY_ORDER_RELAXED;
20468 }
20469
20470 if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
20471 {
20472 c_parser_consume_token (parser);
20473 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
20474 error_at (cloc, "too many %qs clauses", "fail");
20475 else
20476 fail = new_fail;
20477 }
20478 else
20479 c_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> "
20480 "or %<relaxed%>");
20481 parens.skip_until_found_close (parser);
20482 continue;
20483 }
20484 else if (!strcmp (s1: p, s2: "seq_cst"))
20485 new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
20486 else if (!strcmp (s1: p, s2: "acq_rel"))
20487 new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
20488 else if (!strcmp (s1: p, s2: "release"))
20489 new_memory_order = OMP_MEMORY_ORDER_RELEASE;
20490 else if (!strcmp (s1: p, s2: "acquire"))
20491 new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
20492 else if (!strcmp (s1: p, s2: "relaxed"))
20493 new_memory_order = OMP_MEMORY_ORDER_RELAXED;
20494 else if (!strcmp (s1: p, s2: "hint"))
20495 {
20496 c_parser_consume_token (parser);
20497 clauses = c_parser_omp_clause_hint (parser, list: clauses);
20498 continue;
20499 }
20500 else
20501 {
20502 p = NULL;
20503 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
20504 "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
20505 "%<seq_cst%>, %<acq_rel%>, %<release%>, "
20506 "%<relaxed%> or %<hint%> clause");
20507 }
20508 if (p)
20509 {
20510 if (new_code != ERROR_MARK)
20511 {
20512 /* OpenACC permits 'update capture'. */
20513 if (openacc
20514 && code == OMP_ATOMIC
20515 && new_code == OMP_ATOMIC_CAPTURE_NEW)
20516 code = new_code;
20517 else if (code != ERROR_MARK)
20518 error_at (cloc, "too many atomic clauses");
20519 else
20520 code = new_code;
20521 }
20522 else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
20523 {
20524 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
20525 error_at (cloc, "too many memory order clauses");
20526 else
20527 memory_order = new_memory_order;
20528 }
20529 else if (new_capture)
20530 {
20531 if (capture)
20532 error_at (cloc, "too many %qs clauses", "capture");
20533 else
20534 capture = true;
20535 }
20536 else if (new_compare)
20537 {
20538 if (compare)
20539 error_at (cloc, "too many %qs clauses", "compare");
20540 else
20541 compare = true;
20542 }
20543 else if (new_weak)
20544 {
20545 if (weak)
20546 error_at (cloc, "too many %qs clauses", "weak");
20547 else
20548 weak = true;
20549 }
20550 c_parser_consume_token (parser);
20551 continue;
20552 }
20553 }
20554 break;
20555 }
20556 c_parser_skip_to_pragma_eol (parser);
20557
20558 if (code == ERROR_MARK)
20559 code = OMP_ATOMIC;
20560 if (capture)
20561 {
20562 if (code != OMP_ATOMIC)
20563 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
20564 "clauses", "capture");
20565 else
20566 code = OMP_ATOMIC_CAPTURE_NEW;
20567 }
20568 if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
20569 {
20570 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
20571 "clauses", "compare");
20572 compare = false;
20573 }
20574 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
20575 {
20576 error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
20577 fail = OMP_MEMORY_ORDER_UNSPECIFIED;
20578 }
20579 if (weak && !compare)
20580 {
20581 error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
20582 weak = false;
20583 }
20584 if (openacc)
20585 memory_order = OMP_MEMORY_ORDER_RELAXED;
20586 else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
20587 {
20588 omp_requires_mask
20589 = (enum omp_requires) (omp_requires_mask
20590 | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
20591 switch ((enum omp_memory_order)
20592 (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
20593 {
20594 case OMP_MEMORY_ORDER_UNSPECIFIED:
20595 case OMP_MEMORY_ORDER_RELAXED:
20596 memory_order = OMP_MEMORY_ORDER_RELAXED;
20597 break;
20598 case OMP_MEMORY_ORDER_SEQ_CST:
20599 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
20600 break;
20601 case OMP_MEMORY_ORDER_ACQ_REL:
20602 switch (code)
20603 {
20604 case OMP_ATOMIC_READ:
20605 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
20606 break;
20607 case NOP_EXPR: /* atomic write */
20608 memory_order = OMP_MEMORY_ORDER_RELEASE;
20609 break;
20610 default:
20611 memory_order = OMP_MEMORY_ORDER_ACQ_REL;
20612 break;
20613 }
20614 break;
20615 default:
20616 gcc_unreachable ();
20617 }
20618 }
20619 else
20620 switch (code)
20621 {
20622 case OMP_ATOMIC_READ:
20623 if (memory_order == OMP_MEMORY_ORDER_RELEASE)
20624 {
20625 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
20626 "%<release%> clause");
20627 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
20628 }
20629 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
20630 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
20631 break;
20632 case NOP_EXPR: /* atomic write */
20633 if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
20634 {
20635 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
20636 "%<acquire%> clause");
20637 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
20638 }
20639 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
20640 memory_order = OMP_MEMORY_ORDER_RELEASE;
20641 break;
20642 default:
20643 break;
20644 }
20645 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
20646 memory_order
20647 = (enum omp_memory_order) (memory_order
20648 | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
20649
20650 switch (code)
20651 {
20652 case OMP_ATOMIC_READ:
20653 case NOP_EXPR: /* atomic write */
20654 v = c_parser_cast_expression (parser, NULL).value;
20655 non_lvalue_p = !lvalue_p (v);
20656 v = c_fully_fold (v, false, NULL, true);
20657 if (v == error_mark_node)
20658 goto saw_error;
20659 if (non_lvalue_p)
20660 v = non_lvalue (v);
20661 loc = c_parser_peek_token (parser)->location;
20662 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
20663 goto saw_error;
20664 if (code == NOP_EXPR)
20665 {
20666 lhs = c_parser_expression (parser).value;
20667 lhs = c_fully_fold (lhs, false, NULL);
20668 if (lhs == error_mark_node)
20669 goto saw_error;
20670 }
20671 else
20672 {
20673 lhs = c_parser_cast_expression (parser, NULL).value;
20674 non_lvalue_p = !lvalue_p (lhs);
20675 lhs = c_fully_fold (lhs, false, NULL, true);
20676 if (lhs == error_mark_node)
20677 goto saw_error;
20678 if (non_lvalue_p)
20679 lhs = non_lvalue (lhs);
20680 }
20681 if (code == NOP_EXPR)
20682 {
20683 /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
20684 opcode. */
20685 code = OMP_ATOMIC;
20686 rhs = lhs;
20687 lhs = v;
20688 v = NULL_TREE;
20689 }
20690 goto done;
20691 case OMP_ATOMIC_CAPTURE_NEW:
20692 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
20693 {
20694 c_parser_consume_token (parser);
20695 structured_block = true;
20696 }
20697 else if (compare
20698 && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
20699 break;
20700 else
20701 {
20702 v = c_parser_cast_expression (parser, NULL).value;
20703 non_lvalue_p = !lvalue_p (v);
20704 v = c_fully_fold (v, false, NULL, true);
20705 if (v == error_mark_node)
20706 goto saw_error;
20707 if (non_lvalue_p)
20708 v = non_lvalue (v);
20709 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
20710 goto saw_error;
20711 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
20712 {
20713 eloc = c_parser_peek_token (parser)->location;
20714 error_at (eloc, "expected expression");
20715 goto saw_error;
20716 }
20717 }
20718 break;
20719 default:
20720 break;
20721 }
20722
20723 /* For structured_block case we don't know yet whether
20724 old or new x should be captured. */
20725restart:
20726 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
20727 {
20728 c_parser_consume_token (parser);
20729
20730 matching_parens parens;
20731 if (!parens.require_open (parser))
20732 goto saw_error;
20733 eloc = c_parser_peek_token (parser)->location;
20734 c_expr cmp_expr;
20735 if (r)
20736 {
20737 cmp_expr = c_parser_cast_expression (parser, NULL);
20738 cmp_expr = default_function_array_conversion (eloc, cmp_expr);
20739 }
20740 else
20741 cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
20742 parens.skip_until_found_close (parser);
20743 if (cmp_expr.value == error_mark_node)
20744 goto saw_error;
20745 if (r)
20746 {
20747 if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
20748 goto bad_if;
20749 cmp_expr.value = rhs1;
20750 rhs1 = NULL_TREE;
20751 gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
20752 }
20753 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
20754 ;
20755 else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
20756 {
20757 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
20758 "expected %<==%> comparison in %<if%> condition");
20759 goto saw_error;
20760 }
20761 else if (TREE_CODE (cmp_expr.value) != GT_EXPR
20762 && TREE_CODE (cmp_expr.value) != LT_EXPR)
20763 {
20764 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
20765 "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
20766 "condition");
20767 goto saw_error;
20768 }
20769 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
20770 goto saw_error;
20771
20772 extra_scope = true;
20773 eloc = c_parser_peek_token (parser)->location;
20774 expr = c_parser_cast_expression (parser, NULL);
20775 lhs = expr.value;
20776 expr = default_function_array_conversion (eloc, expr);
20777 unfolded_lhs = expr.value;
20778 lhs = c_fully_fold (lhs, false, NULL, true);
20779 orig_lhs = lhs;
20780 if (lhs == error_mark_node)
20781 goto saw_error;
20782 if (!lvalue_p (unfolded_lhs))
20783 lhs = non_lvalue (lhs);
20784 if (!c_parser_next_token_is (parser, type: CPP_EQ))
20785 {
20786 c_parser_error (parser, gmsgid: "expected %<=%>");
20787 goto saw_error;
20788 }
20789 c_parser_consume_token (parser);
20790 eloc = c_parser_peek_token (parser)->location;
20791 expr = c_parser_expr_no_commas (parser, NULL);
20792 rhs1 = expr.value;
20793
20794 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
20795 goto saw_error;
20796
20797 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
20798 goto saw_error;
20799
20800 extra_scope = false;
20801 no_semicolon = true;
20802
20803 if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
20804 {
20805 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
20806 {
20807 opcode = COND_EXPR;
20808 rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
20809 false, NULL, true);
20810 rhs1 = c_fully_fold (rhs1, false, NULL, true);
20811 }
20812 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
20813 {
20814 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
20815 ? MIN_EXPR : MAX_EXPR);
20816 rhs = c_fully_fold (rhs1, false, NULL, true);
20817 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
20818 false, NULL, true);
20819 }
20820 else
20821 goto bad_if;
20822 }
20823 else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
20824 goto bad_if;
20825 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
20826 && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
20827 {
20828 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
20829 ? MAX_EXPR : MIN_EXPR);
20830 rhs = c_fully_fold (rhs1, false, NULL, true);
20831 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
20832 false, NULL, true);
20833 }
20834 else
20835 {
20836 bad_if:
20837 c_parser_error (parser,
20838 gmsgid: "invalid form of %<#pragma omp atomic compare%>");
20839 goto saw_error;
20840 }
20841
20842 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
20843 {
20844 if (code != OMP_ATOMIC_CAPTURE_NEW
20845 || (structured_block && r == NULL_TREE)
20846 || TREE_CODE (cmp_expr.value) != EQ_EXPR)
20847 {
20848 eloc = c_parser_peek_token (parser)->location;
20849 error_at (eloc, "unexpected %<else%>");
20850 goto saw_error;
20851 }
20852
20853 c_parser_consume_token (parser);
20854
20855 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
20856 goto saw_error;
20857
20858 extra_scope = true;
20859 v = c_parser_cast_expression (parser, NULL).value;
20860 non_lvalue_p = !lvalue_p (v);
20861 v = c_fully_fold (v, false, NULL, true);
20862 if (v == error_mark_node)
20863 goto saw_error;
20864 if (non_lvalue_p)
20865 v = non_lvalue (v);
20866 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
20867 goto saw_error;
20868
20869 expr = c_parser_expr_no_commas (parser, NULL);
20870
20871 if (!c_tree_equal (expr.value, unfolded_lhs))
20872 goto bad_if;
20873
20874 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
20875 goto saw_error;
20876
20877 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
20878 goto saw_error;
20879
20880 extra_scope = false;
20881 code = OMP_ATOMIC_CAPTURE_OLD;
20882 if (r == NULL_TREE)
20883 /* Signal to c_finish_omp_atomic that in
20884 if (x == e) { x = d; } else { v = x; }
20885 case the store to v should be conditional. */
20886 r = void_list_node;
20887 }
20888 else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
20889 {
20890 c_parser_require_keyword (parser, keyword: RID_ELSE, msgid: "expected %<else%>");
20891 goto saw_error;
20892 }
20893 else if (code == OMP_ATOMIC_CAPTURE_NEW
20894 && r != NULL_TREE
20895 && v == NULL_TREE)
20896 code = OMP_ATOMIC;
20897 goto stmt_done;
20898 }
20899 eloc = c_parser_peek_token (parser)->location;
20900 expr = c_parser_cast_expression (parser, NULL);
20901 lhs = expr.value;
20902 expr = default_function_array_conversion (eloc, expr);
20903 unfolded_lhs = expr.value;
20904 lhs = c_fully_fold (lhs, false, NULL, true);
20905 orig_lhs = lhs;
20906 switch (TREE_CODE (lhs))
20907 {
20908 invalid_compare:
20909 error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
20910 /* FALLTHRU */
20911 case ERROR_MARK:
20912 saw_error:
20913 c_parser_skip_to_end_of_block_or_statement (parser);
20914 if (extra_scope && c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
20915 c_parser_consume_token (parser);
20916 if (structured_block)
20917 {
20918 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
20919 c_parser_consume_token (parser);
20920 else if (code == OMP_ATOMIC_CAPTURE_NEW)
20921 {
20922 c_parser_skip_to_end_of_block_or_statement (parser);
20923 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
20924 c_parser_consume_token (parser);
20925 }
20926 }
20927 return;
20928
20929 case POSTINCREMENT_EXPR:
20930 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
20931 code = OMP_ATOMIC_CAPTURE_OLD;
20932 /* FALLTHROUGH */
20933 case PREINCREMENT_EXPR:
20934 lhs = TREE_OPERAND (lhs, 0);
20935 unfolded_lhs = NULL_TREE;
20936 opcode = PLUS_EXPR;
20937 rhs = integer_one_node;
20938 if (compare)
20939 goto invalid_compare;
20940 break;
20941
20942 case POSTDECREMENT_EXPR:
20943 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
20944 code = OMP_ATOMIC_CAPTURE_OLD;
20945 /* FALLTHROUGH */
20946 case PREDECREMENT_EXPR:
20947 lhs = TREE_OPERAND (lhs, 0);
20948 unfolded_lhs = NULL_TREE;
20949 opcode = MINUS_EXPR;
20950 rhs = integer_one_node;
20951 if (compare)
20952 goto invalid_compare;
20953 break;
20954
20955 case COMPOUND_EXPR:
20956 if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
20957 && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
20958 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
20959 && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
20960 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
20961 (TREE_OPERAND (lhs, 1), 0), 0))))
20962 /* Undo effects of boolean_increment for post {in,de}crement. */
20963 lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
20964 /* FALLTHRU */
20965 case MODIFY_EXPR:
20966 if (TREE_CODE (lhs) == MODIFY_EXPR
20967 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
20968 {
20969 /* Undo effects of boolean_increment. */
20970 if (integer_onep (TREE_OPERAND (lhs, 1)))
20971 {
20972 /* This is pre or post increment. */
20973 rhs = TREE_OPERAND (lhs, 1);
20974 lhs = TREE_OPERAND (lhs, 0);
20975 unfolded_lhs = NULL_TREE;
20976 opcode = NOP_EXPR;
20977 if (code == OMP_ATOMIC_CAPTURE_NEW
20978 && !structured_block
20979 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
20980 code = OMP_ATOMIC_CAPTURE_OLD;
20981 if (compare)
20982 goto invalid_compare;
20983 break;
20984 }
20985 if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
20986 && TREE_OPERAND (lhs, 0)
20987 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
20988 {
20989 /* This is pre or post decrement. */
20990 rhs = TREE_OPERAND (lhs, 1);
20991 lhs = TREE_OPERAND (lhs, 0);
20992 unfolded_lhs = NULL_TREE;
20993 opcode = NOP_EXPR;
20994 if (code == OMP_ATOMIC_CAPTURE_NEW
20995 && !structured_block
20996 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
20997 code = OMP_ATOMIC_CAPTURE_OLD;
20998 if (compare)
20999 goto invalid_compare;
21000 break;
21001 }
21002 }
21003 /* FALLTHRU */
21004 default:
21005 if (!lvalue_p (unfolded_lhs))
21006 lhs = non_lvalue (lhs);
21007 if (compare && !c_parser_next_token_is (parser, type: CPP_EQ))
21008 {
21009 c_parser_error (parser, gmsgid: "expected %<=%>");
21010 goto saw_error;
21011 }
21012 switch (c_parser_peek_token (parser)->type)
21013 {
21014 case CPP_MULT_EQ:
21015 opcode = MULT_EXPR;
21016 break;
21017 case CPP_DIV_EQ:
21018 opcode = TRUNC_DIV_EXPR;
21019 break;
21020 case CPP_PLUS_EQ:
21021 opcode = PLUS_EXPR;
21022 break;
21023 case CPP_MINUS_EQ:
21024 opcode = MINUS_EXPR;
21025 break;
21026 case CPP_LSHIFT_EQ:
21027 opcode = LSHIFT_EXPR;
21028 break;
21029 case CPP_RSHIFT_EQ:
21030 opcode = RSHIFT_EXPR;
21031 break;
21032 case CPP_AND_EQ:
21033 opcode = BIT_AND_EXPR;
21034 break;
21035 case CPP_OR_EQ:
21036 opcode = BIT_IOR_EXPR;
21037 break;
21038 case CPP_XOR_EQ:
21039 opcode = BIT_XOR_EXPR;
21040 break;
21041 case CPP_EQ:
21042 c_parser_consume_token (parser);
21043 eloc = c_parser_peek_token (parser)->location;
21044 expr = c_parser_expr_no_commas (parser, NULL, omp_atomic_lhs: unfolded_lhs);
21045 rhs1 = expr.value;
21046 switch (TREE_CODE (rhs1))
21047 {
21048 case MULT_EXPR:
21049 case TRUNC_DIV_EXPR:
21050 case RDIV_EXPR:
21051 case PLUS_EXPR:
21052 case MINUS_EXPR:
21053 case LSHIFT_EXPR:
21054 case RSHIFT_EXPR:
21055 case BIT_AND_EXPR:
21056 case BIT_IOR_EXPR:
21057 case BIT_XOR_EXPR:
21058 if (compare)
21059 break;
21060 if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
21061 {
21062 opcode = TREE_CODE (rhs1);
21063 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21064 true);
21065 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
21066 true);
21067 goto stmt_done;
21068 }
21069 if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
21070 {
21071 opcode = TREE_CODE (rhs1);
21072 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
21073 true);
21074 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21075 true);
21076 swapped = !commutative_tree_code (opcode);
21077 goto stmt_done;
21078 }
21079 break;
21080 case COND_EXPR:
21081 if (!compare)
21082 break;
21083 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
21084 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
21085 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
21086 break;
21087 if (!TREE_OPERAND (rhs1, 1))
21088 break;
21089 if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
21090 break;
21091 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
21092 unfolded_lhs))
21093 {
21094 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
21095 {
21096 opcode = COND_EXPR;
21097 rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21098 0), 1),
21099 false, NULL, true);
21100 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
21101 NULL, true);
21102 goto stmt_done;
21103 }
21104 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
21105 TREE_OPERAND (rhs1, 1)))
21106 {
21107 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
21108 ? MIN_EXPR : MAX_EXPR);
21109 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21110 true);
21111 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21112 0), 0),
21113 false, NULL, true);
21114 goto stmt_done;
21115 }
21116 }
21117 else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
21118 break;
21119 else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
21120 unfolded_lhs))
21121 {
21122 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
21123 TREE_OPERAND (rhs1, 1)))
21124 {
21125 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
21126 ? MAX_EXPR : MIN_EXPR);
21127 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
21128 true);
21129 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
21130 0), 1),
21131 false, NULL, true);
21132 goto stmt_done;
21133 }
21134 }
21135 break;
21136 case EQ_EXPR:
21137 if (!compare
21138 || code != OMP_ATOMIC_CAPTURE_NEW
21139 || !structured_block
21140 || v
21141 || r)
21142 break;
21143 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
21144 && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
21145 {
21146 r = lhs;
21147 lhs = NULL_TREE;
21148 c_parser_consume_token (parser);
21149 goto restart;
21150 }
21151 break;
21152 case ERROR_MARK:
21153 goto saw_error;
21154 default:
21155 break;
21156 }
21157 if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
21158 {
21159 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
21160 {
21161 code = OMP_ATOMIC_CAPTURE_OLD;
21162 v = lhs;
21163 lhs = NULL_TREE;
21164 expr = default_function_array_read_conversion (eloc, expr);
21165 unfolded_lhs1 = expr.value;
21166 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
21167 rhs1 = NULL_TREE;
21168 c_parser_consume_token (parser);
21169 goto restart;
21170 }
21171 if (structured_block && !compare)
21172 {
21173 opcode = NOP_EXPR;
21174 expr = default_function_array_read_conversion (eloc, expr);
21175 rhs = c_fully_fold (expr.value, false, NULL, true);
21176 rhs1 = NULL_TREE;
21177 goto stmt_done;
21178 }
21179 }
21180 c_parser_error (parser, gmsgid: "invalid form of %<#pragma omp atomic%>");
21181 goto saw_error;
21182 default:
21183 c_parser_error (parser,
21184 gmsgid: "invalid operator for %<#pragma omp atomic%>");
21185 goto saw_error;
21186 }
21187
21188 /* Arrange to pass the location of the assignment operator to
21189 c_finish_omp_atomic. */
21190 loc = c_parser_peek_token (parser)->location;
21191 c_parser_consume_token (parser);
21192 eloc = c_parser_peek_token (parser)->location;
21193 expr = c_parser_expression (parser);
21194 expr = default_function_array_read_conversion (eloc, expr);
21195 rhs = expr.value;
21196 rhs = c_fully_fold (rhs, false, NULL, true);
21197 break;
21198 }
21199stmt_done:
21200 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
21201 {
21202 if (!no_semicolon
21203 && !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
21204 goto saw_error;
21205 no_semicolon = false;
21206 v = c_parser_cast_expression (parser, NULL).value;
21207 non_lvalue_p = !lvalue_p (v);
21208 v = c_fully_fold (v, false, NULL, true);
21209 if (v == error_mark_node)
21210 goto saw_error;
21211 if (non_lvalue_p)
21212 v = non_lvalue (v);
21213 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
21214 goto saw_error;
21215 eloc = c_parser_peek_token (parser)->location;
21216 expr = c_parser_cast_expression (parser, NULL);
21217 lhs1 = expr.value;
21218 expr = default_function_array_read_conversion (eloc, expr);
21219 unfolded_lhs1 = expr.value;
21220 lhs1 = c_fully_fold (lhs1, false, NULL, true);
21221 if (lhs1 == error_mark_node)
21222 goto saw_error;
21223 if (!lvalue_p (unfolded_lhs1))
21224 lhs1 = non_lvalue (lhs1);
21225 }
21226 if (structured_block)
21227 {
21228 if (!no_semicolon)
21229 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21230 c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>");
21231 }
21232done:
21233 if (weak && opcode != COND_EXPR)
21234 {
21235 error_at (loc, "%<weak%> clause requires atomic equality comparison");
21236 weak = false;
21237 }
21238 if (unfolded_lhs && unfolded_lhs1
21239 && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
21240 {
21241 error ("%<#pragma omp atomic capture%> uses two different "
21242 "expressions for memory");
21243 stmt = error_mark_node;
21244 }
21245 else
21246 stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
21247 swapped, memory_order, weak);
21248 if (stmt != error_mark_node)
21249 add_stmt (stmt);
21250
21251 if (!structured_block && !no_semicolon)
21252 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21253}
21254
21255
21256/* OpenMP 2.5:
21257 # pragma omp barrier new-line
21258*/
21259
21260static void
21261c_parser_omp_barrier (c_parser *parser)
21262{
21263 location_t loc = c_parser_peek_token (parser)->location;
21264 c_parser_consume_pragma (parser);
21265 c_parser_skip_to_pragma_eol (parser);
21266
21267 c_finish_omp_barrier (loc);
21268}
21269
21270/* OpenMP 2.5:
21271 # pragma omp critical [(name)] new-line
21272 structured-block
21273
21274 OpenMP 4.5:
21275 # pragma omp critical [(name) [hint(expression)]] new-line
21276
21277 LOC is the location of the #pragma itself. */
21278
21279#define OMP_CRITICAL_CLAUSE_MASK \
21280 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
21281
21282static tree
21283c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
21284{
21285 tree stmt, name = NULL_TREE, clauses = NULL_TREE;
21286
21287 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
21288 {
21289 c_parser_consume_token (parser);
21290 if (c_parser_next_token_is (parser, type: CPP_NAME))
21291 {
21292 name = c_parser_peek_token (parser)->value;
21293 c_parser_consume_token (parser);
21294 c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
21295 }
21296 else
21297 c_parser_error (parser, gmsgid: "expected identifier");
21298
21299 if (c_parser_next_token_is (parser, type: CPP_COMMA)
21300 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
21301 c_parser_consume_token (parser);
21302 }
21303 clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
21304 where: "#pragma omp critical");
21305 stmt = c_parser_omp_structured_block (parser, if_p);
21306 return c_finish_omp_critical (loc, stmt, name, clauses);
21307}
21308
21309/* OpenMP 5.0:
21310 # pragma omp depobj ( depobj ) depobj-clause new-line
21311
21312 depobj-clause:
21313 depend (dependence-type : locator)
21314 destroy
21315 update (dependence-type)
21316
21317 dependence-type:
21318 in
21319 out
21320 inout
21321 mutexinout */
21322
21323static void
21324c_parser_omp_depobj (c_parser *parser)
21325{
21326 location_t loc = c_parser_peek_token (parser)->location;
21327 c_parser_consume_pragma (parser);
21328 matching_parens parens;
21329 if (!parens.require_open (parser))
21330 {
21331 c_parser_skip_to_pragma_eol (parser);
21332 return;
21333 }
21334
21335 tree depobj = c_parser_expr_no_commas (parser, NULL).value;
21336 if (depobj != error_mark_node)
21337 {
21338 if (!lvalue_p (depobj))
21339 {
21340 error_at (EXPR_LOC_OR_LOC (depobj, loc),
21341 "%<depobj%> expression is not lvalue expression");
21342 depobj = error_mark_node;
21343 }
21344 else
21345 {
21346 tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
21347 depobj, false);
21348 if (addr == error_mark_node)
21349 depobj = error_mark_node;
21350 else
21351 depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
21352 addr, RO_UNARY_STAR);
21353 }
21354 }
21355
21356 parens.skip_until_found_close (parser);
21357 tree clause = NULL_TREE;
21358 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
21359 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21360 c_parser_consume_token (parser);
21361 location_t c_loc = c_parser_peek_token (parser)->location;
21362 if (c_parser_next_token_is (parser, type: CPP_NAME))
21363 {
21364 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21365
21366 c_parser_consume_token (parser);
21367 if (!strcmp (s1: "depend", s2: p))
21368 {
21369 clause = c_parser_omp_clause_depend (parser, NULL_TREE);
21370 clause = c_finish_omp_clauses (clause, C_ORT_OMP);
21371 if (!clause)
21372 clause = error_mark_node;
21373 }
21374 else if (!strcmp (s1: "destroy", s2: p))
21375 kind = OMP_CLAUSE_DEPEND_LAST;
21376 else if (!strcmp (s1: "update", s2: p))
21377 {
21378 matching_parens c_parens;
21379 if (c_parens.require_open (parser))
21380 {
21381 location_t c2_loc = c_parser_peek_token (parser)->location;
21382 if (c_parser_next_token_is (parser, type: CPP_NAME))
21383 {
21384 const char *p2
21385 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21386
21387 c_parser_consume_token (parser);
21388 if (!strcmp (s1: "in", s2: p2))
21389 kind = OMP_CLAUSE_DEPEND_IN;
21390 else if (!strcmp (s1: "out", s2: p2))
21391 kind = OMP_CLAUSE_DEPEND_OUT;
21392 else if (!strcmp (s1: "inout", s2: p2))
21393 kind = OMP_CLAUSE_DEPEND_INOUT;
21394 else if (!strcmp (s1: "mutexinoutset", s2: p2))
21395 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
21396 else if (!strcmp (s1: "inoutset", s2: p2))
21397 kind = OMP_CLAUSE_DEPEND_INOUTSET;
21398 }
21399 if (kind == OMP_CLAUSE_DEPEND_INVALID)
21400 {
21401 clause = error_mark_node;
21402 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
21403 "%<mutexinoutset%> or %<inoutset%>");
21404 }
21405 c_parens.skip_until_found_close (parser);
21406 }
21407 else
21408 clause = error_mark_node;
21409 }
21410 }
21411 if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
21412 {
21413 clause = error_mark_node;
21414 error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
21415 }
21416 c_parser_skip_to_pragma_eol (parser);
21417
21418 c_finish_omp_depobj (loc, depobj, kind, clause);
21419}
21420
21421
21422/* OpenMP 2.5:
21423 # pragma omp flush flush-vars[opt] new-line
21424
21425 flush-vars:
21426 ( variable-list )
21427
21428 OpenMP 5.0:
21429 # pragma omp flush memory-order-clause new-line */
21430
21431static void
21432c_parser_omp_flush (c_parser *parser)
21433{
21434 location_t loc = c_parser_peek_token (parser)->location;
21435 c_parser_consume_pragma (parser);
21436 enum memmodel mo = MEMMODEL_LAST;
21437 if (c_parser_next_token_is (parser, type: CPP_COMMA)
21438 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
21439 c_parser_consume_token (parser);
21440 if (c_parser_next_token_is (parser, type: CPP_NAME))
21441 {
21442 const char *p
21443 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21444
21445 if (!strcmp (s1: p, s2: "seq_cst"))
21446 mo = MEMMODEL_SEQ_CST;
21447 else if (!strcmp (s1: p, s2: "acq_rel"))
21448 mo = MEMMODEL_ACQ_REL;
21449 else if (!strcmp (s1: p, s2: "release"))
21450 mo = MEMMODEL_RELEASE;
21451 else if (!strcmp (s1: p, s2: "acquire"))
21452 mo = MEMMODEL_ACQUIRE;
21453 else
21454 error_at (c_parser_peek_token (parser)->location,
21455 "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
21456 "%<acquire%>");
21457 c_parser_consume_token (parser);
21458 }
21459 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
21460 {
21461 if (mo != MEMMODEL_LAST)
21462 error_at (c_parser_peek_token (parser)->location,
21463 "%<flush%> list specified together with memory order "
21464 "clause");
21465 c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
21466 }
21467 else if (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
21468 c_parser_error (parser, gmsgid: "expected %<(%> or end of line");
21469 c_parser_skip_to_pragma_eol (parser);
21470
21471 c_finish_omp_flush (loc, mo);
21472}
21473
21474/* Return true if next tokens contain a standard attribute that contains
21475 omp::directive (DIRECTIVE). */
21476
21477static bool
21478c_parser_omp_section_scan (c_parser *parser, const char *directive,
21479 bool tentative)
21480{
21481 if (!c_parser_nth_token_starts_std_attributes (parser, n: 1))
21482 return false;
21483 unsigned int n = 3;
21484 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
21485 return false;
21486 c_token *token = c_parser_peek_nth_token_raw (parser, n);
21487 if (token->type != CPP_CLOSE_SQUARE)
21488 return false;
21489 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
21490 if (token->type != CPP_CLOSE_SQUARE)
21491 return false;
21492 if (n < 9)
21493 return false;
21494 if (c_parser_peek_nth_token_raw (parser, n: 3)->type == CPP_NAME
21495 && c_parser_peek_nth_token_raw (parser, n: 4)->type == CPP_OPEN_PAREN
21496 && c_parser_peek_nth_token_raw (parser, n: 5)->type == CPP_NAME)
21497 {
21498 tree first = c_parser_peek_nth_token_raw (parser, n: 3)->value;
21499 tree second = c_parser_peek_nth_token_raw (parser, n: 5)->value;
21500 if (strcmp (IDENTIFIER_POINTER (first), s2: "directive")
21501 && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__"))
21502 return false;
21503 if (strcmp (IDENTIFIER_POINTER (second), s2: directive))
21504 return false;
21505 }
21506 if (tentative)
21507 return true;
21508 location_t first_loc = c_parser_peek_token (parser)->location;
21509 location_t last_loc = c_parser_peek_nth_token_raw (parser, n: n + 1)->location;
21510 location_t middle_loc = UNKNOWN_LOCATION;
21511 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
21512 bool seen = false;
21513 int cnt = 0;
21514 for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
21515 if (is_attribute_namespace_p (attr_ns: "omp", attr)
21516 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (attr)))
21517 {
21518 for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
21519 {
21520 tree d = TREE_VALUE (a);
21521 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
21522 c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
21523 cnt++;
21524 if (first->type == CPP_NAME
21525 && strcmp (IDENTIFIER_POINTER (first->value),
21526 s2: directive) == 0)
21527 {
21528 seen = true;
21529 if (middle_loc == UNKNOWN_LOCATION)
21530 middle_loc = first->location;
21531 }
21532 }
21533 }
21534 if (!seen)
21535 return false;
21536 if (cnt != 1 || TREE_CHAIN (std_attrs))
21537 {
21538 error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc),
21539 "%<[[omp::directive(%s)]]%> must be the only specified "
21540 "attribute on a statement", directive);
21541 return false;
21542 }
21543 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
21544 return true;
21545}
21546
21547/* Parse an OpenMP structured block sequence. KIND is the corresponding
21548 separating directive. */
21549
21550static tree
21551c_parser_omp_structured_block_sequence (c_parser *parser,
21552 enum pragma_kind kind)
21553{
21554 tree stmt = push_stmt_list ();
21555 c_parser_statement (parser, NULL);
21556 do
21557 {
21558 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21559 break;
21560 if (c_parser_next_token_is (parser, type: CPP_EOF))
21561 break;
21562
21563 if (kind != PRAGMA_NONE
21564 && c_parser_peek_token (parser)->pragma_kind == kind)
21565 break;
21566
21567 if (kind != PRAGMA_NONE
21568 && c_parser_omp_section_scan (parser,
21569 directive: kind == PRAGMA_OMP_SCAN
21570 ? "scan" : "section", tentative: false))
21571 break;
21572
21573 c_parser_statement (parser, NULL);
21574 }
21575 while (1);
21576 return pop_stmt_list (stmt);
21577}
21578
21579/* OpenMP 5.0:
21580
21581 scan-loop-body:
21582 { structured-block scan-directive structured-block } */
21583
21584static void
21585c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
21586{
21587 tree substmt;
21588 location_t loc;
21589 tree clauses = NULL_TREE;
21590 bool found_scan = false;
21591
21592 loc = c_parser_peek_token (parser)->location;
21593 if (!open_brace_parsed
21594 && !c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
21595 {
21596 /* Avoid skipping until the end of the block. */
21597 parser->error = false;
21598 return;
21599 }
21600
21601 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
21602 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN);
21603 else
21604 {
21605 warning_at (c_parser_peek_token (parser)->location, 0,
21606 "%<#pragma omp scan%> with zero preceding executable "
21607 "statements");
21608 substmt = build_empty_stmt (loc);
21609 }
21610 substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
21611 SET_EXPR_LOCATION (substmt, loc);
21612 add_stmt (substmt);
21613
21614 loc = c_parser_peek_token (parser)->location;
21615 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
21616 {
21617 enum omp_clause_code clause = OMP_CLAUSE_ERROR;
21618 found_scan = true;
21619
21620 c_parser_consume_pragma (parser);
21621
21622 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21623 c_parser_consume_token (parser);
21624
21625 if (c_parser_next_token_is (parser, type: CPP_NAME))
21626 {
21627 const char *p
21628 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21629 if (strcmp (s1: p, s2: "inclusive") == 0)
21630 clause = OMP_CLAUSE_INCLUSIVE;
21631 else if (strcmp (s1: p, s2: "exclusive") == 0)
21632 clause = OMP_CLAUSE_EXCLUSIVE;
21633 }
21634 if (clause != OMP_CLAUSE_ERROR)
21635 {
21636 c_parser_consume_token (parser);
21637 clauses = c_parser_omp_var_list_parens (parser, kind: clause, NULL_TREE);
21638 }
21639 else
21640 c_parser_error (parser, gmsgid: "expected %<inclusive%> or "
21641 "%<exclusive%> clause");
21642 c_parser_skip_to_pragma_eol (parser);
21643 }
21644 else
21645 error ("expected %<#pragma omp scan%>");
21646
21647 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
21648 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
21649 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE);
21650 else
21651 {
21652 if (found_scan)
21653 warning_at (loc, 0, "%<#pragma omp scan%> with zero succeeding "
21654 "executable statements");
21655 substmt = build_empty_stmt (loc);
21656 }
21657 substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
21658 SET_EXPR_LOCATION (substmt, loc);
21659 add_stmt (substmt);
21660
21661 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
21662 msgid: "expected %<}%>");
21663}
21664
21665
21666/* This function parses a single level of a loop nest, invoking itself
21667 recursively if necessary.
21668
21669 loop-nest :: for (...) loop-body
21670 loop-body :: loop-nest
21671 | { [intervening-code] loop-body [intervening-code] }
21672 | final-loop-body
21673 intervening-code :: structured-block-sequence
21674 final-loop-body :: structured-block
21675
21676 For a collapsed loop nest, only a single OMP_FOR is built, pulling out
21677 all the iterator information from the inner loops into the
21678 parser->omp_for_parse_state structure.
21679
21680 The iterator decl, init, cond, and incr are stored in vectors.
21681
21682 Initialization code for iterator variables is collected into
21683 parser->omp_for_parse_state->pre_body and ends up inserted directly
21684 into the OMP_FOR structure. */
21685
21686static tree
21687c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
21688{
21689 tree decl, cond, incr, init;
21690 tree body = NULL_TREE;
21691 matching_parens parens;
21692 bool moreloops;
21693 unsigned char save_in_statement;
21694 tree loop_scope;
21695 location_t loc;
21696 struct omp_for_parse_data *omp_for_parse_state
21697 = parser->omp_for_parse_state;
21698 gcc_assert (omp_for_parse_state);
21699 int depth = omp_for_parse_state->depth;
21700
21701 /* We have already matched the FOR token but not consumed it yet. */
21702 loc = c_parser_peek_token (parser)->location;
21703 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
21704 c_parser_consume_token (parser);
21705
21706 /* Forbid break/continue in the loop initializer, condition, and
21707 increment expressions. */
21708 save_in_statement = in_statement;
21709 in_statement = IN_OMP_BLOCK;
21710
21711 /* We are not in intervening code now. */
21712 omp_for_parse_state->in_intervening_code = false;
21713
21714 if (!parens.require_open (parser))
21715 {
21716 omp_for_parse_state->fail = true;
21717 return NULL_TREE;
21718 }
21719
21720 /* An implicit scope block surrounds each level of FOR loop, for
21721 declarations of iteration variables at this loop depth. */
21722 loop_scope = c_begin_compound_stmt (true);
21723
21724 /* Parse the initialization declaration or expression. */
21725 if (c_parser_next_tokens_start_declaration (parser))
21726 {
21727 /* This is a declaration, which must be added to the pre_body code. */
21728 tree this_pre_body = push_stmt_list ();
21729 c_in_omp_for = true;
21730 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true);
21731 c_in_omp_for = false;
21732 this_pre_body = pop_stmt_list (this_pre_body);
21733 append_to_statement_list_force (this_pre_body,
21734 &(omp_for_parse_state->pre_body));
21735 decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
21736 if (decl == NULL)
21737 goto error_init;
21738 if (DECL_INITIAL (decl) == error_mark_node)
21739 decl = error_mark_node;
21740 init = decl;
21741 }
21742 else if (c_parser_next_token_is (parser, type: CPP_NAME)
21743 && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
21744 {
21745 struct c_expr decl_exp;
21746 struct c_expr init_exp;
21747 location_t init_loc;
21748
21749 decl_exp = c_parser_postfix_expression (parser);
21750 decl = decl_exp.value;
21751
21752 c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>");
21753
21754 init_loc = c_parser_peek_token (parser)->location;
21755 init_exp = c_parser_expr_no_commas (parser, NULL);
21756 init_exp = default_function_array_read_conversion (init_loc,
21757 init_exp);
21758 c_in_omp_for = true;
21759 init = build_modify_expr (init_loc, decl, decl_exp.original_type,
21760 NOP_EXPR, init_loc, init_exp.value,
21761 init_exp.original_type);
21762 c_in_omp_for = false;
21763 init = c_process_expr_stmt (init_loc, init);
21764
21765 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21766 }
21767 else
21768 {
21769 error_init:
21770 c_parser_error (parser,
21771 gmsgid: "expected iteration declaration or initialization");
21772 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
21773 msgid: "expected %<)%>");
21774 omp_for_parse_state->fail = true;
21775 goto parse_next;
21776 }
21777
21778 /* Parse the loop condition. */
21779 cond = NULL_TREE;
21780 if (c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
21781 {
21782 location_t cond_loc = c_parser_peek_token (parser)->location;
21783 c_in_omp_for = true;
21784 struct c_expr cond_expr
21785 = c_parser_binary_expression (parser, NULL, NULL_TREE);
21786 c_in_omp_for = false;
21787
21788 cond = cond_expr.value;
21789 cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
21790 switch (cond_expr.original_code)
21791 {
21792 case GT_EXPR:
21793 case GE_EXPR:
21794 case LT_EXPR:
21795 case LE_EXPR:
21796 break;
21797 case NE_EXPR:
21798 if (omp_for_parse_state->code != OACC_LOOP)
21799 break;
21800 /* FALLTHRU. */
21801 default:
21802 /* Can't be cond = error_mark_node, because we want to preserve
21803 the location until c_finish_omp_for. */
21804 cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
21805 break;
21806 }
21807 protected_set_expr_location (cond, cond_loc);
21808 }
21809 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
21810
21811 /* Parse the increment expression. */
21812 incr = NULL_TREE;
21813 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
21814 {
21815 location_t incr_loc = c_parser_peek_token (parser)->location;
21816
21817 incr = c_process_expr_stmt (incr_loc,
21818 c_parser_expression (parser).value);
21819 }
21820 parens.skip_until_found_close (parser);
21821
21822 if (decl == NULL || decl == error_mark_node || init == error_mark_node)
21823 omp_for_parse_state->fail = true;
21824 else
21825 {
21826 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
21827 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
21828 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
21829 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
21830 }
21831
21832parse_next:
21833 moreloops = depth < omp_for_parse_state->count - 1;
21834 omp_for_parse_state->want_nested_loop = moreloops;
21835 if (moreloops && c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
21836 {
21837 omp_for_parse_state->depth++;
21838 body = c_parser_omp_loop_nest (parser, if_p);
21839 omp_for_parse_state->depth--;
21840 }
21841 else if (moreloops && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
21842 {
21843 /* This is the open brace in the loop-body grammar production. Rather
21844 than trying to special-case braces, just parse it as a compound
21845 statement and handle the nested loop-body case there. Note that
21846 when we see a further open brace inside the compound statement
21847 loop-body, we don't know whether it is the start of intervening
21848 code that is a compound statement, or a level of braces
21849 surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
21850 bit to ensure we have only one nested loop at each level. */
21851 omp_for_parse_state->in_intervening_code = true;
21852 body = c_parser_compound_statement (parser, NULL);
21853 omp_for_parse_state->in_intervening_code = false;
21854 if (omp_for_parse_state->want_nested_loop)
21855 {
21856 /* We have already parsed the whole loop body and not found a
21857 nested loop. */
21858 error_at (omp_for_parse_state->for_loc,
21859 "not enough nested loops");
21860 omp_for_parse_state->fail = true;
21861 }
21862 if_p = NULL;
21863 }
21864 else
21865 {
21866 /* This is the final-loop-body case in the grammar: we have
21867 something that is not a FOR and not an open brace. */
21868 if (moreloops)
21869 {
21870 /* If we were expecting a nested loop, give an error and mark
21871 that parsing has failed, and try to recover by parsing the
21872 body as regular code without further collapsing. */
21873 error_at (omp_for_parse_state->for_loc,
21874 "not enough nested loops");
21875 omp_for_parse_state->fail = true;
21876 }
21877 in_statement = IN_OMP_FOR;
21878 parser->omp_for_parse_state = NULL;
21879 body = push_stmt_list ();
21880 if (omp_for_parse_state->inscan)
21881 c_parser_omp_scan_loop_body (parser, open_brace_parsed: false);
21882 else
21883 add_stmt (c_parser_c99_block_statement (parser, if_p));
21884 body = pop_stmt_list (body);
21885 parser->omp_for_parse_state = omp_for_parse_state;
21886 }
21887 in_statement = save_in_statement;
21888 omp_for_parse_state->want_nested_loop = false;
21889 omp_for_parse_state->in_intervening_code = true;
21890
21891 /* Pop and return the implicit scope surrounding this level of loop.
21892 If the iteration variable at this depth was bound in the for loop,
21893 pull out and save the binding. Later in c_parser_omp_for_loop,
21894 these bindings will be moved to the scope surrounding the entire
21895 OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
21896 we have already resolved all references to the iteration variable
21897 in its true scope. */
21898 add_stmt (body);
21899 body = c_end_compound_stmt (loc, loop_scope, true);
21900 if (decl && TREE_CODE (body) == BIND_EXPR)
21901 {
21902 tree t = BIND_EXPR_VARS (body);
21903 tree prev = NULL_TREE, next = NULL_TREE;
21904 while (t)
21905 {
21906 next = DECL_CHAIN (t);
21907 if (t == decl)
21908 {
21909 if (prev)
21910 DECL_CHAIN (prev) = next;
21911 else
21912 {
21913 BIND_EXPR_VARS (body) = next;
21914 BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
21915 }
21916 DECL_CHAIN (t) = omp_for_parse_state->bindings;
21917 omp_for_parse_state->bindings = t;
21918 break;
21919 }
21920 else
21921 {
21922 prev = t;
21923 t = next;
21924 }
21925 }
21926 if (BIND_EXPR_VARS (body) == NULL_TREE)
21927 body = BIND_EXPR_BODY (body);
21928 }
21929
21930 return body;
21931}
21932
21933/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
21934 The real trick here is to determine the loop control variable early
21935 so that we can push a new decl if necessary to make it private.
21936 LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
21937 respectively. */
21938
21939static tree
21940c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
21941 tree clauses, tree *cclauses, bool *if_p)
21942{
21943 tree body, stmt, cl;
21944 tree ret = NULL_TREE;
21945 tree ordered_cl = NULL_TREE;
21946 int i, collapse = 1, ordered = 0, count;
21947 bool tiling = false;
21948 bool inscan = false;
21949 struct omp_for_parse_data data;
21950 struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
21951
21952 for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
21953 if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
21954 collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
21955 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
21956 {
21957 tiling = true;
21958 collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
21959 }
21960 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
21961 && OMP_CLAUSE_ORDERED_EXPR (cl))
21962 {
21963 ordered_cl = cl;
21964 ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
21965 }
21966 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
21967 && OMP_CLAUSE_REDUCTION_INSCAN (cl)
21968 && (code == OMP_SIMD || code == OMP_FOR))
21969 inscan = true;
21970
21971 if (ordered && ordered < collapse)
21972 {
21973 error_at (OMP_CLAUSE_LOCATION (ordered_cl),
21974 "%<ordered%> clause parameter is less than %<collapse%>");
21975 OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
21976 = build_int_cst (NULL_TREE, collapse);
21977 ordered = collapse;
21978 }
21979
21980 gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
21981 count = ordered ? ordered : collapse;
21982
21983 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
21984 {
21985 c_parser_error (parser, gmsgid: "for statement expected");
21986 return NULL;
21987 }
21988
21989 /* Initialize parse state for recursive descent. */
21990 data.declv = make_tree_vec (count);
21991 data.initv = make_tree_vec (count);
21992 data.condv = make_tree_vec (count);
21993 data.incrv = make_tree_vec (count);
21994 data.pre_body = NULL_TREE;;
21995 data.bindings = NULL_TREE;
21996 data.for_loc = c_parser_peek_token (parser)->location;
21997 data.count = count;
21998 data.depth = 0;
21999 data.want_nested_loop = true;
22000 data.ordered = ordered > 0;
22001 data.in_intervening_code = false;
22002 data.perfect_nesting_fail = false;
22003 data.fail = false;
22004 data.inscan = inscan;
22005 data.saw_intervening_code = false;
22006 data.code = code;
22007 parser->omp_for_parse_state = &data;
22008
22009 body = c_parser_omp_loop_nest (parser, if_p);
22010
22011 /* Add saved bindings for iteration variables that were declared in
22012 the nested for loop to the scope surrounding the entire loop. */
22013 for (tree t = data.bindings; t; )
22014 {
22015 tree n = TREE_CHAIN (t);
22016 TREE_CHAIN (t) = NULL_TREE;
22017 pushdecl (t);
22018 t = n;
22019 }
22020
22021 /* Only bother calling c_finish_omp_for if we haven't already generated
22022 an error from the initialization parsing. */
22023 if (!data.fail)
22024 {
22025 c_in_omp_for = true;
22026 stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
22027 data.condv, data.incrv,
22028 body, data.pre_body, true);
22029 c_in_omp_for = false;
22030
22031 /* Check for iterators appearing in lb, b or incr expressions. */
22032 if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
22033 stmt = NULL_TREE;
22034
22035 /* Check for errors involving lb/ub/incr expressions referencing
22036 variables declared in intervening code. */
22037 if (data.saw_intervening_code
22038 && !c_omp_check_loop_binding_exprs (stmt, NULL))
22039 stmt = NULL_TREE;
22040
22041 if (stmt)
22042 {
22043 add_stmt (stmt);
22044
22045 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
22046 {
22047 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
22048 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
22049 tree decl = TREE_OPERAND (init, 0);
22050 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
22051 gcc_assert (COMPARISON_CLASS_P (cond));
22052 gcc_assert (TREE_OPERAND (cond, 0) == decl);
22053
22054 tree op0 = TREE_OPERAND (init, 1);
22055 if (!OMP_FOR_NON_RECTANGULAR (stmt)
22056 || TREE_CODE (op0) != TREE_VEC)
22057 TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
22058 else
22059 {
22060 TREE_VEC_ELT (op0, 1)
22061 = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
22062 TREE_VEC_ELT (op0, 2)
22063 = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
22064 }
22065
22066 tree op1 = TREE_OPERAND (cond, 1);
22067 if (!OMP_FOR_NON_RECTANGULAR (stmt)
22068 || TREE_CODE (op1) != TREE_VEC)
22069 TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
22070 else
22071 {
22072 TREE_VEC_ELT (op1, 1)
22073 = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
22074 TREE_VEC_ELT (op1, 2)
22075 = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
22076 }
22077 }
22078
22079 if (cclauses != NULL
22080 && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
22081 {
22082 tree *c;
22083 for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
22084 if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
22085 && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
22086 c = &OMP_CLAUSE_CHAIN (*c);
22087 else
22088 {
22089 for (i = 0; i < count; i++)
22090 if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
22091 break;
22092 if (i == count)
22093 c = &OMP_CLAUSE_CHAIN (*c);
22094 else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
22095 {
22096 error_at (loc,
22097 "iteration variable %qD should not be firstprivate",
22098 OMP_CLAUSE_DECL (*c));
22099 *c = OMP_CLAUSE_CHAIN (*c);
22100 }
22101 else
22102 {
22103 /* Move lastprivate (decl) clause to
22104 OMP_FOR_CLAUSES. */
22105 tree l = *c;
22106 *c = OMP_CLAUSE_CHAIN (*c);
22107 if (code == OMP_SIMD)
22108 {
22109 OMP_CLAUSE_CHAIN (l)
22110 = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22111 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
22112 }
22113 else
22114 {
22115 OMP_CLAUSE_CHAIN (l) = clauses;
22116 clauses = l;
22117 }
22118 }
22119 }
22120 }
22121 OMP_FOR_CLAUSES (stmt) = clauses;
22122 }
22123 ret = stmt;
22124 }
22125
22126 parser->omp_for_parse_state = save_data;
22127 return ret;
22128}
22129
22130/* Helper function for OpenMP parsing, split clauses and call
22131 finish_omp_clauses on each of the set of clauses afterwards. */
22132
22133static void
22134omp_split_clauses (location_t loc, enum tree_code code,
22135 omp_clause_mask mask, tree clauses, tree *cclauses)
22136{
22137 int i;
22138 c_omp_split_clauses (loc, code, mask, clauses, cclauses);
22139 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
22140 if (cclauses[i])
22141 cclauses[i] = c_finish_omp_clauses (cclauses[i],
22142 i == C_OMP_CLAUSE_SPLIT_TARGET
22143 ? C_ORT_OMP_TARGET : C_ORT_OMP);
22144}
22145
22146/* OpenMP 5.0:
22147 #pragma omp loop loop-clause[optseq] new-line
22148 for-loop
22149
22150 LOC is the location of the #pragma token.
22151*/
22152
22153#define OMP_LOOP_CLAUSE_MASK \
22154 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22155 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22156 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22157 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22158 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
22159 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22160
22161static tree
22162c_parser_omp_loop (location_t loc, c_parser *parser,
22163 char *p_name, omp_clause_mask mask, tree *cclauses,
22164 bool *if_p)
22165{
22166 tree block, clauses, ret;
22167
22168 strcat (dest: p_name, src: " loop");
22169 mask |= OMP_LOOP_CLAUSE_MASK;
22170
22171 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22172 if (cclauses)
22173 {
22174 omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses);
22175 clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
22176 }
22177
22178 block = c_begin_compound_stmt (true);
22179 ret = c_parser_omp_for_loop (loc, parser, code: OMP_LOOP, clauses, cclauses, if_p);
22180 block = c_end_compound_stmt (loc, block, true);
22181 add_stmt (block);
22182
22183 return ret;
22184}
22185
22186/* OpenMP 4.0:
22187 #pragma omp simd simd-clause[optseq] new-line
22188 for-loop
22189
22190 LOC is the location of the #pragma token.
22191*/
22192
22193#define OMP_SIMD_CLAUSE_MASK \
22194 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
22195 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
22196 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
22197 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
22198 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22199 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22200 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22201 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22202 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
22203 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
22204 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22205
22206static tree
22207c_parser_omp_simd (location_t loc, c_parser *parser,
22208 char *p_name, omp_clause_mask mask, tree *cclauses,
22209 bool *if_p)
22210{
22211 tree block, clauses, ret;
22212
22213 strcat (dest: p_name, src: " simd");
22214 mask |= OMP_SIMD_CLAUSE_MASK;
22215
22216 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22217 if (cclauses)
22218 {
22219 omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses);
22220 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
22221 }
22222
22223 block = c_begin_compound_stmt (true);
22224 ret = c_parser_omp_for_loop (loc, parser, code: OMP_SIMD, clauses, cclauses, if_p);
22225 block = c_end_compound_stmt (loc, block, true);
22226 add_stmt (block);
22227
22228 return ret;
22229}
22230
22231/* OpenMP 2.5:
22232 #pragma omp for for-clause[optseq] new-line
22233 for-loop
22234
22235 OpenMP 4.0:
22236 #pragma omp for simd for-simd-clause[optseq] new-line
22237 for-loop
22238
22239 LOC is the location of the #pragma token.
22240*/
22241
22242#define OMP_FOR_CLAUSE_MASK \
22243 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22244 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22245 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22246 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
22247 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22248 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
22249 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
22250 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
22251 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
22252 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22253 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
22254
22255static tree
22256c_parser_omp_for (location_t loc, c_parser *parser,
22257 char *p_name, omp_clause_mask mask, tree *cclauses,
22258 bool *if_p)
22259{
22260 tree block, clauses, ret;
22261
22262 strcat (dest: p_name, src: " for");
22263 mask |= OMP_FOR_CLAUSE_MASK;
22264 /* parallel for{, simd} disallows nowait clause, but for
22265 target {teams distribute ,}parallel for{, simd} it should be accepted. */
22266 if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
22267 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
22268 /* Composite distribute parallel for{, simd} disallows ordered clause. */
22269 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
22270 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
22271
22272 if (c_parser_next_token_is (parser, type: CPP_NAME))
22273 {
22274 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22275
22276 if (strcmp (s1: p, s2: "simd") == 0)
22277 {
22278 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22279 if (cclauses == NULL)
22280 cclauses = cclauses_buf;
22281
22282 c_parser_consume_token (parser);
22283 if (!flag_openmp) /* flag_openmp_simd */
22284 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
22285 if_p);
22286 block = c_begin_compound_stmt (true);
22287 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
22288 block = c_end_compound_stmt (loc, block, true);
22289 if (ret == NULL_TREE)
22290 return ret;
22291 ret = make_node (OMP_FOR);
22292 TREE_TYPE (ret) = void_type_node;
22293 OMP_FOR_BODY (ret) = block;
22294 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22295 SET_EXPR_LOCATION (ret, loc);
22296 add_stmt (ret);
22297 return ret;
22298 }
22299 }
22300 if (!flag_openmp) /* flag_openmp_simd */
22301 {
22302 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22303 return NULL_TREE;
22304 }
22305
22306 /* Composite distribute parallel for disallows linear clause. */
22307 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
22308 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
22309
22310 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22311 if (cclauses)
22312 {
22313 omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses);
22314 clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
22315 }
22316
22317 block = c_begin_compound_stmt (true);
22318 ret = c_parser_omp_for_loop (loc, parser, code: OMP_FOR, clauses, cclauses, if_p);
22319 block = c_end_compound_stmt (loc, block, true);
22320 add_stmt (block);
22321
22322 return ret;
22323}
22324
22325static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
22326 omp_clause_mask, tree *, bool *);
22327
22328/* OpenMP 2.5:
22329 # pragma omp master new-line
22330 structured-block
22331
22332 LOC is the location of the #pragma token.
22333*/
22334
22335static tree
22336c_parser_omp_master (location_t loc, c_parser *parser,
22337 char *p_name, omp_clause_mask mask, tree *cclauses,
22338 bool *if_p)
22339{
22340 tree block, clauses, ret;
22341
22342 strcat (dest: p_name, src: " master");
22343
22344 if (c_parser_next_token_is (parser, type: CPP_NAME))
22345 {
22346 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22347
22348 if (strcmp (s1: p, s2: "taskloop") == 0)
22349 {
22350 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22351 if (cclauses == NULL)
22352 cclauses = cclauses_buf;
22353
22354 c_parser_consume_token (parser);
22355 if (!flag_openmp) /* flag_openmp_simd */
22356 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22357 if_p);
22358 block = c_begin_compound_stmt (true);
22359 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22360 if_p);
22361 block = c_end_compound_stmt (loc, block, true);
22362 if (ret == NULL_TREE)
22363 return ret;
22364 ret = c_finish_omp_master (loc, block);
22365 OMP_MASTER_COMBINED (ret) = 1;
22366 return ret;
22367 }
22368 }
22369 if (!flag_openmp) /* flag_openmp_simd */
22370 {
22371 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22372 return NULL_TREE;
22373 }
22374
22375 if (cclauses)
22376 {
22377 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: false);
22378 omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses);
22379 }
22380 else
22381 c_parser_skip_to_pragma_eol (parser);
22382
22383 return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
22384 if_p));
22385}
22386
22387/* OpenMP 5.1:
22388 # pragma omp masked masked-clauses new-line
22389 structured-block
22390
22391 LOC is the location of the #pragma token.
22392*/
22393
22394#define OMP_MASKED_CLAUSE_MASK \
22395 (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
22396
22397static tree
22398c_parser_omp_masked (location_t loc, c_parser *parser,
22399 char *p_name, omp_clause_mask mask, tree *cclauses,
22400 bool *if_p)
22401{
22402 tree block, clauses, ret;
22403
22404 strcat (dest: p_name, src: " masked");
22405 mask |= OMP_MASKED_CLAUSE_MASK;
22406
22407 if (c_parser_next_token_is (parser, type: CPP_NAME))
22408 {
22409 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22410
22411 if (strcmp (s1: p, s2: "taskloop") == 0)
22412 {
22413 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22414 if (cclauses == NULL)
22415 cclauses = cclauses_buf;
22416
22417 c_parser_consume_token (parser);
22418 if (!flag_openmp) /* flag_openmp_simd */
22419 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22420 if_p);
22421 block = c_begin_compound_stmt (true);
22422 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
22423 if_p);
22424 block = c_end_compound_stmt (loc, block, true);
22425 if (ret == NULL_TREE)
22426 return ret;
22427 ret = c_finish_omp_masked (loc, block,
22428 cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
22429 OMP_MASKED_COMBINED (ret) = 1;
22430 return ret;
22431 }
22432 }
22433 if (!flag_openmp) /* flag_openmp_simd */
22434 {
22435 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22436 return NULL_TREE;
22437 }
22438
22439 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22440 if (cclauses)
22441 {
22442 omp_split_clauses (loc, code: OMP_MASKED, mask, clauses, cclauses);
22443 clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
22444 }
22445
22446 return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
22447 if_p),
22448 clauses);
22449}
22450
22451/* OpenMP 2.5:
22452 # pragma omp ordered new-line
22453 structured-block
22454
22455 OpenMP 4.5:
22456 # pragma omp ordered ordered-clauses new-line
22457 structured-block
22458
22459 # pragma omp ordered depend-clauses new-line
22460
22461 OpenMP 5.2
22462 # pragma omp ordered doacross-clauses new-line */
22463
22464#define OMP_ORDERED_CLAUSE_MASK \
22465 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
22466 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
22467
22468#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
22469 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
22470 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
22471
22472static bool
22473c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
22474 bool *if_p)
22475{
22476 location_t loc = c_parser_peek_token (parser)->location;
22477 c_parser_consume_pragma (parser);
22478
22479 if (context != pragma_stmt && context != pragma_compound)
22480 {
22481 c_parser_error (parser, gmsgid: "expected declaration specifiers");
22482 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22483 return false;
22484 }
22485
22486 int n = 1;
22487 if (c_parser_next_token_is (parser, type: CPP_COMMA))
22488 n = 2;
22489
22490 if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
22491 {
22492 const char *p
22493 = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
22494
22495 if (!strcmp (s1: "depend", s2: p) || !strcmp (s1: "doacross", s2: p))
22496 {
22497 if (!flag_openmp) /* flag_openmp_simd */
22498 {
22499 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22500 return false;
22501 }
22502 if (context == pragma_stmt)
22503 {
22504 error_at (loc,
22505 "%<#pragma omp ordered%> with %qs clause may "
22506 "only be used in compound statements", p);
22507 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22508 return true;
22509 }
22510
22511 tree clauses
22512 = c_parser_omp_all_clauses (parser,
22513 OMP_ORDERED_DEPEND_CLAUSE_MASK,
22514 where: "#pragma omp ordered");
22515 c_finish_omp_ordered (loc, clauses, NULL_TREE);
22516 return false;
22517 }
22518 }
22519
22520 tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
22521 where: "#pragma omp ordered");
22522
22523 if (!flag_openmp /* flag_openmp_simd */
22524 && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE)
22525 return false;
22526
22527 c_finish_omp_ordered (loc, clauses,
22528 c_parser_omp_structured_block (parser, if_p));
22529 return true;
22530}
22531
22532/* OpenMP 2.5:
22533
22534 section-scope:
22535 { section-sequence }
22536
22537 section-sequence:
22538 section-directive[opt] structured-block
22539 section-sequence section-directive structured-block
22540
22541 OpenMP 5.1 allows structured-block-sequence instead of structured-block.
22542
22543 SECTIONS_LOC is the location of the #pragma omp sections. */
22544
22545static tree
22546c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
22547{
22548 tree stmt, substmt;
22549 bool error_suppress = false;
22550 location_t loc;
22551
22552 loc = c_parser_peek_token (parser)->location;
22553 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
22554 {
22555 /* Avoid skipping until the end of the block. */
22556 parser->error = false;
22557 return NULL_TREE;
22558 }
22559
22560 stmt = push_stmt_list ();
22561
22562 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
22563 && !c_parser_omp_section_scan (parser, directive: "section", tentative: true))
22564 {
22565 substmt = c_parser_omp_structured_block_sequence (parser,
22566 kind: PRAGMA_OMP_SECTION);
22567 substmt = build1 (OMP_SECTION, void_type_node, substmt);
22568 SET_EXPR_LOCATION (substmt, loc);
22569 add_stmt (substmt);
22570 }
22571
22572 while (1)
22573 {
22574 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
22575 break;
22576 if (c_parser_next_token_is (parser, type: CPP_EOF))
22577 break;
22578
22579 loc = c_parser_peek_token (parser)->location;
22580 c_parser_omp_section_scan (parser, directive: "section", tentative: false);
22581 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
22582 {
22583 c_parser_consume_pragma (parser);
22584 c_parser_skip_to_pragma_eol (parser);
22585 error_suppress = false;
22586 }
22587 else if (!error_suppress)
22588 {
22589 error_at (loc, "expected %<#pragma omp section%> or %<}%>");
22590 error_suppress = true;
22591 }
22592
22593 substmt = c_parser_omp_structured_block_sequence (parser,
22594 kind: PRAGMA_OMP_SECTION);
22595 substmt = build1 (OMP_SECTION, void_type_node, substmt);
22596 SET_EXPR_LOCATION (substmt, loc);
22597 add_stmt (substmt);
22598 }
22599 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
22600 msgid: "expected %<#pragma omp section%> or %<}%>");
22601
22602 substmt = pop_stmt_list (stmt);
22603
22604 stmt = make_node (OMP_SECTIONS);
22605 SET_EXPR_LOCATION (stmt, sections_loc);
22606 TREE_TYPE (stmt) = void_type_node;
22607 OMP_SECTIONS_BODY (stmt) = substmt;
22608
22609 return add_stmt (stmt);
22610}
22611
22612/* OpenMP 2.5:
22613 # pragma omp sections sections-clause[optseq] newline
22614 sections-scope
22615
22616 LOC is the location of the #pragma token.
22617*/
22618
22619#define OMP_SECTIONS_CLAUSE_MASK \
22620 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22621 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22622 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
22623 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22624 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22625 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
22626
22627static tree
22628c_parser_omp_sections (location_t loc, c_parser *parser,
22629 char *p_name, omp_clause_mask mask, tree *cclauses)
22630{
22631 tree block, clauses, ret;
22632
22633 strcat (dest: p_name, src: " sections");
22634 mask |= OMP_SECTIONS_CLAUSE_MASK;
22635 if (cclauses)
22636 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
22637
22638 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22639 if (cclauses)
22640 {
22641 omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses);
22642 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
22643 }
22644
22645 block = c_begin_compound_stmt (true);
22646 ret = c_parser_omp_sections_scope (sections_loc: loc, parser);
22647 if (ret)
22648 OMP_SECTIONS_CLAUSES (ret) = clauses;
22649 block = c_end_compound_stmt (loc, block, true);
22650 add_stmt (block);
22651
22652 return ret;
22653}
22654
22655/* OpenMP 2.5:
22656 # pragma omp parallel parallel-clause[optseq] new-line
22657 structured-block
22658 # pragma omp parallel for parallel-for-clause[optseq] new-line
22659 structured-block
22660 # pragma omp parallel sections parallel-sections-clause[optseq] new-line
22661 structured-block
22662
22663 OpenMP 4.0:
22664 # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
22665 structured-block
22666
22667 LOC is the location of the #pragma token.
22668*/
22669
22670#define OMP_PARALLEL_CLAUSE_MASK \
22671 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
22672 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22673 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22674 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
22675 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
22676 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
22677 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22678 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
22679 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22680 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
22681
22682static tree
22683c_parser_omp_parallel (location_t loc, c_parser *parser,
22684 char *p_name, omp_clause_mask mask, tree *cclauses,
22685 bool *if_p)
22686{
22687 tree stmt, clauses, block;
22688
22689 strcat (dest: p_name, src: " parallel");
22690 mask |= OMP_PARALLEL_CLAUSE_MASK;
22691 /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
22692 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
22693 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
22694 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
22695
22696 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
22697 {
22698 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22699 if (cclauses == NULL)
22700 cclauses = cclauses_buf;
22701
22702 c_parser_consume_token (parser);
22703 if (!flag_openmp) /* flag_openmp_simd */
22704 return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
22705 block = c_begin_omp_parallel ();
22706 tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
22707 stmt
22708 = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
22709 block);
22710 if (ret == NULL_TREE)
22711 return ret;
22712 OMP_PARALLEL_COMBINED (stmt) = 1;
22713 return stmt;
22714 }
22715 /* When combined with distribute, parallel has to be followed by for.
22716 #pragma omp target parallel is allowed though. */
22717 else if (cclauses
22718 && (mask & (OMP_CLAUSE_MASK_1
22719 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
22720 {
22721 error_at (loc, "expected %<for%> after %qs", p_name);
22722 c_parser_skip_to_pragma_eol (parser);
22723 return NULL_TREE;
22724 }
22725 else if (c_parser_next_token_is (parser, type: CPP_NAME))
22726 {
22727 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22728 if (cclauses == NULL && strcmp (s1: p, s2: "masked") == 0)
22729 {
22730 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22731 cclauses = cclauses_buf;
22732
22733 c_parser_consume_token (parser);
22734 if (!flag_openmp) /* flag_openmp_simd */
22735 return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
22736 if_p);
22737 block = c_begin_omp_parallel ();
22738 tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
22739 if_p);
22740 stmt = c_finish_omp_parallel (loc,
22741 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
22742 block);
22743 if (ret == NULL)
22744 return ret;
22745 /* masked does have just filter clause, but during gimplification
22746 isn't represented by a gimplification omp context, so for
22747 #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
22748 so that
22749 #pragma omp parallel masked
22750 #pragma omp taskloop simd lastprivate (x)
22751 isn't confused with
22752 #pragma omp parallel masked taskloop simd lastprivate (x) */
22753 if (OMP_MASKED_COMBINED (ret))
22754 OMP_PARALLEL_COMBINED (stmt) = 1;
22755 return stmt;
22756 }
22757 else if (cclauses == NULL && strcmp (s1: p, s2: "master") == 0)
22758 {
22759 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22760 cclauses = cclauses_buf;
22761
22762 c_parser_consume_token (parser);
22763 if (!flag_openmp) /* flag_openmp_simd */
22764 return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
22765 if_p);
22766 block = c_begin_omp_parallel ();
22767 tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
22768 if_p);
22769 stmt = c_finish_omp_parallel (loc,
22770 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
22771 block);
22772 if (ret == NULL)
22773 return ret;
22774 /* master doesn't have any clauses and during gimplification
22775 isn't represented by a gimplification omp context, so for
22776 #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
22777 so that
22778 #pragma omp parallel master
22779 #pragma omp taskloop simd lastprivate (x)
22780 isn't confused with
22781 #pragma omp parallel master taskloop simd lastprivate (x) */
22782 if (OMP_MASTER_COMBINED (ret))
22783 OMP_PARALLEL_COMBINED (stmt) = 1;
22784 return stmt;
22785 }
22786 else if (strcmp (s1: p, s2: "loop") == 0)
22787 {
22788 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22789 if (cclauses == NULL)
22790 cclauses = cclauses_buf;
22791
22792 c_parser_consume_token (parser);
22793 if (!flag_openmp) /* flag_openmp_simd */
22794 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
22795 if_p);
22796 block = c_begin_omp_parallel ();
22797 tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
22798 if_p);
22799 stmt
22800 = c_finish_omp_parallel (loc,
22801 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
22802 block);
22803 if (ret == NULL_TREE)
22804 return ret;
22805 OMP_PARALLEL_COMBINED (stmt) = 1;
22806 return stmt;
22807 }
22808 else if (!flag_openmp) /* flag_openmp_simd */
22809 {
22810 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22811 return NULL_TREE;
22812 }
22813 else if (cclauses == NULL && strcmp (s1: p, s2: "sections") == 0)
22814 {
22815 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
22816 cclauses = cclauses_buf;
22817
22818 c_parser_consume_token (parser);
22819 block = c_begin_omp_parallel ();
22820 c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
22821 stmt = c_finish_omp_parallel (loc,
22822 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
22823 block);
22824 OMP_PARALLEL_COMBINED (stmt) = 1;
22825 return stmt;
22826 }
22827 }
22828 else if (!flag_openmp) /* flag_openmp_simd */
22829 {
22830 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22831 return NULL_TREE;
22832 }
22833
22834 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
22835 if (cclauses)
22836 {
22837 omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses);
22838 clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
22839 }
22840
22841 block = c_begin_omp_parallel ();
22842 parser->omp_attrs_forbidden_p = true;
22843 c_parser_statement (parser, if_p);
22844 stmt = c_finish_omp_parallel (loc, clauses, block);
22845
22846 return stmt;
22847}
22848
22849/* OpenMP 2.5:
22850 # pragma omp single single-clause[optseq] new-line
22851 structured-block
22852
22853 LOC is the location of the #pragma.
22854*/
22855
22856#define OMP_SINGLE_CLAUSE_MASK \
22857 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22858 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22859 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
22860 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22861 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
22862
22863static tree
22864c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
22865{
22866 tree stmt = make_node (OMP_SINGLE);
22867 SET_EXPR_LOCATION (stmt, loc);
22868 TREE_TYPE (stmt) = void_type_node;
22869
22870 OMP_SINGLE_CLAUSES (stmt)
22871 = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
22872 where: "#pragma omp single");
22873 OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
22874
22875 return add_stmt (stmt);
22876}
22877
22878/* OpenMP 5.1:
22879 # pragma omp scope scope-clause[optseq] new-line
22880 structured-block
22881
22882 LOC is the location of the #pragma.
22883*/
22884
22885#define OMP_SCOPE_CLAUSE_MASK \
22886 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22887 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22888 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
22889 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22890 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
22891
22892static tree
22893c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
22894{
22895 tree stmt = make_node (OMP_SCOPE);
22896 SET_EXPR_LOCATION (stmt, loc);
22897 TREE_TYPE (stmt) = void_type_node;
22898
22899 OMP_SCOPE_CLAUSES (stmt)
22900 = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
22901 where: "#pragma omp scope");
22902 OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
22903
22904 return add_stmt (stmt);
22905}
22906
22907/* OpenMP 3.0:
22908 # pragma omp task task-clause[optseq] new-line
22909
22910 LOC is the location of the #pragma.
22911*/
22912
22913#define OMP_TASK_CLAUSE_MASK \
22914 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
22915 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
22916 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
22917 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
22918 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
22919 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
22920 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
22921 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
22922 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
22923 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
22924 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
22925 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
22926 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
22927 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
22928
22929static tree
22930c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
22931{
22932 tree clauses, block;
22933
22934 clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
22935 where: "#pragma omp task");
22936
22937 block = c_begin_omp_task ();
22938 parser->omp_attrs_forbidden_p = true;
22939 c_parser_statement (parser, if_p);
22940 return c_finish_omp_task (loc, clauses, block);
22941}
22942
22943/* OpenMP 3.0:
22944 # pragma omp taskwait new-line
22945
22946 OpenMP 5.0:
22947 # pragma omp taskwait taskwait-clause[optseq] new-line
22948*/
22949
22950#define OMP_TASKWAIT_CLAUSE_MASK \
22951 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
22952 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
22953
22954static void
22955c_parser_omp_taskwait (c_parser *parser)
22956{
22957 location_t loc = c_parser_peek_token (parser)->location;
22958 c_parser_consume_pragma (parser);
22959
22960 tree clauses
22961 = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
22962 where: "#pragma omp taskwait");
22963
22964 if (clauses)
22965 {
22966 tree stmt = make_node (OMP_TASK);
22967 TREE_TYPE (stmt) = void_node;
22968 OMP_TASK_CLAUSES (stmt) = clauses;
22969 OMP_TASK_BODY (stmt) = NULL_TREE;
22970 SET_EXPR_LOCATION (stmt, loc);
22971 add_stmt (stmt);
22972 }
22973 else
22974 c_finish_omp_taskwait (loc);
22975}
22976
22977/* OpenMP 3.1:
22978 # pragma omp taskyield new-line
22979*/
22980
22981static void
22982c_parser_omp_taskyield (c_parser *parser)
22983{
22984 location_t loc = c_parser_peek_token (parser)->location;
22985 c_parser_consume_pragma (parser);
22986 c_parser_skip_to_pragma_eol (parser);
22987
22988 c_finish_omp_taskyield (loc);
22989}
22990
22991/* OpenMP 4.0:
22992 # pragma omp taskgroup new-line
22993
22994 OpenMP 5.0:
22995 # pragma omp taskgroup taskgroup-clause[optseq] new-line
22996*/
22997
22998#define OMP_TASKGROUP_CLAUSE_MASK \
22999 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23000 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
23001
23002static tree
23003c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
23004{
23005 tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
23006 where: "#pragma omp taskgroup");
23007
23008 tree body = c_parser_omp_structured_block (parser, if_p);
23009 return c_finish_omp_taskgroup (loc, body, clauses);
23010}
23011
23012/* OpenMP 4.0:
23013 # pragma omp cancel cancel-clause[optseq] new-line
23014
23015 LOC is the location of the #pragma.
23016*/
23017
23018#define OMP_CANCEL_CLAUSE_MASK \
23019 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
23020 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
23021 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
23022 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
23023 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
23024
23025static void
23026c_parser_omp_cancel (c_parser *parser)
23027{
23028 location_t loc = c_parser_peek_token (parser)->location;
23029
23030 c_parser_consume_pragma (parser);
23031 tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
23032 where: "#pragma omp cancel");
23033
23034 c_finish_omp_cancel (loc, clauses);
23035}
23036
23037/* OpenMP 4.0:
23038 # pragma omp cancellation point cancelpt-clause[optseq] new-line
23039
23040 LOC is the location of the #pragma.
23041*/
23042
23043#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
23044 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
23045 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
23046 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
23047 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
23048
23049static bool
23050c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
23051{
23052 location_t loc = c_parser_peek_token (parser)->location;
23053 tree clauses;
23054 bool point_seen = false;
23055
23056 c_parser_consume_pragma (parser);
23057 if (c_parser_next_token_is (parser, type: CPP_NAME))
23058 {
23059 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23060 if (strcmp (s1: p, s2: "point") == 0)
23061 {
23062 c_parser_consume_token (parser);
23063 point_seen = true;
23064 }
23065 }
23066 if (!point_seen)
23067 {
23068 c_parser_error (parser, gmsgid: "expected %<point%>");
23069 c_parser_skip_to_pragma_eol (parser);
23070 return false;
23071 }
23072
23073 if (context != pragma_compound)
23074 {
23075 if (context == pragma_stmt)
23076 error_at (loc,
23077 "%<#pragma %s%> may only be used in compound statements",
23078 "omp cancellation point");
23079 else
23080 c_parser_error (parser, gmsgid: "expected declaration specifiers");
23081 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23082 return true;
23083 }
23084
23085 clauses
23086 = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
23087 where: "#pragma omp cancellation point");
23088
23089 c_finish_omp_cancellation_point (loc, clauses);
23090 return true;
23091}
23092
23093/* OpenMP 4.0:
23094 #pragma omp distribute distribute-clause[optseq] new-line
23095 for-loop */
23096
23097#define OMP_DISTRIBUTE_CLAUSE_MASK \
23098 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23099 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23100 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
23101 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
23102 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23103 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
23104 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
23105
23106static tree
23107c_parser_omp_distribute (location_t loc, c_parser *parser,
23108 char *p_name, omp_clause_mask mask, tree *cclauses,
23109 bool *if_p)
23110{
23111 tree clauses, block, ret;
23112
23113 strcat (dest: p_name, src: " distribute");
23114 mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
23115
23116 if (c_parser_next_token_is (parser, type: CPP_NAME))
23117 {
23118 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23119 bool simd = false;
23120 bool parallel = false;
23121
23122 if (strcmp (s1: p, s2: "simd") == 0)
23123 simd = true;
23124 else
23125 parallel = strcmp (s1: p, s2: "parallel") == 0;
23126 if (parallel || simd)
23127 {
23128 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23129 if (cclauses == NULL)
23130 cclauses = cclauses_buf;
23131 c_parser_consume_token (parser);
23132 if (!flag_openmp) /* flag_openmp_simd */
23133 {
23134 if (simd)
23135 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
23136 if_p);
23137 else
23138 return c_parser_omp_parallel (loc, parser, p_name, mask,
23139 cclauses, if_p);
23140 }
23141 block = c_begin_compound_stmt (true);
23142 if (simd)
23143 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
23144 if_p);
23145 else
23146 ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
23147 if_p);
23148 block = c_end_compound_stmt (loc, block, true);
23149 if (ret == NULL)
23150 return ret;
23151 ret = make_node (OMP_DISTRIBUTE);
23152 TREE_TYPE (ret) = void_type_node;
23153 OMP_FOR_BODY (ret) = block;
23154 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
23155 SET_EXPR_LOCATION (ret, loc);
23156 add_stmt (ret);
23157 return ret;
23158 }
23159 }
23160 if (!flag_openmp) /* flag_openmp_simd */
23161 {
23162 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23163 return NULL_TREE;
23164 }
23165
23166 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23167 if (cclauses)
23168 {
23169 omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses);
23170 clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
23171 }
23172
23173 block = c_begin_compound_stmt (true);
23174 ret = c_parser_omp_for_loop (loc, parser, code: OMP_DISTRIBUTE, clauses, NULL,
23175 if_p);
23176 block = c_end_compound_stmt (loc, block, true);
23177 add_stmt (block);
23178
23179 return ret;
23180}
23181
23182/* OpenMP 4.0:
23183 # pragma omp teams teams-clause[optseq] new-line
23184 structured-block */
23185
23186#define OMP_TEAMS_CLAUSE_MASK \
23187 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23188 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23189 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
23190 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
23191 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
23192 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
23193 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23194 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
23195
23196static tree
23197c_parser_omp_teams (location_t loc, c_parser *parser,
23198 char *p_name, omp_clause_mask mask, tree *cclauses,
23199 bool *if_p)
23200{
23201 tree clauses, block, ret;
23202
23203 strcat (dest: p_name, src: " teams");
23204 mask |= OMP_TEAMS_CLAUSE_MASK;
23205
23206 if (c_parser_next_token_is (parser, type: CPP_NAME))
23207 {
23208 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23209 if (strcmp (s1: p, s2: "distribute") == 0)
23210 {
23211 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23212 if (cclauses == NULL)
23213 cclauses = cclauses_buf;
23214
23215 c_parser_consume_token (parser);
23216 if (!flag_openmp) /* flag_openmp_simd */
23217 return c_parser_omp_distribute (loc, parser, p_name, mask,
23218 cclauses, if_p);
23219 block = c_begin_omp_parallel ();
23220 ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
23221 if_p);
23222 block = c_end_compound_stmt (loc, block, true);
23223 if (ret == NULL)
23224 return ret;
23225 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23226 ret = make_node (OMP_TEAMS);
23227 TREE_TYPE (ret) = void_type_node;
23228 OMP_TEAMS_CLAUSES (ret) = clauses;
23229 OMP_TEAMS_BODY (ret) = block;
23230 OMP_TEAMS_COMBINED (ret) = 1;
23231 SET_EXPR_LOCATION (ret, loc);
23232 return add_stmt (ret);
23233 }
23234 else if (strcmp (s1: p, s2: "loop") == 0)
23235 {
23236 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
23237 if (cclauses == NULL)
23238 cclauses = cclauses_buf;
23239
23240 c_parser_consume_token (parser);
23241 if (!flag_openmp) /* flag_openmp_simd */
23242 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
23243 if_p);
23244 block = c_begin_omp_parallel ();
23245 ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
23246 block = c_end_compound_stmt (loc, block, true);
23247 if (ret == NULL)
23248 return ret;
23249 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23250 ret = make_node (OMP_TEAMS);
23251 TREE_TYPE (ret) = void_type_node;
23252 OMP_TEAMS_CLAUSES (ret) = clauses;
23253 OMP_TEAMS_BODY (ret) = block;
23254 OMP_TEAMS_COMBINED (ret) = 1;
23255 SET_EXPR_LOCATION (ret, loc);
23256 return add_stmt (ret);
23257 }
23258 }
23259 if (!flag_openmp) /* flag_openmp_simd */
23260 {
23261 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23262 return NULL_TREE;
23263 }
23264
23265 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
23266 if (cclauses)
23267 {
23268 omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses);
23269 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23270 }
23271
23272 tree stmt = make_node (OMP_TEAMS);
23273 TREE_TYPE (stmt) = void_type_node;
23274 OMP_TEAMS_CLAUSES (stmt) = clauses;
23275 block = c_begin_omp_parallel ();
23276 add_stmt (c_parser_omp_structured_block (parser, if_p));
23277 OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
23278 SET_EXPR_LOCATION (stmt, loc);
23279
23280 return add_stmt (stmt);
23281}
23282
23283/* OpenMP 4.0:
23284 # pragma omp target data target-data-clause[optseq] new-line
23285 structured-block */
23286
23287#define OMP_TARGET_DATA_CLAUSE_MASK \
23288 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23289 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23290 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23291 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
23292 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
23293
23294static tree
23295c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
23296{
23297 if (flag_openmp)
23298 omp_requires_mask
23299 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23300
23301 tree clauses
23302 = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
23303 where: "#pragma omp target data");
23304 c_omp_adjust_map_clauses (clauses, false);
23305 int map_seen = 0;
23306 for (tree *pc = &clauses; *pc;)
23307 {
23308 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
23309 switch (OMP_CLAUSE_MAP_KIND (*pc))
23310 {
23311 case GOMP_MAP_TO:
23312 case GOMP_MAP_ALWAYS_TO:
23313 case GOMP_MAP_PRESENT_TO:
23314 case GOMP_MAP_ALWAYS_PRESENT_TO:
23315 case GOMP_MAP_FROM:
23316 case GOMP_MAP_ALWAYS_FROM:
23317 case GOMP_MAP_PRESENT_FROM:
23318 case GOMP_MAP_ALWAYS_PRESENT_FROM:
23319 case GOMP_MAP_TOFROM:
23320 case GOMP_MAP_ALWAYS_TOFROM:
23321 case GOMP_MAP_PRESENT_TOFROM:
23322 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
23323 case GOMP_MAP_ALLOC:
23324 case GOMP_MAP_PRESENT_ALLOC:
23325 map_seen = 3;
23326 break;
23327 case GOMP_MAP_FIRSTPRIVATE_POINTER:
23328 case GOMP_MAP_ALWAYS_POINTER:
23329 case GOMP_MAP_ATTACH_DETACH:
23330 break;
23331 default:
23332 map_seen |= 1;
23333 error_at (OMP_CLAUSE_LOCATION (*pc),
23334 "%<#pragma omp target data%> with map-type other "
23335 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
23336 "on %<map%> clause");
23337 *pc = OMP_CLAUSE_CHAIN (*pc);
23338 continue;
23339 }
23340 else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
23341 || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
23342 map_seen = 3;
23343 pc = &OMP_CLAUSE_CHAIN (*pc);
23344 }
23345
23346 if (map_seen != 3)
23347 {
23348 if (map_seen == 0)
23349 error_at (loc,
23350 "%<#pragma omp target data%> must contain at least "
23351 "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
23352 "clause");
23353 return NULL_TREE;
23354 }
23355
23356 tree stmt = make_node (OMP_TARGET_DATA);
23357 TREE_TYPE (stmt) = void_type_node;
23358 OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
23359 keep_next_level ();
23360 tree block = c_begin_compound_stmt (true);
23361 add_stmt (c_parser_omp_structured_block (parser, if_p));
23362 OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
23363
23364 SET_EXPR_LOCATION (stmt, loc);
23365 return add_stmt (stmt);
23366}
23367
23368/* OpenMP 4.0:
23369 # pragma omp target update target-update-clause[optseq] new-line */
23370
23371#define OMP_TARGET_UPDATE_CLAUSE_MASK \
23372 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
23373 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
23374 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23375 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23376 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23377 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23378
23379static bool
23380c_parser_omp_target_update (location_t loc, c_parser *parser,
23381 enum pragma_context context)
23382{
23383 if (context == pragma_stmt)
23384 {
23385 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
23386 "omp target update");
23387 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23388 return true;
23389 }
23390
23391 tree clauses
23392 = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
23393 where: "#pragma omp target update");
23394 if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE
23395 && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE)
23396 {
23397 error_at (loc,
23398 "%<#pragma omp target update%> must contain at least one "
23399 "%<from%> or %<to%> clauses");
23400 return false;
23401 }
23402
23403 if (flag_openmp)
23404 omp_requires_mask
23405 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23406
23407 tree stmt = make_node (OMP_TARGET_UPDATE);
23408 TREE_TYPE (stmt) = void_type_node;
23409 OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
23410 SET_EXPR_LOCATION (stmt, loc);
23411 add_stmt (stmt);
23412 return false;
23413}
23414
23415/* OpenMP 4.5:
23416 # pragma omp target enter data target-data-clause[optseq] new-line */
23417
23418#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
23419 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23420 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23421 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23422 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23423 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23424
23425static bool
23426c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
23427 enum pragma_context context)
23428{
23429 bool data_seen = false;
23430 if (c_parser_next_token_is (parser, type: CPP_NAME))
23431 {
23432 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23433 if (strcmp (s1: p, s2: "data") == 0)
23434 {
23435 c_parser_consume_token (parser);
23436 data_seen = true;
23437 }
23438 }
23439 if (!data_seen)
23440 {
23441 c_parser_error (parser, gmsgid: "expected %<data%>");
23442 c_parser_skip_to_pragma_eol (parser);
23443 return false;
23444 }
23445
23446 if (context == pragma_stmt)
23447 {
23448 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
23449 "omp target enter data");
23450 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23451 return true;
23452 }
23453
23454 if (flag_openmp)
23455 omp_requires_mask
23456 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23457
23458 tree clauses
23459 = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
23460 where: "#pragma omp target enter data");
23461 c_omp_adjust_map_clauses (clauses, false);
23462 int map_seen = 0;
23463 for (tree *pc = &clauses; *pc;)
23464 {
23465 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
23466 switch (OMP_CLAUSE_MAP_KIND (*pc))
23467 {
23468 case GOMP_MAP_TO:
23469 case GOMP_MAP_ALWAYS_TO:
23470 case GOMP_MAP_PRESENT_TO:
23471 case GOMP_MAP_ALWAYS_PRESENT_TO:
23472 case GOMP_MAP_ALLOC:
23473 case GOMP_MAP_PRESENT_ALLOC:
23474 map_seen = 3;
23475 break;
23476 case GOMP_MAP_TOFROM:
23477 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
23478 map_seen = 3;
23479 break;
23480 case GOMP_MAP_ALWAYS_TOFROM:
23481 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
23482 map_seen = 3;
23483 break;
23484 case GOMP_MAP_PRESENT_TOFROM:
23485 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
23486 map_seen = 3;
23487 break;
23488 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
23489 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
23490 map_seen = 3;
23491 break;
23492 case GOMP_MAP_FIRSTPRIVATE_POINTER:
23493 case GOMP_MAP_ALWAYS_POINTER:
23494 case GOMP_MAP_ATTACH_DETACH:
23495 break;
23496 default:
23497 map_seen |= 1;
23498 error_at (OMP_CLAUSE_LOCATION (*pc),
23499 "%<#pragma omp target enter data%> with map-type other "
23500 "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
23501 *pc = OMP_CLAUSE_CHAIN (*pc);
23502 continue;
23503 }
23504 pc = &OMP_CLAUSE_CHAIN (*pc);
23505 }
23506
23507 if (map_seen != 3)
23508 {
23509 if (map_seen == 0)
23510 error_at (loc,
23511 "%<#pragma omp target enter data%> must contain at least "
23512 "one %<map%> clause");
23513 return true;
23514 }
23515
23516 tree stmt = make_node (OMP_TARGET_ENTER_DATA);
23517 TREE_TYPE (stmt) = void_type_node;
23518 OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
23519 SET_EXPR_LOCATION (stmt, loc);
23520 add_stmt (stmt);
23521 return true;
23522}
23523
23524/* OpenMP 4.5:
23525 # pragma omp target exit data target-data-clause[optseq] new-line */
23526
23527#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
23528 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23529 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23530 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23531 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23532 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
23533
23534static bool
23535c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
23536 enum pragma_context context)
23537{
23538 bool data_seen = false;
23539 if (c_parser_next_token_is (parser, type: CPP_NAME))
23540 {
23541 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23542 if (strcmp (s1: p, s2: "data") == 0)
23543 {
23544 c_parser_consume_token (parser);
23545 data_seen = true;
23546 }
23547 }
23548 if (!data_seen)
23549 {
23550 c_parser_error (parser, gmsgid: "expected %<data%>");
23551 c_parser_skip_to_pragma_eol (parser);
23552 return false;
23553 }
23554
23555 if (context == pragma_stmt)
23556 {
23557 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
23558 "omp target exit data");
23559 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23560 return true;
23561 }
23562
23563 if (flag_openmp)
23564 omp_requires_mask
23565 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23566
23567 tree clauses
23568 = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
23569 where: "#pragma omp target exit data");
23570 c_omp_adjust_map_clauses (clauses, false);
23571 int map_seen = 0;
23572 for (tree *pc = &clauses; *pc;)
23573 {
23574 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
23575 switch (OMP_CLAUSE_MAP_KIND (*pc))
23576 {
23577 case GOMP_MAP_FROM:
23578 case GOMP_MAP_ALWAYS_FROM:
23579 case GOMP_MAP_PRESENT_FROM:
23580 case GOMP_MAP_ALWAYS_PRESENT_FROM:
23581 case GOMP_MAP_RELEASE:
23582 case GOMP_MAP_DELETE:
23583 map_seen = 3;
23584 break;
23585 case GOMP_MAP_TOFROM:
23586 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
23587 map_seen = 3;
23588 break;
23589 case GOMP_MAP_ALWAYS_TOFROM:
23590 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
23591 map_seen = 3;
23592 break;
23593 case GOMP_MAP_PRESENT_TOFROM:
23594 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
23595 map_seen = 3;
23596 break;
23597 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
23598 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
23599 map_seen = 3;
23600 break;
23601 case GOMP_MAP_FIRSTPRIVATE_POINTER:
23602 case GOMP_MAP_ALWAYS_POINTER:
23603 case GOMP_MAP_ATTACH_DETACH:
23604 break;
23605 default:
23606 map_seen |= 1;
23607 error_at (OMP_CLAUSE_LOCATION (*pc),
23608 "%<#pragma omp target exit data%> with map-type other "
23609 "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
23610 "on %<map%> clause");
23611 *pc = OMP_CLAUSE_CHAIN (*pc);
23612 continue;
23613 }
23614 pc = &OMP_CLAUSE_CHAIN (*pc);
23615 }
23616
23617 if (map_seen != 3)
23618 {
23619 if (map_seen == 0)
23620 error_at (loc,
23621 "%<#pragma omp target exit data%> must contain at least one "
23622 "%<map%> clause");
23623 return true;
23624 }
23625
23626 tree stmt = make_node (OMP_TARGET_EXIT_DATA);
23627 TREE_TYPE (stmt) = void_type_node;
23628 OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
23629 SET_EXPR_LOCATION (stmt, loc);
23630 add_stmt (stmt);
23631 return true;
23632}
23633
23634/* OpenMP 4.0:
23635 # pragma omp target target-clause[optseq] new-line
23636 structured-block */
23637
23638#define OMP_TARGET_CLAUSE_MASK \
23639 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
23640 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
23641 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
23642 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
23643 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
23644 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
23645 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
23646 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
23647 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
23648 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
23649 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
23650 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
23651 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
23652
23653static bool
23654c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
23655{
23656 location_t loc = c_parser_peek_token (parser)->location;
23657 c_parser_consume_pragma (parser);
23658 tree *pc = NULL, stmt, block;
23659
23660 if (context != pragma_stmt && context != pragma_compound)
23661 {
23662 c_parser_error (parser, gmsgid: "expected declaration specifiers");
23663 c_parser_skip_to_pragma_eol (parser);
23664 return false;
23665 }
23666
23667 if (flag_openmp)
23668 omp_requires_mask
23669 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
23670
23671 if (c_parser_next_token_is (parser, type: CPP_NAME))
23672 {
23673 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23674 enum tree_code ccode = ERROR_MARK;
23675
23676 if (strcmp (s1: p, s2: "teams") == 0)
23677 ccode = OMP_TEAMS;
23678 else if (strcmp (s1: p, s2: "parallel") == 0)
23679 ccode = OMP_PARALLEL;
23680 else if (strcmp (s1: p, s2: "simd") == 0)
23681 ccode = OMP_SIMD;
23682 if (ccode != ERROR_MARK)
23683 {
23684 tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
23685 char p_name[sizeof ("#pragma omp target teams distribute "
23686 "parallel for simd")];
23687
23688 c_parser_consume_token (parser);
23689 strcpy (dest: p_name, src: "#pragma omp target");
23690 if (!flag_openmp) /* flag_openmp_simd */
23691 {
23692 tree stmt;
23693 switch (ccode)
23694 {
23695 case OMP_TEAMS:
23696 stmt = c_parser_omp_teams (loc, parser, p_name,
23697 OMP_TARGET_CLAUSE_MASK,
23698 cclauses, if_p);
23699 break;
23700 case OMP_PARALLEL:
23701 stmt = c_parser_omp_parallel (loc, parser, p_name,
23702 OMP_TARGET_CLAUSE_MASK,
23703 cclauses, if_p);
23704 break;
23705 case OMP_SIMD:
23706 stmt = c_parser_omp_simd (loc, parser, p_name,
23707 OMP_TARGET_CLAUSE_MASK,
23708 cclauses, if_p);
23709 break;
23710 default:
23711 gcc_unreachable ();
23712 }
23713 return stmt != NULL_TREE;
23714 }
23715 keep_next_level ();
23716 tree block = c_begin_compound_stmt (true), ret;
23717 switch (ccode)
23718 {
23719 case OMP_TEAMS:
23720 ret = c_parser_omp_teams (loc, parser, p_name,
23721 OMP_TARGET_CLAUSE_MASK, cclauses,
23722 if_p);
23723 break;
23724 case OMP_PARALLEL:
23725 ret = c_parser_omp_parallel (loc, parser, p_name,
23726 OMP_TARGET_CLAUSE_MASK, cclauses,
23727 if_p);
23728 break;
23729 case OMP_SIMD:
23730 ret = c_parser_omp_simd (loc, parser, p_name,
23731 OMP_TARGET_CLAUSE_MASK, cclauses,
23732 if_p);
23733 break;
23734 default:
23735 gcc_unreachable ();
23736 }
23737 block = c_end_compound_stmt (loc, block, true);
23738 if (ret == NULL_TREE)
23739 return false;
23740 if (ccode == OMP_TEAMS)
23741 /* For combined target teams, ensure the num_teams and
23742 thread_limit clause expressions are evaluated on the host,
23743 before entering the target construct. */
23744 for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
23745 c; c = OMP_CLAUSE_CHAIN (c))
23746 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
23747 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
23748 for (int i = 0;
23749 i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
23750 if (OMP_CLAUSE_OPERAND (c, i)
23751 && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
23752 {
23753 tree expr = OMP_CLAUSE_OPERAND (c, i);
23754 tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
23755 expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
23756 expr, NULL_TREE, NULL_TREE);
23757 add_stmt (expr);
23758 OMP_CLAUSE_OPERAND (c, i) = expr;
23759 tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
23760 OMP_CLAUSE_FIRSTPRIVATE);
23761 OMP_CLAUSE_DECL (tc) = tmp;
23762 OMP_CLAUSE_CHAIN (tc)
23763 = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
23764 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
23765 }
23766 tree stmt = make_node (OMP_TARGET);
23767 TREE_TYPE (stmt) = void_type_node;
23768 OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
23769 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
23770 OMP_TARGET_BODY (stmt) = block;
23771 OMP_TARGET_COMBINED (stmt) = 1;
23772 SET_EXPR_LOCATION (stmt, loc);
23773 add_stmt (stmt);
23774 pc = &OMP_TARGET_CLAUSES (stmt);
23775 goto check_clauses;
23776 }
23777 else if (!flag_openmp) /* flag_openmp_simd */
23778 {
23779 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23780 return false;
23781 }
23782 else if (strcmp (s1: p, s2: "data") == 0)
23783 {
23784 c_parser_consume_token (parser);
23785 c_parser_omp_target_data (loc, parser, if_p);
23786 return true;
23787 }
23788 else if (strcmp (s1: p, s2: "enter") == 0)
23789 {
23790 c_parser_consume_token (parser);
23791 return c_parser_omp_target_enter_data (loc, parser, context);
23792 }
23793 else if (strcmp (s1: p, s2: "exit") == 0)
23794 {
23795 c_parser_consume_token (parser);
23796 return c_parser_omp_target_exit_data (loc, parser, context);
23797 }
23798 else if (strcmp (s1: p, s2: "update") == 0)
23799 {
23800 c_parser_consume_token (parser);
23801 return c_parser_omp_target_update (loc, parser, context);
23802 }
23803 }
23804 if (!flag_openmp) /* flag_openmp_simd */
23805 {
23806 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
23807 return false;
23808 }
23809
23810 stmt = make_node (OMP_TARGET);
23811 TREE_TYPE (stmt) = void_type_node;
23812
23813 OMP_TARGET_CLAUSES (stmt)
23814 = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
23815 where: "#pragma omp target", finish_p: false);
23816 for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
23817 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
23818 {
23819 tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
23820 OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
23821 OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
23822 OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
23823 OMP_CLAUSE_CHAIN (c) = nc;
23824 }
23825 OMP_TARGET_CLAUSES (stmt)
23826 = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
23827 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
23828
23829 pc = &OMP_TARGET_CLAUSES (stmt);
23830 keep_next_level ();
23831 block = c_begin_compound_stmt (true);
23832 add_stmt (c_parser_omp_structured_block (parser, if_p));
23833 OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
23834
23835 SET_EXPR_LOCATION (stmt, loc);
23836 add_stmt (stmt);
23837
23838check_clauses:
23839 while (*pc)
23840 {
23841 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
23842 switch (OMP_CLAUSE_MAP_KIND (*pc))
23843 {
23844 case GOMP_MAP_TO:
23845 case GOMP_MAP_ALWAYS_TO:
23846 case GOMP_MAP_PRESENT_TO:
23847 case GOMP_MAP_ALWAYS_PRESENT_TO:
23848 case GOMP_MAP_FROM:
23849 case GOMP_MAP_ALWAYS_FROM:
23850 case GOMP_MAP_PRESENT_FROM:
23851 case GOMP_MAP_ALWAYS_PRESENT_FROM:
23852 case GOMP_MAP_TOFROM:
23853 case GOMP_MAP_ALWAYS_TOFROM:
23854 case GOMP_MAP_PRESENT_TOFROM:
23855 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
23856 case GOMP_MAP_ALLOC:
23857 case GOMP_MAP_PRESENT_ALLOC:
23858 case GOMP_MAP_FIRSTPRIVATE_POINTER:
23859 case GOMP_MAP_ALWAYS_POINTER:
23860 case GOMP_MAP_ATTACH_DETACH:
23861 break;
23862 default:
23863 error_at (OMP_CLAUSE_LOCATION (*pc),
23864 "%<#pragma omp target%> with map-type other "
23865 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
23866 "on %<map%> clause");
23867 *pc = OMP_CLAUSE_CHAIN (*pc);
23868 continue;
23869 }
23870 pc = &OMP_CLAUSE_CHAIN (*pc);
23871 }
23872 cfun->has_omp_target = true;
23873 return true;
23874}
23875
23876/* OpenMP 4.0:
23877 # pragma omp declare simd declare-simd-clauses[optseq] new-line
23878
23879 OpenMP 5.0:
23880 # pragma omp declare variant (identifier) match(context-selector) new-line
23881 */
23882
23883#define OMP_DECLARE_SIMD_CLAUSE_MASK \
23884 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
23885 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
23886 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
23887 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
23888 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
23889 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
23890
23891static void
23892c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
23893{
23894 c_token *token = c_parser_peek_token (parser);
23895 gcc_assert (token->type == CPP_NAME);
23896 tree kind = token->value;
23897 gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
23898 || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
23899
23900 auto_vec<c_token> clauses;
23901 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
23902 {
23903 c_token *token = c_parser_peek_token (parser);
23904 if (token->type == CPP_EOF)
23905 {
23906 c_parser_skip_to_pragma_eol (parser);
23907 return;
23908 }
23909 clauses.safe_push (obj: *token);
23910 c_parser_consume_token (parser);
23911 }
23912 clauses.safe_push (obj: *c_parser_peek_token (parser));
23913 c_parser_skip_to_pragma_eol (parser);
23914
23915 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
23916 {
23917 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
23918 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
23919 || c_parser_peek_2nd_token (parser)->value != kind)
23920 {
23921 error ("%<#pragma omp declare %s%> must be followed by "
23922 "function declaration or definition or another "
23923 "%<#pragma omp declare %s%>",
23924 IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
23925 return;
23926 }
23927 c_parser_consume_pragma (parser);
23928 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
23929 {
23930 c_token *token = c_parser_peek_token (parser);
23931 if (token->type == CPP_EOF)
23932 {
23933 c_parser_skip_to_pragma_eol (parser);
23934 return;
23935 }
23936 clauses.safe_push (obj: *token);
23937 c_parser_consume_token (parser);
23938 }
23939 clauses.safe_push (obj: *c_parser_peek_token (parser));
23940 c_parser_skip_to_pragma_eol (parser);
23941 }
23942
23943 /* Make sure nothing tries to read past the end of the tokens. */
23944 c_token eof_token;
23945 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
23946 eof_token.type = CPP_EOF;
23947 clauses.safe_push (obj: eof_token);
23948 clauses.safe_push (obj: eof_token);
23949
23950 switch (context)
23951 {
23952 case pragma_external:
23953 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23954 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
23955 {
23956 int ext = disable_extension_diagnostics ();
23957 do
23958 c_parser_consume_token (parser);
23959 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23960 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
23961 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
23962 NULL, omp_declare_simd_clauses: &clauses);
23963 restore_extension_diagnostics (flags: ext);
23964 }
23965 else
23966 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
23967 NULL, omp_declare_simd_clauses: &clauses);
23968 break;
23969 case pragma_struct:
23970 case pragma_param:
23971 case pragma_stmt:
23972 error ("%<#pragma omp declare %s%> must be followed by "
23973 "function declaration or definition",
23974 IDENTIFIER_POINTER (kind));
23975 break;
23976 case pragma_compound:
23977 bool have_std_attrs;
23978 tree std_attrs;
23979 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
23980 if (have_std_attrs)
23981 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
23982 else
23983 std_attrs = NULL_TREE;
23984 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23985 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
23986 {
23987 int ext = disable_extension_diagnostics ();
23988 do
23989 c_parser_consume_token (parser);
23990 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
23991 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
23992 if (c_parser_next_tokens_start_declaration (parser)
23993 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
23994 {
23995 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
23996 start_attr_ok: true, NULL, omp_declare_simd_clauses: &clauses,
23997 have_attrs: have_std_attrs, attrs: std_attrs);
23998 restore_extension_diagnostics (flags: ext);
23999 break;
24000 }
24001 restore_extension_diagnostics (flags: ext);
24002 }
24003 else if (c_parser_next_tokens_start_declaration (parser))
24004 {
24005 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
24006 NULL, omp_declare_simd_clauses: &clauses, have_attrs: have_std_attrs,
24007 attrs: std_attrs);
24008 break;
24009 }
24010 error ("%<#pragma omp declare %s%> must be followed by "
24011 "function declaration or definition",
24012 IDENTIFIER_POINTER (kind));
24013 break;
24014 default:
24015 gcc_unreachable ();
24016 }
24017}
24018
24019static const char *const omp_construct_selectors[] = {
24020 "simd", "target", "teams", "parallel", "for", NULL };
24021static const char *const omp_device_selectors[] = {
24022 "kind", "isa", "arch", NULL };
24023static const char *const omp_implementation_selectors[] = {
24024 "vendor", "extension", "atomic_default_mem_order", "unified_address",
24025 "unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
24026static const char *const omp_user_selectors[] = {
24027 "condition", NULL };
24028
24029/* OpenMP 5.0:
24030
24031 trait-selector:
24032 trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
24033
24034 trait-score:
24035 score(score-expression) */
24036
24037static tree
24038c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
24039{
24040 tree ret = NULL_TREE;
24041 do
24042 {
24043 tree selector;
24044 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24045 || c_parser_next_token_is (parser, type: CPP_NAME))
24046 selector = c_parser_peek_token (parser)->value;
24047 else
24048 {
24049 c_parser_error (parser, gmsgid: "expected trait selector name");
24050 return error_mark_node;
24051 }
24052
24053 tree properties = NULL_TREE;
24054 const char *const *selectors = NULL;
24055 bool allow_score = true;
24056 bool allow_user = false;
24057 int property_limit = 0;
24058 enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
24059 CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
24060 CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
24061 switch (IDENTIFIER_POINTER (set)[0])
24062 {
24063 case 'c': /* construct */
24064 selectors = omp_construct_selectors;
24065 allow_score = false;
24066 property_limit = 1;
24067 property_kind = CTX_PROPERTY_SIMD;
24068 break;
24069 case 'd': /* device */
24070 selectors = omp_device_selectors;
24071 allow_score = false;
24072 allow_user = true;
24073 property_limit = 3;
24074 property_kind = CTX_PROPERTY_NAME_LIST;
24075 break;
24076 case 'i': /* implementation */
24077 selectors = omp_implementation_selectors;
24078 allow_user = true;
24079 property_limit = 3;
24080 property_kind = CTX_PROPERTY_NAME_LIST;
24081 break;
24082 case 'u': /* user */
24083 selectors = omp_user_selectors;
24084 property_limit = 1;
24085 property_kind = CTX_PROPERTY_EXPR;
24086 break;
24087 default:
24088 gcc_unreachable ();
24089 }
24090 for (int i = 0; ; i++)
24091 {
24092 if (selectors[i] == NULL)
24093 {
24094 if (allow_user)
24095 {
24096 property_kind = CTX_PROPERTY_USER;
24097 break;
24098 }
24099 else
24100 {
24101 error_at (c_parser_peek_token (parser)->location,
24102 "selector %qs not allowed for context selector "
24103 "set %qs", IDENTIFIER_POINTER (selector),
24104 IDENTIFIER_POINTER (set));
24105 c_parser_consume_token (parser);
24106 return error_mark_node;
24107 }
24108 }
24109 if (i == property_limit)
24110 property_kind = CTX_PROPERTY_NONE;
24111 if (strcmp (s1: selectors[i], IDENTIFIER_POINTER (selector)) == 0)
24112 break;
24113 }
24114 if (property_kind == CTX_PROPERTY_NAME_LIST
24115 && IDENTIFIER_POINTER (set)[0] == 'i'
24116 && strcmp (IDENTIFIER_POINTER (selector),
24117 s2: "atomic_default_mem_order") == 0)
24118 property_kind = CTX_PROPERTY_ID;
24119
24120 c_parser_consume_token (parser);
24121
24122 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24123 {
24124 if (property_kind == CTX_PROPERTY_NONE)
24125 {
24126 error_at (c_parser_peek_token (parser)->location,
24127 "selector %qs does not accept any properties",
24128 IDENTIFIER_POINTER (selector));
24129 return error_mark_node;
24130 }
24131
24132 matching_parens parens;
24133 parens.require_open (parser);
24134
24135 c_token *token = c_parser_peek_token (parser);
24136 if (allow_score
24137 && c_parser_next_token_is (parser, type: CPP_NAME)
24138 && strcmp (IDENTIFIER_POINTER (token->value), s2: "score") == 0
24139 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
24140 {
24141 c_parser_consume_token (parser);
24142
24143 matching_parens parens2;
24144 parens2.require_open (parser);
24145 tree score = c_parser_expr_no_commas (parser, NULL).value;
24146 parens2.skip_until_found_close (parser);
24147 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
24148 if (score != error_mark_node)
24149 {
24150 mark_exp_read (score);
24151 score = c_fully_fold (score, false, NULL);
24152 if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
24153 || TREE_CODE (score) != INTEGER_CST)
24154 error_at (token->location, "score argument must be "
24155 "constant integer expression");
24156 else if (tree_int_cst_sgn (score) < 0)
24157 error_at (token->location, "score argument must be "
24158 "non-negative");
24159 else
24160 properties = tree_cons (get_identifier (" score"),
24161 score, properties);
24162 }
24163 token = c_parser_peek_token (parser);
24164 }
24165
24166 switch (property_kind)
24167 {
24168 tree t;
24169 case CTX_PROPERTY_USER:
24170 do
24171 {
24172 t = c_parser_expr_no_commas (parser, NULL).value;
24173 if (TREE_CODE (t) == STRING_CST)
24174 properties = tree_cons (NULL_TREE, t, properties);
24175 else if (t != error_mark_node)
24176 {
24177 mark_exp_read (t);
24178 t = c_fully_fold (t, false, NULL);
24179 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
24180 || !tree_fits_shwi_p (t))
24181 error_at (token->location, "property must be "
24182 "constant integer expression or string "
24183 "literal");
24184 else
24185 properties = tree_cons (NULL_TREE, t, properties);
24186 }
24187 else
24188 return error_mark_node;
24189
24190 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24191 c_parser_consume_token (parser);
24192 else
24193 break;
24194 }
24195 while (1);
24196 break;
24197 case CTX_PROPERTY_ID:
24198 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24199 || c_parser_next_token_is (parser, type: CPP_NAME))
24200 {
24201 tree prop = c_parser_peek_token (parser)->value;
24202 c_parser_consume_token (parser);
24203 properties = tree_cons (prop, NULL_TREE, properties);
24204 }
24205 else
24206 {
24207 c_parser_error (parser, gmsgid: "expected identifier");
24208 return error_mark_node;
24209 }
24210 break;
24211 case CTX_PROPERTY_NAME_LIST:
24212 do
24213 {
24214 tree prop = NULL_TREE, value = NULL_TREE;
24215 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
24216 || c_parser_next_token_is (parser, type: CPP_NAME))
24217 {
24218 prop = c_parser_peek_token (parser)->value;
24219 c_parser_consume_token (parser);
24220 }
24221 else if (c_parser_next_token_is (parser, type: CPP_STRING))
24222 value = c_parser_string_literal (parser, translate: false,
24223 wide_ok: false).value;
24224 else
24225 {
24226 c_parser_error (parser, gmsgid: "expected identifier or "
24227 "string literal");
24228 return error_mark_node;
24229 }
24230
24231 properties = tree_cons (prop, value, properties);
24232
24233 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24234 c_parser_consume_token (parser);
24235 else
24236 break;
24237 }
24238 while (1);
24239 break;
24240 case CTX_PROPERTY_EXPR:
24241 t = c_parser_expr_no_commas (parser, NULL).value;
24242 if (t != error_mark_node)
24243 {
24244 mark_exp_read (t);
24245 t = c_fully_fold (t, false, NULL);
24246 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
24247 || !tree_fits_shwi_p (t))
24248 error_at (token->location, "property must be "
24249 "constant integer expression");
24250 else
24251 properties = tree_cons (NULL_TREE, t, properties);
24252 }
24253 else
24254 return error_mark_node;
24255 break;
24256 case CTX_PROPERTY_SIMD:
24257 if (parms == NULL_TREE)
24258 {
24259 error_at (token->location, "properties for %<simd%> "
24260 "selector may not be specified in "
24261 "%<metadirective%>");
24262 return error_mark_node;
24263 }
24264 tree c;
24265 c = c_parser_omp_all_clauses (parser,
24266 OMP_DECLARE_SIMD_CLAUSE_MASK,
24267 where: "simd", finish_p: true, nested: 2);
24268 c = c_omp_declare_simd_clauses_to_numbers (parms
24269 == error_mark_node
24270 ? NULL_TREE : parms,
24271 c);
24272 properties = c;
24273 break;
24274 default:
24275 gcc_unreachable ();
24276 }
24277
24278 parens.skip_until_found_close (parser);
24279 properties = nreverse (properties);
24280 }
24281 else if (property_kind == CTX_PROPERTY_NAME_LIST
24282 || property_kind == CTX_PROPERTY_ID
24283 || property_kind == CTX_PROPERTY_EXPR)
24284 {
24285 c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>");
24286 return error_mark_node;
24287 }
24288
24289 ret = tree_cons (selector, properties, ret);
24290
24291 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24292 c_parser_consume_token (parser);
24293 else
24294 break;
24295 }
24296 while (1);
24297
24298 return nreverse (ret);
24299}
24300
24301/* OpenMP 5.0:
24302
24303 trait-set-selector[,trait-set-selector[,...]]
24304
24305 trait-set-selector:
24306 trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
24307
24308 trait-set-selector-name:
24309 constructor
24310 device
24311 implementation
24312 user */
24313
24314static tree
24315c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
24316{
24317 tree ret = NULL_TREE;
24318 do
24319 {
24320 const char *setp = "";
24321 if (c_parser_next_token_is (parser, type: CPP_NAME))
24322 setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24323 switch (setp[0])
24324 {
24325 case 'c':
24326 if (strcmp (s1: setp, s2: "construct") == 0)
24327 setp = NULL;
24328 break;
24329 case 'd':
24330 if (strcmp (s1: setp, s2: "device") == 0)
24331 setp = NULL;
24332 break;
24333 case 'i':
24334 if (strcmp (s1: setp, s2: "implementation") == 0)
24335 setp = NULL;
24336 break;
24337 case 'u':
24338 if (strcmp (s1: setp, s2: "user") == 0)
24339 setp = NULL;
24340 break;
24341 default:
24342 break;
24343 }
24344 if (setp)
24345 {
24346 c_parser_error (parser, gmsgid: "expected %<construct%>, %<device%>, "
24347 "%<implementation%> or %<user%>");
24348 return error_mark_node;
24349 }
24350
24351 tree set = c_parser_peek_token (parser)->value;
24352 c_parser_consume_token (parser);
24353
24354 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
24355 return error_mark_node;
24356
24357 matching_braces braces;
24358 if (!braces.require_open (parser))
24359 return error_mark_node;
24360
24361 tree selectors = c_parser_omp_context_selector (parser, set, parms);
24362 if (selectors == error_mark_node)
24363 ret = error_mark_node;
24364 else if (ret != error_mark_node)
24365 ret = tree_cons (set, selectors, ret);
24366
24367 braces.skip_until_found_close (parser);
24368
24369 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24370 c_parser_consume_token (parser);
24371 else
24372 break;
24373 }
24374 while (1);
24375
24376 if (ret == error_mark_node)
24377 return ret;
24378 return nreverse (ret);
24379}
24380
24381/* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
24382 that into "omp declare variant base" attribute. */
24383
24384static void
24385c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
24386{
24387 matching_parens parens;
24388 if (!parens.require_open (parser))
24389 {
24390 fail:
24391 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24392 return;
24393 }
24394
24395 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
24396 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
24397 {
24398 c_parser_error (parser, gmsgid: "expected identifier");
24399 goto fail;
24400 }
24401
24402 c_token *token = c_parser_peek_token (parser);
24403 tree variant = lookup_name (token->value);
24404
24405 if (variant == NULL_TREE)
24406 {
24407 undeclared_variable (token->location, token->value);
24408 variant = error_mark_node;
24409 }
24410
24411 c_parser_consume_token (parser);
24412
24413 parens.require_close (parser);
24414
24415 if (c_parser_next_token_is (parser, type: CPP_COMMA)
24416 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24417 c_parser_consume_token (parser);
24418
24419 const char *clause = "";
24420 location_t match_loc = c_parser_peek_token (parser)->location;
24421 if (c_parser_next_token_is (parser, type: CPP_NAME))
24422 clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24423 if (strcmp (s1: clause, s2: "match"))
24424 {
24425 c_parser_error (parser, gmsgid: "expected %<match%>");
24426 goto fail;
24427 }
24428
24429 c_parser_consume_token (parser);
24430
24431 if (!parens.require_open (parser))
24432 goto fail;
24433
24434 if (parms == NULL_TREE)
24435 parms = error_mark_node;
24436
24437 tree ctx = c_parser_omp_context_selector_specification (parser, parms);
24438 if (ctx == error_mark_node)
24439 goto fail;
24440 ctx = omp_check_context_selector (loc: match_loc, ctx);
24441 if (ctx != error_mark_node && variant != error_mark_node)
24442 {
24443 if (TREE_CODE (variant) != FUNCTION_DECL)
24444 {
24445 error_at (token->location, "variant %qD is not a function", variant);
24446 variant = error_mark_node;
24447 }
24448 else if (omp_get_context_selector (ctx, "construct", "simd") == NULL_TREE
24449 && !comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
24450 {
24451 error_at (token->location, "variant %qD and base %qD have "
24452 "incompatible types", variant, fndecl);
24453 variant = error_mark_node;
24454 }
24455 else if (fndecl_built_in_p (node: variant)
24456 && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24457 s2: "__builtin_", n: strlen (s: "__builtin_")) == 0
24458 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24459 s2: "__sync_", n: strlen (s: "__sync_")) == 0
24460 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
24461 s2: "__atomic_", n: strlen (s: "__atomic_")) == 0))
24462 {
24463 error_at (token->location, "variant %qD is a built-in", variant);
24464 variant = error_mark_node;
24465 }
24466 if (variant != error_mark_node)
24467 {
24468 C_DECL_USED (variant) = 1;
24469 tree construct = omp_get_context_selector (ctx, "construct", NULL);
24470 omp_mark_declare_variant (loc: match_loc, variant, construct);
24471 if (omp_context_selector_matches (ctx))
24472 {
24473 tree attr
24474 = tree_cons (get_identifier ("omp declare variant base"),
24475 build_tree_list (variant, ctx),
24476 DECL_ATTRIBUTES (fndecl));
24477 DECL_ATTRIBUTES (fndecl) = attr;
24478 }
24479 }
24480 }
24481
24482 parens.require_close (parser);
24483 c_parser_skip_to_pragma_eol (parser);
24484}
24485
24486/* Finalize #pragma omp declare simd or #pragma omp declare variant
24487 clauses after FNDECL has been parsed, and put that into "omp declare simd"
24488 or "omp declare variant base" attribute. */
24489
24490static void
24491c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
24492 vec<c_token> *pclauses)
24493{
24494 vec<c_token> &clauses = *pclauses;
24495
24496 /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
24497 indicates error has been reported and CPP_PRAGMA that
24498 c_finish_omp_declare_simd has already processed the tokens. */
24499 if (clauses.exists () && clauses[0].type == CPP_EOF)
24500 return;
24501 const char *kind = "simd";
24502 if (clauses.exists ()
24503 && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
24504 kind = IDENTIFIER_POINTER (clauses[0].value);
24505 gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
24506 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
24507 {
24508 error ("%<#pragma omp declare %s%> not immediately followed by "
24509 "a function declaration or definition", kind);
24510 clauses[0].type = CPP_EOF;
24511 return;
24512 }
24513 if (clauses.exists () && clauses[0].type != CPP_NAME)
24514 {
24515 error_at (DECL_SOURCE_LOCATION (fndecl),
24516 "%<#pragma omp declare %s%> not immediately followed by "
24517 "a single function declaration or definition", kind);
24518 clauses[0].type = CPP_EOF;
24519 return;
24520 }
24521
24522 if (parms == NULL_TREE)
24523 parms = DECL_ARGUMENTS (fndecl);
24524
24525 unsigned int tokens_avail = parser->tokens_avail;
24526 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
24527
24528 parser->tokens = clauses.address ();
24529 parser->tokens_avail = clauses.length ();
24530
24531 /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
24532 while (parser->tokens_avail > 3)
24533 {
24534 c_token *token = c_parser_peek_token (parser);
24535 gcc_assert (token->type == CPP_NAME);
24536 kind = IDENTIFIER_POINTER (token->value);
24537 c_parser_consume_token (parser);
24538 parser->in_pragma = true;
24539
24540 if (strcmp (s1: kind, s2: "simd") == 0)
24541 {
24542 tree c;
24543 c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
24544 where: "#pragma omp declare simd");
24545 c = c_omp_declare_simd_clauses_to_numbers (parms, c);
24546 if (c != NULL_TREE)
24547 c = tree_cons (NULL_TREE, c, NULL_TREE);
24548 c = build_tree_list (get_identifier ("omp declare simd"), c);
24549 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
24550 DECL_ATTRIBUTES (fndecl) = c;
24551 }
24552 else
24553 {
24554 gcc_assert (strcmp (kind, "variant") == 0);
24555 c_finish_omp_declare_variant (parser, fndecl, parms);
24556 }
24557 }
24558
24559 parser->tokens = &parser->tokens_buf[0];
24560 parser->tokens_avail = tokens_avail;
24561 if (clauses.exists ())
24562 clauses[0].type = CPP_PRAGMA;
24563}
24564
24565/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
24566 a threadprivate, groupprivate, allocate or declare target directive,
24567 return true and parse it for DECL. */
24568
24569bool
24570c_maybe_parse_omp_decl (tree decl, tree d)
24571{
24572 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
24573 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
24574 c_token *first = toks->address ();
24575 c_token *last = first + toks->length ();
24576 const char *directive[3] = {};
24577 for (int j = 0; j < 3; j++)
24578 {
24579 tree id = NULL_TREE;
24580 if (first + j == last)
24581 break;
24582 if (first[j].type == CPP_NAME)
24583 id = first[j].value;
24584 else if (first[j].type == CPP_KEYWORD)
24585 id = ridpointers[(int) first[j].keyword];
24586 else
24587 break;
24588 directive[j] = IDENTIFIER_POINTER (id);
24589 }
24590 const c_omp_directive *dir = NULL;
24591 if (directive[0])
24592 dir = c_omp_categorize_directive (directive[0], directive[1],
24593 directive[2]);
24594 if (dir == NULL)
24595 {
24596 error_at (first->location,
24597 "unknown OpenMP directive name in "
24598 "%qs attribute argument", "omp::decl");
24599 return false;
24600 }
24601 if (dir->id != PRAGMA_OMP_THREADPRIVATE
24602 /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
24603 && dir->id != PRAGMA_OMP_ALLOCATE
24604 && (dir->id != PRAGMA_OMP_DECLARE
24605 || strcmp (s1: directive[1], s2: "target") != 0))
24606 return false;
24607
24608 if (!flag_openmp && !dir->simd)
24609 return true;
24610
24611 c_parser *parser = the_parser;
24612 unsigned int tokens_avail = parser->tokens_avail;
24613 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
24614 toks = NULL;
24615 vec_safe_reserve (v&: toks, nelems: last - first + 2, exact: true);
24616 c_token tok = {};
24617 tok.type = CPP_PRAGMA;
24618 tok.keyword = RID_MAX;
24619 tok.pragma_kind = pragma_kind (dir->id);
24620 tok.location = first->location;
24621 toks->quick_push (obj: tok);
24622 while (++first < last)
24623 toks->quick_push (obj: *first);
24624 tok = {};
24625 tok.type = CPP_PRAGMA_EOL;
24626 tok.keyword = RID_MAX;
24627 tok.location = last[-1].location;
24628 toks->quick_push (obj: tok);
24629 tok = {};
24630 tok.type = CPP_EOF;
24631 tok.keyword = RID_MAX;
24632 tok.location = last[-1].location;
24633 tok.flags = tokens_avail;
24634 toks->quick_push (obj: tok);
24635 parser->in_omp_decl_attribute = decl;
24636 parser->tokens = toks->address ();
24637 parser->tokens_avail = toks->length ();
24638 parser->in_omp_attribute_pragma = toks;
24639 c_parser_pragma (parser, context: pragma_external, NULL);
24640 parser->in_omp_decl_attribute = NULL_TREE;
24641 return true;
24642}
24643
24644/* OpenMP 4.0:
24645 # pragma omp declare target new-line
24646 declarations and definitions
24647 # pragma omp end declare target new-line
24648
24649 OpenMP 4.5:
24650 # pragma omp declare target ( extended-list ) new-line
24651
24652 # pragma omp declare target declare-target-clauses[seq] new-line */
24653
24654#define OMP_DECLARE_TARGET_CLAUSE_MASK \
24655 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
24656 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
24657 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
24658 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
24659 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
24660
24661static void
24662c_parser_omp_declare_target (c_parser *parser)
24663{
24664 tree clauses = NULL_TREE;
24665 int device_type = 0;
24666 bool indirect = false;
24667 bool only_device_type_or_indirect = true;
24668 if (c_parser_next_token_is (parser, type: CPP_NAME)
24669 || (c_parser_next_token_is (parser, type: CPP_COMMA)
24670 && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
24671 clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
24672 where: "#pragma omp declare target");
24673 else if (parser->in_omp_decl_attribute
24674 || c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
24675 {
24676 clauses = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
24677 list: clauses);
24678 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24679 c_parser_skip_to_pragma_eol (parser);
24680 }
24681 else
24682 {
24683 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
24684 c_parser_skip_to_pragma_eol (parser);
24685 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: -1, .indirect: 0 };
24686 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
24687 return;
24688 }
24689 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
24690 {
24691 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
24692 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
24693 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
24694 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
24695 }
24696 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
24697 {
24698 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
24699 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
24700 continue;
24701 tree t = OMP_CLAUSE_DECL (c), id;
24702 tree at1 = lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (t));
24703 tree at2 = lookup_attribute (attr_name: "omp declare target link",
24704 DECL_ATTRIBUTES (t));
24705 only_device_type_or_indirect = false;
24706 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
24707 {
24708 id = get_identifier ("omp declare target link");
24709 std::swap (a&: at1, b&: at2);
24710 }
24711 else
24712 id = get_identifier ("omp declare target");
24713 if (at2)
24714 {
24715 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
24716 error_at (OMP_CLAUSE_LOCATION (c),
24717 "%qD specified both in declare target %<link%> and %qs"
24718 " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
24719 else
24720 error_at (OMP_CLAUSE_LOCATION (c),
24721 "%qD specified both in declare target %<link%> and "
24722 "%<to%> or %<enter%> clauses", t);
24723 continue;
24724 }
24725 if (!at1)
24726 {
24727 DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
24728 if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
24729 continue;
24730
24731 symtab_node *node = symtab_node::get (decl: t);
24732 if (node != NULL)
24733 {
24734 node->offloadable = 1;
24735 if (ENABLE_OFFLOADING)
24736 {
24737 g->have_offload = true;
24738 if (is_a <varpool_node *> (p: node))
24739 vec_safe_push (v&: offload_vars, obj: t);
24740 }
24741 }
24742 }
24743 if (TREE_CODE (t) != FUNCTION_DECL)
24744 continue;
24745 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
24746 {
24747 tree at3 = lookup_attribute (attr_name: "omp declare target host",
24748 DECL_ATTRIBUTES (t));
24749 if (at3 == NULL_TREE)
24750 {
24751 id = get_identifier ("omp declare target host");
24752 DECL_ATTRIBUTES (t)
24753 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
24754 }
24755 }
24756 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
24757 {
24758 tree at3 = lookup_attribute (attr_name: "omp declare target nohost",
24759 DECL_ATTRIBUTES (t));
24760 if (at3 == NULL_TREE)
24761 {
24762 id = get_identifier ("omp declare target nohost");
24763 DECL_ATTRIBUTES (t)
24764 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
24765 }
24766 }
24767 if (indirect)
24768 {
24769 tree at4 = lookup_attribute (attr_name: "omp declare target indirect",
24770 DECL_ATTRIBUTES (t));
24771 if (at4 == NULL_TREE)
24772 {
24773 id = get_identifier ("omp declare target indirect");
24774 DECL_ATTRIBUTES (t)
24775 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
24776 }
24777 }
24778 }
24779 if ((device_type || indirect) && only_device_type_or_indirect)
24780 error_at (OMP_CLAUSE_LOCATION (clauses),
24781 "directive with only %<device_type%> or %<indirect%> clauses");
24782 if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
24783 error_at (OMP_CLAUSE_LOCATION (clauses),
24784 "%<device_type%> clause must specify 'any' when used with "
24785 "an %<indirect%> clause");
24786}
24787
24788/* OpenMP 5.1
24789 #pragma omp begin assumes clauses[optseq] new-line
24790
24791 #pragma omp begin declare target clauses[optseq] new-line */
24792
24793#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
24794 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
24795 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
24796
24797static void
24798c_parser_omp_begin (c_parser *parser)
24799{
24800 const char *p = "";
24801 c_parser_consume_pragma (parser);
24802 if (c_parser_next_token_is (parser, type: CPP_NAME))
24803 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24804 if (strcmp (s1: p, s2: "declare") == 0)
24805 {
24806 c_parser_consume_token (parser);
24807 p = "";
24808 if (c_parser_next_token_is (parser, type: CPP_NAME))
24809 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24810 if (strcmp (s1: p, s2: "target") == 0)
24811 {
24812 c_parser_consume_token (parser);
24813 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
24814 tree clauses
24815 = c_parser_omp_all_clauses (parser,
24816 OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
24817 where: "#pragma omp begin declare target");
24818 int device_type = 0;
24819 int indirect = 0;
24820 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
24821 {
24822 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
24823 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
24824 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
24825 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
24826 }
24827 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: device_type,
24828 .indirect: indirect };
24829 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
24830 }
24831 else
24832 {
24833 c_parser_error (parser, gmsgid: "expected %<target%>");
24834 c_parser_skip_to_pragma_eol (parser);
24835 }
24836 }
24837 else if (strcmp (s1: p, s2: "assumes") == 0)
24838 {
24839 c_parser_consume_token (parser);
24840 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
24841 c_parser_omp_assumption_clauses (parser, false);
24842 struct c_omp_begin_assumes_data a = { .attr_syntax: attr_syntax };
24843 vec_safe_push (v&: current_omp_begin_assumes, obj: a);
24844 }
24845 else
24846 {
24847 c_parser_error (parser, gmsgid: "expected %<declare target%> or %<assumes%>");
24848 c_parser_skip_to_pragma_eol (parser);
24849 }
24850}
24851
24852/* OpenMP 4.0
24853 #pragma omp end declare target
24854
24855 OpenMP 5.1
24856 #pragma omp end assumes */
24857
24858static void
24859c_parser_omp_end (c_parser *parser)
24860{
24861 location_t loc = c_parser_peek_token (parser)->location;
24862 const char *p = "";
24863 c_parser_consume_pragma (parser);
24864 if (c_parser_next_token_is (parser, type: CPP_NAME))
24865 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24866 if (strcmp (s1: p, s2: "declare") == 0)
24867 {
24868 c_parser_consume_token (parser);
24869 if (c_parser_next_token_is (parser, type: CPP_NAME)
24870 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
24871 s2: "target") == 0)
24872 c_parser_consume_token (parser);
24873 else
24874 {
24875 c_parser_error (parser, gmsgid: "expected %<target%>");
24876 c_parser_skip_to_pragma_eol (parser);
24877 return;
24878 }
24879 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
24880 c_parser_skip_to_pragma_eol (parser);
24881 if (!vec_safe_length (v: current_omp_declare_target_attribute))
24882 error_at (loc, "%<#pragma omp end declare target%> without "
24883 "corresponding %<#pragma omp declare target%> or "
24884 "%<#pragma omp begin declare target%>");
24885 else
24886 {
24887 c_omp_declare_target_attr
24888 a = current_omp_declare_target_attribute->pop ();
24889 if (a.attr_syntax != attr_syntax)
24890 {
24891 if (a.attr_syntax)
24892 error_at (loc,
24893 "%qs in attribute syntax terminated "
24894 "with %qs in pragma syntax",
24895 a.device_type >= 0 ? "begin declare target"
24896 : "declare target",
24897 "end declare target");
24898 else
24899 error_at (loc,
24900 "%qs in pragma syntax terminated "
24901 "with %qs in attribute syntax",
24902 a.device_type >= 0 ? "begin declare target"
24903 : "declare target",
24904 "end declare target");
24905 }
24906 }
24907 }
24908 else if (strcmp (s1: p, s2: "assumes") == 0)
24909 {
24910 c_parser_consume_token (parser);
24911 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
24912 c_parser_skip_to_pragma_eol (parser);
24913 if (!vec_safe_length (v: current_omp_begin_assumes))
24914 error_at (loc, "%qs without corresponding %qs",
24915 "#pragma omp end assumes", "#pragma omp begin assumes");
24916 else
24917 {
24918 c_omp_begin_assumes_data
24919 a = current_omp_begin_assumes->pop ();
24920 if (a.attr_syntax != attr_syntax)
24921 {
24922 if (a.attr_syntax)
24923 error_at (loc,
24924 "%qs in attribute syntax terminated "
24925 "with %qs in pragma syntax",
24926 "begin assumes", "end assumes");
24927 else
24928 error_at (loc,
24929 "%qs in pragma syntax terminated "
24930 "with %qs in attribute syntax",
24931 "begin assumes", "end assumes");
24932 }
24933 }
24934 }
24935 else
24936 {
24937 c_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>");
24938 c_parser_skip_to_pragma_eol (parser);
24939 }
24940}
24941
24942/* OpenMP 4.0
24943 #pragma omp declare reduction (reduction-id : typename-list : expression) \
24944 initializer-clause[opt] new-line
24945
24946 initializer-clause:
24947 initializer (omp_priv = initializer)
24948 initializer (function-name (argument-list)) */
24949
24950static void
24951c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
24952{
24953 unsigned int tokens_avail = 0, i;
24954 c_token *saved_tokens = NULL;
24955 vec<tree> types = vNULL;
24956 vec<c_token> clauses = vNULL;
24957 enum tree_code reduc_code = ERROR_MARK;
24958 tree reduc_id = NULL_TREE;
24959 tree type;
24960 location_t rloc = c_parser_peek_token (parser)->location;
24961
24962 if (context == pragma_struct || context == pragma_param)
24963 {
24964 error ("%<#pragma omp declare reduction%> not at file or block scope");
24965 goto fail;
24966 }
24967
24968 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
24969 goto fail;
24970
24971 switch (c_parser_peek_token (parser)->type)
24972 {
24973 case CPP_PLUS:
24974 reduc_code = PLUS_EXPR;
24975 break;
24976 case CPP_MULT:
24977 reduc_code = MULT_EXPR;
24978 break;
24979 case CPP_MINUS:
24980 reduc_code = MINUS_EXPR;
24981 break;
24982 case CPP_AND:
24983 reduc_code = BIT_AND_EXPR;
24984 break;
24985 case CPP_XOR:
24986 reduc_code = BIT_XOR_EXPR;
24987 break;
24988 case CPP_OR:
24989 reduc_code = BIT_IOR_EXPR;
24990 break;
24991 case CPP_AND_AND:
24992 reduc_code = TRUTH_ANDIF_EXPR;
24993 break;
24994 case CPP_OR_OR:
24995 reduc_code = TRUTH_ORIF_EXPR;
24996 break;
24997 case CPP_NAME:
24998 const char *p;
24999 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25000 if (strcmp (s1: p, s2: "min") == 0)
25001 {
25002 reduc_code = MIN_EXPR;
25003 break;
25004 }
25005 if (strcmp (s1: p, s2: "max") == 0)
25006 {
25007 reduc_code = MAX_EXPR;
25008 break;
25009 }
25010 reduc_id = c_parser_peek_token (parser)->value;
25011 break;
25012 default:
25013 c_parser_error (parser,
25014 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
25015 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
25016 goto fail;
25017 }
25018
25019 tree orig_reduc_id, reduc_decl;
25020 orig_reduc_id = reduc_id;
25021 reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
25022 reduc_decl = c_omp_reduction_decl (reduc_id);
25023 c_parser_consume_token (parser);
25024
25025 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
25026 goto fail;
25027
25028 while (true)
25029 {
25030 location_t loc = c_parser_peek_token (parser)->location;
25031 struct c_type_name *ctype = c_parser_type_name (parser);
25032 if (ctype != NULL)
25033 {
25034 type = groktypename (ctype, NULL, NULL);
25035 if (type == error_mark_node)
25036 ;
25037 else if ((INTEGRAL_TYPE_P (type)
25038 || SCALAR_FLOAT_TYPE_P (type)
25039 || TREE_CODE (type) == COMPLEX_TYPE)
25040 && orig_reduc_id == NULL_TREE)
25041 error_at (loc, "predeclared arithmetic type in "
25042 "%<#pragma omp declare reduction%>");
25043 else if (TREE_CODE (type) == FUNCTION_TYPE
25044 || TREE_CODE (type) == ARRAY_TYPE)
25045 error_at (loc, "function or array type in "
25046 "%<#pragma omp declare reduction%>");
25047 else if (TYPE_ATOMIC (type))
25048 error_at (loc, "%<_Atomic%> qualified type in "
25049 "%<#pragma omp declare reduction%>");
25050 else if (TYPE_QUALS_NO_ADDR_SPACE (type))
25051 error_at (loc, "const, volatile or restrict qualified type in "
25052 "%<#pragma omp declare reduction%>");
25053 else
25054 {
25055 tree t;
25056 for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
25057 if (comptypes (TREE_PURPOSE (t), type))
25058 {
25059 error_at (loc, "redeclaration of %qs "
25060 "%<#pragma omp declare reduction%> for "
25061 "type %qT",
25062 IDENTIFIER_POINTER (reduc_id)
25063 + sizeof ("omp declare reduction ") - 1,
25064 type);
25065 location_t ploc
25066 = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
25067 0));
25068 error_at (ploc, "previous %<#pragma omp declare "
25069 "reduction%>");
25070 break;
25071 }
25072 if (t == NULL_TREE)
25073 types.safe_push (obj: type);
25074 }
25075 if (c_parser_next_token_is (parser, type: CPP_COMMA))
25076 c_parser_consume_token (parser);
25077 else
25078 break;
25079 }
25080 else
25081 break;
25082 }
25083
25084 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>")
25085 || types.is_empty ())
25086 {
25087 fail:
25088 clauses.release ();
25089 types.release ();
25090 while (true)
25091 {
25092 c_token *token = c_parser_peek_token (parser);
25093 if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
25094 break;
25095 c_parser_consume_token (parser);
25096 }
25097 c_parser_skip_to_pragma_eol (parser);
25098 return;
25099 }
25100
25101 if (types.length () > 1)
25102 {
25103 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25104 {
25105 c_token *token = c_parser_peek_token (parser);
25106 if (token->type == CPP_EOF)
25107 goto fail;
25108 clauses.safe_push (obj: *token);
25109 c_parser_consume_token (parser);
25110 }
25111 clauses.safe_push (obj: *c_parser_peek_token (parser));
25112 c_parser_skip_to_pragma_eol (parser);
25113
25114 /* Make sure nothing tries to read past the end of the tokens. */
25115 c_token eof_token;
25116 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
25117 eof_token.type = CPP_EOF;
25118 clauses.safe_push (obj: eof_token);
25119 clauses.safe_push (obj: eof_token);
25120 }
25121
25122 int errs = errorcount;
25123 FOR_EACH_VEC_ELT (types, i, type)
25124 {
25125 saved_tokens = parser->tokens;
25126 tokens_avail = parser->tokens_avail;
25127 if (!clauses.is_empty ())
25128 {
25129 parser->tokens = clauses.address ();
25130 parser->tokens_avail = clauses.length ();
25131 parser->in_pragma = true;
25132 }
25133
25134 bool nested = current_function_decl != NULL_TREE;
25135 if (nested)
25136 c_push_function_context ();
25137 tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
25138 reduc_id, default_function_type);
25139 current_function_decl = fndecl;
25140 allocate_struct_function (fndecl, true);
25141 push_scope ();
25142 tree stmt = push_stmt_list ();
25143 /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
25144 warn about these. */
25145 tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
25146 get_identifier ("omp_out"), type);
25147 DECL_ARTIFICIAL (omp_out) = 1;
25148 DECL_CONTEXT (omp_out) = fndecl;
25149 pushdecl (omp_out);
25150 tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
25151 get_identifier ("omp_in"), type);
25152 DECL_ARTIFICIAL (omp_in) = 1;
25153 DECL_CONTEXT (omp_in) = fndecl;
25154 pushdecl (omp_in);
25155 struct c_expr combiner = c_parser_expression (parser);
25156 struct c_expr initializer;
25157 tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
25158 bool bad = false;
25159 initializer.set_error ();
25160 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
25161 bad = true;
25162 else if (c_parser_next_token_is (parser, type: CPP_COMMA)
25163 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25164 c_parser_consume_token (parser);
25165 if (!bad
25166 && (c_parser_next_token_is (parser, type: CPP_NAME)
25167 && strcmp (IDENTIFIER_POINTER
25168 (c_parser_peek_token (parser)->value),
25169 s2: "initializer") == 0))
25170 {
25171 c_parser_consume_token (parser);
25172 pop_scope ();
25173 push_scope ();
25174 omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
25175 get_identifier ("omp_priv"), type);
25176 DECL_ARTIFICIAL (omp_priv) = 1;
25177 DECL_INITIAL (omp_priv) = error_mark_node;
25178 DECL_CONTEXT (omp_priv) = fndecl;
25179 pushdecl (omp_priv);
25180 omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
25181 get_identifier ("omp_orig"), type);
25182 DECL_ARTIFICIAL (omp_orig) = 1;
25183 DECL_CONTEXT (omp_orig) = fndecl;
25184 pushdecl (omp_orig);
25185 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
25186 bad = true;
25187 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
25188 {
25189 c_parser_error (parser, gmsgid: "expected %<omp_priv%> or "
25190 "function-name");
25191 bad = true;
25192 }
25193 else if (strcmp (IDENTIFIER_POINTER
25194 (c_parser_peek_token (parser)->value),
25195 s2: "omp_priv") != 0)
25196 {
25197 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
25198 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
25199 {
25200 c_parser_error (parser, gmsgid: "expected function-name %<(%>");
25201 bad = true;
25202 }
25203 else
25204 initializer = c_parser_postfix_expression (parser);
25205 if (initializer.value
25206 && TREE_CODE (initializer.value) == CALL_EXPR)
25207 {
25208 int j;
25209 tree c = initializer.value;
25210 for (j = 0; j < call_expr_nargs (c); j++)
25211 {
25212 tree a = CALL_EXPR_ARG (c, j);
25213 STRIP_NOPS (a);
25214 if (TREE_CODE (a) == ADDR_EXPR
25215 && TREE_OPERAND (a, 0) == omp_priv)
25216 break;
25217 }
25218 if (j == call_expr_nargs (c))
25219 error ("one of the initializer call arguments should be "
25220 "%<&omp_priv%>");
25221 }
25222 }
25223 else
25224 {
25225 c_parser_consume_token (parser);
25226 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
25227 bad = true;
25228 else
25229 {
25230 tree st = push_stmt_list ();
25231 location_t loc = c_parser_peek_token (parser)->location;
25232 rich_location richloc (line_table, loc);
25233 start_init (omp_priv, NULL_TREE, false, false, &richloc);
25234 struct c_expr init = c_parser_initializer (parser, decl: omp_priv);
25235 finish_init ();
25236 finish_decl (omp_priv, loc, init.value,
25237 init.original_type, NULL_TREE);
25238 pop_stmt_list (st);
25239 }
25240 }
25241 if (!bad
25242 && !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
25243 bad = true;
25244 }
25245
25246 if (!bad)
25247 {
25248 c_parser_skip_to_pragma_eol (parser);
25249
25250 tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
25251 DECL_INITIAL (reduc_decl));
25252 DECL_INITIAL (reduc_decl) = t;
25253 DECL_SOURCE_LOCATION (omp_out) = rloc;
25254 TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
25255 TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
25256 TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
25257 walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
25258 &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
25259 if (omp_priv)
25260 {
25261 DECL_SOURCE_LOCATION (omp_priv) = rloc;
25262 TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
25263 TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
25264 TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
25265 walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
25266 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
25267 walk_tree (&DECL_INITIAL (omp_priv),
25268 c_check_omp_declare_reduction_r,
25269 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
25270 }
25271 }
25272
25273 pop_stmt_list (stmt);
25274 pop_scope ();
25275 if (cfun->language != NULL)
25276 {
25277 ggc_free (cfun->language);
25278 cfun->language = NULL;
25279 }
25280 set_cfun (NULL);
25281 current_function_decl = NULL_TREE;
25282 if (nested)
25283 c_pop_function_context ();
25284
25285 if (!clauses.is_empty ())
25286 {
25287 parser->tokens = saved_tokens;
25288 parser->tokens_avail = tokens_avail;
25289 }
25290 if (bad)
25291 goto fail;
25292 if (errs != errorcount)
25293 break;
25294 }
25295
25296 clauses.release ();
25297 types.release ();
25298}
25299
25300
25301/* OpenMP 4.0
25302 #pragma omp declare simd declare-simd-clauses[optseq] new-line
25303 #pragma omp declare reduction (reduction-id : typename-list : expression) \
25304 initializer-clause[opt] new-line
25305 #pragma omp declare target new-line
25306
25307 OpenMP 5.0
25308 #pragma omp declare variant (identifier) match (context-selector) */
25309
25310static bool
25311c_parser_omp_declare (c_parser *parser, enum pragma_context context)
25312{
25313 c_parser_consume_pragma (parser);
25314 if (c_parser_next_token_is (parser, type: CPP_NAME))
25315 {
25316 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25317 if (strcmp (s1: p, s2: "simd") == 0)
25318 {
25319 /* c_parser_consume_token (parser); done in
25320 c_parser_omp_declare_simd. */
25321 c_parser_omp_declare_simd (parser, context);
25322 return true;
25323 }
25324 if (strcmp (s1: p, s2: "reduction") == 0)
25325 {
25326 c_parser_consume_token (parser);
25327 c_parser_omp_declare_reduction (parser, context);
25328 return false;
25329 }
25330 if (!flag_openmp) /* flag_openmp_simd */
25331 {
25332 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25333 return false;
25334 }
25335 if (strcmp (s1: p, s2: "target") == 0)
25336 {
25337 c_parser_consume_token (parser);
25338 c_parser_omp_declare_target (parser);
25339 return false;
25340 }
25341 if (strcmp (s1: p, s2: "variant") == 0)
25342 {
25343 /* c_parser_consume_token (parser); done in
25344 c_parser_omp_declare_simd. */
25345 c_parser_omp_declare_simd (parser, context);
25346 return true;
25347 }
25348 }
25349
25350 c_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, "
25351 "%<target%> or %<variant%>");
25352 c_parser_skip_to_pragma_eol (parser);
25353 return false;
25354}
25355
25356/* OpenMP 5.0
25357 #pragma omp requires clauses[optseq] new-line */
25358
25359static void
25360c_parser_omp_requires (c_parser *parser)
25361{
25362 enum omp_requires new_req = (enum omp_requires) 0;
25363
25364 c_parser_consume_pragma (parser);
25365
25366 location_t loc = c_parser_peek_token (parser)->location;
25367 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25368 {
25369 if (c_parser_next_token_is (parser, type: CPP_COMMA)
25370 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25371 c_parser_consume_token (parser);
25372
25373 if (c_parser_next_token_is (parser, type: CPP_NAME))
25374 {
25375 const char *p
25376 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25377 location_t cloc = c_parser_peek_token (parser)->location;
25378 enum omp_requires this_req = (enum omp_requires) 0;
25379
25380 if (!strcmp (s1: p, s2: "unified_address"))
25381 this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
25382 else if (!strcmp (s1: p, s2: "unified_shared_memory"))
25383 this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
25384 else if (!strcmp (s1: p, s2: "dynamic_allocators"))
25385 this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
25386 else if (!strcmp (s1: p, s2: "reverse_offload"))
25387 this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
25388 else if (!strcmp (s1: p, s2: "atomic_default_mem_order"))
25389 {
25390 c_parser_consume_token (parser);
25391
25392 matching_parens parens;
25393 if (parens.require_open (parser))
25394 {
25395 if (c_parser_next_token_is (parser, type: CPP_NAME))
25396 {
25397 tree v = c_parser_peek_token (parser)->value;
25398 p = IDENTIFIER_POINTER (v);
25399
25400 if (!strcmp (s1: p, s2: "seq_cst"))
25401 this_req
25402 = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
25403 else if (!strcmp (s1: p, s2: "relaxed"))
25404 this_req
25405 = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
25406 else if (!strcmp (s1: p, s2: "acq_rel"))
25407 this_req
25408 = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
25409 }
25410 if (this_req == 0)
25411 {
25412 error_at (c_parser_peek_token (parser)->location,
25413 "expected %<seq_cst%>, %<relaxed%> or "
25414 "%<acq_rel%>");
25415 switch (c_parser_peek_token (parser)->type)
25416 {
25417 case CPP_EOF:
25418 case CPP_PRAGMA_EOL:
25419 case CPP_CLOSE_PAREN:
25420 break;
25421 default:
25422 if (c_parser_peek_2nd_token (parser)->type
25423 == CPP_CLOSE_PAREN)
25424 c_parser_consume_token (parser);
25425 break;
25426 }
25427 }
25428 else
25429 c_parser_consume_token (parser);
25430
25431 parens.skip_until_found_close (parser);
25432 if (this_req == 0)
25433 {
25434 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25435 return;
25436 }
25437 }
25438 p = NULL;
25439 }
25440 else
25441 {
25442 error_at (cloc, "expected %<unified_address%>, "
25443 "%<unified_shared_memory%>, "
25444 "%<dynamic_allocators%>, "
25445 "%<reverse_offload%> "
25446 "or %<atomic_default_mem_order%> clause");
25447 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25448 return;
25449 }
25450 if (p)
25451 c_parser_consume_token (parser);
25452 if (this_req)
25453 {
25454 if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25455 {
25456 if ((this_req & new_req) != 0)
25457 error_at (cloc, "too many %qs clauses", p);
25458 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
25459 && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
25460 error_at (cloc, "%qs clause used lexically after first "
25461 "target construct or offloading API", p);
25462 }
25463 else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25464 {
25465 error_at (cloc, "too many %qs clauses",
25466 "atomic_default_mem_order");
25467 this_req = (enum omp_requires) 0;
25468 }
25469 else if ((omp_requires_mask
25470 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
25471 {
25472 error_at (cloc, "more than one %<atomic_default_mem_order%>"
25473 " clause in a single compilation unit");
25474 this_req
25475 = (enum omp_requires)
25476 (omp_requires_mask
25477 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
25478 }
25479 else if ((omp_requires_mask
25480 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
25481 error_at (cloc, "%<atomic_default_mem_order%> clause used "
25482 "lexically after first %<atomic%> construct "
25483 "without memory order clause");
25484 new_req = (enum omp_requires) (new_req | this_req);
25485 omp_requires_mask
25486 = (enum omp_requires) (omp_requires_mask | this_req);
25487 continue;
25488 }
25489 }
25490 break;
25491 }
25492 c_parser_skip_to_pragma_eol (parser);
25493
25494 if (new_req == 0)
25495 error_at (loc, "%<pragma omp requires%> requires at least one clause");
25496}
25497
25498/* Helper function for c_parser_omp_taskloop.
25499 Disallow zero sized or potentially zero sized task reductions. */
25500
25501static tree
25502c_finish_taskloop_clauses (tree clauses)
25503{
25504 tree *pc = &clauses;
25505 for (tree c = clauses; c; c = *pc)
25506 {
25507 bool remove = false;
25508 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
25509 {
25510 tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
25511 if (integer_zerop (TYPE_SIZE_UNIT (type)))
25512 {
25513 error_at (OMP_CLAUSE_LOCATION (c),
25514 "zero sized type %qT in %<reduction%> clause", type);
25515 remove = true;
25516 }
25517 else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
25518 {
25519 error_at (OMP_CLAUSE_LOCATION (c),
25520 "variable sized type %qT in %<reduction%> clause",
25521 type);
25522 remove = true;
25523 }
25524 }
25525 if (remove)
25526 *pc = OMP_CLAUSE_CHAIN (c);
25527 else
25528 pc = &OMP_CLAUSE_CHAIN (c);
25529 }
25530 return clauses;
25531}
25532
25533/* OpenMP 4.5:
25534 #pragma omp taskloop taskloop-clause[optseq] new-line
25535 for-loop
25536
25537 #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
25538 for-loop */
25539
25540#define OMP_TASKLOOP_CLAUSE_MASK \
25541 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25542 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25543 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25544 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25545 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25546 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
25547 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
25548 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25549 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
25550 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25551 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
25552 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
25553 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
25554 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
25555 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25556 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25557 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
25558
25559static tree
25560c_parser_omp_taskloop (location_t loc, c_parser *parser,
25561 char *p_name, omp_clause_mask mask, tree *cclauses,
25562 bool *if_p)
25563{
25564 tree clauses, block, ret;
25565
25566 strcat (dest: p_name, src: " taskloop");
25567 mask |= OMP_TASKLOOP_CLAUSE_MASK;
25568 /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
25569 clause. */
25570 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
25571 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
25572
25573 if (c_parser_next_token_is (parser, type: CPP_NAME))
25574 {
25575 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25576
25577 if (strcmp (s1: p, s2: "simd") == 0)
25578 {
25579 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25580 if (cclauses == NULL)
25581 cclauses = cclauses_buf;
25582 c_parser_consume_token (parser);
25583 if (!flag_openmp) /* flag_openmp_simd */
25584 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25585 if_p);
25586 block = c_begin_compound_stmt (true);
25587 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
25588 block = c_end_compound_stmt (loc, block, true);
25589 if (ret == NULL)
25590 return ret;
25591 ret = make_node (OMP_TASKLOOP);
25592 TREE_TYPE (ret) = void_type_node;
25593 OMP_FOR_BODY (ret) = block;
25594 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
25595 OMP_FOR_CLAUSES (ret)
25596 = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
25597 SET_EXPR_LOCATION (ret, loc);
25598 add_stmt (ret);
25599 return ret;
25600 }
25601 }
25602 if (!flag_openmp) /* flag_openmp_simd */
25603 {
25604 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25605 return NULL_TREE;
25606 }
25607
25608 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25609 if (cclauses)
25610 {
25611 omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses);
25612 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
25613 }
25614
25615 clauses = c_finish_taskloop_clauses (clauses);
25616 block = c_begin_compound_stmt (true);
25617 ret = c_parser_omp_for_loop (loc, parser, code: OMP_TASKLOOP, clauses, NULL, if_p);
25618 block = c_end_compound_stmt (loc, block, true);
25619 add_stmt (block);
25620
25621 return ret;
25622}
25623
25624/* OpenMP 5.1
25625 #pragma omp nothing new-line */
25626
25627static void
25628c_parser_omp_nothing (c_parser *parser)
25629{
25630 c_parser_consume_pragma (parser);
25631 c_parser_skip_to_pragma_eol (parser);
25632}
25633
25634/* OpenMP 5.1
25635 #pragma omp error clauses[optseq] new-line */
25636
25637static bool
25638c_parser_omp_error (c_parser *parser, enum pragma_context context)
25639{
25640 int at_compilation = -1;
25641 int severity_fatal = -1;
25642 tree message = NULL_TREE;
25643 bool bad = false;
25644 location_t loc = c_parser_peek_token (parser)->location;
25645
25646 c_parser_consume_pragma (parser);
25647
25648 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25649 {
25650 if (c_parser_next_token_is (parser, type: CPP_COMMA)
25651 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25652 c_parser_consume_token (parser);
25653
25654 if (!c_parser_next_token_is (parser, type: CPP_NAME))
25655 break;
25656
25657 const char *p
25658 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25659 location_t cloc = c_parser_peek_token (parser)->location;
25660 static const char *args[] = {
25661 "execution", "compilation", "warning", "fatal"
25662 };
25663 int *v = NULL;
25664 int idx = 0, n = -1;
25665 tree m = NULL_TREE;
25666
25667 if (!strcmp (s1: p, s2: "at"))
25668 v = &at_compilation;
25669 else if (!strcmp (s1: p, s2: "severity"))
25670 {
25671 v = &severity_fatal;
25672 idx += 2;
25673 }
25674 else if (strcmp (s1: p, s2: "message"))
25675 {
25676 error_at (cloc,
25677 "expected %<at%>, %<severity%> or %<message%> clause");
25678 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25679 return false;
25680 }
25681
25682 c_parser_consume_token (parser);
25683
25684 matching_parens parens;
25685 if (parens.require_open (parser))
25686 {
25687 if (v == NULL)
25688 {
25689 location_t expr_loc = c_parser_peek_token (parser)->location;
25690 c_expr expr = c_parser_expr_no_commas (parser, NULL);
25691 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
25692 m = convert (const_string_type_node, expr.value);
25693 m = c_fully_fold (m, false, NULL);
25694 }
25695 else
25696 {
25697 if (c_parser_next_token_is (parser, type: CPP_NAME))
25698 {
25699 tree val = c_parser_peek_token (parser)->value;
25700 const char *q = IDENTIFIER_POINTER (val);
25701
25702 if (!strcmp (s1: q, s2: args[idx]))
25703 n = 0;
25704 else if (!strcmp (s1: q, s2: args[idx + 1]))
25705 n = 1;
25706 }
25707 if (n == -1)
25708 {
25709 error_at (c_parser_peek_token (parser)->location,
25710 "expected %qs or %qs", args[idx], args[idx + 1]);
25711 bad = true;
25712 switch (c_parser_peek_token (parser)->type)
25713 {
25714 case CPP_EOF:
25715 case CPP_PRAGMA_EOL:
25716 case CPP_CLOSE_PAREN:
25717 break;
25718 default:
25719 if (c_parser_peek_2nd_token (parser)->type
25720 == CPP_CLOSE_PAREN)
25721 c_parser_consume_token (parser);
25722 break;
25723 }
25724 }
25725 else
25726 c_parser_consume_token (parser);
25727 }
25728
25729 parens.skip_until_found_close (parser);
25730
25731 if (v == NULL)
25732 {
25733 if (message)
25734 {
25735 error_at (cloc, "too many %qs clauses", p);
25736 bad = true;
25737 }
25738 else
25739 message = m;
25740 }
25741 else if (n != -1)
25742 {
25743 if (*v != -1)
25744 {
25745 error_at (cloc, "too many %qs clauses", p);
25746 bad = true;
25747 }
25748 else
25749 *v = n;
25750 }
25751 }
25752 else
25753 bad = true;
25754 }
25755 c_parser_skip_to_pragma_eol (parser);
25756 if (bad)
25757 return true;
25758
25759 if (at_compilation == -1)
25760 at_compilation = 1;
25761 if (severity_fatal == -1)
25762 severity_fatal = 1;
25763 if (!at_compilation)
25764 {
25765 if (context != pragma_compound)
25766 {
25767 error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
25768 "may only be used in compound statements");
25769 return true;
25770 }
25771 tree fndecl
25772 = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR
25773 : BUILT_IN_GOMP_WARNING);
25774 if (!message)
25775 message = build_zero_cst (const_string_type_node);
25776 tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
25777 build_all_ones_cst (size_type_node));
25778 add_stmt (stmt);
25779 return true;
25780 }
25781 const char *msg = NULL;
25782 if (message)
25783 {
25784 msg = c_getstr (message);
25785 if (msg == NULL)
25786 msg = _("<message unknown at compile time>");
25787 }
25788 if (msg)
25789 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
25790 "%<pragma omp error%> encountered: %s", msg);
25791 else
25792 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
25793 "%<pragma omp error%> encountered");
25794 return false;
25795}
25796
25797/* Assumption clauses:
25798 OpenMP 5.1
25799 absent (directive-name-list)
25800 contains (directive-name-list)
25801 holds (expression)
25802 no_openmp
25803 no_openmp_routines
25804 no_parallelism */
25805
25806static void
25807c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
25808{
25809 bool no_openmp = false;
25810 bool no_openmp_routines = false;
25811 bool no_parallelism = false;
25812 bitmap_head absent_head, contains_head;
25813
25814 bitmap_obstack_initialize (NULL);
25815 bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack);
25816 bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack);
25817
25818 if (c_parser_next_token_is (parser, type: CPP_PRAGMA_EOL))
25819 error_at (c_parser_peek_token (parser)->location,
25820 "expected at least one assumption clause");
25821
25822 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
25823 {
25824 if (c_parser_next_token_is (parser, type: CPP_COMMA)
25825 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
25826 c_parser_consume_token (parser);
25827
25828 if (!c_parser_next_token_is (parser, type: CPP_NAME))
25829 break;
25830
25831 const char *p
25832 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25833 location_t cloc = c_parser_peek_token (parser)->location;
25834
25835 if (!strcmp (s1: p, s2: "no_openmp"))
25836 {
25837 c_parser_consume_token (parser);
25838 if (no_openmp)
25839 error_at (cloc, "too many %qs clauses", "no_openmp");
25840 no_openmp = true;
25841 }
25842 else if (!strcmp (s1: p, s2: "no_openmp_routines"))
25843 {
25844 c_parser_consume_token (parser);
25845 if (no_openmp_routines)
25846 error_at (cloc, "too many %qs clauses", "no_openmp_routines");
25847 no_openmp_routines = true;
25848 }
25849 else if (!strcmp (s1: p, s2: "no_parallelism"))
25850 {
25851 c_parser_consume_token (parser);
25852 if (no_parallelism)
25853 error_at (cloc, "too many %qs clauses", "no_parallelism");
25854 no_parallelism = true;
25855 }
25856 else if (!strcmp (s1: p, s2: "holds"))
25857 {
25858 c_parser_consume_token (parser);
25859 matching_parens parens;
25860 if (parens.require_open (parser))
25861 {
25862 location_t eloc = c_parser_peek_token (parser)->location;
25863 c_expr expr = c_parser_expr_no_commas (parser, NULL);
25864 tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
25865 t = c_objc_common_truthvalue_conversion (eloc, t);
25866 t = c_fully_fold (t, false, NULL);
25867 if (is_assume && t != error_mark_node)
25868 {
25869 tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
25870 void_type_node, 1,
25871 t);
25872 add_stmt (fn);
25873 }
25874 parens.skip_until_found_close (parser);
25875 }
25876 }
25877 else if (!strcmp (s1: p, s2: "absent") || !strcmp (s1: p, s2: "contains"))
25878 {
25879 c_parser_consume_token (parser);
25880 matching_parens parens;
25881 if (parens.require_open (parser))
25882 {
25883 do
25884 {
25885 const char *directive[3] = {};
25886 int i;
25887 location_t dloc = c_parser_peek_token (parser)->location;
25888 for (i = 0; i < 3; i++)
25889 {
25890 tree id;
25891 if (c_parser_peek_nth_token (parser, n: i + 1)->type
25892 == CPP_NAME)
25893 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
25894 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
25895 != RID_MAX)
25896 {
25897 enum rid rid
25898 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
25899 id = ridpointers[rid];
25900 }
25901 else
25902 break;
25903 directive[i] = IDENTIFIER_POINTER (id);
25904 }
25905 if (i == 0)
25906 error_at (dloc, "expected directive name");
25907 else
25908 {
25909 const struct c_omp_directive *dir
25910 = c_omp_categorize_directive (directive[0],
25911 directive[1],
25912 directive[2]);
25913 if (dir == NULL
25914 || dir->kind == C_OMP_DIR_DECLARATIVE
25915 || dir->kind == C_OMP_DIR_INFORMATIONAL
25916 || dir->id == PRAGMA_OMP_END
25917 || (!dir->second && directive[1])
25918 || (!dir->third && directive[2]))
25919 error_at (dloc, "unknown OpenMP directive name in "
25920 "%qs clause argument", p);
25921 else
25922 {
25923 int id = dir - c_omp_directives;
25924 if (bitmap_bit_p (p[0] == 'a' ? &contains_head
25925 : &absent_head, id))
25926 error_at (dloc, "%<%s%s%s%s%s%> directive "
25927 "mentioned in both %<absent%> and "
25928 "%<contains%> clauses",
25929 directive[0],
25930 directive[1] ? " " : "",
25931 directive[1] ? directive[1] : "",
25932 directive[2] ? " " : "",
25933 directive[2] ? directive[2] : "");
25934 else if (!bitmap_set_bit (p[0] == 'a'
25935 ? &absent_head
25936 : &contains_head, id))
25937 error_at (dloc, "%<%s%s%s%s%s%> directive "
25938 "mentioned multiple times in %qs "
25939 "clauses",
25940 directive[0],
25941 directive[1] ? " " : "",
25942 directive[1] ? directive[1] : "",
25943 directive[2] ? " " : "",
25944 directive[2] ? directive[2] : "", p);
25945 }
25946 for (; i; --i)
25947 c_parser_consume_token (parser);
25948 }
25949 if (c_parser_next_token_is (parser, type: CPP_COMMA))
25950 c_parser_consume_token (parser);
25951 else
25952 break;
25953 }
25954 while (1);
25955 parens.skip_until_found_close (parser);
25956 }
25957 }
25958 else if (startswith (str: p, prefix: "ext_"))
25959 {
25960 warning_at (cloc, 0, "unknown assumption clause %qs", p);
25961 c_parser_consume_token (parser);
25962 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
25963 {
25964 matching_parens parens;
25965 parens.consume_open (parser);
25966 c_parser_balanced_token_sequence (parser);
25967 parens.require_close (parser);
25968 }
25969 }
25970 else
25971 {
25972 c_parser_consume_token (parser);
25973 error_at (cloc, "expected assumption clause");
25974 break;
25975 }
25976 }
25977 c_parser_skip_to_pragma_eol (parser);
25978}
25979
25980/* OpenMP 5.1
25981 #pragma omp assume clauses[optseq] new-line */
25982
25983static void
25984c_parser_omp_assume (c_parser *parser, bool *if_p)
25985{
25986 c_parser_omp_assumption_clauses (parser, is_assume: true);
25987 add_stmt (c_parser_omp_structured_block (parser, if_p));
25988}
25989
25990/* OpenMP 5.1
25991 #pragma omp assumes clauses[optseq] new-line */
25992
25993static void
25994c_parser_omp_assumes (c_parser *parser)
25995{
25996 c_parser_consume_pragma (parser);
25997 c_parser_omp_assumption_clauses (parser, is_assume: false);
25998}
25999
26000/* Main entry point to parsing most OpenMP pragmas. */
26001
26002static void
26003c_parser_omp_construct (c_parser *parser, bool *if_p)
26004{
26005 enum pragma_kind p_kind;
26006 location_t loc;
26007 tree stmt;
26008 char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
26009 omp_clause_mask mask (0);
26010
26011 loc = c_parser_peek_token (parser)->location;
26012 p_kind = c_parser_peek_token (parser)->pragma_kind;
26013 c_parser_consume_pragma (parser);
26014
26015 switch (p_kind)
26016 {
26017 case PRAGMA_OACC_ATOMIC:
26018 c_parser_omp_atomic (loc, parser, openacc: true);
26019 return;
26020 case PRAGMA_OACC_CACHE:
26021 strcpy (dest: p_name, src: "#pragma acc");
26022 stmt = c_parser_oacc_cache (loc, parser);
26023 break;
26024 case PRAGMA_OACC_DATA:
26025 stmt = c_parser_oacc_data (loc, parser, if_p);
26026 break;
26027 case PRAGMA_OACC_HOST_DATA:
26028 stmt = c_parser_oacc_host_data (loc, parser, if_p);
26029 break;
26030 case PRAGMA_OACC_KERNELS:
26031 case PRAGMA_OACC_PARALLEL:
26032 case PRAGMA_OACC_SERIAL:
26033 strcpy (dest: p_name, src: "#pragma acc");
26034 stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
26035 break;
26036 case PRAGMA_OACC_LOOP:
26037 strcpy (dest: p_name, src: "#pragma acc");
26038 stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
26039 break;
26040 case PRAGMA_OACC_WAIT:
26041 strcpy (dest: p_name, src: "#pragma wait");
26042 stmt = c_parser_oacc_wait (loc, parser, p_name);
26043 break;
26044 case PRAGMA_OMP_ATOMIC:
26045 c_parser_omp_atomic (loc, parser, openacc: false);
26046 return;
26047 case PRAGMA_OMP_CRITICAL:
26048 stmt = c_parser_omp_critical (loc, parser, if_p);
26049 break;
26050 case PRAGMA_OMP_DISTRIBUTE:
26051 strcpy (dest: p_name, src: "#pragma omp");
26052 stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
26053 break;
26054 case PRAGMA_OMP_FOR:
26055 strcpy (dest: p_name, src: "#pragma omp");
26056 stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
26057 break;
26058 case PRAGMA_OMP_LOOP:
26059 strcpy (dest: p_name, src: "#pragma omp");
26060 stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
26061 break;
26062 case PRAGMA_OMP_MASKED:
26063 strcpy (dest: p_name, src: "#pragma omp");
26064 stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
26065 break;
26066 case PRAGMA_OMP_MASTER:
26067 strcpy (dest: p_name, src: "#pragma omp");
26068 stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
26069 break;
26070 case PRAGMA_OMP_PARALLEL:
26071 strcpy (dest: p_name, src: "#pragma omp");
26072 stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
26073 break;
26074 case PRAGMA_OMP_SCOPE:
26075 stmt = c_parser_omp_scope (loc, parser, if_p);
26076 break;
26077 case PRAGMA_OMP_SECTIONS:
26078 strcpy (dest: p_name, src: "#pragma omp");
26079 stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
26080 break;
26081 case PRAGMA_OMP_SIMD:
26082 strcpy (dest: p_name, src: "#pragma omp");
26083 stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
26084 break;
26085 case PRAGMA_OMP_SINGLE:
26086 stmt = c_parser_omp_single (loc, parser, if_p);
26087 break;
26088 case PRAGMA_OMP_TASK:
26089 stmt = c_parser_omp_task (loc, parser, if_p);
26090 break;
26091 case PRAGMA_OMP_TASKGROUP:
26092 stmt = c_parser_omp_taskgroup (loc, parser, if_p);
26093 break;
26094 case PRAGMA_OMP_TASKLOOP:
26095 strcpy (dest: p_name, src: "#pragma omp");
26096 stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
26097 break;
26098 case PRAGMA_OMP_TEAMS:
26099 strcpy (dest: p_name, src: "#pragma omp");
26100 stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
26101 break;
26102 case PRAGMA_OMP_ASSUME:
26103 c_parser_omp_assume (parser, if_p);
26104 return;
26105 default:
26106 gcc_unreachable ();
26107 }
26108
26109 if (stmt && stmt != error_mark_node)
26110 gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
26111}
26112
26113
26114/* OpenMP 2.5:
26115 # pragma omp threadprivate (variable-list) */
26116
26117static void
26118c_parser_omp_threadprivate (c_parser *parser)
26119{
26120 tree vars, t;
26121 location_t loc;
26122
26123 c_parser_consume_pragma (parser);
26124 loc = c_parser_peek_token (parser)->location;
26125 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
26126
26127 /* Mark every variable in VARS to be assigned thread local storage. */
26128 for (t = vars; t; t = TREE_CHAIN (t))
26129 {
26130 tree v = TREE_PURPOSE (t);
26131
26132 /* FIXME diagnostics: Ideally we should keep individual
26133 locations for all the variables in the var list to make the
26134 following errors more precise. Perhaps
26135 c_parser_omp_var_list_parens() should construct a list of
26136 locations to go along with the var list. */
26137
26138 /* If V had already been marked threadprivate, it doesn't matter
26139 whether it had been used prior to this point. */
26140 if (!VAR_P (v))
26141 error_at (loc, "%qD is not a variable", v);
26142 else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
26143 error_at (loc, "%qE declared %<threadprivate%> after first use", v);
26144 else if (! is_global_var (t: v))
26145 error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
26146 else if (TREE_TYPE (v) == error_mark_node)
26147 ;
26148 else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
26149 error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
26150 else
26151 {
26152 if (! DECL_THREAD_LOCAL_P (v))
26153 {
26154 set_decl_tls_model (v, decl_default_tls_model (v));
26155 /* If rtl has been already set for this var, call
26156 make_decl_rtl once again, so that encode_section_info
26157 has a chance to look at the new decl flags. */
26158 if (DECL_RTL_SET_P (v))
26159 make_decl_rtl (v);
26160 }
26161 C_DECL_THREADPRIVATE_P (v) = 1;
26162 }
26163 }
26164
26165 c_parser_skip_to_pragma_eol (parser);
26166}
26167
26168/* Parse a transaction attribute (GCC Extension).
26169
26170 transaction-attribute:
26171 gnu-attributes
26172 attribute-specifier
26173*/
26174
26175static tree
26176c_parser_transaction_attributes (c_parser *parser)
26177{
26178 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
26179 return c_parser_gnu_attributes (parser);
26180
26181 if (!c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
26182 return NULL_TREE;
26183 return c_parser_std_attribute_specifier (parser, for_tm: true);
26184}
26185
26186/* Parse a __transaction_atomic or __transaction_relaxed statement
26187 (GCC Extension).
26188
26189 transaction-statement:
26190 __transaction_atomic transaction-attribute[opt] compound-statement
26191 __transaction_relaxed compound-statement
26192
26193 Note that the only valid attribute is: "outer".
26194*/
26195
26196static tree
26197c_parser_transaction (c_parser *parser, enum rid keyword)
26198{
26199 unsigned int old_in = parser->in_transaction;
26200 unsigned int this_in = 1, new_in;
26201 location_t loc = c_parser_peek_token (parser)->location;
26202 tree stmt, attrs;
26203
26204 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
26205 || keyword == RID_TRANSACTION_RELAXED)
26206 && c_parser_next_token_is_keyword (parser, keyword));
26207 c_parser_consume_token (parser);
26208
26209 if (keyword == RID_TRANSACTION_RELAXED)
26210 this_in |= TM_STMT_ATTR_RELAXED;
26211 else
26212 {
26213 attrs = c_parser_transaction_attributes (parser);
26214 if (attrs)
26215 this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
26216 }
26217
26218 /* Keep track if we're in the lexical scope of an outer transaction. */
26219 new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
26220
26221 parser->in_transaction = new_in;
26222 stmt = c_parser_compound_statement (parser);
26223 parser->in_transaction = old_in;
26224
26225 if (flag_tm)
26226 stmt = c_finish_transaction (loc, stmt, this_in);
26227 else
26228 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
26229 "%<__transaction_atomic%> without transactional memory support enabled"
26230 : "%<__transaction_relaxed %> "
26231 "without transactional memory support enabled"));
26232
26233 return stmt;
26234}
26235
26236/* Parse a __transaction_atomic or __transaction_relaxed expression
26237 (GCC Extension).
26238
26239 transaction-expression:
26240 __transaction_atomic ( expression )
26241 __transaction_relaxed ( expression )
26242*/
26243
26244static struct c_expr
26245c_parser_transaction_expression (c_parser *parser, enum rid keyword)
26246{
26247 struct c_expr ret;
26248 unsigned int old_in = parser->in_transaction;
26249 unsigned int this_in = 1;
26250 location_t loc = c_parser_peek_token (parser)->location;
26251 tree attrs;
26252
26253 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
26254 || keyword == RID_TRANSACTION_RELAXED)
26255 && c_parser_next_token_is_keyword (parser, keyword));
26256 c_parser_consume_token (parser);
26257
26258 if (keyword == RID_TRANSACTION_RELAXED)
26259 this_in |= TM_STMT_ATTR_RELAXED;
26260 else
26261 {
26262 attrs = c_parser_transaction_attributes (parser);
26263 if (attrs)
26264 this_in |= parse_tm_stmt_attr (attrs, 0);
26265 }
26266
26267 parser->in_transaction = this_in;
26268 matching_parens parens;
26269 if (parens.require_open (parser))
26270 {
26271 tree expr = c_parser_expression (parser).value;
26272 ret.original_type = TREE_TYPE (expr);
26273 ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
26274 if (this_in & TM_STMT_ATTR_RELAXED)
26275 TRANSACTION_EXPR_RELAXED (ret.value) = 1;
26276 SET_EXPR_LOCATION (ret.value, loc);
26277 ret.original_code = TRANSACTION_EXPR;
26278 ret.m_decimal = 0;
26279 if (!parens.require_close (parser))
26280 {
26281 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
26282 goto error;
26283 }
26284 }
26285 else
26286 {
26287 error:
26288 ret.set_error ();
26289 ret.original_code = ERROR_MARK;
26290 ret.original_type = NULL;
26291 }
26292 parser->in_transaction = old_in;
26293
26294 if (!flag_tm)
26295 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
26296 "%<__transaction_atomic%> without transactional memory support enabled"
26297 : "%<__transaction_relaxed %> "
26298 "without transactional memory support enabled"));
26299
26300 set_c_expr_source_range (expr: &ret, start: loc, finish: loc);
26301
26302 return ret;
26303}
26304
26305/* Parse a __transaction_cancel statement (GCC Extension).
26306
26307 transaction-cancel-statement:
26308 __transaction_cancel transaction-attribute[opt] ;
26309
26310 Note that the only valid attribute is "outer".
26311*/
26312
26313static tree
26314c_parser_transaction_cancel (c_parser *parser)
26315{
26316 location_t loc = c_parser_peek_token (parser)->location;
26317 tree attrs;
26318 bool is_outer = false;
26319
26320 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
26321 c_parser_consume_token (parser);
26322
26323 attrs = c_parser_transaction_attributes (parser);
26324 if (attrs)
26325 is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
26326
26327 if (!flag_tm)
26328 {
26329 error_at (loc, "%<__transaction_cancel%> without "
26330 "transactional memory support enabled");
26331 goto ret_error;
26332 }
26333 else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
26334 {
26335 error_at (loc, "%<__transaction_cancel%> within a "
26336 "%<__transaction_relaxed%>");
26337 goto ret_error;
26338 }
26339 else if (is_outer)
26340 {
26341 if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
26342 && !is_tm_may_cancel_outer (current_function_decl))
26343 {
26344 error_at (loc, "outer %<__transaction_cancel%> not "
26345 "within outer %<__transaction_atomic%> or "
26346 "a %<transaction_may_cancel_outer%> function");
26347 goto ret_error;
26348 }
26349 }
26350 else if (parser->in_transaction == 0)
26351 {
26352 error_at (loc, "%<__transaction_cancel%> not within "
26353 "%<__transaction_atomic%>");
26354 goto ret_error;
26355 }
26356
26357 return add_stmt (build_tm_abort_call (loc, is_outer));
26358
26359 ret_error:
26360 return build1 (NOP_EXPR, void_type_node, error_mark_node);
26361}
26362
26363/* Parse a single source file. */
26364
26365void
26366c_parse_file (void)
26367{
26368 /* Use local storage to begin. If the first token is a pragma, parse it.
26369 If it is #pragma GCC pch_preprocess, then this will load a PCH file
26370 which will cause garbage collection. */
26371 c_parser tparser;
26372
26373 memset (s: &tparser, c: 0, n: sizeof tparser);
26374 tparser.translate_strings_p = true;
26375 tparser.tokens = &tparser.tokens_buf[0];
26376 the_parser = &tparser;
26377
26378 if (c_parser_peek_token (parser: &tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
26379 c_parser_pragma_pch_preprocess (parser: &tparser);
26380 else
26381 c_common_no_more_pch ();
26382
26383 the_parser = ggc_alloc<c_parser> ();
26384 *the_parser = tparser;
26385 if (tparser.tokens == &tparser.tokens_buf[0])
26386 the_parser->tokens = &the_parser->tokens_buf[0];
26387
26388 /* Initialize EH, if we've been told to do so. */
26389 if (flag_exceptions)
26390 using_eh_for_cleanups ();
26391
26392 c_parser_translation_unit (parser: the_parser);
26393 the_parser = NULL;
26394}
26395
26396void
26397c_init_preprocess (void)
26398{
26399 /* Create a parser for use by pragma_lex during preprocessing. */
26400 the_parser = ggc_alloc<c_parser> ();
26401 memset (s: the_parser, c: 0, n: sizeof (c_parser));
26402 the_parser->tokens = &the_parser->tokens_buf[0];
26403}
26404
26405/* Parse the body of a function declaration marked with "__RTL".
26406
26407 The RTL parser works on the level of characters read from a
26408 FILE *, whereas c_parser works at the level of tokens.
26409 Square this circle by consuming all of the tokens up to and
26410 including the closing brace, recording the start/end of the RTL
26411 fragment, and reopening the file and re-reading the relevant
26412 lines within the RTL parser.
26413
26414 This requires the opening and closing braces of the C function
26415 to be on separate lines from the RTL they wrap.
26416
26417 Take ownership of START_WITH_PASS, if non-NULL. */
26418
26419location_t
26420c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
26421{
26422 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
26423 {
26424 free (ptr: start_with_pass);
26425 return c_parser_peek_token (parser)->location;
26426 }
26427
26428 location_t start_loc = c_parser_peek_token (parser)->location;
26429
26430 /* Consume all tokens, up to the closing brace, handling
26431 matching pairs of braces in the rtl dump. */
26432 int num_open_braces = 1;
26433 while (1)
26434 {
26435 switch (c_parser_peek_token (parser)->type)
26436 {
26437 case CPP_OPEN_BRACE:
26438 num_open_braces++;
26439 break;
26440 case CPP_CLOSE_BRACE:
26441 if (--num_open_braces == 0)
26442 goto found_closing_brace;
26443 break;
26444 case CPP_EOF:
26445 error_at (start_loc, "no closing brace");
26446 free (ptr: start_with_pass);
26447 return c_parser_peek_token (parser)->location;
26448 default:
26449 break;
26450 }
26451 c_parser_consume_token (parser);
26452 }
26453
26454 found_closing_brace:
26455 /* At the closing brace; record its location. */
26456 location_t end_loc = c_parser_peek_token (parser)->location;
26457
26458 /* Consume the closing brace. */
26459 c_parser_consume_token (parser);
26460
26461 /* Invoke the RTL parser. */
26462 if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
26463 {
26464 free (ptr: start_with_pass);
26465 return end_loc;
26466 }
26467
26468 /* Run the backend on the cfun created above, transferring ownership of
26469 START_WITH_PASS. */
26470 run_rtl_passes (initial_pass_name: start_with_pass);
26471 return end_loc;
26472}
26473
26474#include "gt-c-c-parser.h"
26475

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