Line data Source code
1 : /* Parser for C and Objective-C.
2 : Copyright (C) 1987-2026 Free Software Foundation, Inc.
3 :
4 : Parser actions based on the old Bison parser; structure somewhat
5 : influenced by and fragments based on the C++ parser.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify it under
10 : the terms of the GNU General Public License as published by the Free
11 : Software Foundation; either version 3, or (at your option) any later
12 : version.
13 :
14 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 : for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : /* TODO:
24 :
25 : Make sure all relevant comments, and all relevant code from all
26 : actions, brought over from old parser. Verify exact correspondence
27 : of syntax accepted.
28 :
29 : Add testcases covering every input symbol in every state in old and
30 : new parsers.
31 :
32 : Include full syntax for GNU C, including erroneous cases accepted
33 : with error messages, in syntax productions in comments.
34 :
35 : Make more diagnostics in the front end generally take an explicit
36 : location rather than implicitly using input_location. */
37 :
38 : #include "config.h"
39 : #define INCLUDE_STRING
40 : #include "system.h"
41 : #include "coretypes.h"
42 : #include "target.h"
43 : #include "function.h"
44 : #include "c-tree.h"
45 : #include "timevar.h"
46 : #include "stringpool.h"
47 : #include "cgraph.h"
48 : #include "attribs.h"
49 : #include "stor-layout.h"
50 : #include "varasm.h"
51 : #include "trans-mem.h"
52 : #include "c-family/c-pragma.h"
53 : #include "c-lang.h"
54 : #include "c-family/c-objc.h"
55 : #include "plugin.h"
56 : #include "omp-general.h"
57 : #include "omp-offload.h"
58 : #include "builtins.h"
59 : #include "gomp-constants.h"
60 : #include "c-family/c-indentation.h"
61 : #include "gimple-expr.h"
62 : #include "context.h"
63 : #include "gcc-rich-location.h"
64 : #include "c-parser.h"
65 : #include "gimple-parser.h"
66 : #include "read-rtl-function.h"
67 : #include "run-rtl-passes.h"
68 : #include "intl.h"
69 : #include "c-family/name-hint.h"
70 : #include "tree-iterator.h"
71 : #include "tree-pretty-print.h"
72 : #include "memmodel.h"
73 : #include "c-family/known-headers.h"
74 : #include "bitmap.h"
75 : #include "analyzer/analyzer-language.h"
76 : #include "toplev.h"
77 : #include "asan.h"
78 : #include "c-family/c-ubsan.h"
79 : #include "gcc-urlifier.h"
80 :
81 : /* We need to walk over decls with incomplete struct/union/enum types
82 : after parsing the whole translation unit.
83 : In finish_decl(), if the decl is static, has incomplete
84 : struct/union/enum type, it is appended to incomplete_record_decls.
85 : In c_parser_translation_unit(), we iterate over incomplete_record_decls
86 : and report error if any of the decls are still incomplete. */
87 :
88 : vec<tree> incomplete_record_decls;
89 :
90 : void
91 208089950 : set_c_expr_source_range (c_expr *expr,
92 : location_t start, location_t finish)
93 : {
94 208089950 : expr->src_range.m_start = start;
95 208089950 : expr->src_range.m_finish = finish;
96 208089950 : if (expr->value)
97 208089824 : set_source_range (expr->value, start, finish);
98 208089950 : }
99 :
100 : void
101 230806666 : set_c_expr_source_range (c_expr *expr,
102 : source_range src_range)
103 : {
104 230806666 : expr->src_range = src_range;
105 230806666 : if (expr->value)
106 230806661 : set_source_range (expr->value, src_range);
107 230806666 : }
108 :
109 :
110 : /* Initialization routine for this file. */
111 :
112 : void
113 110763 : c_parse_init (void)
114 : {
115 : /* The only initialization required is of the reserved word
116 : identifiers. */
117 110763 : unsigned int i;
118 110763 : tree id;
119 110763 : int mask = 0;
120 :
121 : /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
122 : the c_token structure. */
123 110763 : gcc_assert (RID_MAX <= 255);
124 :
125 110763 : mask |= D_CXXONLY;
126 110763 : if (!flag_isoc99)
127 6945 : mask |= D_C99;
128 110763 : if (!flag_isoc23)
129 13185 : mask |= D_C23;
130 110763 : if (flag_no_asm)
131 : {
132 6171 : mask |= D_ASM | D_EXT;
133 6171 : if (!flag_isoc99)
134 3994 : mask |= D_EXT89;
135 6171 : if (!flag_isoc23)
136 5126 : mask |= D_EXT11;
137 : }
138 110763 : if (!c_dialect_objc ())
139 110763 : mask |= D_OBJC | D_CXX_OBJC;
140 :
141 110763 : ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
142 25807779 : for (i = 0; i < num_c_common_reswords; i++)
143 : {
144 : /* If a keyword is disabled, do not enter it into the table
145 : and so create a canonical spelling that isn't a keyword. */
146 25697016 : if (c_common_reswords[i].disable & mask)
147 : {
148 9932928 : if (warn_cxx_compat
149 113021 : && (c_common_reswords[i].disable & D_CXXWARN))
150 : {
151 54177 : id = get_identifier (c_common_reswords[i].word);
152 54177 : C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
153 54177 : C_IS_RESERVED_WORD (id) = 1;
154 : }
155 9932928 : continue;
156 : }
157 :
158 15764088 : id = get_identifier (c_common_reswords[i].word);
159 15764088 : C_SET_RID_CODE (id, c_common_reswords[i].rid);
160 15764088 : C_IS_RESERVED_WORD (id) = 1;
161 15764088 : ridpointers [(int) c_common_reswords[i].rid] = id;
162 : }
163 :
164 221526 : for (i = 0; i < NUM_INT_N_ENTS; i++)
165 : {
166 : /* We always create the symbols but they aren't always supported. */
167 110763 : char name[50];
168 110763 : sprintf (name, "__int%d", int_n_data[i].bitsize);
169 110763 : id = get_identifier (name);
170 110763 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
171 110763 : C_IS_RESERVED_WORD (id) = 1;
172 :
173 110763 : sprintf (name, "__int%d__", int_n_data[i].bitsize);
174 110763 : id = get_identifier (name);
175 110763 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
176 110763 : C_IS_RESERVED_WORD (id) = 1;
177 : }
178 :
179 110763 : if (flag_openmp)
180 : {
181 2289 : id = get_identifier ("omp_all_memory");
182 2289 : C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
183 2289 : C_IS_RESERVED_WORD (id) = 1;
184 2289 : ridpointers [RID_OMP_ALL_MEMORY] = id;
185 : }
186 110763 : }
187 :
188 : /* A parser structure recording information about the state and
189 : context of parsing. Includes lexer information with up to two
190 : tokens of look-ahead; more are not needed for C. */
191 : struct GTY(()) c_parser {
192 : /* The look-ahead tokens. */
193 : c_token * GTY((skip)) tokens;
194 : /* Buffer for look-ahead tokens. */
195 : c_token tokens_buf[4];
196 : /* How many look-ahead tokens are available (0 - 4, or
197 : more if parsing from pre-lexed tokens). */
198 : unsigned int tokens_avail;
199 : /* Raw look-ahead tokens, used only for checking in Objective-C
200 : whether '[[' starts attributes. */
201 : vec<c_token, va_gc> *raw_tokens;
202 : /* The number of raw look-ahead tokens that have since been fully
203 : lexed. */
204 : unsigned int raw_tokens_used;
205 : /* True if a syntax error is being recovered from; false otherwise.
206 : c_parser_error sets this flag. It should clear this flag when
207 : enough tokens have been consumed to recover from the error. */
208 : BOOL_BITFIELD error : 1;
209 : /* True if we're processing a pragma, and shouldn't automatically
210 : consume CPP_PRAGMA_EOL. */
211 : BOOL_BITFIELD in_pragma : 1;
212 : /* True if we're parsing the outermost block of an if statement. */
213 : BOOL_BITFIELD in_if_block : 1;
214 : /* True if we want to lex a translated, joined string (for an
215 : initial #pragma pch_preprocess). Otherwise the parser is
216 : responsible for concatenating strings and translating to the
217 : execution character set as needed. */
218 : BOOL_BITFIELD lex_joined_string : 1;
219 : /* True if, when the parser is concatenating string literals, it
220 : should translate them to the execution character set (false
221 : inside attributes). */
222 : BOOL_BITFIELD translate_strings_p : 1;
223 :
224 : /* Objective-C specific parser/lexer information. */
225 :
226 : /* True if we are in a context where the Objective-C "PQ" keywords
227 : are considered keywords. */
228 : BOOL_BITFIELD objc_pq_context : 1;
229 : /* True if we are parsing a (potential) Objective-C foreach
230 : statement. This is set to true after we parsed 'for (' and while
231 : we wait for 'in' or ';' to decide if it's a standard C for loop or an
232 : Objective-C foreach loop. */
233 : BOOL_BITFIELD objc_could_be_foreach_context : 1;
234 : /* The following flag is needed to contextualize Objective-C lexical
235 : analysis. In some cases (e.g., 'int NSObject;'), it is
236 : undesirable to bind an identifier to an Objective-C class, even
237 : if a class with that name exists. */
238 : BOOL_BITFIELD objc_need_raw_identifier : 1;
239 : /* Nonzero if we're processing a __transaction statement. The value
240 : is 1 | TM_STMT_ATTR_*. */
241 : unsigned int in_transaction : 4;
242 : /* True if we are in a context where the Objective-C "Property attribute"
243 : keywords are valid. */
244 : BOOL_BITFIELD objc_property_attr_context : 1;
245 :
246 : /* Whether we have just seen/constructed a string-literal. Set when
247 : returning a string-literal from c_parser_string_literal. Reset
248 : in consume_token. Useful when we get a parse error and see an
249 : unknown token, which could have been a string-literal constant
250 : macro. */
251 : BOOL_BITFIELD seen_string_literal : 1;
252 :
253 : /* TRUE if omp::directive, omp::decl or omp::sequence attributes may not
254 : appear. */
255 : BOOL_BITFIELD omp_attrs_forbidden_p : 1;
256 :
257 : /* Location of the last consumed token. */
258 : location_t last_token_location;
259 :
260 : /* Holds state for parsing collapsed OMP_FOR loops. Managed by
261 : c_parser_omp_for_loop. */
262 : struct omp_for_parse_data * GTY((skip)) omp_for_parse_state;
263 :
264 : /* If we're in the context of OpenMP directives written as C23
265 : attributes turned into pragma, the tokens field is temporarily
266 : redirected. This holds data needed to restore state afterwards.
267 : It's NULL otherwise. */
268 : struct omp_attribute_pragma_state *in_omp_attribute_pragma;
269 :
270 : /* Set for omp::decl attribute parsing to the decl to which it
271 : appertains. */
272 : tree in_omp_decl_attribute;
273 :
274 : /* Non-null only when parsing the body of an OpenMP metadirective.
275 : Managed by c_parser_omp_metadirective. */
276 : struct omp_metadirective_parse_data * GTY((skip))
277 : omp_metadirective_state;
278 : };
279 :
280 : /* Holds data needed to restore the token stream to its previous state
281 : after parsing an OpenMP attribute-syntax pragma. */
282 : struct GTY(()) omp_attribute_pragma_state
283 : {
284 : vec<c_token, va_gc> *token_vec;
285 : c_token * GTY((skip)) save_tokens;
286 : unsigned int save_tokens_avail;
287 : };
288 :
289 : /* Holds data for deferred lookup of base functions for OpenMP
290 : "begin declare variant", which are permitted to be declared after
291 : the variant. */
292 : struct GTY(()) omp_begin_declare_variant_map_entry {
293 : tree variant; /* The variant decl. */
294 : tree id; /* Name of base function. */
295 : tree ctx; /* The context selector associated with the variant. */
296 : };
297 : vec<omp_begin_declare_variant_map_entry, va_gc> *omp_begin_declare_variant_map;
298 :
299 : static tree omp_start_variant_function (c_declarator *, tree);
300 : static void omp_finish_variant_function (tree, tree, tree);
301 :
302 : /* Return a pointer to the Nth token in PARSERs tokens_buf. */
303 :
304 : c_token *
305 234 : c_parser_tokens_buf (c_parser *parser, unsigned n)
306 : {
307 234 : return &parser->tokens_buf[n];
308 : }
309 :
310 : /* Return the error state of PARSER. */
311 :
312 : bool
313 8095 : c_parser_error (c_parser *parser)
314 : {
315 8095 : return parser->error;
316 : }
317 :
318 : /* Set the error state of PARSER to ERR. */
319 :
320 : void
321 0 : c_parser_set_error (c_parser *parser, bool err)
322 : {
323 0 : parser->error = err;
324 0 : }
325 :
326 :
327 : /* The actual parser and external interface. ??? Does this need to be
328 : garbage-collected? */
329 :
330 : static GTY (()) c_parser *the_parser;
331 :
332 : /* Read in and lex a single token, storing it in *TOKEN. If RAW,
333 : context-sensitive postprocessing of the token is not done. */
334 :
335 : static void
336 2314592814 : c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
337 : {
338 2314592814 : timevar_push (TV_LEX);
339 :
340 2314592814 : if (raw || vec_safe_length (parser->raw_tokens) == 0)
341 : {
342 2314492659 : token->type = c_lex_with_flags (&token->value, &token->location,
343 : &token->flags,
344 2314492659 : (parser->lex_joined_string
345 : ? 0 : C_LEX_STRING_NO_JOIN));
346 2314492502 : token->id_kind = C_ID_NONE;
347 2314492502 : token->keyword = RID_MAX;
348 2314492502 : token->pragma_kind = PRAGMA_NONE;
349 : }
350 : else
351 : {
352 : /* Use a token previously lexed as a raw look-ahead token, and
353 : complete the processing on it. */
354 100155 : *token = (*parser->raw_tokens)[parser->raw_tokens_used];
355 100155 : ++parser->raw_tokens_used;
356 100155 : if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
357 : {
358 15477 : vec_free (parser->raw_tokens);
359 15477 : parser->raw_tokens_used = 0;
360 : }
361 : }
362 :
363 2314592657 : if (raw)
364 100155 : goto out;
365 :
366 2314492502 : switch (token->type)
367 : {
368 1041989265 : case CPP_NAME:
369 1041989265 : {
370 1041989265 : tree decl;
371 :
372 1041989265 : bool objc_force_identifier = parser->objc_need_raw_identifier;
373 1041989265 : if (c_dialect_objc ())
374 0 : parser->objc_need_raw_identifier = false;
375 :
376 1041989265 : if (C_IS_RESERVED_WORD (token->value))
377 : {
378 289088776 : enum rid rid_code = C_RID_CODE (token->value);
379 :
380 289088776 : if (rid_code == RID_CXX_COMPAT_WARN)
381 : {
382 35 : warning_at (token->location,
383 35 : OPT_Wc___compat,
384 : "identifier %qE conflicts with C++ keyword",
385 : token->value);
386 : }
387 289088741 : else if (rid_code >= RID_FIRST_ADDR_SPACE
388 289088741 : && rid_code <= RID_LAST_ADDR_SPACE)
389 : {
390 177 : addr_space_t as;
391 177 : as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
392 177 : targetm.addr_space.diagnose_usage (as, token->location);
393 177 : token->id_kind = C_ID_ADDRSPACE;
394 177 : token->keyword = rid_code;
395 177 : break;
396 : }
397 289088564 : else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
398 : {
399 : /* We found an Objective-C "pq" keyword (in, out,
400 : inout, bycopy, byref, oneway). They need special
401 : care because the interpretation depends on the
402 : context. */
403 0 : if (parser->objc_pq_context)
404 : {
405 0 : token->type = CPP_KEYWORD;
406 0 : token->keyword = rid_code;
407 0 : break;
408 : }
409 0 : else if (parser->objc_could_be_foreach_context
410 0 : && rid_code == RID_IN)
411 : {
412 : /* We are in Objective-C, inside a (potential)
413 : foreach context (which means after having
414 : parsed 'for (', but before having parsed ';'),
415 : and we found 'in'. We consider it the keyword
416 : which terminates the declaration at the
417 : beginning of a foreach-statement. Note that
418 : this means you can't use 'in' for anything else
419 : in that context; in particular, in Objective-C
420 : you can't use 'in' as the name of the running
421 : variable in a C for loop. We could potentially
422 : try to add code here to disambiguate, but it
423 : seems a reasonable limitation. */
424 0 : token->type = CPP_KEYWORD;
425 0 : token->keyword = rid_code;
426 0 : break;
427 : }
428 : /* Else, "pq" keywords outside of the "pq" context are
429 : not keywords, and we fall through to the code for
430 : normal tokens. */
431 : }
432 289088564 : else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
433 : {
434 : /* We found an Objective-C "property attribute"
435 : keyword (getter, setter, readonly, etc). These are
436 : only valid in the property context. */
437 0 : if (parser->objc_property_attr_context)
438 : {
439 0 : token->type = CPP_KEYWORD;
440 0 : token->keyword = rid_code;
441 0 : break;
442 : }
443 : /* Else they are not special keywords.
444 : */
445 : }
446 289088564 : else if (c_dialect_objc ()
447 0 : && (OBJC_IS_AT_KEYWORD (rid_code)
448 : || OBJC_IS_CXX_KEYWORD (rid_code)))
449 : {
450 : /* We found one of the Objective-C "@" keywords (defs,
451 : selector, synchronized, etc) or one of the
452 : Objective-C "cxx" keywords (class, private,
453 : protected, public, try, catch, throw) without a
454 : preceding '@' sign. Do nothing and fall through to
455 : the code for normal tokens (in C++ we would still
456 : consider the CXX ones keywords, but not in C). */
457 : ;
458 : }
459 : else
460 : {
461 289088564 : token->type = CPP_KEYWORD;
462 289088564 : token->keyword = rid_code;
463 289088564 : break;
464 : }
465 : }
466 :
467 752900524 : decl = lookup_name (token->value);
468 752900524 : if (decl)
469 : {
470 421719928 : if (TREE_CODE (decl) == TYPE_DECL)
471 : {
472 245575573 : token->id_kind = C_ID_TYPENAME;
473 245575573 : break;
474 : }
475 : }
476 331180596 : else if (c_dialect_objc ())
477 : {
478 0 : tree objc_interface_decl = objc_is_class_name (token->value);
479 : /* Objective-C class names are in the same namespace as
480 : variables and typedefs, and hence are shadowed by local
481 : declarations. */
482 0 : if (objc_interface_decl
483 0 : && (!objc_force_identifier || global_bindings_p ()))
484 : {
485 0 : token->value = objc_interface_decl;
486 0 : token->id_kind = C_ID_CLASSNAME;
487 0 : break;
488 : }
489 : }
490 507324951 : token->id_kind = C_ID_ID;
491 : }
492 507324951 : break;
493 0 : case CPP_AT_NAME:
494 : /* This only happens in Objective-C; it must be a keyword. */
495 0 : token->type = CPP_KEYWORD;
496 0 : switch (C_RID_CODE (token->value))
497 : {
498 : /* Replace 'class' with '@class', 'private' with '@private',
499 : etc. This prevents confusion with the C++ keyword
500 : 'class', and makes the tokens consistent with other
501 : Objective-C 'AT' keywords. For example '@class' is
502 : reported as RID_AT_CLASS which is consistent with
503 : '@synchronized', which is reported as
504 : RID_AT_SYNCHRONIZED.
505 : */
506 0 : case RID_CLASS: token->keyword = RID_AT_CLASS; break;
507 0 : case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
508 0 : case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
509 0 : case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
510 0 : case RID_THROW: token->keyword = RID_AT_THROW; break;
511 0 : case RID_TRY: token->keyword = RID_AT_TRY; break;
512 0 : case RID_CATCH: token->keyword = RID_AT_CATCH; break;
513 0 : case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
514 0 : default: token->keyword = C_RID_CODE (token->value);
515 : }
516 : break;
517 698010723 : case CPP_COLON:
518 698010723 : case CPP_COMMA:
519 698010723 : case CPP_CLOSE_PAREN:
520 698010723 : case CPP_SEMICOLON:
521 : /* These tokens may affect the interpretation of any identifiers
522 : following, if doing Objective-C. */
523 698010723 : if (c_dialect_objc ())
524 0 : parser->objc_need_raw_identifier = false;
525 : break;
526 1927758 : case CPP_PRAGMA:
527 : /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
528 1927758 : token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
529 1927758 : token->value = NULL;
530 1927758 : break;
531 : default:
532 : break;
533 : }
534 2314592657 : out:
535 2314592657 : timevar_pop (TV_LEX);
536 2314592657 : }
537 :
538 : /* Return a pointer to the next token from PARSER, reading it in if
539 : necessary. */
540 :
541 : c_token *
542 17268880705 : c_parser_peek_token (c_parser *parser)
543 : {
544 17268880705 : if (parser->tokens_avail == 0)
545 : {
546 1896416203 : c_lex_one_token (parser, &parser->tokens[0]);
547 1896416046 : parser->tokens_avail = 1;
548 : }
549 17268880548 : return &parser->tokens[0];
550 : }
551 :
552 : /* Return a pointer to the next-but-one token from PARSER, reading it
553 : in if necessary. The next token is already read in. */
554 :
555 : c_token *
556 157654941 : c_parser_peek_2nd_token (c_parser *parser)
557 : {
558 157654941 : if (parser->tokens_avail >= 2)
559 8507429 : return &parser->tokens[1];
560 149147512 : gcc_assert (parser->tokens_avail == 1);
561 149147512 : gcc_assert (parser->tokens[0].type != CPP_EOF);
562 149147512 : gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
563 149147512 : c_lex_one_token (parser, &parser->tokens[1]);
564 149147512 : parser->tokens_avail = 2;
565 149147512 : return &parser->tokens[1];
566 : }
567 :
568 : /* Return a pointer to the Nth token from PARSER, reading it
569 : in if necessary. The N-1th token is already read in. */
570 :
571 : c_token *
572 1288015786 : c_parser_peek_nth_token (c_parser *parser, unsigned int n)
573 : {
574 : /* N is 1-based, not zero-based. */
575 1288015786 : gcc_assert (n > 0);
576 :
577 1288015786 : if (parser->tokens_avail >= n)
578 1019086842 : return &parser->tokens[n - 1];
579 268928944 : gcc_assert (parser->tokens_avail == n - 1);
580 268928944 : c_lex_one_token (parser, &parser->tokens[n - 1]);
581 268928944 : parser->tokens_avail = n;
582 268928944 : return &parser->tokens[n - 1];
583 : }
584 :
585 : /* Return a pointer to the Nth token from PARSER, reading it in as a
586 : raw look-ahead token if necessary. The N-1th token is already read
587 : in. Raw look-ahead tokens remain available for when the non-raw
588 : functions above are called. */
589 :
590 : c_token *
591 136225 : c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
592 : {
593 : /* N is 1-based, not zero-based. */
594 136225 : gcc_assert (n > 0);
595 :
596 136225 : if (parser->tokens_avail >= n)
597 10327 : return &parser->tokens[n - 1];
598 125898 : unsigned int raw_len = vec_safe_length (parser->raw_tokens);
599 125898 : unsigned int raw_avail
600 125898 : = parser->tokens_avail + raw_len - parser->raw_tokens_used;
601 125898 : gcc_assert (raw_avail >= n - 1);
602 125898 : if (raw_avail >= n)
603 25743 : return &(*parser->raw_tokens)[parser->raw_tokens_used
604 25743 : + n - 1 - parser->tokens_avail];
605 100155 : vec_safe_reserve (parser->raw_tokens, 1);
606 100155 : parser->raw_tokens->quick_grow (raw_len + 1);
607 100155 : c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
608 100155 : return &(*parser->raw_tokens)[raw_len];
609 : }
610 :
611 : bool
612 44663642 : c_keyword_starts_typename (enum rid keyword)
613 : {
614 44663642 : switch (keyword)
615 : {
616 : case RID_UNSIGNED:
617 : case RID_LONG:
618 : case RID_SHORT:
619 : case RID_SIGNED:
620 : case RID_COMPLEX:
621 : case RID_INT:
622 : case RID_CHAR:
623 : case RID_FLOAT:
624 : case RID_DOUBLE:
625 : case RID_VOID:
626 : case RID_DFLOAT32:
627 : case RID_DFLOAT64:
628 : case RID_DFLOAT128:
629 : case RID_DFLOAT64X:
630 : CASE_RID_FLOATN_NX:
631 : case RID_BOOL:
632 : case RID_BITINT:
633 : case RID_ENUM:
634 : case RID_STRUCT:
635 : case RID_UNION:
636 : case RID_TYPEOF:
637 : case RID_TYPEOF_UNQUAL:
638 : case RID_CONST:
639 : case RID_ATOMIC:
640 : case RID_VOLATILE:
641 : case RID_RESTRICT:
642 : case RID_ATTRIBUTE:
643 : case RID_FRACT:
644 : case RID_ACCUM:
645 : case RID_SAT:
646 : case RID_AUTO_TYPE:
647 : case RID_ALIGNAS:
648 : return true;
649 36636666 : default:
650 36636666 : if (keyword >= RID_FIRST_INT_N
651 : && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
652 547 : && int_n_enabled_p[keyword - RID_FIRST_INT_N])
653 : return true;
654 : return false;
655 : }
656 : }
657 :
658 : /* Return true if TOKEN can start a type name,
659 : false otherwise. */
660 : bool
661 447778717 : c_token_starts_typename (c_token *token)
662 : {
663 447778717 : switch (token->type)
664 : {
665 396580538 : case CPP_NAME:
666 396580538 : switch (token->id_kind)
667 : {
668 : case C_ID_ID:
669 : return false;
670 : case C_ID_ADDRSPACE:
671 : return true;
672 : case C_ID_TYPENAME:
673 : return true;
674 0 : case C_ID_CLASSNAME:
675 0 : gcc_assert (c_dialect_objc ());
676 : return true;
677 0 : default:
678 0 : gcc_unreachable ();
679 : }
680 44608194 : case CPP_KEYWORD:
681 44608194 : return c_keyword_starts_typename (token->keyword);
682 0 : case CPP_LESS:
683 0 : if (c_dialect_objc ())
684 : return true;
685 : return false;
686 : default:
687 : return false;
688 : }
689 : }
690 :
691 : /* Return true if the next token from PARSER, starting from token N, can start
692 : a type name, false otherwise. LA specifies how to do lookahead in order to
693 : detect unknown type names. If unsure, pick CLA_PREFER_ID. */
694 :
695 : static inline bool
696 318973440 : c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la,
697 : unsigned int n = 1)
698 : {
699 318973440 : c_token *token = c_parser_peek_nth_token (parser, n);
700 318973440 : if (c_token_starts_typename (token))
701 : return true;
702 :
703 : /* Try a bit harder to detect an unknown typename. */
704 69631839 : if (la != cla_prefer_id
705 44364165 : && token->type == CPP_NAME
706 6474981 : && token->id_kind == C_ID_ID
707 :
708 : /* Do not try too hard when we could have "object in array". */
709 6474981 : && !parser->objc_could_be_foreach_context
710 :
711 6474981 : && (la == cla_prefer_type
712 6474888 : || c_parser_peek_nth_token (parser, n + 1)->type == CPP_NAME
713 6474804 : || c_parser_peek_nth_token (parser, n + 1)->type == CPP_MULT)
714 :
715 : /* Only unknown identifiers. */
716 69633273 : && !lookup_name (token->value))
717 : return true;
718 :
719 : return false;
720 : }
721 :
722 : /* Return true if TOKEN, after an open parenthesis, can start a
723 : compound literal (either a storage class specifier allowed in that
724 : context, or a type name), false otherwise. */
725 : static bool
726 128801361 : c_token_starts_compound_literal (c_token *token)
727 : {
728 128801361 : switch (token->type)
729 : {
730 4486994 : case CPP_KEYWORD:
731 4486994 : switch (token->keyword)
732 : {
733 : case RID_CONSTEXPR:
734 : case RID_REGISTER:
735 : case RID_STATIC:
736 : case RID_THREAD:
737 : return true;
738 : default:
739 : break;
740 : }
741 : /* Fall through. */
742 128801051 : default:
743 128801051 : return c_token_starts_typename (token);
744 : }
745 : }
746 :
747 : /* Return true if TOKEN is a type qualifier, false otherwise. */
748 : static bool
749 436638773 : c_token_is_qualifier (c_token *token)
750 : {
751 436638773 : switch (token->type)
752 : {
753 432820174 : case CPP_NAME:
754 432820174 : switch (token->id_kind)
755 : {
756 : case C_ID_ADDRSPACE:
757 : return true;
758 : default:
759 : return false;
760 : }
761 3818599 : case CPP_KEYWORD:
762 3818599 : switch (token->keyword)
763 : {
764 : case RID_CONST:
765 : case RID_VOLATILE:
766 : case RID_RESTRICT:
767 : case RID_ATTRIBUTE:
768 : case RID_ATOMIC:
769 : return true;
770 : default:
771 : return false;
772 : }
773 : case CPP_LESS:
774 : return false;
775 0 : default:
776 0 : gcc_unreachable ();
777 : }
778 : }
779 :
780 : /* Return true if the next token from PARSER is a type qualifier,
781 : false otherwise. */
782 : static inline bool
783 436638773 : c_parser_next_token_is_qualifier (c_parser *parser)
784 : {
785 436638773 : c_token *token = c_parser_peek_token (parser);
786 436638773 : return c_token_is_qualifier (token);
787 : }
788 :
789 : /* Return true if TOKEN can start declaration specifiers (not
790 : including standard attributes), false otherwise. */
791 : static bool
792 175959936 : c_token_starts_declspecs (c_token *token)
793 : {
794 175959936 : switch (token->type)
795 : {
796 98148205 : case CPP_NAME:
797 98148205 : switch (token->id_kind)
798 : {
799 : case C_ID_ID:
800 : return false;
801 : case C_ID_ADDRSPACE:
802 : return true;
803 : case C_ID_TYPENAME:
804 : return true;
805 0 : case C_ID_CLASSNAME:
806 0 : gcc_assert (c_dialect_objc ());
807 : return true;
808 0 : default:
809 0 : gcc_unreachable ();
810 : }
811 76123258 : case CPP_KEYWORD:
812 76123258 : switch (token->keyword)
813 : {
814 : case RID_STATIC:
815 : case RID_EXTERN:
816 : case RID_REGISTER:
817 : case RID_TYPEDEF:
818 : case RID_INLINE:
819 : case RID_NORETURN:
820 : case RID_AUTO:
821 : case RID_THREAD:
822 : case RID_UNSIGNED:
823 : case RID_LONG:
824 : case RID_SHORT:
825 : case RID_SIGNED:
826 : case RID_COMPLEX:
827 : case RID_INT:
828 : case RID_CHAR:
829 : case RID_FLOAT:
830 : case RID_DOUBLE:
831 : case RID_VOID:
832 : case RID_DFLOAT32:
833 : case RID_DFLOAT64:
834 : case RID_DFLOAT128:
835 : case RID_DFLOAT64X:
836 : CASE_RID_FLOATN_NX:
837 : case RID_BOOL:
838 : case RID_BITINT:
839 : case RID_ENUM:
840 : case RID_STRUCT:
841 : case RID_UNION:
842 : case RID_TYPEOF:
843 : case RID_TYPEOF_UNQUAL:
844 : case RID_CONST:
845 : case RID_VOLATILE:
846 : case RID_RESTRICT:
847 : case RID_ATTRIBUTE:
848 : case RID_FRACT:
849 : case RID_ACCUM:
850 : case RID_SAT:
851 : case RID_ALIGNAS:
852 : case RID_ATOMIC:
853 : case RID_AUTO_TYPE:
854 : case RID_CONSTEXPR:
855 : return true;
856 36288686 : default:
857 36288686 : if (token->keyword >= RID_FIRST_INT_N
858 : && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
859 461 : && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
860 : return true;
861 : return false;
862 : }
863 2 : case CPP_LESS:
864 2 : if (c_dialect_objc ())
865 : return true;
866 : return false;
867 : default:
868 : return false;
869 : }
870 : }
871 :
872 :
873 : /* Return true if TOKEN can start declaration specifiers (not
874 : including standard attributes) or a static assertion, false
875 : otherwise. */
876 : static bool
877 51076623 : c_token_starts_declaration (c_token *token)
878 : {
879 51076623 : if (c_token_starts_declspecs (token)
880 51076623 : || token->keyword == RID_STATIC_ASSERT)
881 7653270 : return true;
882 : else
883 : return false;
884 : }
885 :
886 : /* Return true if the next token from PARSER can start declaration
887 : specifiers (not including standard attributes), false
888 : otherwise. */
889 : bool
890 124883313 : c_parser_next_token_starts_declspecs (c_parser *parser)
891 : {
892 124883313 : c_token *token = c_parser_peek_token (parser);
893 :
894 : /* In Objective-C, a classname normally starts a declspecs unless it
895 : is immediately followed by a dot. In that case, it is the
896 : Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
897 : setter/getter on the class. c_token_starts_declspecs() can't
898 : differentiate between the two cases because it only checks the
899 : current token, so we have a special check here. */
900 124883313 : if (c_dialect_objc ()
901 0 : && token->type == CPP_NAME
902 0 : && token->id_kind == C_ID_CLASSNAME
903 124883313 : && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
904 : return false;
905 :
906 124883313 : return c_token_starts_declspecs (token);
907 : }
908 :
909 : static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
910 : unsigned int *);
911 :
912 : /* Return true if the next tokens from PARSER (starting with token N, 1-based)
913 : can start declaration specifiers (not including standard attributes) or a
914 : static assertion, false otherwise. */
915 : bool
916 51077921 : c_parser_next_tokens_start_declaration (c_parser *parser, unsigned int n)
917 : {
918 51077921 : c_token *token = c_parser_peek_nth_token (parser, n);
919 :
920 : /* Same as above. */
921 51077921 : if (c_dialect_objc ()
922 0 : && token->type == CPP_NAME
923 0 : && token->id_kind == C_ID_CLASSNAME
924 51077921 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_DOT)
925 : return false;
926 :
927 : /* Labels do not start declarations. */
928 51077921 : if (token->type == CPP_NAME
929 51077921 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_COLON)
930 : return false;
931 :
932 : /* A static assertion is only a declaration if followed by a semicolon;
933 : otherwise, it may be an expression in C2Y. */
934 51077903 : if (token->keyword == RID_STATIC_ASSERT
935 51077903 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_PAREN)
936 : {
937 1280 : n += 2;
938 1280 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
939 1280 : || c_parser_peek_nth_token_raw (parser, n)->type != CPP_CLOSE_PAREN)
940 : /* Invalid static assertion syntax; treat as a declaration and report a
941 : syntax error there. */
942 5 : return true;
943 1275 : return c_parser_peek_nth_token_raw (parser, n + 1)->type == CPP_SEMICOLON;
944 : }
945 :
946 51076623 : if (c_token_starts_declaration (token))
947 : return true;
948 :
949 43423353 : if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl, n))
950 : return true;
951 :
952 : return false;
953 : }
954 :
955 : /* Consume the next token from PARSER. */
956 :
957 : void
958 2312505190 : c_parser_consume_token (c_parser *parser)
959 : {
960 2312505190 : gcc_assert (parser->tokens_avail >= 1);
961 2312505190 : gcc_assert (parser->tokens[0].type != CPP_EOF);
962 2312505190 : gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
963 2312505190 : gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
964 2312505190 : parser->last_token_location = parser->tokens[0].location;
965 2312505190 : if (parser->tokens != &parser->tokens_buf[0])
966 45546 : parser->tokens++;
967 2312459644 : else if (parser->tokens_avail >= 2)
968 : {
969 152426053 : parser->tokens[0] = parser->tokens[1];
970 152426053 : if (parser->tokens_avail >= 3)
971 : {
972 32024 : parser->tokens[1] = parser->tokens[2];
973 32024 : if (parser->tokens_avail >= 4)
974 12572 : parser->tokens[2] = parser->tokens[3];
975 : }
976 : }
977 2312505190 : parser->tokens_avail--;
978 2312505190 : parser->seen_string_literal = false;
979 2312505190 : }
980 :
981 : /* Expect the current token to be a #pragma. Consume it and remember
982 : that we've begun parsing a pragma. */
983 :
984 : static void
985 1928572 : c_parser_consume_pragma (c_parser *parser)
986 : {
987 1928572 : gcc_assert (!parser->in_pragma);
988 1928572 : gcc_assert (parser->tokens_avail >= 1);
989 1928572 : gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
990 1928572 : if (parser->tokens != &parser->tokens_buf[0])
991 924 : parser->tokens++;
992 1927648 : else if (parser->tokens_avail >= 2)
993 : {
994 299 : parser->tokens[0] = parser->tokens[1];
995 299 : if (parser->tokens_avail >= 3)
996 10 : parser->tokens[1] = parser->tokens[2];
997 : }
998 1928572 : parser->tokens_avail--;
999 1928572 : parser->in_pragma = true;
1000 1928572 : }
1001 :
1002 : /* Update the global input_location from TOKEN. */
1003 : static inline void
1004 8152321 : c_parser_set_source_position_from_token (c_token *token)
1005 : {
1006 8152321 : if (token->type != CPP_EOF)
1007 : {
1008 8152245 : input_location = token->location;
1009 : }
1010 : }
1011 :
1012 : /* Helper function for c_parser_error.
1013 : Having peeked a token of kind TOK1_KIND that might signify
1014 : a conflict marker, peek successor tokens to determine
1015 : if we actually do have a conflict marker.
1016 : Specifically, we consider a run of 7 '<', '=' or '>' characters
1017 : at the start of a line as a conflict marker.
1018 : These come through the lexer as three pairs and a single,
1019 : e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
1020 : If it returns true, *OUT_LOC is written to with the location/range
1021 : of the marker. */
1022 :
1023 : static bool
1024 30 : c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
1025 : location_t *out_loc)
1026 : {
1027 30 : c_token *token2 = c_parser_peek_2nd_token (parser);
1028 30 : if (token2->type != tok1_kind)
1029 : return false;
1030 25 : c_token *token3 = c_parser_peek_nth_token (parser, 3);
1031 25 : if (token3->type != tok1_kind)
1032 : return false;
1033 22 : c_token *token4 = c_parser_peek_nth_token (parser, 4);
1034 22 : if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
1035 : return false;
1036 :
1037 : /* It must be at the start of the line. */
1038 15 : location_t start_loc = c_parser_peek_token (parser)->location;
1039 15 : if (LOCATION_COLUMN (start_loc) != 1)
1040 : return false;
1041 :
1042 : /* We have a conflict marker. Construct a location of the form:
1043 : <<<<<<<
1044 : ^~~~~~~
1045 : with start == caret, finishing at the end of the marker. */
1046 12 : location_t finish_loc = get_finish (token4->location);
1047 12 : *out_loc = make_location (start_loc, start_loc, finish_loc);
1048 :
1049 12 : return true;
1050 : }
1051 :
1052 : /* Issue a diagnostic of the form
1053 : FILE:LINE: MESSAGE before TOKEN
1054 : where TOKEN is the next token in the input stream of PARSER.
1055 : MESSAGE (specified by the caller) is usually of the form "expected
1056 : OTHER-TOKEN".
1057 :
1058 : Use RICHLOC as the location of the diagnostic.
1059 :
1060 : Do not issue a diagnostic if still recovering from an error.
1061 :
1062 : Return true iff an error was actually emitted.
1063 :
1064 : ??? This is taken from the C++ parser, but building up messages in
1065 : this way is not i18n-friendly and some other approach should be
1066 : used. */
1067 :
1068 : static bool
1069 3082 : c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1070 : rich_location *richloc)
1071 : {
1072 3082 : c_token *token = c_parser_peek_token (parser);
1073 3082 : if (parser->error)
1074 : return false;
1075 2349 : parser->error = true;
1076 2349 : if (!gmsgid)
1077 : return false;
1078 :
1079 : /* If this is actually a conflict marker, report it as such. */
1080 2234 : if (token->type == CPP_LSHIFT
1081 2234 : || token->type == CPP_RSHIFT
1082 2215 : || token->type == CPP_EQ_EQ)
1083 : {
1084 30 : location_t loc;
1085 30 : if (c_parser_peek_conflict_marker (parser, token->type, &loc))
1086 : {
1087 12 : error_at (loc, "version control conflict marker in file");
1088 12 : return true;
1089 : }
1090 : }
1091 :
1092 : /* If we were parsing a string-literal and there is an unknown name
1093 : token right after, then check to see if that could also have been
1094 : a literal string by checking the name against a list of known
1095 : standard string literal constants defined in header files. If
1096 : there is one, then add that as an hint to the error message. */
1097 2222 : auto_diagnostic_group d;
1098 2222 : name_hint h;
1099 2222 : if (parser->seen_string_literal && token->type == CPP_NAME)
1100 : {
1101 16 : tree name = token->value;
1102 16 : const char *token_name = IDENTIFIER_POINTER (name);
1103 16 : const char *header_hint
1104 16 : = get_c_stdlib_header_for_string_macro_name (token_name);
1105 16 : if (header_hint != NULL)
1106 48 : h = name_hint (nullptr,
1107 : std::make_unique<suggest_missing_header>
1108 32 : (token->location,
1109 : token_name,
1110 16 : header_hint));
1111 : }
1112 :
1113 2222 : c_parse_error (gmsgid,
1114 : /* Because c_parse_error does not understand
1115 : CPP_KEYWORD, keywords are treated like
1116 : identifiers. */
1117 2222 : (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
1118 : /* ??? The C parser does not save the cpp flags of a
1119 : token, we need to pass 0 here and we will not get
1120 : the source spelling of some tokens but rather the
1121 : canonical spelling. */
1122 : token->value, /*flags=*/0, richloc);
1123 2222 : return true;
1124 2222 : }
1125 :
1126 : /* As c_parser_error_richloc, but issue the message at the
1127 : location of PARSER's next token, or at input_location
1128 : if the next token is EOF. */
1129 :
1130 : bool
1131 1949 : c_parser_error (c_parser *parser, const char *gmsgid)
1132 : {
1133 1949 : c_token *token = c_parser_peek_token (parser);
1134 1949 : c_parser_set_source_position_from_token (token);
1135 1949 : rich_location richloc (line_table, input_location);
1136 1949 : return c_parser_error_richloc (parser, gmsgid, &richloc);
1137 1949 : }
1138 :
1139 : /* Some tokens naturally come in pairs e.g.'(' and ')'.
1140 : This class is for tracking such a matching pair of symbols.
1141 : In particular, it tracks the location of the first token,
1142 : so that if the second token is missing, we can highlight the
1143 : location of the first token when notifying the user about the
1144 : problem. */
1145 :
1146 : template <typename traits_t>
1147 : class token_pair
1148 : {
1149 : public:
1150 : /* token_pair's ctor. */
1151 176887235 : token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
1152 :
1153 : /* If the next token is the opening symbol for this pair, consume it and
1154 : return true.
1155 : Otherwise, issue an error and return false.
1156 : In either case, record the location of the opening token. */
1157 :
1158 4529317 : bool require_open (c_parser *parser)
1159 : {
1160 4529317 : c_token *token = c_parser_peek_token (parser);
1161 4529317 : if (token)
1162 4529317 : m_open_loc = token->location;
1163 :
1164 4529317 : return c_parser_require (parser, traits_t::open_token_type,
1165 4529317 : traits_t::open_gmsgid);
1166 : }
1167 :
1168 : /* Consume the next token from PARSER, recording its location as
1169 : that of the opening token within the pair. */
1170 :
1171 172358214 : void consume_open (c_parser *parser)
1172 : {
1173 172358214 : c_token *token = c_parser_peek_token (parser);
1174 172358214 : gcc_assert (token->type == traits_t::open_token_type);
1175 172358214 : m_open_loc = token->location;
1176 172358214 : c_parser_consume_token (parser);
1177 172358214 : }
1178 :
1179 : /* If the next token is the closing symbol for this pair, consume it
1180 : and return true.
1181 : Otherwise, issue an error, highlighting the location of the
1182 : corresponding opening token, and return false. */
1183 :
1184 1795772 : bool require_close (c_parser *parser) const
1185 : {
1186 1795772 : return c_parser_require (parser, traits_t::close_token_type,
1187 1795772 : traits_t::close_gmsgid, m_open_loc);
1188 : }
1189 :
1190 : /* Like token_pair::require_close, except that tokens will be skipped
1191 : until the desired token is found. An error message is still produced
1192 : if the next token is not as expected. */
1193 :
1194 173702336 : void skip_until_found_close (c_parser *parser) const
1195 : {
1196 173702336 : c_parser_skip_until_found (parser, traits_t::close_token_type,
1197 173702336 : traits_t::close_gmsgid, m_open_loc);
1198 49135 : }
1199 :
1200 : private:
1201 : location_t m_open_loc;
1202 : };
1203 :
1204 : /* Traits for token_pair<T> for tracking matching pairs of parentheses. */
1205 :
1206 : struct matching_paren_traits
1207 : {
1208 : static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
1209 : static const char * const open_gmsgid;
1210 : static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
1211 : static const char * const close_gmsgid;
1212 : };
1213 :
1214 : const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
1215 : const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
1216 :
1217 : /* "matching_parens" is a token_pair<T> class for tracking matching
1218 : pairs of parentheses. */
1219 :
1220 : typedef token_pair<matching_paren_traits> matching_parens;
1221 :
1222 : /* Traits for token_pair<T> for tracking matching pairs of braces. */
1223 :
1224 : struct matching_brace_traits
1225 : {
1226 : static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
1227 : static const char * const open_gmsgid;
1228 : static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
1229 : static const char * const close_gmsgid;
1230 : };
1231 :
1232 : const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
1233 : const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
1234 :
1235 : /* "matching_braces" is a token_pair<T> class for tracking matching
1236 : pairs of braces. */
1237 :
1238 : typedef token_pair<matching_brace_traits> matching_braces;
1239 :
1240 : /* Get a description of the matching symbol to TYPE e.g. "(" for
1241 : CPP_CLOSE_PAREN. */
1242 :
1243 : static const char *
1244 4 : get_matching_symbol (enum cpp_ttype type)
1245 : {
1246 4 : switch (type)
1247 : {
1248 0 : default:
1249 0 : gcc_unreachable ();
1250 : case CPP_CLOSE_PAREN:
1251 : return "(";
1252 1 : case CPP_CLOSE_BRACE:
1253 1 : return "{";
1254 : }
1255 : }
1256 :
1257 : /* If the next token is of the indicated TYPE, consume it. Otherwise,
1258 : issue the error MSGID. If MSGID is NULL then a message has already
1259 : been produced and no message will be produced this time. Returns
1260 : true if found, false otherwise.
1261 :
1262 : If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1263 : within any error as the location of an "opening" token matching
1264 : the close token TYPE (e.g. the location of the '(' when TYPE is
1265 : CPP_CLOSE_PAREN).
1266 :
1267 : If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
1268 : one type (e.g. "expected %<)%>") and thus it may be reasonable to
1269 : attempt to generate a fix-it hint for the problem.
1270 : Otherwise msgid describes multiple token types (e.g.
1271 : "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
1272 : generate a fix-it hint. */
1273 :
1274 : bool
1275 452509532 : c_parser_require (c_parser *parser,
1276 : enum cpp_ttype type,
1277 : const char *msgid,
1278 : location_t matching_location,
1279 : bool type_is_unique)
1280 : {
1281 452509532 : if (c_parser_next_token_is (parser, type))
1282 : {
1283 452508399 : c_parser_consume_token (parser);
1284 452508399 : return true;
1285 : }
1286 : else
1287 : {
1288 1133 : location_t next_token_loc = c_parser_peek_token (parser)->location;
1289 1133 : gcc_rich_location richloc (next_token_loc);
1290 :
1291 : /* Potentially supply a fix-it hint, suggesting to add the
1292 : missing token immediately after the *previous* token.
1293 : This may move the primary location within richloc. */
1294 1133 : if (!parser->error && type_is_unique)
1295 666 : maybe_suggest_missing_token_insertion (&richloc, type,
1296 : parser->last_token_location);
1297 :
1298 : /* If matching_location != UNKNOWN_LOCATION, highlight it.
1299 : Attempt to consolidate diagnostics by printing it as a
1300 : secondary range within the main diagnostic. */
1301 1133 : bool added_matching_location = false;
1302 1133 : if (matching_location != UNKNOWN_LOCATION)
1303 413 : added_matching_location
1304 413 : = richloc.add_location_if_nearby (*global_dc, matching_location);
1305 :
1306 1133 : if (c_parser_error_richloc (parser, msgid, &richloc))
1307 : /* If we weren't able to consolidate matching_location, then
1308 : print it as a secondary diagnostic. */
1309 559 : if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1310 4 : inform (matching_location, "to match this %qs",
1311 : get_matching_symbol (type));
1312 :
1313 1133 : return false;
1314 1133 : }
1315 : }
1316 :
1317 : /* If the next token is the indicated keyword, consume it. Otherwise,
1318 : issue the error MSGID. Returns true if found, false otherwise. */
1319 :
1320 : static bool
1321 145321 : c_parser_require_keyword (c_parser *parser,
1322 : enum rid keyword,
1323 : const char *msgid)
1324 : {
1325 145321 : if (c_parser_next_token_is_keyword (parser, keyword))
1326 : {
1327 145320 : c_parser_consume_token (parser);
1328 145320 : return true;
1329 : }
1330 : else
1331 : {
1332 1 : c_parser_error (parser, msgid);
1333 1 : return false;
1334 : }
1335 : }
1336 :
1337 : /* Like c_parser_require, except that tokens will be skipped until the
1338 : desired token is found. An error message is still produced if the
1339 : next token is not as expected. If MSGID is NULL then a message has
1340 : already been produced and no message will be produced this
1341 : time.
1342 :
1343 : If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1344 : within any error as the location of an "opening" token matching
1345 : the close token TYPE (e.g. the location of the '(' when TYPE is
1346 : CPP_CLOSE_PAREN). */
1347 :
1348 : void
1349 225742117 : c_parser_skip_until_found (c_parser *parser,
1350 : enum cpp_ttype type,
1351 : const char *msgid,
1352 : location_t matching_location)
1353 : {
1354 225742117 : unsigned nesting_depth = 0;
1355 :
1356 225742117 : if (c_parser_require (parser, type, msgid, matching_location))
1357 : {
1358 225741214 : if (UNLIKELY (type == CPP_PRAGMA_EOL) && parser->in_omp_attribute_pragma)
1359 : {
1360 0 : c_token *token = c_parser_peek_token (parser);
1361 0 : if (token->type == CPP_EOF)
1362 : {
1363 0 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1364 0 : parser->tokens_avail
1365 0 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1366 0 : parser->in_omp_attribute_pragma = NULL;
1367 : }
1368 : }
1369 225741214 : return;
1370 : }
1371 :
1372 : /* Skip tokens until the desired token is found. */
1373 6033 : while (true)
1374 : {
1375 : /* Peek at the next token. */
1376 3468 : c_token *token = c_parser_peek_token (parser);
1377 : /* If we've reached the token we want, consume it and stop. */
1378 3468 : if (token->type == type && !nesting_depth)
1379 : {
1380 700 : c_parser_consume_token (parser);
1381 700 : if (UNLIKELY (type == CPP_PRAGMA_EOL)
1382 108 : && parser->in_omp_attribute_pragma)
1383 : {
1384 1 : c_token *token = c_parser_peek_token (parser);
1385 1 : if (token->type == CPP_EOF)
1386 : {
1387 1 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1388 1 : parser->tokens_avail
1389 1 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1390 1 : parser->in_omp_attribute_pragma = NULL;
1391 : }
1392 : }
1393 : break;
1394 : }
1395 :
1396 : /* If we've run out of tokens, stop. */
1397 2768 : if (token->type == CPP_EOF)
1398 : return;
1399 2749 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1400 : return;
1401 2683 : if (token->type == CPP_OPEN_BRACE
1402 : || token->type == CPP_OPEN_PAREN
1403 : || token->type == CPP_OPEN_SQUARE)
1404 296 : ++nesting_depth;
1405 : else if (token->type == CPP_CLOSE_BRACE
1406 : || token->type == CPP_CLOSE_PAREN
1407 : || token->type == CPP_CLOSE_SQUARE)
1408 : {
1409 414 : if (nesting_depth-- == 0)
1410 : break;
1411 : }
1412 : /* Consume this token. */
1413 2565 : c_parser_consume_token (parser);
1414 2565 : }
1415 818 : parser->error = false;
1416 : }
1417 :
1418 : /* Skip tokens until the end of a parameter is found, but do not
1419 : consume the comma, semicolon or closing delimiter. */
1420 :
1421 : static void
1422 97 : c_parser_skip_to_end_of_parameter (c_parser *parser)
1423 : {
1424 97 : unsigned nesting_depth = 0;
1425 :
1426 501 : while (true)
1427 : {
1428 299 : c_token *token = c_parser_peek_token (parser);
1429 299 : if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1430 25 : && !nesting_depth)
1431 : break;
1432 : /* If we've run out of tokens, stop. */
1433 274 : if (token->type == CPP_EOF)
1434 : return;
1435 274 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1436 : return;
1437 274 : if (token->type == CPP_OPEN_BRACE
1438 : || token->type == CPP_OPEN_PAREN
1439 : || token->type == CPP_OPEN_SQUARE)
1440 3 : ++nesting_depth;
1441 : else if (token->type == CPP_CLOSE_BRACE
1442 : || token->type == CPP_CLOSE_PAREN
1443 : || token->type == CPP_CLOSE_SQUARE)
1444 : {
1445 75 : if (nesting_depth-- == 0)
1446 : break;
1447 : }
1448 : /* Consume this token. */
1449 202 : c_parser_consume_token (parser);
1450 202 : }
1451 97 : parser->error = false;
1452 : }
1453 :
1454 : /* Skip tokens until a non-nested closing curly brace is the next
1455 : token, or there are no more tokens. Return true in the first case,
1456 : false otherwise. */
1457 :
1458 : static bool
1459 26 : c_parser_skip_to_closing_brace (c_parser *parser)
1460 : {
1461 26 : unsigned nesting_depth = 0;
1462 :
1463 96 : while (true)
1464 : {
1465 61 : c_token *token = c_parser_peek_token (parser);
1466 :
1467 61 : switch (token->type)
1468 : {
1469 2 : case CPP_PRAGMA_EOL:
1470 2 : if (!parser->in_pragma)
1471 : break;
1472 : /* FALLTHRU */
1473 : case CPP_EOF:
1474 : /* If we've run out of tokens, stop. */
1475 : return false;
1476 :
1477 24 : case CPP_CLOSE_BRACE:
1478 : /* If the next token is a non-nested `}', then we have reached
1479 : the end of the current block. */
1480 24 : if (nesting_depth-- == 0)
1481 : return true;
1482 : break;
1483 :
1484 0 : case CPP_OPEN_BRACE:
1485 : /* If it the next token is a `{', then we are entering a new
1486 : block. Consume the entire block. */
1487 0 : ++nesting_depth;
1488 0 : break;
1489 :
1490 : default:
1491 : break;
1492 : }
1493 :
1494 : /* Consume the token. */
1495 35 : c_parser_consume_token (parser);
1496 35 : }
1497 : }
1498 :
1499 : /* Expect to be at the end of the pragma directive and consume an
1500 : end of line marker. */
1501 :
1502 : static void
1503 1929714 : c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1504 : {
1505 1929714 : gcc_assert (parser->in_pragma);
1506 1929714 : parser->in_pragma = false;
1507 :
1508 1929714 : if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
1509 197 : c_parser_error (parser, "expected end of line");
1510 :
1511 1931094 : cpp_ttype token_type;
1512 1931094 : do
1513 : {
1514 1931094 : c_token *token = c_parser_peek_token (parser);
1515 1931094 : token_type = token->type;
1516 1931094 : if (token_type == CPP_EOF)
1517 : break;
1518 1931094 : c_parser_consume_token (parser);
1519 : }
1520 1931094 : while (token_type != CPP_PRAGMA_EOL);
1521 :
1522 1929714 : if (parser->in_omp_attribute_pragma)
1523 : {
1524 754 : c_token *token = c_parser_peek_token (parser);
1525 754 : if (token->type == CPP_EOF)
1526 : {
1527 607 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1528 607 : parser->tokens_avail
1529 607 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1530 607 : parser->in_omp_attribute_pragma = NULL;
1531 : }
1532 : }
1533 :
1534 1929714 : parser->error = false;
1535 1929714 : }
1536 :
1537 : /* Skip tokens up to and including "#pragma omp end declare variant".
1538 : Properly handle nested "#pragma omp begin declare variant" pragmas. */
1539 : static void
1540 6 : c_parser_skip_to_pragma_omp_end_declare_variant (c_parser *parser)
1541 : {
1542 166 : for (int depth = 0; depth >= 0; )
1543 : {
1544 160 : c_token *token = c_parser_peek_token (parser);
1545 :
1546 160 : switch (token->type)
1547 : {
1548 0 : case CPP_PRAGMA_EOL:
1549 0 : if (!parser->in_pragma)
1550 : break;
1551 : /* FALLTHRU */
1552 : case CPP_EOF:
1553 : /* If we've run out of tokens, stop. */
1554 : return;
1555 :
1556 10 : case CPP_PRAGMA:
1557 10 : if ((token->pragma_kind == PRAGMA_OMP_BEGIN
1558 8 : || token->pragma_kind == PRAGMA_OMP_END)
1559 10 : && c_parser_peek_nth_token (parser, 2)->type == CPP_NAME
1560 20 : && c_parser_peek_nth_token (parser, 3)->type == CPP_NAME)
1561 : {
1562 10 : tree id1 = c_parser_peek_nth_token (parser, 2)->value;
1563 10 : tree id2 = c_parser_peek_nth_token (parser, 3)->value;
1564 10 : if (strcmp (IDENTIFIER_POINTER (id1), "declare") == 0
1565 20 : && strcmp (IDENTIFIER_POINTER (id2), "variant") == 0)
1566 : {
1567 10 : if (token->pragma_kind == PRAGMA_OMP_BEGIN)
1568 2 : depth++;
1569 : else
1570 8 : depth--;
1571 : }
1572 : }
1573 10 : c_parser_consume_pragma (parser);
1574 10 : c_parser_skip_to_pragma_eol (parser, false);
1575 10 : continue;
1576 :
1577 : default:
1578 : break;
1579 10 : }
1580 :
1581 : /* Consume the token. */
1582 150 : c_parser_consume_token (parser);
1583 : }
1584 : }
1585 :
1586 : /* Skip tokens until we have consumed an entire block, or until we
1587 : have consumed a non-nested ';'. */
1588 :
1589 : static void
1590 488 : c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
1591 : bool metadirective_p = false)
1592 : {
1593 488 : unsigned nesting_depth = 0;
1594 488 : int bracket_depth = 0;
1595 488 : bool save_error = parser->error;
1596 :
1597 1791 : while (true)
1598 : {
1599 1791 : c_token *token;
1600 :
1601 : /* Peek at the next token. */
1602 1791 : token = c_parser_peek_token (parser);
1603 :
1604 1791 : switch (token->type)
1605 : {
1606 : case CPP_EOF:
1607 : return;
1608 :
1609 0 : case CPP_PRAGMA_EOL:
1610 0 : if (parser->in_pragma)
1611 : return;
1612 : break;
1613 :
1614 425 : case CPP_SEMICOLON:
1615 : /* If the next token is a ';', we have reached the
1616 : end of the statement. */
1617 425 : if (!nesting_depth && (!metadirective_p || bracket_depth <= 0))
1618 : {
1619 : /* Consume the ';'. */
1620 360 : c_parser_consume_token (parser);
1621 360 : goto finished;
1622 : }
1623 : break;
1624 :
1625 110 : case CPP_CLOSE_BRACE:
1626 : /* If the next token is a non-nested '}', then we have
1627 : reached the end of the current block. */
1628 61 : if ((nesting_depth == 0 || --nesting_depth == 0)
1629 171 : && (!metadirective_p || bracket_depth <= 0))
1630 : {
1631 110 : c_parser_consume_token (parser);
1632 110 : goto finished;
1633 : }
1634 : break;
1635 :
1636 61 : case CPP_OPEN_BRACE:
1637 : /* If it the next token is a '{', then we are entering a new
1638 : block. Consume the entire block. */
1639 61 : ++nesting_depth;
1640 61 : break;
1641 :
1642 64 : case CPP_OPEN_PAREN:
1643 : /* Track parentheses in case the statement is a standalone 'for'
1644 : statement - we want to skip over the semicolons separating the
1645 : operands. */
1646 64 : if (metadirective_p && nesting_depth == 0)
1647 2 : ++bracket_depth;
1648 : break;
1649 :
1650 90 : case CPP_CLOSE_PAREN:
1651 90 : if (metadirective_p && nesting_depth == 0)
1652 2 : --bracket_depth;
1653 : break;
1654 :
1655 7 : case CPP_PRAGMA:
1656 : /* If we see a pragma, consume the whole thing at once. We
1657 : have some safeguards against consuming pragmas willy-nilly.
1658 : Normally, we'd expect to be here with parser->error set,
1659 : which disables these safeguards. But it's possible to get
1660 : here for secondary error recovery, after parser->error has
1661 : been cleared. */
1662 7 : c_parser_consume_pragma (parser);
1663 7 : c_parser_skip_to_pragma_eol (parser, false);
1664 7 : parser->error = save_error;
1665 7 : continue;
1666 :
1667 : default:
1668 : break;
1669 : }
1670 :
1671 1296 : c_parser_consume_token (parser);
1672 : }
1673 :
1674 470 : finished:
1675 470 : parser->error = false;
1676 : }
1677 :
1678 : /* CPP's options (initialized by c-opts.cc). */
1679 : extern cpp_options *cpp_opts;
1680 :
1681 : /* Save the warning flags which are controlled by __extension__. */
1682 :
1683 : static inline int
1684 975963 : disable_extension_diagnostics (void)
1685 : {
1686 1951926 : int ret = (pedantic
1687 975963 : | (warn_pointer_arith << 1)
1688 975963 : | (warn_traditional << 2)
1689 975963 : | (flag_iso << 3)
1690 975963 : | (warn_long_long << 4)
1691 975963 : | (warn_cxx_compat << 5)
1692 975963 : | (warn_overlength_strings << 6)
1693 : /* warn_c90_c99_compat has three states: -1/0/1, so we must
1694 : play tricks to properly restore it. */
1695 975963 : | ((warn_c90_c99_compat == 1) << 7)
1696 975963 : | ((warn_c90_c99_compat == -1) << 8)
1697 : /* Similarly for warn_c99_c11_compat. */
1698 975963 : | ((warn_c99_c11_compat == 1) << 9)
1699 975963 : | ((warn_c99_c11_compat == -1) << 10)
1700 : /* Similarly for warn_c11_c23_compat. */
1701 975963 : | ((warn_c11_c23_compat == 1) << 11)
1702 975963 : | ((warn_c11_c23_compat == -1) << 12)
1703 : /* Similarly for warn_c23_c2y_compat. */
1704 975963 : | ((warn_c23_c2y_compat == 1) << 13)
1705 975963 : | ((warn_c23_c2y_compat == -1) << 14)
1706 : );
1707 975963 : cpp_opts->cpp_pedantic = pedantic = 0;
1708 975963 : warn_pointer_arith = 0;
1709 975963 : cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1710 975963 : flag_iso = 0;
1711 975963 : cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1712 975963 : warn_cxx_compat = 0;
1713 975963 : warn_overlength_strings = 0;
1714 975963 : warn_c90_c99_compat = 0;
1715 975963 : warn_c99_c11_compat = 0;
1716 975963 : warn_c11_c23_compat = 0;
1717 975963 : warn_c23_c2y_compat = 0;
1718 975963 : return ret;
1719 : }
1720 :
1721 : /* Restore the warning flags which are controlled by __extension__.
1722 : FLAGS is the return value from disable_extension_diagnostics. */
1723 :
1724 : static inline void
1725 975963 : restore_extension_diagnostics (int flags)
1726 : {
1727 975963 : cpp_opts->cpp_pedantic = pedantic = flags & 1;
1728 975963 : warn_pointer_arith = (flags >> 1) & 1;
1729 975963 : cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1730 975963 : flag_iso = (flags >> 3) & 1;
1731 975963 : cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1732 975963 : warn_cxx_compat = (flags >> 5) & 1;
1733 975963 : warn_overlength_strings = (flags >> 6) & 1;
1734 : /* See above for why is this needed. */
1735 975963 : warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1736 975963 : warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1737 975963 : warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1738 975963 : warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
1739 975963 : }
1740 :
1741 : /* Helper data structure for parsing #pragma acc routine. */
1742 : struct oacc_routine_data {
1743 : bool error_seen; /* Set if error has been reported. */
1744 : bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
1745 : tree clauses;
1746 : location_t loc;
1747 : };
1748 :
1749 : /* Used for parsing objc foreach statements. */
1750 : static tree objc_foreach_break_label, objc_foreach_continue_label;
1751 :
1752 : /* Used for parsing OMP for loops.
1753 :
1754 : Some notes on flags used for context:
1755 : parser->omp_for_parse_state is non-null anywhere inside the OMP FOR
1756 : construct, except for the final-loop-body.
1757 : The want_nested_loop flag is true if inside a {} sequence where
1758 : a loop-nest (or another {} sequence containing a loop-nest) is expected,
1759 : but has not yet been seen. It's false when parsing intervening code
1760 : statements or their substatements that cannot contain a loop-nest.
1761 : The in_intervening_code flag is true when parsing any intervening code,
1762 : including substatements, and whether or not want_nested_loop is true.
1763 :
1764 : And, about error handling:
1765 : The saw_intervening_code flag is set if the loop is not perfectly
1766 : nested, even in the usual case where this is not an error.
1767 : perfect_nesting_fail is set if an error has been diagnosed because an
1768 : imperfectly-nested loop was found where a perfectly-nested one is
1769 : required (we diagnose this only once).
1770 : fail is set if any kind of structural error in the loop nest
1771 : has been found and diagnosed.
1772 : */
1773 : struct omp_for_parse_data {
1774 : enum tree_code code;
1775 : tree declv, condv, incrv, initv;
1776 : tree pre_body;
1777 : tree bindings;
1778 : int count; /* Expected nesting depth. */
1779 : int depth; /* Current nesting depth. */
1780 : location_t for_loc;
1781 : bool ordered : 1;
1782 : bool inscan : 1;
1783 : bool want_nested_loop : 1;
1784 : bool in_intervening_code : 1;
1785 : bool saw_intervening_code: 1;
1786 : bool perfect_nesting_fail : 1;
1787 : bool fail : 1;
1788 : };
1789 :
1790 : struct attr_state
1791 : {
1792 : /* True if we parsed a musttail attribute for return. */
1793 : bool musttail_p;
1794 : };
1795 :
1796 : static bool c_parser_nth_token_starts_std_attributes (c_parser *,
1797 : unsigned int);
1798 : static tree c_parser_std_attribute_specifier_sequence (c_parser *);
1799 : static void c_parser_external_declaration (c_parser *);
1800 : static void c_parser_asm_definition (c_parser *);
1801 : static tree c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
1802 : bool, bool, bool, tree * = NULL,
1803 : vec<c_token> * = NULL,
1804 : bool have_attrs = false,
1805 : tree attrs = NULL,
1806 : struct oacc_routine_data * = NULL,
1807 : bool * = NULL);
1808 : static bool c_parser_handle_statement_omp_attributes (c_parser *, tree &,
1809 : bool *);
1810 : static void c_parser_static_assert_declaration_no_semi (c_parser *);
1811 : static void c_parser_static_assert_declaration (c_parser *);
1812 : static struct c_typespec c_parser_enum_specifier (c_parser *);
1813 : static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
1814 : static tree c_parser_struct_declaration (c_parser *, tree *);
1815 : static struct c_typespec c_parser_typeof_specifier (c_parser *);
1816 : static tree c_parser_alignas_specifier (c_parser *);
1817 : static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
1818 : c_dtr_syn, bool *);
1819 : static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
1820 : bool,
1821 : struct c_declarator *);
1822 : static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
1823 : bool);
1824 : static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
1825 : tree, bool);
1826 : static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
1827 : static tree c_parser_asm_string_literal (c_parser *);
1828 : static tree c_parser_simple_asm_expr (c_parser *);
1829 : static tree c_parser_gnu_attributes (c_parser *);
1830 : static struct c_expr c_parser_initializer (c_parser *, tree);
1831 : static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
1832 : struct obstack *, bool);
1833 : static void c_parser_initelt (c_parser *, struct obstack *);
1834 : static void c_parser_initval (c_parser *, struct c_expr *,
1835 : struct obstack *);
1836 : static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
1837 : static location_t c_parser_compound_statement_nostart (c_parser *);
1838 : static void c_parser_label (c_parser *, tree);
1839 : static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
1840 : static void c_parser_statement_after_labels (c_parser *, bool *, tree,
1841 : vec<tree> * = NULL,
1842 : attr_state = {});
1843 : static tree c_parser_c99_block_statement (c_parser *, bool *,
1844 : location_t * = NULL);
1845 : static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
1846 : static void c_parser_switch_statement (c_parser *, bool *, tree);
1847 : static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
1848 : bool *, tree);
1849 : static void c_parser_do_statement (c_parser *, bool, unsigned short, bool,
1850 : tree);
1851 : static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
1852 : bool *, tree);
1853 : static tree c_parser_asm_statement (c_parser *);
1854 : static tree c_parser_asm_operands (c_parser *);
1855 : static tree c_parser_asm_goto_operands (c_parser *);
1856 : static tree c_parser_asm_clobbers (c_parser *);
1857 : static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
1858 : tree = NULL_TREE);
1859 : static struct c_expr c_parser_conditional_expression (c_parser *,
1860 : struct c_expr *, tree);
1861 : static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
1862 : tree);
1863 : static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
1864 : static struct c_expr c_parser_unary_expression (c_parser *);
1865 : static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
1866 : enum rid);
1867 : static struct c_expr c_parser_alignof_expression (c_parser *);
1868 : static struct c_expr c_parser_maxof_or_minof_expression (c_parser *, enum rid);
1869 : static struct c_expr c_parser_postfix_expression (c_parser *);
1870 : static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
1871 : struct c_declspecs *,
1872 : struct c_type_name *,
1873 : location_t);
1874 : static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
1875 : location_t loc,
1876 : struct c_expr);
1877 : static tree c_parser_transaction (c_parser *, enum rid);
1878 : static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
1879 : static tree c_parser_transaction_cancel (c_parser *);
1880 : static struct c_expr c_parser_expression (c_parser *);
1881 : static struct c_expr c_parser_expression_conv (c_parser *);
1882 : static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
1883 : vec<tree, va_gc> **, location_t *,
1884 : tree *, vec<location_t> *,
1885 : unsigned int * = NULL);
1886 : static struct c_expr c_parser_has_attribute_expression (c_parser *);
1887 :
1888 : static void c_parser_oacc_declare (c_parser *);
1889 : static void c_parser_oacc_enter_exit_data (c_parser *, bool);
1890 : static void c_parser_oacc_update (c_parser *);
1891 : static void c_parser_omp_construct (c_parser *, bool *);
1892 : static void c_parser_omp_groupprivate (c_parser *);
1893 : static void c_parser_omp_threadprivate (c_parser *);
1894 : static void c_parser_omp_barrier (c_parser *);
1895 : static void c_parser_omp_depobj (c_parser *);
1896 : static void c_parser_omp_flush (c_parser *);
1897 : static bool c_parser_omp_next_tokens_can_be_canon_loop (c_parser *,
1898 : enum tree_code, bool);
1899 : static tree c_parser_omp_loop_nest (c_parser *, bool *);
1900 : static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
1901 : tree, tree *, bool *);
1902 : static void c_parser_omp_taskwait (c_parser *);
1903 : static void c_parser_omp_taskyield (c_parser *);
1904 : static void c_parser_omp_cancel (c_parser *);
1905 : static void c_parser_omp_nothing (c_parser *);
1906 : static void c_parser_omp_metadirective (c_parser *, bool *);
1907 :
1908 : enum pragma_context { pragma_external, pragma_struct, pragma_param,
1909 : pragma_stmt, pragma_compound };
1910 : static bool c_parser_pragma (c_parser *, enum pragma_context, bool *, tree);
1911 : static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
1912 : static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
1913 : static void c_parser_omp_begin (c_parser *);
1914 : static void c_parser_omp_end (c_parser *);
1915 : static bool c_parser_omp_declare (c_parser *, enum pragma_context);
1916 : static void c_parser_omp_requires (c_parser *);
1917 : static bool c_parser_omp_error (c_parser *, enum pragma_context);
1918 : static void c_parser_omp_assumption_clauses (c_parser *, bool);
1919 : static void c_parser_omp_allocate (c_parser *);
1920 : static void c_parser_omp_assumes (c_parser *);
1921 : static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
1922 : static tree c_parser_omp_dispatch (location_t, c_parser *);
1923 : static void c_parser_omp_interop (c_parser *);
1924 : static void c_parser_oacc_routine (c_parser *, enum pragma_context);
1925 :
1926 : /* These Objective-C parser functions are only ever called when
1927 : compiling Objective-C. */
1928 : static void c_parser_objc_class_definition (c_parser *, tree);
1929 : static void c_parser_objc_class_instance_variables (c_parser *);
1930 : static void c_parser_objc_class_declaration (c_parser *);
1931 : static void c_parser_objc_alias_declaration (c_parser *);
1932 : static void c_parser_objc_protocol_definition (c_parser *, tree);
1933 : static bool c_parser_objc_method_type (c_parser *);
1934 : static void c_parser_objc_method_definition (c_parser *);
1935 : static void c_parser_objc_methodprotolist (c_parser *);
1936 : static void c_parser_objc_methodproto (c_parser *);
1937 : static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
1938 : static tree c_parser_objc_type_name (c_parser *);
1939 : static tree c_parser_objc_protocol_refs (c_parser *);
1940 : static void c_parser_objc_try_catch_finally_statement (c_parser *);
1941 : static void c_parser_objc_synchronized_statement (c_parser *);
1942 : static tree c_parser_objc_selector (c_parser *);
1943 : static tree c_parser_objc_selector_arg (c_parser *);
1944 : static tree c_parser_objc_receiver (c_parser *);
1945 : static tree c_parser_objc_message_args (c_parser *);
1946 : static tree c_parser_objc_keywordexpr (c_parser *);
1947 : static void c_parser_objc_at_property_declaration (c_parser *);
1948 : static void c_parser_objc_at_synthesize_declaration (c_parser *);
1949 : static void c_parser_objc_at_dynamic_declaration (c_parser *);
1950 : static bool c_parser_objc_diagnose_bad_element_prefix
1951 : (c_parser *, struct c_declspecs *);
1952 : static location_t c_parser_parse_rtl_body (c_parser *, char *);
1953 : static tree c_parser_handle_musttail (c_parser *, tree, attr_state &);
1954 :
1955 : #if ENABLE_ANALYZER
1956 :
1957 : namespace ana {
1958 :
1959 : /* Concrete implementation of ana::translation_unit for the C frontend. */
1960 :
1961 : class c_translation_unit : public translation_unit
1962 : {
1963 : public:
1964 : /* Implementation of translation_unit::lookup_constant_by_id for use by the
1965 : analyzer to look up named constants in the user's source code. */
1966 7155 : tree lookup_constant_by_id (tree id) const final override
1967 : {
1968 : /* Consider decls. */
1969 7155 : if (tree decl = lookup_name (id))
1970 42 : if (TREE_CODE (decl) == CONST_DECL)
1971 42 : if (tree value = DECL_INITIAL (decl))
1972 42 : if (TREE_CODE (value) == INTEGER_CST)
1973 : return value;
1974 :
1975 : /* Consider macros. */
1976 7113 : cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1977 7113 : if (cpp_macro_p (hashnode))
1978 48 : if (tree value = consider_macro (hashnode->value.macro))
1979 : return value;
1980 :
1981 : return NULL_TREE;
1982 : }
1983 :
1984 : tree
1985 4 : lookup_type_by_id (tree id) const final override
1986 : {
1987 4 : if (tree type_decl = lookup_name (id))
1988 0 : if (TREE_CODE (type_decl) == TYPE_DECL)
1989 : {
1990 0 : tree record_type = TREE_TYPE (type_decl);
1991 0 : if (TREE_CODE (record_type) == RECORD_TYPE)
1992 0 : return record_type;
1993 : }
1994 :
1995 : return NULL_TREE;
1996 : }
1997 :
1998 : tree
1999 2 : lookup_global_var_by_id (tree id) const final override
2000 : {
2001 2 : if (tree var_decl = lookup_name (id))
2002 0 : if (TREE_CODE (var_decl) == VAR_DECL)
2003 0 : return var_decl;
2004 :
2005 : return NULL_TREE;
2006 : }
2007 :
2008 : private:
2009 : /* Attempt to get an INTEGER_CST from MACRO.
2010 : Only handle the simplest cases: where MACRO's definition is a single
2011 : token containing a number, by lexing the number again.
2012 : This will handle e.g.
2013 : #define NAME 42
2014 : and other bases but not negative numbers, parentheses or e.g.
2015 : #define NAME 1 << 7
2016 : as doing so would require a parser. */
2017 48 : tree consider_macro (cpp_macro *macro) const
2018 : {
2019 48 : if (macro->paramc > 0)
2020 : return NULL_TREE;
2021 45 : if (macro->kind != cmk_macro)
2022 : return NULL_TREE;
2023 45 : if (macro->count != 1)
2024 : return NULL_TREE;
2025 39 : const cpp_token &tok = macro->exp.tokens[0];
2026 39 : if (tok.type != CPP_NUMBER)
2027 : return NULL_TREE;
2028 :
2029 36 : cpp_reader *old_parse_in = parse_in;
2030 36 : parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
2031 :
2032 36 : pretty_printer pp;
2033 36 : pp_string (&pp, (const char *) tok.val.str.text);
2034 36 : pp_newline (&pp);
2035 72 : cpp_push_buffer (parse_in,
2036 36 : (const unsigned char *) pp_formatted_text (&pp),
2037 : strlen (pp_formatted_text (&pp)),
2038 : 0);
2039 :
2040 36 : tree value;
2041 36 : location_t loc;
2042 36 : unsigned char cpp_flags;
2043 36 : c_lex_with_flags (&value, &loc, &cpp_flags, 0);
2044 :
2045 36 : cpp_destroy (parse_in);
2046 36 : parse_in = old_parse_in;
2047 :
2048 36 : if (value && TREE_CODE (value) == INTEGER_CST)
2049 36 : return value;
2050 :
2051 : return NULL_TREE;
2052 36 : }
2053 : };
2054 :
2055 : } // namespace ana
2056 :
2057 : #endif /* #if ENABLE_ANALYZER */
2058 :
2059 : /* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
2060 :
2061 : translation-unit:
2062 : external-declarations
2063 :
2064 : external-declarations:
2065 : external-declaration
2066 : external-declarations external-declaration
2067 :
2068 : GNU extensions:
2069 :
2070 : translation-unit:
2071 : empty
2072 : */
2073 :
2074 : static void
2075 105296 : c_parser_translation_unit (c_parser *parser)
2076 : {
2077 105296 : if (c_parser_next_token_is (parser, CPP_EOF))
2078 : {
2079 1229 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2080 : "ISO C forbids an empty translation unit");
2081 : }
2082 : else
2083 : {
2084 104067 : void *obstack_position = obstack_alloc (&parser_obstack, 0);
2085 104067 : mark_valid_location_for_stdc_pragma (false);
2086 58163954 : do
2087 : {
2088 58163954 : ggc_collect ();
2089 58163954 : c_parser_external_declaration (parser);
2090 58163949 : obstack_free (&parser_obstack, obstack_position);
2091 : }
2092 58163949 : while (c_parser_next_token_is_not (parser, CPP_EOF));
2093 : }
2094 :
2095 : unsigned int i;
2096 : tree decl;
2097 105341 : FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
2098 135 : if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
2099 37 : error ("storage size of %q+D isn%'t known", decl);
2100 :
2101 105206 : if (vec_safe_length (current_omp_declare_target_attribute))
2102 : {
2103 4 : c_omp_declare_target_attr
2104 4 : a = current_omp_declare_target_attribute->pop ();
2105 4 : if (!errorcount)
2106 3 : error ("%qs without corresponding %qs",
2107 : a.device_type >= 0 ? "#pragma omp begin declare target"
2108 : : "#pragma omp declare target",
2109 : "#pragma omp end declare target");
2110 8 : vec_safe_truncate (current_omp_declare_target_attribute, 0);
2111 : }
2112 105206 : if (vec_safe_length (current_omp_begin_assumes))
2113 : {
2114 1 : if (!errorcount)
2115 1 : error ("%qs without corresponding %qs",
2116 : "#pragma omp begin assumes", "#pragma omp end assumes");
2117 1 : vec_safe_truncate (current_omp_begin_assumes, 0);
2118 : }
2119 105206 : if (vec_safe_length (current_omp_declare_variant_attribute))
2120 : {
2121 0 : if (!errorcount)
2122 0 : error ("%<omp begin declare variant%> without corresponding "
2123 : "%<omp end declare variant%>");
2124 0 : vec_safe_truncate (current_omp_declare_variant_attribute, 0);
2125 : }
2126 105206 : if (vec_safe_length (omp_begin_declare_variant_map))
2127 : {
2128 : unsigned int i;
2129 : omp_begin_declare_variant_map_entry *e;
2130 32 : FOR_EACH_VEC_ELT (*omp_begin_declare_variant_map, i, e)
2131 24 : omp_finish_variant_function (e->variant, e->id, e->ctx);
2132 8 : vec_safe_truncate (omp_begin_declare_variant_map, 0);
2133 : }
2134 :
2135 : #if ENABLE_ANALYZER
2136 105206 : if (flag_analyzer)
2137 : {
2138 1431 : ana::c_translation_unit tu;
2139 1431 : ana::on_finish_translation_unit (tu);
2140 : }
2141 : #endif
2142 105206 : }
2143 :
2144 : /* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
2145 :
2146 : external-declaration:
2147 : function-definition
2148 : declaration
2149 :
2150 : GNU extensions:
2151 :
2152 : external-declaration:
2153 : asm-definition
2154 : ;
2155 : __extension__ external-declaration
2156 :
2157 : Objective-C:
2158 :
2159 : external-declaration:
2160 : objc-class-definition
2161 : objc-class-declaration
2162 : objc-alias-declaration
2163 : objc-protocol-definition
2164 : objc-method-definition
2165 : @end
2166 : */
2167 :
2168 : static void
2169 58613461 : c_parser_external_declaration (c_parser *parser)
2170 : {
2171 58613461 : int ext;
2172 58613461 : switch (c_parser_peek_token (parser)->type)
2173 : {
2174 56799346 : case CPP_KEYWORD:
2175 56799346 : switch (c_parser_peek_token (parser)->keyword)
2176 : {
2177 449507 : case RID_EXTENSION:
2178 449507 : ext = disable_extension_diagnostics ();
2179 449507 : c_parser_consume_token (parser);
2180 449507 : c_parser_external_declaration (parser);
2181 449507 : restore_extension_diagnostics (ext);
2182 449507 : break;
2183 214 : case RID_ASM:
2184 214 : c_parser_asm_definition (parser);
2185 214 : break;
2186 0 : case RID_AT_INTERFACE:
2187 0 : case RID_AT_IMPLEMENTATION:
2188 0 : gcc_assert (c_dialect_objc ());
2189 0 : c_parser_objc_class_definition (parser, NULL_TREE);
2190 0 : break;
2191 0 : case RID_AT_CLASS:
2192 0 : gcc_assert (c_dialect_objc ());
2193 0 : c_parser_objc_class_declaration (parser);
2194 0 : break;
2195 0 : case RID_AT_ALIAS:
2196 0 : gcc_assert (c_dialect_objc ());
2197 0 : c_parser_objc_alias_declaration (parser);
2198 0 : break;
2199 0 : case RID_AT_PROTOCOL:
2200 0 : gcc_assert (c_dialect_objc ());
2201 0 : c_parser_objc_protocol_definition (parser, NULL_TREE);
2202 0 : break;
2203 0 : case RID_AT_PROPERTY:
2204 0 : gcc_assert (c_dialect_objc ());
2205 0 : c_parser_objc_at_property_declaration (parser);
2206 0 : break;
2207 0 : case RID_AT_SYNTHESIZE:
2208 0 : gcc_assert (c_dialect_objc ());
2209 0 : c_parser_objc_at_synthesize_declaration (parser);
2210 0 : break;
2211 0 : case RID_AT_DYNAMIC:
2212 0 : gcc_assert (c_dialect_objc ());
2213 0 : c_parser_objc_at_dynamic_declaration (parser);
2214 0 : break;
2215 0 : case RID_AT_END:
2216 0 : gcc_assert (c_dialect_objc ());
2217 0 : c_parser_consume_token (parser);
2218 0 : objc_finish_implementation ();
2219 0 : break;
2220 56349625 : default:
2221 56349625 : goto decl_or_fndef;
2222 : }
2223 : break;
2224 2136 : case CPP_SEMICOLON:
2225 2136 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2226 : "ISO C does not allow extra %<;%> outside of a function");
2227 2136 : c_parser_consume_token (parser);
2228 2136 : break;
2229 1588943 : case CPP_PRAGMA:
2230 1588943 : mark_valid_location_for_stdc_pragma (true);
2231 1588943 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2232 1588943 : mark_valid_location_for_stdc_pragma (false);
2233 1588943 : break;
2234 1 : case CPP_PLUS:
2235 1 : case CPP_MINUS:
2236 1 : if (c_dialect_objc ())
2237 : {
2238 0 : c_parser_objc_method_definition (parser);
2239 0 : break;
2240 : }
2241 : /* Else fall through, and yield a syntax error trying to parse
2242 : as a declaration or function definition. */
2243 : /* FALLTHRU */
2244 56572661 : default:
2245 1 : decl_or_fndef:
2246 : /* A declaration or a function definition (or, in Objective-C,
2247 : an @interface or @protocol with prefix attributes). We can
2248 : only tell which after parsing the declaration specifiers, if
2249 : any, and the first declarator. */
2250 56572661 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
2251 : false);
2252 56572661 : break;
2253 : }
2254 58613456 : }
2255 :
2256 : static void c_parser_handle_directive_omp_attributes (tree &, vec<c_token> *&,
2257 : vec<c_token> *);
2258 : static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
2259 : static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
2260 :
2261 : /* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
2262 :
2263 : static void
2264 106925724 : add_debug_begin_stmt (location_t loc)
2265 : {
2266 : /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2267 106925724 : if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2268 104179523 : return;
2269 :
2270 2746201 : tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2271 2746201 : SET_EXPR_LOCATION (stmt, loc);
2272 2746201 : add_stmt (stmt);
2273 : }
2274 :
2275 : /* Helper function for c_parser_declaration_or_fndef and
2276 : Handle assume attribute(s). */
2277 :
2278 : static tree
2279 38 : handle_assume_attribute (location_t here, tree attrs, bool nested)
2280 : {
2281 38 : if (nested)
2282 78 : for (tree attr = lookup_attribute ("gnu", "assume", attrs); attr;
2283 41 : attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr)))
2284 : {
2285 41 : tree args = TREE_VALUE (attr);
2286 41 : int nargs = list_length (args);
2287 41 : if (nargs != 1)
2288 : {
2289 6 : error_at (here, "wrong number of arguments specified "
2290 : "for %qE attribute",
2291 : get_attribute_name (attr));
2292 6 : inform (here, "expected %i, found %i", 1, nargs);
2293 : }
2294 : else
2295 : {
2296 35 : tree arg = TREE_VALUE (args);
2297 35 : arg = c_objc_common_truthvalue_conversion (here, arg);
2298 35 : arg = c_fully_fold (arg, false, NULL);
2299 35 : if (arg != error_mark_node)
2300 : {
2301 33 : tree fn = build_call_expr_internal_loc (here, IFN_ASSUME,
2302 : void_type_node, 1,
2303 : arg);
2304 33 : add_stmt (fn);
2305 : }
2306 : }
2307 : }
2308 : else
2309 1 : pedwarn (here, OPT_Wattributes,
2310 : "%<assume%> attribute at top level");
2311 :
2312 38 : return remove_attribute ("gnu", "assume", attrs);
2313 : }
2314 :
2315 : /* We might need to reclassify any previously-lexed identifier, e.g.
2316 : when we've left a for loop with an if-statement without else in the
2317 : body - we might have used a wrong scope for the token. See PR67784. */
2318 :
2319 : static void
2320 37885556 : c_parser_maybe_reclassify_token (c_parser *parser)
2321 : {
2322 37885556 : if (c_parser_next_token_is (parser, CPP_NAME))
2323 : {
2324 203650 : c_token *token = c_parser_peek_token (parser);
2325 :
2326 203650 : if (token->id_kind == C_ID_ID || token->id_kind == C_ID_TYPENAME)
2327 : {
2328 203649 : tree decl = lookup_name (token->value);
2329 :
2330 203649 : token->id_kind = C_ID_ID;
2331 203649 : if (decl)
2332 : {
2333 200608 : if (TREE_CODE (decl) == TYPE_DECL)
2334 2233 : token->id_kind = C_ID_TYPENAME;
2335 : }
2336 3041 : else if (c_dialect_objc ())
2337 : {
2338 0 : tree objc_interface_decl = objc_is_class_name (token->value);
2339 : /* Objective-C class names are in the same namespace as
2340 : variables and typedefs, and hence are shadowed by local
2341 : declarations. */
2342 0 : if (objc_interface_decl)
2343 : {
2344 0 : token->value = objc_interface_decl;
2345 0 : token->id_kind = C_ID_CLASSNAME;
2346 : }
2347 : }
2348 : }
2349 : }
2350 37885556 : }
2351 :
2352 : /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
2353 : 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
2354 : is accepted; otherwise (old-style parameter declarations) only other
2355 : declarations are accepted. If STATIC_ASSERT_OK is true, a static
2356 : assertion is accepted; otherwise (old-style parameter declarations)
2357 : it is not. If NESTED is true, we are inside a function or parsing
2358 : old-style parameter declarations; any functions encountered are
2359 : nested functions and declaration specifiers are required; otherwise
2360 : we are at top level and functions are normal functions and
2361 : declaration specifiers may be optional. If EMPTY_OK is true, empty
2362 : declarations are OK (subject to all other constraints); otherwise
2363 : (old-style parameter declarations) they are diagnosed. If
2364 : START_ATTR_OK is true, the declaration specifiers may start with
2365 : attributes (GNU or standard); otherwise they may not.
2366 : OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
2367 : declaration when parsing an Objective-C foreach statement.
2368 : FALLTHRU_ATTR_P is used to signal whether this function parsed
2369 : "__attribute__((fallthrough));". ATTRS are any standard attributes
2370 : parsed in the caller (in contexts where such attributes had to be
2371 : parsed to determine whether what follows is a declaration or a
2372 : statement); HAVE_ATTRS says whether there were any such attributes
2373 : (even empty). If SIMPLE_OK, the construct can be a simple-declaration;
2374 : in that case, the ';' is not consumed (left to the caller so that it
2375 : can figure out if there was a simple-declaration or not), there must
2376 : be an initializer, and only one object may be declared. When SIMPLE_OK
2377 : is true we are called from c_parser_selection_header.
2378 :
2379 : Returns the resulting declaration, if there was any with an initializer.
2380 :
2381 : declaration:
2382 : declaration-specifiers init-declarator-list[opt] ;
2383 : static_assert-declaration
2384 :
2385 : function-definition:
2386 : declaration-specifiers[opt] declarator declaration-list[opt]
2387 : compound-statement
2388 :
2389 : declaration-list:
2390 : declaration
2391 : declaration-list declaration
2392 :
2393 : init-declarator-list:
2394 : init-declarator
2395 : init-declarator-list , init-declarator
2396 :
2397 : init-declarator:
2398 : declarator simple-asm-expr[opt] gnu-attributes[opt]
2399 : declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
2400 :
2401 : simple-declaration:
2402 : attribute-specifier-sequence[opt] declaration-specifiers declarator
2403 : = initializer
2404 :
2405 : GNU extensions:
2406 :
2407 : nested-function-definition:
2408 : declaration-specifiers declarator declaration-list[opt]
2409 : compound-statement
2410 :
2411 : attribute ;
2412 :
2413 : Objective-C:
2414 : gnu-attributes objc-class-definition
2415 : gnu-attributes objc-category-definition
2416 : gnu-attributes objc-protocol-definition
2417 :
2418 : The simple-asm-expr and gnu-attributes are GNU extensions.
2419 :
2420 : This function does not handle __extension__; that is handled in its
2421 : callers. ??? Following the old parser, __extension__ may start
2422 : external declarations, declarations in functions and declarations
2423 : at the start of "for" loops, but not old-style parameter
2424 : declarations.
2425 :
2426 : C99 requires declaration specifiers in a function definition; the
2427 : absence is diagnosed through the diagnosis of implicit int. In GNU
2428 : C we also allow but diagnose declarations without declaration
2429 : specifiers, but only at top level (elsewhere they conflict with
2430 : other syntax).
2431 :
2432 : In Objective-C, declarations of the looping variable in a foreach
2433 : statement are exceptionally terminated by 'in' (for example, 'for
2434 : (NSObject *object in array) { ... }').
2435 :
2436 : OpenMP:
2437 :
2438 : declaration:
2439 : threadprivate-directive
2440 :
2441 : GIMPLE:
2442 :
2443 : gimple-function-definition:
2444 : declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
2445 : declaration-list[opt] compound-statement
2446 :
2447 : rtl-function-definition:
2448 : declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
2449 : declaration-list[opt] compound-statement */
2450 :
2451 : static tree
2452 64239168 : c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
2453 : bool static_assert_ok, bool empty_ok,
2454 : bool nested, bool start_attr_ok,
2455 : bool simple_ok,
2456 : tree *objc_foreach_object_declaration
2457 : /* = NULL */,
2458 : vec<c_token> *omp_declare_simd_clauses
2459 : /* = NULL */,
2460 : bool have_attrs /* = false */,
2461 : tree attrs /* = NULL_TREE */,
2462 : struct oacc_routine_data *oacc_routine_data
2463 : /* = NULL */,
2464 : bool *fallthru_attr_p /* = NULL */)
2465 : {
2466 64239168 : struct c_declspecs *specs;
2467 64239168 : tree prefix_attrs;
2468 64239168 : tree all_prefix_attrs;
2469 64239168 : bool diagnosed_no_specs = false;
2470 64239168 : location_t here = c_parser_peek_token (parser)->location;
2471 64239168 : tree result = NULL_TREE;
2472 :
2473 64239168 : add_debug_begin_stmt (c_parser_peek_token (parser)->location);
2474 :
2475 64239168 : if (static_assert_ok
2476 128464989 : && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
2477 : {
2478 1948 : c_parser_static_assert_declaration (parser);
2479 1948 : return result;
2480 : }
2481 64237220 : specs = build_null_declspecs ();
2482 :
2483 : /* Handle any standard attributes parsed in the caller. */
2484 64237220 : if (have_attrs)
2485 : {
2486 143 : declspecs_add_attrs (here, specs, attrs);
2487 143 : specs->non_std_attrs_seen_p = false;
2488 : }
2489 :
2490 : /* Try to detect an unknown type name when we have "A B" or "A *B". */
2491 64237220 : if (c_parser_peek_token (parser)->type == CPP_NAME
2492 5895650 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
2493 9295 : && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2494 9186 : || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2495 64237353 : && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2496 : {
2497 131 : tree name = c_parser_peek_token (parser)->value;
2498 :
2499 : /* Issue a warning about NAME being an unknown type name, perhaps
2500 : with some kind of hint.
2501 : If the user forgot a "struct" etc, suggest inserting
2502 : it. Otherwise, attempt to look for misspellings. */
2503 131 : gcc_rich_location richloc (here);
2504 131 : if (tag_exists_p (RECORD_TYPE, name))
2505 : {
2506 : /* This is not C++ with its implicit typedef. */
2507 3 : richloc.add_fixit_insert_before ("struct ");
2508 3 : error_at (&richloc,
2509 : "unknown type name %qE;"
2510 : " use %<struct%> keyword to refer to the type",
2511 : name);
2512 : }
2513 128 : else if (tag_exists_p (UNION_TYPE, name))
2514 : {
2515 3 : richloc.add_fixit_insert_before ("union ");
2516 3 : error_at (&richloc,
2517 : "unknown type name %qE;"
2518 : " use %<union%> keyword to refer to the type",
2519 : name);
2520 : }
2521 125 : else if (tag_exists_p (ENUMERAL_TYPE, name))
2522 : {
2523 3 : richloc.add_fixit_insert_before ("enum ");
2524 3 : error_at (&richloc,
2525 : "unknown type name %qE;"
2526 : " use %<enum%> keyword to refer to the type",
2527 : name);
2528 : }
2529 : else
2530 : {
2531 122 : auto_diagnostic_group d;
2532 122 : name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2533 122 : here);
2534 122 : if (const char *suggestion = hint.suggestion ())
2535 : {
2536 12 : richloc.add_fixit_replace (suggestion);
2537 12 : error_at (&richloc,
2538 : "unknown type name %qE; did you mean %qs?",
2539 : name, suggestion);
2540 : }
2541 : else
2542 110 : error_at (here, "unknown type name %qE", name);
2543 122 : }
2544 :
2545 : /* Parse declspecs normally to get a correct pointer type, but avoid
2546 : a further "fails to be a type name" error. Refuse nested functions
2547 : since it is not how the user likely wants us to recover. */
2548 131 : c_parser_peek_token (parser)->type = CPP_KEYWORD;
2549 131 : c_parser_peek_token (parser)->keyword = RID_VOID;
2550 131 : c_parser_peek_token (parser)->value = error_mark_node;
2551 131 : fndef_ok = !nested;
2552 131 : }
2553 :
2554 : /* When there are standard attributes at the start of the
2555 : declaration (to apply to the entity being declared), an
2556 : init-declarator-list or function definition must be present. */
2557 64237220 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
2558 602 : have_attrs = true;
2559 :
2560 64237220 : c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2561 : true, true, start_attr_ok, true, cla_nonabstract_decl);
2562 64237220 : if (parser->error)
2563 : {
2564 33 : c_parser_skip_to_end_of_block_or_statement (parser);
2565 33 : return result;
2566 : }
2567 64237187 : if (nested && !specs->declspecs_seen_p)
2568 : {
2569 63 : c_parser_error (parser, "expected declaration specifiers");
2570 63 : c_parser_skip_to_end_of_block_or_statement (parser);
2571 63 : return result;
2572 : }
2573 :
2574 64237124 : finish_declspecs (specs);
2575 : /* When the decl is declared, its type is a top level type, we should
2576 : call verify_counted_by_for_top_anonymous_type. */
2577 64237124 : if (specs->typespec_kind == ctsk_tagdef)
2578 1192288 : verify_counted_by_for_top_anonymous_type (specs->type);
2579 :
2580 64237124 : bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2581 64237124 : bool std_auto_type_p = specs->c23_auto_p;
2582 64237124 : bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2583 64237124 : gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2584 64237124 : const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2585 64237124 : if (specs->constexpr_p)
2586 : {
2587 : /* An underspecified declaration may not declare tags or members
2588 : or structures or unions; it is undefined behavior to declare
2589 : the members of an enumeration. Where the structure, union or
2590 : enumeration type is declared within an initializer, this is
2591 : diagnosed elsewhere. Diagnose here the case of declaring
2592 : such a type in the type specifiers of a constexpr
2593 : declaration. */
2594 368 : switch (specs->typespec_kind)
2595 : {
2596 6 : case ctsk_tagfirstref:
2597 6 : case ctsk_tagfirstref_attrs:
2598 6 : error_at (here, "%qT declared in underspecified object declaration",
2599 : specs->type);
2600 6 : break;
2601 :
2602 10 : case ctsk_tagdef:
2603 10 : error_at (here, "%qT defined in underspecified object declaration",
2604 : specs->type);
2605 10 : break;
2606 :
2607 : default:
2608 : break;
2609 : }
2610 : }
2611 :
2612 64237124 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
2613 : {
2614 501899 : bool handled_assume = false;
2615 501899 : if (specs->attrs
2616 504 : && !nested
2617 127 : && specs->typespec_kind == ctsk_none
2618 502008 : && c_parser_handle_statement_omp_attributes (parser, specs->attrs,
2619 : NULL))
2620 : {
2621 88 : if (specs->attrs)
2622 0 : c_warn_unused_attributes (specs->attrs);
2623 177 : while (parser->in_omp_attribute_pragma)
2624 : {
2625 89 : gcc_assert (c_parser_next_token_is (parser, CPP_PRAGMA));
2626 89 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2627 : }
2628 88 : c_parser_consume_token (parser);
2629 88 : return result;
2630 : }
2631 501811 : if (specs->typespec_kind == ctsk_none
2632 501811 : && lookup_attribute ("gnu", "assume", specs->attrs))
2633 : {
2634 38 : handled_assume = true;
2635 38 : specs->attrs
2636 38 : = handle_assume_attribute (here, specs->attrs, nested);
2637 : }
2638 501811 : if (any_auto_type_p)
2639 6 : error_at (here, "%qs in empty declaration", auto_type_keyword);
2640 501805 : else if (specs->typespec_kind == ctsk_none
2641 501805 : && attribute_fallthrough_p (specs->attrs))
2642 : {
2643 328 : if (fallthru_attr_p != NULL)
2644 327 : *fallthru_attr_p = true;
2645 328 : if (nested)
2646 : {
2647 327 : tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2648 : void_type_node, 0);
2649 327 : add_stmt (fn);
2650 : }
2651 : else
2652 1 : pedwarn (here, OPT_Wattributes,
2653 : "%<fallthrough%> attribute at top level");
2654 : }
2655 501477 : else if (empty_ok
2656 501460 : && !(have_attrs && specs->non_std_attrs_seen_p)
2657 501457 : && !handled_assume)
2658 501419 : shadow_tag (specs);
2659 : else
2660 : {
2661 58 : shadow_tag_warned (specs, 1);
2662 58 : if (!handled_assume)
2663 20 : pedwarn (here, 0, "empty declaration");
2664 : }
2665 : /* We still have to evaluate size expressions. */
2666 501811 : if (specs->expr)
2667 107 : add_stmt (fold_convert (void_type_node, specs->expr));
2668 501811 : c_parser_consume_token (parser);
2669 501811 : if (oacc_routine_data)
2670 0 : c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2671 501811 : return result;
2672 : }
2673 63735225 : else if (specs->typespec_kind == ctsk_none
2674 : && nested
2675 : /* Only parse __attribute__((musttail)) when called from
2676 : c_parser_compound_statement_nostart. This certainly isn't
2677 : a declaration in that case, but we don't do tentative parsing
2678 : of GNU attributes right now. */
2679 9772 : && fallthru_attr_p
2680 63735306 : && c_parser_next_token_is_keyword (parser, RID_RETURN))
2681 : {
2682 12 : attr_state astate = {};
2683 12 : specs->attrs = c_parser_handle_musttail (parser, specs->attrs, astate);
2684 12 : if (astate.musttail_p)
2685 : {
2686 12 : if (specs->attrs)
2687 : {
2688 0 : auto_urlify_attributes sentinel;
2689 0 : warning_at (c_parser_peek_token (parser)->location,
2690 0 : OPT_Wattributes,
2691 : "attribute %<musttail%> mixed with other attributes "
2692 : "on %<return%> statement");
2693 0 : }
2694 12 : c_parser_statement_after_labels (parser, NULL, NULL_TREE, NULL,
2695 : astate);
2696 12 : return result;
2697 : }
2698 : }
2699 :
2700 : /* Provide better error recovery. Note that a type name here is usually
2701 : better diagnosed as a redeclaration. */
2702 63735213 : if (empty_ok
2703 63722080 : && specs->typespec_kind == ctsk_tagdef
2704 779031 : && c_parser_next_token_starts_declspecs (parser)
2705 63735243 : && !c_parser_next_token_is (parser, CPP_NAME))
2706 : {
2707 9 : c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
2708 9 : parser->error = false;
2709 9 : shadow_tag_warned (specs, 1);
2710 9 : return result;
2711 : }
2712 63735204 : else if (c_dialect_objc () && !any_auto_type_p)
2713 : {
2714 : /* Prefix attributes are an error on method decls. */
2715 0 : switch (c_parser_peek_token (parser)->type)
2716 : {
2717 0 : case CPP_PLUS:
2718 0 : case CPP_MINUS:
2719 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2720 : return result;
2721 0 : if (specs->attrs)
2722 : {
2723 0 : warning_at (c_parser_peek_token (parser)->location,
2724 0 : OPT_Wattributes,
2725 : "prefix attributes are ignored for methods");
2726 0 : specs->attrs = NULL_TREE;
2727 : }
2728 0 : if (fndef_ok)
2729 0 : c_parser_objc_method_definition (parser);
2730 : else
2731 0 : c_parser_objc_methodproto (parser);
2732 0 : return result;
2733 0 : break;
2734 0 : default:
2735 0 : break;
2736 : }
2737 : /* This is where we parse 'attributes @interface ...',
2738 : 'attributes @implementation ...', 'attributes @protocol ...'
2739 : (where attributes could be, for example, __attribute__
2740 : ((deprecated)).
2741 : */
2742 0 : switch (c_parser_peek_token (parser)->keyword)
2743 : {
2744 0 : case RID_AT_INTERFACE:
2745 0 : {
2746 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2747 : return result;
2748 0 : c_parser_objc_class_definition (parser, specs->attrs);
2749 0 : return result;
2750 : }
2751 0 : break;
2752 0 : case RID_AT_IMPLEMENTATION:
2753 0 : {
2754 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2755 : return result;
2756 0 : if (specs->attrs)
2757 : {
2758 0 : warning_at (c_parser_peek_token (parser)->location,
2759 0 : OPT_Wattributes,
2760 : "prefix attributes are ignored for implementations");
2761 0 : specs->attrs = NULL_TREE;
2762 : }
2763 0 : c_parser_objc_class_definition (parser, NULL_TREE);
2764 0 : return result;
2765 : }
2766 0 : break;
2767 0 : case RID_AT_PROTOCOL:
2768 0 : {
2769 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2770 : return result;
2771 0 : c_parser_objc_protocol_definition (parser, specs->attrs);
2772 0 : return result;
2773 : }
2774 0 : break;
2775 0 : case RID_AT_ALIAS:
2776 0 : case RID_AT_CLASS:
2777 0 : case RID_AT_END:
2778 0 : case RID_AT_PROPERTY:
2779 0 : if (specs->attrs)
2780 : {
2781 0 : c_parser_error (parser, "unexpected attribute");
2782 0 : specs->attrs = NULL;
2783 : }
2784 : break;
2785 : default:
2786 : break;
2787 : }
2788 : }
2789 63735204 : else if (attribute_fallthrough_p (specs->attrs))
2790 5 : warning_at (here, OPT_Wattributes,
2791 : "%<fallthrough%> attribute not followed by %<;%>");
2792 63735199 : else if (lookup_attribute ("gnu", "assume", specs->attrs))
2793 2 : warning_at (here, OPT_Wattributes,
2794 : "%<assume%> attribute not followed by %<;%>");
2795 :
2796 127470403 : auto_vec<c_token> omp_declare_simd_attr_clauses;
2797 63735204 : c_parser_handle_directive_omp_attributes (specs->attrs,
2798 : omp_declare_simd_clauses,
2799 : &omp_declare_simd_attr_clauses);
2800 63735204 : pending_xref_error ();
2801 63735204 : prefix_attrs = specs->attrs;
2802 63735204 : all_prefix_attrs = prefix_attrs;
2803 63735204 : specs->attrs = NULL_TREE;
2804 63735204 : bool more_than_one_decl = false;
2805 64585756 : while (true)
2806 : {
2807 64160480 : struct c_declarator *declarator;
2808 64160480 : bool dummy = false;
2809 64160480 : timevar_id_t tv;
2810 64160480 : tree fnbody = NULL_TREE;
2811 64160480 : tree underspec_name = NULL_TREE;
2812 64160480 : auto_vec<c_token> omp_dsimd_idattr_clauses;
2813 : /* Declaring either one or more declarators (in which case we
2814 : should diagnose if there were no declaration specifiers) or a
2815 : function definition (in which case the diagnostic for
2816 : implicit int suffices). */
2817 128320960 : declarator = c_parser_declarator (parser,
2818 64160480 : specs->typespec_kind != ctsk_none,
2819 : C_DTR_NORMAL, &dummy);
2820 64160480 : if (declarator == NULL)
2821 : {
2822 211 : if (omp_declare_simd_clauses)
2823 1 : c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2824 : omp_declare_simd_clauses);
2825 211 : if (oacc_routine_data)
2826 0 : c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2827 : /* This check is here purely to improve the diagnostic. */
2828 211 : if (!simple_ok)
2829 191 : c_parser_skip_to_end_of_block_or_statement (parser);
2830 211 : return result;
2831 : }
2832 64160269 : if (flag_openmp || flag_openmp_simd)
2833 : {
2834 : struct c_declarator *d = declarator;
2835 857716 : while (d->kind != cdk_id)
2836 372924 : d = d->declarator;
2837 484792 : vec<c_token> *dummy = NULL;
2838 484792 : c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2839 : &omp_dsimd_idattr_clauses);
2840 : }
2841 64160269 : if (gnu_auto_type_p && declarator->kind != cdk_id)
2842 : {
2843 1 : error_at (here,
2844 : "%<__auto_type%> requires a plain identifier"
2845 : " as declarator");
2846 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2847 1 : return result;
2848 : }
2849 64160268 : if (std_auto_type_p)
2850 : {
2851 : struct c_declarator *d = declarator;
2852 82 : while (d->kind == cdk_attrs)
2853 0 : d = d->declarator;
2854 82 : if (d->kind != cdk_id)
2855 : {
2856 1 : error_at (here,
2857 : "%<auto%> requires a plain identifier, possibly with"
2858 : " attributes, as declarator");
2859 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2860 1 : return result;
2861 : }
2862 81 : underspec_name = d->u.id.id;
2863 : }
2864 64160186 : else if (specs->constexpr_p)
2865 : {
2866 : struct c_declarator *d = declarator;
2867 432 : while (d->kind != cdk_id)
2868 79 : d = d->declarator;
2869 353 : underspec_name = d->u.id.id;
2870 : }
2871 64160267 : if (c_parser_next_token_is (parser, CPP_EQ)
2872 57824493 : || c_parser_next_token_is (parser, CPP_COMMA)
2873 57515825 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
2874 49481048 : || c_parser_next_token_is_keyword (parser, RID_ASM)
2875 48609602 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
2876 100410687 : || c_parser_next_token_is_keyword (parser, RID_IN))
2877 : {
2878 27909847 : tree asm_name = NULL_TREE;
2879 27909847 : tree postfix_attrs = NULL_TREE;
2880 27909847 : if (!diagnosed_no_specs && !specs->declspecs_seen_p)
2881 : {
2882 79 : diagnosed_no_specs = true;
2883 79 : pedwarn (here, 0, "data definition has no type or storage class");
2884 : }
2885 : /* Having seen a data definition, there cannot now be a
2886 : function definition. */
2887 27909847 : fndef_ok = false;
2888 27909847 : if (c_parser_next_token_is_keyword (parser, RID_ASM))
2889 871446 : asm_name = c_parser_simple_asm_expr (parser);
2890 27909847 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
2891 : {
2892 13181331 : postfix_attrs = c_parser_gnu_attributes (parser);
2893 13181331 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
2894 : {
2895 : /* This means there is an attribute specifier after
2896 : the declarator in a function definition. Provide
2897 : some more information for the user. */
2898 1 : error_at (here, "attributes should be specified before the "
2899 : "declarator in a function definition");
2900 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2901 1 : return result;
2902 : }
2903 : }
2904 27909846 : if (c_parser_next_token_is (parser, CPP_EQ))
2905 : {
2906 6337213 : tree d;
2907 6337213 : struct c_expr init;
2908 6337213 : location_t init_loc;
2909 6337213 : c_parser_consume_token (parser);
2910 6337213 : if (any_auto_type_p)
2911 : {
2912 1953 : init_loc = c_parser_peek_token (parser)->location;
2913 1953 : rich_location richloc (line_table, init_loc);
2914 1953 : unsigned int underspec_state = 0;
2915 1953 : if (std_auto_type_p)
2916 79 : underspec_state =
2917 79 : start_underspecified_init (init_loc, underspec_name);
2918 1953 : start_init (NULL_TREE, asm_name,
2919 1953 : (global_bindings_p ()
2920 1889 : || specs->storage_class == csc_static
2921 3840 : || specs->constexpr_p),
2922 1953 : specs->constexpr_p, &richloc);
2923 : /* A parameter is initialized, which is invalid. Don't
2924 : attempt to instrument the initializer. */
2925 1953 : sanitize_code_type flag_sanitize_save = flag_sanitize;
2926 1953 : if (nested && !empty_ok)
2927 30 : flag_sanitize = 0;
2928 1953 : init = c_parser_expr_no_commas (parser, NULL);
2929 1953 : if (std_auto_type_p)
2930 79 : finish_underspecified_init (underspec_name,
2931 : underspec_state);
2932 1953 : flag_sanitize = flag_sanitize_save;
2933 1953 : if (gnu_auto_type_p
2934 1874 : && TREE_CODE (init.value) == COMPONENT_REF
2935 1954 : && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
2936 1 : error_at (here,
2937 : "%<__auto_type%> used with a bit-field"
2938 : " initializer");
2939 1953 : init = convert_lvalue_to_rvalue (init_loc, init, true, true,
2940 : true);
2941 1953 : tree init_type = TREE_TYPE (init.value);
2942 1953 : bool vm_type = c_type_variably_modified_p (init_type);
2943 1953 : if (vm_type)
2944 95 : init.value = save_expr (init.value);
2945 1953 : finish_init ();
2946 1953 : specs->typespec_kind = ctsk_typeof;
2947 1953 : specs->locations[cdw_typedef] = init_loc;
2948 1953 : specs->typedef_p = true;
2949 1953 : specs->type = init_type;
2950 1953 : if (specs->postfix_attrs)
2951 : {
2952 : /* Postfix [[]] attributes are valid with C23
2953 : auto, although not with __auto_type, and
2954 : modify the type given by the initializer. */
2955 2 : specs->postfix_attrs
2956 2 : = c_warn_type_attributes (specs->type,
2957 : specs->postfix_attrs);
2958 2 : decl_attributes (&specs->type, specs->postfix_attrs, 0);
2959 2 : specs->postfix_attrs = NULL_TREE;
2960 : }
2961 1953 : if (vm_type)
2962 : {
2963 95 : bool maybe_const = true;
2964 95 : tree type_expr = c_fully_fold (init.value, false,
2965 : &maybe_const);
2966 95 : specs->expr_const_operands &= maybe_const;
2967 95 : if (specs->expr)
2968 0 : specs->expr = build2 (COMPOUND_EXPR,
2969 0 : TREE_TYPE (type_expr),
2970 : specs->expr, type_expr);
2971 : else
2972 95 : specs->expr = type_expr;
2973 : }
2974 1953 : d = start_decl (declarator, specs, true,
2975 : chainon (postfix_attrs, all_prefix_attrs));
2976 1953 : if (!d)
2977 12 : d = error_mark_node;
2978 1953 : if (omp_declare_simd_clauses)
2979 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2980 : omp_declare_simd_clauses);
2981 1953 : if (!omp_dsimd_idattr_clauses.is_empty ())
2982 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2983 : &omp_dsimd_idattr_clauses);
2984 1953 : }
2985 : else
2986 : {
2987 : /* The declaration of the variable is in effect while
2988 : its initializer is parsed, except for a constexpr
2989 : variable. */
2990 6335260 : init_loc = c_parser_peek_token (parser)->location;
2991 6335260 : rich_location richloc (line_table, init_loc);
2992 6335260 : unsigned int underspec_state = 0;
2993 6335260 : if (specs->constexpr_p)
2994 348 : underspec_state =
2995 348 : start_underspecified_init (init_loc, underspec_name);
2996 6335260 : d = start_decl (declarator, specs, true,
2997 : chainon (postfix_attrs,
2998 : all_prefix_attrs),
2999 6335260 : !specs->constexpr_p);
3000 6335260 : if (!d)
3001 4 : d = error_mark_node;
3002 6335260 : if (!specs->constexpr_p && omp_declare_simd_clauses)
3003 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
3004 : omp_declare_simd_clauses);
3005 6335260 : if (!specs->constexpr_p
3006 6335260 : && !omp_dsimd_idattr_clauses.is_empty ())
3007 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
3008 : &omp_dsimd_idattr_clauses);
3009 6335260 : start_init (d, asm_name,
3010 6158716 : TREE_STATIC (d) || specs->constexpr_p,
3011 6335260 : specs->constexpr_p, &richloc);
3012 : /* A parameter is initialized, which is invalid. Don't
3013 : attempt to instrument the initializer. */
3014 6335260 : sanitize_code_type flag_sanitize_save = flag_sanitize;
3015 6335260 : if (TREE_CODE (d) == PARM_DECL)
3016 35 : flag_sanitize = 0;
3017 6335260 : init = c_parser_initializer (parser, d);
3018 6335258 : flag_sanitize = flag_sanitize_save;
3019 6335258 : if (specs->constexpr_p)
3020 : {
3021 348 : finish_underspecified_init (underspec_name,
3022 : underspec_state);
3023 348 : d = pushdecl (d);
3024 348 : if (omp_declare_simd_clauses)
3025 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
3026 : omp_declare_simd_clauses);
3027 348 : if (!specs->constexpr_p
3028 348 : && !omp_dsimd_idattr_clauses.is_empty ())
3029 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
3030 : &omp_dsimd_idattr_clauses);
3031 : }
3032 6335258 : finish_init ();
3033 6335258 : }
3034 6337211 : if (oacc_routine_data)
3035 0 : c_finish_oacc_routine (oacc_routine_data, d, false);
3036 6337211 : if (d != error_mark_node)
3037 : {
3038 6337195 : maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
3039 6337195 : finish_decl (d, init_loc, init.value,
3040 : init.original_type, asm_name);
3041 6337195 : result = d;
3042 : }
3043 : }
3044 : else
3045 : {
3046 21572633 : if (any_auto_type_p || specs->constexpr_p)
3047 : {
3048 8 : error_at (here,
3049 : "%qs requires an initialized data declaration",
3050 : any_auto_type_p ? auto_type_keyword : "constexpr");
3051 5 : c_parser_skip_to_end_of_block_or_statement (parser);
3052 5 : return result;
3053 : }
3054 :
3055 21572628 : location_t lastloc = UNKNOWN_LOCATION;
3056 21572628 : tree attrs = chainon (postfix_attrs, all_prefix_attrs);
3057 21572628 : tree d = start_decl (declarator, specs, false, attrs, true,
3058 : &lastloc);
3059 21572627 : if (d && TREE_CODE (d) == FUNCTION_DECL)
3060 : {
3061 : /* Find the innermost declarator that is neither cdk_id
3062 : nor cdk_attrs. */
3063 : const struct c_declarator *decl = declarator;
3064 : const struct c_declarator *last_non_id_attrs = NULL;
3065 :
3066 29692165 : while (decl)
3067 29692165 : switch (decl->kind)
3068 : {
3069 15020635 : case cdk_array:
3070 15020635 : case cdk_function:
3071 15020635 : case cdk_pointer:
3072 15020635 : last_non_id_attrs = decl;
3073 15020635 : decl = decl->declarator;
3074 15020635 : break;
3075 :
3076 111 : case cdk_attrs:
3077 111 : decl = decl->declarator;
3078 111 : break;
3079 :
3080 : case cdk_id:
3081 : decl = 0;
3082 : break;
3083 :
3084 0 : default:
3085 0 : gcc_unreachable ();
3086 : }
3087 :
3088 : /* If it exists and is cdk_function declaration whose
3089 : arguments have not been set yet, use its arguments. */
3090 14671419 : if (last_non_id_attrs
3091 14050743 : && last_non_id_attrs->kind == cdk_function)
3092 : {
3093 14050743 : tree parms = last_non_id_attrs->u.arg_info->parms;
3094 14050743 : if (DECL_ARGUMENTS (d) == NULL_TREE
3095 14050743 : && DECL_INITIAL (d) == NULL_TREE)
3096 13596770 : DECL_ARGUMENTS (d) = parms;
3097 :
3098 14050743 : warn_parms_array_mismatch (lastloc, d, parms);
3099 : }
3100 : }
3101 21572627 : if (omp_declare_simd_clauses
3102 21572627 : || !omp_dsimd_idattr_clauses.is_empty ())
3103 : {
3104 489 : tree parms = NULL_TREE;
3105 489 : if (d && TREE_CODE (d) == FUNCTION_DECL)
3106 : {
3107 : struct c_declarator *ce = declarator;
3108 478 : while (ce != NULL)
3109 478 : if (ce->kind == cdk_function)
3110 : {
3111 475 : parms = ce->u.arg_info->parms;
3112 475 : break;
3113 : }
3114 : else
3115 3 : ce = ce->declarator;
3116 : }
3117 475 : if (parms)
3118 249 : temp_store_parm_decls (d, parms);
3119 489 : if (omp_declare_simd_clauses)
3120 469 : c_finish_omp_declare_simd (parser, d, parms,
3121 : omp_declare_simd_clauses);
3122 489 : if (!specs->constexpr_p
3123 489 : && !omp_dsimd_idattr_clauses.is_empty ())
3124 22 : c_finish_omp_declare_simd (parser, d, parms,
3125 : &omp_dsimd_idattr_clauses);
3126 489 : if (parms)
3127 249 : temp_pop_parm_decls ();
3128 : }
3129 21572627 : if (oacc_routine_data)
3130 72 : c_finish_oacc_routine (oacc_routine_data, d, false);
3131 21572627 : if (d)
3132 21572619 : finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
3133 : NULL_TREE, asm_name);
3134 :
3135 21572627 : if (c_parser_next_token_is_keyword (parser, RID_IN))
3136 : {
3137 0 : if (d)
3138 0 : *objc_foreach_object_declaration = d;
3139 : else
3140 0 : *objc_foreach_object_declaration = error_mark_node;
3141 : }
3142 : }
3143 27909838 : if (c_parser_next_token_is (parser, CPP_COMMA))
3144 : {
3145 425279 : more_than_one_decl = true;
3146 425279 : if (any_auto_type_p || specs->constexpr_p)
3147 : {
3148 4 : error_at (here,
3149 : "%qs may only be used with a single declarator",
3150 : any_auto_type_p ? auto_type_keyword : "constexpr");
3151 3 : c_parser_skip_to_end_of_block_or_statement (parser);
3152 3 : return result;
3153 : }
3154 425276 : c_parser_consume_token (parser);
3155 425276 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
3156 19 : all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
3157 : prefix_attrs);
3158 : else
3159 : all_prefix_attrs = prefix_attrs;
3160 425276 : continue;
3161 : }
3162 27484559 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
3163 : {
3164 27484419 : if (!simple_ok)
3165 27484320 : c_parser_consume_token (parser);
3166 27484419 : return result;
3167 : }
3168 140 : else if (c_parser_next_token_is_keyword (parser, RID_IN))
3169 : {
3170 : /* This can only happen in Objective-C: we found the
3171 : 'in' that terminates the declaration inside an
3172 : Objective-C foreach statement. Do not consume the
3173 : token, so that the caller can use it to determine
3174 : that this indeed is a foreach context. */
3175 : return result;
3176 : }
3177 : else
3178 : {
3179 140 : if (!simple_ok)
3180 : {
3181 48 : c_parser_error (parser, "expected %<,%> or %<;%>");
3182 48 : c_parser_skip_to_end_of_block_or_statement (parser);
3183 : }
3184 : /* It's not valid to use if (int i = 2, j = 3). */
3185 92 : else if (more_than_one_decl)
3186 4 : error_at (here, "declaration in condition can only declare "
3187 : "a single object");
3188 140 : return result;
3189 : }
3190 : }
3191 36250420 : else if (any_auto_type_p || specs->constexpr_p)
3192 : {
3193 4 : error_at (here,
3194 : "%qs requires an initialized data declaration",
3195 : any_auto_type_p ? auto_type_keyword : "constexpr");
3196 4 : c_parser_skip_to_end_of_block_or_statement (parser);
3197 4 : return result;
3198 : }
3199 36250416 : else if (!fndef_ok)
3200 : {
3201 76 : if (simple_ok && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3202 : /* Let c_parser_selection_header emit the error. */;
3203 : else
3204 : {
3205 36 : c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
3206 : "%<asm%> or %<__attribute__%>");
3207 36 : c_parser_skip_to_end_of_block_or_statement (parser);
3208 : }
3209 56 : return result;
3210 : }
3211 : /* Function definition (nested or otherwise). */
3212 36250360 : if (nested)
3213 : {
3214 1588 : pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
3215 1588 : c_push_function_context ();
3216 : }
3217 :
3218 : /* If we're in an OpenMP "begin declare variant" block, the
3219 : name in the declarator refers to the base function. We need
3220 : to save that and modify the declarator to have the mangled
3221 : name for the variant function instead. */
3222 36250360 : tree dv_base = NULL_TREE;
3223 36250360 : tree dv_ctx = NULL_TREE;
3224 36250360 : if (!vec_safe_is_empty (current_omp_declare_variant_attribute))
3225 : {
3226 24 : c_omp_declare_variant_attr a
3227 24 : = current_omp_declare_variant_attribute->last ();
3228 24 : dv_ctx = copy_list (a.selector);
3229 24 : dv_base = omp_start_variant_function (declarator, dv_ctx);
3230 : }
3231 :
3232 36250360 : if (!start_function (specs, declarator, all_prefix_attrs))
3233 : {
3234 : /* At this point we've consumed:
3235 : declaration-specifiers declarator
3236 : and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
3237 : RID_ASM, RID_ATTRIBUTE, or RID_IN,
3238 : but the
3239 : declaration-specifiers declarator
3240 : aren't grokkable as a function definition, so we have
3241 : an error. */
3242 38 : gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
3243 38 : if (c_parser_next_token_starts_declspecs (parser))
3244 : {
3245 : /* If we have
3246 : declaration-specifiers declarator decl-specs
3247 : then assume we have a missing semicolon, which would
3248 : give us:
3249 : declaration-specifiers declarator decl-specs
3250 : ^
3251 : ;
3252 : <~~~~~~~~~ declaration ~~~~~~~~~~>
3253 : Use c_parser_require to get an error with a fix-it hint. */
3254 13 : c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>");
3255 13 : parser->error = false;
3256 : }
3257 : else
3258 : {
3259 : /* This can appear in many cases looking nothing like a
3260 : function definition, so we don't give a more specific
3261 : error suggesting there was one. */
3262 25 : c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
3263 : "or %<__attribute__%>");
3264 : }
3265 38 : if (nested)
3266 1 : c_pop_function_context ();
3267 : break;
3268 : }
3269 :
3270 36250322 : if (DECL_DECLARED_INLINE_P (current_function_decl))
3271 : tv = TV_PARSE_INLINE;
3272 : else
3273 689642 : tv = TV_PARSE_FUNC;
3274 36250322 : auto_timevar at (g_timer, tv);
3275 :
3276 : /* Parse old-style parameter declarations. ??? Attributes are
3277 : not allowed to start declaration specifiers here because of a
3278 : syntax conflict between a function declaration with attribute
3279 : suffix and a function definition with an attribute prefix on
3280 : first old-style parameter declaration. Following the old
3281 : parser, they are not accepted on subsequent old-style
3282 : parameter declarations either. However, there is no
3283 : ambiguity after the first declaration, nor indeed on the
3284 : first as long as we don't allow postfix attributes after a
3285 : declarator with a nonempty identifier list in a definition;
3286 : and postfix attributes have never been accepted here in
3287 : function definitions either. */
3288 36250322 : int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
3289 36250322 : debug_nonbind_markers_p = 0;
3290 36250322 : c_parser_maybe_reclassify_token (parser);
3291 36250322 : while (c_parser_next_token_is_not (parser, CPP_EOF)
3292 72526584 : && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
3293 12978 : c_parser_declaration_or_fndef (parser, false, false, false,
3294 : true, false, false);
3295 36250322 : debug_nonbind_markers_p = save_debug_nonbind_markers_p;
3296 36250322 : store_parm_decls ();
3297 36250322 : if (omp_declare_simd_clauses)
3298 357 : c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3299 : omp_declare_simd_clauses);
3300 36250322 : if (!omp_dsimd_idattr_clauses.is_empty ())
3301 4 : c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3302 : &omp_dsimd_idattr_clauses);
3303 36250322 : if (oacc_routine_data)
3304 130 : c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
3305 36250322 : location_t startloc = c_parser_peek_token (parser)->location;
3306 36250322 : DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
3307 36250322 : = startloc;
3308 36250322 : location_t endloc = startloc;
3309 : /* If this function was in a "begin declare variant" block,
3310 : remember it. We will associate it with the base function at
3311 : the end of processing the translation unit, since it is permitted
3312 : for the variant definition to appear before the base declaration. */
3313 36250322 : if (dv_base && current_function_decl != error_mark_node)
3314 : {
3315 24 : omp_begin_declare_variant_map_entry e
3316 24 : = { current_function_decl, dv_base, dv_ctx };
3317 24 : vec_safe_push (omp_begin_declare_variant_map, e);
3318 : }
3319 :
3320 : /* If the definition was marked with __RTL, use the RTL parser now,
3321 : consuming the function body. */
3322 36250322 : if (specs->declspec_il == cdil_rtl)
3323 : {
3324 25 : endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
3325 :
3326 : /* Normally, store_parm_decls sets next_is_function_body,
3327 : anticipating a function body. We need a push_scope/pop_scope
3328 : pair to flush out this state, or subsequent function parsing
3329 : will go wrong. */
3330 24 : push_scope ();
3331 24 : pop_scope ();
3332 :
3333 24 : finish_function (endloc);
3334 24 : return result;
3335 : }
3336 : /* If the definition was marked with __GIMPLE then parse the
3337 : function body as GIMPLE. */
3338 36250297 : else if (specs->declspec_il != cdil_none)
3339 : {
3340 507 : bool saved = in_late_binary_op;
3341 507 : in_late_binary_op = true;
3342 507 : c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3343 507 : specs->declspec_il,
3344 : specs->entry_bb_count);
3345 507 : in_late_binary_op = saved;
3346 : }
3347 : else
3348 36249790 : fnbody = c_parser_compound_statement (parser, &endloc);
3349 36250296 : tree fndecl = current_function_decl;
3350 36250296 : if (nested && specs->declspec_il == cdil_none)
3351 : {
3352 1586 : tree decl = current_function_decl;
3353 : /* Mark nested functions as needing static-chain initially.
3354 : lower_nested_functions will recompute it but the
3355 : DECL_STATIC_CHAIN flag is also used before that happens,
3356 : by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
3357 1586 : DECL_STATIC_CHAIN (decl) = 1;
3358 1586 : add_stmt (fnbody);
3359 1586 : finish_function (endloc);
3360 1586 : c_pop_function_context ();
3361 1586 : add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
3362 1586 : }
3363 1 : else if (nested)
3364 : {
3365 1 : if (specs->declspec_il == cdil_rtl)
3366 0 : error ("%<__RTL%> function cannot be a nested function");
3367 : else
3368 1 : error ("%<__GIMPLE%> function cannot be a nested function");
3369 1 : finish_function (endloc);
3370 1 : c_pop_function_context ();
3371 : }
3372 : else
3373 : {
3374 36248709 : if (fnbody)
3375 36248203 : add_stmt (fnbody);
3376 36248709 : finish_function (endloc);
3377 : }
3378 : /* Get rid of the empty stmt list for GIMPLE/RTL. */
3379 36250296 : if (specs->declspec_il != cdil_none)
3380 507 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
3381 :
3382 36250296 : break;
3383 27910141 : }
3384 :
3385 36250334 : return result;
3386 : }
3387 :
3388 : /* Parse an asm-definition (asm() outside a function body). This is a
3389 : GNU extension.
3390 :
3391 : asm-definition:
3392 : simple-asm-expr ;
3393 : asm ( toplevel-asm-argument ) ;
3394 :
3395 : toplevel-asm-argument:
3396 : asm-string-literal
3397 : asm-string-literal : asm-operands[opt]
3398 : asm-string-literal : asm-operands[opt] : asm-operands[opt]
3399 :
3400 : The :: token is considered equivalent to two consecutive : tokens. */
3401 :
3402 : static void
3403 214 : c_parser_asm_definition (c_parser *parser)
3404 : {
3405 214 : location_t asm_loc = c_parser_peek_token (parser)->location;
3406 214 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
3407 214 : c_parser_consume_token (parser);
3408 214 : matching_parens parens;
3409 214 : tree asm_str = NULL_TREE;
3410 214 : tree outputs = NULL_TREE, inputs = NULL_TREE;
3411 214 : if (!parens.require_open (parser))
3412 5 : goto done;
3413 209 : asm_str = c_parser_asm_string_literal (parser);
3414 209 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3415 : {
3416 154 : parens.require_close (parser);
3417 154 : goto done;
3418 : }
3419 73 : for (int section = 0; section < 2; ++section)
3420 : {
3421 71 : if (c_parser_next_token_is (parser, CPP_SCOPE))
3422 : {
3423 29 : ++section;
3424 29 : if (section == 2)
3425 : {
3426 0 : c_parser_error (parser, "expected %<)%>");
3427 1 : error_close_paren:
3428 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
3429 1 : asm_str = NULL_TREE;
3430 1 : goto done;
3431 : }
3432 29 : c_parser_consume_token (parser);
3433 : }
3434 42 : else if (!c_parser_require (parser, CPP_COLON,
3435 : "expected %<:%> or %<)%>",
3436 : UNKNOWN_LOCATION, false))
3437 1 : goto error_close_paren;
3438 70 : if (!c_parser_next_token_is (parser, CPP_COLON)
3439 56 : && !c_parser_next_token_is (parser, CPP_SCOPE)
3440 126 : && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3441 : {
3442 56 : if (section)
3443 45 : inputs = c_parser_asm_operands (parser);
3444 : else
3445 11 : outputs = c_parser_asm_operands (parser);
3446 : }
3447 70 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3448 : break;
3449 : }
3450 :
3451 54 : if (!parens.require_close (parser))
3452 : {
3453 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
3454 2 : asm_str = NULL_TREE;
3455 : }
3456 :
3457 54 : if (asm_str)
3458 52 : asm_str = build_asm_expr (asm_loc, asm_str, outputs, inputs,
3459 : NULL_TREE, NULL_TREE, false, false);
3460 212 : done:
3461 212 : if (asm_str)
3462 206 : symtab->finalize_toplevel_asm (asm_str);
3463 214 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
3464 214 : }
3465 :
3466 : /* Parse a static assertion (C11 6.7.10).
3467 :
3468 : static_assert-declaration:
3469 : static_assert-declaration-no-semi ;
3470 : */
3471 :
3472 : static void
3473 1948 : c_parser_static_assert_declaration (c_parser *parser)
3474 : {
3475 1948 : c_parser_static_assert_declaration_no_semi (parser);
3476 1948 : if (parser->error
3477 1948 : || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
3478 8 : c_parser_skip_to_end_of_block_or_statement (parser);
3479 1948 : }
3480 :
3481 : /* Parse a static assertion (C11 6.7.10), without the trailing
3482 : semicolon.
3483 :
3484 : static_assert-declaration-no-semi:
3485 : _Static_assert ( constant-expression , string-literal )
3486 :
3487 : C23:
3488 : static_assert-declaration-no-semi:
3489 : _Static_assert ( constant-expression )
3490 : */
3491 :
3492 : static void
3493 2133 : c_parser_static_assert_declaration_no_semi (c_parser *parser)
3494 : {
3495 2133 : location_t assert_loc, value_loc;
3496 2133 : tree value;
3497 2133 : tree string = NULL_TREE;
3498 :
3499 2133 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3500 2133 : tree spelling = c_parser_peek_token (parser)->value;
3501 2133 : assert_loc = c_parser_peek_token (parser)->location;
3502 2133 : if (flag_isoc99)
3503 2129 : pedwarn_c99 (assert_loc, OPT_Wpedantic,
3504 : "ISO C99 does not support %qE", spelling);
3505 : else
3506 4 : pedwarn_c99 (assert_loc, OPT_Wpedantic,
3507 : "ISO C90 does not support %qE", spelling);
3508 2133 : c_parser_consume_token (parser);
3509 2133 : matching_parens parens;
3510 2133 : if (!parens.require_open (parser))
3511 15 : return;
3512 2132 : location_t value_tok_loc = c_parser_peek_token (parser)->location;
3513 2132 : value = convert_lvalue_to_rvalue (value_tok_loc,
3514 : c_parser_expr_no_commas (parser, NULL),
3515 : true, true).value;
3516 2132 : value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3517 2132 : if (c_parser_next_token_is (parser, CPP_COMMA))
3518 : {
3519 1584 : c_parser_consume_token (parser);
3520 1584 : switch (c_parser_peek_token (parser)->type)
3521 : {
3522 1581 : case CPP_STRING:
3523 1581 : case CPP_STRING16:
3524 1581 : case CPP_STRING32:
3525 1581 : case CPP_WSTRING:
3526 1581 : case CPP_UTF8STRING:
3527 1581 : string = c_parser_string_literal (parser, false, true).value;
3528 1581 : break;
3529 3 : default:
3530 3 : c_parser_error (parser, "expected string literal");
3531 3 : return;
3532 : }
3533 : }
3534 548 : else if (flag_isoc11)
3535 : /* If pedantic for pre-C11, the use of _Static_assert itself will
3536 : have been diagnosed, so do not also diagnose the use of this
3537 : new C23 feature of _Static_assert. */
3538 546 : pedwarn_c11 (assert_loc, OPT_Wpedantic,
3539 : "ISO C11 does not support omitting the string in "
3540 : "%qE", spelling);
3541 2129 : parens.require_close (parser);
3542 :
3543 2129 : if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
3544 : {
3545 5 : error_at (value_loc, "expression in static assertion is not an integer");
3546 5 : return;
3547 : }
3548 2124 : if (TREE_CODE (value) != INTEGER_CST)
3549 : {
3550 12 : value = c_fully_fold (value, false, NULL);
3551 : /* Strip no-op conversions. */
3552 24 : STRIP_TYPE_NOPS (value);
3553 12 : if (TREE_CODE (value) == INTEGER_CST)
3554 6 : pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
3555 : "is not an integer constant expression");
3556 : }
3557 2124 : if (TREE_CODE (value) != INTEGER_CST)
3558 : {
3559 6 : error_at (value_loc, "expression in static assertion is not constant");
3560 6 : return;
3561 : }
3562 2118 : constant_expression_warning (value);
3563 2118 : if (integer_zerop (value))
3564 : {
3565 41 : if (string)
3566 22 : error_at (assert_loc, "static assertion failed: %E", string);
3567 : else
3568 19 : error_at (assert_loc, "static assertion failed");
3569 : }
3570 : }
3571 :
3572 : /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
3573 : 6.7, C11 6.7), adding them to SPECS (which may already include some).
3574 : Storage class specifiers are accepted iff SCSPEC_OK; type
3575 : specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
3576 : accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
3577 : iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
3578 : addition to the syntax shown, standard attributes are accepted at
3579 : the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
3580 : unlike gnu-attributes, they are not accepted in the middle of the
3581 : list. (This combines various different syntax productions in the C
3582 : standard, and in some cases gnu-attributes and standard attributes
3583 : at the start may already have been parsed before this function is
3584 : called.)
3585 :
3586 : declaration-specifiers:
3587 : storage-class-specifier declaration-specifiers[opt]
3588 : type-specifier declaration-specifiers[opt]
3589 : type-qualifier declaration-specifiers[opt]
3590 : function-specifier declaration-specifiers[opt]
3591 : alignment-specifier declaration-specifiers[opt]
3592 :
3593 : Function specifiers (inline) are from C99, and are currently
3594 : handled as storage class specifiers, as is __thread. Alignment
3595 : specifiers are from C11.
3596 :
3597 : C90 6.5.1, C99 6.7.1, C11 6.7.1:
3598 : storage-class-specifier:
3599 : typedef
3600 : extern
3601 : static
3602 : auto
3603 : register
3604 : _Thread_local
3605 :
3606 : (_Thread_local is new in C11.)
3607 :
3608 : C99 6.7.4, C11 6.7.4:
3609 : function-specifier:
3610 : inline
3611 : _Noreturn
3612 :
3613 : (_Noreturn is new in C11.)
3614 :
3615 : C90 6.5.2, C99 6.7.2, C11 6.7.2:
3616 : type-specifier:
3617 : void
3618 : char
3619 : short
3620 : int
3621 : long
3622 : float
3623 : double
3624 : signed
3625 : unsigned
3626 : _Bool
3627 : _Complex
3628 : [_Imaginary removed in C99 TC2]
3629 : _BitInt ( constant-expression )
3630 : struct-or-union-specifier
3631 : enum-specifier
3632 : typedef-name
3633 : atomic-type-specifier
3634 :
3635 : (_Bool and _Complex are new in C99.)
3636 : (atomic-type-specifier is new in C11.)
3637 : (_BitInt is new in C23.)
3638 :
3639 : C90 6.5.3, C99 6.7.3, C11 6.7.3:
3640 :
3641 : type-qualifier:
3642 : const
3643 : restrict
3644 : volatile
3645 : address-space-qualifier
3646 : _Atomic
3647 :
3648 : (restrict is new in C99.)
3649 : (_Atomic is new in C11.)
3650 :
3651 : GNU extensions:
3652 :
3653 : declaration-specifiers:
3654 : gnu-attributes declaration-specifiers[opt]
3655 :
3656 : type-qualifier:
3657 : address-space
3658 :
3659 : address-space:
3660 : identifier recognized by the target
3661 :
3662 : storage-class-specifier:
3663 : __thread
3664 :
3665 : type-specifier:
3666 : typeof-specifier
3667 : __auto_type
3668 : __intN
3669 : _Decimal32
3670 : _Decimal64
3671 : _Decimal128
3672 : _Fract
3673 : _Accum
3674 : _Sat
3675 :
3676 : (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
3677 : http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
3678 :
3679 : atomic-type-specifier
3680 : _Atomic ( type-name )
3681 :
3682 : Objective-C:
3683 :
3684 : type-specifier:
3685 : class-name objc-protocol-refs[opt]
3686 : typedef-name objc-protocol-refs
3687 : objc-protocol-refs
3688 : */
3689 :
3690 : void
3691 333052723 : c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
3692 : bool scspec_ok, bool typespec_ok, bool start_attr_ok,
3693 : bool alignspec_ok, bool auto_type_ok,
3694 : bool start_std_attr_ok, bool end_std_attr_ok,
3695 : enum c_lookahead_kind la)
3696 : {
3697 333052723 : bool attrs_ok = start_attr_ok;
3698 333052723 : bool seen_type = specs->typespec_kind != ctsk_none;
3699 :
3700 333052723 : if (!typespec_ok)
3701 19362703 : gcc_assert (la == cla_prefer_id);
3702 :
3703 333052723 : if (start_std_attr_ok
3704 333052723 : && c_parser_nth_token_starts_std_attributes (parser, 1))
3705 : {
3706 640 : gcc_assert (!specs->non_std_attrs_seen_p);
3707 640 : location_t loc = c_parser_peek_token (parser)->location;
3708 640 : tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3709 640 : declspecs_add_attrs (loc, specs, attrs);
3710 640 : specs->non_std_attrs_seen_p = false;
3711 : }
3712 :
3713 806973348 : while (c_parser_next_token_is (parser, CPP_NAME)
3714 374152998 : || c_parser_next_token_is (parser, CPP_KEYWORD)
3715 952725134 : || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
3716 : {
3717 661221562 : struct c_typespec t;
3718 661221562 : tree attrs;
3719 661221562 : tree align;
3720 661221562 : location_t loc = c_parser_peek_token (parser)->location;
3721 :
3722 : /* If we cannot accept a type, exit if the next token must start
3723 : one. Also, if we already have seen a tagged definition,
3724 : a typename would be an error anyway and likely the user
3725 : has simply forgotten a semicolon, so we exit. */
3726 645178964 : if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3727 16973602 : && c_parser_next_tokens_start_typename (parser, la)
3728 3818706 : && !c_parser_next_token_is_qualifier (parser)
3729 661221689 : && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS))
3730 : break;
3731 :
3732 661221444 : if (c_parser_next_token_is (parser, CPP_NAME))
3733 : {
3734 432820244 : c_token *name_token = c_parser_peek_token (parser);
3735 432820244 : tree value = name_token->value;
3736 432820244 : c_id_kind kind = name_token->id_kind;
3737 :
3738 432820244 : if (kind == C_ID_ADDRSPACE)
3739 : {
3740 177 : addr_space_t as
3741 177 : = name_token->keyword - RID_FIRST_ADDR_SPACE;
3742 177 : declspecs_add_addrspace (name_token->location, specs, as);
3743 177 : c_parser_consume_token (parser);
3744 177 : attrs_ok = true;
3745 245522037 : continue;
3746 177 : }
3747 :
3748 432820067 : gcc_assert (!c_parser_next_token_is_qualifier (parser));
3749 :
3750 : /* If we cannot accept a type, and the next token must start one,
3751 : exit. Do the same if we already have seen a tagged definition,
3752 : since it would be an error anyway and likely the user has simply
3753 : forgotten a semicolon. */
3754 432820067 : if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
3755 : break;
3756 :
3757 : /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
3758 : a C_ID_CLASSNAME. */
3759 245521860 : c_parser_consume_token (parser);
3760 245521860 : seen_type = true;
3761 245521860 : attrs_ok = true;
3762 245521860 : if (kind == C_ID_ID)
3763 : {
3764 51 : auto_diagnostic_group d;
3765 51 : name_hint hint = lookup_name_fuzzy (value, FUZZY_LOOKUP_TYPENAME,
3766 51 : loc);
3767 51 : if (const char *suggestion = hint.suggestion ())
3768 : {
3769 2 : gcc_rich_location richloc (loc);
3770 2 : richloc.add_fixit_replace (suggestion);
3771 2 : error_at (&richloc,
3772 : "unknown type name %qE; did you mean %qs?",
3773 : value, suggestion);
3774 2 : }
3775 : else
3776 49 : error_at (loc, "unknown type name %qE", value);
3777 51 : t.kind = ctsk_typedef;
3778 51 : t.spec = error_mark_node;
3779 51 : }
3780 245521809 : else if (kind == C_ID_TYPENAME
3781 245521809 : && (!c_dialect_objc ()
3782 0 : || c_parser_next_token_is_not (parser, CPP_LESS)))
3783 : {
3784 245521809 : t.kind = ctsk_typedef;
3785 : /* For a typedef name, record the meaning, not the name.
3786 : In case of 'foo foo, bar;'. */
3787 245521809 : t.spec = lookup_name (value);
3788 : }
3789 : else
3790 : {
3791 0 : tree proto = NULL_TREE;
3792 0 : gcc_assert (c_dialect_objc ());
3793 0 : t.kind = ctsk_objc;
3794 0 : if (c_parser_next_token_is (parser, CPP_LESS))
3795 0 : proto = c_parser_objc_protocol_refs (parser);
3796 0 : t.spec = objc_get_protocol_qualified_type (value, proto);
3797 : }
3798 245521860 : t.expr = NULL_TREE;
3799 245521860 : t.expr_const_operands = true;
3800 245521860 : t.has_enum_type_specifier = false;
3801 245521860 : declspecs_add_type (name_token->location, specs, t);
3802 245521860 : continue;
3803 245521860 : }
3804 228401200 : if (c_parser_next_token_is (parser, CPP_LESS))
3805 : {
3806 : /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
3807 : nisse@lysator.liu.se. */
3808 0 : tree proto;
3809 0 : gcc_assert (c_dialect_objc ());
3810 0 : if (!typespec_ok || seen_type)
3811 : break;
3812 0 : proto = c_parser_objc_protocol_refs (parser);
3813 0 : t.kind = ctsk_objc;
3814 0 : t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
3815 0 : t.expr = NULL_TREE;
3816 0 : t.expr_const_operands = true;
3817 0 : t.has_enum_type_specifier = false;
3818 0 : declspecs_add_type (loc, specs, t);
3819 0 : continue;
3820 0 : }
3821 228401200 : gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3822 228401200 : switch (c_parser_peek_token (parser)->keyword)
3823 : {
3824 90234623 : case RID_STATIC:
3825 90234623 : case RID_EXTERN:
3826 90234623 : case RID_REGISTER:
3827 90234623 : case RID_TYPEDEF:
3828 90234623 : case RID_INLINE:
3829 90234623 : case RID_NORETURN:
3830 90234623 : case RID_AUTO:
3831 90234623 : case RID_THREAD:
3832 90234623 : case RID_CONSTEXPR:
3833 90234623 : if (!scspec_ok)
3834 2612 : goto out;
3835 90234490 : attrs_ok = true;
3836 : /* TODO: Distinguish between function specifiers (inline, noreturn)
3837 : and storage class specifiers, either here or in
3838 : declspecs_add_scspec. */
3839 90234490 : declspecs_add_scspec (loc, specs,
3840 90234490 : c_parser_peek_token (parser)->value);
3841 90234490 : c_parser_consume_token (parser);
3842 90234490 : break;
3843 1884 : case RID_AUTO_TYPE:
3844 1884 : if (!auto_type_ok)
3845 0 : goto out;
3846 : /* Fall through. */
3847 82410726 : case RID_UNSIGNED:
3848 82410726 : case RID_LONG:
3849 82410726 : case RID_SHORT:
3850 82410726 : case RID_SIGNED:
3851 82410726 : case RID_COMPLEX:
3852 82410726 : case RID_INT:
3853 82410726 : case RID_CHAR:
3854 82410726 : case RID_FLOAT:
3855 82410726 : case RID_DOUBLE:
3856 82410726 : case RID_VOID:
3857 82410726 : case RID_DFLOAT32:
3858 82410726 : case RID_DFLOAT64:
3859 82410726 : case RID_DFLOAT128:
3860 82410726 : case RID_DFLOAT64X:
3861 82410726 : CASE_RID_FLOATN_NX:
3862 82410726 : case RID_BOOL:
3863 82410726 : case RID_FRACT:
3864 82410726 : case RID_ACCUM:
3865 82410726 : case RID_SAT:
3866 82410726 : case RID_INT_N_0:
3867 82410726 : case RID_INT_N_1:
3868 82410726 : case RID_INT_N_2:
3869 82410726 : case RID_INT_N_3:
3870 82410726 : if (!typespec_ok)
3871 0 : goto out;
3872 82410726 : attrs_ok = true;
3873 82410726 : seen_type = true;
3874 82410726 : if (c_dialect_objc ())
3875 0 : parser->objc_need_raw_identifier = true;
3876 82410726 : t.kind = ctsk_resword;
3877 82410726 : t.spec = c_parser_peek_token (parser)->value;
3878 82410726 : t.expr = NULL_TREE;
3879 82410726 : t.expr_const_operands = true;
3880 82410726 : t.has_enum_type_specifier = false;
3881 82410726 : declspecs_add_type (loc, specs, t);
3882 82410726 : c_parser_consume_token (parser);
3883 82410726 : break;
3884 238421 : case RID_ENUM:
3885 238421 : if (!typespec_ok)
3886 0 : goto out;
3887 238421 : attrs_ok = true;
3888 238421 : seen_type = true;
3889 238421 : t = c_parser_enum_specifier (parser);
3890 238421 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3891 238421 : declspecs_add_type (loc, specs, t);
3892 238421 : break;
3893 2202281 : case RID_STRUCT:
3894 2202281 : case RID_UNION:
3895 2202281 : if (!typespec_ok)
3896 0 : goto out;
3897 2202281 : attrs_ok = true;
3898 2202281 : seen_type = true;
3899 2202281 : t = c_parser_struct_or_union_specifier (parser);
3900 2202281 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3901 2202281 : declspecs_add_type (loc, specs, t);
3902 2202281 : break;
3903 819812 : case RID_TYPEOF:
3904 819812 : case RID_TYPEOF_UNQUAL:
3905 : /* ??? The old parser rejected typeof after other type
3906 : specifiers, but is a syntax error the best way of
3907 : handling this? */
3908 819812 : if (!typespec_ok || seen_type)
3909 2 : goto out;
3910 819810 : attrs_ok = true;
3911 819810 : seen_type = true;
3912 819810 : t = c_parser_typeof_specifier (parser);
3913 819810 : declspecs_add_type (loc, specs, t);
3914 819810 : break;
3915 45651 : case RID_BITINT:
3916 45651 : if (!typespec_ok)
3917 0 : goto out;
3918 : else
3919 : {
3920 45651 : attrs_ok = true;
3921 45651 : seen_type = true;
3922 45651 : t.kind = ctsk_resword;
3923 45651 : t.spec = c_parser_peek_token (parser)->value;
3924 45651 : t.expr = error_mark_node;
3925 45651 : t.expr_const_operands = true;
3926 45651 : t.has_enum_type_specifier = false;
3927 45651 : c_parser_consume_token (parser);
3928 45651 : matching_parens parens;
3929 45651 : if (parens.require_open (parser))
3930 : {
3931 45651 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
3932 45651 : t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3933 45651 : true).value;
3934 45651 : parens.skip_until_found_close (parser);
3935 : }
3936 45651 : declspecs_add_type (loc, specs, t);
3937 : }
3938 45651 : break;
3939 33791 : case RID_ATOMIC:
3940 : /* C parser handling of Objective-C constructs needs
3941 : checking for correct lvalue-to-rvalue conversions, and
3942 : the code in build_modify_expr handling various
3943 : Objective-C cases, and that in build_unary_op handling
3944 : Objective-C cases for increment / decrement, also needs
3945 : updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
3946 : and objc_types_are_equivalent may also need updates. */
3947 33791 : if (c_dialect_objc ())
3948 0 : sorry ("%<_Atomic%> in Objective-C");
3949 33791 : if (flag_isoc99)
3950 33740 : pedwarn_c99 (loc, OPT_Wpedantic,
3951 : "ISO C99 does not support the %<_Atomic%> qualifier");
3952 : else
3953 51 : pedwarn_c99 (loc, OPT_Wpedantic,
3954 : "ISO C90 does not support the %<_Atomic%> qualifier");
3955 33791 : attrs_ok = true;
3956 33791 : tree value;
3957 33791 : value = c_parser_peek_token (parser)->value;
3958 33791 : c_parser_consume_token (parser);
3959 67372 : if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN))
3960 : {
3961 : /* _Atomic ( type-name ). */
3962 13430 : seen_type = true;
3963 13430 : c_parser_consume_token (parser);
3964 13430 : struct c_type_name *type = c_parser_type_name (parser);
3965 13430 : t.kind = ctsk_typeof;
3966 13430 : t.spec = error_mark_node;
3967 13430 : t.expr = NULL_TREE;
3968 13430 : t.expr_const_operands = true;
3969 13430 : t.has_enum_type_specifier = false;
3970 13430 : if (type != NULL)
3971 13429 : t.spec = groktypename (type, &t.expr,
3972 : &t.expr_const_operands);
3973 13430 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
3974 : "expected %<)%>");
3975 13430 : if (t.spec != error_mark_node)
3976 : {
3977 13429 : if (TREE_CODE (t.spec) == ARRAY_TYPE)
3978 1 : error_at (loc, "%<_Atomic%>-qualified array type");
3979 13428 : else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
3980 1 : error_at (loc, "%<_Atomic%>-qualified function type");
3981 13427 : else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
3982 4 : error_at (loc, "%<_Atomic%> applied to a qualified type");
3983 : else
3984 13423 : t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
3985 : }
3986 13430 : declspecs_add_type (loc, specs, t);
3987 : }
3988 : else
3989 20361 : declspecs_add_qual (loc, specs, value);
3990 : break;
3991 16540495 : case RID_CONST:
3992 16540495 : case RID_VOLATILE:
3993 16540495 : case RID_RESTRICT:
3994 16540495 : attrs_ok = true;
3995 16540495 : declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3996 16540495 : c_parser_consume_token (parser);
3997 16540495 : break;
3998 35872188 : case RID_ATTRIBUTE:
3999 35872188 : if (!attrs_ok)
4000 0 : goto out;
4001 35872188 : attrs = c_parser_gnu_attributes (parser);
4002 35872188 : declspecs_add_attrs (loc, specs, attrs);
4003 35872188 : break;
4004 218 : case RID_ALIGNAS:
4005 218 : if (!alignspec_ok)
4006 16 : goto out;
4007 202 : align = c_parser_alignas_specifier (parser);
4008 202 : declspecs_add_alignas (loc, specs, align);
4009 202 : break;
4010 508 : case RID_GIMPLE:
4011 508 : if (! flag_gimple)
4012 0 : error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
4013 508 : c_parser_consume_token (parser);
4014 508 : specs->declspec_il = cdil_gimple;
4015 508 : specs->locations[cdw_gimple] = loc;
4016 508 : c_parser_gimple_or_rtl_pass_list (parser, specs);
4017 508 : break;
4018 25 : case RID_RTL:
4019 25 : c_parser_consume_token (parser);
4020 25 : specs->declspec_il = cdil_rtl;
4021 25 : specs->locations[cdw_rtl] = loc;
4022 25 : c_parser_gimple_or_rtl_pass_list (parser, specs);
4023 25 : break;
4024 2461 : default:
4025 2461 : goto out;
4026 : }
4027 : }
4028 333052723 : out:
4029 333052723 : if (end_std_attr_ok
4030 333052723 : && c_parser_nth_token_starts_std_attributes (parser, 1))
4031 117 : specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
4032 333052723 : }
4033 :
4034 : /* Complain about a non-CPP_NAME within an enumerator list. */
4035 :
4036 : static void
4037 11 : report_bad_enum_name (c_parser *parser)
4038 : {
4039 11 : if (!parser->error)
4040 : {
4041 11 : c_token *token = c_parser_peek_token (parser);
4042 11 : switch (token->type)
4043 : {
4044 : default:
4045 : break;
4046 6 : case CPP_CLOSE_BRACE:
4047 : /* Give a nicer error for "enum {}". */
4048 6 : error_at (token->location,
4049 : "empty enum is invalid");
4050 6 : parser->error = true;
4051 6 : return;
4052 3 : case CPP_KEYWORD:
4053 : /* Give a nicer error for attempts to use "true" and "false"
4054 : in enums with C23 onwards. */
4055 3 : if (token->keyword == RID_FALSE
4056 2 : || token->keyword == RID_TRUE)
4057 : {
4058 2 : auto_diagnostic_group d;
4059 4 : error_at (token->location,
4060 : "cannot use keyword %qs as enumeration constant",
4061 2 : IDENTIFIER_POINTER (token->value));
4062 2 : add_note_about_new_keyword (token->location,
4063 : token->value);
4064 2 : parser->error = true;
4065 2 : return;
4066 2 : }
4067 : break;
4068 : }
4069 : }
4070 :
4071 : /* Otherwise, a more generic error message. */
4072 3 : c_parser_error (parser, "expected identifier");
4073 : }
4074 :
4075 : /* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
4076 :
4077 : enum-specifier:
4078 : enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
4079 : { enumerator-list } gnu-attributes[opt]
4080 : enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
4081 : { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
4082 : enum gnu-attributes[opt] identifier
4083 :
4084 : The form with trailing comma is new in C99; enum-type-specifiers
4085 : are new in C23. The forms with gnu-attributes are GNU extensions.
4086 : In GNU C, we accept any expression without commas in the syntax
4087 : (assignment expressions, not just conditional expressions);
4088 : assignment expressions will be diagnosed as non-constant.
4089 :
4090 : enum-type-specifier:
4091 : : specifier-qualifier-list
4092 :
4093 : enumerator-list:
4094 : enumerator
4095 : enumerator-list , enumerator
4096 :
4097 : enumerator:
4098 : enumeration-constant attribute-specifier-sequence[opt]
4099 : enumeration-constant attribute-specifier-sequence[opt]
4100 : = constant-expression
4101 :
4102 : GNU Extensions:
4103 :
4104 : enumerator:
4105 : enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
4106 : enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
4107 : = constant-expression
4108 :
4109 : */
4110 :
4111 : static struct c_typespec
4112 238421 : c_parser_enum_specifier (c_parser *parser)
4113 : {
4114 238421 : struct c_typespec ret;
4115 238421 : bool have_std_attrs;
4116 238421 : bool potential_nesting_p = false;
4117 238421 : tree std_attrs = NULL_TREE;
4118 238421 : tree attrs;
4119 238421 : tree ident = NULL_TREE;
4120 238421 : tree fixed_underlying_type = NULL_TREE;
4121 238421 : location_t enum_loc;
4122 238421 : location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4123 238421 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
4124 238421 : c_parser_consume_token (parser);
4125 238421 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4126 238421 : if (have_std_attrs)
4127 14 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4128 238421 : attrs = c_parser_gnu_attributes (parser);
4129 238421 : enum_loc = c_parser_peek_token (parser)->location;
4130 : /* Set the location in case we create a decl now. */
4131 238421 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
4132 238421 : if (c_parser_next_token_is (parser, CPP_NAME))
4133 : {
4134 129728 : ident = c_parser_peek_token (parser)->value;
4135 129728 : ident_loc = c_parser_peek_token (parser)->location;
4136 129728 : enum_loc = ident_loc;
4137 129728 : c_parser_consume_token (parser);
4138 : }
4139 238421 : if (c_parser_next_token_is (parser, CPP_COLON)
4140 : /* Distinguish an enum-type-specifier from a bit-field
4141 : declaration of the form "enum e : constant-expression;". */
4142 238421 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
4143 : {
4144 169 : pedwarn_c11 (enum_loc, OPT_Wpedantic,
4145 : "ISO C does not support specifying %<enum%> underlying "
4146 : "types before C23");
4147 169 : if (ident)
4148 : {
4149 : /* The tag is in scope during the enum-type-specifier (which
4150 : may refer to the tag inside typeof). */
4151 165 : ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
4152 : have_std_attrs, std_attrs, true);
4153 165 : if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
4154 3 : error_at (enum_loc, "%<enum%> declared both with and without "
4155 : "fixed underlying type");
4156 165 : potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
4157 : }
4158 : else
4159 : {
4160 : /* There must be an enum definition, so this initialization
4161 : (to avoid possible warnings about uninitialized data)
4162 : will be replaced later (either with the results of that
4163 : definition, or with the results of error handling for the
4164 : case of no tag and no definition). */
4165 4 : ret.spec = NULL_TREE;
4166 4 : ret.kind = ctsk_tagdef;
4167 4 : ret.expr = NULL_TREE;
4168 4 : ret.expr_const_operands = true;
4169 4 : ret.has_enum_type_specifier = true;
4170 : }
4171 169 : c_parser_consume_token (parser);
4172 169 : struct c_declspecs *specs = build_null_declspecs ();
4173 169 : c_parser_declspecs (parser, specs, false, true, false, false, false,
4174 : false, true, cla_prefer_id);
4175 169 : finish_declspecs (specs);
4176 169 : if (specs->default_int_p)
4177 1 : error_at (enum_loc, "no %<enum%> underlying type specified");
4178 168 : else if (TREE_CODE (specs->type) != INTEGER_TYPE
4179 168 : && TREE_CODE (specs->type) != BOOLEAN_TYPE)
4180 : {
4181 9 : error_at (enum_loc, "invalid %<enum%> underlying type");
4182 9 : specs->type = integer_type_node;
4183 : }
4184 159 : else if (specs->restrict_p)
4185 1 : error_at (enum_loc, "invalid use of %<restrict%>");
4186 169 : fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
4187 169 : if (ident)
4188 : {
4189 : /* The type specified must be consistent with any previously
4190 : specified underlying type. If this is a newly declared
4191 : type, it is now a complete type. */
4192 165 : if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4193 165 : && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
4194 : {
4195 432 : TYPE_MIN_VALUE (ret.spec) =
4196 144 : TYPE_MIN_VALUE (fixed_underlying_type);
4197 432 : TYPE_MAX_VALUE (ret.spec) =
4198 144 : TYPE_MAX_VALUE (fixed_underlying_type);
4199 144 : TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
4200 144 : SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
4201 144 : TYPE_SIZE (ret.spec) = NULL_TREE;
4202 144 : TYPE_PRECISION (ret.spec) =
4203 144 : TYPE_PRECISION (fixed_underlying_type);
4204 144 : ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
4205 144 : layout_type (ret.spec);
4206 : }
4207 21 : else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4208 37 : && !comptypes (fixed_underlying_type,
4209 16 : ENUM_UNDERLYING_TYPE (ret.spec)))
4210 : {
4211 3 : error_at (enum_loc, "%<enum%> underlying type incompatible with "
4212 : "previous declaration");
4213 3 : fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
4214 : }
4215 : }
4216 : }
4217 238421 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
4218 : {
4219 : /* Parse an enum definition. */
4220 180381 : struct c_enum_contents the_enum;
4221 180381 : tree type;
4222 180381 : tree postfix_attrs;
4223 : /* We chain the enumerators in reverse order, then put them in
4224 : forward order at the end. */
4225 180381 : tree values;
4226 180381 : timevar_push (TV_PARSE_ENUM);
4227 180381 : type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
4228 : potential_nesting_p);
4229 180381 : values = NULL_TREE;
4230 180381 : c_parser_consume_token (parser);
4231 5709584 : while (true)
4232 : {
4233 5709584 : tree enum_id;
4234 5709584 : tree enum_value;
4235 5709584 : tree enum_decl;
4236 5709584 : bool seen_comma;
4237 5709584 : c_token *token;
4238 5709584 : location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4239 5709584 : location_t decl_loc, value_loc;
4240 5709584 : if (c_parser_next_token_is_not (parser, CPP_NAME))
4241 : {
4242 11 : report_bad_enum_name (parser);
4243 11 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4244 11 : values = error_mark_node;
4245 11 : break;
4246 : }
4247 5709573 : token = c_parser_peek_token (parser);
4248 5709573 : enum_id = token->value;
4249 : /* Set the location in case we create a decl now. */
4250 5709573 : c_parser_set_source_position_from_token (token);
4251 5709573 : decl_loc = value_loc = token->location;
4252 5709573 : c_parser_consume_token (parser);
4253 : /* Parse any specified attributes. */
4254 5709573 : tree std_attrs = NULL_TREE;
4255 5709573 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
4256 12 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4257 5709573 : tree enum_attrs = chainon (std_attrs,
4258 : c_parser_gnu_attributes (parser));
4259 5709573 : if (c_parser_next_token_is (parser, CPP_EQ))
4260 : {
4261 3549731 : c_parser_consume_token (parser);
4262 3549731 : value_loc = c_parser_peek_token (parser)->location;
4263 3549731 : enum_value = convert_lvalue_to_rvalue (value_loc,
4264 : (c_parser_expr_no_commas
4265 : (parser, NULL)),
4266 : true, true).value;
4267 : }
4268 : else
4269 : enum_value = NULL_TREE;
4270 5709573 : enum_decl = build_enumerator (decl_loc, value_loc,
4271 : &the_enum, enum_id, enum_value);
4272 5709573 : if (enum_attrs)
4273 3324 : decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
4274 5709573 : TREE_CHAIN (enum_decl) = values;
4275 5709573 : values = enum_decl;
4276 5709573 : seen_comma = false;
4277 5709573 : if (c_parser_next_token_is (parser, CPP_COMMA))
4278 : {
4279 5549826 : comma_loc = c_parser_peek_token (parser)->location;
4280 5549826 : seen_comma = true;
4281 5549826 : c_parser_consume_token (parser);
4282 : }
4283 5709573 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4284 : {
4285 180355 : if (seen_comma)
4286 20623 : pedwarn_c90 (comma_loc, OPT_Wpedantic,
4287 : "comma at end of enumerator list");
4288 180355 : c_parser_consume_token (parser);
4289 180355 : break;
4290 : }
4291 5529218 : if (!seen_comma)
4292 : {
4293 15 : c_parser_error (parser, "expected %<,%> or %<}%>");
4294 15 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4295 15 : values = error_mark_node;
4296 15 : break;
4297 : }
4298 : }
4299 180381 : postfix_attrs = c_parser_gnu_attributes (parser);
4300 180381 : ret.spec = finish_enum (type, nreverse (values),
4301 : chainon (std_attrs,
4302 : chainon (attrs, postfix_attrs)));
4303 180381 : ret.kind = ctsk_tagdef;
4304 180381 : ret.expr = NULL_TREE;
4305 180381 : ret.expr_const_operands = true;
4306 180381 : ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
4307 180381 : timevar_pop (TV_PARSE_ENUM);
4308 180381 : return ret;
4309 : }
4310 58040 : else if (!ident)
4311 : {
4312 1 : c_parser_error (parser, "expected %<{%>");
4313 1 : ret.spec = error_mark_node;
4314 1 : ret.kind = ctsk_tagref;
4315 1 : ret.expr = NULL_TREE;
4316 1 : ret.expr_const_operands = true;
4317 1 : ret.has_enum_type_specifier = false;
4318 1 : return ret;
4319 : }
4320 : /* Attributes may only appear when the members are defined or in
4321 : certain forward declarations (treat enum forward declarations in
4322 : GNU C analogously to struct and union forward declarations in
4323 : standard C). */
4324 58040 : if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
4325 1 : c_parser_error (parser, "expected %<;%>");
4326 58039 : if (fixed_underlying_type == NULL_TREE)
4327 : {
4328 57990 : ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
4329 : std_attrs, false);
4330 : /* In ISO C, enumerated types without a fixed underlying type
4331 : can be referred to only if already defined. */
4332 57990 : if (pedantic && !COMPLETE_TYPE_P (ret.spec))
4333 : {
4334 11 : gcc_assert (ident);
4335 11 : pedwarn (enum_loc, OPT_Wpedantic,
4336 : "ISO C forbids forward references to %<enum%> types");
4337 : }
4338 : }
4339 : return ret;
4340 : }
4341 :
4342 : /* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
4343 :
4344 : struct-or-union-specifier:
4345 : struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4346 : identifier[opt] { struct-contents } gnu-attributes[opt]
4347 : struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4348 : identifier
4349 :
4350 : struct-contents:
4351 : struct-declaration-list
4352 :
4353 : struct-declaration-list:
4354 : struct-declaration ;
4355 : struct-declaration-list struct-declaration ;
4356 :
4357 : GNU extensions:
4358 :
4359 : struct-contents:
4360 : empty
4361 : struct-declaration
4362 : struct-declaration-list struct-declaration
4363 :
4364 : struct-declaration-list:
4365 : struct-declaration-list ;
4366 : ;
4367 :
4368 : (Note that in the syntax here, unlike that in ISO C, the semicolons
4369 : are included here rather than in struct-declaration, in order to
4370 : describe the syntax with extra semicolons and missing semicolon at
4371 : end.)
4372 :
4373 : Objective-C:
4374 :
4375 : struct-declaration-list:
4376 : @defs ( class-name )
4377 :
4378 : (Note this does not include a trailing semicolon, but can be
4379 : followed by further declarations, and gets a pedwarn-if-pedantic
4380 : when followed by a semicolon.) */
4381 :
4382 : static struct c_typespec
4383 2202281 : c_parser_struct_or_union_specifier (c_parser *parser)
4384 : {
4385 2202281 : struct c_typespec ret;
4386 2202281 : bool have_std_attrs;
4387 2202281 : tree std_attrs = NULL_TREE;
4388 2202281 : tree attrs;
4389 2202281 : tree ident = NULL_TREE;
4390 2202281 : location_t struct_loc;
4391 2202281 : location_t ident_loc = UNKNOWN_LOCATION;
4392 2202281 : enum tree_code code;
4393 2202281 : switch (c_parser_peek_token (parser)->keyword)
4394 : {
4395 : case RID_STRUCT:
4396 : code = RECORD_TYPE;
4397 : break;
4398 417599 : case RID_UNION:
4399 417599 : code = UNION_TYPE;
4400 417599 : break;
4401 0 : default:
4402 0 : gcc_unreachable ();
4403 : }
4404 2202281 : struct_loc = c_parser_peek_token (parser)->location;
4405 2202281 : c_parser_consume_token (parser);
4406 2202281 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4407 2202281 : if (have_std_attrs)
4408 34 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4409 2202281 : attrs = c_parser_gnu_attributes (parser);
4410 :
4411 : /* Set the location in case we create a decl now. */
4412 2202281 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
4413 :
4414 2202281 : if (c_parser_next_token_is (parser, CPP_NAME))
4415 : {
4416 1509023 : ident = c_parser_peek_token (parser)->value;
4417 1509023 : ident_loc = c_parser_peek_token (parser)->location;
4418 1509023 : struct_loc = ident_loc;
4419 1509023 : c_parser_consume_token (parser);
4420 : }
4421 2202281 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
4422 : {
4423 : /* Parse a struct or union definition. Start the scope of the
4424 : tag before parsing components. */
4425 1177497 : class c_struct_parse_info *struct_info;
4426 1177497 : tree type = start_struct (struct_loc, code, ident, &struct_info);
4427 1177497 : tree postfix_attrs;
4428 : /* We chain the components in reverse order, then put them in
4429 : forward order at the end. Each struct-declaration may
4430 : declare multiple components (comma-separated), so we must use
4431 : chainon to join them, although when parsing each
4432 : struct-declaration we can use TREE_CHAIN directly.
4433 :
4434 : The theory behind all this is that there will be more
4435 : semicolon separated fields than comma separated fields, and
4436 : so we'll be minimizing the number of node traversals required
4437 : by chainon. */
4438 1177497 : tree contents;
4439 1177497 : tree expr = NULL;
4440 1177497 : timevar_push (TV_PARSE_STRUCT);
4441 1177497 : contents = NULL_TREE;
4442 1177497 : c_parser_consume_token (parser);
4443 : /* Handle the Objective-C @defs construct,
4444 : e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4445 1177497 : if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
4446 : {
4447 0 : tree name;
4448 0 : gcc_assert (c_dialect_objc ());
4449 0 : c_parser_consume_token (parser);
4450 0 : matching_parens parens;
4451 0 : if (!parens.require_open (parser))
4452 0 : goto end_at_defs;
4453 0 : if (c_parser_next_token_is (parser, CPP_NAME)
4454 0 : && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4455 : {
4456 0 : name = c_parser_peek_token (parser)->value;
4457 0 : c_parser_consume_token (parser);
4458 : }
4459 : else
4460 : {
4461 0 : c_parser_error (parser, "expected class name");
4462 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
4463 0 : goto end_at_defs;
4464 : }
4465 0 : parens.skip_until_found_close (parser);
4466 0 : contents = nreverse (objc_get_class_ivars (name));
4467 : }
4468 1177497 : end_at_defs:
4469 : /* Parse the struct-declarations and semicolons. Problems with
4470 : semicolons are diagnosed here; empty structures are diagnosed
4471 : elsewhere. */
4472 5438530 : while (true)
4473 : {
4474 5438530 : tree decls;
4475 : /* Parse any stray semicolon. */
4476 5438530 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
4477 : {
4478 14 : location_t semicolon_loc
4479 14 : = c_parser_peek_token (parser)->location;
4480 14 : gcc_rich_location richloc (semicolon_loc);
4481 14 : richloc.add_fixit_remove ();
4482 14 : pedwarn (&richloc, OPT_Wpedantic,
4483 : "extra semicolon in struct or union specified");
4484 14 : c_parser_consume_token (parser);
4485 14 : continue;
4486 14 : }
4487 : /* Stop if at the end of the struct or union contents. */
4488 5438516 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4489 : {
4490 1177488 : c_parser_consume_token (parser);
4491 1177488 : break;
4492 : }
4493 : /* Accept #pragmas at struct scope. */
4494 4261028 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
4495 : {
4496 20 : c_parser_pragma (parser, pragma_struct, NULL, NULL_TREE);
4497 20 : continue;
4498 : }
4499 : /* Parse some comma-separated declarations, but not the
4500 : trailing semicolon if any. */
4501 4261008 : decls = c_parser_struct_declaration (parser, &expr);
4502 4261008 : contents = chainon (decls, contents);
4503 : /* If no semicolon follows, either we have a parse error or
4504 : are at the end of the struct or union and should
4505 : pedwarn. */
4506 4261008 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
4507 4260969 : c_parser_consume_token (parser);
4508 : else
4509 : {
4510 39 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4511 28 : pedwarn (c_parser_peek_token (parser)->location, 0,
4512 : "no semicolon at end of struct or union");
4513 11 : else if (parser->error
4514 11 : || !c_parser_next_token_starts_declspecs (parser))
4515 : {
4516 9 : c_parser_error (parser, "expected %<;%>");
4517 9 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4518 9 : break;
4519 : }
4520 :
4521 : /* If we come here, we have already emitted an error
4522 : for an expected `;', identifier or `(', and we also
4523 : recovered already. Go on with the next field. */
4524 : }
4525 : }
4526 1177497 : postfix_attrs = c_parser_gnu_attributes (parser);
4527 1177497 : ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4528 : chainon (std_attrs,
4529 : chainon (attrs, postfix_attrs)),
4530 : struct_info, &expr);
4531 1177497 : ret.kind = ctsk_tagdef;
4532 1177497 : ret.expr = expr;
4533 1177497 : ret.expr_const_operands = true;
4534 1177497 : ret.has_enum_type_specifier = false;
4535 1177497 : timevar_pop (TV_PARSE_STRUCT);
4536 1177497 : return ret;
4537 : }
4538 1024784 : else if (!ident)
4539 : {
4540 10 : c_parser_error (parser, "expected %<{%>");
4541 10 : ret.spec = error_mark_node;
4542 10 : ret.kind = ctsk_tagref;
4543 10 : ret.expr = NULL_TREE;
4544 10 : ret.expr_const_operands = true;
4545 10 : ret.has_enum_type_specifier = false;
4546 10 : return ret;
4547 : }
4548 : /* Attributes may only appear when the members are defined or in
4549 : certain forward declarations. */
4550 1024784 : if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
4551 2 : c_parser_error (parser, "expected %<;%>");
4552 : /* ??? Existing practice is that GNU attributes are ignored after
4553 : the struct or union keyword when not defining the members. */
4554 1024774 : ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4555 : false);
4556 1024774 : return ret;
4557 : }
4558 :
4559 : /* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4560 : *without* the trailing semicolon.
4561 :
4562 : struct-declaration:
4563 : attribute-specifier-sequence[opt] specifier-qualifier-list
4564 : attribute-specifier-sequence[opt] struct-declarator-list
4565 : static_assert-declaration-no-semi
4566 :
4567 : specifier-qualifier-list:
4568 : type-specifier specifier-qualifier-list[opt]
4569 : type-qualifier specifier-qualifier-list[opt]
4570 : alignment-specifier specifier-qualifier-list[opt]
4571 : gnu-attributes specifier-qualifier-list[opt]
4572 :
4573 : struct-declarator-list:
4574 : struct-declarator
4575 : struct-declarator-list , gnu-attributes[opt] struct-declarator
4576 :
4577 : struct-declarator:
4578 : declarator gnu-attributes[opt]
4579 : declarator[opt] : constant-expression gnu-attributes[opt]
4580 :
4581 : GNU extensions:
4582 :
4583 : struct-declaration:
4584 : __extension__ struct-declaration
4585 : specifier-qualifier-list
4586 :
4587 : Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4588 : of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4589 : any expression without commas in the syntax (assignment
4590 : expressions, not just conditional expressions); assignment
4591 : expressions will be diagnosed as non-constant. */
4592 :
4593 : static tree
4594 4326250 : c_parser_struct_declaration (c_parser *parser, tree *expr)
4595 : {
4596 4326250 : struct c_declspecs *specs;
4597 4326250 : tree prefix_attrs;
4598 4326250 : tree all_prefix_attrs;
4599 4326250 : tree decls;
4600 4326250 : location_t decl_loc;
4601 4326250 : if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
4602 : {
4603 65242 : int ext;
4604 65242 : tree decl;
4605 65242 : ext = disable_extension_diagnostics ();
4606 65242 : c_parser_consume_token (parser);
4607 65242 : decl = c_parser_struct_declaration (parser, expr);
4608 65242 : restore_extension_diagnostics (ext);
4609 65242 : return decl;
4610 : }
4611 4261008 : if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
4612 : {
4613 17 : c_parser_static_assert_declaration_no_semi (parser);
4614 17 : return NULL_TREE;
4615 : }
4616 4260991 : specs = build_null_declspecs ();
4617 4260991 : decl_loc = c_parser_peek_token (parser)->location;
4618 : /* Strictly by the standard, we shouldn't allow _Alignas here,
4619 : but it appears to have been intended to allow it there, so
4620 : we're keeping it as it is until WG14 reaches a conclusion
4621 : of N1731.
4622 : <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4623 4260991 : c_parser_declspecs (parser, specs, false, true, true,
4624 : true, false, true, true, cla_nonabstract_decl);
4625 4260991 : if (parser->error)
4626 : return NULL_TREE;
4627 4260983 : if (!specs->declspecs_seen_p)
4628 : {
4629 1 : c_parser_error (parser, "expected specifier-qualifier-list");
4630 1 : return NULL_TREE;
4631 : }
4632 4260982 : finish_declspecs (specs);
4633 4260982 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4634 8511057 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4635 : {
4636 10911 : tree ret;
4637 10911 : if (specs->typespec_kind == ctsk_none)
4638 : {
4639 3 : pedwarn (decl_loc, OPT_Wpedantic,
4640 : "ISO C forbids member declarations with no members");
4641 3 : shadow_tag_warned (specs, pedantic);
4642 3 : ret = NULL_TREE;
4643 : }
4644 : else
4645 : {
4646 : /* Support for unnamed structs or unions as members of
4647 : structs or unions (which is [a] useful and [b] supports
4648 : MS P-SDK). */
4649 10908 : tree attrs = NULL;
4650 :
4651 10908 : ret = grokfield (c_parser_peek_token (parser)->location,
4652 : build_id_declarator (NULL_TREE), specs,
4653 : NULL_TREE, &attrs, expr);
4654 10908 : if (ret)
4655 10879 : decl_attributes (&ret, attrs, 0);
4656 : }
4657 10911 : return ret;
4658 : }
4659 :
4660 : /* Provide better error recovery. Note that a type name here is valid,
4661 : and will be treated as a field name. */
4662 4250071 : if (specs->typespec_kind == ctsk_tagdef
4663 153018 : && TREE_CODE (specs->type) != ENUMERAL_TYPE
4664 152865 : && c_parser_next_token_starts_declspecs (parser)
4665 4250074 : && !c_parser_next_token_is (parser, CPP_NAME))
4666 : {
4667 2 : c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
4668 2 : parser->error = false;
4669 2 : return NULL_TREE;
4670 : }
4671 :
4672 4250069 : pending_xref_error ();
4673 4250069 : prefix_attrs = specs->attrs;
4674 4250069 : all_prefix_attrs = prefix_attrs;
4675 4250069 : specs->attrs = NULL_TREE;
4676 4250069 : decls = NULL_TREE;
4677 57663 : while (true)
4678 : {
4679 : /* Declaring one or more declarators or un-named bit-fields. */
4680 4307732 : struct c_declarator *declarator;
4681 4307732 : bool dummy = false;
4682 4307732 : if (c_parser_next_token_is (parser, CPP_COLON))
4683 9740 : declarator = build_id_declarator (NULL_TREE);
4684 : else
4685 4297992 : declarator = c_parser_declarator (parser,
4686 4297992 : specs->typespec_kind != ctsk_none,
4687 : C_DTR_NORMAL, &dummy);
4688 4307732 : if (declarator == NULL)
4689 : {
4690 1 : c_parser_skip_to_end_of_block_or_statement (parser);
4691 1 : break;
4692 : }
4693 4307731 : if (c_parser_next_token_is (parser, CPP_COLON)
4694 4255151 : || c_parser_next_token_is (parser, CPP_COMMA)
4695 4199686 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
4696 33331 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
4697 4341039 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4698 : {
4699 4307731 : tree postfix_attrs = NULL_TREE;
4700 4307731 : tree width = NULL_TREE;
4701 4307731 : tree d;
4702 4307731 : if (c_parser_next_token_is (parser, CPP_COLON))
4703 : {
4704 52580 : c_parser_consume_token (parser);
4705 52580 : location_t loc = c_parser_peek_token (parser)->location;
4706 52580 : width = convert_lvalue_to_rvalue (loc,
4707 : (c_parser_expr_no_commas
4708 : (parser, NULL)),
4709 : true, true).value;
4710 : }
4711 4307731 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4712 33491 : postfix_attrs = c_parser_gnu_attributes (parser);
4713 4307731 : d = grokfield (c_parser_peek_token (parser)->location,
4714 : declarator, specs, width, &all_prefix_attrs, expr);
4715 4307731 : decl_attributes (&d, chainon (postfix_attrs,
4716 : all_prefix_attrs), 0);
4717 4307731 : DECL_CHAIN (d) = decls;
4718 4307731 : decls = d;
4719 4307731 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4720 0 : all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4721 : prefix_attrs);
4722 : else
4723 4307731 : all_prefix_attrs = prefix_attrs;
4724 4307731 : if (c_parser_next_token_is (parser, CPP_COMMA))
4725 57663 : c_parser_consume_token (parser);
4726 4250068 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4727 4250091 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4728 : {
4729 : /* Semicolon consumed in caller. */
4730 : break;
4731 : }
4732 : else
4733 : {
4734 0 : c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
4735 0 : break;
4736 : }
4737 : }
4738 : else
4739 : {
4740 0 : c_parser_error (parser,
4741 : "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4742 : "%<__attribute__%>");
4743 0 : break;
4744 : }
4745 : }
4746 4250069 : return decls;
4747 : }
4748 :
4749 : /* Parse a typeof specifier (a GNU extension adopted in C23).
4750 :
4751 : typeof-specifier:
4752 : typeof ( expression )
4753 : typeof ( type-name )
4754 : typeof_unqual ( expression )
4755 : typeof_unqual ( type-name )
4756 : */
4757 :
4758 : static struct c_typespec
4759 819810 : c_parser_typeof_specifier (c_parser *parser)
4760 : {
4761 819810 : bool is_unqual;
4762 819810 : bool is_std;
4763 819810 : struct c_typespec ret;
4764 819810 : ret.kind = ctsk_typeof;
4765 819810 : ret.spec = error_mark_node;
4766 819810 : ret.expr = NULL_TREE;
4767 819810 : ret.expr_const_operands = true;
4768 819810 : ret.has_enum_type_specifier = false;
4769 819810 : if (c_parser_next_token_is_keyword (parser, RID_TYPEOF))
4770 : {
4771 819718 : is_unqual = false;
4772 819718 : tree spelling = c_parser_peek_token (parser)->value;
4773 819718 : is_std = (flag_isoc23
4774 920596 : && strcmp (IDENTIFIER_POINTER (spelling), "typeof") == 0);
4775 : }
4776 : else
4777 : {
4778 92 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4779 92 : is_unqual = true;
4780 92 : tree spelling = c_parser_peek_token (parser)->value;
4781 92 : is_std = strcmp (IDENTIFIER_POINTER (spelling), "typeof_unqual") == 0;
4782 : }
4783 819810 : c_parser_consume_token (parser);
4784 819810 : c_inhibit_evaluation_warnings++;
4785 819810 : in_typeof++;
4786 819810 : matching_parens parens;
4787 819810 : if (!parens.require_open (parser))
4788 : {
4789 0 : c_inhibit_evaluation_warnings--;
4790 0 : in_typeof--;
4791 0 : return ret;
4792 : }
4793 819810 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
4794 : {
4795 689 : struct c_type_name *type = c_parser_type_name (parser);
4796 689 : c_inhibit_evaluation_warnings--;
4797 689 : in_typeof--;
4798 689 : if (type != NULL)
4799 : {
4800 689 : ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4801 689 : pop_maybe_used (c_type_variably_modified_p (ret.spec));
4802 : }
4803 : }
4804 : else
4805 : {
4806 819121 : bool was_vm;
4807 819121 : location_t here = c_parser_peek_token (parser)->location;
4808 819121 : struct c_expr expr = c_parser_expression (parser);
4809 819121 : c_inhibit_evaluation_warnings--;
4810 819121 : in_typeof--;
4811 819121 : if (TREE_CODE (expr.value) == COMPONENT_REF
4812 819121 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4813 13 : error_at (here, "%<typeof%> applied to a bit-field");
4814 819121 : mark_exp_read (expr.value);
4815 819121 : ret.spec = TREE_TYPE (expr.value);
4816 819121 : was_vm = c_type_variably_modified_p (ret.spec);
4817 : /* This is returned with the type so that when the type is
4818 : evaluated, this can be evaluated. */
4819 819121 : if (was_vm)
4820 218 : ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4821 819121 : pop_maybe_used (was_vm);
4822 : }
4823 819810 : parens.skip_until_found_close (parser);
4824 819810 : if (ret.spec != error_mark_node)
4825 : {
4826 819799 : if (is_unqual)
4827 : {
4828 92 : bool is_array = TREE_CODE (ret.spec) == ARRAY_TYPE;
4829 92 : int quals = TYPE_QUALS (strip_array_types (ret.spec));
4830 92 : if ((is_array ? quals & ~TYPE_QUAL_ATOMIC : quals)
4831 : != TYPE_UNQUALIFIED)
4832 : {
4833 51 : ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4834 51 : if (quals & TYPE_QUAL_ATOMIC && is_array)
4835 4 : ret.spec = c_build_qualified_type (ret.spec,
4836 : TYPE_QUAL_ATOMIC);
4837 : }
4838 : }
4839 819799 : if (is_std)
4840 : {
4841 : /* In ISO C terms, _Noreturn is not part of the type of
4842 : expressions such as &abort, but in GCC it is represented
4843 : internally as a type qualifier. */
4844 4282 : if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4845 4282 : && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4846 2 : ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4847 2917 : else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4848 7108 : && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4849 2 : ret.spec
4850 2 : = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4851 : }
4852 : }
4853 : return ret;
4854 : }
4855 :
4856 : /* Parse an alignment-specifier.
4857 :
4858 : C11 6.7.5:
4859 :
4860 : alignment-specifier:
4861 : _Alignas ( type-name )
4862 : _Alignas ( constant-expression )
4863 : */
4864 :
4865 : static tree
4866 202 : c_parser_alignas_specifier (c_parser * parser)
4867 : {
4868 202 : tree ret = error_mark_node;
4869 202 : location_t loc = c_parser_peek_token (parser)->location;
4870 202 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4871 202 : tree spelling = c_parser_peek_token (parser)->value;
4872 202 : c_parser_consume_token (parser);
4873 202 : if (flag_isoc99)
4874 199 : pedwarn_c99 (loc, OPT_Wpedantic,
4875 : "ISO C99 does not support %qE", spelling);
4876 : else
4877 3 : pedwarn_c99 (loc, OPT_Wpedantic,
4878 : "ISO C90 does not support %qE", spelling);
4879 202 : matching_parens parens;
4880 202 : if (!parens.require_open (parser))
4881 : return ret;
4882 202 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
4883 : {
4884 132 : struct c_type_name *type = c_parser_type_name (parser);
4885 132 : if (type != NULL)
4886 131 : ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4887 : false, true, 1);
4888 : }
4889 : else
4890 70 : ret = convert_lvalue_to_rvalue (loc,
4891 : c_parser_expr_no_commas (parser, NULL),
4892 : true, true).value;
4893 202 : parens.skip_until_found_close (parser);
4894 202 : return ret;
4895 : }
4896 :
4897 : /* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4898 : 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4899 : a typedef name may be redeclared; otherwise it may not. KIND
4900 : indicates which kind of declarator is wanted. Returns a valid
4901 : declarator except in the case of a syntax error in which case NULL is
4902 : returned. *SEEN_ID is set to true if an identifier being declared is
4903 : seen; this is used to diagnose bad forms of abstract array declarators
4904 : and to determine whether an identifier list is syntactically permitted.
4905 :
4906 : declarator:
4907 : pointer[opt] direct-declarator
4908 :
4909 : direct-declarator:
4910 : identifier
4911 : ( gnu-attributes[opt] declarator )
4912 : direct-declarator array-declarator
4913 : direct-declarator ( parameter-type-list )
4914 : direct-declarator ( identifier-list[opt] )
4915 :
4916 : pointer:
4917 : * type-qualifier-list[opt]
4918 : * type-qualifier-list[opt] pointer
4919 :
4920 : type-qualifier-list:
4921 : type-qualifier
4922 : gnu-attributes
4923 : type-qualifier-list type-qualifier
4924 : type-qualifier-list gnu-attributes
4925 :
4926 : array-declarator:
4927 : [ type-qualifier-list[opt] assignment-expression[opt] ]
4928 : [ static type-qualifier-list[opt] assignment-expression ]
4929 : [ type-qualifier-list static assignment-expression ]
4930 : [ type-qualifier-list[opt] * ]
4931 :
4932 : parameter-type-list:
4933 : parameter-list
4934 : parameter-list , ...
4935 :
4936 : parameter-list:
4937 : parameter-declaration
4938 : parameter-list , parameter-declaration
4939 :
4940 : parameter-declaration:
4941 : declaration-specifiers declarator gnu-attributes[opt]
4942 : declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4943 :
4944 : identifier-list:
4945 : identifier
4946 : identifier-list , identifier
4947 :
4948 : abstract-declarator:
4949 : pointer
4950 : pointer[opt] direct-abstract-declarator
4951 :
4952 : direct-abstract-declarator:
4953 : ( gnu-attributes[opt] abstract-declarator )
4954 : direct-abstract-declarator[opt] array-declarator
4955 : direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4956 :
4957 : GNU extensions:
4958 :
4959 : direct-declarator:
4960 : direct-declarator ( parameter-forward-declarations
4961 : parameter-type-list[opt] )
4962 :
4963 : direct-abstract-declarator:
4964 : direct-abstract-declarator[opt] ( parameter-forward-declarations
4965 : parameter-type-list[opt] )
4966 :
4967 : parameter-forward-declarations:
4968 : parameter-list ;
4969 : parameter-forward-declarations parameter-list ;
4970 :
4971 : The uses of gnu-attributes shown above are GNU extensions.
4972 :
4973 : Some forms of array declarator are not included in C99 in the
4974 : syntax for abstract declarators; these are disallowed elsewhere.
4975 : This may be a defect (DR#289).
4976 :
4977 : This function also accepts an omitted abstract declarator as being
4978 : an abstract declarator, although not part of the formal syntax. */
4979 :
4980 : struct c_declarator *
4981 332088435 : c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4982 : bool *seen_id)
4983 : {
4984 : /* Parse any initial pointer part. */
4985 332088435 : if (c_parser_next_token_is (parser, CPP_MULT))
4986 : {
4987 18211099 : struct c_declspecs *quals_attrs = build_null_declspecs ();
4988 18211099 : struct c_declarator *inner;
4989 18211099 : c_parser_consume_token (parser);
4990 18211099 : c_parser_declspecs (parser, quals_attrs, false, false, true,
4991 : false, false, true, false, cla_prefer_id);
4992 18211099 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4993 18211099 : if (inner == NULL)
4994 : return NULL;
4995 : else
4996 18211090 : return make_pointer_declarator (quals_attrs, inner);
4997 : }
4998 : /* Now we have a direct declarator, direct abstract declarator or
4999 : nothing (which counts as a direct abstract declarator here). */
5000 313877336 : return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
5001 : }
5002 :
5003 : /* Parse a direct declarator or direct abstract declarator; arguments
5004 : as c_parser_declarator. */
5005 :
5006 : static struct c_declarator *
5007 313877336 : c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
5008 : bool *seen_id)
5009 : {
5010 : /* The direct declarator must start with an identifier (possibly
5011 : omitted) or a parenthesized declarator (possibly abstract). In
5012 : an ordinary declarator, initial parentheses must start a
5013 : parenthesized declarator. In an abstract declarator or parameter
5014 : declarator, they could start a parenthesized declarator or a
5015 : parameter list. To tell which, the open parenthesis and any
5016 : following gnu-attributes must be read. If a declaration
5017 : specifier or standard attributes follow, then it is a parameter
5018 : list; if the specifier is a typedef name, there might be an
5019 : ambiguity about redeclaring it, which is resolved in the
5020 : direction of treating it as a typedef name. If a close
5021 : parenthesis follows, it is also an empty parameter list, as the
5022 : syntax does not permit empty abstract declarators. Otherwise, it
5023 : is a parenthesized declarator (in which case the analysis may be
5024 : repeated inside it, recursively).
5025 :
5026 : ??? There is an ambiguity in a parameter declaration "int
5027 : (__attribute__((foo)) x)", where x is not a typedef name: it
5028 : could be an abstract declarator for a function, or declare x with
5029 : parentheses. The proper resolution of this ambiguity needs
5030 : documenting. At present we follow an accident of the old
5031 : parser's implementation, whereby the first parameter must have
5032 : some declaration specifiers other than just gnu-attributes. Thus as
5033 : a parameter declaration it is treated as a parenthesized
5034 : parameter named x, and as an abstract declarator it is
5035 : rejected.
5036 :
5037 : ??? Also following the old parser, gnu-attributes inside an empty
5038 : parameter list are ignored, making it a list not yielding a
5039 : prototype, rather than giving an error or making it have one
5040 : parameter with implicit type int.
5041 :
5042 : ??? Also following the old parser, typedef names may be
5043 : redeclared in declarators, but not Objective-C class names. */
5044 :
5045 313877336 : if (kind != C_DTR_ABSTRACT
5046 192545008 : && c_parser_next_token_is (parser, CPP_NAME)
5047 501616293 : && ((type_seen_p
5048 187729097 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
5049 187681829 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
5050 187691689 : || c_parser_peek_token (parser)->id_kind == C_ID_ID))
5051 : {
5052 187738957 : struct c_declarator *inner
5053 187738957 : = build_id_declarator (c_parser_peek_token (parser)->value);
5054 187738957 : *seen_id = true;
5055 187738957 : inner->id_loc = c_parser_peek_token (parser)->location;
5056 187738957 : c_parser_consume_token (parser);
5057 187738957 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
5058 84 : inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
5059 187738957 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5060 : }
5061 :
5062 126138379 : if (kind != C_DTR_NORMAL
5063 125997315 : && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
5064 126162538 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5065 : {
5066 24159 : struct c_declarator *inner = build_id_declarator (NULL_TREE);
5067 24159 : inner->id_loc = c_parser_peek_token (parser)->location;
5068 24159 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5069 : }
5070 :
5071 : /* Either we are at the end of an abstract declarator, or we have
5072 : parentheses. */
5073 :
5074 126114220 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
5075 : {
5076 227292 : tree attrs;
5077 227292 : struct c_declarator *inner;
5078 227292 : c_parser_consume_token (parser);
5079 227292 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5080 : RID_ATTRIBUTE);
5081 227292 : attrs = c_parser_gnu_attributes (parser);
5082 227292 : if (kind != C_DTR_NORMAL
5083 227292 : && (c_parser_next_token_starts_declspecs (parser)
5084 86296 : || (!have_gnu_attrs
5085 86138 : && (c_parser_nth_token_starts_std_attributes (parser, 1)
5086 86138 : || c_parser_next_token_is (parser, CPP_ELLIPSIS)))
5087 86291 : || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
5088 : {
5089 64 : struct c_arg_info *args
5090 64 : = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
5091 : attrs, have_gnu_attrs);
5092 64 : if (args == NULL)
5093 : return NULL;
5094 : else
5095 : {
5096 64 : inner = build_id_declarator (NULL_TREE);
5097 89 : if (!(args->types
5098 25 : && args->types != error_mark_node
5099 25 : && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5100 89 : && c_parser_nth_token_starts_std_attributes (parser, 1))
5101 : {
5102 4 : tree std_attrs
5103 4 : = c_parser_std_attribute_specifier_sequence (parser);
5104 4 : if (std_attrs)
5105 2 : inner = build_attrs_declarator (std_attrs, inner);
5106 : }
5107 64 : inner = build_function_declarator (args, inner);
5108 64 : return c_parser_direct_declarator_inner (parser, *seen_id,
5109 64 : inner);
5110 : }
5111 : }
5112 : /* A parenthesized declarator. */
5113 227228 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
5114 227228 : if (inner != NULL && attrs != NULL)
5115 179 : inner = build_attrs_declarator (attrs, inner);
5116 227228 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5117 : {
5118 227212 : c_parser_consume_token (parser);
5119 227212 : if (inner == NULL)
5120 : return NULL;
5121 : else
5122 227212 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
5123 : }
5124 : else
5125 : {
5126 16 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5127 : "expected %<)%>");
5128 16 : return NULL;
5129 : }
5130 : }
5131 : else
5132 : {
5133 125886928 : if (kind == C_DTR_NORMAL)
5134 : {
5135 93 : c_parser_error (parser, "expected identifier or %<(%>");
5136 93 : return NULL;
5137 : }
5138 : else
5139 125886835 : return build_id_declarator (NULL_TREE);
5140 : }
5141 : }
5142 :
5143 : /* Parse part of a direct declarator or direct abstract declarator,
5144 : given that some (in INNER) has already been parsed; ID_PRESENT is
5145 : true if an identifier is present, false for an abstract
5146 : declarator. */
5147 :
5148 : static struct c_declarator *
5149 239638334 : c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
5150 : struct c_declarator *inner)
5151 : {
5152 : /* Parse a sequence of array declarators and parameter lists. */
5153 239638334 : if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
5154 239638334 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5155 : {
5156 1151493 : location_t brace_loc = c_parser_peek_token (parser)->location;
5157 1151493 : struct c_declarator *declarator;
5158 1151493 : struct c_declspecs *quals_attrs = build_null_declspecs ();
5159 1151493 : struct c_expr dimen;
5160 1151493 : dimen.value = NULL_TREE;
5161 1151493 : dimen.original_code = ERROR_MARK;
5162 1151493 : dimen.original_type = NULL_TREE;
5163 1151493 : c_parser_consume_token (parser);
5164 1151493 : c_parser_declspecs (parser, quals_attrs, false, false, true,
5165 : false, false, false, false, cla_prefer_id);
5166 :
5167 1151493 : location_t static_loc = UNKNOWN_LOCATION;
5168 1151493 : if (c_parser_next_token_is_keyword (parser, RID_STATIC))
5169 : {
5170 131 : static_loc = c_parser_peek_token (parser)->location;
5171 131 : c_parser_consume_token (parser);
5172 131 : if (!quals_attrs->declspecs_seen_p)
5173 111 : c_parser_declspecs (parser, quals_attrs, false, false, true,
5174 : false, false, false, false, cla_prefer_id);
5175 : }
5176 1151493 : if (!quals_attrs->declspecs_seen_p)
5177 1150522 : quals_attrs = NULL;
5178 : /* If "static" is present, there must be an array dimension.
5179 : Otherwise, there may be a dimension, "*", or no
5180 : dimension. */
5181 1151493 : const bool static_seen = (static_loc != UNKNOWN_LOCATION);
5182 1151493 : bool star_seen = false;
5183 1151493 : if (c_parser_next_token_is (parser, CPP_MULT)
5184 1151493 : && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
5185 : {
5186 154 : star_seen = true;
5187 154 : c_parser_consume_token (parser);
5188 : }
5189 1151339 : else if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5190 980394 : dimen = c_parser_expr_no_commas (parser, NULL);
5191 :
5192 1151493 : if (static_seen)
5193 : {
5194 131 : if (star_seen)
5195 : {
5196 3 : error_at (static_loc,
5197 : "%<static%> may not be used with an unspecified "
5198 : "variable length array size");
5199 : /* Prevent further errors. */
5200 3 : star_seen = false;
5201 3 : dimen.value = error_mark_node;
5202 : }
5203 128 : else if (!dimen.value)
5204 2 : error_at (static_loc,
5205 : "%<static%> may not be used without an array size");
5206 : }
5207 :
5208 1151493 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5209 1151478 : c_parser_consume_token (parser);
5210 : else
5211 : {
5212 15 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
5213 : "expected %<]%>");
5214 15 : return NULL;
5215 : }
5216 1151478 : if (dimen.value)
5217 980382 : dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
5218 1151478 : declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
5219 : static_seen, star_seen);
5220 1151478 : if (declarator == NULL)
5221 : return NULL;
5222 1151478 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
5223 : {
5224 16 : tree std_attrs
5225 16 : = c_parser_std_attribute_specifier_sequence (parser);
5226 16 : if (std_attrs)
5227 10 : inner = build_attrs_declarator (std_attrs, inner);
5228 : }
5229 1151478 : inner = set_array_declarator_inner (declarator, inner);
5230 1151478 : return c_parser_direct_declarator_inner (parser, id_present, inner);
5231 : }
5232 238486841 : else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
5233 : {
5234 50496572 : tree attrs;
5235 50496572 : struct c_arg_info *args;
5236 50496572 : c_parser_consume_token (parser);
5237 50496572 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5238 : RID_ATTRIBUTE);
5239 50496572 : attrs = c_parser_gnu_attributes (parser);
5240 50496572 : args = c_parser_parms_declarator (parser, id_present, attrs,
5241 : have_gnu_attrs);
5242 50496572 : if (args == NULL)
5243 : return NULL;
5244 : else
5245 : {
5246 100220719 : if (!(args->types
5247 49724255 : && args->types != error_mark_node
5248 49724255 : && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5249 100212032 : && c_parser_nth_token_starts_std_attributes (parser, 1))
5250 : {
5251 98 : tree std_attrs
5252 98 : = c_parser_std_attribute_specifier_sequence (parser);
5253 98 : if (std_attrs)
5254 81 : inner = build_attrs_declarator (std_attrs, inner);
5255 : }
5256 50496464 : inner = build_function_declarator (args, inner);
5257 50496464 : return c_parser_direct_declarator_inner (parser, id_present, inner);
5258 : }
5259 : }
5260 : return inner;
5261 : }
5262 :
5263 : /* Parse a parameter list or identifier list, including the closing
5264 : parenthesis but not the opening one. ATTRS are the gnu-attributes
5265 : at the start of the list. ID_LIST_OK is true if an identifier list
5266 : is acceptable; such a list must not have attributes at the start.
5267 : HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
5268 : attributes) were present (in which case standard attributes cannot
5269 : occur). */
5270 :
5271 : static struct c_arg_info *
5272 50496636 : c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
5273 : bool have_gnu_attrs)
5274 : {
5275 50496636 : push_scope ();
5276 50496636 : declare_parm_level ();
5277 : /* If the list starts with an identifier, it is an identifier list.
5278 : Otherwise, it is either a prototype list or an empty list. */
5279 50496636 : if (id_list_ok
5280 50496636 : && !attrs
5281 50484483 : && c_parser_next_token_is (parser, CPP_NAME)
5282 33765974 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
5283 :
5284 : /* Look ahead to detect typos in type names. */
5285 8698 : && c_parser_peek_2nd_token (parser)->type != CPP_NAME
5286 8691 : && c_parser_peek_2nd_token (parser)->type != CPP_MULT
5287 8690 : && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
5288 8689 : && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
5289 50505324 : && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
5290 : {
5291 8687 : tree list = NULL_TREE, *nextp = &list;
5292 8687 : while (c_parser_next_token_is (parser, CPP_NAME)
5293 34292 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
5294 : {
5295 34292 : *nextp = build_tree_list (NULL_TREE,
5296 34292 : c_parser_peek_token (parser)->value);
5297 34292 : nextp = & TREE_CHAIN (*nextp);
5298 34292 : c_parser_consume_token (parser);
5299 34292 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
5300 : break;
5301 25605 : c_parser_consume_token (parser);
5302 25605 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5303 : {
5304 0 : c_parser_error (parser, "expected identifier");
5305 0 : break;
5306 : }
5307 : }
5308 8687 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5309 : {
5310 8687 : struct c_arg_info *ret = build_arg_info ();
5311 8687 : ret->types = list;
5312 8687 : c_parser_consume_token (parser);
5313 8687 : pop_scope ();
5314 8687 : return ret;
5315 : }
5316 : else
5317 : {
5318 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5319 : "expected %<)%>");
5320 0 : pop_scope ();
5321 0 : return NULL;
5322 : }
5323 : }
5324 : else
5325 : {
5326 50487949 : struct c_arg_info *ret
5327 50487949 : = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
5328 50487949 : pop_scope ();
5329 50487949 : return ret;
5330 : }
5331 : }
5332 :
5333 : /* Parse a parameter list (possibly empty), including the closing
5334 : parenthesis but not the opening one. ATTRS are the gnu-attributes
5335 : at the start of the list; if HAVE_GNU_ATTRS, there were some such
5336 : attributes (possibly empty, in which case ATTRS is NULL_TREE),
5337 : which means standard attributes cannot start the list. EXPR is
5338 : NULL or an expression that needs to be evaluated for the side
5339 : effects of array size expressions in the parameters. */
5340 :
5341 : static struct c_arg_info *
5342 50487991 : c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
5343 : bool have_gnu_attrs)
5344 : {
5345 50487991 : bool bad_parm = false;
5346 :
5347 : /* ??? Following the old parser, forward parameter declarations may
5348 : use abstract declarators, and if no real parameter declarations
5349 : follow the forward declarations then this is not diagnosed. Also
5350 : note as above that gnu-attributes are ignored as the only contents of
5351 : the parentheses, or as the only contents after forward
5352 : declarations. */
5353 50487991 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5354 : {
5355 772089 : struct c_arg_info *ret = build_arg_info ();
5356 772089 : c_parser_consume_token (parser);
5357 772089 : return ret;
5358 : }
5359 49715902 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS) && !have_gnu_attrs)
5360 : {
5361 136 : struct c_arg_info *ret = build_arg_info ();
5362 :
5363 136 : ret->types = NULL_TREE;
5364 136 : pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
5365 : "ISO C requires a named argument before %<...%> "
5366 : "before C23");
5367 136 : c_parser_consume_token (parser);
5368 136 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5369 : {
5370 136 : ret->no_named_args_stdarg_p = true;
5371 136 : c_parser_consume_token (parser);
5372 136 : return ret;
5373 : }
5374 : else
5375 : {
5376 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5377 : "expected %<)%>");
5378 0 : return NULL;
5379 : }
5380 : }
5381 : /* Nonempty list of parameters, either terminated with semicolon
5382 : (forward declarations; recurse) or with close parenthesis (normal
5383 : function) or with ", ... )" (variadic function). */
5384 123862934 : while (true)
5385 : {
5386 : /* Parse a parameter. */
5387 123862934 : struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
5388 : have_gnu_attrs);
5389 123862934 : attrs = NULL_TREE;
5390 123862934 : have_gnu_attrs = false;
5391 123862934 : if (parm == NULL)
5392 : bad_parm = true;
5393 : else
5394 123862825 : push_parm_decl (parm, &expr);
5395 123862934 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
5396 : {
5397 42 : tree new_attrs;
5398 42 : c_parser_consume_token (parser);
5399 42 : mark_forward_parm_decls ();
5400 42 : bool new_have_gnu_attrs
5401 42 : = c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE);
5402 42 : new_attrs = c_parser_gnu_attributes (parser);
5403 42 : return c_parser_parms_list_declarator (parser, new_attrs, expr,
5404 42 : new_have_gnu_attrs);
5405 : }
5406 123862892 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5407 : {
5408 49502989 : c_parser_consume_token (parser);
5409 49502989 : if (bad_parm)
5410 : return NULL;
5411 : else
5412 49502904 : return get_parm_info (false, expr);
5413 : }
5414 74359903 : if (!c_parser_require (parser, CPP_COMMA,
5415 : "expected %<;%>, %<,%> or %<)%>",
5416 : UNKNOWN_LOCATION, false))
5417 : {
5418 8 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5419 8 : return NULL;
5420 : }
5421 74359895 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
5422 : {
5423 212727 : c_parser_consume_token (parser);
5424 212727 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5425 : {
5426 212720 : c_parser_consume_token (parser);
5427 212720 : if (bad_parm)
5428 : return NULL;
5429 : else
5430 212712 : return get_parm_info (true, expr);
5431 : }
5432 : else
5433 : {
5434 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5435 : "expected %<)%>");
5436 7 : return NULL;
5437 : }
5438 : }
5439 : }
5440 : }
5441 :
5442 : /* Parse a parameter declaration. ATTRS are the gnu-attributes at the
5443 : start of the declaration if it is the first parameter;
5444 : HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
5445 : empty) there. */
5446 :
5447 : static struct c_parm *
5448 123862934 : c_parser_parameter_declaration (c_parser *parser, tree attrs,
5449 : bool have_gnu_attrs)
5450 : {
5451 123862934 : struct c_declspecs *specs;
5452 123862934 : struct c_declarator *declarator;
5453 123862934 : tree prefix_attrs;
5454 123862934 : tree postfix_attrs = NULL_TREE;
5455 123862934 : bool dummy = false;
5456 :
5457 : /* Accept #pragmas between parameter declarations. */
5458 123862936 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
5459 2 : c_parser_pragma (parser, pragma_param, NULL, NULL_TREE);
5460 :
5461 123862934 : if (!c_parser_next_token_starts_declspecs (parser)
5462 123862934 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5463 : {
5464 97 : c_token *token = c_parser_peek_token (parser);
5465 97 : if (parser->error)
5466 : return NULL;
5467 97 : c_parser_set_source_position_from_token (token);
5468 97 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
5469 : {
5470 79 : auto_diagnostic_group d;
5471 79 : name_hint hint = lookup_name_fuzzy (token->value,
5472 : FUZZY_LOOKUP_TYPENAME,
5473 79 : token->location);
5474 79 : if (const char *suggestion = hint.suggestion ())
5475 : {
5476 30 : gcc_rich_location richloc (token->location);
5477 30 : richloc.add_fixit_replace (suggestion);
5478 30 : error_at (&richloc,
5479 : "unknown type name %qE; did you mean %qs?",
5480 : token->value, suggestion);
5481 30 : }
5482 : else
5483 49 : error_at (token->location, "unknown type name %qE", token->value);
5484 79 : parser->error = true;
5485 79 : }
5486 : /* ??? In some Objective-C cases '...' isn't applicable so there
5487 : should be a different message. */
5488 : else
5489 18 : c_parser_error (parser,
5490 : "expected declaration specifiers or %<...%>");
5491 97 : c_parser_skip_to_end_of_parameter (parser);
5492 97 : return NULL;
5493 : }
5494 :
5495 123862837 : location_t start_loc = c_parser_peek_token (parser)->location;
5496 :
5497 123862837 : specs = build_null_declspecs ();
5498 123862837 : if (attrs)
5499 : {
5500 339 : declspecs_add_attrs (input_location, specs, attrs);
5501 339 : attrs = NULL_TREE;
5502 : }
5503 123862837 : c_parser_declspecs (parser, specs, true, true, true, true, false,
5504 123862837 : !have_gnu_attrs, true, cla_nonabstract_decl);
5505 123862837 : finish_declspecs (specs);
5506 : /* When the param is declared, its type is a top level type, we should
5507 : call verify_counted_by_for_top_anonymous_type. */
5508 123862837 : if (specs->typespec_kind == ctsk_tagdef)
5509 65 : verify_counted_by_for_top_anonymous_type (specs->type);
5510 :
5511 123862837 : pending_xref_error ();
5512 123862837 : prefix_attrs = specs->attrs;
5513 123862837 : specs->attrs = NULL_TREE;
5514 247725674 : declarator = c_parser_declarator (parser,
5515 123862837 : specs->typespec_kind != ctsk_none,
5516 : C_DTR_PARM, &dummy);
5517 123862837 : if (declarator == NULL)
5518 : {
5519 12 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
5520 12 : return NULL;
5521 : }
5522 123862825 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
5523 17287 : postfix_attrs = c_parser_gnu_attributes (parser);
5524 :
5525 : /* Generate a location for the parameter, ranging from the start of the
5526 : initial token to the end of the final token.
5527 :
5528 : If we have a identifier, then use it for the caret location, e.g.
5529 :
5530 : extern int callee (int one, int (*two)(int, int), float three);
5531 : ~~~~~~^~~~~~~~~~~~~~
5532 :
5533 : otherwise, reuse the start location for the caret location e.g.:
5534 :
5535 : extern int callee (int one, int (*)(int, int), float three);
5536 : ^~~~~~~~~~~~~~~~~
5537 : */
5538 123862825 : location_t end_loc = parser->last_token_location;
5539 :
5540 : /* Find any cdk_id declarator; determine if we have an identifier. */
5541 123862825 : c_declarator *id_declarator = declarator;
5542 136754652 : while (id_declarator && id_declarator->kind != cdk_id)
5543 12891827 : id_declarator = id_declarator->declarator;
5544 119278451 : location_t caret_loc = (id_declarator->u.id.id
5545 123862825 : ? id_declarator->id_loc
5546 : : start_loc);
5547 123862825 : location_t param_loc = make_location (caret_loc, start_loc, end_loc);
5548 :
5549 123862825 : return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5550 123862825 : declarator, param_loc);
5551 : }
5552 :
5553 : /* Parse a string literal in an asm expression. It should not be
5554 : translated, and wide string literals are an error although
5555 : permitted by the syntax. This is a GNU extension.
5556 :
5557 : asm-string-literal:
5558 : string-literal
5559 : */
5560 :
5561 : static tree
5562 1967962 : c_parser_asm_string_literal (c_parser *parser)
5563 : {
5564 1967962 : tree str;
5565 1967962 : int save_flag = warn_overlength_strings;
5566 1967962 : warn_overlength_strings = 0;
5567 1967962 : str = c_parser_string_literal (parser, false, false).value;
5568 1967962 : warn_overlength_strings = save_flag;
5569 1967962 : return str;
5570 : }
5571 :
5572 : /* Parse a simple asm expression. This is used in restricted
5573 : contexts, where a full expression with inputs and outputs does not
5574 : make sense. This is a GNU extension.
5575 :
5576 : simple-asm-expr:
5577 : asm ( asm-string-literal )
5578 : */
5579 :
5580 : static tree
5581 871446 : c_parser_simple_asm_expr (c_parser *parser)
5582 : {
5583 871446 : tree str;
5584 871446 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5585 871446 : c_parser_consume_token (parser);
5586 871446 : matching_parens parens;
5587 871446 : if (!parens.require_open (parser))
5588 : return NULL_TREE;
5589 871446 : str = c_parser_asm_string_literal (parser);
5590 871446 : if (!parens.require_close (parser))
5591 : {
5592 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5593 0 : return NULL_TREE;
5594 : }
5595 : return str;
5596 : }
5597 :
5598 : static tree
5599 135224691 : c_parser_gnu_attribute_any_word (c_parser *parser)
5600 : {
5601 135224691 : tree attr_name = NULL_TREE;
5602 :
5603 135224691 : if (c_parser_next_token_is (parser, CPP_KEYWORD))
5604 : {
5605 : /* ??? See comment above about what keywords are accepted here. */
5606 864424 : bool ok;
5607 864424 : switch (c_parser_peek_token (parser)->keyword)
5608 : {
5609 : case RID_STATIC:
5610 : case RID_UNSIGNED:
5611 : case RID_LONG:
5612 : case RID_CONST:
5613 : case RID_EXTERN:
5614 : case RID_REGISTER:
5615 : case RID_TYPEDEF:
5616 : case RID_SHORT:
5617 : case RID_INLINE:
5618 : case RID_NORETURN:
5619 : case RID_VOLATILE:
5620 : case RID_SIGNED:
5621 : case RID_AUTO:
5622 : case RID_RESTRICT:
5623 : case RID_COMPLEX:
5624 : case RID_THREAD:
5625 : case RID_INT:
5626 : case RID_CHAR:
5627 : case RID_FLOAT:
5628 : case RID_DOUBLE:
5629 : case RID_VOID:
5630 : case RID_DFLOAT32:
5631 : case RID_DFLOAT64:
5632 : case RID_DFLOAT128:
5633 : case RID_DFLOAT64X:
5634 : CASE_RID_FLOATN_NX:
5635 : case RID_BOOL:
5636 : case RID_BITINT:
5637 : case RID_FRACT:
5638 : case RID_ACCUM:
5639 : case RID_SAT:
5640 : case RID_TRANSACTION_ATOMIC:
5641 : case RID_TRANSACTION_CANCEL:
5642 : case RID_ATOMIC:
5643 : case RID_AUTO_TYPE:
5644 : case RID_CONSTEXPR:
5645 : case RID_INT_N_0:
5646 : case RID_INT_N_1:
5647 : case RID_INT_N_2:
5648 : case RID_INT_N_3:
5649 : ok = true;
5650 : break;
5651 : default:
5652 : ok = false;
5653 : break;
5654 : }
5655 864424 : if (!ok)
5656 : return NULL_TREE;
5657 :
5658 : /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5659 864424 : attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5660 : }
5661 134360267 : else if (c_parser_next_token_is (parser, CPP_NAME))
5662 134360264 : attr_name = c_parser_peek_token (parser)->value;
5663 :
5664 : return attr_name;
5665 : }
5666 :
5667 : /* Parse attribute arguments. This is a common form of syntax
5668 : covering all currently valid GNU and standard attributes.
5669 :
5670 : gnu-attribute-arguments:
5671 : identifier
5672 : identifier , nonempty-expr-list
5673 : expr-list
5674 :
5675 : where the "identifier" must not be declared as a type. ??? Why not
5676 : allow identifiers declared as types to start the arguments? */
5677 :
5678 : static tree
5679 4520221 : c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5680 : bool require_string, bool assume_attr,
5681 : bool allow_empty_args)
5682 : {
5683 4520221 : vec<tree, va_gc> *expr_list;
5684 4520221 : tree attr_args;
5685 : /* Parse the attribute contents. If they start with an
5686 : identifier which is followed by a comma or close
5687 : parenthesis, then the arguments start with that
5688 : identifier; otherwise they are an expression list.
5689 : In objective-c the identifier may be a classname. */
5690 4520221 : if (c_parser_next_token_is (parser, CPP_NAME)
5691 570086 : && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5692 1 : || (c_dialect_objc ()
5693 0 : && c_parser_peek_token (parser)->id_kind
5694 : == C_ID_CLASSNAME))
5695 570085 : && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5696 40016 : || (c_parser_peek_2nd_token (parser)->type
5697 : == CPP_CLOSE_PAREN))
5698 5090267 : && (takes_identifier
5699 143938 : || (c_dialect_objc ()
5700 0 : && !assume_attr
5701 0 : && c_parser_peek_token (parser)->id_kind
5702 : == C_ID_CLASSNAME)))
5703 : {
5704 426108 : tree arg1 = c_parser_peek_token (parser)->value;
5705 426108 : c_parser_consume_token (parser);
5706 426108 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5707 35869 : attr_args = build_tree_list (NULL_TREE, arg1);
5708 : else
5709 : {
5710 390239 : tree tree_list;
5711 390239 : c_parser_consume_token (parser);
5712 390239 : expr_list = c_parser_expr_list (parser, false, true,
5713 : NULL, NULL, NULL, NULL);
5714 390239 : tree_list = build_tree_list_vec (expr_list);
5715 390239 : attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5716 390239 : release_tree_vector (expr_list);
5717 : }
5718 : }
5719 : else
5720 : {
5721 4094113 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5722 : {
5723 16 : if (!allow_empty_args)
5724 3 : error_at (c_parser_peek_token (parser)->location,
5725 : "parentheses must be omitted if "
5726 : "attribute argument list is empty");
5727 : attr_args = NULL_TREE;
5728 : }
5729 4094097 : else if (require_string)
5730 : {
5731 : /* The only valid argument for this attribute is a string
5732 : literal. Handle this specially here to avoid accepting
5733 : string literals with excess parentheses. */
5734 19 : tree string = c_parser_string_literal (parser, false, true).value;
5735 19 : attr_args = build_tree_list (NULL_TREE, string);
5736 : }
5737 4094078 : else if (assume_attr)
5738 : {
5739 45 : tree cond
5740 45 : = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5741 45 : if (!c_parser_next_token_is (parser, CPP_COMMA))
5742 43 : attr_args = build_tree_list (NULL_TREE, cond);
5743 : else
5744 : {
5745 2 : tree tree_list;
5746 2 : c_parser_consume_token (parser);
5747 2 : expr_list = c_parser_expr_list (parser, false, true,
5748 : NULL, NULL, NULL, NULL);
5749 2 : tree_list = build_tree_list_vec (expr_list);
5750 2 : attr_args = tree_cons (NULL_TREE, cond, tree_list);
5751 2 : release_tree_vector (expr_list);
5752 : }
5753 : }
5754 : else
5755 : {
5756 4094033 : expr_list = c_parser_expr_list (parser, false, true,
5757 : NULL, NULL, NULL, NULL);
5758 4094033 : attr_args = build_tree_list_vec (expr_list);
5759 4094033 : release_tree_vector (expr_list);
5760 : }
5761 : }
5762 4520221 : return attr_args;
5763 : }
5764 :
5765 : /* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5766 :
5767 : gnu-attributes:
5768 : empty
5769 : gnu-attributes gnu-attribute
5770 :
5771 : gnu-attribute:
5772 : __attribute__ ( ( gnu-attribute-list ) )
5773 :
5774 : gnu-attribute-list:
5775 : gnu-attrib
5776 : gnu-attribute_list , gnu-attrib
5777 :
5778 : gnu-attrib:
5779 : empty
5780 : any-word
5781 : any-word ( gnu-attribute-arguments )
5782 :
5783 : where "any-word" may be any identifier (including one declared as a
5784 : type), a reserved word storage class specifier, type specifier or
5785 : type qualifier. ??? This still leaves out most reserved keywords
5786 : (following the old parser), shouldn't we include them?
5787 : When EXPECT_COMMA is true, expect the attribute to be preceded
5788 : by a comma and fail if it isn't.
5789 : When EMPTY_OK is true, allow and consume any number of consecutive
5790 : commas with no attributes in between. */
5791 :
5792 : static tree
5793 188222913 : c_parser_gnu_attribute (c_parser *parser, tree attrs,
5794 : bool expect_comma = false, bool empty_ok = true)
5795 : {
5796 188222913 : bool comma_first = c_parser_next_token_is (parser, CPP_COMMA);
5797 188222913 : if (!comma_first
5798 105997203 : && !c_parser_next_token_is (parser, CPP_NAME)
5799 242085452 : && !c_parser_next_token_is (parser, CPP_KEYWORD))
5800 : return NULL_TREE;
5801 :
5802 217450408 : while (c_parser_next_token_is (parser, CPP_COMMA))
5803 : {
5804 82225717 : c_parser_consume_token (parser);
5805 82225717 : if (!empty_ok)
5806 : return attrs;
5807 : }
5808 :
5809 135224691 : tree attr_name = c_parser_gnu_attribute_any_word (parser);
5810 135224691 : if (attr_name == NULL_TREE)
5811 : return NULL_TREE;
5812 :
5813 135224688 : attr_name = canonicalize_attr_name (attr_name);
5814 135224688 : c_parser_consume_token (parser);
5815 :
5816 135224688 : tree attr;
5817 135224688 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
5818 : {
5819 130704563 : if (expect_comma && !comma_first)
5820 : {
5821 : /* A comma is missing between the last attribute on the chain
5822 : and this one. */
5823 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5824 : "expected %<)%>");
5825 7 : return error_mark_node;
5826 : }
5827 130704556 : attr = build_tree_list (attr_name, NULL_TREE);
5828 : /* Add this attribute to the list. */
5829 130704556 : attrs = chainon (attrs, attr);
5830 130704556 : return attrs;
5831 : }
5832 4520125 : c_parser_consume_token (parser);
5833 :
5834 4520125 : tree attr_args
5835 4520125 : = c_parser_attribute_arguments (parser,
5836 4520125 : attribute_takes_identifier_p (attr_name),
5837 : false,
5838 4520125 : is_attribute_p ("assume", attr_name),
5839 : true);
5840 :
5841 4520125 : attr = build_tree_list (attr_name, attr_args);
5842 4520125 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5843 4520123 : c_parser_consume_token (parser);
5844 : else
5845 : {
5846 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5847 : "expected %<)%>");
5848 2 : return error_mark_node;
5849 : }
5850 :
5851 4520123 : if (expect_comma && !comma_first)
5852 : {
5853 : /* A comma is missing between the last attribute on the chain
5854 : and this one. */
5855 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5856 : "expected %<)%>");
5857 0 : return error_mark_node;
5858 : }
5859 :
5860 : /* Add this attribute to the list. */
5861 4520123 : attrs = chainon (attrs, attr);
5862 4520123 : return attrs;
5863 : }
5864 :
5865 : static tree
5866 109360182 : c_parser_gnu_attributes (c_parser *parser)
5867 : {
5868 109360182 : tree attrs = NULL_TREE;
5869 162358403 : while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
5870 : {
5871 52998231 : bool save_translate_strings_p = parser->translate_strings_p;
5872 52998231 : parser->translate_strings_p = false;
5873 : /* Consume the `__attribute__' keyword. */
5874 52998231 : c_parser_consume_token (parser);
5875 : /* Look for the two `(' tokens. */
5876 52998231 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
5877 : {
5878 0 : parser->translate_strings_p = save_translate_strings_p;
5879 0 : return attrs;
5880 : }
5881 52998231 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
5882 : {
5883 0 : parser->translate_strings_p = save_translate_strings_p;
5884 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5885 0 : return attrs;
5886 : }
5887 : /* Parse the attribute list. Require a comma between successive
5888 : (possibly empty) attributes. */
5889 : for (bool expect_comma = false; ; expect_comma = true)
5890 : {
5891 : /* Parse a single attribute. */
5892 188222153 : tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5893 188222153 : if (attr == error_mark_node)
5894 : return attrs;
5895 188222144 : if (!attr)
5896 : break;
5897 : attrs = attr;
5898 : }
5899 :
5900 : /* Look for the two `)' tokens. */
5901 52998222 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5902 52998222 : c_parser_consume_token (parser);
5903 : else
5904 : {
5905 0 : parser->translate_strings_p = save_translate_strings_p;
5906 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5907 : "expected %<)%>");
5908 0 : return attrs;
5909 : }
5910 52998222 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5911 52998221 : c_parser_consume_token (parser);
5912 : else
5913 : {
5914 1 : parser->translate_strings_p = save_translate_strings_p;
5915 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5916 : "expected %<)%>");
5917 1 : return attrs;
5918 : }
5919 52998221 : parser->translate_strings_p = save_translate_strings_p;
5920 : }
5921 :
5922 : return attrs;
5923 : }
5924 :
5925 : /* Parse an optional balanced token sequence.
5926 :
5927 : balanced-token-sequence:
5928 : balanced-token
5929 : balanced-token-sequence balanced-token
5930 :
5931 : balanced-token:
5932 : ( balanced-token-sequence[opt] )
5933 : [ balanced-token-sequence[opt] ]
5934 : { balanced-token-sequence[opt] }
5935 : any token other than ()[]{}
5936 : */
5937 :
5938 : static void
5939 142 : c_parser_balanced_token_sequence (c_parser *parser)
5940 : {
5941 551 : while (true)
5942 : {
5943 551 : c_token *token = c_parser_peek_token (parser);
5944 551 : switch (token->type)
5945 : {
5946 4 : case CPP_OPEN_BRACE:
5947 4 : {
5948 4 : matching_braces braces;
5949 4 : braces.consume_open (parser);
5950 4 : c_parser_balanced_token_sequence (parser);
5951 4 : braces.require_close (parser);
5952 4 : break;
5953 : }
5954 :
5955 42 : case CPP_OPEN_PAREN:
5956 42 : {
5957 42 : matching_parens parens;
5958 42 : parens.consume_open (parser);
5959 42 : c_parser_balanced_token_sequence (parser);
5960 42 : parens.require_close (parser);
5961 42 : break;
5962 : }
5963 :
5964 33 : case CPP_OPEN_SQUARE:
5965 33 : c_parser_consume_token (parser);
5966 33 : c_parser_balanced_token_sequence (parser);
5967 33 : c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
5968 33 : break;
5969 :
5970 142 : case CPP_CLOSE_BRACE:
5971 142 : case CPP_CLOSE_PAREN:
5972 142 : case CPP_CLOSE_SQUARE:
5973 142 : case CPP_EOF:
5974 142 : return;
5975 :
5976 1 : case CPP_PRAGMA:
5977 1 : c_parser_consume_pragma (parser);
5978 1 : c_parser_skip_to_pragma_eol (parser, false);
5979 1 : break;
5980 :
5981 329 : default:
5982 329 : c_parser_consume_token (parser);
5983 329 : break;
5984 : }
5985 : }
5986 : }
5987 :
5988 : /* Parse arguments of omp::directive or omp::decl attribute.
5989 :
5990 : directive-name ,[opt] clause-list[opt]
5991 :
5992 : For directive just remember the tokens in a vector for subsequent
5993 : parsing. */
5994 :
5995 : static void
5996 914 : c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5997 : {
5998 914 : unsigned int n = 1;
5999 914 : c_token *first = c_parser_peek_token (parser);
6000 914 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
6001 914 : || (c_parser_peek_nth_token_raw (parser, n)->type
6002 : != CPP_CLOSE_PAREN))
6003 : {
6004 1 : c_parser_balanced_token_sequence (parser);
6005 1 : TREE_VALUE (attribute) = NULL_TREE;
6006 3 : return;
6007 : }
6008 913 : if (n == 1)
6009 : {
6010 2 : error_at (first->location, "expected OpenMP directive name");
6011 2 : TREE_VALUE (attribute) = NULL_TREE;
6012 2 : return;
6013 : }
6014 911 : vec<c_token, va_gc> *v;
6015 911 : vec_alloc (v, n - 1);
6016 18777 : for (--n; n; --n)
6017 : {
6018 17866 : c_token *tok = c_parser_peek_token (parser);
6019 17866 : v->quick_push (*tok);
6020 17866 : c_parser_consume_token (parser);
6021 : }
6022 911 : tree arg = make_node (C_TOKEN_VEC);
6023 911 : C_TOKEN_VEC_TOKENS (arg) = v;
6024 911 : if (decl_p)
6025 58 : TREE_PUBLIC (arg) = 1;
6026 911 : TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
6027 : }
6028 :
6029 : /* Parse arguments of omp::sequence attribute.
6030 :
6031 : omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
6032 :
6033 : static void
6034 157 : c_parser_omp_sequence_args (c_parser *parser, tree attribute)
6035 : {
6036 314 : do
6037 : {
6038 314 : c_token *token = c_parser_peek_token (parser);
6039 314 : if (token->type == CPP_NAME
6040 313 : && strcmp (IDENTIFIER_POINTER (token->value), "omp") == 0
6041 378 : && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
6042 : {
6043 64 : c_parser_consume_token (parser);
6044 64 : c_parser_consume_token (parser);
6045 64 : token = c_parser_peek_token (parser);
6046 : }
6047 314 : bool directive = false;
6048 314 : const char *p;
6049 314 : if (token->type != CPP_NAME)
6050 : p = "";
6051 : else
6052 313 : p = IDENTIFIER_POINTER (token->value);
6053 314 : if (strcmp (p, "directive") == 0)
6054 : directive = true;
6055 12 : else if (strcmp (p, "sequence") != 0)
6056 : {
6057 7 : error_at (token->location, "expected %<directive%> or %<sequence%>");
6058 7 : unsigned nesting_depth = 0;
6059 :
6060 47 : while (true)
6061 : {
6062 : /* Peek at the next token. */
6063 27 : token = c_parser_peek_token (parser);
6064 : /* If we've reached the token we want, consume it and stop. */
6065 27 : if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
6066 13 : && !nesting_depth)
6067 : break;
6068 : /* If we've run out of tokens, stop. */
6069 20 : if (token->type == CPP_EOF)
6070 : break;
6071 20 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
6072 : break;
6073 20 : if (token->type == CPP_OPEN_BRACE
6074 : || token->type == CPP_OPEN_PAREN
6075 : || token->type == CPP_OPEN_SQUARE)
6076 6 : ++nesting_depth;
6077 : else if (token->type == CPP_CLOSE_BRACE
6078 : || token->type == CPP_CLOSE_PAREN
6079 : || token->type == CPP_CLOSE_SQUARE)
6080 : {
6081 6 : if (nesting_depth-- == 0)
6082 : break;
6083 : }
6084 : /* Consume this token. */
6085 20 : c_parser_consume_token (parser);
6086 : }
6087 7 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
6088 : break;
6089 0 : c_parser_consume_token (parser);
6090 0 : continue;
6091 0 : }
6092 307 : c_parser_consume_token (parser);
6093 307 : matching_parens parens;
6094 307 : if (parens.require_open (parser))
6095 : {
6096 305 : if (directive)
6097 301 : c_parser_omp_directive_args (parser, attribute, false);
6098 : else
6099 4 : c_parser_omp_sequence_args (parser, attribute);
6100 305 : parens.skip_until_found_close (parser);
6101 305 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
6102 : break;
6103 157 : c_parser_consume_token (parser);
6104 : }
6105 2 : else if (c_parser_next_token_is_not (parser, CPP_COMMA))
6106 : break;
6107 : else
6108 0 : c_parser_consume_token (parser);
6109 : }
6110 : while (1);
6111 157 : }
6112 :
6113 : /* Parse standard (C23) attributes (including GNU attributes in the
6114 : gnu:: namespace).
6115 :
6116 : attribute-specifier-sequence:
6117 : attribute-specifier-sequence[opt] attribute-specifier
6118 :
6119 : attribute-specifier:
6120 : [ [ attribute-list ] ]
6121 :
6122 : attribute-list:
6123 : attribute[opt]
6124 : attribute-list, attribute[opt]
6125 :
6126 : attribute:
6127 : attribute-token attribute-argument-clause[opt]
6128 :
6129 : attribute-token:
6130 : standard-attribute
6131 : attribute-prefixed-token
6132 :
6133 : standard-attribute:
6134 : identifier
6135 :
6136 : attribute-prefixed-token:
6137 : attribute-prefix :: identifier
6138 :
6139 : attribute-prefix:
6140 : identifier
6141 :
6142 : attribute-argument-clause:
6143 : ( balanced-token-sequence[opt] )
6144 :
6145 : Keywords are accepted as identifiers for this purpose.
6146 :
6147 : As an extension, we permit an attribute-specifier to be:
6148 :
6149 : [ [ __extension__ attribute-list ] ]
6150 :
6151 : Two colons are then accepted as a synonym for ::. No attempt is made
6152 : to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
6153 : indicates whether this relaxation is in effect. */
6154 :
6155 : static tree
6156 2007 : c_parser_std_attribute (c_parser *parser, bool for_tm)
6157 : {
6158 2007 : c_token *token = c_parser_peek_token (parser);
6159 2007 : tree ns, name, attribute;
6160 :
6161 : /* Parse the attribute-token. */
6162 2007 : if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6163 : {
6164 2 : c_parser_error (parser, "expected identifier");
6165 2 : return error_mark_node;
6166 : }
6167 2005 : name = canonicalize_attr_name (token->value);
6168 2005 : c_parser_consume_token (parser);
6169 2005 : if (c_parser_next_token_is (parser, CPP_SCOPE)
6170 2467 : || (c_parser_next_token_is (parser, CPP_COLON)
6171 36 : && (c_parser_peek_token (parser)->flags & COLON_SCOPE) != 0
6172 10 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
6173 : {
6174 1553 : ns = name;
6175 1553 : if (c_parser_next_token_is (parser, CPP_COLON))
6176 10 : c_parser_consume_token (parser);
6177 1553 : c_parser_consume_token (parser);
6178 1553 : token = c_parser_peek_token (parser);
6179 1553 : if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6180 : {
6181 0 : c_parser_error (parser, "expected identifier");
6182 0 : return error_mark_node;
6183 : }
6184 1553 : name = canonicalize_attr_name (token->value);
6185 1553 : c_parser_consume_token (parser);
6186 : }
6187 : else
6188 : ns = NULL_TREE;
6189 2005 : attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
6190 :
6191 : /* Parse the arguments, if any. */
6192 2005 : const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
6193 2005 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
6194 : {
6195 1056 : if ((flag_openmp || flag_openmp_simd)
6196 9 : && ns
6197 7 : && is_attribute_p ("omp", ns)
6198 1068 : && (is_attribute_p ("directive", name)
6199 2 : || is_attribute_p ("sequence", name)
6200 1 : || is_attribute_p ("decl", name)))
6201 : {
6202 3 : error ("%<omp::%E%> attribute requires argument", name);
6203 3 : return error_mark_node;
6204 : }
6205 1062 : goto out;
6206 : }
6207 940 : {
6208 940 : location_t open_loc = c_parser_peek_token (parser)->location;
6209 940 : matching_parens parens;
6210 940 : parens.consume_open (parser);
6211 132 : if ((as && as->max_length == 0)
6212 : /* Special-case the transactional-memory attribute "outer",
6213 : which is specially handled but not registered as an
6214 : attribute, to avoid allowing arbitrary balanced token
6215 : sequences as arguments. */
6216 1049 : || is_attribute_p ("outer", name))
6217 : {
6218 24 : error_at (open_loc, "%qE attribute does not take any arguments", name);
6219 24 : parens.skip_until_found_close (parser);
6220 790 : return error_mark_node;
6221 : }
6222 : /* If this is a fake attribute created to handle -Wno-attributes,
6223 : we must skip parsing the arguments. */
6224 916 : if (as && !attribute_ignored_p (as))
6225 : {
6226 96 : bool takes_identifier
6227 : = (ns != NULL_TREE
6228 75 : && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
6229 171 : && attribute_takes_identifier_p (name));
6230 21 : bool require_string
6231 : = (ns == NULL_TREE
6232 21 : && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0
6233 11 : || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0));
6234 75 : bool assume_attr
6235 : = (ns != NULL_TREE
6236 75 : && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
6237 75 : && strcmp (IDENTIFIER_POINTER (name), "assume") == 0);
6238 192 : TREE_VALUE (attribute)
6239 96 : = c_parser_attribute_arguments (parser, takes_identifier,
6240 : require_string, assume_attr, false);
6241 : }
6242 : else
6243 : {
6244 54 : if ((flag_openmp || flag_openmp_simd)
6245 766 : && ns
6246 1586 : && is_attribute_p ("omp", ns))
6247 : {
6248 766 : if (is_attribute_p ("directive", name))
6249 : {
6250 554 : c_parser_omp_directive_args (parser, attribute, false);
6251 554 : parens.skip_until_found_close (parser);
6252 554 : return attribute;
6253 : }
6254 212 : else if (is_attribute_p ("decl", name))
6255 : {
6256 59 : TREE_VALUE (TREE_PURPOSE (attribute))
6257 59 : = get_identifier ("directive");
6258 59 : c_parser_omp_directive_args (parser, attribute, true);
6259 59 : parens.skip_until_found_close (parser);
6260 59 : return attribute;
6261 : }
6262 153 : else if (is_attribute_p ("sequence", name))
6263 : {
6264 153 : TREE_VALUE (TREE_PURPOSE (attribute))
6265 153 : = get_identifier ("directive");
6266 153 : c_parser_omp_sequence_args (parser, attribute);
6267 153 : parens.skip_until_found_close (parser);
6268 153 : TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
6269 153 : return attribute;
6270 : }
6271 : }
6272 54 : c_parser_balanced_token_sequence (parser);
6273 : }
6274 150 : parens.require_close (parser);
6275 : }
6276 1212 : out:
6277 1212 : if (ns == NULL_TREE && !for_tm && !as)
6278 : {
6279 : /* An attribute with standard syntax and no namespace specified
6280 : is a constraint violation if it is not one of the known
6281 : standard attributes. Diagnose it here with a pedwarn and
6282 : then discard it to prevent a duplicate warning later. */
6283 72 : pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
6284 : name);
6285 72 : return error_mark_node;
6286 : }
6287 : return attribute;
6288 : }
6289 :
6290 : static tree
6291 2117 : c_parser_std_attribute_list (c_parser *parser, bool for_tm)
6292 : {
6293 2117 : tree attributes = NULL_TREE;
6294 2351 : while (true)
6295 : {
6296 2351 : c_token *token = c_parser_peek_token (parser);
6297 2351 : if (token->type == CPP_CLOSE_SQUARE)
6298 : break;
6299 2135 : if (token->type == CPP_COMMA)
6300 : {
6301 128 : c_parser_consume_token (parser);
6302 128 : continue;
6303 : }
6304 2007 : tree attribute = c_parser_std_attribute (parser, for_tm);
6305 2007 : if (attribute != error_mark_node)
6306 : {
6307 1906 : TREE_CHAIN (attribute) = attributes;
6308 1906 : attributes = attribute;
6309 : }
6310 2007 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
6311 : break;
6312 : }
6313 2117 : return attributes;
6314 : }
6315 :
6316 : static tree
6317 2117 : c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
6318 : {
6319 2117 : location_t loc = c_parser_peek_token (parser)->location;
6320 2117 : if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
6321 : return NULL_TREE;
6322 2117 : if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
6323 : {
6324 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6325 0 : return NULL_TREE;
6326 : }
6327 2117 : tree attributes;
6328 2117 : if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
6329 : {
6330 42 : auto ext = disable_extension_diagnostics ();
6331 42 : c_parser_consume_token (parser);
6332 42 : attributes = c_parser_std_attribute_list (parser, for_tm);
6333 42 : restore_extension_diagnostics (ext);
6334 : }
6335 : else
6336 : {
6337 2075 : if (!for_tm)
6338 2055 : pedwarn_c11 (loc, OPT_Wpedantic,
6339 : "ISO C does not support %<[[]]%> attributes before C23");
6340 2075 : attributes = c_parser_std_attribute_list (parser, for_tm);
6341 : }
6342 2117 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6343 2117 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6344 2117 : return nreverse (attributes);
6345 : }
6346 :
6347 : /* Look past an optional balanced token sequence of raw look-ahead
6348 : tokens starting with the *Nth token. *N is updated to point to the
6349 : following token. Return true if such a sequence was found, false
6350 : if the tokens parsed were not balanced. */
6351 :
6352 : static bool
6353 13319 : c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
6354 : {
6355 59022 : while (true)
6356 : {
6357 59022 : c_token *token = c_parser_peek_nth_token_raw (parser, *n);
6358 59022 : switch (token->type)
6359 : {
6360 66 : case CPP_OPEN_BRACE:
6361 66 : {
6362 66 : ++*n;
6363 66 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6364 : {
6365 66 : token = c_parser_peek_nth_token_raw (parser, *n);
6366 66 : if (token->type == CPP_CLOSE_BRACE)
6367 66 : ++*n;
6368 : else
6369 : return false;
6370 : }
6371 : else
6372 : return false;
6373 66 : break;
6374 : }
6375 :
6376 10693 : case CPP_OPEN_PAREN:
6377 10693 : {
6378 10693 : ++*n;
6379 10693 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6380 : {
6381 10693 : token = c_parser_peek_nth_token_raw (parser, *n);
6382 10693 : if (token->type == CPP_CLOSE_PAREN)
6383 10693 : ++*n;
6384 : else
6385 : return false;
6386 : }
6387 : else
6388 : return false;
6389 10693 : break;
6390 : }
6391 :
6392 79 : case CPP_OPEN_SQUARE:
6393 79 : {
6394 79 : ++*n;
6395 79 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6396 : {
6397 79 : token = c_parser_peek_nth_token_raw (parser, *n);
6398 79 : if (token->type == CPP_CLOSE_SQUARE)
6399 79 : ++*n;
6400 : else
6401 : return false;
6402 : }
6403 : else
6404 : return false;
6405 79 : break;
6406 : }
6407 :
6408 : case CPP_CLOSE_BRACE:
6409 : case CPP_CLOSE_PAREN:
6410 : case CPP_CLOSE_SQUARE:
6411 : case CPP_EOF:
6412 : return true;
6413 :
6414 34865 : default:
6415 34865 : ++*n;
6416 34865 : break;
6417 : }
6418 : }
6419 : }
6420 :
6421 : /* Return whether standard attributes start with the Nth token. */
6422 :
6423 : static bool
6424 891447559 : c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
6425 : {
6426 891447559 : if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
6427 2322717 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
6428 891444836 : return false;
6429 : /* In C, '[[' must start attributes. In Objective-C, we need to
6430 : check whether '[[' is matched by ']]'. */
6431 2723 : if (!c_dialect_objc ())
6432 : return true;
6433 0 : n += 2;
6434 0 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
6435 : return false;
6436 0 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
6437 0 : if (token->type != CPP_CLOSE_SQUARE)
6438 : return false;
6439 0 : token = c_parser_peek_nth_token_raw (parser, n + 1);
6440 0 : return token->type == CPP_CLOSE_SQUARE;
6441 : }
6442 :
6443 : /* Skip standard attribute tokens starting at Nth token (with 1 as the
6444 : next token), return index of the first token after the standard
6445 : attribute tokens, or N on failure. */
6446 :
6447 : static size_t
6448 329 : c_parser_skip_std_attribute_spec_seq (c_parser *parser, size_t n)
6449 : {
6450 329 : size_t orig_n = n;
6451 361 : while (true)
6452 : {
6453 345 : if (c_parser_peek_nth_token_raw (parser, n)->type == CPP_OPEN_SQUARE
6454 345 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
6455 : == CPP_OPEN_SQUARE))
6456 : {
6457 16 : unsigned int m = n + 2;
6458 16 : if (!c_parser_check_balanced_raw_token_sequence (parser, &m))
6459 0 : return orig_n;
6460 16 : c_token *token = c_parser_peek_nth_token_raw (parser, m);
6461 16 : if (token->type != CPP_CLOSE_SQUARE)
6462 : return orig_n;
6463 16 : token = c_parser_peek_nth_token_raw (parser, m + 1);
6464 16 : if (token->type != CPP_CLOSE_SQUARE)
6465 : return orig_n;
6466 16 : n = m + 2;
6467 : }
6468 : else
6469 : break;
6470 16 : }
6471 : return n;
6472 : }
6473 :
6474 : static tree
6475 2036 : c_parser_std_attribute_specifier_sequence (c_parser *parser)
6476 : {
6477 2036 : tree attributes = NULL_TREE;
6478 2097 : do
6479 : {
6480 2097 : tree attrs = c_parser_std_attribute_specifier (parser, false);
6481 2097 : attributes = chainon (attributes, attrs);
6482 : }
6483 2097 : while (c_parser_nth_token_starts_std_attributes (parser, 1));
6484 2036 : return attributes;
6485 : }
6486 :
6487 : /* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6488 : says whether alignment specifiers are OK (only in cases that might
6489 : be the type name of a compound literal).
6490 :
6491 : type-name:
6492 : specifier-qualifier-list abstract-declarator[opt]
6493 : */
6494 :
6495 : struct c_type_name *
6496 121326681 : c_parser_type_name (c_parser *parser, bool alignas_ok)
6497 : {
6498 121326681 : struct c_declspecs *specs = build_null_declspecs ();
6499 121326681 : struct c_declarator *declarator;
6500 121326681 : struct c_type_name *ret;
6501 121326681 : bool dummy = false;
6502 121326681 : c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false,
6503 : false, true, cla_prefer_type);
6504 121326681 : if (!specs->declspecs_seen_p)
6505 : {
6506 4 : c_parser_error (parser, "expected specifier-qualifier-list");
6507 4 : return NULL;
6508 : }
6509 121326677 : if (specs->type != error_mark_node)
6510 : {
6511 121326660 : pending_xref_error ();
6512 121326660 : finish_declspecs (specs);
6513 : /* When the typename is declared, its type is a top level type, we should
6514 : call verify_counted_by_for_top_anonymous_type. */
6515 121326660 : if (specs->typespec_kind == ctsk_tagdef)
6516 1664 : verify_counted_by_for_top_anonymous_type (specs->type);
6517 : }
6518 242653354 : declarator = c_parser_declarator (parser,
6519 121326677 : specs->typespec_kind != ctsk_none,
6520 : C_DTR_ABSTRACT, &dummy);
6521 121326677 : if (declarator == NULL)
6522 : return NULL;
6523 121326672 : ret = XOBNEW (&parser_obstack, struct c_type_name);
6524 121326672 : ret->specs = specs;
6525 121326672 : ret->declarator = declarator;
6526 121326672 : return ret;
6527 : }
6528 :
6529 : /* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6530 :
6531 : initializer:
6532 : assignment-expression
6533 : { initializer-list }
6534 : { initializer-list , }
6535 :
6536 : initializer-list:
6537 : designation[opt] initializer
6538 : initializer-list , designation[opt] initializer
6539 :
6540 : designation:
6541 : designator-list =
6542 :
6543 : designator-list:
6544 : designator
6545 : designator-list designator
6546 :
6547 : designator:
6548 : array-designator
6549 : . identifier
6550 :
6551 : array-designator:
6552 : [ constant-expression ]
6553 :
6554 : GNU extensions:
6555 :
6556 : initializer:
6557 : { }
6558 :
6559 : designation:
6560 : array-designator
6561 : identifier :
6562 :
6563 : array-designator:
6564 : [ constant-expression ... constant-expression ]
6565 :
6566 : Any expression without commas is accepted in the syntax for the
6567 : constant-expressions, with non-constant expressions rejected later.
6568 :
6569 : DECL is the declaration we're parsing this initializer for.
6570 :
6571 : This function is only used for top-level initializers; for nested
6572 : ones, see c_parser_initval. */
6573 :
6574 : static struct c_expr
6575 6335315 : c_parser_initializer (c_parser *parser, tree decl)
6576 : {
6577 6335315 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
6578 105376 : return c_parser_braced_init (parser, NULL_TREE, false, NULL,
6579 105376 : decl != error_mark_node
6580 210752 : && C_DECL_VARIABLE_SIZE (decl));
6581 : else
6582 : {
6583 6229939 : struct c_expr ret;
6584 6229939 : location_t loc = c_parser_peek_token (parser)->location;
6585 6229939 : ret = c_parser_expr_no_commas (parser, NULL);
6586 6229937 : if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6587 : {
6588 2 : error_at (loc,
6589 : "variable-sized object may not be initialized except "
6590 : "with an empty initializer");
6591 2 : ret.set_error ();
6592 : }
6593 : /* This is handled mostly by gimplify.cc, but we have to deal with
6594 : not warning about int x = x; as it is a GCC extension to turn off
6595 : this warning but only if warn_init_self is zero. */
6596 6229937 : if (VAR_P (decl)
6597 6229889 : && !DECL_EXTERNAL (decl)
6598 6229889 : && !TREE_STATIC (decl)
6599 6110716 : && ret.value == decl
6600 6319119 : && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), OPT_Winit_self))
6601 89175 : suppress_warning (decl, OPT_Winit_self);
6602 6229937 : if (TREE_CODE (ret.value) != STRING_CST
6603 6229937 : && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6604 95398 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6605 : (ret.value))))
6606 6120553 : ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6607 6229937 : return ret;
6608 : }
6609 : }
6610 :
6611 : /* The location of the last comma within the current initializer list,
6612 : or UNKNOWN_LOCATION if not within one. */
6613 :
6614 : location_t last_init_list_comma;
6615 :
6616 : /* Parse a braced initializer list. TYPE is the type specified for a
6617 : compound literal, and NULL_TREE for other initializers and for
6618 : nested braced lists. NESTED_P is true for nested braced lists,
6619 : false for the list of a compound literal or the list that is the
6620 : top-level initializer in a declaration. VARSIZE_P indicates
6621 : wether the object to be initialized has a variable size. */
6622 :
6623 : static struct c_expr
6624 1362714 : c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6625 : struct obstack *outer_obstack, bool varsize_p)
6626 : {
6627 1362714 : struct c_expr ret;
6628 1362714 : struct obstack braced_init_obstack;
6629 1362714 : location_t brace_loc = c_parser_peek_token (parser)->location;
6630 1362714 : gcc_obstack_init (&braced_init_obstack);
6631 1362714 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6632 1362714 : bool save_c_omp_array_section_p = c_omp_array_section_p;
6633 1362714 : c_omp_array_section_p = false;
6634 1362714 : bool zero_init_padding_bits = false;
6635 1362714 : matching_braces braces;
6636 1362714 : braces.consume_open (parser);
6637 1362714 : if (nested_p)
6638 : {
6639 339617 : finish_implicit_inits (brace_loc, outer_obstack);
6640 339617 : push_init_level (brace_loc, 0, &braced_init_obstack);
6641 : }
6642 : else
6643 1023097 : really_start_incremental_init (type);
6644 1362714 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6645 : {
6646 2615 : pedwarn_c11 (brace_loc, OPT_Wpedantic,
6647 : "ISO C forbids empty initializer braces before C23");
6648 2615 : if (flag_isoc23)
6649 1362714 : zero_init_padding_bits = true;
6650 : }
6651 : else
6652 : {
6653 1360099 : if (varsize_p)
6654 61 : error_at (brace_loc,
6655 : "variable-sized object may not be initialized except "
6656 : "with an empty initializer");
6657 : /* Parse a non-empty initializer list, possibly with a trailing
6658 : comma. */
6659 8891123 : while (true)
6660 : {
6661 8891123 : c_parser_initelt (parser, &braced_init_obstack);
6662 8891123 : if (parser->error)
6663 : break;
6664 8891093 : if (c_parser_next_token_is (parser, CPP_COMMA))
6665 : {
6666 7533730 : last_init_list_comma = c_parser_peek_token (parser)->location;
6667 7533730 : c_parser_consume_token (parser);
6668 : /* CPP_EMBED should be always in between two CPP_COMMA
6669 : tokens. */
6670 15067563 : while (c_parser_next_token_is (parser, CPP_EMBED))
6671 : {
6672 103 : c_token *embed = c_parser_peek_token (parser);
6673 103 : c_parser_consume_token (parser);
6674 103 : c_expr embed_val;
6675 103 : embed_val.value = embed->value;
6676 103 : embed_val.original_code = RAW_DATA_CST;
6677 103 : embed_val.original_type = integer_type_node;
6678 103 : set_c_expr_source_range (&embed_val, embed->get_range ());
6679 103 : embed_val.m_decimal = 0;
6680 103 : process_init_element (embed->location, embed_val, false,
6681 : &braced_init_obstack);
6682 103 : gcc_checking_assert (c_parser_next_token_is (parser,
6683 : CPP_COMMA));
6684 103 : last_init_list_comma = c_parser_peek_token (parser)->location;
6685 103 : c_parser_consume_token (parser);
6686 : }
6687 : }
6688 : else
6689 : break;
6690 7533730 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6691 : break;
6692 : }
6693 : }
6694 1362714 : c_omp_array_section_p = save_c_omp_array_section_p;
6695 1362714 : c_token *next_tok = c_parser_peek_token (parser);
6696 1362714 : if (next_tok->type != CPP_CLOSE_BRACE)
6697 : {
6698 31 : ret.set_error ();
6699 31 : ret.original_code = ERROR_MARK;
6700 31 : ret.original_type = NULL;
6701 31 : braces.skip_until_found_close (parser);
6702 31 : pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6703 31 : obstack_free (&braced_init_obstack, NULL);
6704 : return ret;
6705 : }
6706 1362683 : location_t close_loc = next_tok->location;
6707 1362683 : c_parser_consume_token (parser);
6708 1362683 : ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6709 1362683 : if (zero_init_padding_bits
6710 2358 : && ret.value
6711 2291 : && TREE_CODE (ret.value) == CONSTRUCTOR)
6712 2196 : CONSTRUCTOR_ZERO_PADDING_BITS (ret.value) = 1;
6713 1362683 : obstack_free (&braced_init_obstack, NULL);
6714 1362683 : set_c_expr_source_range (&ret, brace_loc, close_loc);
6715 1362683 : return ret;
6716 : }
6717 :
6718 : /* Parse a nested initializer, including designators. */
6719 :
6720 : static void
6721 8891123 : c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6722 : {
6723 : /* Parse any designator or designator list. A single array
6724 : designator may have the subsequent "=" omitted in GNU C, but a
6725 : longer list or a structure member designator may not. */
6726 8891123 : if (c_parser_next_token_is (parser, CPP_NAME)
6727 8891123 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6728 : {
6729 : /* Old-style structure member designator. */
6730 156 : set_init_label (c_parser_peek_token (parser)->location,
6731 156 : c_parser_peek_token (parser)->value,
6732 156 : c_parser_peek_token (parser)->location,
6733 : braced_init_obstack);
6734 : /* Use the colon as the error location. */
6735 156 : pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6736 : "obsolete use of designated initializer with %<:%>");
6737 156 : c_parser_consume_token (parser);
6738 156 : c_parser_consume_token (parser);
6739 : }
6740 : else
6741 : {
6742 : /* des_seen is 0 if there have been no designators, 1 if there
6743 : has been a single array designator and 2 otherwise. */
6744 : int des_seen = 0;
6745 : /* Location of a designator. */
6746 : location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6747 8924763 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
6748 17848377 : || c_parser_next_token_is (parser, CPP_DOT))
6749 : {
6750 33796 : int des_prev = des_seen;
6751 33796 : if (!des_seen)
6752 33218 : des_loc = c_parser_peek_token (parser)->location;
6753 33796 : if (des_seen < 2)
6754 33296 : des_seen++;
6755 33796 : if (c_parser_next_token_is (parser, CPP_DOT))
6756 : {
6757 32647 : des_seen = 2;
6758 32647 : c_parser_consume_token (parser);
6759 32647 : if (c_parser_next_token_is (parser, CPP_NAME))
6760 : {
6761 32647 : set_init_label (des_loc, c_parser_peek_token (parser)->value,
6762 32647 : c_parser_peek_token (parser)->location,
6763 : braced_init_obstack);
6764 32647 : c_parser_consume_token (parser);
6765 : }
6766 : else
6767 : {
6768 0 : struct c_expr init;
6769 0 : init.set_error ();
6770 0 : init.original_code = ERROR_MARK;
6771 0 : init.original_type = NULL;
6772 0 : c_parser_error (parser, "expected identifier");
6773 0 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
6774 0 : process_init_element (input_location, init, false,
6775 : braced_init_obstack);
6776 0 : return;
6777 : }
6778 : }
6779 : else
6780 : {
6781 1149 : struct c_expr first_expr;
6782 1149 : tree first, second;
6783 1149 : location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6784 1149 : location_t array_index_loc = UNKNOWN_LOCATION;
6785 : /* ??? Following the old parser, [ objc-receiver
6786 : objc-message-args ] is accepted as an initializer,
6787 : being distinguished from a designator by what follows
6788 : the first assignment expression inside the square
6789 : brackets, but after a first array designator a
6790 : subsequent square bracket is for Objective-C taken to
6791 : start an expression, using the obsolete form of
6792 : designated initializer without '=', rather than
6793 : possibly being a second level of designation: in LALR
6794 : terms, the '[' is shifted rather than reducing
6795 : designator to designator-list. */
6796 1149 : if (des_prev == 1 && c_dialect_objc ())
6797 : {
6798 0 : des_seen = des_prev;
6799 0 : break;
6800 : }
6801 1149 : if (des_prev == 0 && c_dialect_objc ())
6802 : {
6803 : /* This might be an array designator or an
6804 : Objective-C message expression. If the former,
6805 : continue parsing here; if the latter, parse the
6806 : remainder of the initializer given the starting
6807 : primary-expression. ??? It might make sense to
6808 : distinguish when des_prev == 1 as well; see
6809 : previous comment. */
6810 0 : tree rec, args;
6811 0 : struct c_expr mexpr;
6812 0 : c_parser_consume_token (parser);
6813 0 : if (c_parser_peek_token (parser)->type == CPP_NAME
6814 0 : && ((c_parser_peek_token (parser)->id_kind
6815 : == C_ID_TYPENAME)
6816 0 : || (c_parser_peek_token (parser)->id_kind
6817 : == C_ID_CLASSNAME)))
6818 : {
6819 : /* Type name receiver. */
6820 0 : tree id = c_parser_peek_token (parser)->value;
6821 0 : c_parser_consume_token (parser);
6822 0 : rec = objc_get_class_reference (id);
6823 0 : goto parse_message_args;
6824 : }
6825 0 : array_index_loc = c_parser_peek_token (parser)->location;
6826 0 : first_expr = c_parser_expr_no_commas (parser, NULL);
6827 0 : mark_exp_read (first_expr.value);
6828 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
6829 0 : || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
6830 0 : goto array_desig_after_first;
6831 0 : first = first_expr.value;
6832 : /* Expression receiver. So far only one part
6833 : without commas has been parsed; there might be
6834 : more of the expression. */
6835 : rec = first;
6836 0 : while (c_parser_next_token_is (parser, CPP_COMMA))
6837 : {
6838 0 : struct c_expr next;
6839 0 : location_t comma_loc, exp_loc;
6840 0 : comma_loc = c_parser_peek_token (parser)->location;
6841 0 : c_parser_consume_token (parser);
6842 0 : exp_loc = c_parser_peek_token (parser)->location;
6843 0 : next = c_parser_expr_no_commas (parser, NULL);
6844 0 : next = convert_lvalue_to_rvalue (exp_loc, next,
6845 : true, true);
6846 0 : rec = build_compound_expr (comma_loc, rec, next.value);
6847 : }
6848 0 : parse_message_args:
6849 : /* Now parse the objc-message-args. */
6850 0 : args = c_parser_objc_message_args (parser);
6851 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
6852 : "expected %<]%>");
6853 0 : mexpr.value
6854 0 : = objc_build_message_expr (rec, args);
6855 0 : mexpr.original_code = ERROR_MARK;
6856 0 : mexpr.original_type = NULL;
6857 0 : mexpr.m_decimal = 0;
6858 : /* Now parse and process the remainder of the
6859 : initializer, starting with this message
6860 : expression as a primary-expression. */
6861 0 : c_parser_initval (parser, &mexpr, braced_init_obstack);
6862 0 : return;
6863 : }
6864 1149 : c_parser_consume_token (parser);
6865 1149 : array_index_loc = c_parser_peek_token (parser)->location;
6866 1149 : first_expr = c_parser_expr_no_commas (parser, NULL);
6867 1149 : mark_exp_read (first_expr.value);
6868 1149 : array_desig_after_first:
6869 1149 : first_expr = convert_lvalue_to_rvalue (array_index_loc,
6870 : first_expr,
6871 : true, true);
6872 1149 : first = first_expr.value;
6873 1149 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
6874 : {
6875 397 : ellipsis_loc = c_parser_peek_token (parser)->location;
6876 397 : c_parser_consume_token (parser);
6877 397 : second = convert_lvalue_to_rvalue (ellipsis_loc,
6878 : (c_parser_expr_no_commas
6879 : (parser, NULL)),
6880 : true, true).value;
6881 397 : mark_exp_read (second);
6882 : }
6883 : else
6884 : second = NULL_TREE;
6885 1149 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
6886 : {
6887 1149 : c_parser_consume_token (parser);
6888 1149 : set_init_index (array_index_loc, first, second,
6889 : braced_init_obstack);
6890 1149 : if (second)
6891 397 : pedwarn (ellipsis_loc, OPT_Wpedantic,
6892 : "ISO C forbids specifying range of elements to initialize");
6893 : }
6894 : else
6895 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
6896 : "expected %<]%>");
6897 : }
6898 : }
6899 8890967 : if (des_seen >= 1)
6900 : {
6901 33218 : if (c_parser_next_token_is (parser, CPP_EQ))
6902 : {
6903 33197 : pedwarn_c90 (des_loc, OPT_Wpedantic,
6904 : "ISO C90 forbids specifying subobject "
6905 : "to initialize");
6906 33197 : c_parser_consume_token (parser);
6907 : }
6908 : else
6909 : {
6910 21 : if (des_seen == 1)
6911 19 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6912 : "obsolete use of designated initializer without %<=%>");
6913 : else
6914 : {
6915 2 : struct c_expr init;
6916 2 : init.set_error ();
6917 2 : init.original_code = ERROR_MARK;
6918 2 : init.original_type = NULL;
6919 2 : c_parser_error (parser, "expected %<=%>");
6920 2 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
6921 2 : process_init_element (input_location, init, false,
6922 : braced_init_obstack);
6923 2 : return;
6924 : }
6925 : }
6926 : }
6927 : }
6928 8891121 : c_parser_initval (parser, NULL, braced_init_obstack);
6929 : }
6930 :
6931 : /* Parse a nested initializer; as c_parser_initializer but parses
6932 : initializers within braced lists, after any designators have been
6933 : applied. If AFTER is not NULL then it is an Objective-C message
6934 : expression which is the primary-expression starting the
6935 : initializer. */
6936 :
6937 : static void
6938 8891121 : c_parser_initval (c_parser *parser, struct c_expr *after,
6939 : struct obstack * braced_init_obstack)
6940 : {
6941 8891121 : struct c_expr init;
6942 8891121 : gcc_assert (!after || c_dialect_objc ());
6943 8891121 : location_t loc = c_parser_peek_token (parser)->location;
6944 :
6945 8891121 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
6946 339617 : init = c_parser_braced_init (parser, NULL_TREE, true,
6947 : braced_init_obstack, false);
6948 : else
6949 : {
6950 8551504 : init = c_parser_expr_no_commas (parser, after);
6951 8551504 : if (init.value != NULL_TREE
6952 8551504 : && TREE_CODE (init.value) != STRING_CST
6953 17061487 : && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6954 177 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6955 : (init.value))))
6956 8509811 : init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6957 : }
6958 8891121 : tree val = init.value;
6959 8891121 : process_init_element (loc, init, false, braced_init_obstack);
6960 :
6961 : /* Attempt to optimize large char array initializers into RAW_DATA_CST
6962 : to save compile time and memory even when not using #embed. */
6963 8891121 : static unsigned vals_to_ignore;
6964 8891121 : if (vals_to_ignore)
6965 : /* If earlier call determined there is certain number of CPP_COMMA
6966 : CPP_NUMBER tokens with 0-255 int values, but not enough for
6967 : RAW_DATA_CST to be beneficial, don't try to check it again until
6968 : they are all parsed. */
6969 6022 : --vals_to_ignore;
6970 8885099 : else if (val
6971 8884973 : && TREE_CODE (val) == INTEGER_CST
6972 4191393 : && TREE_TYPE (val) == integer_type_node
6973 12527818 : && c_parser_next_token_is (parser, CPP_COMMA))
6974 2983582 : if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
6975 : {
6976 8525 : char buf1[64];
6977 8525 : unsigned int i;
6978 8525 : gcc_checking_assert (len >= 64);
6979 : location_t last_loc = UNKNOWN_LOCATION;
6980 20115 : for (i = 0; i < 64; ++i)
6981 : {
6982 20022 : c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
6983 20022 : if (tok->type != CPP_COMMA)
6984 : break;
6985 19225 : tok = c_parser_peek_nth_token_raw (parser, 2 + 2 * i);
6986 19225 : if (tok->type != CPP_NUMBER
6987 11590 : || TREE_CODE (tok->value) != INTEGER_CST
6988 11590 : || TREE_TYPE (tok->value) != integer_type_node
6989 11590 : || wi::neg_p (wi::to_wide (tok->value))
6990 30815 : || wi::to_widest (tok->value) > UCHAR_MAX)
6991 : break;
6992 11590 : buf1[i] = (char) tree_to_uhwi (tok->value);
6993 11590 : if (i == 0)
6994 1108 : loc = tok->location;
6995 11590 : last_loc = tok->location;
6996 : }
6997 8525 : if (i < 64)
6998 : {
6999 8432 : vals_to_ignore = i;
7000 8438 : return;
7001 : }
7002 93 : c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
7003 : /* If 64 CPP_COMMA CPP_NUMBER pairs are followed by CPP_CLOSE_BRACE,
7004 : punt if len is INT_MAX as that can mean this is a flexible array
7005 : member and in that case we need one CPP_NUMBER afterwards
7006 : (as guaranteed for CPP_EMBED). */
7007 93 : if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
7008 : len = i;
7009 91 : else if (tok->type != CPP_COMMA
7010 91 : || (c_parser_peek_nth_token_raw (parser, 2 + 2 * i)->type
7011 : != CPP_NUMBER))
7012 : {
7013 6 : vals_to_ignore = i;
7014 6 : return;
7015 : }
7016 : /* Ensure the STRING_CST fits into 128K. */
7017 87 : unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
7018 87 : unsigned int orig_len = len;
7019 87 : unsigned int off = 0, last = 0;
7020 87 : if (!wi::neg_p (wi::to_wide (val)) && wi::to_widest (val) <= UCHAR_MAX)
7021 79 : off = 1;
7022 87 : len = MIN (len, max_len - off);
7023 87 : char *buf2 = XNEWVEC (char, len + off);
7024 87 : if (off)
7025 79 : buf2[0] = (char) tree_to_uhwi (val);
7026 87 : memcpy (buf2 + off, buf1, i);
7027 5655 : for (unsigned int j = 0; j < i; ++j)
7028 : {
7029 5568 : c_parser_peek_token (parser);
7030 5568 : c_parser_consume_token (parser);
7031 5568 : c_parser_peek_token (parser);
7032 5568 : c_parser_consume_token (parser);
7033 : }
7034 18780 : for (; i < len; ++i)
7035 : {
7036 18743 : if (!c_parser_next_token_is (parser, CPP_COMMA))
7037 : break;
7038 18741 : tok = c_parser_peek_2nd_token (parser);
7039 18741 : if (tok->type != CPP_NUMBER
7040 18733 : || TREE_CODE (tok->value) != INTEGER_CST
7041 18733 : || TREE_TYPE (tok->value) != integer_type_node
7042 18733 : || wi::neg_p (wi::to_wide (tok->value))
7043 37474 : || wi::to_widest (tok->value) > UCHAR_MAX)
7044 : break;
7045 18733 : c_token *tok2 = c_parser_peek_nth_token (parser, 3);
7046 18733 : if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
7047 : break;
7048 18730 : buf2[i + off] = (char) tree_to_uhwi (tok->value);
7049 : /* If orig_len is INT_MAX, this can be flexible array member and
7050 : in that case we need to ensure another element which
7051 : for CPP_EMBED is normally guaranteed after it. Include
7052 : that byte in the RAW_DATA_OWNER though, so it can be optimized
7053 : later. */
7054 18730 : if (orig_len == INT_MAX
7055 18730 : && (tok2->type == CPP_CLOSE_BRACE
7056 12517 : || (c_parser_peek_nth_token (parser, 4)->type
7057 : != CPP_NUMBER)))
7058 : {
7059 : last = 1;
7060 : break;
7061 : }
7062 18693 : last_loc = tok->location;
7063 18693 : c_parser_consume_token (parser);
7064 18693 : c_parser_consume_token (parser);
7065 : }
7066 87 : val = make_node (RAW_DATA_CST);
7067 87 : TREE_TYPE (val) = integer_type_node;
7068 87 : RAW_DATA_LENGTH (val) = i;
7069 87 : tree owner = build_string (i + off + last, buf2);
7070 87 : XDELETEVEC (buf2);
7071 87 : TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
7072 87 : i + off + last);
7073 87 : RAW_DATA_OWNER (val) = owner;
7074 87 : RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
7075 87 : init.value = val;
7076 87 : set_c_expr_source_range (&init, loc, last_loc);
7077 87 : init.original_code = RAW_DATA_CST;
7078 87 : init.original_type = integer_type_node;
7079 87 : init.m_decimal = 0;
7080 87 : process_init_element (loc, init, false, braced_init_obstack);
7081 : }
7082 : }
7083 :
7084 : /* Parse a compound statement (possibly a function body) (C90 6.6.2,
7085 : C99 6.8.2, C11 6.8.2, C23 6.8.2).
7086 :
7087 : compound-statement:
7088 : { block-item-list[opt] }
7089 : { label-declarations block-item-list }
7090 :
7091 : block-item-list:
7092 : block-item
7093 : block-item-list block-item
7094 :
7095 : block-item:
7096 : label
7097 : nested-declaration
7098 : statement
7099 :
7100 : nested-declaration:
7101 : declaration
7102 :
7103 : GNU extensions:
7104 :
7105 : compound-statement:
7106 : { label-declarations block-item-list }
7107 :
7108 : nested-declaration:
7109 : __extension__ nested-declaration
7110 : nested-function-definition
7111 :
7112 : label-declarations:
7113 : label-declaration
7114 : label-declarations label-declaration
7115 :
7116 : label-declaration:
7117 : __label__ identifier-list ;
7118 :
7119 : Allowing the mixing of declarations and code is new in C99. The
7120 : GNU syntax also permits (not shown above) labels at the end of
7121 : compound statements, which yield an error. We don't allow labels
7122 : on declarations; this might seem like a natural extension, but
7123 : there would be a conflict between gnu-attributes on the label and
7124 : prefix gnu-attributes on the declaration. ??? The syntax follows the
7125 : old parser in requiring something after label declarations.
7126 : Although they are erroneous if the labels declared aren't defined,
7127 : is it useful for the syntax to be this way?
7128 :
7129 : OpenACC:
7130 :
7131 : block-item:
7132 : openacc-directive
7133 :
7134 : openacc-directive:
7135 : update-directive
7136 :
7137 : OpenMP:
7138 :
7139 : block-item:
7140 : openmp-directive
7141 :
7142 : openmp-directive:
7143 : barrier-directive
7144 : flush-directive
7145 : taskwait-directive
7146 : taskyield-directive
7147 : cancel-directive
7148 : cancellation-point-directive */
7149 :
7150 : static tree
7151 37155583 : c_parser_compound_statement (c_parser *parser, location_t *endlocp)
7152 : {
7153 37155583 : tree stmt;
7154 37155583 : location_t brace_loc;
7155 37155583 : brace_loc = c_parser_peek_token (parser)->location;
7156 37155583 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
7157 : {
7158 : /* Ensure a scope is entered and left anyway to avoid confusion
7159 : if we have just prepared to enter a function body. */
7160 16 : stmt = c_begin_compound_stmt (true);
7161 16 : c_end_compound_stmt (brace_loc, stmt, true);
7162 16 : return error_mark_node;
7163 : }
7164 37155567 : stmt = c_begin_compound_stmt (true);
7165 37155567 : location_t end_loc = c_parser_compound_statement_nostart (parser);
7166 37155566 : if (endlocp)
7167 36249773 : *endlocp = end_loc;
7168 :
7169 37155566 : return c_end_compound_stmt (brace_loc, stmt, true);
7170 : }
7171 :
7172 : /* Diagnose errors related to imperfectly nested loops in an OMP
7173 : loop construct. This function is called when such code is seen.
7174 : Only issue one such diagnostic no matter how much invalid
7175 : intervening code there is in the loop.
7176 : FIXME: maybe the location associated with the diagnostic should
7177 : be the current parser token instead of the location of the outer loop
7178 : nest. */
7179 :
7180 : static void
7181 299 : check_omp_intervening_code (c_parser *parser)
7182 : {
7183 299 : struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
7184 299 : gcc_assert (omp_for_parse_state);
7185 :
7186 299 : if (!omp_for_parse_state->in_intervening_code)
7187 : return;
7188 278 : omp_for_parse_state->saw_intervening_code = true;
7189 :
7190 : /* Only diagnose errors related to perfect nesting once. */
7191 278 : if (!omp_for_parse_state->perfect_nesting_fail)
7192 : {
7193 :
7194 : /* OpenACC does not (yet) permit intervening code, in
7195 : addition to situations forbidden by the OpenMP spec. */
7196 256 : if (omp_for_parse_state->code == OACC_LOOP)
7197 : {
7198 3 : error_at (omp_for_parse_state->for_loc,
7199 : "inner loops must be perfectly nested in "
7200 : "%<#pragma acc loop%>");
7201 3 : omp_for_parse_state->perfect_nesting_fail = true;
7202 : }
7203 253 : else if (omp_for_parse_state->ordered)
7204 : {
7205 11 : error_at (omp_for_parse_state->for_loc,
7206 : "inner loops must be perfectly nested with "
7207 : "%<ordered%> clause");
7208 11 : omp_for_parse_state->perfect_nesting_fail = true;
7209 : }
7210 242 : else if (omp_for_parse_state->inscan)
7211 : {
7212 2 : error_at (omp_for_parse_state->for_loc,
7213 : "inner loops must be perfectly nested with "
7214 : "%<reduction%> %<inscan%> clause");
7215 2 : omp_for_parse_state->perfect_nesting_fail = true;
7216 : }
7217 240 : else if (omp_for_parse_state->code == OMP_TILE)
7218 : {
7219 9 : error_at (omp_for_parse_state->for_loc,
7220 : "inner loops must be perfectly nested in "
7221 : "%<pragma omp tile%>");
7222 9 : omp_for_parse_state->perfect_nesting_fail = true;
7223 : }
7224 256 : if (omp_for_parse_state->perfect_nesting_fail)
7225 25 : omp_for_parse_state->fail = true;
7226 : }
7227 : }
7228 :
7229 : /* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
7230 : and add the statement to the current list. If SL is an empty statement
7231 : list, do nothing. */
7232 : static void
7233 294 : add_structured_block_stmt (tree sl)
7234 : {
7235 294 : if (TREE_CODE (sl) != STATEMENT_LIST
7236 294 : || !tsi_end_p (tsi_start (sl)))
7237 152 : add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
7238 294 : }
7239 :
7240 : struct c_omp_attribute_data
7241 : {
7242 : vec<c_token, va_gc> *tokens;
7243 : const c_omp_directive *dir;
7244 : c_omp_directive_kind kind;
7245 : };
7246 :
7247 : /* Handle omp::directive and omp::sequence attributes in ATTRS
7248 : (if any) at the start of a statement or in attribute-declaration. */
7249 :
7250 : static bool
7251 876 : c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
7252 : bool *have_std_attrs)
7253 : {
7254 876 : if (!flag_openmp && !flag_openmp_simd)
7255 : return false;
7256 :
7257 610 : auto_vec<c_omp_attribute_data, 16> vd;
7258 610 : int cnt = 0;
7259 610 : int tokens = 0;
7260 610 : bool bad = false;
7261 1220 : for (tree *pa = &attrs; *pa; )
7262 610 : if (is_attribute_namespace_p ("omp", *pa)
7263 610 : && is_attribute_p ("directive", get_attribute_name (*pa)))
7264 : {
7265 609 : cnt++;
7266 1358 : for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
7267 : {
7268 749 : tree d = TREE_VALUE (a);
7269 749 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7270 749 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7271 749 : c_token *first = toks->address ();
7272 749 : c_token *last = first + toks->length ();
7273 749 : if (parser->omp_attrs_forbidden_p)
7274 : {
7275 14 : error_at (first->location,
7276 : "mixing OpenMP directives with attribute and pragma "
7277 : "syntax on the same statement");
7278 14 : parser->omp_attrs_forbidden_p = false;
7279 14 : bad = true;
7280 : }
7281 735 : else if (TREE_PUBLIC (d))
7282 : {
7283 3 : error_at (first->location,
7284 : "OpenMP %<omp::decl%> attribute on a statement");
7285 3 : bad = true;
7286 : }
7287 749 : const char *directive[3] = {};
7288 2208 : for (int i = 0; i < 3; i++)
7289 : {
7290 2026 : tree id = NULL_TREE;
7291 2026 : if (first + i == last)
7292 : break;
7293 1781 : if (first[i].type == CPP_NAME)
7294 1341 : id = first[i].value;
7295 440 : else if (first[i].type == CPP_KEYWORD)
7296 118 : id = ridpointers[(int) first[i].keyword];
7297 : else
7298 : break;
7299 1459 : directive[i] = IDENTIFIER_POINTER (id);
7300 : }
7301 749 : const c_omp_directive *dir = NULL;
7302 749 : if (directive[0])
7303 749 : dir = c_omp_categorize_directive (directive[0], directive[1],
7304 : directive[2]);
7305 749 : if (dir == NULL)
7306 : {
7307 1 : error_at (first->location,
7308 : "unknown OpenMP directive name in %qs attribute "
7309 : "argument",
7310 1 : TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7311 1 : continue;
7312 : }
7313 748 : c_omp_directive_kind kind = dir->kind;
7314 748 : if (dir->id == PRAGMA_OMP_ORDERED)
7315 : {
7316 : /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
7317 : depend/doacross clause. */
7318 8 : if (directive[1]
7319 4 : && (strcmp (directive[1], "depend") == 0
7320 2 : || strcmp (directive[1], "doacross") == 0))
7321 : kind = C_OMP_DIR_STANDALONE;
7322 6 : else if (first + 2 < last
7323 4 : && first[1].type == CPP_COMMA
7324 4 : && first[2].type == CPP_NAME
7325 10 : && (strcmp (IDENTIFIER_POINTER (first[2].value),
7326 : "depend") == 0
7327 2 : || strcmp (IDENTIFIER_POINTER (first[2].value),
7328 : "doacross") == 0))
7329 : kind = C_OMP_DIR_STANDALONE;
7330 : }
7331 740 : else if (dir->id == PRAGMA_OMP_ERROR)
7332 : {
7333 : /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
7334 : int paren_depth = 0;
7335 99 : for (int i = 1; first + i < last; i++)
7336 84 : if (first[i].type == CPP_OPEN_PAREN)
7337 18 : paren_depth++;
7338 66 : else if (first[i].type == CPP_CLOSE_PAREN)
7339 18 : paren_depth--;
7340 48 : else if (paren_depth == 0
7341 30 : && first + i + 2 < last
7342 30 : && first[i].type == CPP_NAME
7343 21 : && first[i + 1].type == CPP_OPEN_PAREN
7344 21 : && first[i + 2].type == CPP_NAME
7345 15 : && !strcmp (IDENTIFIER_POINTER (first[i].value),
7346 : "at")
7347 57 : && !strcmp (IDENTIFIER_POINTER (first[i
7348 : + 2].value),
7349 : "execution"))
7350 : {
7351 : kind = C_OMP_DIR_STANDALONE;
7352 : break;
7353 : }
7354 : }
7355 748 : c_omp_attribute_data v = { toks, dir, kind };
7356 748 : vd.safe_push (v);
7357 748 : if (flag_openmp || dir->simd)
7358 748 : tokens += (last - first) + 1;
7359 : }
7360 609 : c_omp_attribute_data v = {};
7361 609 : vd.safe_push (v);
7362 609 : *pa = TREE_CHAIN (*pa);
7363 : }
7364 : else
7365 1 : pa = &TREE_CHAIN (*pa);
7366 :
7367 610 : if (bad)
7368 : {
7369 17 : fail:
7370 29 : if (have_std_attrs && attrs == NULL)
7371 26 : *have_std_attrs = false;
7372 29 : return false;
7373 : }
7374 :
7375 : unsigned int i;
7376 : c_omp_attribute_data *v;
7377 : c_omp_attribute_data *construct_seen = nullptr;
7378 : c_omp_attribute_data *standalone_seen = nullptr;
7379 : c_omp_attribute_data *prev_standalone_seen = nullptr;
7380 1915 : FOR_EACH_VEC_ELT (vd, i, v)
7381 1322 : if (v->tokens)
7382 : {
7383 730 : if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
7384 : construct_seen = v;
7385 359 : else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
7386 71 : standalone_seen = v;
7387 : }
7388 : else
7389 : {
7390 592 : if (standalone_seen && !prev_standalone_seen)
7391 : {
7392 1322 : prev_standalone_seen = standalone_seen;
7393 1322 : standalone_seen = nullptr;
7394 : }
7395 : }
7396 :
7397 593 : if (cnt > 1 && construct_seen)
7398 : {
7399 4 : error_at ((*construct_seen->tokens)[0].location,
7400 : "OpenMP construct among %<omp::directive%> attributes"
7401 : " requires all %<omp::directive%> attributes on the"
7402 : " same statement to be in the same %<omp::sequence%>");
7403 4 : goto fail;
7404 : }
7405 589 : if (cnt > 1 && standalone_seen && prev_standalone_seen)
7406 : {
7407 2 : error_at ((*standalone_seen->tokens)[0].location,
7408 : "multiple OpenMP standalone directives among"
7409 : " %<omp::directive%> attributes must be all within the"
7410 : " same %<omp::sequence%>");
7411 2 : goto fail;
7412 : }
7413 :
7414 587 : if (prev_standalone_seen)
7415 : standalone_seen = prev_standalone_seen;
7416 520 : if (standalone_seen
7417 587 : && !c_parser_next_token_is (parser, CPP_SEMICOLON))
7418 : {
7419 2 : error_at (standalone_seen->tokens->address ()->location,
7420 : "standalone OpenMP directives in %<omp::directive%> attribute"
7421 : " can only appear on an empty statement");
7422 2 : goto fail;
7423 : }
7424 1162 : if (cnt && c_parser_next_token_is (parser, CPP_PRAGMA))
7425 : {
7426 4 : c_token *token = c_parser_peek_token (parser);
7427 4 : enum pragma_kind kind = token->pragma_kind;
7428 4 : if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
7429 : {
7430 4 : error_at (token->location,
7431 : "mixing OpenMP directives with attribute and pragma "
7432 : "syntax on the same statement");
7433 4 : goto fail;
7434 : }
7435 : }
7436 :
7437 581 : if (!tokens)
7438 : return false;
7439 :
7440 565 : unsigned int tokens_avail = parser->tokens_avail;
7441 :
7442 565 : tokens++;
7443 565 : vec<c_token, va_gc> *toks = NULL;
7444 565 : vec_safe_reserve (toks, tokens, true);
7445 1843 : FOR_EACH_VEC_ELT (vd, i, v)
7446 : {
7447 1278 : if (!v->tokens)
7448 566 : continue;
7449 712 : if (!flag_openmp && !v->dir->simd)
7450 0 : continue;
7451 712 : c_token *first = v->tokens->address ();
7452 712 : c_token *last = first + v->tokens->length ();
7453 712 : c_token tok = {};
7454 712 : tok.type = CPP_PRAGMA;
7455 712 : tok.keyword = RID_MAX;
7456 712 : tok.pragma_kind = pragma_kind (v->dir->id);
7457 712 : tok.location = first->location;
7458 712 : toks->quick_push (tok);
7459 17475 : while (++first < last)
7460 16051 : toks->quick_push (*first);
7461 712 : tok = {};
7462 712 : tok.type = CPP_PRAGMA_EOL;
7463 712 : tok.keyword = RID_MAX;
7464 712 : tok.location = last[-1].location;
7465 712 : toks->quick_push (tok);
7466 : }
7467 :
7468 565 : c_token tok = {};
7469 565 : tok.type = CPP_EOF;
7470 565 : tok.keyword = RID_MAX;
7471 565 : tok.location = toks->last ().location;
7472 565 : toks->quick_push (tok);
7473 :
7474 565 : gcc_assert (!parser->in_omp_attribute_pragma);
7475 565 : parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
7476 565 : parser->in_omp_attribute_pragma->token_vec = toks;
7477 565 : parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
7478 565 : parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
7479 565 : parser->tokens = toks->address ();
7480 565 : parser->tokens_avail = tokens;
7481 565 : return true;
7482 610 : }
7483 :
7484 : /* Handle omp::directive and omp::sequence attributes in ATTRS
7485 : (if any) at the start or after declaration-id of a declaration. */
7486 :
7487 : static void
7488 64219996 : c_parser_handle_directive_omp_attributes (tree &attrs,
7489 : vec<c_token> *&pragma_clauses,
7490 : vec<c_token> *attr_clauses)
7491 : {
7492 64219996 : if (!flag_openmp && !flag_openmp_simd)
7493 : return;
7494 :
7495 1606725 : for (tree *pa = &attrs; *pa; )
7496 643940 : if (is_attribute_namespace_p ("omp", *pa)
7497 643940 : && is_attribute_p ("directive", get_attribute_name (*pa)))
7498 : {
7499 141 : int cnt = 0;
7500 281 : for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
7501 : {
7502 142 : tree a = *pa2;
7503 142 : tree d = TREE_VALUE (a);
7504 142 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7505 142 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7506 142 : c_token *first = toks->address ();
7507 142 : c_token *last = first + toks->length ();
7508 142 : const char *directive[3] = {};
7509 424 : for (int i = 0; i < 3; i++)
7510 : {
7511 390 : tree id = NULL_TREE;
7512 390 : if (first + i == last)
7513 : break;
7514 335 : if (first[i].type == CPP_NAME)
7515 282 : id = first[i].value;
7516 53 : else if (first[i].type == CPP_KEYWORD)
7517 0 : id = ridpointers[(int) first[i].keyword];
7518 : else
7519 : break;
7520 282 : directive[i] = IDENTIFIER_POINTER (id);
7521 : }
7522 142 : const c_omp_directive *dir = NULL;
7523 142 : if (directive[0])
7524 142 : dir = c_omp_categorize_directive (directive[0], directive[1],
7525 : directive[2]);
7526 142 : if (dir == NULL)
7527 : {
7528 9 : error_at (first->location,
7529 : "unknown OpenMP directive name in "
7530 : "%qs attribute argument",
7531 9 : TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7532 9 : *pa2 = TREE_CHAIN (a);
7533 : }
7534 133 : else if (dir->id == PRAGMA_OMP_DECLARE
7535 105 : && (strcmp (directive[1], "simd") == 0
7536 22 : || strcmp (directive[1], "variant") == 0))
7537 : {
7538 92 : if (pragma_clauses)
7539 : {
7540 2 : error_at (first->location,
7541 : "mixing OpenMP directives with attribute and "
7542 : "pragma syntax on the same declaration");
7543 6 : for (pa = &attrs; *pa; )
7544 2 : if (is_attribute_namespace_p ("omp", *pa)
7545 4 : && is_attribute_p ("directive",
7546 2 : get_attribute_name (*pa)))
7547 2 : *pa = TREE_CHAIN (*pa);
7548 : else
7549 0 : pa = &TREE_CHAIN (*pa);
7550 2 : return;
7551 : }
7552 90 : ++cnt;
7553 110 : attr_clauses->reserve (attr_clauses->length ()
7554 90 : + toks->length () + 2);
7555 834 : for (++first; first < last; ++first)
7556 744 : attr_clauses->quick_push (*first);
7557 90 : c_token tok = {};
7558 90 : tok.type = CPP_PRAGMA_EOL;
7559 90 : tok.keyword = RID_MAX;
7560 90 : tok.location = last[-1].location;
7561 90 : attr_clauses->quick_push (tok);
7562 90 : *pa2 = TREE_CHAIN (a);
7563 90 : }
7564 : else
7565 41 : pa2 = &TREE_CHAIN (a);
7566 : }
7567 139 : if (cnt && TREE_VALUE (*pa) == NULL_TREE)
7568 86 : *pa = TREE_CHAIN (*pa);
7569 : else
7570 53 : pa = &TREE_CHAIN (*pa);
7571 : }
7572 : else
7573 643799 : pa = &TREE_CHAIN (*pa);
7574 962785 : if (attr_clauses->length ())
7575 : {
7576 70 : c_token tok = {};
7577 70 : tok.type = CPP_EOF;
7578 70 : tok.keyword = RID_MAX;
7579 70 : tok.location = attr_clauses->last ().location;
7580 70 : attr_clauses->quick_push (tok);
7581 70 : attr_clauses->quick_push (tok);
7582 70 : pragma_clauses = attr_clauses;
7583 : }
7584 : }
7585 :
7586 : /* Check if STD_ATTR contains a musttail attribute and remove if it
7587 : precedes a return. PARSER is the parser and ATTR is the output
7588 : attr_state. */
7589 :
7590 : static tree
7591 973 : c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
7592 : {
7593 973 : if (c_parser_next_token_is_keyword (parser, RID_RETURN))
7594 : {
7595 224 : if (tree a = lookup_attribute ("gnu", "musttail", std_attrs))
7596 : {
7597 416 : for (; a; a = lookup_attribute ("gnu", "musttail", TREE_CHAIN (a)))
7598 209 : if (TREE_VALUE (a))
7599 2 : error ("%qs attribute does not take any arguments",
7600 : "musttail");
7601 207 : std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
7602 207 : attr.musttail_p = true;
7603 : }
7604 224 : if (lookup_attribute ("clang", "musttail", std_attrs))
7605 : {
7606 10 : std_attrs = remove_attribute ("clang", "musttail", std_attrs);
7607 10 : attr.musttail_p = true;
7608 : }
7609 : }
7610 973 : return std_attrs;
7611 : }
7612 :
7613 : /* Return a statement before optional series of LABEL_EXPR/CASE_LABEL_EXPRs.
7614 : Instead of collecting vectors of labels before each stmt just in case
7615 : the statement would be iteration or switch statement for named loops,
7616 : we just remember last emitted statement and let the iteration/switch
7617 : statement search backwards in cur_stmt_list until that stmt for loop
7618 : names if any. */
7619 :
7620 : static tree
7621 88705422 : get_before_labels ()
7622 : {
7623 88705422 : if (!building_stmt_list_p ())
7624 0 : return NULL_TREE;
7625 88705422 : tree_stmt_iterator tsi = tsi_last (cur_stmt_list);
7626 88705422 : if (tsi_end_p (tsi))
7627 : return NULL_TREE;
7628 49125894 : return tsi_stmt (tsi);
7629 : }
7630 :
7631 : /* Parse a compound statement except for the opening brace. This is
7632 : used for parsing both compound statements and statement expressions
7633 : (which follow different paths to handling the opening). */
7634 :
7635 : static location_t
7636 37190418 : c_parser_compound_statement_nostart (c_parser *parser)
7637 : {
7638 37190418 : bool last_stmt = false;
7639 37190418 : bool last_label = false;
7640 37190418 : bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
7641 37190418 : location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
7642 37190418 : struct omp_for_parse_data *omp_for_parse_state
7643 : = parser->omp_for_parse_state;
7644 74380836 : bool in_omp_loop_block
7645 37190418 : = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
7646 37190418 : tree sl = NULL_TREE;
7647 37190418 : attr_state a = {};
7648 :
7649 37190418 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
7650 : {
7651 22928 : location_t endloc = c_parser_peek_token (parser)->location;
7652 22928 : add_debug_begin_stmt (endloc);
7653 22928 : c_parser_consume_token (parser);
7654 22928 : return endloc;
7655 : }
7656 :
7657 : /* If we're parsing a {} sequence in an OMP_FOR body, start a
7658 : statement list for intervening code. */
7659 37167490 : if (in_omp_loop_block)
7660 178 : sl = push_stmt_list ();
7661 :
7662 37167490 : mark_valid_location_for_stdc_pragma (true);
7663 37167490 : if (c_parser_next_token_is_keyword (parser, RID_LABEL))
7664 : {
7665 : /* Read zero or more forward-declarations for labels that nested
7666 : functions can jump to. */
7667 728 : mark_valid_location_for_stdc_pragma (false);
7668 728 : if (in_omp_loop_block)
7669 5 : check_omp_intervening_code (parser);
7670 1578 : while (c_parser_next_token_is_keyword (parser, RID_LABEL))
7671 : {
7672 850 : label_loc = c_parser_peek_token (parser)->location;
7673 850 : c_parser_consume_token (parser);
7674 : /* Any identifiers, including those declared as type names,
7675 : are OK here. */
7676 1534 : while (true)
7677 : {
7678 1192 : tree label;
7679 1192 : if (c_parser_next_token_is_not (parser, CPP_NAME))
7680 : {
7681 0 : c_parser_error (parser, "expected identifier");
7682 0 : break;
7683 : }
7684 1192 : label
7685 1192 : = declare_label (c_parser_peek_token (parser)->value);
7686 1192 : C_DECLARED_LABEL_FLAG (label) = 1;
7687 1192 : add_stmt (build_stmt (label_loc, DECL_EXPR, label));
7688 1192 : c_parser_consume_token (parser);
7689 1192 : if (c_parser_next_token_is (parser, CPP_COMMA))
7690 342 : c_parser_consume_token (parser);
7691 : else
7692 : break;
7693 342 : }
7694 850 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
7695 : }
7696 728 : pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7697 : }
7698 : /* We must now have at least one statement, label or declaration. */
7699 37167490 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
7700 : {
7701 0 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7702 0 : c_parser_error (parser, "expected declaration or statement");
7703 0 : location_t endloc = c_parser_peek_token (parser)->location;
7704 0 : c_parser_consume_token (parser);
7705 0 : return endloc;
7706 : }
7707 37167490 : tree before_labels = get_before_labels ();
7708 124867484 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
7709 : {
7710 50532563 : location_t loc = c_parser_peek_token (parser)->location;
7711 50532563 : loc = expansion_point_location_if_in_system_header (loc);
7712 :
7713 101065126 : bool want_nested_loop = (omp_for_parse_state
7714 50532563 : ? omp_for_parse_state->want_nested_loop
7715 : : false);
7716 :
7717 : /* First take care of special cases for OpenMP "canonical loop
7718 : nest form", that do not allow standard attributes, labels, or
7719 : __extension__ before the nested statement. */
7720 50532563 : if (in_omp_loop_block && !last_label)
7721 : {
7722 397 : tree_code code = omp_for_parse_state->code;
7723 513 : if (want_nested_loop
7724 397 : && c_parser_omp_next_tokens_can_be_canon_loop (parser, code,
7725 : false))
7726 : {
7727 : /* Found the next nested loop. If there were intervening
7728 : code statements collected before now, wrap them in an
7729 : OMP_STRUCTURED_BLOCK node, and start a new structured
7730 : block to hold statements that may come after the FOR. */
7731 116 : gcc_assert (sl);
7732 116 : add_structured_block_stmt (pop_stmt_list (sl));
7733 116 : omp_for_parse_state->depth++;
7734 116 : add_stmt (c_parser_omp_loop_nest (parser, NULL));
7735 116 : omp_for_parse_state->depth--;
7736 116 : sl = push_stmt_list ();
7737 116 : parser->error = false;
7738 116 : before_labels = get_before_labels ();
7739 167 : continue;
7740 : }
7741 281 : else if (want_nested_loop
7742 468 : && c_parser_next_token_is (parser, CPP_OPEN_BRACE))
7743 : {
7744 : /* If this nested compound statement contains the nested loop,
7745 : we need to separate the other statements in the current
7746 : statement into separate blocks of intervening code. If
7747 : there's no nested loop, it's all part of the same
7748 : chunk of intervening code. */
7749 44 : tree pre_sl = pop_stmt_list (sl);
7750 44 : tree nested_sl = push_stmt_list ();
7751 44 : mark_valid_location_for_stdc_pragma (false);
7752 44 : c_parser_statement_after_labels (parser, NULL, NULL_TREE);
7753 44 : nested_sl = pop_stmt_list (nested_sl);
7754 44 : if (omp_for_parse_state->want_nested_loop)
7755 : {
7756 : /* This block didn't contain a loop-nest, so it's
7757 : all part of the same chunk of intervening code. */
7758 13 : check_omp_intervening_code (parser);
7759 13 : sl = push_stmt_list ();
7760 13 : add_stmt (pre_sl);
7761 13 : add_stmt (nested_sl);
7762 : }
7763 : else
7764 : {
7765 : /* It contains the nested loop. */
7766 31 : add_structured_block_stmt (pre_sl);
7767 31 : add_stmt (nested_sl);
7768 31 : sl = push_stmt_list ();
7769 : }
7770 44 : parser->error = false;
7771 44 : before_labels = get_before_labels ();
7772 44 : continue;
7773 44 : }
7774 237 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
7775 : {
7776 : /* Prior to implementing the OpenMP 5.1 syntax for canonical
7777 : loop form, GCC used to accept an empty statements that
7778 : would now be flagged as intervening code. Continue to
7779 : do that, as an extension. */
7780 : /* FIXME: Maybe issue a warning or something here? */
7781 4 : c_parser_consume_token (parser);
7782 4 : before_labels = get_before_labels ();
7783 4 : continue;
7784 : }
7785 : }
7786 :
7787 : /* Standard attributes may start a label, statement or declaration. */
7788 50532399 : bool have_std_attrs
7789 50532399 : = c_parser_nth_token_starts_std_attributes (parser, 1);
7790 50532399 : tree std_attrs = NULL_TREE;
7791 50532399 : if (have_std_attrs)
7792 : {
7793 840 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7794 840 : std_attrs = c_parser_handle_musttail (parser, std_attrs, a);
7795 : }
7796 50532399 : if (c_parser_next_token_is_keyword (parser, RID_CASE)
7797 49536427 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
7798 100035489 : || (c_parser_next_token_is (parser, CPP_NAME)
7799 10070328 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7800 : {
7801 1052640 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
7802 995972 : label_loc = c_parser_peek_2nd_token (parser)->location;
7803 : else
7804 56668 : label_loc = c_parser_peek_token (parser)->location;
7805 1052640 : last_label = true;
7806 1052640 : last_stmt = false;
7807 1052640 : mark_valid_location_for_stdc_pragma (false);
7808 1052640 : if (in_omp_loop_block)
7809 26 : check_omp_intervening_code (parser);
7810 1052640 : c_parser_label (parser, std_attrs);
7811 : }
7812 49479759 : else if (c_parser_next_tokens_start_declaration (parser)
7813 49479759 : || (have_std_attrs
7814 703 : && !c_parser_handle_statement_omp_attributes
7815 703 : (parser, std_attrs, &have_std_attrs)
7816 269 : && c_parser_next_token_is (parser, CPP_SEMICOLON)
7817 77 : && (have_std_attrs = true)))
7818 : {
7819 7626503 : if (last_label)
7820 87 : pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wfree_labels,
7821 : "a label can only be part of a statement and "
7822 : "a declaration is not a statement");
7823 : /* It's unlikely we'll see a nested loop in a declaration in
7824 : intervening code in an OMP loop, but disallow it anyway. */
7825 7626503 : if (in_omp_loop_block)
7826 : {
7827 19 : check_omp_intervening_code (parser);
7828 19 : omp_for_parse_state->want_nested_loop = false;
7829 : }
7830 7626503 : mark_valid_location_for_stdc_pragma (false);
7831 7626503 : bool fallthru_attr_p = false;
7832 7626503 : c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
7833 : true, true, true, false, NULL,
7834 : NULL, have_std_attrs, std_attrs,
7835 : NULL, &fallthru_attr_p);
7836 :
7837 7626503 : if (in_omp_loop_block)
7838 19 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7839 7626503 : if (last_stmt && !fallthru_attr_p)
7840 309104 : pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7841 : "ISO C90 forbids mixed declarations and code");
7842 7626503 : last_stmt = fallthru_attr_p;
7843 7626503 : last_label = false;
7844 7626503 : before_labels = get_before_labels ();
7845 : }
7846 41853256 : else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
7847 : {
7848 : /* __extension__ can start a declaration, but is also an
7849 : unary operator that can start an expression. Consume all
7850 : but the last of a possible series of __extension__ to
7851 : determine which. If standard attributes have already
7852 : been seen, it must start a statement, not a declaration,
7853 : but standard attributes starting a declaration may appear
7854 : after __extension__. */
7855 1560 : while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7856 780 : && (c_parser_peek_2nd_token (parser)->keyword
7857 : == RID_EXTENSION))
7858 0 : c_parser_consume_token (parser);
7859 780 : if (!have_std_attrs
7860 780 : && (c_parser_next_tokens_start_declaration (parser, 2)
7861 709 : || c_parser_nth_token_starts_std_attributes (parser, 2)))
7862 : {
7863 74 : int ext;
7864 74 : ext = disable_extension_diagnostics ();
7865 74 : c_parser_consume_token (parser);
7866 74 : last_label = false;
7867 : /* It's unlikely we'll see a nested loop in a declaration in
7868 : intervening code in an OMP loop, but disallow it anyway. */
7869 74 : if (in_omp_loop_block)
7870 : {
7871 0 : check_omp_intervening_code (parser);
7872 0 : omp_for_parse_state->want_nested_loop = false;
7873 : }
7874 74 : mark_valid_location_for_stdc_pragma (false);
7875 74 : c_parser_declaration_or_fndef (parser, true, true, true, true,
7876 : true, false);
7877 74 : if (in_omp_loop_block)
7878 0 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7879 : /* Following the old parser, __extension__ does not
7880 : disable this diagnostic. */
7881 74 : restore_extension_diagnostics (ext);
7882 74 : if (last_stmt)
7883 7 : pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7884 : "ISO C90 forbids mixed declarations and code");
7885 74 : last_stmt = false;
7886 74 : before_labels = get_before_labels ();
7887 : }
7888 : else
7889 706 : goto statement;
7890 : }
7891 41852476 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
7892 : {
7893 335328 : if (have_std_attrs && !parser->in_omp_attribute_pragma)
7894 0 : c_parser_error (parser, "expected declaration or statement");
7895 335328 : else if (std_attrs)
7896 0 : c_warn_unused_attributes (std_attrs);
7897 : /* External pragmas, and some omp pragmas, are not associated
7898 : with regular c code, and so are not to be considered statements
7899 : syntactically. This ensures that the user doesn't put them
7900 : places that would turn into syntax errors if the directive
7901 : were ignored. */
7902 335328 : if (omp_for_parse_state)
7903 13 : omp_for_parse_state->want_nested_loop = false;
7904 670574 : if (c_parser_pragma (parser,
7905 : last_label ? pragma_stmt : pragma_compound,
7906 : NULL, before_labels))
7907 : {
7908 23133 : last_label = false;
7909 23133 : last_stmt = true;
7910 23133 : if (omp_for_parse_state)
7911 5 : check_omp_intervening_code (parser);
7912 : }
7913 312200 : if (omp_for_parse_state)
7914 13 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7915 335328 : before_labels = get_before_labels ();
7916 : }
7917 41517148 : else if (c_parser_next_token_is (parser, CPP_EOF))
7918 : {
7919 56 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7920 56 : c_parser_error (parser, "expected declaration or statement");
7921 58 : return c_parser_peek_token (parser)->location;
7922 : }
7923 41517092 : else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
7924 : {
7925 5 : if (parser->in_if_block)
7926 : {
7927 2 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7928 2 : error_at (loc, "expected %<}%> before %<else%>");
7929 2 : return c_parser_peek_token (parser)->location;
7930 : }
7931 : else
7932 : {
7933 3 : error_at (loc, "%<else%> without a previous %<if%>");
7934 3 : c_parser_consume_token (parser);
7935 3 : before_labels = get_before_labels ();
7936 3 : continue;
7937 : }
7938 : }
7939 : else
7940 : {
7941 41517087 : statement:
7942 41517793 : c_warn_unused_attributes (std_attrs);
7943 41517793 : last_label = false;
7944 41517793 : last_stmt = true;
7945 41517793 : mark_valid_location_for_stdc_pragma (false);
7946 41517793 : if (!omp_for_parse_state)
7947 41517562 : c_parser_statement_after_labels (parser, NULL, before_labels,
7948 : NULL, a);
7949 : else
7950 : {
7951 : /* In canonical loop nest form, nested loops can only appear
7952 : directly, or in a directly nested compound statement. We
7953 : already took care of those cases above, so now we have
7954 : something else. This statement and everything inside
7955 : it must be intervening code. */
7956 231 : omp_for_parse_state->want_nested_loop = false;
7957 231 : check_omp_intervening_code (parser);
7958 231 : c_parser_statement_after_labels (parser, NULL, before_labels);
7959 231 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7960 : }
7961 41517792 : before_labels = get_before_labels ();
7962 : }
7963 :
7964 50532337 : parser->error = false;
7965 : }
7966 37167431 : if (last_label)
7967 45 : pedwarn_c11 (label_loc, OPT_Wfree_labels,
7968 : "label at end of compound statement");
7969 37167431 : location_t endloc = c_parser_peek_token (parser)->location;
7970 37167431 : c_parser_consume_token (parser);
7971 :
7972 : /* Restore the value we started with. */
7973 37167431 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7974 :
7975 : /* Package leftover intervening code, or the whole contents of the
7976 : compound statement if we were looking for a nested loop in an OMP_FOR
7977 : construct and didn't find one. */
7978 37167431 : if (sl)
7979 : {
7980 178 : sl = pop_stmt_list (sl);
7981 178 : if (omp_for_parse_state->want_nested_loop)
7982 31 : add_stmt (sl);
7983 : else
7984 147 : add_structured_block_stmt (sl);
7985 : }
7986 : return endloc;
7987 : }
7988 :
7989 : /* Parse all consecutive labels, possibly preceded by standard
7990 : attributes. In this context, a statement is required, not a
7991 : declaration, so attributes must be followed by a statement that is
7992 : not just a semicolon. Returns an attr_state. */
7993 :
7994 : static attr_state
7995 2058068 : c_parser_all_labels (c_parser *parser)
7996 : {
7997 2058068 : attr_state attr = {};
7998 2058068 : bool have_std_attrs;
7999 2058068 : tree std_attrs = NULL;
8000 2058068 : if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1)))
8001 : {
8002 109 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8003 109 : std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
8004 : }
8005 :
8006 2059039 : while (c_parser_next_token_is_keyword (parser, RID_CASE)
8007 2058546 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
8008 4117574 : || (c_parser_next_token_is (parser, CPP_NAME)
8009 503051 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
8010 : {
8011 971 : c_parser_label (parser, std_attrs);
8012 971 : std_attrs = NULL;
8013 971 : if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
8014 : 1)))
8015 : {
8016 3 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8017 3 : std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
8018 : }
8019 : }
8020 2058068 : if (std_attrs
8021 2058068 : && (!c_parser_handle_statement_omp_attributes (parser, std_attrs, &have_std_attrs)
8022 11 : || std_attrs))
8023 : {
8024 22 : if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
8025 0 : c_parser_error (parser, "expected statement");
8026 18 : c_warn_unused_attributes (std_attrs);
8027 : }
8028 2058142 : else if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
8029 1 : c_parser_error (parser, "expected statement");
8030 2058068 : return attr;
8031 : }
8032 :
8033 :
8034 : /* Information used while parsing an OpenMP metadirective. */
8035 : struct omp_metadirective_parse_data {
8036 : /* These fields are used to unique-ify labels when reparsing the
8037 : code in a metadirective alternative. */
8038 : vec<tree> * GTY((skip)) body_labels;
8039 : unsigned int region_num;
8040 : };
8041 :
8042 : /* Helper function for c_parser_label: mangle a metadirective region
8043 : label NAME. */
8044 : static tree
8045 0 : mangle_metadirective_region_label (c_parser *parser, tree name)
8046 : {
8047 0 : if (parser->omp_metadirective_state->body_labels->contains (name))
8048 : {
8049 0 : const char *old_name = IDENTIFIER_POINTER (name);
8050 0 : char *new_name = (char *) XALLOCAVEC (char, strlen (old_name) + 32);
8051 0 : sprintf (new_name, "%s_MDR%u", old_name,
8052 : parser->omp_metadirective_state->region_num);
8053 0 : return get_identifier (new_name);
8054 : }
8055 0 : return name;
8056 : }
8057 :
8058 : /* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
8059 :
8060 : label:
8061 : identifier : gnu-attributes[opt]
8062 : case constant-expression :
8063 : default :
8064 :
8065 : GNU extensions:
8066 :
8067 : label:
8068 : case constant-expression ... constant-expression :
8069 :
8070 : The use of gnu-attributes on labels is a GNU extension. The syntax in
8071 : GNU C accepts any expressions without commas, non-constant
8072 : expressions being rejected later. Any standard
8073 : attribute-specifier-sequence before the first label has been parsed
8074 : in the caller, to distinguish statements from declarations. Any
8075 : attribute-specifier-sequence after the label is parsed in this
8076 : function. */
8077 : static void
8078 1053611 : c_parser_label (c_parser *parser, tree std_attrs)
8079 : {
8080 1053611 : location_t loc1 = c_parser_peek_token (parser)->location;
8081 1053611 : tree label = NULL_TREE;
8082 :
8083 : /* Remember whether this case or a user-defined label is allowed to fall
8084 : through to. */
8085 1053611 : bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
8086 :
8087 1053611 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
8088 : {
8089 996465 : tree exp1, exp2;
8090 996465 : c_parser_consume_token (parser);
8091 996465 : exp1 = convert_lvalue_to_rvalue (loc1,
8092 : c_parser_expr_no_commas (parser, NULL),
8093 : true, true).value;
8094 996465 : if (c_parser_next_token_is (parser, CPP_COLON))
8095 : {
8096 996143 : c_parser_consume_token (parser);
8097 996143 : label = do_case (loc1, exp1, NULL_TREE, std_attrs);
8098 : }
8099 322 : else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
8100 : {
8101 314 : c_parser_consume_token (parser);
8102 314 : exp2 = convert_lvalue_to_rvalue (loc1,
8103 : c_parser_expr_no_commas (parser,
8104 : NULL),
8105 : true, true).value;
8106 314 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
8107 314 : label = do_case (loc1, exp1, exp2, std_attrs);
8108 : }
8109 : else
8110 8 : c_parser_error (parser, "expected %<:%> or %<...%>");
8111 : }
8112 57146 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
8113 : {
8114 33348 : c_parser_consume_token (parser);
8115 33348 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
8116 33348 : label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
8117 : }
8118 : else
8119 : {
8120 23798 : tree name = c_parser_peek_token (parser)->value;
8121 23798 : tree tlab;
8122 23798 : tree attrs;
8123 23798 : location_t loc2 = c_parser_peek_token (parser)->location;
8124 23798 : gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
8125 23798 : c_parser_consume_token (parser);
8126 23798 : gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
8127 23798 : c_parser_consume_token (parser);
8128 23798 : attrs = c_parser_gnu_attributes (parser);
8129 23798 : if (parser->omp_metadirective_state)
8130 0 : name = mangle_metadirective_region_label (parser, name);
8131 23798 : tlab = define_label (loc2, name);
8132 23798 : if (tlab)
8133 : {
8134 23770 : decl_attributes (&tlab, attrs, 0);
8135 23770 : decl_attributes (&tlab, std_attrs, 0);
8136 23770 : label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
8137 : }
8138 23798 : if (attrs
8139 23798 : && c_parser_next_tokens_start_declaration (parser))
8140 1 : warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
8141 : " label and declaration appertains to the label");
8142 : }
8143 1053611 : if (label)
8144 : {
8145 1053431 : if (TREE_CODE (label) == LABEL_EXPR)
8146 23770 : FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
8147 : else
8148 1029661 : FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
8149 : }
8150 1053611 : }
8151 :
8152 : /* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
8153 :
8154 : statement:
8155 : labeled-statement
8156 : attribute-specifier-sequence[opt] compound-statement
8157 : expression-statement
8158 : attribute-specifier-sequence[opt] selection-statement
8159 : attribute-specifier-sequence[opt] iteration-statement
8160 : attribute-specifier-sequence[opt] jump-statement
8161 :
8162 : labeled-statement:
8163 : attribute-specifier-sequence[opt] label statement
8164 :
8165 : expression-statement:
8166 : expression[opt] ;
8167 : attribute-specifier-sequence expression ;
8168 :
8169 : selection-statement:
8170 : if-statement
8171 : switch-statement
8172 :
8173 : iteration-statement:
8174 : while-statement
8175 : do-statement
8176 : for-statement
8177 :
8178 : jump-statement:
8179 : goto identifier ;
8180 : continue ;
8181 : break ;
8182 : return expression[opt] ;
8183 :
8184 : GNU extensions:
8185 :
8186 : statement:
8187 : attribute-specifier-sequence[opt] asm-statement
8188 :
8189 : jump-statement:
8190 : goto * expression ;
8191 :
8192 : expression-statement:
8193 : gnu-attributes ;
8194 :
8195 : Objective-C:
8196 :
8197 : statement:
8198 : attribute-specifier-sequence[opt] objc-throw-statement
8199 : attribute-specifier-sequence[opt] objc-try-catch-statement
8200 : attribute-specifier-sequence[opt] objc-synchronized-statement
8201 :
8202 : objc-throw-statement:
8203 : @throw expression ;
8204 : @throw ;
8205 :
8206 : OpenACC:
8207 :
8208 : statement:
8209 : attribute-specifier-sequence[opt] openacc-construct
8210 :
8211 : openacc-construct:
8212 : parallel-construct
8213 : kernels-construct
8214 : data-construct
8215 : loop-construct
8216 :
8217 : parallel-construct:
8218 : parallel-directive structured-block
8219 :
8220 : kernels-construct:
8221 : kernels-directive structured-block
8222 :
8223 : data-construct:
8224 : data-directive structured-block
8225 :
8226 : loop-construct:
8227 : loop-directive structured-block
8228 :
8229 : OpenMP:
8230 :
8231 : statement:
8232 : attribute-specifier-sequence[opt] openmp-construct
8233 :
8234 : openmp-construct:
8235 : parallel-construct
8236 : for-construct
8237 : simd-construct
8238 : for-simd-construct
8239 : sections-construct
8240 : single-construct
8241 : parallel-for-construct
8242 : parallel-for-simd-construct
8243 : parallel-sections-construct
8244 : master-construct
8245 : critical-construct
8246 : atomic-construct
8247 : ordered-construct
8248 :
8249 : parallel-construct:
8250 : parallel-directive structured-block
8251 :
8252 : for-construct:
8253 : for-directive iteration-statement
8254 :
8255 : simd-construct:
8256 : simd-directive iteration-statements
8257 :
8258 : for-simd-construct:
8259 : for-simd-directive iteration-statements
8260 :
8261 : sections-construct:
8262 : sections-directive section-scope
8263 :
8264 : single-construct:
8265 : single-directive structured-block
8266 :
8267 : parallel-for-construct:
8268 : parallel-for-directive iteration-statement
8269 :
8270 : parallel-for-simd-construct:
8271 : parallel-for-simd-directive iteration-statement
8272 :
8273 : parallel-sections-construct:
8274 : parallel-sections-directive section-scope
8275 :
8276 : master-construct:
8277 : master-directive structured-block
8278 :
8279 : critical-construct:
8280 : critical-directive structured-block
8281 :
8282 : atomic-construct:
8283 : atomic-directive expression-statement
8284 :
8285 : ordered-construct:
8286 : ordered-directive structured-block
8287 :
8288 : Transactional Memory:
8289 :
8290 : statement:
8291 : attribute-specifier-sequence[opt] transaction-statement
8292 : attribute-specifier-sequence[opt] transaction-cancel-statement
8293 :
8294 : IF_P is used to track whether there's a (possibly labeled) if statement
8295 : which is not enclosed in braces and has an else clause. This is used to
8296 : implement -Wparentheses. */
8297 :
8298 : static void
8299 532091 : c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
8300 : {
8301 532091 : tree before_labels = get_before_labels ();
8302 532091 : attr_state a = c_parser_all_labels (parser);
8303 532091 : if (loc_after_labels)
8304 366471 : *loc_after_labels = c_parser_peek_token (parser)->location;
8305 532091 : parser->omp_attrs_forbidden_p = false;
8306 532091 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8307 532091 : }
8308 :
8309 : /* Parse and handle optional identifier after break or continue keywords. */
8310 :
8311 : static tree
8312 187071 : c_parser_bc_name (c_parser *parser, bool is_break)
8313 : {
8314 187071 : if (!c_parser_next_token_is (parser, CPP_NAME))
8315 : return NULL_TREE;
8316 :
8317 316 : c_token *tok = c_parser_peek_token (parser);
8318 316 : tree label = c_finish_bc_name (tok->location, tok->value, is_break);
8319 316 : c_parser_consume_token (parser);
8320 316 : return label;
8321 : }
8322 :
8323 : /* Parse a statement, other than a labeled statement. CHAIN is a vector
8324 : of if-else-if conditions. All labels and standard attributes have
8325 : been parsed in the caller.
8326 :
8327 : IF_P is used to track whether there's a (possibly labeled) if statement
8328 : which is not enclosed in braces and has an else clause. This is used to
8329 : implement -Wparentheses. ASTATE is an earlier parsed attribute state.
8330 :
8331 : BEFORE_LABELS is last statement before possible labels, see
8332 : get_before_labels description for details. */
8333 :
8334 : static void
8335 43115965 : c_parser_statement_after_labels (c_parser *parser, bool *if_p,
8336 : tree before_labels,
8337 : vec<tree> *chain, attr_state astate)
8338 : {
8339 43115965 : location_t loc = c_parser_peek_token (parser)->location;
8340 43115965 : tree stmt = NULL_TREE;
8341 43115965 : bool in_if_block = parser->in_if_block;
8342 43115965 : parser->in_if_block = false;
8343 43115965 : if (if_p != NULL)
8344 811937 : *if_p = false;
8345 :
8346 43115965 : if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
8347 42663628 : add_debug_begin_stmt (loc);
8348 :
8349 452337 : restart:
8350 43116001 : switch (c_parser_peek_token (parser)->type)
8351 : {
8352 452341 : case CPP_OPEN_BRACE:
8353 452341 : add_stmt (c_parser_compound_statement (parser));
8354 452341 : break;
8355 36806047 : case CPP_KEYWORD:
8356 36806047 : switch (c_parser_peek_token (parser)->keyword)
8357 : {
8358 1268763 : case RID_IF:
8359 1268763 : c_parser_if_statement (parser, if_p, chain);
8360 1268763 : break;
8361 37243 : case RID_SWITCH:
8362 37243 : c_parser_switch_statement (parser, if_p, before_labels);
8363 37243 : break;
8364 44415 : case RID_WHILE:
8365 44415 : c_parser_while_statement (parser, false, 0, false, if_p, before_labels);
8366 44415 : break;
8367 145261 : case RID_DO:
8368 145261 : c_parser_do_statement (parser, false, 0, false, before_labels);
8369 145261 : break;
8370 281561 : case RID_FOR:
8371 281561 : c_parser_for_statement (parser, false, 0, false, if_p, before_labels);
8372 281561 : break;
8373 83627 : case RID_GOTO:
8374 83627 : c_parser_consume_token (parser);
8375 83627 : if (c_parser_next_token_is (parser, CPP_NAME))
8376 : {
8377 82687 : tree name = c_parser_peek_token (parser)->value;
8378 82687 : if (parser->omp_metadirective_state)
8379 0 : name = mangle_metadirective_region_label (parser, name);
8380 82687 : stmt = c_finish_goto_label (loc, name);
8381 82687 : c_parser_consume_token (parser);
8382 : }
8383 940 : else if (c_parser_next_token_is (parser, CPP_MULT))
8384 : {
8385 940 : struct c_expr val;
8386 :
8387 940 : c_parser_consume_token (parser);
8388 940 : val = c_parser_expression (parser);
8389 940 : val = convert_lvalue_to_rvalue (loc, val, false, true);
8390 940 : stmt = c_finish_goto_ptr (loc, val);
8391 : }
8392 : else
8393 0 : c_parser_error (parser, "expected identifier or %<*%>");
8394 83627 : goto expect_semicolon;
8395 13160 : case RID_CONTINUE:
8396 13160 : c_parser_consume_token (parser);
8397 13160 : stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false,
8398 : c_parser_bc_name (parser, false));
8399 13160 : goto expect_semicolon;
8400 173911 : case RID_BREAK:
8401 173911 : c_parser_consume_token (parser);
8402 173911 : stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true,
8403 : c_parser_bc_name (parser, true));
8404 173911 : goto expect_semicolon;
8405 34534675 : case RID_RETURN:
8406 34534675 : c_parser_consume_token (parser);
8407 34534675 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8408 : {
8409 42440 : stmt = c_finish_return (loc, NULL_TREE, NULL_TREE,
8410 21220 : astate.musttail_p);
8411 21220 : c_parser_consume_token (parser);
8412 : }
8413 : else
8414 : {
8415 34513455 : location_t xloc = c_parser_peek_token (parser)->location;
8416 34513455 : struct c_expr expr = c_parser_expression_conv (parser);
8417 34513455 : mark_exp_read (expr.value);
8418 35291846 : stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
8419 : expr.value, expr.original_type,
8420 34513455 : astate.musttail_p);
8421 34513455 : goto expect_semicolon;
8422 : }
8423 21220 : break;
8424 204806 : case RID_ASM:
8425 204806 : stmt = c_parser_asm_statement (parser);
8426 204806 : break;
8427 137 : case RID_TRANSACTION_ATOMIC:
8428 137 : case RID_TRANSACTION_RELAXED:
8429 274 : stmt = c_parser_transaction (parser,
8430 137 : c_parser_peek_token (parser)->keyword);
8431 137 : break;
8432 28 : case RID_TRANSACTION_CANCEL:
8433 28 : stmt = c_parser_transaction_cancel (parser);
8434 28 : goto expect_semicolon;
8435 0 : case RID_AT_THROW:
8436 0 : gcc_assert (c_dialect_objc ());
8437 0 : c_parser_consume_token (parser);
8438 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8439 : {
8440 0 : stmt = objc_build_throw_stmt (loc, NULL_TREE);
8441 0 : c_parser_consume_token (parser);
8442 : }
8443 : else
8444 : {
8445 0 : struct c_expr expr = c_parser_expression (parser);
8446 0 : expr = convert_lvalue_to_rvalue (loc, expr, false, false);
8447 0 : expr.value = c_fully_fold (expr.value, false, NULL);
8448 0 : stmt = objc_build_throw_stmt (loc, expr.value);
8449 0 : goto expect_semicolon;
8450 : }
8451 0 : break;
8452 0 : case RID_AT_TRY:
8453 0 : gcc_assert (c_dialect_objc ());
8454 0 : c_parser_objc_try_catch_finally_statement (parser);
8455 0 : break;
8456 0 : case RID_AT_SYNCHRONIZED:
8457 0 : gcc_assert (c_dialect_objc ());
8458 0 : c_parser_objc_synchronized_statement (parser);
8459 0 : break;
8460 9 : case RID_ATTRIBUTE:
8461 9 : {
8462 : /* Allow '__attribute__((fallthrough));' or
8463 : '__attribute__((assume(cond)));' or
8464 : '__attribute__((musttail))) return'. */
8465 9 : tree attrs = c_parser_gnu_attributes (parser);
8466 9 : bool has_assume = lookup_attribute ("assume", attrs);
8467 9 : if (has_assume)
8468 : {
8469 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8470 0 : attrs = handle_assume_attribute (loc, attrs, true);
8471 : else
8472 : {
8473 0 : auto_urlify_attributes sentinel;
8474 0 : warning_at (loc, OPT_Wattributes,
8475 : "%<assume%> attribute not followed by %<;%>");
8476 0 : has_assume = false;
8477 0 : }
8478 : }
8479 9 : gcc_assert (!astate.musttail_p);
8480 9 : attrs = c_parser_handle_musttail (parser, attrs, astate);
8481 9 : if (astate.musttail_p)
8482 : {
8483 4 : if (attrs)
8484 : {
8485 1 : auto_urlify_attributes sentinel;
8486 1 : warning_at (c_parser_peek_token (parser)->location,
8487 1 : OPT_Wattributes,
8488 : "attribute %<musttail%> mixed with other "
8489 : "attributes on %<return%> statement");
8490 1 : }
8491 4 : goto restart;
8492 : }
8493 5 : if (attribute_fallthrough_p (attrs))
8494 : {
8495 5 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8496 : {
8497 5 : tree fn = build_call_expr_internal_loc (loc,
8498 : IFN_FALLTHROUGH,
8499 : void_type_node, 0);
8500 5 : add_stmt (fn);
8501 : /* Eat the ';'. */
8502 5 : c_parser_consume_token (parser);
8503 : }
8504 : else
8505 : {
8506 0 : auto_urlify_attributes sentinel;
8507 0 : warning_at (loc, OPT_Wattributes,
8508 : "%<fallthrough%> attribute not followed "
8509 : "by %<;%>");
8510 0 : }
8511 : }
8512 0 : else if (has_assume)
8513 : /* Eat the ';'. */
8514 0 : c_parser_consume_token (parser);
8515 0 : else if (attrs != NULL_TREE)
8516 : {
8517 0 : auto_urlify_attributes sentinel;
8518 0 : warning_at (loc, OPT_Wattributes,
8519 : "only attribute %<fallthrough%> or %<assume%> can "
8520 : "be applied to a null statement");
8521 0 : }
8522 : break;
8523 : }
8524 18451 : default:
8525 18451 : goto expr_stmt;
8526 : }
8527 : break;
8528 207297 : case CPP_SEMICOLON:
8529 207297 : c_parser_consume_token (parser);
8530 207297 : break;
8531 5 : case CPP_CLOSE_PAREN:
8532 5 : case CPP_CLOSE_SQUARE:
8533 : /* Avoid infinite loop in error recovery:
8534 : c_parser_skip_until_found stops at a closing nesting
8535 : delimiter without consuming it, but here we need to consume
8536 : it to proceed further. */
8537 5 : c_parser_error (parser, "expected statement");
8538 5 : c_parser_consume_token (parser);
8539 5 : break;
8540 2703 : case CPP_PRAGMA:
8541 2703 : if (!c_parser_pragma (parser, pragma_stmt, if_p, before_labels))
8542 32 : goto restart;
8543 : break;
8544 5666059 : default:
8545 5666059 : expr_stmt:
8546 5666059 : stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
8547 40450239 : expect_semicolon:
8548 40450239 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
8549 40450239 : break;
8550 : }
8551 : /* Two cases cannot and do not have line numbers associated: If stmt
8552 : is degenerate, such as "2;", then stmt is an INTEGER_CST, which
8553 : cannot hold line numbers. But that's OK because the statement
8554 : will either be changed to a MODIFY_EXPR during gimplification of
8555 : the statement expr, or discarded. If stmt was compound, but
8556 : without new variables, we will have skipped the creation of a
8557 : BIND and will have a bare STATEMENT_LIST. But that's OK because
8558 : (recursively) all of the component statements should already have
8559 : line numbers assigned. ??? Can we discard no-op statements
8560 : earlier? */
8561 43115964 : if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
8562 2442896 : protected_set_expr_location (stmt, loc);
8563 :
8564 43115964 : parser->in_if_block = in_if_block;
8565 43115964 : }
8566 :
8567 : /* Parse the condition from an if, do, while or for statements. */
8568 :
8569 : static tree
8570 471410 : c_parser_condition (c_parser *parser)
8571 : {
8572 471410 : location_t loc = c_parser_peek_token (parser)->location;
8573 471410 : tree cond;
8574 471410 : cond = c_parser_expression_conv (parser).value;
8575 471410 : cond = c_objc_common_truthvalue_conversion (loc, cond);
8576 471410 : cond = c_fully_fold (cond, false, NULL);
8577 471410 : if (warn_sequence_point)
8578 82077 : verify_sequence_points (cond);
8579 471410 : return cond;
8580 : }
8581 :
8582 : /* Parse a parenthesized condition from a do or while statement.
8583 :
8584 : condition:
8585 : ( expression )
8586 : */
8587 :
8588 : static tree
8589 189750 : c_parser_paren_condition (c_parser *parser)
8590 : {
8591 189750 : tree cond;
8592 189750 : matching_parens parens;
8593 189750 : if (!parens.require_open (parser))
8594 0 : return error_mark_node;
8595 189750 : cond = c_parser_condition (parser);
8596 189750 : parens.skip_until_found_close (parser);
8597 189750 : return cond;
8598 : }
8599 :
8600 : /* Parse a selection-header:
8601 :
8602 : selection-header:
8603 : expression
8604 : declaration expression
8605 : simple-declaration
8606 :
8607 : simple-declaration:
8608 : attribute-specifier-sequence[opt] declaration-specifiers declarator
8609 : = initializer
8610 :
8611 : SWITCH_P is true if we are called from c_parser_switch_statement; in
8612 : that case, don't perform the truthvalue conversion. */
8613 :
8614 : static c_expr
8615 1305998 : c_parser_selection_header (c_parser *parser, bool switch_p)
8616 : {
8617 1305998 : location_t loc = c_parser_peek_token (parser)->location;
8618 1305998 : c_expr expr;
8619 1305998 : bool parse_expr = true;
8620 1305998 : tree std_attrs;
8621 1305998 : bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
8622 1305998 : if (have_std_attrs)
8623 20 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8624 : else
8625 : std_attrs = NULL_TREE;
8626 1305998 : if (c_parser_next_tokens_start_declaration (parser))
8627 : {
8628 239 : pedwarn_c23 (loc, OPT_Wpedantic,
8629 : "ISO C does not support if declarations before C2Y");
8630 239 : expr.value
8631 239 : = c_parser_declaration_or_fndef (parser,
8632 : /*fndef_ok=*/false,
8633 : /*static_assert_ok=*/false,
8634 : /*empty_ok=*/false,
8635 : /*nested=*/true,
8636 : /*start_attr_ok=*/true,
8637 : /*simple_ok=*/true,
8638 : /*objc_foreach_object_decl=*/nullptr,
8639 : /*omp_declare_simd_clauses=*/nullptr,
8640 : have_std_attrs,
8641 : std_attrs);
8642 239 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8643 99 : c_parser_consume_token (parser);
8644 : else
8645 : {
8646 : /* A simple-declaration is a declaration that can appear in
8647 : place of the controlling expression of a selection statement.
8648 : In that case, there shall be an initializer. */
8649 140 : if (!expr.value)
8650 : {
8651 48 : error_at (loc, "declaration in the controlling expression must "
8652 : "have an initializer");
8653 48 : expr.original_type = error_mark_node;
8654 48 : expr.set_error ();
8655 48 : return expr;
8656 : }
8657 : parse_expr = false;
8658 : }
8659 191 : if (expr.value)
8660 : {
8661 175 : expr.original_type = TREE_TYPE (expr.value);
8662 175 : expr = convert_lvalue_to_rvalue (loc, expr, /*convert_p=*/true,
8663 : /*read_p=*/true);
8664 : }
8665 : }
8666 1305759 : else if (have_std_attrs)
8667 : {
8668 8 : c_parser_error (parser, "expected declaration");
8669 8 : expr.original_type = error_mark_node;
8670 8 : expr.set_error ();
8671 8 : return expr;
8672 : }
8673 :
8674 191 : if (parse_expr)
8675 1305850 : expr = c_parser_expression_conv (parser);
8676 1305942 : if (!switch_p)
8677 : {
8678 1268734 : expr.value = c_objc_common_truthvalue_conversion (loc, expr.value);
8679 1268734 : expr.value = c_fully_fold (expr.value, false, NULL);
8680 1268734 : if (warn_sequence_point)
8681 245621 : verify_sequence_points (expr.value);
8682 : }
8683 : return expr;
8684 : }
8685 :
8686 : /* Parse a selection-header enclosed in parentheses:
8687 :
8688 : ( selection-header )
8689 : */
8690 :
8691 : static tree
8692 1268763 : c_parser_paren_selection_header (c_parser *parser)
8693 : {
8694 1268763 : matching_parens parens;
8695 1268763 : if (!parens.require_open (parser))
8696 1 : return error_mark_node;
8697 1268762 : tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value;
8698 1268762 : parens.skip_until_found_close (parser);
8699 1268762 : return cond;
8700 : }
8701 :
8702 : /* Parse a statement which is a block in C99.
8703 :
8704 : IF_P is used to track whether there's a (possibly labeled) if statement
8705 : which is not enclosed in braces and has an else clause. This is used to
8706 : implement -Wparentheses. */
8707 :
8708 : static tree
8709 522475 : c_parser_c99_block_statement (c_parser *parser, bool *if_p,
8710 : location_t *loc_after_labels)
8711 : {
8712 522475 : tree block = c_begin_compound_stmt (flag_isoc99);
8713 522475 : location_t loc = c_parser_peek_token (parser)->location;
8714 522475 : c_parser_statement (parser, if_p, loc_after_labels);
8715 522475 : return c_end_compound_stmt (loc, block, flag_isoc99);
8716 : }
8717 :
8718 : /* Parse the body of an if statement. This is just parsing a
8719 : statement but (a) it is a block in C99, (b) we track whether the
8720 : body is an if statement for the sake of -Wparentheses warnings, (c)
8721 : we handle an empty body specially for the sake of -Wempty-body
8722 : warnings, and (d) we call parser_compound_statement directly
8723 : because c_parser_statement_after_labels resets
8724 : parser->in_if_block.
8725 :
8726 : IF_P is used to track whether there's a (possibly labeled) if statement
8727 : which is not enclosed in braces and has an else clause. This is used to
8728 : implement -Wparentheses. */
8729 :
8730 : static tree
8731 1268763 : c_parser_if_body (c_parser *parser, bool *if_p,
8732 : const token_indent_info &if_tinfo)
8733 : {
8734 1268763 : tree block = c_begin_compound_stmt (flag_isoc99);
8735 1268763 : location_t body_loc = c_parser_peek_token (parser)->location;
8736 1268763 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8737 1268763 : token_indent_info body_tinfo
8738 1268763 : = get_token_indent_info (c_parser_peek_token (parser));
8739 1268763 : tree before_labels = get_before_labels ();
8740 1268763 : attr_state a = c_parser_all_labels (parser);
8741 :
8742 1268763 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8743 : {
8744 6735 : location_t loc = c_parser_peek_token (parser)->location;
8745 6735 : add_stmt (build_empty_stmt (loc));
8746 6735 : c_parser_consume_token (parser);
8747 6735 : if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
8748 466 : warning_at (loc, OPT_Wempty_body,
8749 : "suggest braces around empty body in an %<if%> statement");
8750 : }
8751 1262028 : else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8752 453188 : add_stmt (c_parser_compound_statement (parser));
8753 : else
8754 : {
8755 808840 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8756 808840 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8757 : }
8758 :
8759 1268763 : token_indent_info next_tinfo
8760 1268763 : = get_token_indent_info (c_parser_peek_token (parser));
8761 1268763 : warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
8762 1268763 : if (body_loc_after_labels != UNKNOWN_LOCATION
8763 808840 : && next_tinfo.type != CPP_SEMICOLON)
8764 803959 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8765 803959 : if_tinfo.location, RID_IF);
8766 :
8767 1268763 : return c_end_compound_stmt (body_loc, block, flag_isoc99);
8768 : }
8769 :
8770 : /* Parse the else body of an if statement. This is just parsing a
8771 : statement but (a) it is a block in C99, (b) we handle an empty body
8772 : specially for the sake of -Wempty-body warnings. CHAIN is a vector
8773 : of if-else-if conditions. */
8774 :
8775 : static tree
8776 257214 : c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
8777 : vec<tree> *chain)
8778 : {
8779 257214 : location_t body_loc = c_parser_peek_token (parser)->location;
8780 257214 : tree block = c_begin_compound_stmt (flag_isoc99);
8781 257214 : token_indent_info body_tinfo
8782 257214 : = get_token_indent_info (c_parser_peek_token (parser));
8783 257214 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8784 257214 : tree before_labels = get_before_labels ();
8785 257214 : attr_state a = c_parser_all_labels (parser);
8786 :
8787 257214 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8788 : {
8789 29 : location_t loc = c_parser_peek_token (parser)->location;
8790 29 : warning_at (loc,
8791 29 : OPT_Wempty_body,
8792 : "suggest braces around empty body in an %<else%> statement");
8793 29 : add_stmt (build_empty_stmt (loc));
8794 29 : c_parser_consume_token (parser);
8795 : }
8796 : else
8797 : {
8798 257185 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8799 220298 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8800 257185 : c_parser_statement_after_labels (parser, NULL, before_labels, chain, a);
8801 : }
8802 :
8803 257214 : token_indent_info next_tinfo
8804 257214 : = get_token_indent_info (c_parser_peek_token (parser));
8805 257214 : warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
8806 257214 : if (body_loc_after_labels != UNKNOWN_LOCATION
8807 220298 : && next_tinfo.type != CPP_SEMICOLON)
8808 220280 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8809 220280 : else_tinfo.location, RID_ELSE);
8810 :
8811 257214 : return c_end_compound_stmt (body_loc, block, flag_isoc99);
8812 : }
8813 :
8814 : /* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8815 :
8816 : if-statement:
8817 : if ( selection-header ) statement
8818 : if ( selection-header ) statement else statement
8819 :
8820 : CHAIN is a vector of if-else-if conditions.
8821 : IF_P is used to track whether there's a (possibly labeled) if statement
8822 : which is not enclosed in braces and has an else clause. This is used to
8823 : implement -Wparentheses. */
8824 :
8825 : static void
8826 1268763 : c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
8827 : {
8828 1268763 : tree block;
8829 1268763 : location_t loc;
8830 1268763 : tree cond;
8831 1268763 : bool nested_if = false;
8832 1268763 : tree first_body, second_body;
8833 1268763 : bool in_if_block;
8834 :
8835 1268763 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
8836 1268763 : token_indent_info if_tinfo
8837 1268763 : = get_token_indent_info (c_parser_peek_token (parser));
8838 1268763 : c_parser_consume_token (parser);
8839 1268763 : block = c_begin_compound_stmt (flag_isoc99);
8840 1268763 : loc = c_parser_peek_token (parser)->location;
8841 1268763 : cond = c_parser_paren_selection_header (parser);
8842 1268763 : in_if_block = parser->in_if_block;
8843 1268763 : parser->in_if_block = true;
8844 1268763 : first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
8845 1268763 : parser->in_if_block = in_if_block;
8846 :
8847 1268763 : if (warn_duplicated_cond)
8848 62 : warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
8849 :
8850 1268763 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
8851 : {
8852 257214 : token_indent_info else_tinfo
8853 257214 : = get_token_indent_info (c_parser_peek_token (parser));
8854 257214 : c_parser_consume_token (parser);
8855 257214 : if (warn_duplicated_cond)
8856 : {
8857 43 : if (c_parser_next_token_is_keyword (parser, RID_IF)
8858 43 : && chain == NULL)
8859 : {
8860 : /* We've got "if (COND) else if (COND2)". Start the
8861 : condition chain and add COND as the first element. */
8862 18 : chain = new vec<tree> ();
8863 18 : if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8864 12 : chain->safe_push (cond);
8865 : }
8866 25 : else if (!c_parser_next_token_is_keyword (parser, RID_IF))
8867 : /* This is if-else without subsequent if. Zap the condition
8868 : chain; we would have already warned at this point. */
8869 4 : vec_free (chain);
8870 : }
8871 257214 : second_body = c_parser_else_body (parser, else_tinfo, chain);
8872 : /* Set IF_P to true to indicate that this if statement has an
8873 : else clause. This may trigger the Wparentheses warning
8874 : below when we get back up to the parent if statement. */
8875 257214 : if (if_p != NULL)
8876 289 : *if_p = true;
8877 : }
8878 : else
8879 : {
8880 1011549 : second_body = NULL_TREE;
8881 :
8882 : /* Diagnose an ambiguous else if if-then-else is nested inside
8883 : if-then. */
8884 1011549 : if (nested_if)
8885 215 : warning_at (loc, OPT_Wdangling_else,
8886 : "suggest explicit braces to avoid ambiguous %<else%>");
8887 :
8888 1011549 : if (warn_duplicated_cond)
8889 : /* This if statement does not have an else clause. We don't
8890 : need the condition chain anymore. */
8891 19 : vec_free (chain);
8892 : }
8893 1268763 : c_finish_if_stmt (loc, cond, first_body, second_body);
8894 1268763 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8895 :
8896 1268763 : c_parser_maybe_reclassify_token (parser);
8897 1268763 : }
8898 :
8899 : /* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8900 :
8901 : switch-statement:
8902 : switch (expression) statement
8903 :
8904 : BEFORE_LABELS is last statement before possible labels, see
8905 : get_before_labels description for details. */
8906 :
8907 : static void
8908 37243 : c_parser_switch_statement (c_parser *parser, bool *if_p, tree before_labels)
8909 : {
8910 37243 : struct c_expr ce;
8911 37243 : tree block, expr, body;
8912 37243 : unsigned char save_in_statement;
8913 37243 : location_t switch_loc = c_parser_peek_token (parser)->location;
8914 37243 : location_t switch_cond_loc;
8915 37243 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8916 37243 : c_parser_consume_token (parser);
8917 37243 : tree switch_name;
8918 37243 : int num_names = c_get_loop_names (before_labels, true, &switch_name);
8919 37243 : block = c_begin_compound_stmt (flag_isoc99);
8920 37243 : bool explicit_cast_p = false;
8921 37243 : matching_parens parens;
8922 37243 : if (parens.require_open (parser))
8923 : {
8924 37236 : switch_cond_loc = c_parser_peek_token (parser)->location;
8925 37236 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
8926 37236 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
8927 : explicit_cast_p = true;
8928 37236 : ce = c_parser_selection_header (parser, /*switch_p=*/true);
8929 : /* The call above already performed convert_lvalue_to_rvalue, but
8930 : if it parsed an expression, read_p was false. Make sure we mark
8931 : the expression as read. */
8932 37236 : ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8933 37236 : expr = ce.value;
8934 : /* ??? expr has no valid location? */
8935 37236 : parens.skip_until_found_close (parser);
8936 : }
8937 : else
8938 : {
8939 7 : switch_cond_loc = UNKNOWN_LOCATION;
8940 7 : expr = error_mark_node;
8941 7 : ce.original_type = error_mark_node;
8942 : }
8943 37243 : tree stmt
8944 37243 : = c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p,
8945 : switch_name);
8946 37243 : save_in_statement = in_statement;
8947 37243 : in_statement |= IN_SWITCH_STMT;
8948 37243 : if (switch_name)
8949 : {
8950 122 : C_DECL_LOOP_SWITCH_NAME_VALID (switch_name) = 1;
8951 122 : in_statement |= IN_NAMED_STMT;
8952 : }
8953 : else
8954 37121 : in_statement &= ~IN_NAMED_STMT;
8955 37243 : location_t loc_after_labels;
8956 37243 : bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8957 37243 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
8958 37243 : location_t next_loc = c_parser_peek_token (parser)->location;
8959 37243 : if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8960 385 : warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8961 : RID_SWITCH);
8962 37243 : c_finish_switch (body, ce.original_type);
8963 37243 : in_statement = save_in_statement;
8964 37243 : if (num_names)
8965 : {
8966 122 : if (!C_DECL_LOOP_SWITCH_NAME_USED (switch_name))
8967 110 : SWITCH_STMT_NAME (stmt) = NULL_TREE;
8968 : else
8969 12 : SWITCH_STMT_NO_BREAK_P (stmt) = 0;
8970 122 : c_release_loop_names (num_names);
8971 : }
8972 37243 : add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8973 37243 : c_parser_maybe_reclassify_token (parser);
8974 37243 : }
8975 :
8976 : /* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8977 :
8978 : while-statement:
8979 : while (expression) statement
8980 :
8981 : IF_P is used to track whether there's a (possibly labeled) if statement
8982 : which is not enclosed in braces and has an else clause. This is used to
8983 : implement -Wparentheses.
8984 :
8985 : BEFORE_LABELS is last statement before possible labels, see
8986 : get_before_labels description for details. */
8987 :
8988 : static void
8989 44430 : c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8990 : bool novector, bool *if_p, tree before_labels)
8991 : {
8992 44430 : tree block, cond, body;
8993 44430 : unsigned char save_in_statement;
8994 44430 : location_t loc;
8995 44430 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8996 44430 : token_indent_info while_tinfo
8997 44430 : = get_token_indent_info (c_parser_peek_token (parser));
8998 44430 : tree loop_name;
8999 44430 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
9000 :
9001 44430 : if (parser->omp_for_parse_state)
9002 : {
9003 1 : error_at (c_parser_peek_token (parser)->location,
9004 : "loop not permitted in intervening code in OpenMP loop body");
9005 1 : parser->omp_for_parse_state->fail = true;
9006 : }
9007 :
9008 44430 : c_parser_consume_token (parser);
9009 44430 : block = c_begin_compound_stmt (flag_isoc99);
9010 44430 : loc = c_parser_peek_token (parser)->location;
9011 44430 : cond = c_parser_paren_condition (parser);
9012 44430 : if (ivdep && cond != error_mark_node)
9013 3 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9014 : build_int_cst (integer_type_node,
9015 : annot_expr_ivdep_kind),
9016 : integer_zero_node);
9017 44430 : if (unroll && cond != error_mark_node)
9018 6 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9019 : build_int_cst (integer_type_node,
9020 : annot_expr_unroll_kind),
9021 6 : build_int_cst (integer_type_node, unroll));
9022 44430 : if (novector && cond != error_mark_node)
9023 6 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9024 : build_int_cst (integer_type_node,
9025 : annot_expr_no_vector_kind),
9026 : integer_zero_node);
9027 44430 : save_in_statement = in_statement;
9028 44430 : in_statement = IN_ITERATION_STMT;
9029 44430 : if (loop_name)
9030 : {
9031 135 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9032 135 : in_statement |= IN_NAMED_STMT;
9033 : }
9034 :
9035 44430 : token_indent_info body_tinfo
9036 44430 : = get_token_indent_info (c_parser_peek_token (parser));
9037 :
9038 44430 : location_t loc_after_labels;
9039 44430 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
9040 44430 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
9041 44430 : if (loop_name && !C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
9042 133 : loop_name = NULL_TREE;
9043 44430 : add_stmt (build_stmt (loc, WHILE_STMT, cond, body, loop_name, NULL_TREE,
9044 : NULL_TREE));
9045 44430 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
9046 44430 : c_parser_maybe_reclassify_token (parser);
9047 44430 : if (num_names)
9048 135 : c_release_loop_names (num_names);
9049 :
9050 44430 : token_indent_info next_tinfo
9051 44430 : = get_token_indent_info (c_parser_peek_token (parser));
9052 44430 : warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
9053 :
9054 44430 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9055 10638 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9056 : while_tinfo.location, RID_WHILE);
9057 :
9058 44430 : in_statement = save_in_statement;
9059 44430 : }
9060 :
9061 : /* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
9062 :
9063 : do-statement:
9064 : do statement while ( expression ) ;
9065 :
9066 : BEFORE_LABELS is last statement before possible labels, see
9067 : get_before_labels description for details. */
9068 :
9069 : static void
9070 145320 : c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9071 : bool novector, tree before_labels)
9072 : {
9073 145320 : tree block, cond, body;
9074 145320 : unsigned char save_in_statement;
9075 145320 : location_t loc;
9076 145320 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
9077 145320 : tree loop_name;
9078 145320 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
9079 :
9080 145320 : if (parser->omp_for_parse_state)
9081 : {
9082 1 : error_at (c_parser_peek_token (parser)->location,
9083 : "loop not permitted in intervening code in OpenMP loop body");
9084 1 : parser->omp_for_parse_state->fail = true;
9085 : }
9086 :
9087 145320 : c_parser_consume_token (parser);
9088 145320 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9089 50 : warning_at (c_parser_peek_token (parser)->location,
9090 50 : OPT_Wempty_body,
9091 : "suggest braces around empty body in %<do%> statement");
9092 145320 : block = c_begin_compound_stmt (flag_isoc99);
9093 145320 : loc = c_parser_peek_token (parser)->location;
9094 145320 : save_in_statement = in_statement;
9095 145320 : in_statement = IN_ITERATION_STMT;
9096 145320 : if (loop_name)
9097 : {
9098 176 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9099 176 : in_statement |= IN_NAMED_STMT;
9100 : }
9101 145320 : body = c_parser_c99_block_statement (parser, NULL);
9102 145320 : c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
9103 145320 : in_statement = save_in_statement;
9104 145320 : if (num_names)
9105 : {
9106 176 : if (!C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
9107 174 : loop_name = NULL_TREE;
9108 176 : c_release_loop_names (num_names);
9109 : }
9110 145320 : cond = c_parser_paren_condition (parser);
9111 145320 : if (ivdep && cond != error_mark_node)
9112 2 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9113 : build_int_cst (integer_type_node,
9114 : annot_expr_ivdep_kind),
9115 : integer_zero_node);
9116 145320 : if (unroll && cond != error_mark_node)
9117 3 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9118 : build_int_cst (integer_type_node,
9119 : annot_expr_unroll_kind),
9120 3 : build_int_cst (integer_type_node, unroll));
9121 145320 : if (novector && cond != error_mark_node)
9122 54 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9123 : build_int_cst (integer_type_node,
9124 : annot_expr_no_vector_kind),
9125 : integer_zero_node);
9126 145320 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
9127 0 : c_parser_skip_to_end_of_block_or_statement (parser);
9128 :
9129 145320 : add_stmt (build_stmt (loc, DO_STMT, cond, body, loop_name));
9130 145320 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
9131 145320 : }
9132 :
9133 : /* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
9134 :
9135 : for-statement:
9136 : for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
9137 : for ( nested-declaration expression[opt] ; expression[opt] ) statement
9138 :
9139 : The form with a declaration is new in C99.
9140 :
9141 : ??? In accordance with the old parser, the declaration may be a
9142 : nested function, which is then rejected in check_for_loop_decls,
9143 : but does it make any sense for this to be included in the grammar?
9144 : Note in particular that the nested function does not include a
9145 : trailing ';', whereas the "declaration" production includes one.
9146 : Also, can we reject bad declarations earlier and cheaper than
9147 : check_for_loop_decls?
9148 :
9149 : In Objective-C, there are two additional variants:
9150 :
9151 : foreach-statement:
9152 : for ( expression in expresssion ) statement
9153 : for ( declaration in expression ) statement
9154 :
9155 : This is inconsistent with C, because the second variant is allowed
9156 : even if c99 is not enabled.
9157 :
9158 : The rest of the comment documents these Objective-C foreach-statement.
9159 :
9160 : Here is the canonical example of the first variant:
9161 : for (object in array) { do something with object }
9162 : we call the first expression ("object") the "object_expression" and
9163 : the second expression ("array") the "collection_expression".
9164 : object_expression must be an lvalue of type "id" (a generic Objective-C
9165 : object) because the loop works by assigning to object_expression the
9166 : various objects from the collection_expression. collection_expression
9167 : must evaluate to something of type "id" which responds to the method
9168 : countByEnumeratingWithState:objects:count:.
9169 :
9170 : The canonical example of the second variant is:
9171 : for (id object in array) { do something with object }
9172 : which is completely equivalent to
9173 : {
9174 : id object;
9175 : for (object in array) { do something with object }
9176 : }
9177 : Note that initizializing 'object' in some way (eg, "for ((object =
9178 : xxx) in array) { do something with object }") is possibly
9179 : technically valid, but completely pointless as 'object' will be
9180 : assigned to something else as soon as the loop starts. We should
9181 : most likely reject it (TODO).
9182 :
9183 : The beginning of the Objective-C foreach-statement looks exactly
9184 : like the beginning of the for-statement, and we can tell it is a
9185 : foreach-statement only because the initial declaration or
9186 : expression is terminated by 'in' instead of ';'.
9187 :
9188 : IF_P is used to track whether there's a (possibly labeled) if statement
9189 : which is not enclosed in braces and has an else clause. This is used to
9190 : implement -Wparentheses.
9191 :
9192 : BEFORE_LABELS is last statement before possible labels, see
9193 : get_before_labels description for details. */
9194 :
9195 : static void
9196 284798 : c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9197 : bool novector, bool *if_p, tree before_labels)
9198 : {
9199 284798 : tree block, cond, incr, body;
9200 284798 : unsigned char save_in_statement;
9201 284798 : tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
9202 : /* The following are only used when parsing an ObjC foreach statement. */
9203 284798 : tree object_expression;
9204 : /* Silence the bogus uninitialized warning. */
9205 284798 : tree collection_expression = NULL;
9206 284798 : location_t loc = c_parser_peek_token (parser)->location;
9207 284798 : location_t for_loc = loc;
9208 284798 : bool is_foreach_statement = false;
9209 284798 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
9210 284798 : token_indent_info for_tinfo
9211 284798 : = get_token_indent_info (c_parser_peek_token (parser));
9212 284798 : tree loop_name;
9213 284798 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
9214 :
9215 284798 : if (parser->omp_for_parse_state)
9216 : {
9217 13 : error_at (for_loc,
9218 : "loop not permitted in intervening code in OpenMP loop body");
9219 13 : parser->omp_for_parse_state->fail = true;
9220 : }
9221 :
9222 284798 : c_parser_consume_token (parser);
9223 : /* Open a compound statement in Objective-C as well, just in case this is
9224 : as foreach expression. */
9225 568709 : block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
9226 284798 : cond = error_mark_node;
9227 284798 : incr = error_mark_node;
9228 284798 : matching_parens parens;
9229 284798 : if (parens.require_open (parser))
9230 : {
9231 : /* Parse the initialization declaration or expression. */
9232 284797 : object_expression = error_mark_node;
9233 284797 : parser->objc_could_be_foreach_context = c_dialect_objc ();
9234 284797 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9235 : {
9236 12484 : parser->objc_could_be_foreach_context = false;
9237 12484 : c_parser_consume_token (parser);
9238 12484 : c_finish_expr_stmt (loc, NULL_TREE);
9239 : }
9240 272313 : else if (c_parser_next_tokens_start_declaration (parser)
9241 272313 : || c_parser_nth_token_starts_std_attributes (parser, 1))
9242 : {
9243 20995 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
9244 : false, &object_expression);
9245 20995 : parser->objc_could_be_foreach_context = false;
9246 :
9247 20995 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9248 : {
9249 0 : c_parser_consume_token (parser);
9250 0 : is_foreach_statement = true;
9251 0 : if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9252 0 : c_parser_error (parser, "multiple iterating variables in "
9253 : "fast enumeration");
9254 : }
9255 : else
9256 20995 : check_for_loop_decls (for_loc, flag_isoc99);
9257 : }
9258 251318 : else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
9259 : {
9260 : /* __extension__ can start a declaration, but is also an
9261 : unary operator that can start an expression. Consume all
9262 : but the last of a possible series of __extension__ to
9263 : determine which. */
9264 0 : while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
9265 0 : && (c_parser_peek_2nd_token (parser)->keyword
9266 : == RID_EXTENSION))
9267 0 : c_parser_consume_token (parser);
9268 0 : if (c_parser_next_tokens_start_declaration (parser, 2)
9269 0 : || c_parser_nth_token_starts_std_attributes (parser, 2))
9270 : {
9271 0 : int ext;
9272 0 : ext = disable_extension_diagnostics ();
9273 0 : c_parser_consume_token (parser);
9274 0 : c_parser_declaration_or_fndef (parser, true, true, true, true,
9275 : true, false, &object_expression);
9276 0 : parser->objc_could_be_foreach_context = false;
9277 :
9278 0 : restore_extension_diagnostics (ext);
9279 0 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9280 : {
9281 0 : c_parser_consume_token (parser);
9282 0 : is_foreach_statement = true;
9283 0 : if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9284 0 : c_parser_error (parser, "multiple iterating variables in "
9285 : "fast enumeration");
9286 : }
9287 : else
9288 0 : check_for_loop_decls (for_loc, flag_isoc99);
9289 : }
9290 : else
9291 0 : goto init_expr;
9292 : }
9293 : else
9294 : {
9295 251318 : init_expr:
9296 251318 : {
9297 251318 : struct c_expr ce;
9298 251318 : tree init_expression;
9299 251318 : ce = c_parser_expression (parser);
9300 251318 : init_expression = ce.value;
9301 251318 : parser->objc_could_be_foreach_context = false;
9302 251318 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9303 : {
9304 0 : c_parser_consume_token (parser);
9305 0 : is_foreach_statement = true;
9306 0 : if (! lvalue_p (init_expression))
9307 0 : c_parser_error (parser, "invalid iterating variable in "
9308 : "fast enumeration");
9309 0 : object_expression
9310 0 : = c_fully_fold (init_expression, false, NULL);
9311 : }
9312 : else
9313 : {
9314 251318 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9315 251318 : init_expression = ce.value;
9316 251318 : c_finish_expr_stmt (loc, init_expression);
9317 251318 : c_parser_skip_until_found (parser, CPP_SEMICOLON,
9318 : "expected %<;%>");
9319 : }
9320 : }
9321 : }
9322 : /* Parse the loop condition. In the case of a foreach
9323 : statement, there is no loop condition. */
9324 284797 : gcc_assert (!parser->objc_could_be_foreach_context);
9325 284797 : if (!is_foreach_statement)
9326 : {
9327 284797 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9328 : {
9329 3137 : if (ivdep)
9330 : {
9331 1 : c_parser_error (parser, "missing loop condition in loop "
9332 : "with %<GCC ivdep%> pragma");
9333 1 : cond = error_mark_node;
9334 : }
9335 3136 : else if (unroll)
9336 : {
9337 0 : c_parser_error (parser, "missing loop condition in loop "
9338 : "with %<GCC unroll%> pragma");
9339 0 : cond = error_mark_node;
9340 : }
9341 : else
9342 : {
9343 3136 : c_parser_consume_token (parser);
9344 3136 : cond = NULL_TREE;
9345 : }
9346 : }
9347 : else
9348 : {
9349 281660 : cond = c_parser_condition (parser);
9350 281660 : c_parser_skip_until_found (parser, CPP_SEMICOLON,
9351 : "expected %<;%>");
9352 : }
9353 284797 : if (ivdep && cond != error_mark_node)
9354 122 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9355 : build_int_cst (integer_type_node,
9356 : annot_expr_ivdep_kind),
9357 : integer_zero_node);
9358 284797 : if (unroll && cond != error_mark_node)
9359 275 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9360 : build_int_cst (integer_type_node,
9361 : annot_expr_unroll_kind),
9362 275 : build_int_cst (integer_type_node, unroll));
9363 284797 : if (novector && cond && cond != error_mark_node)
9364 2850 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9365 : build_int_cst (integer_type_node,
9366 : annot_expr_no_vector_kind),
9367 : integer_zero_node);
9368 : }
9369 : /* Parse the increment expression (the third expression in a
9370 : for-statement). In the case of a foreach-statement, this is
9371 : the expression that follows the 'in'. */
9372 284797 : loc = c_parser_peek_token (parser)->location;
9373 284797 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9374 : {
9375 4323 : if (is_foreach_statement)
9376 : {
9377 0 : c_parser_error (parser,
9378 : "missing collection in fast enumeration");
9379 0 : collection_expression = error_mark_node;
9380 : }
9381 : else
9382 4323 : incr = c_process_expr_stmt (loc, NULL_TREE);
9383 : }
9384 : else
9385 : {
9386 280474 : if (is_foreach_statement)
9387 0 : collection_expression
9388 0 : = c_fully_fold (c_parser_expression (parser).value, false, NULL);
9389 : else
9390 : {
9391 280474 : struct c_expr ce = c_parser_expression (parser);
9392 280474 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9393 280474 : incr = c_process_expr_stmt (loc, ce.value);
9394 : }
9395 : }
9396 284797 : parens.skip_until_found_close (parser);
9397 : }
9398 284798 : save_in_statement = in_statement;
9399 284798 : if (is_foreach_statement)
9400 : {
9401 0 : in_statement = IN_OBJC_FOREACH;
9402 0 : save_objc_foreach_break_label = objc_foreach_break_label;
9403 0 : save_objc_foreach_continue_label = objc_foreach_continue_label;
9404 0 : objc_foreach_break_label = create_artificial_label (loc);
9405 0 : objc_foreach_continue_label = create_artificial_label (loc);
9406 0 : if (loop_name)
9407 : {
9408 0 : gcc_checking_assert (!DECL_CHAIN (loop_name)
9409 : && !DECL_CHAIN (objc_foreach_break_label));
9410 0 : C_DECL_SWITCH_NAME (loop_name) = 1;
9411 0 : DECL_CHAIN (loop_name) = objc_foreach_break_label;
9412 0 : DECL_CHAIN (objc_foreach_break_label) = objc_foreach_continue_label;
9413 : }
9414 : }
9415 : else
9416 284798 : in_statement = IN_ITERATION_STMT;
9417 284798 : if (loop_name)
9418 : {
9419 460 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9420 460 : in_statement |= IN_NAMED_STMT;
9421 : }
9422 :
9423 284798 : token_indent_info body_tinfo
9424 284798 : = get_token_indent_info (c_parser_peek_token (parser));
9425 :
9426 284798 : location_t loc_after_labels;
9427 284798 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
9428 284798 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
9429 :
9430 284798 : if (loop_name && is_foreach_statement)
9431 : {
9432 0 : gcc_checking_assert (DECL_CHAIN (loop_name) == objc_foreach_break_label
9433 : && (DECL_CHAIN (objc_foreach_break_label)
9434 : == objc_foreach_continue_label));
9435 0 : C_DECL_SWITCH_NAME (loop_name) = 0;
9436 0 : DECL_CHAIN (loop_name) = NULL_TREE;
9437 0 : DECL_CHAIN (objc_foreach_break_label) = NULL_TREE;
9438 : }
9439 :
9440 284338 : if (is_foreach_statement)
9441 0 : objc_finish_foreach_loop (for_loc, object_expression,
9442 : collection_expression, body,
9443 : objc_foreach_break_label,
9444 : objc_foreach_continue_label);
9445 : else
9446 569596 : add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
9447 : body, NULL_TREE,
9448 460 : loop_name && C_DECL_LOOP_SWITCH_NAME_USED (loop_name)
9449 : ? loop_name : NULL_TREE, NULL_TREE, NULL_TREE));
9450 284798 : add_stmt (c_end_compound_stmt (for_loc, block,
9451 284798 : flag_isoc99 || c_dialect_objc ()));
9452 284798 : c_parser_maybe_reclassify_token (parser);
9453 :
9454 284798 : token_indent_info next_tinfo
9455 284798 : = get_token_indent_info (c_parser_peek_token (parser));
9456 284798 : warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
9457 :
9458 284798 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9459 167782 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9460 : for_tinfo.location, RID_FOR);
9461 :
9462 284798 : in_statement = save_in_statement;
9463 284798 : if (num_names)
9464 460 : c_release_loop_names (num_names);
9465 284798 : if (is_foreach_statement)
9466 : {
9467 0 : objc_foreach_break_label = save_objc_foreach_break_label;
9468 0 : objc_foreach_continue_label = save_objc_foreach_continue_label;
9469 : }
9470 284798 : }
9471 :
9472 : /* Parse an asm statement, a GNU extension. This is a full-blown asm
9473 : statement with inputs, outputs, clobbers, and volatile, inline, and goto
9474 : tags allowed.
9475 :
9476 : asm-qualifier:
9477 : volatile
9478 : inline
9479 : goto
9480 :
9481 : asm-qualifier-list:
9482 : asm-qualifier-list asm-qualifier
9483 : asm-qualifier
9484 :
9485 : asm-statement:
9486 : asm asm-qualifier-list[opt] ( asm-argument ) ;
9487 :
9488 : asm-argument:
9489 : asm-string-literal
9490 : asm-string-literal : asm-operands[opt]
9491 : asm-string-literal : asm-operands[opt] : asm-operands[opt]
9492 : asm-string-literal : asm-operands[opt] : asm-operands[opt] \
9493 : : asm-clobbers[opt]
9494 : asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
9495 : : asm-goto-operands
9496 :
9497 : The form with asm-goto-operands is valid if and only if the
9498 : asm-qualifier-list contains goto, and is the only allowed form in that case.
9499 : Duplicate asm-qualifiers are not allowed.
9500 :
9501 : The :: token is considered equivalent to two consecutive : tokens. */
9502 :
9503 : static tree
9504 204806 : c_parser_asm_statement (c_parser *parser)
9505 : {
9506 204806 : tree str, outputs, inputs, clobbers, labels, ret;
9507 204806 : bool simple;
9508 204806 : location_t asm_loc = c_parser_peek_token (parser)->location;
9509 204806 : int section, nsections;
9510 :
9511 204806 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
9512 204806 : c_parser_consume_token (parser);
9513 :
9514 : /* Handle the asm-qualifier-list. */
9515 204806 : location_t volatile_loc = UNKNOWN_LOCATION;
9516 204806 : location_t inline_loc = UNKNOWN_LOCATION;
9517 204806 : location_t goto_loc = UNKNOWN_LOCATION;
9518 370321 : for (;;)
9519 : {
9520 370321 : c_token *token = c_parser_peek_token (parser);
9521 370321 : location_t loc = token->location;
9522 370321 : switch (token->keyword)
9523 : {
9524 164991 : case RID_VOLATILE:
9525 164991 : if (volatile_loc)
9526 : {
9527 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9528 6 : inform (volatile_loc, "first seen here");
9529 : }
9530 : else
9531 : volatile_loc = loc;
9532 164991 : c_parser_consume_token (parser);
9533 164991 : continue;
9534 :
9535 38 : case RID_INLINE:
9536 38 : if (inline_loc)
9537 : {
9538 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9539 6 : inform (inline_loc, "first seen here");
9540 : }
9541 : else
9542 : inline_loc = loc;
9543 38 : c_parser_consume_token (parser);
9544 38 : continue;
9545 :
9546 484 : case RID_GOTO:
9547 484 : if (goto_loc)
9548 : {
9549 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9550 6 : inform (goto_loc, "first seen here");
9551 : }
9552 : else
9553 : goto_loc = loc;
9554 484 : c_parser_consume_token (parser);
9555 484 : continue;
9556 :
9557 2 : case RID_CONST:
9558 2 : case RID_RESTRICT:
9559 2 : error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
9560 2 : c_parser_consume_token (parser);
9561 2 : continue;
9562 :
9563 204806 : default:
9564 204806 : break;
9565 : }
9566 204806 : break;
9567 : }
9568 :
9569 204806 : bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
9570 204806 : bool is_inline = (inline_loc != UNKNOWN_LOCATION);
9571 204806 : bool is_goto = (goto_loc != UNKNOWN_LOCATION);
9572 :
9573 204806 : ret = NULL;
9574 :
9575 204806 : matching_parens parens;
9576 204806 : if (!parens.require_open (parser))
9577 0 : goto error;
9578 :
9579 204806 : str = c_parser_asm_string_literal (parser);
9580 204806 : if (str == NULL_TREE)
9581 12 : goto error_close_paren;
9582 :
9583 204794 : simple = true;
9584 204794 : outputs = NULL_TREE;
9585 204794 : inputs = NULL_TREE;
9586 204794 : clobbers = NULL_TREE;
9587 204794 : labels = NULL_TREE;
9588 :
9589 204794 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9590 1861 : goto done_asm;
9591 :
9592 : /* Parse each colon-delimited section of operands. */
9593 202933 : nsections = 3 + is_goto;
9594 518188 : for (section = 0; section < nsections; ++section)
9595 : {
9596 517720 : if (c_parser_next_token_is (parser, CPP_SCOPE))
9597 : {
9598 35612 : ++section;
9599 35612 : if (section == nsections)
9600 : {
9601 5 : c_parser_error (parser, "expected %<)%>");
9602 5 : goto error_close_paren;
9603 : }
9604 35607 : c_parser_consume_token (parser);
9605 : }
9606 962612 : else if (!c_parser_require (parser, CPP_COLON,
9607 : is_goto
9608 : ? G_("expected %<:%>")
9609 : : G_("expected %<:%> or %<)%>"),
9610 : UNKNOWN_LOCATION, is_goto))
9611 7 : goto error_close_paren;
9612 :
9613 : /* Once past any colon, we're no longer a simple asm. */
9614 517708 : simple = false;
9615 :
9616 517708 : if ((!c_parser_next_token_is (parser, CPP_COLON)
9617 421286 : && !c_parser_next_token_is (parser, CPP_SCOPE)
9618 421216 : && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9619 522646 : || section == 3)
9620 416349 : switch (section)
9621 : {
9622 132392 : case 0:
9623 132392 : outputs = c_parser_asm_operands (parser);
9624 132392 : break;
9625 131837 : case 1:
9626 131837 : inputs = c_parser_asm_operands (parser);
9627 131837 : break;
9628 151652 : case 2:
9629 151652 : clobbers = c_parser_asm_clobbers (parser);
9630 151652 : break;
9631 468 : case 3:
9632 468 : labels = c_parser_asm_goto_operands (parser);
9633 468 : break;
9634 0 : default:
9635 0 : gcc_unreachable ();
9636 : }
9637 :
9638 517708 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9639 202453 : goto done_asm;
9640 : }
9641 :
9642 468 : done_asm:
9643 204782 : if (!parens.require_close (parser))
9644 : {
9645 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9646 0 : goto error;
9647 : }
9648 :
9649 204782 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
9650 0 : c_parser_skip_to_end_of_block_or_statement (parser);
9651 :
9652 204782 : ret = build_asm_stmt (is_volatile,
9653 : build_asm_expr (asm_loc, str, outputs, inputs,
9654 : clobbers, labels, simple, is_inline));
9655 :
9656 204806 : error:
9657 204806 : return ret;
9658 :
9659 24 : error_close_paren:
9660 24 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9661 24 : goto error;
9662 : }
9663 :
9664 : /* Parse asm operands, a GNU extension.
9665 :
9666 : asm-operands:
9667 : asm-operand
9668 : asm-operands , asm-operand
9669 :
9670 : asm-operand:
9671 : asm-string-literal ( expression )
9672 : [ identifier ] asm-string-literal ( expression )
9673 : */
9674 :
9675 : static tree
9676 264285 : c_parser_asm_operands (c_parser *parser)
9677 : {
9678 264285 : tree list = NULL_TREE;
9679 1161387 : while (true)
9680 : {
9681 712836 : tree name, str;
9682 712836 : struct c_expr expr;
9683 712836 : if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
9684 : {
9685 730 : c_parser_consume_token (parser);
9686 730 : if (c_parser_next_token_is (parser, CPP_NAME))
9687 : {
9688 730 : tree id = c_parser_peek_token (parser)->value;
9689 730 : c_parser_consume_token (parser);
9690 730 : name = build_string (IDENTIFIER_LENGTH (id),
9691 730 : IDENTIFIER_POINTER (id));
9692 : }
9693 : else
9694 : {
9695 0 : c_parser_error (parser, "expected identifier");
9696 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
9697 0 : return NULL_TREE;
9698 : }
9699 730 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
9700 : "expected %<]%>");
9701 : }
9702 : else
9703 : name = NULL_TREE;
9704 712836 : str = c_parser_asm_string_literal (parser);
9705 712836 : if (str == NULL_TREE)
9706 : return NULL_TREE;
9707 712836 : matching_parens parens;
9708 712836 : if (!parens.require_open (parser))
9709 : return NULL_TREE;
9710 712836 : expr = c_parser_expression (parser);
9711 712836 : mark_exp_read (expr.value);
9712 712836 : if (!parens.require_close (parser))
9713 : {
9714 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9715 0 : return NULL_TREE;
9716 : }
9717 712836 : list = chainon (list, build_tree_list (build_tree_list (name, str),
9718 : expr.value));
9719 712836 : if (c_parser_next_token_is (parser, CPP_COMMA))
9720 448551 : c_parser_consume_token (parser);
9721 : else
9722 : break;
9723 448551 : }
9724 264285 : return list;
9725 : }
9726 :
9727 : /* Parse asm clobbers, a GNU extension.
9728 :
9729 : asm-clobbers:
9730 : asm-string-literal
9731 : asm-clobbers , asm-string-literal
9732 : */
9733 :
9734 : static tree
9735 151652 : c_parser_asm_clobbers (c_parser *parser)
9736 : {
9737 151652 : tree list = NULL_TREE;
9738 205678 : while (true)
9739 : {
9740 178665 : tree str = c_parser_asm_string_literal (parser);
9741 178665 : if (str)
9742 178665 : list = tree_cons (NULL_TREE, str, list);
9743 : else
9744 : return NULL_TREE;
9745 178665 : if (c_parser_next_token_is (parser, CPP_COMMA))
9746 27013 : c_parser_consume_token (parser);
9747 : else
9748 : break;
9749 27013 : }
9750 : return list;
9751 : }
9752 :
9753 : /* Parse asm goto labels, a GNU extension.
9754 :
9755 : asm-goto-operands:
9756 : identifier
9757 : asm-goto-operands , identifier
9758 : */
9759 :
9760 : static tree
9761 468 : c_parser_asm_goto_operands (c_parser *parser)
9762 : {
9763 468 : tree list = NULL_TREE;
9764 1104 : while (true)
9765 : {
9766 786 : tree name, label;
9767 :
9768 786 : if (c_parser_next_token_is (parser, CPP_NAME))
9769 : {
9770 785 : c_token *tok = c_parser_peek_token (parser);
9771 785 : name = tok->value;
9772 785 : label = lookup_label_for_goto (tok->location, name);
9773 785 : c_parser_consume_token (parser);
9774 785 : TREE_USED (label) = 1;
9775 : }
9776 : else
9777 : {
9778 1 : c_parser_error (parser, "expected identifier");
9779 1 : return NULL_TREE;
9780 : }
9781 :
9782 785 : name = build_string (IDENTIFIER_LENGTH (name),
9783 785 : IDENTIFIER_POINTER (name));
9784 785 : list = tree_cons (name, label, list);
9785 785 : if (c_parser_next_token_is (parser, CPP_COMMA))
9786 318 : c_parser_consume_token (parser);
9787 : else
9788 467 : return nreverse (list);
9789 318 : }
9790 : }
9791 :
9792 : /* Parse a possibly concatenated sequence of string literals.
9793 : TRANSLATE says whether to translate them to the execution character
9794 : set; WIDE_OK says whether any kind of prefixed string literal is
9795 : permitted in this context. This code is based on that in
9796 : lex_string. */
9797 :
9798 : struct c_expr
9799 3769007 : c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
9800 : {
9801 3769007 : struct c_expr ret;
9802 3769007 : size_t count;
9803 3769007 : struct obstack str_ob;
9804 3769007 : struct obstack loc_ob;
9805 3769007 : cpp_string str, istr, *strs;
9806 3769007 : c_token *tok;
9807 3769007 : location_t loc, last_tok_loc;
9808 3769007 : enum cpp_ttype type;
9809 3769007 : tree value, string_tree;
9810 :
9811 3769007 : tok = c_parser_peek_token (parser);
9812 3769007 : loc = tok->location;
9813 3769007 : last_tok_loc = linemap_resolve_location (line_table, loc,
9814 : LRK_MACRO_DEFINITION_LOCATION,
9815 : NULL);
9816 3769007 : type = tok->type;
9817 3769007 : switch (type)
9818 : {
9819 3768990 : case CPP_STRING:
9820 3768990 : case CPP_WSTRING:
9821 3768990 : case CPP_STRING16:
9822 3768990 : case CPP_STRING32:
9823 3768990 : case CPP_UTF8STRING:
9824 3768990 : string_tree = tok->value;
9825 3768990 : break;
9826 :
9827 17 : default:
9828 17 : c_parser_error (parser, "expected string literal");
9829 17 : ret.set_error ();
9830 17 : ret.value = NULL_TREE;
9831 17 : ret.original_code = ERROR_MARK;
9832 17 : ret.original_type = NULL_TREE;
9833 17 : return ret;
9834 : }
9835 :
9836 : /* Try to avoid the overhead of creating and destroying an obstack
9837 : for the common case of just one string. */
9838 3768990 : switch (c_parser_peek_2nd_token (parser)->type)
9839 : {
9840 2888088 : default:
9841 2888088 : c_parser_consume_token (parser);
9842 2888088 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9843 2888088 : str.len = TREE_STRING_LENGTH (string_tree);
9844 2888088 : count = 1;
9845 2888088 : strs = &str;
9846 2888088 : break;
9847 :
9848 880902 : case CPP_STRING:
9849 880902 : case CPP_WSTRING:
9850 880902 : case CPP_STRING16:
9851 880902 : case CPP_STRING32:
9852 880902 : case CPP_UTF8STRING:
9853 880902 : gcc_obstack_init (&str_ob);
9854 880902 : gcc_obstack_init (&loc_ob);
9855 880902 : count = 0;
9856 27871769 : do
9857 : {
9858 27871769 : c_parser_consume_token (parser);
9859 27871769 : count++;
9860 27871769 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9861 27871769 : str.len = TREE_STRING_LENGTH (string_tree);
9862 27871769 : if (type != tok->type)
9863 : {
9864 669 : if (type == CPP_STRING)
9865 29 : type = tok->type;
9866 640 : else if (tok->type != CPP_STRING)
9867 66 : error ("unsupported non-standard concatenation "
9868 : "of string literals");
9869 : }
9870 27871769 : obstack_grow (&str_ob, &str, sizeof (cpp_string));
9871 27871769 : obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
9872 27871769 : tok = c_parser_peek_token (parser);
9873 27871769 : string_tree = tok->value;
9874 27871769 : last_tok_loc
9875 27871769 : = linemap_resolve_location (line_table, tok->location,
9876 : LRK_MACRO_DEFINITION_LOCATION, NULL);
9877 : }
9878 27871769 : while (tok->type == CPP_STRING
9879 : || tok->type == CPP_WSTRING
9880 : || tok->type == CPP_STRING16
9881 : || tok->type == CPP_STRING32
9882 27871769 : || tok->type == CPP_UTF8STRING);
9883 880902 : strs = (cpp_string *) obstack_finish (&str_ob);
9884 : }
9885 :
9886 3768990 : if (count > 1 && !in_system_header_at (input_location))
9887 658717 : warning (OPT_Wtraditional,
9888 : "traditional C rejects string constant concatenation");
9889 :
9890 3768990 : if ((type == CPP_STRING || wide_ok)
9891 7537970 : && ((translate
9892 3768980 : ? cpp_interpret_string : cpp_interpret_string_notranslate)
9893 3768980 : (parse_in, strs, count, &istr, type)))
9894 : {
9895 3768980 : value = build_string (istr.len, (const char *) istr.text);
9896 3768980 : free (const_cast<unsigned char *> (istr.text));
9897 3768980 : if (count > 1)
9898 : {
9899 880902 : location_t *locs = (location_t *) obstack_finish (&loc_ob);
9900 880902 : gcc_assert (g_string_concat_db);
9901 880902 : g_string_concat_db->record_string_concatenation (count, locs);
9902 : }
9903 : }
9904 : else
9905 : {
9906 10 : if (type != CPP_STRING && !wide_ok)
9907 : {
9908 10 : error_at (loc, "a wide string is invalid in this context");
9909 10 : type = CPP_STRING;
9910 : }
9911 : /* Callers cannot generally handle error_mark_node in this
9912 : context, so return the empty string instead. An error has
9913 : been issued, either above or from cpp_interpret_string. */
9914 10 : switch (type)
9915 : {
9916 10 : default:
9917 10 : case CPP_STRING:
9918 10 : case CPP_UTF8STRING:
9919 10 : if (type == CPP_UTF8STRING && flag_char8_t)
9920 : {
9921 0 : value = build_string (TYPE_PRECISION (char8_type_node)
9922 0 : / TYPE_PRECISION (char_type_node),
9923 : ""); /* char8_t is 8 bits */
9924 : }
9925 : else
9926 10 : value = build_string (1, "");
9927 : break;
9928 0 : case CPP_STRING16:
9929 0 : value = build_string (TYPE_PRECISION (char16_type_node)
9930 0 : / TYPE_PRECISION (char_type_node),
9931 : "\0"); /* char16_t is 16 bits */
9932 0 : break;
9933 0 : case CPP_STRING32:
9934 0 : value = build_string (TYPE_PRECISION (char32_type_node)
9935 0 : / TYPE_PRECISION (char_type_node),
9936 : "\0\0\0"); /* char32_t is 32 bits */
9937 0 : break;
9938 0 : case CPP_WSTRING:
9939 0 : value = build_string (TYPE_PRECISION (wchar_type_node)
9940 0 : / TYPE_PRECISION (char_type_node),
9941 : "\0\0\0"); /* widest supported wchar_t
9942 : is 32 bits */
9943 0 : break;
9944 : }
9945 : }
9946 :
9947 3768990 : switch (type)
9948 : {
9949 3765680 : default:
9950 3765680 : case CPP_STRING:
9951 3765680 : TREE_TYPE (value) = char_array_type_node;
9952 3765680 : break;
9953 264 : case CPP_UTF8STRING:
9954 264 : if (flag_char8_t)
9955 82 : TREE_TYPE (value) = char8_array_type_node;
9956 : else
9957 182 : TREE_TYPE (value) = char_array_type_node;
9958 : break;
9959 229 : case CPP_STRING16:
9960 229 : TREE_TYPE (value) = char16_array_type_node;
9961 229 : break;
9962 2292 : case CPP_STRING32:
9963 2292 : TREE_TYPE (value) = char32_array_type_node;
9964 2292 : break;
9965 525 : case CPP_WSTRING:
9966 525 : TREE_TYPE (value) = wchar_array_type_node;
9967 : }
9968 3768990 : value = fix_string_type (value);
9969 :
9970 3768990 : if (count > 1)
9971 : {
9972 880902 : obstack_free (&str_ob, 0);
9973 880902 : obstack_free (&loc_ob, 0);
9974 : }
9975 :
9976 3768990 : ret.value = value;
9977 3768990 : ret.original_code = STRING_CST;
9978 3768990 : ret.original_type = NULL_TREE;
9979 3768990 : set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc));
9980 3768990 : ret.m_decimal = 0;
9981 3768990 : parser->seen_string_literal = true;
9982 3768990 : return ret;
9983 : }
9984 :
9985 : /* Parse an expression other than a compound expression; that is, an
9986 : assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9987 : AFTER is not NULL then it is an Objective-C message expression which
9988 : is the primary-expression starting the expression as an initializer.
9989 :
9990 : assignment-expression:
9991 : conditional-expression
9992 : unary-expression assignment-operator assignment-expression
9993 :
9994 : assignment-operator: one of
9995 : = *= /= %= += -= <<= >>= &= ^= |=
9996 :
9997 : In GNU C we accept any conditional expression on the LHS and
9998 : diagnose the invalid lvalue rather than producing a syntax
9999 : error. */
10000 :
10001 : static struct c_expr
10002 227428794 : c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
10003 : tree omp_atomic_lhs)
10004 : {
10005 227428794 : struct c_expr lhs, rhs, ret;
10006 227428794 : enum tree_code code;
10007 227428794 : location_t op_location, exp_location;
10008 227428794 : bool save_in_omp_for = c_in_omp_for;
10009 227428794 : c_in_omp_for = false;
10010 227428794 : gcc_assert (!after || c_dialect_objc ());
10011 227428794 : lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
10012 227428792 : op_location = c_parser_peek_token (parser)->location;
10013 227428792 : switch (c_parser_peek_token (parser)->type)
10014 : {
10015 : case CPP_EQ:
10016 : code = NOP_EXPR;
10017 : break;
10018 12298 : case CPP_MULT_EQ:
10019 12298 : code = MULT_EXPR;
10020 12298 : break;
10021 8763 : case CPP_DIV_EQ:
10022 8763 : code = TRUNC_DIV_EXPR;
10023 8763 : break;
10024 2245 : case CPP_MOD_EQ:
10025 2245 : code = TRUNC_MOD_EXPR;
10026 2245 : break;
10027 90402 : case CPP_PLUS_EQ:
10028 90402 : code = PLUS_EXPR;
10029 90402 : break;
10030 29223 : case CPP_MINUS_EQ:
10031 29223 : code = MINUS_EXPR;
10032 29223 : break;
10033 4126 : case CPP_LSHIFT_EQ:
10034 4126 : code = LSHIFT_EXPR;
10035 4126 : break;
10036 16868 : case CPP_RSHIFT_EQ:
10037 16868 : code = RSHIFT_EXPR;
10038 16868 : break;
10039 25372 : case CPP_AND_EQ:
10040 25372 : code = BIT_AND_EXPR;
10041 25372 : break;
10042 3200 : case CPP_XOR_EQ:
10043 3200 : code = BIT_XOR_EXPR;
10044 3200 : break;
10045 21366 : case CPP_OR_EQ:
10046 21366 : code = BIT_IOR_EXPR;
10047 21366 : break;
10048 224549981 : default:
10049 224549981 : c_in_omp_for = save_in_omp_for;
10050 224549981 : return lhs;
10051 : }
10052 2878811 : c_parser_consume_token (parser);
10053 2878811 : exp_location = c_parser_peek_token (parser)->location;
10054 2878811 : rhs = c_parser_expr_no_commas (parser, NULL);
10055 2878811 : rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
10056 :
10057 2878811 : ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
10058 : code, exp_location, rhs.value,
10059 : rhs.original_type);
10060 2878811 : ret.m_decimal = 0;
10061 2878811 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
10062 2878811 : if (code == NOP_EXPR)
10063 2664948 : ret.original_code = MODIFY_EXPR;
10064 : else
10065 : {
10066 213863 : suppress_warning (ret.value, OPT_Wparentheses);
10067 213863 : ret.original_code = ERROR_MARK;
10068 : }
10069 2878811 : ret.original_type = NULL;
10070 2878811 : c_in_omp_for = save_in_omp_for;
10071 2878811 : return ret;
10072 : }
10073 :
10074 : /* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
10075 : AFTER is not NULL then it is an Objective-C message expression which is
10076 : the primary-expression starting the expression as an initializer.
10077 :
10078 : conditional-expression:
10079 : logical-OR-expression
10080 : logical-OR-expression ? expression : conditional-expression
10081 :
10082 : GNU extensions:
10083 :
10084 : conditional-expression:
10085 : logical-OR-expression ? : conditional-expression
10086 : */
10087 :
10088 : static struct c_expr
10089 227837645 : c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
10090 : tree omp_atomic_lhs)
10091 : {
10092 227837645 : struct c_expr cond, exp1, exp2, ret;
10093 227837645 : location_t start, cond_loc, colon_loc;
10094 227837645 : bool save_c_omp_array_section_p = c_omp_array_section_p;
10095 :
10096 227837645 : gcc_assert (!after || c_dialect_objc ());
10097 :
10098 227837645 : cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
10099 :
10100 227837643 : if (c_parser_next_token_is_not (parser, CPP_QUERY))
10101 227428983 : return cond;
10102 408660 : c_omp_array_section_p = false;
10103 408660 : if (cond.value != error_mark_node)
10104 408649 : start = cond.get_start ();
10105 : else
10106 : start = UNKNOWN_LOCATION;
10107 408660 : cond_loc = c_parser_peek_token (parser)->location;
10108 408660 : cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
10109 408660 : c_parser_consume_token (parser);
10110 408660 : if (c_parser_next_token_is (parser, CPP_COLON))
10111 : {
10112 770 : tree eptype = NULL_TREE;
10113 :
10114 770 : location_t middle_loc = c_parser_peek_token (parser)->location;
10115 770 : pedwarn (middle_loc, OPT_Wpedantic,
10116 : "ISO C forbids omitting the middle term of a %<?:%> expression");
10117 770 : if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
10118 : {
10119 1 : eptype = TREE_TYPE (cond.value);
10120 1 : cond.value = TREE_OPERAND (cond.value, 0);
10121 : }
10122 770 : tree e = cond.value;
10123 773 : while (TREE_CODE (e) == COMPOUND_EXPR)
10124 3 : e = TREE_OPERAND (e, 1);
10125 770 : warn_for_omitted_condop (middle_loc, e);
10126 : /* Make sure first operand is calculated only once. */
10127 770 : exp1.value = save_expr (default_conversion (cond.value));
10128 770 : if (eptype)
10129 1 : exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
10130 770 : exp1.original_type = NULL;
10131 770 : exp1.src_range = cond.src_range;
10132 770 : cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
10133 770 : c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
10134 : }
10135 : else
10136 : {
10137 407890 : cond.value
10138 407890 : = c_objc_common_truthvalue_conversion
10139 407890 : (cond_loc, default_conversion (cond.value));
10140 407890 : c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
10141 407890 : exp1 = c_parser_expression_conv (parser);
10142 407890 : mark_exp_read (exp1.value);
10143 407890 : c_inhibit_evaluation_warnings +=
10144 407890 : ((cond.value == truthvalue_true_node)
10145 407890 : - (cond.value == truthvalue_false_node));
10146 : }
10147 :
10148 408660 : colon_loc = c_parser_peek_token (parser)->location;
10149 408660 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
10150 : {
10151 9 : c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10152 9 : ret.set_error ();
10153 9 : ret.original_code = ERROR_MARK;
10154 9 : ret.original_type = NULL;
10155 9 : c_omp_array_section_p = save_c_omp_array_section_p;
10156 9 : return ret;
10157 : }
10158 408651 : {
10159 408651 : location_t exp2_loc = c_parser_peek_token (parser)->location;
10160 408651 : exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
10161 408651 : exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
10162 : }
10163 408651 : c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10164 408651 : location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
10165 408651 : location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
10166 408651 : if (UNLIKELY (omp_atomic_lhs != NULL)
10167 69 : && (TREE_CODE (cond.value) == GT_EXPR
10168 : || TREE_CODE (cond.value) == LT_EXPR
10169 : || TREE_CODE (cond.value) == EQ_EXPR)
10170 63 : && c_tree_equal (exp2.value, omp_atomic_lhs)
10171 408709 : && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
10172 19 : || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
10173 55 : ret.value = build3_loc (colon_loc, COND_EXPR, TREE_TYPE (omp_atomic_lhs),
10174 : cond.value, exp1.value, exp2.value);
10175 : else
10176 408596 : ret.value
10177 408596 : = build_conditional_expr (colon_loc, cond.value,
10178 408596 : cond.original_code == C_MAYBE_CONST_EXPR,
10179 : exp1.value, exp1.original_type, loc1,
10180 : exp2.value, exp2.original_type, loc2);
10181 408651 : ret.original_code = ERROR_MARK;
10182 408651 : if (exp1.value == error_mark_node || exp2.value == error_mark_node)
10183 15 : ret.original_type = NULL;
10184 : else
10185 : {
10186 408636 : tree t1, t2;
10187 :
10188 : /* If both sides are enum type, the default conversion will have
10189 : made the type of the result be an integer type. We want to
10190 : remember the enum types we started with. */
10191 408636 : t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
10192 408636 : t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
10193 408636 : ret.original_type = ((t1 != error_mark_node
10194 408636 : && t2 != error_mark_node
10195 408636 : && (TYPE_MAIN_VARIANT (t1)
10196 408636 : == TYPE_MAIN_VARIANT (t2)))
10197 408636 : ? t1
10198 : : NULL);
10199 : }
10200 408651 : set_c_expr_source_range (&ret, start, exp2.get_finish ());
10201 408651 : ret.m_decimal = 0;
10202 408651 : c_omp_array_section_p = save_c_omp_array_section_p;
10203 408651 : return ret;
10204 : }
10205 :
10206 : /* Parse a binary expression; that is, a logical-OR-expression (C90
10207 : 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
10208 : NULL then it is an Objective-C message expression which is the
10209 : primary-expression starting the expression as an initializer.
10210 :
10211 : OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
10212 : when it should be the unfolded lhs. In a valid OpenMP source,
10213 : one of the operands of the toplevel binary expression must be equal
10214 : to it. In that case, just return a build2 created binary operation
10215 : rather than result of parser_build_binary_op.
10216 :
10217 : multiplicative-expression:
10218 : cast-expression
10219 : multiplicative-expression * cast-expression
10220 : multiplicative-expression / cast-expression
10221 : multiplicative-expression % cast-expression
10222 :
10223 : additive-expression:
10224 : multiplicative-expression
10225 : additive-expression + multiplicative-expression
10226 : additive-expression - multiplicative-expression
10227 :
10228 : shift-expression:
10229 : additive-expression
10230 : shift-expression << additive-expression
10231 : shift-expression >> additive-expression
10232 :
10233 : relational-expression:
10234 : shift-expression
10235 : relational-expression < shift-expression
10236 : relational-expression > shift-expression
10237 : relational-expression <= shift-expression
10238 : relational-expression >= shift-expression
10239 :
10240 : equality-expression:
10241 : relational-expression
10242 : equality-expression == relational-expression
10243 : equality-expression != relational-expression
10244 :
10245 : AND-expression:
10246 : equality-expression
10247 : AND-expression & equality-expression
10248 :
10249 : exclusive-OR-expression:
10250 : AND-expression
10251 : exclusive-OR-expression ^ AND-expression
10252 :
10253 : inclusive-OR-expression:
10254 : exclusive-OR-expression
10255 : inclusive-OR-expression | exclusive-OR-expression
10256 :
10257 : logical-AND-expression:
10258 : inclusive-OR-expression
10259 : logical-AND-expression && inclusive-OR-expression
10260 :
10261 : logical-OR-expression:
10262 : logical-AND-expression
10263 : logical-OR-expression || logical-AND-expression
10264 : */
10265 :
10266 : static struct c_expr
10267 227854110 : c_parser_binary_expression (c_parser *parser, struct c_expr *after,
10268 : tree omp_atomic_lhs)
10269 : {
10270 : /* A binary expression is parsed using operator-precedence parsing,
10271 : with the operands being cast expressions. All the binary
10272 : operators are left-associative. Thus a binary expression is of
10273 : form:
10274 :
10275 : E0 op1 E1 op2 E2 ...
10276 :
10277 : which we represent on a stack. On the stack, the precedence
10278 : levels are strictly increasing. When a new operator is
10279 : encountered of higher precedence than that at the top of the
10280 : stack, it is pushed; its LHS is the top expression, and its RHS
10281 : is everything parsed until it is popped. When a new operator is
10282 : encountered with precedence less than or equal to that at the top
10283 : of the stack, triples E[i-1] op[i] E[i] are popped and replaced
10284 : by the result of the operation until the operator at the top of
10285 : the stack has lower precedence than the new operator or there is
10286 : only one element on the stack; then the top expression is the LHS
10287 : of the new operator. In the case of logical AND and OR
10288 : expressions, we also need to adjust c_inhibit_evaluation_warnings
10289 : as appropriate when the operators are pushed and popped. */
10290 :
10291 227854110 : struct {
10292 : /* The expression at this stack level. */
10293 : struct c_expr expr;
10294 : /* The precedence of the operator on its left, PREC_NONE at the
10295 : bottom of the stack. */
10296 : enum c_parser_prec prec;
10297 : /* The operation on its left. */
10298 : enum tree_code op;
10299 : /* The source location of this operation. */
10300 : location_t loc;
10301 : /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
10302 : tree sizeof_arg;
10303 : } stack[NUM_PRECS];
10304 227854110 : int sp;
10305 : /* Location of the binary operator. */
10306 227854110 : location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
10307 : #define POP \
10308 : do { \
10309 : switch (stack[sp].op) \
10310 : { \
10311 : case TRUTH_ANDIF_EXPR: \
10312 : c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10313 : == truthvalue_false_node); \
10314 : break; \
10315 : case TRUTH_ORIF_EXPR: \
10316 : c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10317 : == truthvalue_true_node); \
10318 : break; \
10319 : case TRUNC_DIV_EXPR: \
10320 : if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
10321 : || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
10322 : && (stack[sp].expr.original_code == SIZEOF_EXPR \
10323 : || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
10324 : { \
10325 : tree type0 = stack[sp - 1].sizeof_arg; \
10326 : tree type1 = stack[sp].sizeof_arg; \
10327 : tree first_arg = type0; \
10328 : if (!TYPE_P (type0)) \
10329 : type0 = TREE_TYPE (type0); \
10330 : if (!TYPE_P (type1)) \
10331 : type1 = TREE_TYPE (type1); \
10332 : if (POINTER_TYPE_P (type0) \
10333 : && comptypes (TREE_TYPE (type0), type1) \
10334 : && !(TREE_CODE (first_arg) == PARM_DECL \
10335 : && C_ARRAY_PARAMETER (first_arg) \
10336 : && warn_sizeof_array_argument)) \
10337 : { \
10338 : auto_diagnostic_group d; \
10339 : if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
10340 : "division %<sizeof (%T) / sizeof (%T)%> " \
10341 : "does not compute the number of array " \
10342 : "elements", \
10343 : type0, type1)) \
10344 : if (DECL_P (first_arg)) \
10345 : inform (DECL_SOURCE_LOCATION (first_arg), \
10346 : "first %<sizeof%> operand was declared here"); \
10347 : } \
10348 : else if (TREE_CODE (type0) == ARRAY_TYPE \
10349 : && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
10350 : && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
10351 : maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
10352 : stack[sp].sizeof_arg, type1); \
10353 : } \
10354 : break; \
10355 : default: \
10356 : break; \
10357 : } \
10358 : stack[sp - 1].expr \
10359 : = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
10360 : stack[sp - 1].expr, true, true); \
10361 : stack[sp].expr \
10362 : = convert_lvalue_to_rvalue (stack[sp].loc, \
10363 : stack[sp].expr, true, true); \
10364 : if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
10365 : && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
10366 : && ((1 << stack[sp].prec) \
10367 : & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
10368 : | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
10369 : | (1 << PREC_ADD) | (1 << PREC_MULT) \
10370 : | (1 << PREC_EQ)))) \
10371 : || ((c_parser_next_token_is (parser, CPP_QUERY) \
10372 : || (omp_atomic_lhs == void_list_node \
10373 : && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
10374 : && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
10375 : && stack[sp].op != TRUNC_MOD_EXPR \
10376 : && stack[sp].op != GE_EXPR \
10377 : && stack[sp].op != LE_EXPR \
10378 : && stack[sp].op != NE_EXPR \
10379 : && stack[0].expr.value != error_mark_node \
10380 : && stack[1].expr.value != error_mark_node \
10381 : && (omp_atomic_lhs == void_list_node \
10382 : || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
10383 : || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
10384 : || (stack[sp].op == EQ_EXPR \
10385 : && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
10386 : { \
10387 : tree t = make_node (stack[1].op); \
10388 : TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
10389 : TREE_OPERAND (t, 0) = stack[0].expr.value; \
10390 : TREE_OPERAND (t, 1) = stack[1].expr.value; \
10391 : stack[0].expr.value = t; \
10392 : stack[0].expr.m_decimal = 0; \
10393 : } \
10394 : else \
10395 : stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
10396 : stack[sp].op, \
10397 : stack[sp - 1].expr, \
10398 : stack[sp].expr); \
10399 : sp--; \
10400 : } while (0)
10401 227854110 : gcc_assert (!after || c_dialect_objc ());
10402 227854110 : stack[0].loc = c_parser_peek_token (parser)->location;
10403 227854110 : stack[0].expr = c_parser_cast_expression (parser, after);
10404 227854110 : stack[0].prec = PREC_NONE;
10405 227854110 : stack[0].sizeof_arg = c_last_sizeof_arg;
10406 227854110 : sp = 0;
10407 246480852 : while (true)
10408 : {
10409 237167481 : enum c_parser_prec oprec;
10410 237167481 : enum tree_code ocode;
10411 237167481 : source_range src_range;
10412 237167481 : if (parser->error)
10413 1076 : goto out;
10414 237166405 : switch (c_parser_peek_token (parser)->type)
10415 : {
10416 : case CPP_MULT:
10417 : oprec = PREC_MULT;
10418 : ocode = MULT_EXPR;
10419 : break;
10420 264593 : case CPP_DIV:
10421 264593 : oprec = PREC_MULT;
10422 264593 : ocode = TRUNC_DIV_EXPR;
10423 264593 : break;
10424 56185 : case CPP_MOD:
10425 56185 : oprec = PREC_MULT;
10426 56185 : ocode = TRUNC_MOD_EXPR;
10427 56185 : break;
10428 1827535 : case CPP_PLUS:
10429 1827535 : oprec = PREC_ADD;
10430 1827535 : ocode = PLUS_EXPR;
10431 1827535 : break;
10432 749100 : case CPP_MINUS:
10433 749100 : oprec = PREC_ADD;
10434 749100 : ocode = MINUS_EXPR;
10435 749100 : break;
10436 798151 : case CPP_LSHIFT:
10437 798151 : oprec = PREC_SHIFT;
10438 798151 : ocode = LSHIFT_EXPR;
10439 798151 : break;
10440 214042 : case CPP_RSHIFT:
10441 214042 : oprec = PREC_SHIFT;
10442 214042 : ocode = RSHIFT_EXPR;
10443 214042 : break;
10444 470245 : case CPP_LESS:
10445 470245 : oprec = PREC_REL;
10446 470245 : ocode = LT_EXPR;
10447 470245 : break;
10448 195238 : case CPP_GREATER:
10449 195238 : oprec = PREC_REL;
10450 195238 : ocode = GT_EXPR;
10451 195238 : break;
10452 163153 : case CPP_LESS_EQ:
10453 163153 : oprec = PREC_REL;
10454 163153 : ocode = LE_EXPR;
10455 163153 : break;
10456 167400 : case CPP_GREATER_EQ:
10457 167400 : oprec = PREC_REL;
10458 167400 : ocode = GE_EXPR;
10459 167400 : break;
10460 394776 : case CPP_EQ_EQ:
10461 394776 : oprec = PREC_EQ;
10462 394776 : ocode = EQ_EXPR;
10463 394776 : break;
10464 770457 : case CPP_NOT_EQ:
10465 770457 : oprec = PREC_EQ;
10466 770457 : ocode = NE_EXPR;
10467 770457 : break;
10468 593280 : case CPP_AND:
10469 593280 : oprec = PREC_BITAND;
10470 593280 : ocode = BIT_AND_EXPR;
10471 593280 : break;
10472 76969 : case CPP_XOR:
10473 76969 : oprec = PREC_BITXOR;
10474 76969 : ocode = BIT_XOR_EXPR;
10475 76969 : break;
10476 864393 : case CPP_OR:
10477 864393 : oprec = PREC_BITOR;
10478 864393 : ocode = BIT_IOR_EXPR;
10479 864393 : break;
10480 184789 : case CPP_AND_AND:
10481 184789 : oprec = PREC_LOGAND;
10482 184789 : ocode = TRUTH_ANDIF_EXPR;
10483 184789 : break;
10484 323422 : case CPP_OR_OR:
10485 323422 : oprec = PREC_LOGOR;
10486 323422 : ocode = TRUTH_ORIF_EXPR;
10487 323422 : break;
10488 227853034 : default:
10489 : /* Not a binary operator, so end of the binary
10490 : expression. */
10491 227853034 : goto out;
10492 : }
10493 9313371 : binary_loc = c_parser_peek_token (parser)->location;
10494 9313371 : while (oprec <= stack[sp].prec)
10495 10756537 : POP;
10496 9313371 : c_parser_consume_token (parser);
10497 9313371 : switch (ocode)
10498 : {
10499 184789 : case TRUTH_ANDIF_EXPR:
10500 184789 : src_range = stack[sp].expr.src_range;
10501 184789 : stack[sp].expr
10502 184789 : = convert_lvalue_to_rvalue (stack[sp].loc,
10503 : stack[sp].expr, true, true);
10504 369578 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10505 184789 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10506 184789 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10507 184789 : == truthvalue_false_node);
10508 184789 : set_c_expr_source_range (&stack[sp].expr, src_range);
10509 184789 : break;
10510 323422 : case TRUTH_ORIF_EXPR:
10511 323422 : src_range = stack[sp].expr.src_range;
10512 323422 : stack[sp].expr
10513 323422 : = convert_lvalue_to_rvalue (stack[sp].loc,
10514 : stack[sp].expr, true, true);
10515 646844 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10516 323422 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10517 323422 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10518 323422 : == truthvalue_true_node);
10519 323422 : set_c_expr_source_range (&stack[sp].expr, src_range);
10520 323422 : break;
10521 : default:
10522 : break;
10523 : }
10524 9313371 : sp++;
10525 9313371 : stack[sp].loc = binary_loc;
10526 9313371 : stack[sp].expr = c_parser_cast_expression (parser, NULL);
10527 9313371 : stack[sp].prec = oprec;
10528 9313371 : stack[sp].op = ocode;
10529 9313371 : stack[sp].sizeof_arg = c_last_sizeof_arg;
10530 9313371 : }
10531 227854110 : out:
10532 227854110 : while (sp > 0)
10533 235725036 : POP;
10534 227854108 : return stack[0].expr;
10535 : #undef POP
10536 : }
10537 :
10538 : /* Parse any storage class specifiers after an open parenthesis in a
10539 : context where a compound literal is permitted. */
10540 :
10541 : static struct c_declspecs *
10542 121284805 : c_parser_compound_literal_scspecs (c_parser *parser)
10543 : {
10544 121284805 : bool seen_scspec = false;
10545 121284805 : struct c_declspecs *specs = build_null_declspecs ();
10546 242569953 : while (c_parser_next_token_is (parser, CPP_KEYWORD))
10547 : {
10548 4195448 : switch (c_parser_peek_token (parser)->keyword)
10549 : {
10550 343 : case RID_CONSTEXPR:
10551 343 : case RID_REGISTER:
10552 343 : case RID_STATIC:
10553 343 : case RID_THREAD:
10554 343 : seen_scspec = true;
10555 343 : declspecs_add_scspec (c_parser_peek_token (parser)->location,
10556 343 : specs, c_parser_peek_token (parser)->value);
10557 343 : c_parser_consume_token (parser);
10558 343 : break;
10559 4195105 : default:
10560 4195105 : goto out;
10561 : }
10562 : }
10563 117089700 : out:
10564 121284805 : return seen_scspec ? specs : NULL;
10565 : }
10566 :
10567 : /* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
10568 : is not NULL then it is an Objective-C message expression which is the
10569 : primary-expression starting the expression as an initializer.
10570 :
10571 : cast-expression:
10572 : unary-expression
10573 : ( type-name ) unary-expression
10574 : */
10575 :
10576 : static struct c_expr
10577 366990256 : c_parser_cast_expression (c_parser *parser, struct c_expr *after)
10578 : {
10579 366990256 : location_t cast_loc = c_parser_peek_token (parser)->location;
10580 366990256 : gcc_assert (!after || c_dialect_objc ());
10581 0 : if (after)
10582 0 : return c_parser_postfix_expression_after_primary (parser,
10583 0 : cast_loc, *after);
10584 : /* If the expression begins with a parenthesized type name, it may
10585 : be either a cast or a compound literal; we need to see whether
10586 : the next character is '{' to tell the difference. If not, it is
10587 : an unary expression. Full detection of unknown typenames here
10588 : would require a 3-token lookahead. */
10589 366990256 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10590 366990256 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10591 : {
10592 120921860 : struct c_declspecs *scspecs;
10593 120921860 : struct c_type_name *type_name;
10594 120921860 : struct c_expr ret;
10595 120921860 : struct c_expr expr;
10596 120921860 : matching_parens parens;
10597 120921860 : parens.consume_open (parser);
10598 120921860 : scspecs = c_parser_compound_literal_scspecs (parser);
10599 120921860 : type_name = c_parser_type_name (parser, true);
10600 120921860 : parens.skip_until_found_close (parser);
10601 120921860 : if (type_name == NULL)
10602 : {
10603 1 : ret.set_error ();
10604 1 : ret.original_code = ERROR_MARK;
10605 1 : ret.original_type = NULL;
10606 1 : return ret;
10607 : }
10608 :
10609 : /* Save casted types in the function's used types hash table. */
10610 120921859 : used_types_insert (type_name->specs->type);
10611 :
10612 120921859 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10613 917693 : return c_parser_postfix_expression_after_paren_type (parser, scspecs,
10614 : type_name,
10615 917693 : cast_loc);
10616 120004166 : if (scspecs)
10617 1 : error_at (cast_loc, "storage class specifier in cast");
10618 120004166 : if (type_name->specs->alignas_p)
10619 1 : error_at (type_name->specs->locations[cdw_alignas],
10620 : "alignment specified for type name in cast");
10621 120004166 : {
10622 120004166 : location_t expr_loc = c_parser_peek_token (parser)->location;
10623 120004166 : expr = c_parser_cast_expression (parser, NULL);
10624 120004166 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
10625 : }
10626 120004166 : ret.value = c_cast_expr (cast_loc, type_name, expr.value);
10627 120004166 : if (ret.value && expr.value)
10628 120004166 : set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
10629 120004166 : ret.original_code = ERROR_MARK;
10630 120004166 : ret.original_type = NULL;
10631 120004166 : ret.m_decimal = 0;
10632 120004166 : return ret;
10633 : }
10634 : else
10635 246068396 : return c_parser_unary_expression (parser);
10636 : }
10637 :
10638 : /* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
10639 :
10640 : unary-expression:
10641 : postfix-expression
10642 : ++ unary-expression
10643 : -- unary-expression
10644 : unary-operator cast-expression
10645 : _Countof unary-expression
10646 : _Countof ( type-name )
10647 : sizeof unary-expression
10648 : sizeof ( type-name )
10649 : static-assert-declaration-no-semi
10650 :
10651 : (_Countof and the use of static assertions in expressions are new in C2y.)
10652 :
10653 : unary-operator: one of
10654 : & * + - ~ !
10655 :
10656 : GNU extensions:
10657 :
10658 : unary-expression:
10659 : __alignof__ unary-expression
10660 : __alignof__ ( type-name )
10661 : _Maxof ( type-name )
10662 : _Minof ( type-name )
10663 : && identifier
10664 :
10665 : (C11 permits _Alignof with type names only.)
10666 :
10667 : unary-operator: one of
10668 : __extension__ __real__ __imag__
10669 :
10670 : Transactional Memory:
10671 :
10672 : unary-expression:
10673 : transaction-expression
10674 :
10675 : In addition, the GNU syntax treats ++ and -- as unary operators, so
10676 : they may be applied to cast expressions with errors for non-lvalues
10677 : given later. */
10678 :
10679 : static struct c_expr
10680 246421985 : c_parser_unary_expression (c_parser *parser)
10681 : {
10682 246421985 : int ext;
10683 246421985 : struct c_expr ret, op;
10684 246421985 : location_t op_loc = c_parser_peek_token (parser)->location;
10685 246421985 : location_t exp_loc;
10686 246421985 : location_t finish;
10687 246421985 : ret.original_code = ERROR_MARK;
10688 246421985 : ret.original_type = NULL;
10689 246421985 : switch (c_parser_peek_token (parser)->type)
10690 : {
10691 220509 : case CPP_PLUS_PLUS:
10692 220509 : c_parser_consume_token (parser);
10693 220509 : exp_loc = c_parser_peek_token (parser)->location;
10694 220509 : op = c_parser_cast_expression (parser, NULL);
10695 4095 : if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10696 217548 : && !DECL_READ_P (op.value)
10697 226741 : && (VAR_P (op.value) ? warn_unused_but_set_variable
10698 : : warn_unused_but_set_parameter) > 1)
10699 : {
10700 399 : op = default_function_array_read_conversion (exp_loc, op);
10701 399 : DECL_READ_P (op.value) = 0;
10702 : }
10703 : else
10704 220110 : op = default_function_array_read_conversion (exp_loc, op);
10705 220509 : return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
10706 20024 : case CPP_MINUS_MINUS:
10707 20024 : c_parser_consume_token (parser);
10708 20024 : exp_loc = c_parser_peek_token (parser)->location;
10709 20024 : op = c_parser_cast_expression (parser, NULL);
10710 14785 : if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10711 19387 : && !DECL_READ_P (op.value)
10712 21982 : && (VAR_P (op.value) ? warn_unused_but_set_variable
10713 : : warn_unused_but_set_parameter) > 1)
10714 : {
10715 202 : op = default_function_array_read_conversion (exp_loc, op);
10716 202 : DECL_READ_P (op.value) = 0;
10717 : }
10718 : else
10719 19822 : op = default_function_array_read_conversion (exp_loc, op);
10720 20024 : return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
10721 445213 : case CPP_AND:
10722 445213 : c_parser_consume_token (parser);
10723 445213 : op = c_parser_cast_expression (parser, NULL);
10724 445213 : mark_exp_read (op.value);
10725 445213 : return parser_build_unary_op (op_loc, ADDR_EXPR, op);
10726 1209706 : case CPP_MULT:
10727 1209706 : {
10728 1209706 : c_parser_consume_token (parser);
10729 1209706 : exp_loc = c_parser_peek_token (parser)->location;
10730 1209706 : op = c_parser_cast_expression (parser, NULL);
10731 1209706 : finish = op.get_finish ();
10732 1209706 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10733 1209706 : location_t combined_loc = make_location (op_loc, op_loc, finish);
10734 1209706 : ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
10735 1209706 : ret.src_range.m_start = op_loc;
10736 1209706 : ret.src_range.m_finish = finish;
10737 1209706 : ret.m_decimal = 0;
10738 1209706 : return ret;
10739 : }
10740 28760 : case CPP_PLUS:
10741 28760 : if (!c_dialect_objc () && !in_system_header_at (input_location))
10742 28758 : warning_at (op_loc,
10743 28758 : OPT_Wtraditional,
10744 : "traditional C rejects the unary plus operator");
10745 28760 : c_parser_consume_token (parser);
10746 28760 : exp_loc = c_parser_peek_token (parser)->location;
10747 28760 : op = c_parser_cast_expression (parser, NULL);
10748 28760 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10749 28760 : return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
10750 6683547 : case CPP_MINUS:
10751 6683547 : c_parser_consume_token (parser);
10752 6683547 : exp_loc = c_parser_peek_token (parser)->location;
10753 6683547 : op = c_parser_cast_expression (parser, NULL);
10754 6683547 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10755 6683547 : return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
10756 294688 : case CPP_COMPL:
10757 294688 : c_parser_consume_token (parser);
10758 294688 : exp_loc = c_parser_peek_token (parser)->location;
10759 294688 : op = c_parser_cast_expression (parser, NULL);
10760 294688 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10761 294688 : return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
10762 375766 : case CPP_NOT:
10763 375766 : c_parser_consume_token (parser);
10764 375766 : exp_loc = c_parser_peek_token (parser)->location;
10765 375766 : op = c_parser_cast_expression (parser, NULL);
10766 375766 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10767 375766 : return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
10768 1839 : case CPP_AND_AND:
10769 : /* Refer to the address of a label as a pointer. */
10770 1839 : c_parser_consume_token (parser);
10771 1839 : if (c_parser_next_token_is (parser, CPP_NAME))
10772 : {
10773 3664 : ret.value = finish_label_address_expr
10774 1832 : (c_parser_peek_token (parser)->value, op_loc);
10775 1832 : set_c_expr_source_range (&ret, op_loc,
10776 : c_parser_peek_token (parser)->get_finish ());
10777 1832 : c_parser_consume_token (parser);
10778 : }
10779 : else
10780 : {
10781 7 : c_parser_error (parser, "expected identifier");
10782 7 : ret.set_error ();
10783 : }
10784 1839 : return ret;
10785 2891083 : case CPP_KEYWORD:
10786 2891083 : {
10787 2891083 : enum rid rid = c_parser_peek_token (parser)->keyword;
10788 2891083 : switch (rid)
10789 : {
10790 643848 : case RID_COUNTOF:
10791 643848 : case RID_SIZEOF:
10792 643848 : return c_parser_sizeof_or_countof_expression (parser, rid);
10793 72686 : case RID_ALIGNOF:
10794 72686 : return c_parser_alignof_expression (parser);
10795 102 : case RID_MAXOF:
10796 102 : case RID_MINOF:
10797 102 : return c_parser_maxof_or_minof_expression (parser, rid);
10798 764 : case RID_BUILTIN_HAS_ATTRIBUTE:
10799 764 : return c_parser_has_attribute_expression (parser);
10800 461093 : case RID_EXTENSION:
10801 461093 : c_parser_consume_token (parser);
10802 461093 : ext = disable_extension_diagnostics ();
10803 461093 : ret = c_parser_cast_expression (parser, NULL);
10804 461093 : restore_extension_diagnostics (ext);
10805 461093 : return ret;
10806 38400 : case RID_REALPART:
10807 38400 : c_parser_consume_token (parser);
10808 38400 : exp_loc = c_parser_peek_token (parser)->location;
10809 38400 : op = c_parser_cast_expression (parser, NULL);
10810 38400 : op = default_function_array_conversion (exp_loc, op);
10811 38400 : return parser_build_unary_op (op_loc, REALPART_EXPR, op);
10812 38322 : case RID_IMAGPART:
10813 38322 : c_parser_consume_token (parser);
10814 38322 : exp_loc = c_parser_peek_token (parser)->location;
10815 38322 : op = c_parser_cast_expression (parser, NULL);
10816 38322 : op = default_function_array_conversion (exp_loc, op);
10817 38322 : return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
10818 7 : case RID_TRANSACTION_ATOMIC:
10819 7 : case RID_TRANSACTION_RELAXED:
10820 7 : return c_parser_transaction_expression (parser, rid);
10821 168 : case RID_STATIC_ASSERT:
10822 168 : c_parser_static_assert_declaration_no_semi (parser);
10823 168 : pedwarn_c23 (op_loc, OPT_Wpedantic,
10824 : "ISO C does not support static assertions in "
10825 : "expressions before C2Y");
10826 168 : ret.value = void_node;
10827 168 : set_c_expr_source_range (&ret, op_loc, op_loc);
10828 168 : ret.m_decimal = 0;
10829 168 : return ret;
10830 1635693 : default:
10831 1635693 : return c_parser_postfix_expression (parser);
10832 : }
10833 : }
10834 234250850 : default:
10835 234250850 : return c_parser_postfix_expression (parser);
10836 : }
10837 : }
10838 :
10839 : /* Parse a sizeof or _Countof expression. */
10840 :
10841 : static struct c_expr
10842 643848 : c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
10843 : {
10844 643848 : const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
10845 643848 : struct c_expr expr;
10846 643848 : struct c_expr result;
10847 643848 : location_t expr_loc;
10848 643848 : gcc_assert (c_parser_next_token_is_keyword (parser, rid));
10849 :
10850 643848 : location_t start;
10851 643848 : location_t finish = UNKNOWN_LOCATION;
10852 :
10853 643848 : start = c_parser_peek_token (parser)->location;
10854 :
10855 643848 : if (rid == RID_COUNTOF)
10856 72 : pedwarn_c23 (start, OPT_Wpedantic,
10857 : "ISO C does not support %qs before C2Y", op_name);
10858 :
10859 643848 : c_parser_consume_token (parser);
10860 643848 : c_inhibit_evaluation_warnings++;
10861 643848 : if (rid == RID_COUNTOF)
10862 72 : in_countof++;
10863 : else
10864 643776 : in_sizeof++;
10865 643848 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10866 643848 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10867 : {
10868 : /* Either sizeof ( type-name ) or sizeof unary-expression
10869 : starting with a compound literal. */
10870 331058 : struct c_declspecs *scspecs;
10871 331058 : struct c_type_name *type_name;
10872 331058 : matching_parens parens;
10873 331058 : parens.consume_open (parser);
10874 331058 : expr_loc = c_parser_peek_token (parser)->location;
10875 331058 : scspecs = c_parser_compound_literal_scspecs (parser);
10876 331058 : type_name = c_parser_type_name (parser, true);
10877 331058 : parens.skip_until_found_close (parser);
10878 331058 : finish = parser->tokens_buf[0].location;
10879 331058 : if (type_name == NULL)
10880 : {
10881 : /* Let c_expr_sizeof_expr call pop_maybe_used and fill in c_expr
10882 : for parsing error; the parsing of the expression could have
10883 : called record_maybe_used_decl. */
10884 1 : expr.set_error ();
10885 27 : goto Xof_expr;
10886 : }
10887 331057 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10888 : {
10889 26 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10890 : type_name,
10891 : expr_loc);
10892 26 : finish = expr.get_finish ();
10893 26 : goto Xof_expr;
10894 : }
10895 : /* sizeof ( type-name ). */
10896 331031 : if (scspecs)
10897 1 : error_at (expr_loc, "storage class specifier in %qs", op_name);
10898 331031 : if (type_name->specs->alignas_p)
10899 2 : error_at (type_name->specs->locations[cdw_alignas],
10900 : "alignment specified for type name in %qs", op_name);
10901 331031 : c_inhibit_evaluation_warnings--;
10902 331031 : if (rid == RID_COUNTOF)
10903 : {
10904 18 : in_countof--;
10905 18 : result = c_expr_countof_type (expr_loc, type_name);
10906 : }
10907 : else
10908 : {
10909 331013 : in_sizeof--;
10910 331013 : result = c_expr_sizeof_type (expr_loc, type_name);
10911 : }
10912 : }
10913 : else
10914 : {
10915 312790 : expr_loc = c_parser_peek_token (parser)->location;
10916 312790 : expr = c_parser_unary_expression (parser);
10917 312790 : finish = expr.get_finish ();
10918 312817 : Xof_expr:
10919 312817 : c_inhibit_evaluation_warnings--;
10920 312817 : if (rid == RID_COUNTOF)
10921 54 : in_countof--;
10922 : else
10923 312763 : in_sizeof--;
10924 312817 : mark_exp_read (expr.value);
10925 312817 : if (TREE_CODE (expr.value) == COMPONENT_REF
10926 312817 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
10927 1 : error_at (expr_loc, "%qs applied to a bit-field", op_name);
10928 312817 : if (rid == RID_COUNTOF)
10929 54 : result = c_expr_countof_expr (expr_loc, expr);
10930 : else
10931 312763 : result = c_expr_sizeof_expr (expr_loc, expr);
10932 : }
10933 643848 : if (finish == UNKNOWN_LOCATION)
10934 1 : finish = start;
10935 643848 : set_c_expr_source_range (&result, start, finish);
10936 643848 : return result;
10937 : }
10938 :
10939 : /* Parse an alignof expression. */
10940 :
10941 : static struct c_expr
10942 72686 : c_parser_alignof_expression (c_parser *parser)
10943 : {
10944 72686 : struct c_expr expr;
10945 72686 : location_t start_loc = c_parser_peek_token (parser)->location;
10946 72686 : location_t end_loc;
10947 72686 : tree alignof_spelling = c_parser_peek_token (parser)->value;
10948 72686 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
10949 72686 : bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
10950 : "_Alignof") == 0
10951 72686 : || strcmp (IDENTIFIER_POINTER (alignof_spelling),
10952 72916 : "alignof") == 0);
10953 : /* A diagnostic is not required for the use of this identifier in
10954 : the implementation namespace; only diagnose it for the C11 or C23
10955 : spelling because of existing code using the other spellings. */
10956 230 : if (is_c11_alignof)
10957 : {
10958 230 : if (flag_isoc99)
10959 226 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
10960 : alignof_spelling);
10961 : else
10962 4 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
10963 : alignof_spelling);
10964 : }
10965 72686 : c_parser_consume_token (parser);
10966 72686 : c_inhibit_evaluation_warnings++;
10967 72686 : in_alignof++;
10968 72686 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10969 72686 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10970 : {
10971 : /* Either __alignof__ ( type-name ) or __alignof__
10972 : unary-expression starting with a compound literal. */
10973 31887 : location_t loc;
10974 31887 : struct c_declspecs *scspecs;
10975 31887 : struct c_type_name *type_name;
10976 31887 : struct c_expr ret;
10977 31887 : matching_parens parens;
10978 31887 : parens.consume_open (parser);
10979 31887 : loc = c_parser_peek_token (parser)->location;
10980 31887 : scspecs = c_parser_compound_literal_scspecs (parser);
10981 31887 : type_name = c_parser_type_name (parser, true);
10982 31887 : end_loc = c_parser_peek_token (parser)->location;
10983 31887 : parens.skip_until_found_close (parser);
10984 31887 : if (type_name == NULL)
10985 : {
10986 0 : struct c_expr ret;
10987 0 : c_inhibit_evaluation_warnings--;
10988 0 : in_alignof--;
10989 0 : ret.set_error ();
10990 0 : ret.original_code = ERROR_MARK;
10991 0 : ret.original_type = NULL;
10992 31885 : return ret;
10993 : }
10994 31887 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10995 : {
10996 2 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10997 : type_name,
10998 : loc);
10999 2 : goto alignof_expr;
11000 : }
11001 : /* alignof ( type-name ). */
11002 31885 : if (scspecs)
11003 1 : error_at (loc, "storage class specifier in %qE", alignof_spelling);
11004 31885 : if (type_name->specs->alignas_p)
11005 1 : error_at (type_name->specs->locations[cdw_alignas],
11006 : "alignment specified for type name in %qE",
11007 : alignof_spelling);
11008 31885 : c_inhibit_evaluation_warnings--;
11009 31885 : in_alignof--;
11010 31885 : ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
11011 : NULL, NULL),
11012 : false, is_c11_alignof, 1);
11013 31885 : ret.original_code = ERROR_MARK;
11014 31885 : ret.original_type = NULL;
11015 31885 : set_c_expr_source_range (&ret, start_loc, end_loc);
11016 31885 : ret.m_decimal = 0;
11017 31885 : return ret;
11018 : }
11019 : else
11020 : {
11021 40799 : struct c_expr ret;
11022 40799 : expr = c_parser_unary_expression (parser);
11023 40799 : end_loc = expr.src_range.m_finish;
11024 40801 : alignof_expr:
11025 40801 : mark_exp_read (expr.value);
11026 40801 : c_inhibit_evaluation_warnings--;
11027 40801 : in_alignof--;
11028 40801 : if (is_c11_alignof)
11029 36 : pedwarn (start_loc,
11030 36 : OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
11031 : alignof_spelling);
11032 40801 : ret.value = c_alignof_expr (start_loc, expr.value);
11033 40801 : ret.original_code = ERROR_MARK;
11034 40801 : ret.original_type = NULL;
11035 40801 : set_c_expr_source_range (&ret, start_loc, end_loc);
11036 40801 : ret.m_decimal = 0;
11037 40801 : return ret;
11038 : }
11039 : }
11040 :
11041 : /* Parse a _Maxof or _Minof expression. */
11042 :
11043 : static struct c_expr
11044 102 : c_parser_maxof_or_minof_expression (c_parser *parser, enum rid rid)
11045 : {
11046 102 : const char *op_name = (rid == RID_MAXOF) ? "_Maxof" : "_Minof";
11047 102 : struct c_expr result;
11048 102 : location_t expr_loc;
11049 102 : struct c_type_name *type_name;
11050 102 : matching_parens parens;
11051 102 : gcc_assert (c_parser_next_token_is_keyword (parser, rid));
11052 :
11053 102 : location_t start;
11054 102 : location_t finish = UNKNOWN_LOCATION;
11055 :
11056 102 : start = c_parser_peek_token (parser)->location;
11057 :
11058 102 : pedwarn (start, OPT_Wpedantic, "ISO C does not support %qs", op_name);
11059 :
11060 102 : c_parser_consume_token (parser);
11061 102 : c_inhibit_evaluation_warnings++;
11062 102 : if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
11063 : {
11064 2 : c_parser_error (parser, "expected %<(%>");
11065 2 : goto fail;
11066 : }
11067 100 : parens.consume_open (parser);
11068 100 : expr_loc = c_parser_peek_token (parser)->location;
11069 100 : if (!c_token_starts_typename (c_parser_peek_token (parser)))
11070 : {
11071 6 : error_at (expr_loc, "invalid application of %qs to something not a type", op_name);
11072 6 : parens.skip_until_found_close (parser);
11073 6 : goto fail;
11074 : }
11075 94 : type_name = c_parser_type_name (parser, true);
11076 94 : if (type_name == NULL)
11077 : {
11078 : // c_parser_type_name() has already diagnosed the error.
11079 2 : parens.skip_until_found_close (parser);
11080 2 : goto fail;
11081 : }
11082 92 : parens.skip_until_found_close (parser);
11083 92 : finish = parser->tokens_buf[0].location;
11084 92 : if (type_name->specs->alignas_p)
11085 2 : error_at (type_name->specs->locations[cdw_alignas],
11086 : "alignment specified for type name in %qs", op_name);
11087 92 : c_inhibit_evaluation_warnings--;
11088 92 : if (rid == RID_MAXOF)
11089 46 : result = c_expr_maxof_type (expr_loc, type_name);
11090 : else
11091 46 : result = c_expr_minof_type (expr_loc, type_name);
11092 92 : set_c_expr_source_range (&result, start, finish);
11093 92 : return result;
11094 10 : fail:
11095 10 : c_inhibit_evaluation_warnings--;
11096 10 : result.set_error ();
11097 10 : result.original_code = ERROR_MARK;
11098 10 : result.original_type = NULL;
11099 10 : return result;
11100 : }
11101 :
11102 : /* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
11103 : expression. */
11104 :
11105 : static struct c_expr
11106 764 : c_parser_has_attribute_expression (c_parser *parser)
11107 : {
11108 764 : gcc_assert (c_parser_next_token_is_keyword (parser,
11109 : RID_BUILTIN_HAS_ATTRIBUTE));
11110 764 : location_t start = c_parser_peek_token (parser)->location;
11111 764 : c_parser_consume_token (parser);
11112 :
11113 764 : c_inhibit_evaluation_warnings++;
11114 :
11115 764 : matching_parens parens;
11116 764 : if (!parens.require_open (parser))
11117 : {
11118 0 : c_inhibit_evaluation_warnings--;
11119 0 : in_typeof--;
11120 :
11121 0 : struct c_expr result;
11122 0 : result.set_error ();
11123 0 : result.original_code = ERROR_MARK;
11124 0 : result.original_type = NULL;
11125 0 : return result;
11126 : }
11127 :
11128 : /* Treat the type argument the same way as in typeof for the purposes
11129 : of warnings. FIXME: Generalize this so the warning refers to
11130 : __builtin_has_attribute rather than typeof. */
11131 764 : in_typeof++;
11132 :
11133 : /* The first operand: one of DECL, EXPR, or TYPE. */
11134 764 : tree oper = NULL_TREE;
11135 764 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
11136 : {
11137 148 : struct c_type_name *tname = c_parser_type_name (parser);
11138 148 : in_typeof--;
11139 148 : if (tname)
11140 : {
11141 148 : oper = groktypename (tname, NULL, NULL);
11142 148 : pop_maybe_used (c_type_variably_modified_p (oper));
11143 : }
11144 : }
11145 : else
11146 : {
11147 616 : struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
11148 616 : c_inhibit_evaluation_warnings--;
11149 616 : in_typeof--;
11150 616 : if (cexpr.value != error_mark_node)
11151 : {
11152 613 : mark_exp_read (cexpr.value);
11153 613 : oper = cexpr.value;
11154 613 : tree etype = TREE_TYPE (oper);
11155 613 : bool was_vm = c_type_variably_modified_p (etype);
11156 : /* This is returned with the type so that when the type is
11157 : evaluated, this can be evaluated. */
11158 613 : if (was_vm)
11159 0 : oper = c_fully_fold (oper, false, NULL);
11160 613 : pop_maybe_used (was_vm);
11161 : }
11162 : }
11163 :
11164 764 : struct c_expr result;
11165 764 : result.original_code = ERROR_MARK;
11166 764 : result.original_type = NULL;
11167 :
11168 764 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11169 : {
11170 : /* Consume the closing parenthesis if that's the next token
11171 : in the likely case the built-in was invoked with fewer
11172 : than two arguments. */
11173 4 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11174 4 : c_parser_consume_token (parser);
11175 4 : c_inhibit_evaluation_warnings--;
11176 4 : result.set_error ();
11177 4 : return result;
11178 : }
11179 :
11180 760 : bool save_translate_strings_p = parser->translate_strings_p;
11181 :
11182 760 : location_t atloc = c_parser_peek_token (parser)->location;
11183 : /* Parse a single attribute. Require no leading comma and do not
11184 : allow empty attributes. */
11185 760 : tree attr = c_parser_gnu_attribute (parser, NULL_TREE, false, false);
11186 :
11187 760 : parser->translate_strings_p = save_translate_strings_p;
11188 :
11189 760 : location_t finish = c_parser_peek_token (parser)->location;
11190 760 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11191 757 : c_parser_consume_token (parser);
11192 : else
11193 : {
11194 3 : c_parser_error (parser, "expected identifier");
11195 3 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11196 :
11197 3 : result.set_error ();
11198 3 : return result;
11199 : }
11200 :
11201 757 : if (!attr)
11202 : {
11203 0 : error_at (atloc, "expected identifier");
11204 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11205 : "expected %<)%>");
11206 0 : result.set_error ();
11207 0 : return result;
11208 : }
11209 :
11210 757 : result.original_code = INTEGER_CST;
11211 757 : result.original_type = boolean_type_node;
11212 :
11213 757 : if (has_attribute (atloc, oper, attr, default_conversion))
11214 296 : result.value = boolean_true_node;
11215 : else
11216 461 : result.value = boolean_false_node;
11217 :
11218 757 : set_c_expr_source_range (&result, start, finish);
11219 757 : result.m_decimal = 0;
11220 757 : return result;
11221 : }
11222 :
11223 : /* Helper function to read arguments of builtins which are interfaces
11224 : for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
11225 : others. The name of the builtin is passed using BNAME parameter.
11226 : Function returns true if there were no errors while parsing and
11227 : stores the arguments in CEXPR_LIST. If it returns true,
11228 : *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
11229 : parenthesis. */
11230 : static bool
11231 1561839 : c_parser_get_builtin_args (c_parser *parser, const char *bname,
11232 : vec<c_expr_t, va_gc> **ret_cexpr_list,
11233 : bool choose_expr_p,
11234 : location_t *out_close_paren_loc)
11235 : {
11236 1561839 : location_t loc = c_parser_peek_token (parser)->location;
11237 1561839 : vec<c_expr_t, va_gc> *cexpr_list;
11238 1561839 : c_expr_t expr;
11239 1561839 : bool saved_force_folding_builtin_constant_p;
11240 :
11241 1561839 : *ret_cexpr_list = NULL;
11242 1561839 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
11243 : {
11244 1 : error_at (loc, "cannot take address of %qs", bname);
11245 1 : return false;
11246 : }
11247 :
11248 1561838 : c_parser_consume_token (parser);
11249 :
11250 1561838 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11251 : {
11252 19 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11253 19 : c_parser_consume_token (parser);
11254 19 : return true;
11255 : }
11256 :
11257 1561819 : saved_force_folding_builtin_constant_p
11258 1561819 : = force_folding_builtin_constant_p;
11259 1561819 : force_folding_builtin_constant_p |= choose_expr_p;
11260 1561819 : expr = c_parser_expr_no_commas (parser, NULL);
11261 1561819 : force_folding_builtin_constant_p
11262 1561819 : = saved_force_folding_builtin_constant_p;
11263 1561819 : vec_alloc (cexpr_list, 1);
11264 1561819 : vec_safe_push (cexpr_list, expr);
11265 18273112 : while (c_parser_next_token_is (parser, CPP_COMMA))
11266 : {
11267 15149474 : c_parser_consume_token (parser);
11268 15149474 : if (c_parser_next_token_is (parser, CPP_EMBED))
11269 : {
11270 2 : c_token *embed = c_parser_peek_token (parser);
11271 2 : tree value = embed->value;
11272 2 : expr.original_code = INTEGER_CST;
11273 2 : expr.original_type = integer_type_node;
11274 2 : expr.value = NULL_TREE;
11275 2 : set_c_expr_source_range (&expr, embed->get_range ());
11276 2 : expr.m_decimal = 0;
11277 510 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
11278 : {
11279 1016 : expr.value = build_int_cst (integer_type_node,
11280 508 : RAW_DATA_UCHAR_ELT (value, i));
11281 508 : vec_safe_push (cexpr_list, expr);
11282 : }
11283 2 : c_parser_consume_token (parser);
11284 2 : continue;
11285 2 : }
11286 15149472 : expr = c_parser_expr_no_commas (parser, NULL);
11287 15149472 : vec_safe_push (cexpr_list, expr);
11288 : }
11289 :
11290 1561819 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11291 1561819 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
11292 : return false;
11293 :
11294 1561819 : *ret_cexpr_list = cexpr_list;
11295 1561819 : return true;
11296 : }
11297 :
11298 : /* This represents a single generic-association. */
11299 :
11300 : struct c_generic_association
11301 : {
11302 : /* The location of the starting token of the type. */
11303 : location_t type_location;
11304 : /* The association's type, or NULL_TREE for 'default'. */
11305 : tree type;
11306 : /* The association's expression. */
11307 : struct c_expr expression;
11308 : };
11309 :
11310 : /* Parse a generic-selection. (C11 6.5.1.1).
11311 :
11312 : generic-selection:
11313 : _Generic ( generic-controlling-operand , generic-assoc-list )
11314 :
11315 : generic-controlling-operand:
11316 : assignment-expression
11317 : type-name
11318 :
11319 : (The use of a type-name is new in C2Y.)
11320 :
11321 : generic-assoc-list:
11322 : generic-association
11323 : generic-assoc-list , generic-association
11324 :
11325 : generic-association:
11326 : type-name : assignment-expression
11327 : default : assignment-expression
11328 : */
11329 :
11330 : static struct c_expr
11331 711 : c_parser_generic_selection (c_parser *parser)
11332 : {
11333 711 : struct c_expr selector, error_expr;
11334 711 : tree selector_type;
11335 711 : struct c_generic_association matched_assoc;
11336 711 : int match_found = -1;
11337 711 : location_t generic_loc, selector_loc;
11338 :
11339 711 : error_expr.original_code = ERROR_MARK;
11340 711 : error_expr.original_type = NULL;
11341 711 : error_expr.set_error ();
11342 711 : matched_assoc.type_location = UNKNOWN_LOCATION;
11343 711 : matched_assoc.type = NULL_TREE;
11344 711 : matched_assoc.expression = error_expr;
11345 :
11346 711 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
11347 711 : generic_loc = c_parser_peek_token (parser)->location;
11348 711 : c_parser_consume_token (parser);
11349 711 : if (flag_isoc99)
11350 709 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11351 : "ISO C99 does not support %<_Generic%>");
11352 : else
11353 2 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11354 : "ISO C90 does not support %<_Generic%>");
11355 :
11356 711 : matching_parens parens;
11357 711 : if (!parens.require_open (parser))
11358 0 : return error_expr;
11359 :
11360 711 : selector_loc = c_parser_peek_token (parser)->location;
11361 711 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
11362 : {
11363 38 : c_inhibit_evaluation_warnings++;
11364 38 : pedwarn_c23 (selector_loc, OPT_Wpedantic,
11365 : "ISO C does not support use of type name as %<_Generic%> "
11366 : "controlling operand before C2Y");
11367 38 : struct c_type_name *type = c_parser_type_name (parser);
11368 38 : if (type)
11369 37 : selector_type = groktypename (type, NULL, NULL);
11370 38 : c_inhibit_evaluation_warnings--;
11371 38 : if (!type)
11372 : {
11373 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11374 1 : return error_expr;
11375 : }
11376 : }
11377 : else
11378 : {
11379 673 : c_inhibit_evaluation_warnings++;
11380 673 : in_generic++;
11381 673 : selector = c_parser_expr_no_commas (parser, NULL);
11382 673 : selector = default_function_array_conversion (selector_loc, selector);
11383 673 : c_inhibit_evaluation_warnings--;
11384 673 : in_generic--;
11385 673 : pop_maybe_used (!flag_isoc23);
11386 :
11387 673 : if (selector.value == error_mark_node)
11388 : {
11389 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11390 0 : return selector;
11391 : }
11392 673 : mark_exp_read (selector.value);
11393 673 : selector_type = TREE_TYPE (selector.value);
11394 : /* In ISO C terms, rvalues (including the controlling expression
11395 : of _Generic) do not have qualified types. */
11396 673 : if (TREE_CODE (selector_type) != ARRAY_TYPE)
11397 673 : selector_type = TYPE_MAIN_VARIANT (selector_type);
11398 : /* In ISO C terms, _Noreturn is not part of the type of expressions
11399 : such as &abort, but in GCC it is represented internally as a type
11400 : qualifier. */
11401 74 : if (FUNCTION_POINTER_TYPE_P (selector_type)
11402 677 : && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
11403 1 : selector_type
11404 1 : = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
11405 : }
11406 :
11407 710 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11408 : {
11409 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11410 0 : return error_expr;
11411 : }
11412 :
11413 710 : auto_vec<c_generic_association> associations;
11414 710 : struct maybe_used_decl *maybe_used_default = NULL;
11415 1960 : while (1)
11416 : {
11417 1335 : struct c_generic_association assoc, *iter;
11418 1335 : unsigned int ix;
11419 1335 : c_token *token = c_parser_peek_token (parser);
11420 :
11421 1335 : assoc.type_location = token->location;
11422 1335 : if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
11423 : {
11424 514 : c_parser_consume_token (parser);
11425 514 : assoc.type = NULL_TREE;
11426 : }
11427 : else
11428 : {
11429 821 : struct c_type_name *type_name;
11430 :
11431 821 : type_name = c_parser_type_name (parser);
11432 821 : if (type_name == NULL)
11433 : {
11434 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11435 1 : return error_expr;
11436 : }
11437 820 : assoc.type = grokgenassoc (type_name);
11438 820 : if (assoc.type == error_mark_node)
11439 : {
11440 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11441 0 : return error_expr;
11442 : }
11443 :
11444 820 : if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
11445 9 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11446 : "ISO C does not support %<_Generic%> association with "
11447 : "function type before C2Y");
11448 811 : else if (!COMPLETE_TYPE_P (assoc.type))
11449 13 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11450 : "ISO C does not support %<_Generic%> association with "
11451 : "incomplete type before C2Y");
11452 :
11453 820 : if (c_type_variably_modified_p (assoc.type))
11454 9 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11455 : "ISO C does not support %<_Generic%> association with "
11456 : "variably-modified type before C2Y");
11457 : }
11458 :
11459 1334 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
11460 : {
11461 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11462 0 : return error_expr;
11463 : }
11464 :
11465 1334 : bool match = assoc.type == NULL_TREE
11466 1334 : || comptypes (assoc.type, selector_type);
11467 :
11468 178 : if (!match)
11469 178 : c_inhibit_evaluation_warnings++;
11470 1334 : in_generic++;
11471 :
11472 1334 : assoc.expression = c_parser_expr_no_commas (parser, NULL);
11473 :
11474 1334 : if (!match)
11475 178 : c_inhibit_evaluation_warnings--;
11476 1334 : in_generic--;
11477 1334 : if (!match)
11478 178 : pop_maybe_used (!flag_isoc23);
11479 1156 : else if (assoc.type == NULL_TREE)
11480 514 : maybe_used_default = save_maybe_used ();
11481 : else
11482 642 : pop_maybe_used (true);
11483 :
11484 1334 : if (assoc.expression.value == error_mark_node)
11485 : {
11486 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11487 0 : return error_expr;
11488 : }
11489 :
11490 2073 : for (ix = 0; associations.iterate (ix, &iter); ++ix)
11491 : {
11492 739 : if (assoc.type == NULL_TREE)
11493 : {
11494 219 : if (iter->type == NULL_TREE)
11495 : {
11496 1 : error_at (assoc.type_location,
11497 : "duplicate %<default%> case in %<_Generic%>");
11498 1 : inform (iter->type_location, "original %<default%> is here");
11499 : }
11500 : }
11501 520 : else if (iter->type != NULL_TREE)
11502 : {
11503 178 : if (comptypes (assoc.type, iter->type))
11504 : {
11505 1 : error_at (assoc.type_location,
11506 : "%<_Generic%> specifies two compatible types");
11507 1 : inform (iter->type_location, "compatible type is here");
11508 : }
11509 : }
11510 : }
11511 :
11512 1334 : if (assoc.type == NULL_TREE)
11513 : {
11514 514 : if (match_found < 0)
11515 : {
11516 360 : matched_assoc = assoc;
11517 409 : match_found = associations.length ();
11518 : }
11519 : }
11520 820 : else if (match)
11521 : {
11522 642 : if (match_found < 0 || matched_assoc.type == NULL_TREE)
11523 : {
11524 642 : matched_assoc = assoc;
11525 980 : match_found = associations.length ();
11526 : }
11527 : else
11528 : {
11529 0 : error_at (assoc.type_location,
11530 : "%<_Generic%> selector matches multiple associations");
11531 0 : inform (matched_assoc.type_location,
11532 : "other match is here");
11533 : }
11534 : }
11535 :
11536 1334 : associations.safe_push (assoc);
11537 :
11538 1334 : if (c_parser_peek_token (parser)->type != CPP_COMMA)
11539 : break;
11540 625 : c_parser_consume_token (parser);
11541 625 : }
11542 :
11543 709 : if (match_found >= 0 && matched_assoc.type == NULL_TREE)
11544 : {
11545 : /* Declarations referenced in the default association are used. */
11546 64 : restore_maybe_used (maybe_used_default);
11547 64 : pop_maybe_used (true);
11548 : }
11549 645 : else if (maybe_used_default)
11550 : {
11551 : /* Declarations referenced in the default association are not used, but
11552 : are treated as used before C23. */
11553 8 : restore_maybe_used (maybe_used_default);
11554 8 : pop_maybe_used (!flag_isoc23);
11555 : }
11556 :
11557 : unsigned int ix;
11558 : struct c_generic_association *iter;
11559 2042 : FOR_EACH_VEC_ELT (associations, ix, iter)
11560 1333 : if (ix != (unsigned) match_found)
11561 628 : mark_exp_read (iter->expression.value);
11562 :
11563 709 : if (!parens.require_close (parser))
11564 : {
11565 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11566 0 : return error_expr;
11567 : }
11568 :
11569 709 : if (match_found < 0)
11570 : {
11571 4 : error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
11572 : "compatible with any association",
11573 : selector_type);
11574 4 : return error_expr;
11575 : }
11576 :
11577 705 : return matched_assoc.expression;
11578 710 : }
11579 :
11580 : /* Check the validity of a function pointer argument *EXPR (argument
11581 : position POS) to __builtin_tgmath. Return the number of function
11582 : arguments if possibly valid; return 0 having reported an error if
11583 : not valid. */
11584 :
11585 : static unsigned int
11586 1755 : check_tgmath_function (c_expr *expr, unsigned int pos)
11587 : {
11588 1755 : tree type = TREE_TYPE (expr->value);
11589 1755 : if (!FUNCTION_POINTER_TYPE_P (type))
11590 : {
11591 2 : error_at (expr->get_location (),
11592 : "argument %u of %<__builtin_tgmath%> is not a function pointer",
11593 : pos);
11594 2 : return 0;
11595 : }
11596 1753 : type = TREE_TYPE (type);
11597 1753 : if (!prototype_p (type))
11598 : {
11599 2 : error_at (expr->get_location (),
11600 : "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
11601 2 : return 0;
11602 : }
11603 1751 : if (stdarg_p (type))
11604 : {
11605 2 : error_at (expr->get_location (),
11606 : "argument %u of %<__builtin_tgmath%> has variable arguments",
11607 : pos);
11608 2 : return 0;
11609 : }
11610 1749 : unsigned int nargs = 0;
11611 1749 : function_args_iterator iter;
11612 1749 : tree t;
11613 4176 : FOREACH_FUNCTION_ARGS (type, t, iter)
11614 : {
11615 4176 : if (t == void_type_node)
11616 : break;
11617 2427 : nargs++;
11618 : }
11619 1749 : if (nargs == 0)
11620 : {
11621 2 : error_at (expr->get_location (),
11622 : "argument %u of %<__builtin_tgmath%> has no arguments", pos);
11623 2 : return 0;
11624 : }
11625 : return nargs;
11626 : }
11627 :
11628 : /* Ways in which a parameter or return value of a type-generic macro
11629 : may vary between the different functions the macro may call. */
11630 : enum tgmath_parm_kind
11631 : {
11632 : tgmath_fixed, tgmath_real, tgmath_complex
11633 : };
11634 :
11635 : /* Helper function for c_parser_postfix_expression. Parse predefined
11636 : identifiers. */
11637 :
11638 : static struct c_expr
11639 13278 : c_parser_predefined_identifier (c_parser *parser)
11640 : {
11641 13278 : location_t loc = c_parser_peek_token (parser)->location;
11642 13278 : switch (c_parser_peek_token (parser)->keyword)
11643 : {
11644 709 : case RID_FUNCTION_NAME:
11645 709 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11646 : "identifier", "__FUNCTION__");
11647 709 : break;
11648 6179 : case RID_PRETTY_FUNCTION_NAME:
11649 6179 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11650 : "identifier", "__PRETTY_FUNCTION__");
11651 6179 : break;
11652 6390 : case RID_C99_FUNCTION_NAME:
11653 6390 : pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
11654 : "%<__func__%> predefined identifier");
11655 6390 : break;
11656 0 : default:
11657 0 : gcc_unreachable ();
11658 : }
11659 :
11660 13278 : struct c_expr expr;
11661 13278 : expr.original_code = ERROR_MARK;
11662 13278 : expr.original_type = NULL;
11663 13278 : expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
11664 13278 : c_parser_peek_token (parser)->value);
11665 13278 : set_c_expr_source_range (&expr, loc, loc);
11666 13278 : expr.m_decimal = 0;
11667 13278 : c_parser_consume_token (parser);
11668 13278 : return expr;
11669 : }
11670 :
11671 : /* Check whether the REF has an counted-by object associated with it
11672 : through the "counted_by" attribute. */
11673 :
11674 : static bool
11675 80 : has_counted_by_object (tree ref)
11676 : {
11677 : /* Currently, there are two cases are valid:
11678 : A. when the ref is an indirect_ref to a call to the
11679 : .ACCESS_WITH_SIZE, return true. (this is for FAM)
11680 : B. when the ref is a call to .ACCESS_WITH_SIZE, return true.
11681 : (this is for pointer field inside a structure)
11682 : More cases can be included later when the counted_by attribute is
11683 : extended to other situations. */
11684 80 : if ((TREE_CODE (ref) == INDIRECT_REF
11685 25 : && is_access_with_size_p (TREE_OPERAND (ref, 0)))
11686 80 : || is_access_with_size_p (ref))
11687 50 : return true;
11688 : return false;
11689 : }
11690 :
11691 : /* Get the reference to the counted-by object associated with the REF. */
11692 :
11693 : static tree
11694 50 : get_counted_by_ref (tree ref)
11695 : {
11696 : /* Currently, there are two cases are valid:
11697 : A. when the ref is an indirect_ref to a call to the
11698 : .ACCESS_WITH_SIZE, return true. (this is for FAM)
11699 : B. when the ref is a call to .ACCESS_WITH_SIZE, return true.
11700 : (this is for pointer field inside a structure)
11701 : More cases can be included later when the counted_by attribute is
11702 : extended to other situations. */
11703 50 : if (TREE_CODE (ref) == INDIRECT_REF
11704 50 : && is_access_with_size_p (TREE_OPERAND (ref, 0)))
11705 25 : return CALL_EXPR_ARG (TREE_OPERAND (ref, 0), 1);
11706 25 : else if (is_access_with_size_p (ref))
11707 25 : return CALL_EXPR_ARG (ref, 1);
11708 :
11709 : return NULL_TREE;
11710 : }
11711 :
11712 : /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
11713 : C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
11714 : call c_parser_postfix_expression_after_paren_type on encountering them.
11715 :
11716 : postfix-expression:
11717 : primary-expression
11718 : postfix-expression [ expression ]
11719 : postfix-expression ( argument-expression-list[opt] )
11720 : postfix-expression . identifier
11721 : postfix-expression -> identifier
11722 : postfix-expression ++
11723 : postfix-expression --
11724 : ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
11725 : ( storage-class-specifiers[opt] type-name ) { initializer-list , }
11726 :
11727 : argument-expression-list:
11728 : argument-expression
11729 : argument-expression-list , argument-expression
11730 :
11731 : primary-expression:
11732 : identifier
11733 : constant
11734 : string-literal
11735 : ( expression )
11736 : generic-selection
11737 :
11738 : GNU extensions:
11739 :
11740 : primary-expression:
11741 : __func__
11742 : (treated as a keyword in GNU C)
11743 : __FUNCTION__
11744 : __PRETTY_FUNCTION__
11745 : ( compound-statement )
11746 : __builtin_va_arg ( assignment-expression , type-name )
11747 : __builtin_offsetof ( type-name , offsetof-member-designator )
11748 : __builtin_choose_expr ( assignment-expression ,
11749 : assignment-expression ,
11750 : assignment-expression )
11751 : __builtin_types_compatible_p ( type-name , type-name )
11752 : __builtin_tgmath ( expr-list )
11753 : __builtin_complex ( assignment-expression , assignment-expression )
11754 : __builtin_shuffle ( assignment-expression , assignment-expression )
11755 : __builtin_shuffle ( assignment-expression ,
11756 : assignment-expression ,
11757 : assignment-expression, )
11758 : __builtin_convertvector ( assignment-expression , type-name )
11759 : __builtin_assoc_barrier ( assignment-expression )
11760 :
11761 : offsetof-member-designator:
11762 : identifier
11763 : offsetof-member-designator . identifier
11764 : offsetof-member-designator [ expression ]
11765 :
11766 : Objective-C:
11767 :
11768 : primary-expression:
11769 : [ objc-receiver objc-message-args ]
11770 : @selector ( objc-selector-arg )
11771 : @protocol ( identifier )
11772 : @encode ( type-name )
11773 : objc-string-literal
11774 : Classname . identifier
11775 : */
11776 :
11777 : static struct c_expr
11778 235898210 : c_parser_postfix_expression (c_parser *parser)
11779 : {
11780 235898210 : struct c_expr expr, e1;
11781 235898210 : struct c_type_name *t1, *t2;
11782 235898210 : location_t loc = c_parser_peek_token (parser)->location;
11783 235898210 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
11784 235898210 : expr.original_code = ERROR_MARK;
11785 235898210 : expr.original_type = NULL;
11786 235898210 : expr.m_decimal = 0;
11787 235898210 : switch (c_parser_peek_token (parser)->type)
11788 : {
11789 50880176 : case CPP_NUMBER:
11790 50880176 : expr.value = c_parser_peek_token (parser)->value;
11791 50880176 : set_c_expr_source_range (&expr, tok_range);
11792 50880176 : loc = c_parser_peek_token (parser)->location;
11793 50880176 : expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
11794 50880176 : c_parser_consume_token (parser);
11795 50880176 : if (TREE_CODE (expr.value) == FIXED_CST
11796 50880176 : && !targetm.fixed_point_supported_p ())
11797 : {
11798 6 : error_at (loc, "fixed-point types not supported for this target");
11799 6 : expr.set_error ();
11800 : }
11801 : break;
11802 113305 : case CPP_CHAR:
11803 113305 : case CPP_CHAR16:
11804 113305 : case CPP_CHAR32:
11805 113305 : case CPP_UTF8CHAR:
11806 113305 : case CPP_WCHAR:
11807 113305 : expr.value = c_parser_peek_token (parser)->value;
11808 : /* For the purpose of warning when a pointer is compared with
11809 : a zero character constant. */
11810 113305 : expr.original_type = char_type_node;
11811 113305 : set_c_expr_source_range (&expr, tok_range);
11812 113305 : c_parser_consume_token (parser);
11813 113305 : break;
11814 1164664 : case CPP_STRING:
11815 1164664 : case CPP_STRING16:
11816 1164664 : case CPP_STRING32:
11817 1164664 : case CPP_WSTRING:
11818 1164664 : case CPP_UTF8STRING:
11819 1164664 : expr = c_parser_string_literal (parser, parser->translate_strings_p,
11820 : true);
11821 1164664 : break;
11822 0 : case CPP_OBJC_STRING:
11823 0 : gcc_assert (c_dialect_objc ());
11824 0 : expr.value
11825 0 : = objc_build_string_object (c_parser_peek_token (parser)->value);
11826 0 : set_c_expr_source_range (&expr, tok_range);
11827 0 : c_parser_consume_token (parser);
11828 0 : break;
11829 174587021 : case CPP_NAME:
11830 174587021 : switch (c_parser_peek_token (parser)->id_kind)
11831 : {
11832 174587019 : case C_ID_ID:
11833 174587019 : {
11834 174587019 : tree id = c_parser_peek_token (parser)->value;
11835 174587019 : c_parser_consume_token (parser);
11836 523761057 : expr.value = build_external_ref (loc, id,
11837 174587019 : (c_parser_peek_token (parser)->type
11838 : == CPP_OPEN_PAREN),
11839 : &expr.original_type);
11840 174587019 : set_c_expr_source_range (&expr, tok_range);
11841 174587019 : break;
11842 : }
11843 0 : case C_ID_CLASSNAME:
11844 0 : {
11845 : /* Here we parse the Objective-C 2.0 Class.name dot
11846 : syntax. */
11847 0 : tree class_name = c_parser_peek_token (parser)->value;
11848 0 : tree component;
11849 0 : c_parser_consume_token (parser);
11850 0 : gcc_assert (c_dialect_objc ());
11851 0 : if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
11852 : {
11853 0 : expr.set_error ();
11854 0 : break;
11855 : }
11856 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
11857 : {
11858 0 : c_parser_error (parser, "expected identifier");
11859 0 : expr.set_error ();
11860 0 : break;
11861 : }
11862 0 : c_token *component_tok = c_parser_peek_token (parser);
11863 0 : component = component_tok->value;
11864 0 : location_t end_loc = component_tok->get_finish ();
11865 0 : c_parser_consume_token (parser);
11866 0 : expr.value = objc_build_class_component_ref (class_name,
11867 : component);
11868 0 : set_c_expr_source_range (&expr, loc, end_loc);
11869 0 : break;
11870 : }
11871 2 : default:
11872 2 : c_parser_error (parser, "expected expression");
11873 2 : expr.set_error ();
11874 2 : break;
11875 : }
11876 : break;
11877 7516556 : case CPP_OPEN_PAREN:
11878 : /* A parenthesized expression, statement expression or compound
11879 : literal. */
11880 7516556 : if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
11881 : {
11882 : /* A statement expression. */
11883 34875 : tree stmt;
11884 34875 : location_t brace_loc;
11885 34875 : bool save_c_omp_array_section_p = c_omp_array_section_p;
11886 34875 : c_parser_consume_token (parser);
11887 34875 : brace_loc = c_parser_peek_token (parser)->location;
11888 34875 : c_parser_consume_token (parser);
11889 : /* If we've not yet started the current function's statement list,
11890 : or we're in the parameter scope of an old-style function
11891 : declaration, statement expressions are not allowed. */
11892 34875 : if (!building_stmt_list_p () || old_style_parameter_scope ())
11893 : {
11894 24 : error_at (loc, "braced-group within expression allowed "
11895 : "only inside a function");
11896 24 : parser->error = true;
11897 24 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
11898 24 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11899 24 : expr.set_error ();
11900 24 : break;
11901 : }
11902 34851 : c_omp_array_section_p = false;
11903 34851 : stmt = c_begin_stmt_expr ();
11904 34851 : c_parser_compound_statement_nostart (parser);
11905 34851 : location_t close_loc = c_parser_peek_token (parser)->location;
11906 34851 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11907 : "expected %<)%>");
11908 34851 : pedwarn (loc, OPT_Wpedantic,
11909 : "ISO C forbids braced-groups within expressions");
11910 34851 : expr.value = c_finish_stmt_expr (brace_loc, stmt);
11911 34851 : set_c_expr_source_range (&expr, loc, close_loc);
11912 34851 : mark_exp_read (expr.value);
11913 34851 : c_omp_array_section_p = save_c_omp_array_section_p;
11914 : }
11915 : else
11916 : {
11917 : /* A parenthesized expression. */
11918 7481681 : location_t loc_open_paren = c_parser_peek_token (parser)->location;
11919 7481681 : c_parser_consume_token (parser);
11920 7481681 : expr = c_parser_expression (parser);
11921 7481681 : if (TREE_CODE (expr.value) == MODIFY_EXPR)
11922 38243 : suppress_warning (expr.value, OPT_Wparentheses);
11923 7481681 : if (expr.original_code != C_MAYBE_CONST_EXPR
11924 7481669 : && expr.original_code != SIZEOF_EXPR)
11925 7476768 : expr.original_code = ERROR_MARK;
11926 : /* Remember that we saw ( ) around the sizeof. */
11927 7481681 : if (expr.original_code == SIZEOF_EXPR)
11928 4901 : expr.original_code = PAREN_SIZEOF_EXPR;
11929 : /* Don't change EXPR.ORIGINAL_TYPE. */
11930 7481681 : location_t loc_close_paren = c_parser_peek_token (parser)->location;
11931 7481681 : set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
11932 7481681 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11933 : "expected %<)%>", loc_open_paren);
11934 : }
11935 : break;
11936 1635693 : case CPP_KEYWORD:
11937 1635693 : switch (c_parser_peek_token (parser)->keyword)
11938 : {
11939 13258 : case RID_FUNCTION_NAME:
11940 13258 : case RID_PRETTY_FUNCTION_NAME:
11941 13258 : case RID_C99_FUNCTION_NAME:
11942 13258 : expr = c_parser_predefined_identifier (parser);
11943 13258 : break;
11944 19884 : case RID_VA_ARG:
11945 19884 : {
11946 19884 : location_t start_loc = loc;
11947 19884 : c_parser_consume_token (parser);
11948 19884 : matching_parens parens;
11949 19884 : if (!parens.require_open (parser))
11950 : {
11951 0 : expr.set_error ();
11952 0 : break;
11953 : }
11954 19884 : e1 = c_parser_expr_no_commas (parser, NULL);
11955 19884 : mark_exp_read (e1.value);
11956 19884 : e1.value = c_fully_fold (e1.value, false, NULL);
11957 19884 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11958 : {
11959 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11960 0 : expr.set_error ();
11961 0 : break;
11962 : }
11963 19884 : loc = c_parser_peek_token (parser)->location;
11964 19884 : t1 = c_parser_type_name (parser);
11965 19884 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11966 19884 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11967 : "expected %<)%>");
11968 19884 : if (t1 == NULL)
11969 : {
11970 0 : expr.set_error ();
11971 : }
11972 : else
11973 : {
11974 19884 : tree type_expr = NULL_TREE;
11975 19884 : tree type = groktypename (t1, &type_expr, NULL);
11976 19884 : expr.value = c_build_va_arg (start_loc, e1.value, loc,
11977 : type, type_expr);
11978 19884 : set_c_expr_source_range (&expr, start_loc, end_loc);
11979 : }
11980 : }
11981 19884 : break;
11982 13619 : case RID_C23_VA_START:
11983 13619 : {
11984 13619 : c_parser_consume_token (parser);
11985 13619 : matching_parens parens;
11986 13619 : if (!parens.require_open (parser))
11987 : {
11988 0 : expr.set_error ();
11989 0 : break;
11990 : }
11991 13619 : e1 = c_parser_expr_no_commas (parser, NULL);
11992 13619 : e1 = convert_lvalue_to_rvalue (e1.get_location (), e1, true, true);
11993 13619 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11994 : {
11995 13441 : location_t cloc = c_parser_peek_token (parser)->location;
11996 13441 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11997 : {
11998 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11999 0 : expr.set_error ();
12000 0 : break;
12001 : }
12002 13441 : if (c_parser_next_token_is (parser, CPP_NAME)
12003 13436 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
12004 26877 : && (c_parser_peek_2nd_token (parser)->type
12005 : == CPP_CLOSE_PAREN))
12006 : {
12007 13415 : tree name = c_parser_peek_token (parser)->value;
12008 13415 : location_t nloc = c_parser_peek_token (parser)->location;
12009 13415 : tree decl = lookup_name (name);
12010 13415 : tree last_parm
12011 13415 : = tree_last (DECL_ARGUMENTS (current_function_decl));
12012 13415 : if (!last_parm || decl != last_parm)
12013 4 : warning_at (nloc, OPT_Wvarargs,
12014 : "optional second parameter of %<va_start%> "
12015 : "not last named argument");
12016 13411 : else if (DECL_REGISTER (decl))
12017 2 : warning_at (nloc, OPT_Wvarargs,
12018 : "undefined behavior when second parameter "
12019 : "of %<va_start%> is declared with "
12020 : "%<register%> storage");
12021 13415 : c_parser_consume_token (parser);
12022 : }
12023 : else
12024 : {
12025 26 : unsigned nesting_depth = 0;
12026 26 : location_t sloc = c_parser_peek_token (parser)->location;
12027 26 : location_t eloc = sloc;
12028 :
12029 : /* For va_start (ap,) the ) comes from stdarg.h.
12030 : Use location of , in that case, otherwise without
12031 : -Wsystem-headers nothing is reported. After all,
12032 : the problematic token is the comma in that case. */
12033 26 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
12034 1 : sloc = eloc = cloc;
12035 492 : while (true)
12036 : {
12037 259 : c_token *token = c_parser_peek_token (parser);
12038 259 : if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
12039 : break;
12040 :
12041 233 : if (token->type == CPP_EOF)
12042 : break;
12043 233 : if (token->type == CPP_OPEN_PAREN)
12044 8 : ++nesting_depth;
12045 225 : else if (token->type == CPP_CLOSE_PAREN)
12046 8 : --nesting_depth;
12047 233 : eloc = token->location;
12048 233 : c_parser_consume_token (parser);
12049 233 : }
12050 26 : if (sloc != eloc)
12051 25 : sloc = make_location (sloc, sloc, eloc);
12052 26 : warning_at (sloc, OPT_Wvarargs,
12053 : "%<va_start%> macro used with additional "
12054 : "arguments other than identifier of the "
12055 : "last named argument");
12056 : }
12057 : }
12058 13619 : parens.skip_until_found_close (parser);
12059 13619 : tree fndecl = builtin_decl_explicit (BUILT_IN_VA_START);
12060 13619 : vec<tree, va_gc> *params;
12061 13619 : vec_alloc (params, 2);
12062 13619 : params->quick_push (e1.value);
12063 13619 : params->quick_push (integer_zero_node);
12064 13619 : auto_vec<location_t> arg_loc (2);
12065 13619 : arg_loc.quick_push (e1.get_location ());
12066 13619 : arg_loc.quick_push (UNKNOWN_LOCATION);
12067 13619 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
12068 : params, NULL);
12069 13619 : set_c_expr_source_range (&expr, loc,
12070 : parser->tokens_buf[0].get_finish ());
12071 13619 : expr.m_decimal = 0;
12072 13619 : expr.original_code = ERROR_MARK;
12073 13619 : expr.original_type = NULL;
12074 13619 : release_tree_vector (params);
12075 13619 : break;
12076 13619 : }
12077 3628 : case RID_OFFSETOF:
12078 3628 : {
12079 3628 : c_parser_consume_token (parser);
12080 3628 : matching_parens parens;
12081 3628 : if (!parens.require_open (parser))
12082 : {
12083 0 : expr.set_error ();
12084 1 : break;
12085 : }
12086 3628 : t1 = c_parser_type_name (parser);
12087 3628 : if (t1 == NULL)
12088 0 : parser->error = true;
12089 3628 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
12090 1 : gcc_assert (parser->error);
12091 3628 : if (parser->error)
12092 : {
12093 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
12094 1 : expr.set_error ();
12095 1 : break;
12096 : }
12097 3627 : tree type = groktypename (t1, NULL, NULL);
12098 3627 : tree offsetof_ref;
12099 3627 : if (type == error_mark_node)
12100 : offsetof_ref = error_mark_node;
12101 : else
12102 : {
12103 3626 : offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
12104 3626 : SET_EXPR_LOCATION (offsetof_ref, loc);
12105 : }
12106 : /* Parse the second argument to __builtin_offsetof. We
12107 : must have one identifier, and beyond that we want to
12108 : accept sub structure and sub array references. */
12109 3627 : if (c_parser_next_token_is (parser, CPP_NAME))
12110 : {
12111 3627 : c_token *comp_tok = c_parser_peek_token (parser);
12112 3627 : offsetof_ref
12113 3627 : = build_component_ref (loc, offsetof_ref, comp_tok->value,
12114 : comp_tok->location, UNKNOWN_LOCATION);
12115 3627 : c_parser_consume_token (parser);
12116 3627 : while (c_parser_next_token_is (parser, CPP_DOT)
12117 4089 : || c_parser_next_token_is (parser,
12118 : CPP_OPEN_SQUARE)
12119 7955 : || c_parser_next_token_is (parser,
12120 : CPP_DEREF))
12121 : {
12122 700 : if (c_parser_next_token_is (parser, CPP_DEREF))
12123 : {
12124 1 : loc = c_parser_peek_token (parser)->location;
12125 1 : offsetof_ref = build_array_ref (loc,
12126 : offsetof_ref,
12127 : integer_zero_node);
12128 1 : goto do_dot;
12129 : }
12130 699 : else if (c_parser_next_token_is (parser, CPP_DOT))
12131 : {
12132 238 : do_dot:
12133 239 : c_parser_consume_token (parser);
12134 239 : if (c_parser_next_token_is_not (parser,
12135 : CPP_NAME))
12136 : {
12137 0 : c_parser_error (parser, "expected identifier");
12138 0 : break;
12139 : }
12140 239 : c_token *comp_tok = c_parser_peek_token (parser);
12141 239 : offsetof_ref
12142 239 : = build_component_ref (loc, offsetof_ref,
12143 : comp_tok->value,
12144 : comp_tok->location,
12145 : UNKNOWN_LOCATION);
12146 239 : c_parser_consume_token (parser);
12147 : }
12148 : else
12149 : {
12150 461 : struct c_expr ce;
12151 461 : tree idx;
12152 461 : loc = c_parser_peek_token (parser)->location;
12153 461 : c_parser_consume_token (parser);
12154 461 : ce = c_parser_expression (parser);
12155 461 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
12156 461 : idx = ce.value;
12157 461 : idx = c_fully_fold (idx, false, NULL);
12158 461 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
12159 : "expected %<]%>");
12160 461 : offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
12161 : }
12162 : }
12163 : }
12164 : else
12165 0 : c_parser_error (parser, "expected identifier");
12166 3627 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12167 3627 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
12168 : "expected %<)%>");
12169 3627 : expr.value = fold_offsetof (offsetof_ref);
12170 3627 : set_c_expr_source_range (&expr, loc, end_loc);
12171 : }
12172 3627 : break;
12173 1167 : case RID_CHOOSE_EXPR:
12174 1167 : {
12175 1167 : vec<c_expr_t, va_gc> *cexpr_list;
12176 1167 : c_expr_t *e1_p, *e2_p, *e3_p;
12177 1167 : tree c;
12178 1167 : location_t close_paren_loc;
12179 :
12180 1167 : c_parser_consume_token (parser);
12181 1167 : if (!c_parser_get_builtin_args (parser,
12182 : "__builtin_choose_expr",
12183 : &cexpr_list, true,
12184 : &close_paren_loc))
12185 : {
12186 0 : expr.set_error ();
12187 0 : break;
12188 : }
12189 :
12190 1167 : if (vec_safe_length (cexpr_list) != 3)
12191 : {
12192 0 : error_at (loc, "wrong number of arguments to "
12193 : "%<__builtin_choose_expr%>");
12194 0 : expr.set_error ();
12195 0 : break;
12196 : }
12197 :
12198 1167 : e1_p = &(*cexpr_list)[0];
12199 1167 : e2_p = &(*cexpr_list)[1];
12200 1167 : e3_p = &(*cexpr_list)[2];
12201 :
12202 1167 : c = e1_p->value;
12203 1167 : mark_exp_read (e2_p->value);
12204 1167 : mark_exp_read (e3_p->value);
12205 1167 : if (TREE_CODE (c) != INTEGER_CST
12206 1167 : || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
12207 7 : error_at (loc,
12208 : "first argument to %<__builtin_choose_expr%> not"
12209 : " a constant");
12210 1167 : constant_expression_warning (c);
12211 1167 : expr = integer_zerop (c) ? *e3_p : *e2_p;
12212 1167 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12213 1167 : break;
12214 : }
12215 673 : case RID_TYPES_COMPATIBLE_P:
12216 673 : {
12217 673 : c_parser_consume_token (parser);
12218 673 : matching_parens parens;
12219 673 : if (!parens.require_open (parser))
12220 : {
12221 0 : expr.set_error ();
12222 2 : break;
12223 : }
12224 673 : t1 = c_parser_type_name (parser);
12225 673 : if (t1 == NULL)
12226 : {
12227 0 : expr.set_error ();
12228 0 : break;
12229 : }
12230 673 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
12231 : {
12232 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
12233 1 : expr.set_error ();
12234 1 : break;
12235 : }
12236 672 : t2 = c_parser_type_name (parser);
12237 672 : if (t2 == NULL)
12238 : {
12239 0 : expr.set_error ();
12240 0 : break;
12241 : }
12242 672 : location_t close_paren_loc = c_parser_peek_token (parser)->location;
12243 672 : parens.skip_until_found_close (parser);
12244 672 : tree e1, e2;
12245 672 : e1 = groktypename (t1, NULL, NULL);
12246 672 : e2 = groktypename (t2, NULL, NULL);
12247 672 : if (e1 == error_mark_node || e2 == error_mark_node)
12248 : {
12249 1 : expr.set_error ();
12250 1 : break;
12251 : }
12252 :
12253 671 : e1 = TYPE_MAIN_VARIANT (e1);
12254 671 : e2 = TYPE_MAIN_VARIANT (e2);
12255 :
12256 671 : expr.value
12257 671 : = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
12258 671 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12259 : }
12260 671 : break;
12261 356 : case RID_BUILTIN_TGMATH:
12262 356 : {
12263 356 : vec<c_expr_t, va_gc> *cexpr_list;
12264 356 : location_t close_paren_loc;
12265 :
12266 356 : c_parser_consume_token (parser);
12267 356 : if (!c_parser_get_builtin_args (parser,
12268 : "__builtin_tgmath",
12269 : &cexpr_list, false,
12270 : &close_paren_loc))
12271 : {
12272 0 : expr.set_error ();
12273 327 : break;
12274 : }
12275 :
12276 356 : if (vec_safe_length (cexpr_list) < 3)
12277 : {
12278 3 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12279 3 : expr.set_error ();
12280 3 : break;
12281 : }
12282 :
12283 : unsigned int i;
12284 : c_expr_t *p;
12285 2587 : FOR_EACH_VEC_ELT (*cexpr_list, i, p)
12286 2234 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12287 353 : unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1);
12288 353 : if (nargs == 0)
12289 : {
12290 4 : expr.set_error ();
12291 4 : break;
12292 : }
12293 698 : if (vec_safe_length (cexpr_list) < nargs)
12294 : {
12295 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12296 1 : expr.set_error ();
12297 1 : break;
12298 : }
12299 348 : unsigned int num_functions = vec_safe_length (cexpr_list) - nargs;
12300 348 : if (num_functions < 2)
12301 : {
12302 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12303 1 : expr.set_error ();
12304 1 : break;
12305 : }
12306 :
12307 : /* The first NUM_FUNCTIONS expressions are the function
12308 : pointers. The remaining NARGS expressions are the
12309 : arguments that are to be passed to one of those
12310 : functions, chosen following <tgmath.h> rules. */
12311 1744 : for (unsigned int j = 1; j < num_functions; j++)
12312 : {
12313 1402 : unsigned int this_nargs
12314 1402 : = check_tgmath_function (&(*cexpr_list)[j], j + 1);
12315 1402 : if (this_nargs == 0)
12316 : {
12317 4 : expr.set_error ();
12318 29 : goto out;
12319 : }
12320 1398 : if (this_nargs != nargs)
12321 : {
12322 1 : error_at ((*cexpr_list)[j].get_location (),
12323 : "argument %u of %<__builtin_tgmath%> has "
12324 : "wrong number of arguments", j + 1);
12325 1 : expr.set_error ();
12326 1 : goto out;
12327 : }
12328 : }
12329 :
12330 : /* The functions all have the same number of arguments.
12331 : Determine whether arguments and return types vary in
12332 : ways permitted for <tgmath.h> functions. */
12333 : /* The first entry in each of these vectors is for the
12334 : return type, subsequent entries for parameter
12335 : types. */
12336 342 : auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
12337 342 : auto_vec<tree> parm_first (nargs + 1);
12338 342 : auto_vec<bool> parm_complex (nargs + 1);
12339 342 : auto_vec<bool> parm_varies (nargs + 1);
12340 342 : tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
12341 342 : tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
12342 342 : parm_first.quick_push (first_ret);
12343 342 : parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
12344 342 : parm_varies.quick_push (false);
12345 342 : function_args_iterator iter;
12346 342 : tree t;
12347 342 : unsigned int argpos;
12348 802 : FOREACH_FUNCTION_ARGS (first_type, t, iter)
12349 : {
12350 802 : if (t == void_type_node)
12351 : break;
12352 460 : parm_first.quick_push (TYPE_MAIN_VARIANT (t));
12353 460 : parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
12354 460 : parm_varies.quick_push (false);
12355 : }
12356 1727 : for (unsigned int j = 1; j < num_functions; j++)
12357 : {
12358 1397 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12359 1397 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12360 1397 : if (ret != parm_first[0])
12361 : {
12362 1294 : parm_varies[0] = true;
12363 1294 : if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
12364 1294 : && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
12365 : {
12366 3 : error_at ((*cexpr_list)[0].get_location (),
12367 : "invalid type-generic return type for "
12368 : "argument %u of %<__builtin_tgmath%>",
12369 : 1);
12370 3 : expr.set_error ();
12371 3 : goto out;
12372 : }
12373 1291 : if (!SCALAR_FLOAT_TYPE_P (ret)
12374 1291 : && !COMPLEX_FLOAT_TYPE_P (ret))
12375 : {
12376 3 : error_at ((*cexpr_list)[j].get_location (),
12377 : "invalid type-generic return type for "
12378 : "argument %u of %<__builtin_tgmath%>",
12379 : j + 1);
12380 3 : expr.set_error ();
12381 3 : goto out;
12382 : }
12383 : }
12384 1391 : if (TREE_CODE (ret) == COMPLEX_TYPE)
12385 342 : parm_complex[0] = true;
12386 1391 : argpos = 1;
12387 3329 : FOREACH_FUNCTION_ARGS (type, t, iter)
12388 : {
12389 3329 : if (t == void_type_node)
12390 : break;
12391 1944 : t = TYPE_MAIN_VARIANT (t);
12392 1944 : if (t != parm_first[argpos])
12393 : {
12394 1919 : parm_varies[argpos] = true;
12395 1919 : if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
12396 1919 : && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
12397 : {
12398 3 : error_at ((*cexpr_list)[0].get_location (),
12399 : "invalid type-generic type for "
12400 : "argument %u of argument %u of "
12401 : "%<__builtin_tgmath%>", argpos, 1);
12402 3 : expr.set_error ();
12403 3 : goto out;
12404 : }
12405 1916 : if (!SCALAR_FLOAT_TYPE_P (t)
12406 1916 : && !COMPLEX_FLOAT_TYPE_P (t))
12407 : {
12408 3 : error_at ((*cexpr_list)[j].get_location (),
12409 : "invalid type-generic type for "
12410 : "argument %u of argument %u of "
12411 : "%<__builtin_tgmath%>", argpos, j + 1);
12412 3 : expr.set_error ();
12413 3 : goto out;
12414 : }
12415 : }
12416 1938 : if (TREE_CODE (t) == COMPLEX_TYPE)
12417 674 : parm_complex[argpos] = true;
12418 1938 : argpos++;
12419 : }
12420 : }
12421 : enum tgmath_parm_kind max_variation = tgmath_fixed;
12422 1108 : for (unsigned int j = 0; j <= nargs; j++)
12423 : {
12424 778 : enum tgmath_parm_kind this_kind;
12425 778 : if (parm_varies[j])
12426 : {
12427 731 : if (parm_complex[j])
12428 394 : max_variation = this_kind = tgmath_complex;
12429 : else
12430 : {
12431 337 : this_kind = tgmath_real;
12432 337 : if (max_variation != tgmath_complex)
12433 778 : max_variation = tgmath_real;
12434 : }
12435 : }
12436 : else
12437 47 : this_kind = tgmath_fixed;
12438 778 : parm_kind.quick_push (this_kind);
12439 : }
12440 330 : if (max_variation == tgmath_fixed)
12441 : {
12442 1 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12443 : "all have the same type");
12444 1 : expr.set_error ();
12445 1 : break;
12446 : }
12447 :
12448 : /* Identify a parameter (not the return type) that varies,
12449 : including with complex types if any variation includes
12450 : complex types; there must be at least one such
12451 : parameter. */
12452 341 : unsigned int tgarg = 0;
12453 341 : for (unsigned int j = 1; j <= nargs; j++)
12454 339 : if (parm_kind[j] == max_variation)
12455 : {
12456 : tgarg = j;
12457 : break;
12458 : }
12459 329 : if (tgarg == 0)
12460 : {
12461 2 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12462 : "lack type-generic parameter");
12463 2 : expr.set_error ();
12464 2 : break;
12465 : }
12466 :
12467 : /* Determine the type of the relevant parameter for each
12468 : function. */
12469 327 : auto_vec<tree> tg_type (num_functions);
12470 2035 : for (unsigned int j = 0; j < num_functions; j++)
12471 : {
12472 1708 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12473 1708 : argpos = 1;
12474 1738 : FOREACH_FUNCTION_ARGS (type, t, iter)
12475 : {
12476 1738 : if (argpos == tgarg)
12477 : {
12478 1708 : tg_type.quick_push (TYPE_MAIN_VARIANT (t));
12479 1708 : break;
12480 : }
12481 30 : argpos++;
12482 : }
12483 : }
12484 :
12485 : /* Verify that the corresponding types are different for
12486 : all the listed functions. Also determine whether all
12487 : the types are complex, whether all the types are
12488 : standard or binary, and whether all the types are
12489 : decimal. */
12490 327 : bool all_complex = true;
12491 327 : bool all_binary = true;
12492 327 : bool all_decimal = true;
12493 327 : hash_set<tree> tg_types;
12494 2687 : FOR_EACH_VEC_ELT (tg_type, i, t)
12495 : {
12496 1708 : if (TREE_CODE (t) == COMPLEX_TYPE)
12497 : all_decimal = false;
12498 : else
12499 : {
12500 1186 : all_complex = false;
12501 1186 : if (DECIMAL_FLOAT_TYPE_P (t))
12502 : all_binary = false;
12503 : else
12504 : all_decimal = false;
12505 : }
12506 1708 : if (tg_types.add (t))
12507 : {
12508 1 : error_at ((*cexpr_list)[i].get_location (),
12509 : "duplicate type-generic parameter type for "
12510 : "function argument %u of %<__builtin_tgmath%>",
12511 : i + 1);
12512 1 : expr.set_error ();
12513 1 : goto out;
12514 : }
12515 : }
12516 :
12517 : /* Verify that other parameters and the return type whose
12518 : types vary have their types varying in the correct
12519 : way. */
12520 2029 : for (unsigned int j = 0; j < num_functions; j++)
12521 : {
12522 1705 : tree exp_type = tg_type[j];
12523 1705 : tree exp_real_type = exp_type;
12524 1705 : if (TREE_CODE (exp_type) == COMPLEX_TYPE)
12525 522 : exp_real_type = TREE_TYPE (exp_type);
12526 1705 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12527 1705 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12528 2606 : if ((parm_kind[0] == tgmath_complex && ret != exp_type)
12529 2606 : || (parm_kind[0] == tgmath_real && ret != exp_real_type))
12530 : {
12531 1 : error_at ((*cexpr_list)[j].get_location (),
12532 : "bad return type for function argument %u "
12533 : "of %<__builtin_tgmath%>", j + 1);
12534 1 : expr.set_error ();
12535 1 : goto out;
12536 : }
12537 1704 : argpos = 1;
12538 4078 : FOREACH_FUNCTION_ARGS (type, t, iter)
12539 : {
12540 4078 : if (t == void_type_node)
12541 : break;
12542 2375 : t = TYPE_MAIN_VARIANT (t);
12543 2375 : if ((parm_kind[argpos] == tgmath_complex
12544 1787 : && t != exp_type)
12545 4162 : || (parm_kind[argpos] == tgmath_real
12546 558 : && t != exp_real_type))
12547 : {
12548 1 : error_at ((*cexpr_list)[j].get_location (),
12549 : "bad type for argument %u of "
12550 : "function argument %u of "
12551 : "%<__builtin_tgmath%>", argpos, j + 1);
12552 1 : expr.set_error ();
12553 1 : goto out;
12554 : }
12555 2374 : argpos++;
12556 : }
12557 : }
12558 :
12559 : /* The functions listed are a valid set of functions for a
12560 : <tgmath.h> macro to select between. Identify the
12561 : matching function, if any. First, the argument types
12562 : must be combined following <tgmath.h> rules. Integer
12563 : types are treated as _Decimal64 if any type-generic
12564 : argument is decimal, or if the only alternatives for
12565 : type-generic arguments are of decimal types, and are
12566 : otherwise treated as _Float32x (or _Complex _Float32x
12567 : for complex integer types) if any type-generic argument
12568 : has _FloatNx type, otherwise as double (or _Complex
12569 : double for complex integer types). After that
12570 : adjustment, types are combined following the usual
12571 : arithmetic conversions. If the function only accepts
12572 : complex arguments, a complex type is produced. */
12573 : bool arg_complex = all_complex;
12574 : bool arg_binary = all_binary;
12575 : bool arg_int_decimal = all_decimal;
12576 : bool arg_int_floatnx = false;
12577 : bool arg_int_decimalx = false;
12578 756 : for (unsigned int j = 1; j <= nargs; j++)
12579 : {
12580 441 : if (parm_kind[j] == tgmath_fixed)
12581 10 : continue;
12582 431 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12583 431 : tree type = TREE_TYPE (ce->value);
12584 431 : if (!INTEGRAL_TYPE_P (type)
12585 431 : && !SCALAR_FLOAT_TYPE_P (type)
12586 89 : && TREE_CODE (type) != COMPLEX_TYPE)
12587 : {
12588 1 : error_at (ce->get_location (),
12589 : "invalid type of argument %u of type-generic "
12590 : "function", j);
12591 1 : expr.set_error ();
12592 1 : goto out;
12593 : }
12594 430 : if (DECIMAL_FLOAT_TYPE_P (type))
12595 : {
12596 68 : arg_int_decimal = true;
12597 68 : if (all_complex)
12598 : {
12599 1 : error_at (ce->get_location (),
12600 : "decimal floating-point argument %u to "
12601 : "complex-only type-generic function", j);
12602 1 : expr.set_error ();
12603 1 : goto out;
12604 : }
12605 67 : else if (all_binary)
12606 : {
12607 1 : error_at (ce->get_location (),
12608 : "decimal floating-point argument %u to "
12609 : "binary-only type-generic function", j);
12610 1 : expr.set_error ();
12611 1 : goto out;
12612 : }
12613 66 : else if (arg_complex)
12614 : {
12615 1 : error_at (ce->get_location (),
12616 : "both complex and decimal floating-point "
12617 : "arguments to type-generic function");
12618 1 : expr.set_error ();
12619 1 : goto out;
12620 : }
12621 65 : else if (arg_binary)
12622 : {
12623 1 : error_at (ce->get_location (),
12624 : "both binary and decimal floating-point "
12625 : "arguments to type-generic function");
12626 1 : expr.set_error ();
12627 1 : goto out;
12628 : }
12629 : }
12630 362 : else if (TREE_CODE (type) == COMPLEX_TYPE)
12631 : {
12632 88 : arg_complex = true;
12633 88 : if (COMPLEX_FLOAT_TYPE_P (type))
12634 : arg_binary = true;
12635 88 : if (all_decimal)
12636 : {
12637 1 : error_at (ce->get_location (),
12638 : "complex argument %u to "
12639 : "decimal-only type-generic function", j);
12640 1 : expr.set_error ();
12641 1 : goto out;
12642 : }
12643 87 : else if (arg_int_decimal)
12644 : {
12645 1 : error_at (ce->get_location (),
12646 : "both complex and decimal floating-point "
12647 : "arguments to type-generic function");
12648 1 : expr.set_error ();
12649 1 : goto out;
12650 : }
12651 : }
12652 274 : else if (SCALAR_FLOAT_TYPE_P (type))
12653 : {
12654 180 : arg_binary = true;
12655 180 : if (all_decimal)
12656 : {
12657 1 : error_at (ce->get_location (),
12658 : "binary argument %u to "
12659 : "decimal-only type-generic function", j);
12660 1 : expr.set_error ();
12661 1 : goto out;
12662 : }
12663 179 : else if (arg_int_decimal)
12664 : {
12665 1 : error_at (ce->get_location (),
12666 : "both binary and decimal floating-point "
12667 : "arguments to type-generic function");
12668 1 : expr.set_error ();
12669 1 : goto out;
12670 : }
12671 : }
12672 422 : tree rtype = TYPE_MAIN_VARIANT (type);
12673 422 : if (TREE_CODE (rtype) == COMPLEX_TYPE)
12674 86 : rtype = TREE_TYPE (rtype);
12675 422 : if (SCALAR_FLOAT_TYPE_P (rtype))
12676 1208 : for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
12677 908 : if (rtype == FLOATNX_TYPE_NODE (j))
12678 : {
12679 : arg_int_floatnx = true;
12680 : break;
12681 : }
12682 422 : if (rtype == dfloat64x_type_node)
12683 0 : arg_int_decimalx = true;
12684 : }
12685 : tree arg_real = NULL_TREE;
12686 743 : for (unsigned int j = 1; j <= nargs; j++)
12687 : {
12688 428 : if (parm_kind[j] == tgmath_fixed)
12689 10 : continue;
12690 418 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12691 418 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
12692 418 : if (TREE_CODE (type) == COMPLEX_TYPE)
12693 85 : type = TREE_TYPE (type);
12694 418 : if (INTEGRAL_TYPE_P (type))
12695 114 : type = (arg_int_decimalx
12696 114 : ? dfloat64x_type_node
12697 : : arg_int_floatnx
12698 114 : ? float32x_type_node
12699 : : arg_int_decimal
12700 106 : ? dfloat64_type_node
12701 : : double_type_node);
12702 418 : if (arg_real == NULL_TREE)
12703 : arg_real = type;
12704 : else
12705 103 : arg_real = common_type (arg_real, type);
12706 418 : if (arg_real == error_mark_node)
12707 : {
12708 0 : expr.set_error ();
12709 0 : goto out;
12710 : }
12711 : }
12712 315 : tree arg_type = (arg_complex
12713 315 : ? build_complex_type (arg_real)
12714 : : arg_real);
12715 :
12716 : /* Look for a function to call with type-generic parameter
12717 : type ARG_TYPE. */
12718 315 : c_expr_t *fn = NULL;
12719 976 : for (unsigned int j = 0; j < num_functions; j++)
12720 : {
12721 970 : if (tg_type[j] == arg_type)
12722 : {
12723 309 : fn = &(*cexpr_list)[j];
12724 309 : break;
12725 : }
12726 : }
12727 315 : if (fn == NULL
12728 6 : && parm_kind[0] == tgmath_fixed
12729 4 : && SCALAR_FLOAT_TYPE_P (parm_first[0]))
12730 : {
12731 : /* Presume this is a macro that rounds its result to a
12732 : narrower type, and look for the first function with
12733 : at least the range and precision of the argument
12734 : type. */
12735 4 : for (unsigned int j = 0; j < num_functions; j++)
12736 : {
12737 8 : if (arg_complex
12738 4 : != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
12739 0 : continue;
12740 4 : tree real_tg_type = (arg_complex
12741 4 : ? TREE_TYPE (tg_type[j])
12742 0 : : tg_type[j]);
12743 8 : if (DECIMAL_FLOAT_TYPE_P (arg_real)
12744 4 : != DECIMAL_FLOAT_TYPE_P (real_tg_type))
12745 0 : continue;
12746 4 : scalar_float_mode arg_mode
12747 4 : = SCALAR_FLOAT_TYPE_MODE (arg_real);
12748 4 : scalar_float_mode tg_mode
12749 4 : = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
12750 4 : const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
12751 4 : const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
12752 4 : if (arg_fmt->b == tg_fmt->b
12753 4 : && arg_fmt->p <= tg_fmt->p
12754 4 : && arg_fmt->emax <= tg_fmt->emax
12755 4 : && (arg_fmt->emin - arg_fmt->p
12756 4 : >= tg_fmt->emin - tg_fmt->p))
12757 : {
12758 4 : fn = &(*cexpr_list)[j];
12759 4 : break;
12760 : }
12761 : }
12762 : }
12763 315 : if (fn == NULL)
12764 : {
12765 2 : error_at (loc, "no matching function for type-generic call");
12766 2 : expr.set_error ();
12767 2 : break;
12768 : }
12769 :
12770 : /* Construct a call to FN. */
12771 313 : vec<tree, va_gc> *args;
12772 313 : vec_alloc (args, nargs);
12773 313 : vec<tree, va_gc> *origtypes;
12774 313 : vec_alloc (origtypes, nargs);
12775 313 : auto_vec<location_t> arg_loc (nargs);
12776 739 : for (unsigned int j = 0; j < nargs; j++)
12777 : {
12778 426 : c_expr_t *ce = &(*cexpr_list)[num_functions + j];
12779 426 : args->quick_push (ce->value);
12780 426 : arg_loc.quick_push (ce->get_location ());
12781 426 : origtypes->quick_push (ce->original_type);
12782 : }
12783 313 : expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
12784 : args, origtypes);
12785 313 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12786 313 : break;
12787 982 : }
12788 22 : case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
12789 22 : {
12790 22 : vec<c_expr_t, va_gc> *cexpr_list;
12791 22 : c_expr_t *e2_p;
12792 22 : tree chain_value;
12793 22 : location_t close_paren_loc;
12794 :
12795 22 : c_parser_consume_token (parser);
12796 22 : if (!c_parser_get_builtin_args (parser,
12797 : "__builtin_call_with_static_chain",
12798 : &cexpr_list, false,
12799 : &close_paren_loc))
12800 : {
12801 0 : expr.set_error ();
12802 0 : break;
12803 : }
12804 22 : if (vec_safe_length (cexpr_list) != 2)
12805 : {
12806 0 : error_at (loc, "wrong number of arguments to "
12807 : "%<__builtin_call_with_static_chain%>");
12808 0 : expr.set_error ();
12809 0 : break;
12810 : }
12811 :
12812 22 : expr = (*cexpr_list)[0];
12813 22 : e2_p = &(*cexpr_list)[1];
12814 22 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12815 22 : chain_value = e2_p->value;
12816 22 : mark_exp_read (chain_value);
12817 :
12818 22 : if (TREE_CODE (expr.value) != CALL_EXPR)
12819 3 : error_at (loc, "first argument to "
12820 : "%<__builtin_call_with_static_chain%> "
12821 : "must be a call expression");
12822 19 : else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
12823 1 : error_at (loc, "second argument to "
12824 : "%<__builtin_call_with_static_chain%> "
12825 : "must be a pointer type");
12826 : else
12827 18 : CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
12828 22 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12829 22 : break;
12830 : }
12831 12078 : case RID_BUILTIN_COMPLEX:
12832 12078 : {
12833 12078 : vec<c_expr_t, va_gc> *cexpr_list;
12834 12078 : c_expr_t *e1_p, *e2_p;
12835 12078 : location_t close_paren_loc;
12836 :
12837 12078 : c_parser_consume_token (parser);
12838 12078 : if (!c_parser_get_builtin_args (parser,
12839 : "__builtin_complex",
12840 : &cexpr_list, false,
12841 : &close_paren_loc))
12842 : {
12843 1 : expr.set_error ();
12844 1 : break;
12845 : }
12846 :
12847 12077 : if (vec_safe_length (cexpr_list) != 2)
12848 : {
12849 2 : error_at (loc, "wrong number of arguments to "
12850 : "%<__builtin_complex%>");
12851 2 : expr.set_error ();
12852 2 : break;
12853 : }
12854 :
12855 12075 : e1_p = &(*cexpr_list)[0];
12856 12075 : e2_p = &(*cexpr_list)[1];
12857 :
12858 12075 : *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
12859 12075 : if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
12860 56 : e1_p->value = convert (TREE_TYPE (e1_p->value),
12861 56 : TREE_OPERAND (e1_p->value, 0));
12862 12075 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12863 12075 : if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
12864 56 : e2_p->value = convert (TREE_TYPE (e2_p->value),
12865 56 : TREE_OPERAND (e2_p->value, 0));
12866 12075 : if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12867 12074 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12868 12073 : || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
12869 24147 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
12870 : {
12871 3 : error_at (loc, "%<__builtin_complex%> operand "
12872 : "not of real binary floating-point type");
12873 3 : expr.set_error ();
12874 3 : break;
12875 : }
12876 12072 : if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
12877 12072 : != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
12878 : {
12879 1 : error_at (loc,
12880 : "%<__builtin_complex%> operands of different types");
12881 1 : expr.set_error ();
12882 1 : break;
12883 : }
12884 12071 : pedwarn_c90 (loc, OPT_Wpedantic,
12885 : "ISO C90 does not support complex types");
12886 12071 : expr.value = build2_loc (loc, COMPLEX_EXPR,
12887 : build_complex_type
12888 12071 : (TYPE_MAIN_VARIANT
12889 : (TREE_TYPE (e1_p->value))),
12890 : e1_p->value, e2_p->value);
12891 12071 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12892 12071 : break;
12893 : }
12894 88 : case RID_BUILTIN_COUNTED_BY_REF:
12895 88 : {
12896 88 : vec<c_expr_t, va_gc> *cexpr_list;
12897 88 : c_expr_t *e_p;
12898 88 : location_t close_paren_loc;
12899 :
12900 88 : c_parser_consume_token (parser);
12901 88 : if (!c_parser_get_builtin_args (parser,
12902 : "__builtin_counted_by_ref",
12903 : &cexpr_list, false,
12904 : &close_paren_loc))
12905 : {
12906 0 : expr.set_error ();
12907 0 : break;
12908 : }
12909 88 : if (vec_safe_length (cexpr_list) != 1)
12910 : {
12911 4 : error_at (loc, "wrong number of arguments to "
12912 : "%<__builtin_counted_by_ref%>");
12913 4 : expr.set_error ();
12914 4 : break;
12915 : }
12916 :
12917 84 : e_p = &(*cexpr_list)[0];
12918 84 : tree ref = e_p->value;
12919 :
12920 84 : if (TREE_CODE (TREE_TYPE (ref)) != ARRAY_TYPE
12921 84 : && TREE_CODE (TREE_TYPE (ref)) != POINTER_TYPE)
12922 : {
12923 2 : error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12924 : " must be an array or pointer");
12925 2 : expr.set_error ();
12926 2 : break;
12927 : }
12928 :
12929 82 : if (TREE_CODE (ref) != COMPONENT_REF)
12930 : {
12931 2 : error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12932 : " must be a field of a structure");
12933 2 : expr.set_error ();
12934 2 : break;
12935 : }
12936 :
12937 : /* If the ref is inside TYPEOF or ALIGNOF, the call to
12938 : .ACCESS_WITH_SIZE was not generated by the routine
12939 : build_component_ref by default, we should generate it here. */
12940 80 : if (TREE_CODE (ref) == COMPONENT_REF)
12941 80 : ref = handle_counted_by_for_component_ref (loc, ref);
12942 :
12943 80 : if (has_counted_by_object (ref))
12944 50 : expr.value = get_counted_by_ref (ref);
12945 : else
12946 30 : expr.value = null_pointer_node;
12947 :
12948 80 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12949 80 : break;
12950 : }
12951 469676 : case RID_BUILTIN_SHUFFLE:
12952 469676 : {
12953 469676 : vec<c_expr_t, va_gc> *cexpr_list;
12954 469676 : unsigned int i;
12955 469676 : c_expr_t *p;
12956 469676 : location_t close_paren_loc;
12957 :
12958 469676 : c_parser_consume_token (parser);
12959 469676 : if (!c_parser_get_builtin_args (parser,
12960 : "__builtin_shuffle",
12961 : &cexpr_list, false,
12962 : &close_paren_loc))
12963 : {
12964 0 : expr.set_error ();
12965 0 : break;
12966 : }
12967 :
12968 1450519 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12969 980843 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12970 :
12971 469676 : if (vec_safe_length (cexpr_list) == 2)
12972 428185 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12973 : NULL_TREE,
12974 428185 : (*cexpr_list)[1].value);
12975 :
12976 41491 : else if (vec_safe_length (cexpr_list) == 3)
12977 41491 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12978 41491 : (*cexpr_list)[1].value,
12979 41491 : (*cexpr_list)[2].value);
12980 : else
12981 : {
12982 0 : error_at (loc, "wrong number of arguments to "
12983 : "%<__builtin_shuffle%>");
12984 0 : expr.set_error ();
12985 : }
12986 469676 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12987 469676 : break;
12988 : }
12989 1077379 : case RID_BUILTIN_SHUFFLEVECTOR:
12990 1077379 : {
12991 1077379 : vec<c_expr_t, va_gc> *cexpr_list;
12992 1077379 : unsigned int i;
12993 1077379 : c_expr_t *p;
12994 1077379 : location_t close_paren_loc;
12995 :
12996 1077379 : c_parser_consume_token (parser);
12997 1077379 : if (!c_parser_get_builtin_args (parser,
12998 : "__builtin_shufflevector",
12999 : &cexpr_list, false,
13000 : &close_paren_loc))
13001 : {
13002 0 : expr.set_error ();
13003 0 : break;
13004 : }
13005 :
13006 16776957 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
13007 15699578 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
13008 :
13009 1077379 : if (vec_safe_length (cexpr_list) < 3)
13010 : {
13011 0 : error_at (loc, "wrong number of arguments to "
13012 : "%<__builtin_shuffle%>");
13013 0 : expr.set_error ();
13014 : }
13015 : else
13016 : {
13017 1077379 : auto_vec<tree, 16> mask;
13018 14622199 : for (i = 2; i < cexpr_list->length (); ++i)
13019 13544820 : mask.safe_push ((*cexpr_list)[i].value);
13020 1077379 : expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
13021 1077379 : (*cexpr_list)[1].value,
13022 : mask);
13023 1077379 : }
13024 1077379 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13025 1077379 : break;
13026 : }
13027 396 : case RID_BUILTIN_CONVERTVECTOR:
13028 396 : {
13029 396 : location_t start_loc = loc;
13030 396 : c_parser_consume_token (parser);
13031 396 : matching_parens parens;
13032 396 : if (!parens.require_open (parser))
13033 : {
13034 0 : expr.set_error ();
13035 2 : break;
13036 : }
13037 396 : e1 = c_parser_expr_no_commas (parser, NULL);
13038 396 : mark_exp_read (e1.value);
13039 396 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
13040 : {
13041 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13042 2 : expr.set_error ();
13043 2 : break;
13044 : }
13045 394 : loc = c_parser_peek_token (parser)->location;
13046 394 : t1 = c_parser_type_name (parser);
13047 394 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
13048 394 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
13049 : "expected %<)%>");
13050 394 : if (t1 == NULL)
13051 1 : expr.set_error ();
13052 : else
13053 : {
13054 393 : tree type_expr = NULL_TREE;
13055 393 : expr.value = c_build_vec_convert (start_loc, e1.value, loc,
13056 : groktypename (t1, &type_expr,
13057 : NULL));
13058 393 : set_c_expr_source_range (&expr, start_loc, end_loc);
13059 : }
13060 : }
13061 394 : break;
13062 10 : case RID_BUILTIN_ASSOC_BARRIER:
13063 10 : {
13064 10 : location_t start_loc = loc;
13065 10 : c_parser_consume_token (parser);
13066 10 : matching_parens parens;
13067 10 : if (!parens.require_open (parser))
13068 : {
13069 0 : expr.set_error ();
13070 0 : break;
13071 : }
13072 10 : e1 = c_parser_expr_no_commas (parser, NULL);
13073 10 : mark_exp_read (e1.value);
13074 10 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
13075 10 : parens.skip_until_found_close (parser);
13076 10 : expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
13077 10 : set_c_expr_source_range (&expr, start_loc, end_loc);
13078 : }
13079 10 : break;
13080 1073 : case RID_BUILTIN_STDC:
13081 1073 : {
13082 1073 : vec<c_expr_t, va_gc> *cexpr_list;
13083 1073 : c_expr_t *arg_p;
13084 1073 : location_t close_paren_loc;
13085 1073 : enum c_builtin_stdc {
13086 : C_BUILTIN_STDC_BIT_CEIL,
13087 : C_BUILTIN_STDC_BIT_FLOOR,
13088 : C_BUILTIN_STDC_BIT_WIDTH,
13089 : C_BUILTIN_STDC_COUNT_ONES,
13090 : C_BUILTIN_STDC_COUNT_ZEROS,
13091 : C_BUILTIN_STDC_FIRST_LEADING_ONE,
13092 : C_BUILTIN_STDC_FIRST_LEADING_ZERO,
13093 : C_BUILTIN_STDC_FIRST_TRAILING_ONE,
13094 : C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
13095 : C_BUILTIN_STDC_HAS_SINGLE_BIT,
13096 : C_BUILTIN_STDC_LEADING_ONES,
13097 : C_BUILTIN_STDC_LEADING_ZEROS,
13098 : C_BUILTIN_STDC_ROTATE_LEFT,
13099 : C_BUILTIN_STDC_ROTATE_RIGHT,
13100 : C_BUILTIN_STDC_TRAILING_ONES,
13101 : C_BUILTIN_STDC_TRAILING_ZEROS,
13102 : C_BUILTIN_STDC_MAX
13103 1073 : } stdc_rid = C_BUILTIN_STDC_MAX;
13104 1073 : const char *name
13105 1073 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
13106 1073 : unsigned num_args = 1;
13107 1073 : switch (name[sizeof ("__builtin_stdc_") - 1])
13108 : {
13109 202 : case 'b':
13110 202 : switch (name[sizeof ("__builtin_stdc_bit_") - 1])
13111 : {
13112 : case 'c':
13113 : stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
13114 : break;
13115 64 : case 'f':
13116 64 : stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
13117 64 : break;
13118 58 : default:
13119 58 : stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
13120 58 : break;
13121 : }
13122 : break;
13123 106 : case 'c':
13124 106 : if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
13125 : stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
13126 : else
13127 53 : stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
13128 : break;
13129 215 : case 'f':
13130 215 : switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
13131 : {
13132 : case 'n':
13133 : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
13134 : break;
13135 : case 'e':
13136 : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
13137 : break;
13138 : case 'o':
13139 : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
13140 : break;
13141 : default:
13142 : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
13143 : break;
13144 : }
13145 : break;
13146 : case 'h':
13147 : stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
13148 : break;
13149 106 : case 'l':
13150 106 : if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
13151 : stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
13152 : else
13153 53 : stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
13154 : break;
13155 285 : case 'r':
13156 285 : if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l')
13157 : stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT;
13158 : else
13159 138 : stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT;
13160 : num_args = 2;
13161 : break;
13162 106 : case 't':
13163 106 : if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
13164 : stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
13165 : else
13166 53 : stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
13167 : break;
13168 : }
13169 281 : gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
13170 :
13171 1073 : c_parser_consume_token (parser);
13172 1073 : if (!c_parser_get_builtin_args (parser, name,
13173 : &cexpr_list, false,
13174 : &close_paren_loc))
13175 : {
13176 0 : expr.set_error ();
13177 0 : break;
13178 : }
13179 :
13180 2130 : if (vec_safe_length (cexpr_list) != num_args)
13181 : {
13182 34 : error_at (loc, "wrong number of arguments to %qs", name);
13183 34 : expr.set_error ();
13184 34 : break;
13185 : }
13186 :
13187 1039 : arg_p = &(*cexpr_list)[0];
13188 1039 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13189 1039 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13190 : {
13191 80 : error_at (loc, "%qs operand not an integral type", name);
13192 80 : expr.set_error ();
13193 80 : break;
13194 : }
13195 959 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13196 : {
13197 16 : error_at (loc, "argument %u in call to function "
13198 : "%qs has enumerated type", 1, name);
13199 16 : expr.set_error ();
13200 16 : break;
13201 : }
13202 943 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
13203 : {
13204 16 : error_at (loc, "argument %u in call to function "
13205 : "%qs has boolean type", 1, name);
13206 16 : expr.set_error ();
13207 16 : break;
13208 : }
13209 927 : if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
13210 : {
13211 16 : error_at (loc, "argument 1 in call to function "
13212 : "%qs has signed type", name);
13213 16 : expr.set_error ();
13214 16 : break;
13215 : }
13216 911 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
13217 911 : == char_type_node)
13218 : {
13219 16 : error_at (loc, "argument 1 in call to function "
13220 : "%qs has %<char%> type", name);
13221 16 : expr.set_error ();
13222 16 : break;
13223 : }
13224 895 : tree arg = arg_p->value;
13225 895 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
13226 : /* Expand:
13227 : __builtin_stdc_leading_zeros (arg) as
13228 : (unsigned int) __builtin_clzg (arg, prec)
13229 : __builtin_stdc_leading_ones (arg) as
13230 : (unsigned int) __builtin_clzg ((type) ~arg, prec)
13231 : __builtin_stdc_trailing_zeros (arg) as
13232 : (unsigned int) __builtin_ctzg (arg, prec)
13233 : __builtin_stdc_trailing_ones (arg) as
13234 : (unsigned int) __builtin_ctzg ((type) ~arg, prec)
13235 : __builtin_stdc_first_leading_zero (arg) as
13236 : __builtin_clzg ((type) ~arg, -1) + 1U
13237 : __builtin_stdc_first_leading_one (arg) as
13238 : __builtin_clzg (arg, -1) + 1U
13239 : __builtin_stdc_first_trailing_zero (arg) as
13240 : __builtin_ctzg ((type) ~arg, -1) + 1U
13241 : __builtin_stdc_first_trailing_one (arg) as
13242 : __builtin_ctzg (arg, -1) + 1U
13243 : __builtin_stdc_count_zeros (arg) as
13244 : (unsigned int) __builtin_popcountg ((type) ~arg)
13245 : __builtin_stdc_count_ones (arg) as
13246 : (unsigned int) __builtin_popcountg (arg)
13247 : __builtin_stdc_has_single_bit (arg) as
13248 : (_Bool) (__builtin_popcountg (arg) == 1)
13249 : __builtin_stdc_bit_width (arg) as
13250 : (unsigned int) (prec - __builtin_clzg (arg, prec))
13251 : __builtin_stdc_bit_floor (arg) as
13252 : arg == 0 ? (type) 0
13253 : : (type) 1 << (prec - 1 - __builtin_clzg (arg))
13254 : __builtin_stdc_bit_ceil (arg) as
13255 : arg <= 1 ? (type) 1
13256 : : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
13257 : without evaluating arg multiple times, type being
13258 : __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
13259 895 : int prec = TYPE_PRECISION (type);
13260 895 : if (num_args == 2)
13261 : {
13262 : /* Expand:
13263 : __builtin_stdc_rotate_left (arg1, arg2) as
13264 : arg1 r<< (arg2 % prec)
13265 : __builtin_stdc_rotate_right (arg1, arg2) as
13266 : arg1 r>> (arg2 % prec). */
13267 261 : arg_p = &(*cexpr_list)[1];
13268 261 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13269 261 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13270 : {
13271 10 : error_at (loc, "%qs operand not an integral type", name);
13272 10 : expr.set_error ();
13273 10 : break;
13274 : }
13275 251 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13276 : {
13277 2 : error_at (loc, "argument %u in call to function "
13278 : "%qs has enumerated type", 2, name);
13279 2 : expr.set_error ();
13280 2 : break;
13281 : }
13282 249 : tree arg1 = save_expr (arg);
13283 249 : tree arg2 = save_expr (arg_p->value);
13284 249 : tree_code code;
13285 249 : if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT)
13286 : code = LROTATE_EXPR;
13287 : else
13288 120 : code = RROTATE_EXPR;
13289 :
13290 249 : if (TREE_CODE (arg2) == INTEGER_CST
13291 249 : && tree_int_cst_sgn (arg2) < 0)
13292 20 : warning_at (loc, OPT_Wshift_count_negative,
13293 : "rotate count is negative");
13294 :
13295 249 : tree instrument_expr = NULL_TREE;
13296 249 : if (sanitize_flags_p (SANITIZE_SHIFT))
13297 28 : instrument_expr = ubsan_instrument_shift (loc, code,
13298 : arg1, arg2);
13299 :
13300 : /* Promote arg2 to unsigned just so that we don't
13301 : need to deal with arg2 type not being able to represent
13302 : prec. In the end gimplification uses unsigned int
13303 : for all shifts/rotates anyway. */
13304 249 : if (TYPE_PRECISION (TREE_TYPE (arg2))
13305 249 : < TYPE_PRECISION (integer_type_node))
13306 13 : arg2 = fold_convert (unsigned_type_node, arg2);
13307 :
13308 249 : if (TYPE_UNSIGNED (TREE_TYPE (arg2)))
13309 26 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg2),
13310 26 : arg2, build_int_cst (TREE_TYPE (arg2),
13311 26 : prec));
13312 : else
13313 : {
13314 : /* When second argument is signed, just do the modulo in
13315 : unsigned type, that results in better generated code
13316 : (for power of 2 precisions bitwise AND). */
13317 223 : tree utype = c_common_unsigned_type (TREE_TYPE (arg2));
13318 223 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, utype,
13319 : fold_convert (utype, arg2),
13320 223 : build_int_cst (utype, prec));
13321 : }
13322 :
13323 : /* The middle-end isn't prepared to handle {L,R}ROTATE_EXPR
13324 : on types without mode precision, except for large/huge
13325 : _BitInt types. */
13326 249 : if (type_has_mode_precision_p (TREE_TYPE (arg1))
13327 249 : || (TREE_CODE (TREE_TYPE (arg1)) == BITINT_TYPE
13328 150 : && prec > MAX_FIXED_MODE_SIZE))
13329 192 : expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg1,
13330 : arg2);
13331 : else
13332 : {
13333 57 : arg2 = save_expr (arg2);
13334 82 : tree t1 = build2_loc (loc, (code == LROTATE_EXPR
13335 : ? LSHIFT_EXPR : RSHIFT_EXPR),
13336 57 : TREE_TYPE (arg1), arg1, arg2);
13337 114 : tree t2 = build2_loc (loc, MINUS_EXPR,
13338 57 : TREE_TYPE (arg2),
13339 57 : build_int_cst (TREE_TYPE (arg2),
13340 57 : prec), arg2);
13341 82 : t2 = build2_loc (loc, (code == LROTATE_EXPR
13342 : ? RSHIFT_EXPR : LSHIFT_EXPR),
13343 57 : TREE_TYPE (arg1), arg1, t2);
13344 57 : suppress_warning (t2, OPT_Wshift_count_overflow);
13345 57 : tree t3 = build2_loc (loc, BIT_IOR_EXPR,
13346 57 : TREE_TYPE (arg1), t1, t2);
13347 57 : tree t4 = build2_loc (loc, NE_EXPR, boolean_type_node,
13348 : arg2,
13349 57 : build_zero_cst (TREE_TYPE (arg2)));
13350 57 : t4 = build2_loc (loc, COMPOUND_EXPR, boolean_type_node,
13351 : arg1, t4);
13352 57 : expr.value = build3_loc (loc, COND_EXPR,
13353 57 : TREE_TYPE (arg1), t4, t3, arg1);
13354 : }
13355 249 : if (instrument_expr)
13356 28 : expr.value = build2_loc (loc, COMPOUND_EXPR,
13357 28 : TREE_TYPE (expr.value),
13358 : instrument_expr, expr.value);
13359 249 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13360 249 : break;
13361 : }
13362 634 : tree barg1 = arg;
13363 634 : switch (stdc_rid)
13364 : {
13365 69 : case C_BUILTIN_STDC_BIT_CEIL:
13366 69 : arg = save_expr (arg);
13367 69 : barg1 = build2_loc (loc, PLUS_EXPR, type, arg,
13368 : build_int_cst (type, -1));
13369 69 : break;
13370 53 : case C_BUILTIN_STDC_BIT_FLOOR:
13371 53 : barg1 = arg = save_expr (arg);
13372 53 : break;
13373 211 : case C_BUILTIN_STDC_COUNT_ZEROS:
13374 211 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13375 211 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13376 211 : case C_BUILTIN_STDC_LEADING_ONES:
13377 211 : case C_BUILTIN_STDC_TRAILING_ONES:
13378 211 : barg1 = build1_loc (loc, BIT_NOT_EXPR, type, arg);
13379 211 : break;
13380 : default:
13381 : break;
13382 : }
13383 634 : tree barg2 = NULL_TREE;
13384 634 : switch (stdc_rid)
13385 : {
13386 215 : case C_BUILTIN_STDC_BIT_WIDTH:
13387 215 : case C_BUILTIN_STDC_LEADING_ONES:
13388 215 : case C_BUILTIN_STDC_LEADING_ZEROS:
13389 215 : case C_BUILTIN_STDC_TRAILING_ONES:
13390 215 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13391 215 : barg2 = build_int_cst (integer_type_node, prec);
13392 215 : break;
13393 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13394 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13395 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13396 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13397 171 : barg2 = integer_minus_one_node;
13398 171 : break;
13399 : default:
13400 : break;
13401 : }
13402 634 : tree fndecl = NULL_TREE;
13403 634 : switch (stdc_rid)
13404 : {
13405 340 : case C_BUILTIN_STDC_BIT_CEIL:
13406 340 : case C_BUILTIN_STDC_BIT_FLOOR:
13407 340 : case C_BUILTIN_STDC_BIT_WIDTH:
13408 340 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13409 340 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13410 340 : case C_BUILTIN_STDC_LEADING_ONES:
13411 340 : case C_BUILTIN_STDC_LEADING_ZEROS:
13412 340 : fndecl = builtin_decl_explicit (BUILT_IN_CLZG);
13413 340 : break;
13414 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13415 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13416 168 : case C_BUILTIN_STDC_TRAILING_ONES:
13417 168 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13418 168 : fndecl = builtin_decl_explicit (BUILT_IN_CTZG);
13419 168 : break;
13420 126 : case C_BUILTIN_STDC_COUNT_ONES:
13421 126 : case C_BUILTIN_STDC_COUNT_ZEROS:
13422 126 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13423 126 : fndecl = builtin_decl_explicit (BUILT_IN_POPCOUNTG);
13424 126 : break;
13425 0 : default:
13426 0 : gcc_unreachable ();
13427 : }
13428 : /* Construct a call to __builtin_{clz,ctz,popcount}g. */
13429 634 : int nargs = barg2 != NULL_TREE ? 2 : 1;
13430 634 : vec<tree, va_gc> *args;
13431 634 : vec_alloc (args, nargs);
13432 634 : vec<tree, va_gc> *origtypes;
13433 634 : vec_alloc (origtypes, nargs);
13434 1268 : auto_vec<location_t> arg_loc (nargs);
13435 634 : args->quick_push (barg1);
13436 634 : arg_loc.quick_push (arg_p->get_location ());
13437 634 : origtypes->quick_push (arg_p->original_type);
13438 634 : if (nargs == 2)
13439 : {
13440 386 : args->quick_push (barg2);
13441 386 : arg_loc.quick_push (loc);
13442 386 : origtypes->quick_push (integer_type_node);
13443 : }
13444 634 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
13445 : args, origtypes);
13446 634 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13447 634 : if (expr.value == error_mark_node)
13448 : break;
13449 634 : switch (stdc_rid)
13450 : {
13451 122 : case C_BUILTIN_STDC_BIT_CEIL:
13452 122 : case C_BUILTIN_STDC_BIT_FLOOR:
13453 122 : --prec;
13454 : /* FALLTHRU */
13455 169 : case C_BUILTIN_STDC_BIT_WIDTH:
13456 169 : expr.value = build2_loc (loc, MINUS_EXPR, integer_type_node,
13457 : build_int_cst (integer_type_node,
13458 169 : prec), expr.value);
13459 169 : break;
13460 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13461 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13462 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13463 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13464 171 : expr.value = build2_loc (loc, PLUS_EXPR, integer_type_node,
13465 : expr.value, integer_one_node);
13466 171 : break;
13467 42 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13468 42 : expr.value = build2_loc (loc, EQ_EXPR, boolean_type_node,
13469 : expr.value, integer_one_node);
13470 42 : break;
13471 : default:
13472 : break;
13473 : }
13474 :
13475 382 : if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
13476 : && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
13477 : {
13478 512 : if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
13479 470 : expr.value = fold_convert_loc (loc, unsigned_type_node,
13480 : expr.value);
13481 : break;
13482 : }
13483 : /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
13484 : or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
13485 : warnings. The LSHIFT_EXPR is in dead code in that case. */
13486 122 : if (integer_zerop (arg)
13487 122 : || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
13488 42 : expr.value = build_int_cst (type, 0);
13489 : else
13490 80 : expr.value
13491 80 : = build2_loc (loc, LSHIFT_EXPR, type,
13492 : build_int_cst (type,
13493 : (stdc_rid
13494 : == C_BUILTIN_STDC_BIT_CEIL
13495 114 : ? 2 : 1)), expr.value);
13496 122 : if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
13497 69 : expr.value = build3_loc (loc, COND_EXPR, type,
13498 : build2_loc (loc, LE_EXPR,
13499 : boolean_type_node, arg,
13500 : build_int_cst (type, 1)),
13501 : build_int_cst (type, 1),
13502 : expr.value);
13503 : else
13504 53 : expr.value = build3_loc (loc, COND_EXPR, type,
13505 : build2_loc (loc, EQ_EXPR,
13506 : boolean_type_node, arg,
13507 : build_int_cst (type, 0)),
13508 : build_int_cst (type, 0),
13509 : expr.value);
13510 : break;
13511 : }
13512 0 : case RID_AT_SELECTOR:
13513 0 : {
13514 0 : gcc_assert (c_dialect_objc ());
13515 0 : c_parser_consume_token (parser);
13516 0 : matching_parens parens;
13517 0 : if (!parens.require_open (parser))
13518 : {
13519 0 : expr.set_error ();
13520 0 : break;
13521 : }
13522 0 : tree sel = c_parser_objc_selector_arg (parser);
13523 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13524 0 : parens.skip_until_found_close (parser);
13525 0 : expr.value = objc_build_selector_expr (loc, sel);
13526 0 : set_c_expr_source_range (&expr, loc, close_loc);
13527 : }
13528 0 : break;
13529 0 : case RID_AT_PROTOCOL:
13530 0 : {
13531 0 : gcc_assert (c_dialect_objc ());
13532 0 : c_parser_consume_token (parser);
13533 0 : matching_parens parens;
13534 0 : if (!parens.require_open (parser))
13535 : {
13536 0 : expr.set_error ();
13537 0 : break;
13538 : }
13539 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
13540 : {
13541 0 : c_parser_error (parser, "expected identifier");
13542 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13543 0 : expr.set_error ();
13544 0 : break;
13545 : }
13546 0 : tree id = c_parser_peek_token (parser)->value;
13547 0 : c_parser_consume_token (parser);
13548 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13549 0 : parens.skip_until_found_close (parser);
13550 0 : expr.value = objc_build_protocol_expr (id);
13551 0 : set_c_expr_source_range (&expr, loc, close_loc);
13552 : }
13553 0 : break;
13554 0 : case RID_AT_ENCODE:
13555 0 : {
13556 : /* Extension to support C-structures in the archiver. */
13557 0 : gcc_assert (c_dialect_objc ());
13558 0 : c_parser_consume_token (parser);
13559 0 : matching_parens parens;
13560 0 : if (!parens.require_open (parser))
13561 : {
13562 0 : expr.set_error ();
13563 0 : break;
13564 : }
13565 0 : t1 = c_parser_type_name (parser);
13566 0 : if (t1 == NULL)
13567 : {
13568 0 : expr.set_error ();
13569 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13570 0 : break;
13571 : }
13572 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13573 0 : parens.skip_until_found_close (parser);
13574 0 : tree type = groktypename (t1, NULL, NULL);
13575 0 : expr.value = objc_build_encode_expr (type);
13576 0 : set_c_expr_source_range (&expr, loc, close_loc);
13577 : }
13578 0 : break;
13579 711 : case RID_GENERIC:
13580 711 : expr = c_parser_generic_selection (parser);
13581 711 : break;
13582 3 : case RID_OMP_ALL_MEMORY:
13583 3 : gcc_assert (flag_openmp);
13584 3 : c_parser_consume_token (parser);
13585 3 : error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
13586 : "%<depend%> clause");
13587 3 : expr.set_error ();
13588 3 : break;
13589 : /* C23 'nullptr' literal. */
13590 11401 : case RID_NULLPTR:
13591 11401 : c_parser_consume_token (parser);
13592 11401 : expr.value = nullptr_node;
13593 11401 : set_c_expr_source_range (&expr, tok_range);
13594 11401 : pedwarn_c11 (loc, OPT_Wpedantic,
13595 : "ISO C does not support %qs before C23", "nullptr");
13596 11401 : break;
13597 5444 : case RID_TRUE:
13598 5444 : c_parser_consume_token (parser);
13599 5444 : expr.value = boolean_true_node;
13600 5444 : set_c_expr_source_range (&expr, tok_range);
13601 5444 : break;
13602 4790 : case RID_FALSE:
13603 4790 : c_parser_consume_token (parser);
13604 4790 : expr.value = boolean_false_node;
13605 4790 : set_c_expr_source_range (&expr, tok_range);
13606 4790 : break;
13607 37 : default:
13608 37 : c_parser_error (parser, "expected expression");
13609 37 : expr.set_error ();
13610 37 : break;
13611 : }
13612 : break;
13613 2 : case CPP_OPEN_SQUARE:
13614 2 : if (c_dialect_objc ())
13615 : {
13616 0 : tree receiver, args;
13617 0 : c_parser_consume_token (parser);
13618 0 : receiver = c_parser_objc_receiver (parser);
13619 0 : args = c_parser_objc_message_args (parser);
13620 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13621 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13622 : "expected %<]%>");
13623 0 : expr.value = objc_build_message_expr (receiver, args);
13624 0 : set_c_expr_source_range (&expr, loc, close_loc);
13625 0 : break;
13626 : }
13627 : /* Else fall through to report error. */
13628 : /* FALLTHRU */
13629 795 : default:
13630 795 : c_parser_error (parser, "expected expression");
13631 795 : expr.set_error ();
13632 795 : break;
13633 : }
13634 235898210 : out:
13635 235898210 : return c_parser_postfix_expression_after_primary
13636 235898210 : (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
13637 : }
13638 :
13639 : /* Parse a postfix expression after a parenthesized type name: the
13640 : brace-enclosed initializer of a compound literal, possibly followed
13641 : by some postfix operators. This is separate because it is not
13642 : possible to tell until after the type name whether a cast
13643 : expression has a cast or a compound literal, or whether the operand
13644 : of sizeof is a parenthesized type name or starts with a compound
13645 : literal. TYPE_LOC is the location where TYPE_NAME starts--the
13646 : location of the first token after the parentheses around the type
13647 : name. */
13648 :
13649 : static struct c_expr
13650 917721 : c_parser_postfix_expression_after_paren_type (c_parser *parser,
13651 : struct c_declspecs *scspecs,
13652 : struct c_type_name *type_name,
13653 : location_t type_loc)
13654 : {
13655 917721 : tree type;
13656 917721 : struct c_expr init;
13657 917721 : bool non_const;
13658 917721 : struct c_expr expr;
13659 917721 : location_t start_loc;
13660 917721 : tree type_expr = NULL_TREE;
13661 917721 : bool type_expr_const = true;
13662 917721 : bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
13663 917721 : unsigned int underspec_state = 0;
13664 917721 : check_compound_literal_type (type_loc, type_name);
13665 917721 : rich_location richloc (line_table, type_loc);
13666 917721 : start_loc = c_parser_peek_token (parser)->location;
13667 917721 : if (constexpr_p)
13668 : {
13669 234 : underspec_state = start_underspecified_init (start_loc, NULL_TREE);
13670 : /* A constexpr compound literal is subject to the constraints on
13671 : underspecified declarations, which may not declare tags or
13672 : members or structures or unions; it is undefined behavior to
13673 : declare the members of an enumeration. Where the structure,
13674 : union or enumeration type is declared within the compound
13675 : literal initializer, this is diagnosed elsewhere as a result
13676 : of the above call to start_underspecified_init. Diagnose
13677 : here the case of declaring such a type in the type specifiers
13678 : of the compound literal. */
13679 234 : switch (type_name->specs->typespec_kind)
13680 : {
13681 2 : case ctsk_tagfirstref:
13682 2 : case ctsk_tagfirstref_attrs:
13683 2 : error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
13684 : type_name->specs->type);
13685 2 : break;
13686 :
13687 4 : case ctsk_tagdef:
13688 4 : error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
13689 : type_name->specs->type);
13690 4 : break;
13691 :
13692 : default:
13693 : break;
13694 : }
13695 : }
13696 917721 : start_init (NULL_TREE, NULL,
13697 917721 : (global_bindings_p ()
13698 917467 : || (scspecs && scspecs->storage_class == csc_static)
13699 1835158 : || constexpr_p), constexpr_p, &richloc);
13700 917721 : type = groktypename (type_name, &type_expr, &type_expr_const);
13701 917721 : bool varsize_p = false;
13702 917721 : if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
13703 : {
13704 16 : pedwarn (type_loc, OPT_Wpedantic, "compound literal has variable size");
13705 16 : varsize_p = true;
13706 : }
13707 917705 : else if (TREE_CODE (type) == FUNCTION_TYPE)
13708 : {
13709 3 : error_at (type_loc, "compound literal has function type");
13710 3 : type = error_mark_node;
13711 : }
13712 917721 : if (constexpr_p && type != error_mark_node)
13713 : {
13714 234 : tree type_no_array = strip_array_types (type);
13715 : /* The type of a constexpr object must not be variably modified
13716 : (which applies to all compound literals), volatile, atomic or
13717 : restrict qualified or have a member with such a qualifier.
13718 : const qualification is implicitly added. */
13719 234 : if (TYPE_QUALS (type_no_array)
13720 234 : & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
13721 9 : error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
13722 225 : else if (RECORD_OR_UNION_TYPE_P (type_no_array)
13723 225 : && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
13724 8 : error_at (type_loc, "invalid qualifiers for field of "
13725 : "%<constexpr%> object");
13726 468 : type = c_build_qualified_type (type,
13727 234 : (TYPE_QUALS (type_no_array)
13728 : | TYPE_QUAL_CONST));
13729 : }
13730 917721 : init = c_parser_braced_init (parser, type, false, NULL, varsize_p);
13731 917721 : if (constexpr_p)
13732 234 : finish_underspecified_init (NULL_TREE, underspec_state);
13733 917721 : finish_init ();
13734 917721 : maybe_warn_string_init (type_loc, type, init);
13735 :
13736 917721 : if (type != error_mark_node
13737 917714 : && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
13738 917721 : && current_function_decl)
13739 : {
13740 0 : error ("compound literal qualified by address-space qualifier");
13741 0 : type = error_mark_node;
13742 : }
13743 :
13744 1835137 : if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
13745 917721 : "ISO C90 forbids compound literals") && scspecs)
13746 305 : pedwarn_c11 (start_loc, OPT_Wpedantic,
13747 : "ISO C forbids storage class specifiers in compound literals "
13748 : "before C23");
13749 917721 : non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
13750 1834979 : ? CONSTRUCTOR_NON_CONST (init.value)
13751 463 : : init.original_code == C_MAYBE_CONST_EXPR);
13752 917721 : non_const |= !type_expr_const;
13753 917721 : unsigned int alignas_align = 0;
13754 917721 : if (type != error_mark_node
13755 917714 : && type_name->specs->align_log != -1)
13756 : {
13757 4 : alignas_align = 1U << type_name->specs->align_log;
13758 4 : if (alignas_align < min_align_of_type (type))
13759 : {
13760 1 : error_at (type_name->specs->locations[cdw_alignas],
13761 : "%<_Alignas%> specifiers cannot reduce "
13762 : "alignment of compound literal");
13763 1 : alignas_align = 0;
13764 : }
13765 : }
13766 917721 : expr.value = build_compound_literal (start_loc, type, init.value, non_const,
13767 : alignas_align, scspecs);
13768 917721 : set_c_expr_source_range (&expr, init.src_range);
13769 917721 : expr.m_decimal = 0;
13770 917721 : expr.original_code = ERROR_MARK;
13771 917721 : expr.original_type = NULL;
13772 917721 : if (type != error_mark_node
13773 917714 : && expr.value != error_mark_node
13774 917642 : && type_expr)
13775 : {
13776 41 : if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
13777 : {
13778 19 : gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
13779 19 : C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
13780 : }
13781 : else
13782 : {
13783 22 : gcc_assert (!non_const);
13784 22 : expr.value = build2 (C_MAYBE_CONST_EXPR, type,
13785 : type_expr, expr.value);
13786 : }
13787 : }
13788 917721 : return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
13789 917721 : }
13790 :
13791 : /* Callback function for sizeof_pointer_memaccess_warning to compare
13792 : types. */
13793 :
13794 : static bool
13795 3456 : sizeof_ptr_memacc_comptypes (tree type1, tree type2)
13796 : {
13797 3456 : return comptypes (type1, type2) == 1;
13798 : }
13799 :
13800 : /* Warn for patterns where abs-like function appears to be used incorrectly,
13801 : gracefully ignore any non-abs-like function. The warning location should
13802 : be LOC. FNDECL is the declaration of called function, it must be a
13803 : BUILT_IN_NORMAL function. ARG is the first and only argument of the
13804 : call. */
13805 :
13806 : static void
13807 57427 : warn_for_abs (location_t loc, tree fndecl, tree arg)
13808 : {
13809 : /* Avoid warning in unreachable subexpressions. */
13810 57427 : if (c_inhibit_evaluation_warnings)
13811 : return;
13812 :
13813 31089 : tree atype = TREE_TYPE (arg);
13814 :
13815 : /* Casts from pointers (and thus arrays and fndecls) will generate
13816 : -Wint-conversion warnings. Most other wrong types hopefully lead to type
13817 : mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
13818 : types and possibly other exotic types. */
13819 31089 : if (!INTEGRAL_TYPE_P (atype)
13820 31089 : && !SCALAR_FLOAT_TYPE_P (atype)
13821 5131 : && TREE_CODE (atype) != COMPLEX_TYPE)
13822 : return;
13823 :
13824 26436 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13825 :
13826 26436 : switch (fcode)
13827 : {
13828 35 : case BUILT_IN_ABS:
13829 35 : case BUILT_IN_LABS:
13830 35 : case BUILT_IN_LLABS:
13831 35 : case BUILT_IN_IMAXABS:
13832 35 : if (!INTEGRAL_TYPE_P (atype))
13833 : {
13834 4 : if (SCALAR_FLOAT_TYPE_P (atype))
13835 3 : warning_at (loc, OPT_Wabsolute_value,
13836 : "using integer absolute value function %qD when "
13837 : "argument is of floating-point type %qT",
13838 : fndecl, atype);
13839 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13840 1 : warning_at (loc, OPT_Wabsolute_value,
13841 : "using integer absolute value function %qD when "
13842 : "argument is of complex type %qT", fndecl, atype);
13843 : else
13844 : gcc_unreachable ();
13845 4 : return;
13846 : }
13847 31 : if (TYPE_UNSIGNED (atype))
13848 9 : warning_at (loc, OPT_Wabsolute_value,
13849 : "taking the absolute value of unsigned type %qT "
13850 : "has no effect", atype);
13851 : break;
13852 :
13853 334 : CASE_FLT_FN (BUILT_IN_FABS):
13854 334 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
13855 334 : if (!SCALAR_FLOAT_TYPE_P (atype)
13856 334 : || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
13857 : {
13858 4 : if (INTEGRAL_TYPE_P (atype))
13859 2 : warning_at (loc, OPT_Wabsolute_value,
13860 : "using floating-point absolute value function %qD "
13861 : "when argument is of integer type %qT", fndecl, atype);
13862 2 : else if (DECIMAL_FLOAT_TYPE_P (atype))
13863 1 : warning_at (loc, OPT_Wabsolute_value,
13864 : "using floating-point absolute value function %qD "
13865 : "when argument is of decimal floating-point type %qT",
13866 : fndecl, atype);
13867 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13868 1 : warning_at (loc, OPT_Wabsolute_value,
13869 : "using floating-point absolute value function %qD when "
13870 : "argument is of complex type %qT", fndecl, atype);
13871 : else
13872 0 : gcc_unreachable ();
13873 4 : return;
13874 : }
13875 : break;
13876 :
13877 7 : CASE_FLT_FN (BUILT_IN_CABS):
13878 7 : if (TREE_CODE (atype) != COMPLEX_TYPE)
13879 : {
13880 4 : if (INTEGRAL_TYPE_P (atype))
13881 2 : warning_at (loc, OPT_Wabsolute_value,
13882 : "using complex absolute value function %qD when "
13883 : "argument is of integer type %qT", fndecl, atype);
13884 2 : else if (SCALAR_FLOAT_TYPE_P (atype))
13885 2 : warning_at (loc, OPT_Wabsolute_value,
13886 : "using complex absolute value function %qD when "
13887 : "argument is of floating-point type %qT",
13888 : fndecl, atype);
13889 : else
13890 : gcc_unreachable ();
13891 :
13892 4 : return;
13893 : }
13894 : break;
13895 :
13896 6 : case BUILT_IN_FABSD32:
13897 6 : case BUILT_IN_FABSD64:
13898 6 : case BUILT_IN_FABSD128:
13899 6 : case BUILT_IN_FABSD64X:
13900 6 : if (!DECIMAL_FLOAT_TYPE_P (atype))
13901 : {
13902 4 : if (INTEGRAL_TYPE_P (atype))
13903 1 : warning_at (loc, OPT_Wabsolute_value,
13904 : "using decimal floating-point absolute value "
13905 : "function %qD when argument is of integer type %qT",
13906 : fndecl, atype);
13907 3 : else if (SCALAR_FLOAT_TYPE_P (atype))
13908 2 : warning_at (loc, OPT_Wabsolute_value,
13909 : "using decimal floating-point absolute value "
13910 : "function %qD when argument is of floating-point "
13911 : "type %qT", fndecl, atype);
13912 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13913 1 : warning_at (loc, OPT_Wabsolute_value,
13914 : "using decimal floating-point absolute value "
13915 : "function %qD when argument is of complex type %qT",
13916 : fndecl, atype);
13917 : else
13918 0 : gcc_unreachable ();
13919 4 : return;
13920 : }
13921 : break;
13922 :
13923 : default:
13924 : return;
13925 : }
13926 :
13927 366 : if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13928 : return;
13929 :
13930 365 : tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13931 365 : if (TREE_CODE (atype) == COMPLEX_TYPE)
13932 : {
13933 3 : gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
13934 3 : atype = TREE_TYPE (atype);
13935 3 : ftype = TREE_TYPE (ftype);
13936 : }
13937 :
13938 365 : if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
13939 9 : warning_at (loc, OPT_Wabsolute_value,
13940 : "absolute value function %qD given an argument of type %qT "
13941 : "but has parameter of type %qT which may cause truncation "
13942 : "of value", fndecl, atype, ftype);
13943 : }
13944 :
13945 :
13946 : /* Parse a postfix expression after the initial primary or compound
13947 : literal; that is, parse a series of postfix operators.
13948 :
13949 : EXPR_LOC is the location of the primary expression. */
13950 :
13951 : static struct c_expr
13952 236815981 : c_parser_postfix_expression_after_primary (c_parser *parser,
13953 : location_t expr_loc,
13954 : struct c_expr expr)
13955 : {
13956 236815981 : struct c_expr orig_expr;
13957 236815981 : tree ident, idx, len;
13958 236815981 : location_t sizeof_arg_loc[6], comp_loc;
13959 236815981 : tree sizeof_arg[6];
13960 236815981 : unsigned int literal_zero_mask;
13961 236815981 : unsigned int i;
13962 236815981 : vec<tree, va_gc> *exprlist;
13963 236815981 : vec<tree, va_gc> *origtypes = NULL;
13964 236815981 : vec<location_t> arg_loc = vNULL;
13965 292943883 : location_t start;
13966 292943883 : location_t finish;
13967 :
13968 292943883 : while (true)
13969 : {
13970 292943883 : location_t op_loc = c_parser_peek_token (parser)->location;
13971 292943883 : switch (c_parser_peek_token (parser)->type)
13972 : {
13973 3461416 : case CPP_OPEN_SQUARE:
13974 : /* Array reference. */
13975 3461416 : c_parser_consume_token (parser);
13976 3461416 : idx = len = NULL_TREE;
13977 3461416 : if (!c_omp_array_section_p
13978 3462138 : || c_parser_next_token_is_not (parser, CPP_COLON))
13979 3461223 : idx = c_parser_expression (parser).value;
13980 :
13981 3461416 : if (c_omp_array_section_p
13982 3462138 : && c_parser_next_token_is (parser, CPP_COLON))
13983 : {
13984 577 : c_parser_consume_token (parser);
13985 577 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
13986 542 : len = c_parser_expression (parser).value;
13987 :
13988 577 : expr.value = build_omp_array_section (op_loc, expr.value, idx,
13989 : len);
13990 : }
13991 : else
13992 3460839 : expr.value = build_array_ref (op_loc, expr.value, idx);
13993 :
13994 3461416 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13995 : "expected %<]%>");
13996 :
13997 3461416 : start = expr.get_start ();
13998 3461416 : finish = parser->tokens_buf[0].location;
13999 3461416 : set_c_expr_source_range (&expr, start, finish);
14000 3461416 : expr.original_code = ERROR_MARK;
14001 3461416 : expr.original_type = NULL;
14002 3461416 : expr.m_decimal = 0;
14003 3461416 : break;
14004 49709222 : case CPP_OPEN_PAREN:
14005 : /* Function call. */
14006 49709222 : {
14007 49709222 : matching_parens parens;
14008 49709222 : parens.consume_open (parser);
14009 397673776 : for (i = 0; i < 6; i++)
14010 : {
14011 298255332 : sizeof_arg[i] = NULL_TREE;
14012 298255332 : sizeof_arg_loc[i] = UNKNOWN_LOCATION;
14013 : }
14014 49709222 : literal_zero_mask = 0;
14015 49709222 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
14016 : exprlist = NULL;
14017 38017589 : else if (TREE_CODE (expr.value) == FUNCTION_DECL
14018 37950248 : && fndecl_built_in_p (expr.value, BUILT_IN_CLASSIFY_TYPE)
14019 38019369 : && c_parser_next_tokens_start_typename (parser,
14020 : cla_prefer_id))
14021 : {
14022 : /* __builtin_classify_type (type) */
14023 29 : c_inhibit_evaluation_warnings++;
14024 29 : in_alignof++;
14025 29 : struct c_type_name *type = c_parser_type_name (parser);
14026 29 : c_inhibit_evaluation_warnings--;
14027 29 : in_alignof--;
14028 29 : struct c_typespec ret;
14029 29 : ret.expr = NULL_TREE;
14030 29 : ret.spec = error_mark_node;
14031 29 : ret.expr_const_operands = false;
14032 29 : if (type != NULL)
14033 29 : ret.spec = groktypename (type, &ret.expr,
14034 : &ret.expr_const_operands);
14035 29 : parens.skip_until_found_close (parser);
14036 29 : expr.value = build_int_cst (integer_type_node,
14037 29 : type_to_class (ret.spec));
14038 29 : break;
14039 : }
14040 : else
14041 38017560 : exprlist = c_parser_expr_list (parser, true, false, &origtypes,
14042 : sizeof_arg_loc, sizeof_arg,
14043 : &arg_loc, &literal_zero_mask);
14044 49709193 : parens.skip_until_found_close (parser);
14045 : }
14046 49709193 : orig_expr = expr;
14047 49709193 : mark_exp_read (expr.value);
14048 49709193 : if (warn_sizeof_pointer_memaccess)
14049 4547031 : sizeof_pointer_memaccess_warning (sizeof_arg_loc,
14050 : expr.value, exprlist,
14051 : sizeof_arg,
14052 : sizeof_ptr_memacc_comptypes);
14053 49709193 : if (TREE_CODE (expr.value) == FUNCTION_DECL)
14054 : {
14055 49632118 : if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET)
14056 49663459 : && vec_safe_length (exprlist) == 3)
14057 : {
14058 31341 : tree arg0 = (*exprlist)[0];
14059 31341 : tree arg2 = (*exprlist)[2];
14060 31341 : warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
14061 : }
14062 49632118 : if (warn_absolute_value
14063 4273037 : && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL)
14064 49771307 : && vec_safe_length (exprlist) == 1)
14065 57427 : warn_for_abs (expr_loc, expr.value, (*exprlist)[0]);
14066 49632118 : if (parser->omp_for_parse_state
14067 178 : && parser->omp_for_parse_state->in_intervening_code
14068 49632257 : && omp_runtime_api_call (expr.value))
14069 : {
14070 2 : error_at (expr_loc, "calls to the OpenMP runtime API are "
14071 : "not permitted in intervening code");
14072 2 : parser->omp_for_parse_state->fail = true;
14073 : }
14074 49632118 : if (warn_calloc_transposed_args)
14075 4273012 : if (tree attr = lookup_attribute ("alloc_size",
14076 4273012 : TYPE_ATTRIBUTES
14077 : (TREE_TYPE (expr.value))))
14078 1259 : if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
14079 146 : warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
14080 : sizeof_arg, attr);
14081 : }
14082 :
14083 49709193 : start = expr.get_start ();
14084 49709193 : finish = parser->tokens_buf[0].get_finish ();
14085 49709193 : expr.value
14086 49709193 : = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
14087 : exprlist, origtypes);
14088 49709193 : set_c_expr_source_range (&expr, start, finish);
14089 49709193 : expr.m_decimal = 0;
14090 :
14091 49709193 : expr.original_code = ERROR_MARK;
14092 49709193 : if (TREE_CODE (expr.value) == INTEGER_CST
14093 12724 : && TREE_CODE (orig_expr.value) == FUNCTION_DECL
14094 49721917 : && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P))
14095 1549 : expr.original_code = C_MAYBE_CONST_EXPR;
14096 49709193 : expr.original_type = NULL;
14097 49709193 : if (exprlist)
14098 : {
14099 38017560 : release_tree_vector (exprlist);
14100 38017560 : release_tree_vector (origtypes);
14101 : }
14102 49709193 : arg_loc.release ();
14103 49709193 : break;
14104 1763351 : case CPP_DOT:
14105 : /* Structure element reference. */
14106 1763351 : c_parser_consume_token (parser);
14107 1763351 : expr = default_function_array_conversion (expr_loc, expr);
14108 1763351 : if (c_parser_next_token_is (parser, CPP_NAME))
14109 : {
14110 1763351 : c_token *comp_tok = c_parser_peek_token (parser);
14111 1763351 : ident = comp_tok->value;
14112 1763351 : comp_loc = comp_tok->location;
14113 : }
14114 : else
14115 : {
14116 0 : c_parser_error (parser, "expected identifier");
14117 0 : expr.set_error ();
14118 0 : expr.original_code = ERROR_MARK;
14119 0 : expr.original_type = NULL;
14120 0 : return expr;
14121 : }
14122 1763351 : start = expr.get_start ();
14123 1763351 : finish = c_parser_peek_token (parser)->get_finish ();
14124 1763351 : c_parser_consume_token (parser);
14125 1763351 : expr.value = build_component_ref (op_loc, expr.value, ident,
14126 : comp_loc, UNKNOWN_LOCATION);
14127 1763351 : set_c_expr_source_range (&expr, start, finish);
14128 1763351 : expr.original_code = ERROR_MARK;
14129 1763351 : if (TREE_CODE (expr.value) != COMPONENT_REF)
14130 32 : expr.original_type = NULL;
14131 : else
14132 : {
14133 : /* Remember the original type of a bitfield. */
14134 1763319 : tree field = TREE_OPERAND (expr.value, 1);
14135 1763319 : if (TREE_CODE (field) != FIELD_DECL)
14136 0 : expr.original_type = NULL;
14137 : else
14138 1763319 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
14139 : }
14140 1763351 : expr.m_decimal = 0;
14141 1763351 : break;
14142 499925 : case CPP_DEREF:
14143 : /* Structure element reference. */
14144 499925 : c_parser_consume_token (parser);
14145 499925 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
14146 499925 : if (c_parser_next_token_is (parser, CPP_NAME))
14147 : {
14148 499893 : c_token *comp_tok = c_parser_peek_token (parser);
14149 499893 : ident = comp_tok->value;
14150 499893 : comp_loc = comp_tok->location;
14151 : }
14152 : else
14153 : {
14154 32 : c_parser_error (parser, "expected identifier");
14155 32 : expr.set_error ();
14156 32 : expr.original_code = ERROR_MARK;
14157 32 : expr.original_type = NULL;
14158 32 : return expr;
14159 : }
14160 499893 : start = expr.get_start ();
14161 499893 : finish = c_parser_peek_token (parser)->get_finish ();
14162 499893 : c_parser_consume_token (parser);
14163 499893 : expr.value = build_component_ref (op_loc,
14164 : build_indirect_ref (op_loc,
14165 : expr.value,
14166 : RO_ARROW),
14167 : ident, comp_loc,
14168 : expr.get_location ());
14169 499893 : set_c_expr_source_range (&expr, start, finish);
14170 499893 : expr.original_code = ERROR_MARK;
14171 499893 : if (TREE_CODE (expr.value) != COMPONENT_REF)
14172 121 : expr.original_type = NULL;
14173 : else
14174 : {
14175 : /* Remember the original type of a bitfield. */
14176 499772 : tree field = TREE_OPERAND (expr.value, 1);
14177 499772 : if (TREE_CODE (field) != FIELD_DECL)
14178 0 : expr.original_type = NULL;
14179 : else
14180 499772 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
14181 : }
14182 499893 : expr.m_decimal = 0;
14183 499893 : break;
14184 676000 : case CPP_PLUS_PLUS:
14185 : /* Postincrement. */
14186 676000 : start = expr.get_start ();
14187 676000 : finish = c_parser_peek_token (parser)->get_finish ();
14188 676000 : c_parser_consume_token (parser);
14189 237089 : if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
14190 603820 : && !DECL_READ_P (expr.value)
14191 161491 : && (VAR_P (expr.value) ? warn_unused_but_set_variable
14192 : : warn_unused_but_set_parameter) > 1
14193 706971 : && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
14194 : {
14195 30971 : expr = default_function_array_read_conversion (expr_loc, expr);
14196 30971 : DECL_READ_P (expr.value) = 0;
14197 : }
14198 : else
14199 645029 : expr = default_function_array_read_conversion (expr_loc, expr);
14200 676000 : expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
14201 : expr.value, false);
14202 676000 : set_c_expr_source_range (&expr, start, finish);
14203 676000 : expr.original_code = ERROR_MARK;
14204 676000 : expr.original_type = NULL;
14205 676000 : break;
14206 18020 : case CPP_MINUS_MINUS:
14207 : /* Postdecrement. */
14208 18020 : start = expr.get_start ();
14209 18020 : finish = c_parser_peek_token (parser)->get_finish ();
14210 18020 : c_parser_consume_token (parser);
14211 6474 : if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
14212 14982 : && !DECL_READ_P (expr.value)
14213 3395 : && (VAR_P (expr.value) ? warn_unused_but_set_variable
14214 : : warn_unused_but_set_parameter) > 1
14215 18356 : && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
14216 : {
14217 336 : expr = default_function_array_read_conversion (expr_loc, expr);
14218 336 : DECL_READ_P (expr.value) = 0;
14219 : }
14220 : else
14221 17684 : expr = default_function_array_read_conversion (expr_loc, expr);
14222 18020 : expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
14223 : expr.value, false);
14224 18020 : set_c_expr_source_range (&expr, start, finish);
14225 18020 : expr.original_code = ERROR_MARK;
14226 18020 : expr.original_type = NULL;
14227 18020 : break;
14228 236815949 : default:
14229 236815949 : return expr;
14230 : }
14231 : }
14232 : }
14233 :
14234 : /* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
14235 :
14236 : expression:
14237 : assignment-expression
14238 : expression , assignment-expression
14239 : */
14240 :
14241 : static struct c_expr
14242 55395620 : c_parser_expression (c_parser *parser)
14243 : {
14244 55395620 : location_t tloc = c_parser_peek_token (parser)->location;
14245 55395620 : struct c_expr expr;
14246 55395620 : expr = c_parser_expr_no_commas (parser, NULL);
14247 55395620 : if (c_parser_next_token_is (parser, CPP_COMMA))
14248 88593 : expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
14249 55497395 : while (c_parser_next_token_is (parser, CPP_COMMA))
14250 : {
14251 101775 : struct c_expr next;
14252 101775 : tree lhsval;
14253 101775 : location_t loc = c_parser_peek_token (parser)->location;
14254 101775 : location_t expr_loc;
14255 101775 : c_parser_consume_token (parser);
14256 101775 : expr_loc = c_parser_peek_token (parser)->location;
14257 101775 : lhsval = expr.value;
14258 101775 : while (TREE_CODE (lhsval) == COMPOUND_EXPR
14259 115811 : || TREE_CODE (lhsval) == NOP_EXPR)
14260 : {
14261 14036 : if (TREE_CODE (lhsval) == COMPOUND_EXPR)
14262 13938 : lhsval = TREE_OPERAND (lhsval, 1);
14263 : else
14264 98 : lhsval = TREE_OPERAND (lhsval, 0);
14265 : }
14266 101775 : if (DECL_P (lhsval) || handled_component_p (lhsval))
14267 89 : mark_exp_read (lhsval);
14268 101775 : if (c_parser_next_token_is (parser, CPP_EMBED))
14269 : {
14270 : /* Users aren't interested in milions of -Wunused-value
14271 : warnings when using #embed inside of a comma expression,
14272 : and one CPP_NUMBER plus CPP_COMMA before it and one
14273 : CPP_COMMA plus CPP_NUMBER after it is guaranteed by
14274 : the preprocessor. Thus, parse the whole CPP_EMBED just
14275 : as a single INTEGER_CST, the last byte in it. */
14276 1 : c_token *embed = c_parser_peek_token (parser);
14277 1 : tree val = embed->value;
14278 1 : unsigned last = RAW_DATA_LENGTH (val) - 1;
14279 1 : next.value = build_int_cst (TREE_TYPE (val),
14280 1 : RAW_DATA_UCHAR_ELT (val, last));
14281 1 : next.original_type = integer_type_node;
14282 1 : c_parser_consume_token (parser);
14283 : }
14284 : else
14285 : {
14286 101774 : next = c_parser_expr_no_commas (parser, NULL);
14287 101774 : next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
14288 : }
14289 101775 : expr.value = build_compound_expr (loc, expr.value, next.value);
14290 101775 : expr.original_code = COMPOUND_EXPR;
14291 101775 : expr.original_type = next.original_type;
14292 101775 : expr.m_decimal = 0;
14293 : }
14294 55395620 : return expr;
14295 : }
14296 :
14297 : /* Parse an expression and convert functions or arrays to pointers and
14298 : lvalues to rvalues. */
14299 :
14300 : static struct c_expr
14301 42364664 : c_parser_expression_conv (c_parser *parser)
14302 : {
14303 42364664 : struct c_expr expr;
14304 42364664 : location_t loc = c_parser_peek_token (parser)->location;
14305 42364664 : expr = c_parser_expression (parser);
14306 42364664 : expr = convert_lvalue_to_rvalue (loc, expr, true, false);
14307 42364664 : return expr;
14308 : }
14309 :
14310 : /* Helper function of c_parser_expr_list. Check if IDXth (0 based)
14311 : argument is a literal zero alone and if so, set it in literal_zero_mask. */
14312 :
14313 : static inline void
14314 126043522 : c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
14315 : unsigned int idx)
14316 : {
14317 126043522 : if (idx >= HOST_BITS_PER_INT)
14318 : return;
14319 :
14320 126021497 : c_token *tok = c_parser_peek_token (parser);
14321 126021497 : switch (tok->type)
14322 : {
14323 6887805 : case CPP_NUMBER:
14324 6887805 : case CPP_CHAR:
14325 6887805 : case CPP_WCHAR:
14326 6887805 : case CPP_CHAR16:
14327 6887805 : case CPP_CHAR32:
14328 6887805 : case CPP_UTF8CHAR:
14329 : /* If a parameter is literal zero alone, remember it
14330 : for -Wmemset-transposed-args warning. */
14331 6887805 : if (integer_zerop (tok->value)
14332 1260920 : && !TREE_OVERFLOW (tok->value)
14333 8148725 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14334 873608 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
14335 1260086 : *literal_zero_mask |= 1U << idx;
14336 : default:
14337 : break;
14338 : }
14339 : }
14340 :
14341 : /* Parse a non-empty list of expressions. If CONVERT_P, convert
14342 : functions and arrays to pointers and lvalues to rvalues. If
14343 : FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
14344 : locations of function arguments into this vector.
14345 :
14346 : nonempty-expr-list:
14347 : assignment-expression
14348 : nonempty-expr-list , assignment-expression
14349 : */
14350 :
14351 : static vec<tree, va_gc> *
14352 42502436 : c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
14353 : vec<tree, va_gc> **p_orig_types,
14354 : location_t *sizeof_arg_loc, tree *sizeof_arg,
14355 : vec<location_t> *locations,
14356 : unsigned int *literal_zero_mask)
14357 : {
14358 42502436 : vec<tree, va_gc> *ret;
14359 42502436 : vec<tree, va_gc> *orig_types;
14360 42502436 : struct c_expr expr;
14361 42502436 : unsigned int idx = 0;
14362 42502436 : bool save_c_omp_array_section_p = c_omp_array_section_p;
14363 42502436 : c_omp_array_section_p = false;
14364 :
14365 42502436 : ret = make_tree_vector ();
14366 42502436 : if (p_orig_types == NULL)
14367 4484876 : orig_types = NULL;
14368 : else
14369 38017560 : orig_types = make_tree_vector ();
14370 :
14371 42502436 : if (literal_zero_mask)
14372 38017560 : c_parser_check_literal_zero (parser, literal_zero_mask, 0);
14373 42502436 : expr = c_parser_expr_no_commas (parser, NULL);
14374 42502436 : if (convert_p)
14375 38018031 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
14376 42502436 : if (fold_p)
14377 4484876 : expr.value = c_fully_fold (expr.value, false, NULL);
14378 42502436 : ret->quick_push (expr.value);
14379 42502436 : if (orig_types)
14380 38017560 : orig_types->quick_push (expr.original_type);
14381 42502436 : if (locations)
14382 38017560 : locations->safe_push (expr.get_location ());
14383 42502436 : if (sizeof_arg != NULL
14384 38017560 : && (expr.original_code == SIZEOF_EXPR
14385 38017560 : || expr.original_code == PAREN_SIZEOF_EXPR))
14386 : {
14387 2115 : sizeof_arg[0] = c_last_sizeof_arg;
14388 2115 : sizeof_arg_loc[0] = c_last_sizeof_loc;
14389 : }
14390 131865522 : while (c_parser_next_token_is (parser, CPP_COMMA))
14391 : {
14392 89363086 : c_parser_consume_token (parser);
14393 89363086 : if (c_parser_next_token_is (parser, CPP_EMBED))
14394 : {
14395 3 : c_token *embed = c_parser_peek_token (parser);
14396 3 : tree value = embed->value;
14397 3 : expr.original_code = INTEGER_CST;
14398 3 : expr.original_type = integer_type_node;
14399 3 : expr.value = NULL_TREE;
14400 3 : set_c_expr_source_range (&expr, embed->get_range ());
14401 3 : expr.m_decimal = 0;
14402 381 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
14403 : {
14404 378 : if (literal_zero_mask
14405 126 : && idx + 1 < HOST_BITS_PER_INT
14406 409 : && RAW_DATA_POINTER (value)[i] == 0)
14407 0 : *literal_zero_mask |= 1U << (idx + 1);
14408 378 : expr.value = build_int_cst (integer_type_node,
14409 378 : RAW_DATA_UCHAR_ELT (value, i));
14410 378 : vec_safe_push (ret, expr.value);
14411 378 : if (orig_types)
14412 126 : vec_safe_push (orig_types, expr.original_type);
14413 378 : if (locations)
14414 126 : locations->safe_push (expr.get_location ());
14415 378 : ++idx;
14416 : }
14417 3 : c_parser_consume_token (parser);
14418 3 : continue;
14419 3 : }
14420 89363083 : if (literal_zero_mask)
14421 88025962 : c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
14422 89363083 : expr = c_parser_expr_no_commas (parser, NULL);
14423 89363083 : if (convert_p)
14424 88026228 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
14425 : true);
14426 89363083 : if (fold_p)
14427 1337121 : expr.value = c_fully_fold (expr.value, false, NULL);
14428 89363083 : vec_safe_push (ret, expr.value);
14429 89363083 : if (orig_types)
14430 88025962 : vec_safe_push (orig_types, expr.original_type);
14431 89363083 : if (locations)
14432 88025962 : locations->safe_push (expr.get_location ());
14433 89363083 : if (++idx < 6
14434 87814569 : && sizeof_arg != NULL
14435 89363083 : && (expr.original_code == SIZEOF_EXPR
14436 86477462 : || expr.original_code == PAREN_SIZEOF_EXPR))
14437 : {
14438 79108 : sizeof_arg[idx] = c_last_sizeof_arg;
14439 79108 : sizeof_arg_loc[idx] = c_last_sizeof_loc;
14440 : }
14441 : }
14442 42502436 : if (orig_types)
14443 38017560 : *p_orig_types = orig_types;
14444 42502436 : c_omp_array_section_p = save_c_omp_array_section_p;
14445 42502436 : return ret;
14446 : }
14447 :
14448 : /* Parse Objective-C-specific constructs. */
14449 :
14450 : /* Parse an objc-class-definition.
14451 :
14452 : objc-class-definition:
14453 : @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
14454 : objc-class-instance-variables[opt] objc-methodprotolist @end
14455 : @implementation identifier objc-superclass[opt]
14456 : objc-class-instance-variables[opt]
14457 : @interface identifier ( identifier ) objc-protocol-refs[opt]
14458 : objc-methodprotolist @end
14459 : @interface identifier ( ) objc-protocol-refs[opt]
14460 : objc-methodprotolist @end
14461 : @implementation identifier ( identifier )
14462 :
14463 : objc-superclass:
14464 : : identifier
14465 :
14466 : "@interface identifier (" must start "@interface identifier (
14467 : identifier ) ...": objc-methodprotolist in the first production may
14468 : not start with a parenthesized identifier as a declarator of a data
14469 : definition with no declaration specifiers if the objc-superclass,
14470 : objc-protocol-refs and objc-class-instance-variables are omitted. */
14471 :
14472 : static void
14473 0 : c_parser_objc_class_definition (c_parser *parser, tree attributes)
14474 : {
14475 0 : bool iface_p;
14476 0 : tree id1;
14477 0 : tree superclass;
14478 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
14479 : iface_p = true;
14480 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
14481 : iface_p = false;
14482 : else
14483 0 : gcc_unreachable ();
14484 :
14485 0 : c_parser_consume_token (parser);
14486 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14487 : {
14488 0 : c_parser_error (parser, "expected identifier");
14489 0 : return;
14490 : }
14491 0 : id1 = c_parser_peek_token (parser)->value;
14492 0 : location_t loc1 = c_parser_peek_token (parser)->location;
14493 0 : c_parser_consume_token (parser);
14494 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14495 : {
14496 : /* We have a category or class extension. */
14497 0 : tree id2;
14498 0 : tree proto = NULL_TREE;
14499 0 : matching_parens parens;
14500 0 : parens.consume_open (parser);
14501 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14502 : {
14503 0 : if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
14504 : {
14505 : /* We have a class extension. */
14506 : id2 = NULL_TREE;
14507 : }
14508 : else
14509 : {
14510 0 : c_parser_error (parser, "expected identifier or %<)%>");
14511 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
14512 0 : return;
14513 : }
14514 : }
14515 : else
14516 : {
14517 0 : id2 = c_parser_peek_token (parser)->value;
14518 0 : c_parser_consume_token (parser);
14519 : }
14520 0 : parens.skip_until_found_close (parser);
14521 0 : if (!iface_p)
14522 : {
14523 0 : objc_start_category_implementation (id1, id2);
14524 0 : return;
14525 : }
14526 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14527 0 : proto = c_parser_objc_protocol_refs (parser);
14528 0 : objc_start_category_interface (id1, id2, proto, attributes);
14529 0 : c_parser_objc_methodprotolist (parser);
14530 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14531 0 : objc_finish_interface ();
14532 0 : return;
14533 : }
14534 0 : if (c_parser_next_token_is (parser, CPP_COLON))
14535 : {
14536 0 : c_parser_consume_token (parser);
14537 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14538 : {
14539 0 : c_parser_error (parser, "expected identifier");
14540 0 : return;
14541 : }
14542 0 : superclass = c_parser_peek_token (parser)->value;
14543 0 : c_parser_consume_token (parser);
14544 : }
14545 : else
14546 : superclass = NULL_TREE;
14547 0 : if (iface_p)
14548 : {
14549 0 : tree proto = NULL_TREE;
14550 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14551 0 : proto = c_parser_objc_protocol_refs (parser);
14552 0 : objc_start_class_interface (id1, loc1, superclass, proto, attributes);
14553 : }
14554 : else
14555 0 : objc_start_class_implementation (id1, superclass);
14556 0 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14557 0 : c_parser_objc_class_instance_variables (parser);
14558 0 : if (iface_p)
14559 : {
14560 0 : objc_continue_interface ();
14561 0 : c_parser_objc_methodprotolist (parser);
14562 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14563 0 : objc_finish_interface ();
14564 : }
14565 : else
14566 : {
14567 0 : objc_continue_implementation ();
14568 0 : return;
14569 : }
14570 : }
14571 :
14572 : /* Parse objc-class-instance-variables.
14573 :
14574 : objc-class-instance-variables:
14575 : { objc-instance-variable-decl-list[opt] }
14576 :
14577 : objc-instance-variable-decl-list:
14578 : objc-visibility-spec
14579 : objc-instance-variable-decl ;
14580 : ;
14581 : objc-instance-variable-decl-list objc-visibility-spec
14582 : objc-instance-variable-decl-list objc-instance-variable-decl ;
14583 : objc-instance-variable-decl-list ;
14584 :
14585 : objc-visibility-spec:
14586 : @private
14587 : @protected
14588 : @public
14589 :
14590 : objc-instance-variable-decl:
14591 : struct-declaration
14592 : */
14593 :
14594 : static void
14595 0 : c_parser_objc_class_instance_variables (c_parser *parser)
14596 : {
14597 0 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
14598 0 : c_parser_consume_token (parser);
14599 0 : while (c_parser_next_token_is_not (parser, CPP_EOF))
14600 : {
14601 0 : tree decls;
14602 : /* Parse any stray semicolon. */
14603 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14604 : {
14605 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14606 : "extra semicolon");
14607 0 : c_parser_consume_token (parser);
14608 0 : continue;
14609 : }
14610 : /* Stop if at the end of the instance variables. */
14611 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
14612 : {
14613 0 : c_parser_consume_token (parser);
14614 0 : break;
14615 : }
14616 : /* Parse any objc-visibility-spec. */
14617 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
14618 : {
14619 0 : c_parser_consume_token (parser);
14620 0 : objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
14621 0 : continue;
14622 : }
14623 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
14624 : {
14625 0 : c_parser_consume_token (parser);
14626 0 : objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
14627 0 : continue;
14628 : }
14629 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
14630 : {
14631 0 : c_parser_consume_token (parser);
14632 0 : objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
14633 0 : continue;
14634 : }
14635 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
14636 : {
14637 0 : c_parser_consume_token (parser);
14638 0 : objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
14639 0 : continue;
14640 : }
14641 0 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
14642 : {
14643 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14644 0 : continue;
14645 : }
14646 :
14647 : /* Parse some comma-separated declarations. */
14648 0 : decls = c_parser_struct_declaration (parser, NULL);
14649 0 : if (decls == NULL)
14650 : {
14651 : /* There is a syntax error. We want to skip the offending
14652 : tokens up to the next ';' (included) or '}'
14653 : (excluded). */
14654 :
14655 : /* First, skip manually a ')' or ']'. This is because they
14656 : reduce the nesting level, so c_parser_skip_until_found()
14657 : wouldn't be able to skip past them. */
14658 0 : c_token *token = c_parser_peek_token (parser);
14659 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
14660 0 : c_parser_consume_token (parser);
14661 :
14662 : /* Then, do the standard skipping. */
14663 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14664 :
14665 : /* We hopefully recovered. Start normal parsing again. */
14666 0 : parser->error = false;
14667 0 : continue;
14668 0 : }
14669 : else
14670 : {
14671 : /* Comma-separated instance variables are chained together
14672 : in reverse order; add them one by one. */
14673 0 : tree ivar = nreverse (decls);
14674 0 : for (; ivar; ivar = DECL_CHAIN (ivar))
14675 0 : objc_add_instance_variable (copy_node (ivar));
14676 : }
14677 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14678 : }
14679 0 : }
14680 :
14681 : /* Parse an objc-class-declaration.
14682 :
14683 : objc-class-declaration:
14684 : @class identifier-list ;
14685 : */
14686 :
14687 : static void
14688 0 : c_parser_objc_class_declaration (c_parser *parser)
14689 : {
14690 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
14691 0 : c_parser_consume_token (parser);
14692 : /* Any identifiers, including those declared as type names, are OK
14693 : here. */
14694 0 : while (true)
14695 : {
14696 0 : tree id;
14697 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14698 : {
14699 0 : c_parser_error (parser, "expected identifier");
14700 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14701 0 : parser->error = false;
14702 0 : return;
14703 : }
14704 0 : id = c_parser_peek_token (parser)->value;
14705 0 : objc_declare_class (id);
14706 0 : c_parser_consume_token (parser);
14707 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14708 0 : c_parser_consume_token (parser);
14709 : else
14710 : break;
14711 0 : }
14712 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14713 : }
14714 :
14715 : /* Parse an objc-alias-declaration.
14716 :
14717 : objc-alias-declaration:
14718 : @compatibility_alias identifier identifier ;
14719 : */
14720 :
14721 : static void
14722 0 : c_parser_objc_alias_declaration (c_parser *parser)
14723 : {
14724 0 : tree id1, id2;
14725 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
14726 0 : c_parser_consume_token (parser);
14727 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14728 : {
14729 0 : c_parser_error (parser, "expected identifier");
14730 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14731 0 : return;
14732 : }
14733 0 : id1 = c_parser_peek_token (parser)->value;
14734 0 : c_parser_consume_token (parser);
14735 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14736 : {
14737 0 : c_parser_error (parser, "expected identifier");
14738 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14739 0 : return;
14740 : }
14741 0 : id2 = c_parser_peek_token (parser)->value;
14742 0 : c_parser_consume_token (parser);
14743 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14744 0 : objc_declare_alias (id1, id2);
14745 : }
14746 :
14747 : /* Parse an objc-protocol-definition.
14748 :
14749 : objc-protocol-definition:
14750 : @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
14751 : @protocol identifier-list ;
14752 :
14753 : "@protocol identifier ;" should be resolved as "@protocol
14754 : identifier-list ;": objc-methodprotolist may not start with a
14755 : semicolon in the first alternative if objc-protocol-refs are
14756 : omitted. */
14757 :
14758 : static void
14759 0 : c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
14760 : {
14761 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
14762 :
14763 0 : c_parser_consume_token (parser);
14764 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14765 : {
14766 0 : c_parser_error (parser, "expected identifier");
14767 0 : return;
14768 : }
14769 0 : if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14770 0 : || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
14771 : {
14772 : /* Any identifiers, including those declared as type names, are
14773 : OK here. */
14774 0 : while (true)
14775 : {
14776 0 : tree id;
14777 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14778 : {
14779 0 : c_parser_error (parser, "expected identifier");
14780 0 : break;
14781 : }
14782 0 : id = c_parser_peek_token (parser)->value;
14783 0 : objc_declare_protocol (id, attributes);
14784 0 : c_parser_consume_token (parser);
14785 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14786 0 : c_parser_consume_token (parser);
14787 : else
14788 : break;
14789 0 : }
14790 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14791 : }
14792 : else
14793 : {
14794 0 : tree id = c_parser_peek_token (parser)->value;
14795 0 : tree proto = NULL_TREE;
14796 0 : c_parser_consume_token (parser);
14797 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14798 0 : proto = c_parser_objc_protocol_refs (parser);
14799 0 : parser->objc_pq_context = true;
14800 0 : objc_start_protocol (id, proto, attributes);
14801 0 : c_parser_objc_methodprotolist (parser);
14802 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14803 0 : parser->objc_pq_context = false;
14804 0 : objc_finish_interface ();
14805 : }
14806 : }
14807 :
14808 : /* Parse an objc-method-type.
14809 :
14810 : objc-method-type:
14811 : +
14812 : -
14813 :
14814 : Return true if it is a class method (+) and false if it is
14815 : an instance method (-).
14816 : */
14817 : static inline bool
14818 0 : c_parser_objc_method_type (c_parser *parser)
14819 : {
14820 0 : switch (c_parser_peek_token (parser)->type)
14821 : {
14822 0 : case CPP_PLUS:
14823 0 : c_parser_consume_token (parser);
14824 0 : return true;
14825 0 : case CPP_MINUS:
14826 0 : c_parser_consume_token (parser);
14827 0 : return false;
14828 0 : default:
14829 0 : gcc_unreachable ();
14830 : }
14831 : }
14832 :
14833 : /* Parse an objc-method-definition.
14834 :
14835 : objc-method-definition:
14836 : objc-method-type objc-method-decl ;[opt] compound-statement
14837 : */
14838 :
14839 : static void
14840 0 : c_parser_objc_method_definition (c_parser *parser)
14841 : {
14842 0 : bool is_class_method = c_parser_objc_method_type (parser);
14843 0 : tree decl, attributes = NULL_TREE, expr = NULL_TREE;
14844 0 : parser->objc_pq_context = true;
14845 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14846 : &expr);
14847 0 : if (decl == error_mark_node)
14848 0 : return; /* Bail here. */
14849 :
14850 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14851 : {
14852 0 : c_parser_consume_token (parser);
14853 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14854 : "extra semicolon in method definition specified");
14855 : }
14856 :
14857 0 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14858 : {
14859 0 : c_parser_error (parser, "expected %<{%>");
14860 0 : return;
14861 : }
14862 :
14863 0 : parser->objc_pq_context = false;
14864 0 : if (objc_start_method_definition (is_class_method, decl, attributes, expr))
14865 : {
14866 0 : add_stmt (c_parser_compound_statement (parser));
14867 0 : objc_finish_method_definition (current_function_decl);
14868 : }
14869 : else
14870 : {
14871 : /* This code is executed when we find a method definition
14872 : outside of an @implementation context (or invalid for other
14873 : reasons). Parse the method (to keep going) but do not emit
14874 : any code.
14875 : */
14876 0 : c_parser_compound_statement (parser);
14877 : }
14878 : }
14879 :
14880 : /* Parse an objc-methodprotolist.
14881 :
14882 : objc-methodprotolist:
14883 : empty
14884 : objc-methodprotolist objc-methodproto
14885 : objc-methodprotolist declaration
14886 : objc-methodprotolist ;
14887 : @optional
14888 : @required
14889 :
14890 : The declaration is a data definition, which may be missing
14891 : declaration specifiers under the same rules and diagnostics as
14892 : other data definitions outside functions, and the stray semicolon
14893 : is diagnosed the same way as a stray semicolon outside a
14894 : function. */
14895 :
14896 : static void
14897 0 : c_parser_objc_methodprotolist (c_parser *parser)
14898 : {
14899 0 : while (true)
14900 : {
14901 : /* The list is terminated by @end. */
14902 0 : switch (c_parser_peek_token (parser)->type)
14903 : {
14904 0 : case CPP_SEMICOLON:
14905 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14906 : "ISO C does not allow extra %<;%> outside of a function");
14907 0 : c_parser_consume_token (parser);
14908 0 : break;
14909 0 : case CPP_PLUS:
14910 0 : case CPP_MINUS:
14911 0 : c_parser_objc_methodproto (parser);
14912 0 : break;
14913 0 : case CPP_PRAGMA:
14914 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14915 0 : break;
14916 : case CPP_EOF:
14917 : return;
14918 0 : default:
14919 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_END))
14920 : return;
14921 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
14922 0 : c_parser_objc_at_property_declaration (parser);
14923 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
14924 : {
14925 0 : objc_set_method_opt (true);
14926 0 : c_parser_consume_token (parser);
14927 : }
14928 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
14929 : {
14930 0 : objc_set_method_opt (false);
14931 0 : c_parser_consume_token (parser);
14932 : }
14933 : else
14934 0 : c_parser_declaration_or_fndef (parser, false, false, true,
14935 : false, true, false);
14936 : break;
14937 : }
14938 : }
14939 : }
14940 :
14941 : /* Parse an objc-methodproto.
14942 :
14943 : objc-methodproto:
14944 : objc-method-type objc-method-decl ;
14945 : */
14946 :
14947 : static void
14948 0 : c_parser_objc_methodproto (c_parser *parser)
14949 : {
14950 0 : bool is_class_method = c_parser_objc_method_type (parser);
14951 0 : tree decl, attributes = NULL_TREE;
14952 :
14953 : /* Remember protocol qualifiers in prototypes. */
14954 0 : parser->objc_pq_context = true;
14955 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14956 : NULL);
14957 : /* Forget protocol qualifiers now. */
14958 0 : parser->objc_pq_context = false;
14959 :
14960 : /* Do not allow the presence of attributes to hide an erroneous
14961 : method implementation in the interface section. */
14962 0 : if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
14963 : {
14964 0 : c_parser_error (parser, "expected %<;%>");
14965 0 : return;
14966 : }
14967 :
14968 0 : if (decl != error_mark_node)
14969 0 : objc_add_method_declaration (is_class_method, decl, attributes);
14970 :
14971 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14972 : }
14973 :
14974 : /* If we are at a position that method attributes may be present, check that
14975 : there are not any parsed already (a syntax error) and then collect any
14976 : specified at the current location. Finally, if new attributes were present,
14977 : check that the next token is legal ( ';' for decls and '{' for defs). */
14978 :
14979 : static bool
14980 0 : c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
14981 : {
14982 0 : bool bad = false;
14983 0 : if (*attributes)
14984 : {
14985 0 : c_parser_error (parser,
14986 : "method attributes must be specified at the end only");
14987 0 : *attributes = NULL_TREE;
14988 0 : bad = true;
14989 : }
14990 :
14991 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
14992 0 : *attributes = c_parser_gnu_attributes (parser);
14993 :
14994 : /* If there were no attributes here, just report any earlier error. */
14995 0 : if (*attributes == NULL_TREE || bad)
14996 : return bad;
14997 :
14998 : /* If the attributes are followed by a ; or {, then just report any earlier
14999 : error. */
15000 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
15001 0 : || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
15002 0 : return bad;
15003 :
15004 : /* We've got attributes, but not at the end. */
15005 0 : c_parser_error (parser,
15006 : "expected %<;%> or %<{%> after method attribute definition");
15007 0 : return true;
15008 : }
15009 :
15010 : /* Parse an objc-method-decl.
15011 :
15012 : objc-method-decl:
15013 : ( objc-type-name ) objc-selector
15014 : objc-selector
15015 : ( objc-type-name ) objc-keyword-selector objc-optparmlist
15016 : objc-keyword-selector objc-optparmlist
15017 : gnu-attributes
15018 :
15019 : objc-keyword-selector:
15020 : objc-keyword-decl
15021 : objc-keyword-selector objc-keyword-decl
15022 :
15023 : objc-keyword-decl:
15024 : objc-selector : ( objc-type-name ) identifier
15025 : objc-selector : identifier
15026 : : ( objc-type-name ) identifier
15027 : : identifier
15028 :
15029 : objc-optparmlist:
15030 : objc-optparms objc-optellipsis
15031 :
15032 : objc-optparms:
15033 : empty
15034 : objc-opt-parms , parameter-declaration
15035 :
15036 : objc-optellipsis:
15037 : empty
15038 : , ...
15039 : */
15040 :
15041 : static tree
15042 0 : c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
15043 : tree *attributes, tree *expr)
15044 : {
15045 0 : tree type = NULL_TREE;
15046 0 : tree sel;
15047 0 : tree parms = NULL_TREE;
15048 0 : bool ellipsis = false;
15049 0 : bool attr_err = false;
15050 :
15051 0 : *attributes = NULL_TREE;
15052 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
15053 : {
15054 0 : matching_parens parens;
15055 0 : parens.consume_open (parser);
15056 0 : type = c_parser_objc_type_name (parser);
15057 0 : parens.skip_until_found_close (parser);
15058 : }
15059 0 : sel = c_parser_objc_selector (parser);
15060 : /* If there is no selector, or a colon follows, we have an
15061 : objc-keyword-selector. If there is a selector, and a colon does
15062 : not follow, that selector ends the objc-method-decl. */
15063 0 : if (!sel || c_parser_next_token_is (parser, CPP_COLON))
15064 : {
15065 : tree tsel = sel;
15066 : tree list = NULL_TREE;
15067 0 : while (true)
15068 : {
15069 0 : tree atype = NULL_TREE, id, keyworddecl;
15070 0 : tree param_attr = NULL_TREE;
15071 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15072 : break;
15073 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
15074 : {
15075 0 : c_parser_consume_token (parser);
15076 0 : atype = c_parser_objc_type_name (parser);
15077 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
15078 : "expected %<)%>");
15079 : }
15080 : /* New ObjC allows attributes on method parameters. */
15081 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
15082 0 : param_attr = c_parser_gnu_attributes (parser);
15083 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15084 : {
15085 0 : c_parser_error (parser, "expected identifier");
15086 0 : return error_mark_node;
15087 : }
15088 0 : id = c_parser_peek_token (parser)->value;
15089 0 : c_parser_consume_token (parser);
15090 0 : keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
15091 0 : list = chainon (list, keyworddecl);
15092 0 : tsel = c_parser_objc_selector (parser);
15093 0 : if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
15094 : break;
15095 : }
15096 :
15097 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
15098 :
15099 : /* Parse the optional parameter list. Optional Objective-C
15100 : method parameters follow the C syntax, and may include '...'
15101 : to denote a variable number of arguments. */
15102 0 : parms = make_node (TREE_LIST);
15103 0 : while (c_parser_next_token_is (parser, CPP_COMMA))
15104 : {
15105 0 : struct c_parm *parm;
15106 0 : c_parser_consume_token (parser);
15107 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
15108 : {
15109 0 : ellipsis = true;
15110 0 : c_parser_consume_token (parser);
15111 0 : attr_err |= c_parser_objc_maybe_method_attributes
15112 0 : (parser, attributes) ;
15113 0 : break;
15114 : }
15115 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
15116 0 : if (parm == NULL)
15117 : break;
15118 0 : parms = chainon (parms,
15119 : build_tree_list (NULL_TREE, grokparm (parm, expr)));
15120 : }
15121 : sel = list;
15122 : }
15123 : else
15124 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
15125 :
15126 0 : if (sel == NULL)
15127 : {
15128 0 : c_parser_error (parser, "objective-c method declaration is expected");
15129 0 : return error_mark_node;
15130 : }
15131 :
15132 0 : if (attr_err)
15133 0 : return error_mark_node;
15134 :
15135 0 : return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
15136 : }
15137 :
15138 : /* Parse an objc-type-name.
15139 :
15140 : objc-type-name:
15141 : objc-type-qualifiers[opt] type-name
15142 : objc-type-qualifiers[opt]
15143 :
15144 : objc-type-qualifiers:
15145 : objc-type-qualifier
15146 : objc-type-qualifiers objc-type-qualifier
15147 :
15148 : objc-type-qualifier: one of
15149 : in out inout bycopy byref oneway
15150 : */
15151 :
15152 : static tree
15153 0 : c_parser_objc_type_name (c_parser *parser)
15154 : {
15155 0 : tree quals = NULL_TREE;
15156 0 : struct c_type_name *type_name = NULL;
15157 0 : tree type = NULL_TREE;
15158 0 : while (true)
15159 : {
15160 0 : c_token *token = c_parser_peek_token (parser);
15161 0 : if (token->type == CPP_KEYWORD
15162 0 : && (token->keyword == RID_IN
15163 : || token->keyword == RID_OUT
15164 : || token->keyword == RID_INOUT
15165 : || token->keyword == RID_BYCOPY
15166 : || token->keyword == RID_BYREF
15167 0 : || token->keyword == RID_ONEWAY))
15168 : {
15169 0 : quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
15170 0 : c_parser_consume_token (parser);
15171 : }
15172 : else
15173 : break;
15174 0 : }
15175 0 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
15176 0 : type_name = c_parser_type_name (parser);
15177 0 : if (type_name)
15178 0 : type = groktypename (type_name, NULL, NULL);
15179 :
15180 : /* If the type is unknown, and error has already been produced and
15181 : we need to recover from the error. In that case, use NULL_TREE
15182 : for the type, as if no type had been specified; this will use the
15183 : default type ('id') which is good for error recovery. */
15184 0 : if (type == error_mark_node)
15185 0 : type = NULL_TREE;
15186 :
15187 0 : return build_tree_list (quals, type);
15188 : }
15189 :
15190 : /* Parse objc-protocol-refs.
15191 :
15192 : objc-protocol-refs:
15193 : < identifier-list >
15194 : */
15195 :
15196 : static tree
15197 0 : c_parser_objc_protocol_refs (c_parser *parser)
15198 : {
15199 0 : tree list = NULL_TREE;
15200 0 : gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
15201 0 : c_parser_consume_token (parser);
15202 : /* Any identifiers, including those declared as type names, are OK
15203 : here. */
15204 0 : while (true)
15205 : {
15206 0 : tree id;
15207 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15208 : {
15209 0 : c_parser_error (parser, "expected identifier");
15210 0 : break;
15211 : }
15212 0 : id = c_parser_peek_token (parser)->value;
15213 0 : list = chainon (list, build_tree_list (NULL_TREE, id));
15214 0 : c_parser_consume_token (parser);
15215 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15216 0 : c_parser_consume_token (parser);
15217 : else
15218 : break;
15219 0 : }
15220 0 : c_parser_require (parser, CPP_GREATER, "expected %<>%>");
15221 0 : return list;
15222 : }
15223 :
15224 : /* Parse an objc-try-catch-finally-statement.
15225 :
15226 : objc-try-catch-finally-statement:
15227 : @try compound-statement objc-catch-list[opt]
15228 : @try compound-statement objc-catch-list[opt] @finally compound-statement
15229 :
15230 : objc-catch-list:
15231 : @catch ( objc-catch-parameter-declaration ) compound-statement
15232 : objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
15233 :
15234 : objc-catch-parameter-declaration:
15235 : parameter-declaration
15236 : '...'
15237 :
15238 : where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
15239 :
15240 : PS: This function is identical to cp_parser_objc_try_catch_finally_statement
15241 : for C++. Keep them in sync. */
15242 :
15243 : static void
15244 0 : c_parser_objc_try_catch_finally_statement (c_parser *parser)
15245 : {
15246 0 : location_t location;
15247 0 : tree stmt;
15248 :
15249 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
15250 0 : c_parser_consume_token (parser);
15251 0 : location = c_parser_peek_token (parser)->location;
15252 0 : objc_maybe_warn_exceptions (location);
15253 0 : stmt = c_parser_compound_statement (parser);
15254 0 : objc_begin_try_stmt (location, stmt);
15255 :
15256 0 : while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
15257 : {
15258 0 : struct c_parm *parm;
15259 0 : tree parameter_declaration = error_mark_node;
15260 0 : bool seen_open_paren = false;
15261 :
15262 0 : c_parser_consume_token (parser);
15263 0 : matching_parens parens;
15264 0 : if (!parens.require_open (parser))
15265 0 : seen_open_paren = true;
15266 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
15267 : {
15268 : /* We have "@catch (...)" (where the '...' are literally
15269 : what is in the code). Skip the '...'.
15270 : parameter_declaration is set to NULL_TREE, and
15271 : objc_being_catch_clauses() knows that that means
15272 : '...'. */
15273 0 : c_parser_consume_token (parser);
15274 0 : parameter_declaration = NULL_TREE;
15275 : }
15276 : else
15277 : {
15278 : /* We have "@catch (NSException *exception)" or something
15279 : like that. Parse the parameter declaration. */
15280 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
15281 0 : if (parm == NULL)
15282 0 : parameter_declaration = error_mark_node;
15283 : else
15284 0 : parameter_declaration = grokparm (parm, NULL);
15285 : }
15286 0 : if (seen_open_paren)
15287 0 : parens.require_close (parser);
15288 : else
15289 : {
15290 : /* If there was no open parenthesis, we are recovering from
15291 : an error, and we are trying to figure out what mistake
15292 : the user has made. */
15293 :
15294 : /* If there is an immediate closing parenthesis, the user
15295 : probably forgot the opening one (ie, they typed "@catch
15296 : NSException *e)". Parse the closing parenthesis and keep
15297 : going. */
15298 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15299 0 : c_parser_consume_token (parser);
15300 :
15301 : /* If these is no immediate closing parenthesis, the user
15302 : probably doesn't know that parenthesis are required at
15303 : all (ie, they typed "@catch NSException *e"). So, just
15304 : forget about the closing parenthesis and keep going. */
15305 : }
15306 0 : objc_begin_catch_clause (parameter_declaration);
15307 0 : if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
15308 0 : c_parser_compound_statement_nostart (parser);
15309 0 : objc_finish_catch_clause ();
15310 : }
15311 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
15312 : {
15313 0 : c_parser_consume_token (parser);
15314 0 : location = c_parser_peek_token (parser)->location;
15315 0 : stmt = c_parser_compound_statement (parser);
15316 0 : objc_build_finally_clause (location, stmt);
15317 : }
15318 0 : objc_finish_try_stmt ();
15319 0 : }
15320 :
15321 : /* Parse an objc-synchronized-statement.
15322 :
15323 : objc-synchronized-statement:
15324 : @synchronized ( expression ) compound-statement
15325 : */
15326 :
15327 : static void
15328 0 : c_parser_objc_synchronized_statement (c_parser *parser)
15329 : {
15330 0 : location_t loc;
15331 0 : tree expr, stmt;
15332 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
15333 0 : c_parser_consume_token (parser);
15334 0 : loc = c_parser_peek_token (parser)->location;
15335 0 : objc_maybe_warn_exceptions (loc);
15336 0 : matching_parens parens;
15337 0 : if (parens.require_open (parser))
15338 : {
15339 0 : struct c_expr ce = c_parser_expression (parser);
15340 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15341 0 : expr = ce.value;
15342 0 : expr = c_fully_fold (expr, false, NULL);
15343 0 : parens.skip_until_found_close (parser);
15344 : }
15345 : else
15346 0 : expr = error_mark_node;
15347 0 : stmt = c_parser_compound_statement (parser);
15348 0 : objc_build_synchronized (loc, expr, stmt);
15349 0 : }
15350 :
15351 : /* Parse an objc-selector; return NULL_TREE without an error if the
15352 : next token is not an objc-selector.
15353 :
15354 : objc-selector:
15355 : identifier
15356 : one of
15357 : enum struct union if else while do for switch case default
15358 : break continue return goto asm sizeof typeof typeof_unqual __alignof
15359 : unsigned long const short volatile signed restrict _Complex
15360 : in out inout bycopy byref oneway int char float double void _Bool
15361 : _Atomic
15362 :
15363 : ??? Why this selection of keywords but not, for example, storage
15364 : class specifiers? */
15365 :
15366 : static tree
15367 0 : c_parser_objc_selector (c_parser *parser)
15368 : {
15369 0 : c_token *token = c_parser_peek_token (parser);
15370 0 : tree value = token->value;
15371 0 : if (token->type == CPP_NAME)
15372 : {
15373 0 : c_parser_consume_token (parser);
15374 0 : return value;
15375 : }
15376 0 : if (token->type != CPP_KEYWORD)
15377 : return NULL_TREE;
15378 0 : switch (token->keyword)
15379 : {
15380 0 : case RID_ENUM:
15381 0 : case RID_STRUCT:
15382 0 : case RID_UNION:
15383 0 : case RID_IF:
15384 0 : case RID_ELSE:
15385 0 : case RID_WHILE:
15386 0 : case RID_DO:
15387 0 : case RID_FOR:
15388 0 : case RID_SWITCH:
15389 0 : case RID_CASE:
15390 0 : case RID_DEFAULT:
15391 0 : case RID_BREAK:
15392 0 : case RID_CONTINUE:
15393 0 : case RID_RETURN:
15394 0 : case RID_GOTO:
15395 0 : case RID_ASM:
15396 0 : case RID_SIZEOF:
15397 0 : case RID_TYPEOF:
15398 0 : case RID_TYPEOF_UNQUAL:
15399 0 : case RID_ALIGNOF:
15400 0 : case RID_UNSIGNED:
15401 0 : case RID_LONG:
15402 0 : case RID_CONST:
15403 0 : case RID_SHORT:
15404 0 : case RID_VOLATILE:
15405 0 : case RID_SIGNED:
15406 0 : case RID_RESTRICT:
15407 0 : case RID_COMPLEX:
15408 0 : case RID_IN:
15409 0 : case RID_OUT:
15410 0 : case RID_INOUT:
15411 0 : case RID_BYCOPY:
15412 0 : case RID_BYREF:
15413 0 : case RID_ONEWAY:
15414 0 : case RID_INT:
15415 0 : case RID_CHAR:
15416 0 : case RID_FLOAT:
15417 0 : case RID_DOUBLE:
15418 0 : CASE_RID_FLOATN_NX:
15419 0 : case RID_VOID:
15420 0 : case RID_BOOL:
15421 0 : case RID_ATOMIC:
15422 0 : case RID_AUTO_TYPE:
15423 0 : case RID_INT_N_0:
15424 0 : case RID_INT_N_1:
15425 0 : case RID_INT_N_2:
15426 0 : case RID_INT_N_3:
15427 0 : c_parser_consume_token (parser);
15428 0 : return value;
15429 : default:
15430 : return NULL_TREE;
15431 : }
15432 : }
15433 :
15434 : /* Parse an objc-selector-arg.
15435 :
15436 : objc-selector-arg:
15437 : objc-selector
15438 : objc-keywordname-list
15439 :
15440 : objc-keywordname-list:
15441 : objc-keywordname
15442 : objc-keywordname-list objc-keywordname
15443 :
15444 : objc-keywordname:
15445 : objc-selector :
15446 : :
15447 : */
15448 :
15449 : static tree
15450 0 : c_parser_objc_selector_arg (c_parser *parser)
15451 : {
15452 0 : tree sel = c_parser_objc_selector (parser);
15453 0 : tree list = NULL_TREE;
15454 0 : if (sel
15455 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15456 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15457 : return sel;
15458 0 : while (true)
15459 : {
15460 0 : if (c_parser_next_token_is (parser, CPP_SCOPE))
15461 : {
15462 0 : c_parser_consume_token (parser);
15463 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15464 0 : list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
15465 : }
15466 : else
15467 : {
15468 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15469 : return list;
15470 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15471 : }
15472 0 : sel = c_parser_objc_selector (parser);
15473 0 : if (!sel
15474 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15475 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15476 : break;
15477 : }
15478 : return list;
15479 : }
15480 :
15481 : /* Parse an objc-receiver.
15482 :
15483 : objc-receiver:
15484 : expression
15485 : class-name
15486 : type-name
15487 : */
15488 :
15489 : static tree
15490 0 : c_parser_objc_receiver (c_parser *parser)
15491 : {
15492 0 : location_t loc = c_parser_peek_token (parser)->location;
15493 :
15494 0 : if (c_parser_peek_token (parser)->type == CPP_NAME
15495 0 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
15496 0 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
15497 : {
15498 0 : tree id = c_parser_peek_token (parser)->value;
15499 0 : c_parser_consume_token (parser);
15500 0 : return objc_get_class_reference (id);
15501 : }
15502 0 : struct c_expr ce = c_parser_expression (parser);
15503 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15504 0 : return c_fully_fold (ce.value, false, NULL);
15505 : }
15506 :
15507 : /* Parse objc-message-args.
15508 :
15509 : objc-message-args:
15510 : objc-selector
15511 : objc-keywordarg-list
15512 :
15513 : objc-keywordarg-list:
15514 : objc-keywordarg
15515 : objc-keywordarg-list objc-keywordarg
15516 :
15517 : objc-keywordarg:
15518 : objc-selector : objc-keywordexpr
15519 : : objc-keywordexpr
15520 : */
15521 :
15522 : static tree
15523 0 : c_parser_objc_message_args (c_parser *parser)
15524 : {
15525 0 : tree sel = c_parser_objc_selector (parser);
15526 0 : tree list = NULL_TREE;
15527 0 : if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
15528 : return sel;
15529 0 : while (true)
15530 : {
15531 0 : tree keywordexpr;
15532 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15533 0 : return error_mark_node;
15534 0 : keywordexpr = c_parser_objc_keywordexpr (parser);
15535 0 : list = chainon (list, build_tree_list (sel, keywordexpr));
15536 0 : sel = c_parser_objc_selector (parser);
15537 0 : if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
15538 : break;
15539 : }
15540 : return list;
15541 : }
15542 :
15543 : /* Parse an objc-keywordexpr.
15544 :
15545 : objc-keywordexpr:
15546 : nonempty-expr-list
15547 : */
15548 :
15549 : static tree
15550 0 : c_parser_objc_keywordexpr (c_parser *parser)
15551 : {
15552 0 : tree ret;
15553 0 : vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true,
15554 : NULL, NULL, NULL, NULL);
15555 0 : if (vec_safe_length (expr_list) == 1)
15556 : {
15557 : /* Just return the expression, remove a level of
15558 : indirection. */
15559 0 : ret = (*expr_list)[0];
15560 : }
15561 : else
15562 : {
15563 : /* We have a comma expression, we will collapse later. */
15564 0 : ret = build_tree_list_vec (expr_list);
15565 : }
15566 0 : release_tree_vector (expr_list);
15567 0 : return ret;
15568 : }
15569 :
15570 : /* A check, needed in several places, that ObjC interface, implementation or
15571 : method definitions are not prefixed by incorrect items. */
15572 : static bool
15573 0 : c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
15574 : struct c_declspecs *specs)
15575 : {
15576 0 : if (!specs->declspecs_seen_p || specs->non_sc_seen_p
15577 0 : || specs->typespec_kind != ctsk_none)
15578 : {
15579 0 : c_parser_error (parser,
15580 : "no type or storage class may be specified here,");
15581 0 : c_parser_skip_to_end_of_block_or_statement (parser);
15582 0 : return true;
15583 : }
15584 : return false;
15585 : }
15586 :
15587 : /* Parse an Objective-C @property declaration. The syntax is:
15588 :
15589 : objc-property-declaration:
15590 : '@property' objc-property-attributes[opt] struct-declaration ;
15591 :
15592 : objc-property-attributes:
15593 : '(' objc-property-attribute-list ')'
15594 :
15595 : objc-property-attribute-list:
15596 : objc-property-attribute
15597 : objc-property-attribute-list, objc-property-attribute
15598 :
15599 : objc-property-attribute
15600 : 'getter' = identifier
15601 : 'setter' = identifier
15602 : 'readonly'
15603 : 'readwrite'
15604 : 'assign'
15605 : 'retain'
15606 : 'copy'
15607 : 'nonatomic'
15608 :
15609 : For example:
15610 : @property NSString *name;
15611 : @property (readonly) id object;
15612 : @property (retain, nonatomic, getter=getTheName) id name;
15613 : @property int a, b, c;
15614 :
15615 : PS: This function is identical to cp_parser_objc_at_propery_declaration
15616 : for C++. Keep them in sync. */
15617 : static void
15618 0 : c_parser_objc_at_property_declaration (c_parser *parser)
15619 : {
15620 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
15621 0 : location_t loc = c_parser_peek_token (parser)->location;
15622 0 : c_parser_consume_token (parser); /* Eat '@property'. */
15623 :
15624 : /* Parse the optional attribute list.
15625 :
15626 : A list of parsed, but not verified, attributes. */
15627 0 : vec<property_attribute_info *> prop_attr_list = vNULL;
15628 :
15629 0 : bool syntax_error = false;
15630 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
15631 : {
15632 0 : matching_parens parens;
15633 :
15634 0 : location_t attr_start = c_parser_peek_token (parser)->location;
15635 : /* Eat the '(' */
15636 0 : parens.consume_open (parser);
15637 :
15638 : /* Property attribute keywords are valid now. */
15639 0 : parser->objc_property_attr_context = true;
15640 :
15641 : /* Allow @property (), with a warning. */
15642 0 : location_t attr_end = c_parser_peek_token (parser)->location;
15643 :
15644 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15645 : {
15646 0 : location_t attr_comb = make_location (attr_end, attr_start, attr_end);
15647 0 : warning_at (attr_comb, OPT_Wattributes,
15648 : "empty property attribute list");
15649 : }
15650 : else
15651 0 : while (true)
15652 : {
15653 0 : c_token *token = c_parser_peek_token (parser);
15654 0 : attr_start = token->location;
15655 0 : attr_end = get_finish (token->location);
15656 0 : location_t attr_comb = make_location (attr_start, attr_start,
15657 : attr_end);
15658 :
15659 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
15660 : {
15661 0 : warning_at (attr_comb, OPT_Wattributes,
15662 : "missing property attribute");
15663 0 : if (token->type == CPP_CLOSE_PAREN)
15664 : break;
15665 0 : c_parser_consume_token (parser);
15666 0 : continue;
15667 : }
15668 :
15669 0 : tree attr_name = NULL_TREE;
15670 0 : enum rid keyword = RID_MAX; /* Not a valid property attribute. */
15671 0 : bool add_at = false;
15672 0 : if (token->type == CPP_KEYWORD)
15673 : {
15674 0 : keyword = token->keyword;
15675 0 : if (OBJC_IS_AT_KEYWORD (keyword))
15676 : {
15677 : /* For '@' keywords the token value has the keyword,
15678 : prepend the '@' for diagnostics. */
15679 0 : attr_name = token->value;
15680 0 : add_at = true;
15681 : }
15682 : else
15683 0 : attr_name = ridpointers[(int)keyword];
15684 : }
15685 0 : else if (token->type == CPP_NAME)
15686 0 : attr_name = token->value;
15687 0 : c_parser_consume_token (parser);
15688 :
15689 0 : enum objc_property_attribute_kind prop_kind
15690 0 : = objc_prop_attr_kind_for_rid (keyword);
15691 0 : property_attribute_info *prop
15692 0 : = new property_attribute_info (attr_name, attr_comb, prop_kind);
15693 0 : prop_attr_list.safe_push (prop);
15694 :
15695 0 : tree meth_name;
15696 0 : switch (prop->prop_kind)
15697 : {
15698 : default: break;
15699 0 : case OBJC_PROPERTY_ATTR_UNKNOWN:
15700 0 : if (attr_name)
15701 0 : error_at (attr_comb, "unknown property attribute %<%s%s%>",
15702 0 : add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
15703 : else
15704 0 : error_at (attr_comb, "unknown property attribute");
15705 0 : prop->parse_error = syntax_error = true;
15706 0 : break;
15707 :
15708 0 : case OBJC_PROPERTY_ATTR_GETTER:
15709 0 : case OBJC_PROPERTY_ATTR_SETTER:
15710 0 : if (c_parser_next_token_is_not (parser, CPP_EQ))
15711 : {
15712 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15713 0 : error_at (attr_comb, "expected %<=%> after Objective-C %qE",
15714 : attr_name);
15715 0 : prop->parse_error = syntax_error = true;
15716 0 : break;
15717 : }
15718 0 : token = c_parser_peek_token (parser);
15719 0 : attr_end = token->location;
15720 0 : c_parser_consume_token (parser); /* eat the = */
15721 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15722 : {
15723 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15724 0 : error_at (attr_comb, "expected %qE selector name",
15725 : attr_name);
15726 0 : prop->parse_error = syntax_error = true;
15727 0 : break;
15728 : }
15729 : /* Get the end of the method name, and consume the name. */
15730 0 : token = c_parser_peek_token (parser);
15731 0 : attr_end = get_finish (token->location);
15732 0 : meth_name = token->value;
15733 0 : c_parser_consume_token (parser);
15734 0 : if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
15735 : {
15736 0 : if (c_parser_next_token_is_not (parser, CPP_COLON))
15737 : {
15738 0 : attr_comb = make_location (attr_end, attr_start,
15739 : attr_end);
15740 0 : error_at (attr_comb, "setter method names must"
15741 : " terminate with %<:%>");
15742 0 : prop->parse_error = syntax_error = true;
15743 : }
15744 : else
15745 : {
15746 0 : attr_end = get_finish (c_parser_peek_token
15747 0 : (parser)->location);
15748 0 : c_parser_consume_token (parser);
15749 : }
15750 0 : attr_comb = make_location (attr_start, attr_start,
15751 : attr_end);
15752 : }
15753 : else
15754 0 : attr_comb = make_location (attr_start, attr_start,
15755 : attr_end);
15756 0 : prop->ident = meth_name;
15757 : /* Updated location including all that was successfully
15758 : parsed. */
15759 0 : prop->prop_loc = attr_comb;
15760 0 : break;
15761 : }
15762 :
15763 : /* If we see a comma here, then keep going - even if we already
15764 : saw a syntax error. For simple mistakes e.g. (asign, getter=x)
15765 : this makes a more useful output and avoid spurious warnings about
15766 : missing attributes that are, in fact, specified after the one with
15767 : the syntax error. */
15768 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15769 0 : c_parser_consume_token (parser);
15770 : else
15771 : break;
15772 : }
15773 0 : parser->objc_property_attr_context = false;
15774 :
15775 0 : if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
15776 : /* We don't really want to chew the whole of the file looking for a
15777 : matching closing parenthesis, so we will try to read the decl and
15778 : let the error handling for that close out the statement. */
15779 : ;
15780 : else
15781 0 : syntax_error = false, parens.skip_until_found_close (parser);
15782 : }
15783 :
15784 : /* 'properties' is the list of properties that we read. Usually a
15785 : single one, but maybe more (eg, in "@property int a, b, c;" there
15786 : are three). */
15787 0 : tree properties = c_parser_struct_declaration (parser, NULL);
15788 :
15789 0 : if (properties == error_mark_node)
15790 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15791 : else
15792 : {
15793 0 : if (properties == NULL_TREE)
15794 0 : c_parser_error (parser, "expected identifier");
15795 : else
15796 : {
15797 : /* Comma-separated properties are chained together in reverse order;
15798 : add them one by one. */
15799 0 : properties = nreverse (properties);
15800 0 : for (; properties; properties = TREE_CHAIN (properties))
15801 0 : objc_add_property_declaration (loc, copy_node (properties),
15802 : prop_attr_list);
15803 : }
15804 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15805 : }
15806 :
15807 0 : while (!prop_attr_list.is_empty())
15808 0 : delete prop_attr_list.pop ();
15809 0 : prop_attr_list.release ();
15810 0 : parser->error = false;
15811 0 : }
15812 :
15813 : /* Parse an Objective-C @synthesize declaration. The syntax is:
15814 :
15815 : objc-synthesize-declaration:
15816 : @synthesize objc-synthesize-identifier-list ;
15817 :
15818 : objc-synthesize-identifier-list:
15819 : objc-synthesize-identifier
15820 : objc-synthesize-identifier-list, objc-synthesize-identifier
15821 :
15822 : objc-synthesize-identifier
15823 : identifier
15824 : identifier = identifier
15825 :
15826 : For example:
15827 : @synthesize MyProperty;
15828 : @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
15829 :
15830 : PS: This function is identical to cp_parser_objc_at_synthesize_declaration
15831 : for C++. Keep them in sync.
15832 : */
15833 : static void
15834 0 : c_parser_objc_at_synthesize_declaration (c_parser *parser)
15835 : {
15836 0 : tree list = NULL_TREE;
15837 0 : location_t loc;
15838 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
15839 0 : loc = c_parser_peek_token (parser)->location;
15840 :
15841 0 : c_parser_consume_token (parser);
15842 0 : while (true)
15843 : {
15844 0 : tree property, ivar;
15845 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15846 : {
15847 0 : c_parser_error (parser, "expected identifier");
15848 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15849 : /* Once we find the semicolon, we can resume normal parsing.
15850 : We have to reset parser->error manually because
15851 : c_parser_skip_until_found() won't reset it for us if the
15852 : next token is precisely a semicolon. */
15853 0 : parser->error = false;
15854 0 : return;
15855 : }
15856 0 : property = c_parser_peek_token (parser)->value;
15857 0 : c_parser_consume_token (parser);
15858 0 : if (c_parser_next_token_is (parser, CPP_EQ))
15859 : {
15860 0 : c_parser_consume_token (parser);
15861 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15862 : {
15863 0 : c_parser_error (parser, "expected identifier");
15864 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15865 0 : parser->error = false;
15866 0 : return;
15867 : }
15868 0 : ivar = c_parser_peek_token (parser)->value;
15869 0 : c_parser_consume_token (parser);
15870 : }
15871 : else
15872 : ivar = NULL_TREE;
15873 0 : list = chainon (list, build_tree_list (ivar, property));
15874 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15875 0 : c_parser_consume_token (parser);
15876 : else
15877 : break;
15878 0 : }
15879 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15880 0 : objc_add_synthesize_declaration (loc, list);
15881 : }
15882 :
15883 : /* Parse an Objective-C @dynamic declaration. The syntax is:
15884 :
15885 : objc-dynamic-declaration:
15886 : @dynamic identifier-list ;
15887 :
15888 : For example:
15889 : @dynamic MyProperty;
15890 : @dynamic MyProperty, AnotherProperty;
15891 :
15892 : PS: This function is identical to cp_parser_objc_at_dynamic_declaration
15893 : for C++. Keep them in sync.
15894 : */
15895 : static void
15896 0 : c_parser_objc_at_dynamic_declaration (c_parser *parser)
15897 : {
15898 0 : tree list = NULL_TREE;
15899 0 : location_t loc;
15900 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
15901 0 : loc = c_parser_peek_token (parser)->location;
15902 :
15903 0 : c_parser_consume_token (parser);
15904 0 : while (true)
15905 : {
15906 0 : tree property;
15907 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15908 : {
15909 0 : c_parser_error (parser, "expected identifier");
15910 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15911 0 : parser->error = false;
15912 0 : return;
15913 : }
15914 0 : property = c_parser_peek_token (parser)->value;
15915 0 : list = chainon (list, build_tree_list (NULL_TREE, property));
15916 0 : c_parser_consume_token (parser);
15917 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15918 0 : c_parser_consume_token (parser);
15919 : else
15920 : break;
15921 0 : }
15922 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15923 0 : objc_add_dynamic_declaration (loc, list);
15924 : }
15925 :
15926 :
15927 : /* Parse a pragma GCC ivdep. */
15928 :
15929 : static bool
15930 128 : c_parse_pragma_ivdep (c_parser *parser)
15931 : {
15932 0 : c_parser_consume_pragma (parser);
15933 0 : c_parser_skip_to_pragma_eol (parser);
15934 128 : return true;
15935 : }
15936 :
15937 : /* Parse a pragma GCC novector. */
15938 :
15939 : static bool
15940 2911 : c_parse_pragma_novector (c_parser *parser)
15941 : {
15942 0 : c_parser_consume_pragma (parser);
15943 0 : c_parser_skip_to_pragma_eol (parser);
15944 2911 : return true;
15945 : }
15946 :
15947 : /* Parse a pragma GCC unroll. */
15948 :
15949 : static unsigned short
15950 288 : c_parser_pragma_unroll (c_parser *parser)
15951 : {
15952 288 : unsigned short unroll;
15953 288 : c_parser_consume_pragma (parser);
15954 288 : location_t location = c_parser_peek_token (parser)->location;
15955 288 : tree expr = c_parser_expr_no_commas (parser, NULL).value;
15956 288 : mark_exp_read (expr);
15957 288 : expr = c_fully_fold (expr, false, NULL);
15958 288 : HOST_WIDE_INT lunroll = 0;
15959 576 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
15960 287 : || TREE_CODE (expr) != INTEGER_CST
15961 286 : || (lunroll = tree_to_shwi (expr)) < 0
15962 573 : || lunroll >= USHRT_MAX)
15963 : {
15964 4 : error_at (location, "%<#pragma GCC unroll%> requires an"
15965 : " assignment-expression that evaluates to a non-negative"
15966 : " integral constant less than %u", USHRT_MAX);
15967 4 : unroll = 0;
15968 : }
15969 : else
15970 : {
15971 284 : unroll = (unsigned short)lunroll;
15972 284 : if (unroll == 0)
15973 : unroll = 1;
15974 : }
15975 :
15976 288 : c_parser_skip_to_pragma_eol (parser);
15977 288 : return unroll;
15978 : }
15979 :
15980 : /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
15981 : should be considered, statements. ALLOW_STMT is true if we're within
15982 : the context of a function and such pragmas are to be allowed. Returns
15983 : true if we actually parsed such a pragma. BEFORE_LABELS is last statement
15984 : before possible labels, see get_before_labels description for details. */
15985 :
15986 : static bool
15987 1927292 : c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
15988 : tree before_labels)
15989 : {
15990 1927292 : unsigned int id;
15991 1927292 : const char *construct = NULL;
15992 :
15993 1927292 : input_location = c_parser_peek_token (parser)->location;
15994 1927292 : id = c_parser_peek_token (parser)->pragma_kind;
15995 1927292 : gcc_assert (id != PRAGMA_NONE);
15996 1927292 : if (parser->omp_for_parse_state
15997 16 : && parser->omp_for_parse_state->in_intervening_code
15998 13 : && id >= PRAGMA_OMP__START_ && id <= PRAGMA_OMP__LAST_
15999 : /* Allow a safe subset of non-executable directives. See classification in
16000 : array c_omp_directives. */
16001 7 : && id != PRAGMA_OMP_METADIRECTIVE && id != PRAGMA_OMP_NOTHING
16002 5 : && id != PRAGMA_OMP_ASSUME && id != PRAGMA_OMP_ERROR)
16003 : {
16004 2 : error_at (
16005 : input_location,
16006 : "intervening code must not contain executable OpenMP directives");
16007 2 : parser->omp_for_parse_state->fail = true;
16008 2 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16009 2 : return false;
16010 : }
16011 :
16012 1927290 : switch (id)
16013 : {
16014 144 : case PRAGMA_OACC_DECLARE:
16015 144 : c_parser_oacc_declare (parser);
16016 144 : return false;
16017 :
16018 136 : case PRAGMA_OACC_ENTER_DATA:
16019 136 : if (context != pragma_compound)
16020 : {
16021 : construct = "acc enter data";
16022 62 : in_compound:
16023 62 : if (context == pragma_stmt)
16024 : {
16025 59 : error_at (c_parser_peek_token (parser)->location,
16026 : "%<#pragma %s%> may only be used in compound "
16027 : "statements", construct);
16028 59 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16029 59 : return true;
16030 : }
16031 3 : goto bad_stmt;
16032 : }
16033 133 : c_parser_oacc_enter_exit_data (parser, true);
16034 133 : return false;
16035 :
16036 131 : case PRAGMA_OACC_EXIT_DATA:
16037 131 : if (context != pragma_compound)
16038 : {
16039 3 : construct = "acc exit data";
16040 3 : goto in_compound;
16041 : }
16042 128 : c_parser_oacc_enter_exit_data (parser, false);
16043 128 : return false;
16044 :
16045 350 : case PRAGMA_OACC_ROUTINE:
16046 350 : if (context != pragma_external)
16047 : {
16048 5 : error_at (c_parser_peek_token (parser)->location,
16049 : "%<#pragma acc routine%> must be at file scope");
16050 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16051 5 : return false;
16052 : }
16053 345 : c_parser_oacc_routine (parser, context);
16054 345 : return false;
16055 :
16056 100 : case PRAGMA_OACC_UPDATE:
16057 100 : if (context != pragma_compound)
16058 : {
16059 8 : construct = "acc update";
16060 8 : goto in_compound;
16061 : }
16062 92 : c_parser_oacc_update (parser);
16063 92 : return false;
16064 :
16065 357 : case PRAGMA_OMP_BARRIER:
16066 357 : if (context != pragma_compound)
16067 : {
16068 11 : construct = "omp barrier";
16069 11 : goto in_compound;
16070 : }
16071 346 : c_parser_omp_barrier (parser);
16072 346 : return false;
16073 :
16074 76 : case PRAGMA_OMP_DEPOBJ:
16075 76 : if (context != pragma_compound)
16076 : {
16077 1 : construct = "omp depobj";
16078 1 : goto in_compound;
16079 : }
16080 75 : c_parser_omp_depobj (parser);
16081 75 : return false;
16082 :
16083 68 : case PRAGMA_OMP_FLUSH:
16084 68 : if (context != pragma_compound)
16085 : {
16086 9 : construct = "omp flush";
16087 9 : goto in_compound;
16088 : }
16089 59 : c_parser_omp_flush (parser);
16090 59 : return false;
16091 :
16092 183 : case PRAGMA_OMP_INTEROP:
16093 183 : if (context != pragma_compound)
16094 : {
16095 0 : construct = "omp interop";
16096 0 : goto in_compound;
16097 : }
16098 183 : c_parser_omp_interop (parser);
16099 183 : return false;
16100 :
16101 101 : case PRAGMA_OMP_TASKWAIT:
16102 101 : if (context != pragma_compound)
16103 : {
16104 8 : construct = "omp taskwait";
16105 8 : goto in_compound;
16106 : }
16107 93 : c_parser_omp_taskwait (parser);
16108 93 : return false;
16109 :
16110 14 : case PRAGMA_OMP_TASKYIELD:
16111 14 : if (context != pragma_compound)
16112 : {
16113 8 : construct = "omp taskyield";
16114 8 : goto in_compound;
16115 : }
16116 6 : c_parser_omp_taskyield (parser);
16117 6 : return false;
16118 :
16119 221 : case PRAGMA_OMP_CANCEL:
16120 221 : if (context != pragma_compound)
16121 : {
16122 8 : construct = "omp cancel";
16123 8 : goto in_compound;
16124 : }
16125 213 : c_parser_omp_cancel (parser);
16126 213 : return false;
16127 :
16128 179 : case PRAGMA_OMP_CANCELLATION_POINT:
16129 179 : return c_parser_omp_cancellation_point (parser, context);
16130 :
16131 9 : case PRAGMA_OMP_GROUPPRIVATE:
16132 9 : c_parser_omp_groupprivate (parser);
16133 9 : return false;
16134 :
16135 78 : case PRAGMA_OMP_THREADPRIVATE:
16136 78 : c_parser_omp_threadprivate (parser);
16137 78 : return false;
16138 :
16139 7549 : case PRAGMA_OMP_TARGET:
16140 7549 : return c_parser_omp_target (parser, context, if_p);
16141 :
16142 128 : case PRAGMA_OMP_BEGIN:
16143 128 : c_parser_omp_begin (parser);
16144 128 : return false;
16145 :
16146 222 : case PRAGMA_OMP_END:
16147 222 : c_parser_omp_end (parser);
16148 222 : return false;
16149 :
16150 22 : case PRAGMA_OMP_SCAN:
16151 22 : error_at (c_parser_peek_token (parser)->location,
16152 : "%<#pragma omp scan%> may only be used in "
16153 : "a loop construct with %<inscan%> %<reduction%> clause");
16154 22 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16155 22 : return false;
16156 :
16157 5 : case PRAGMA_OMP_SECTION:
16158 5 : error_at (c_parser_peek_token (parser)->location,
16159 : "%<#pragma omp section%> may only be used in "
16160 : "%<#pragma omp sections%> construct");
16161 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16162 5 : return false;
16163 :
16164 1280 : case PRAGMA_OMP_DECLARE:
16165 1280 : return c_parser_omp_declare (parser, context);
16166 :
16167 67 : case PRAGMA_OMP_REQUIRES:
16168 67 : if (context != pragma_external)
16169 : {
16170 8 : error_at (c_parser_peek_token (parser)->location,
16171 : "%<#pragma %s%> may only be used at file scope",
16172 : "omp requires");
16173 8 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16174 8 : return false;
16175 : }
16176 59 : c_parser_omp_requires (parser);
16177 59 : return false;
16178 :
16179 71 : case PRAGMA_OMP_ALLOCATE:
16180 71 : c_parser_omp_allocate (parser);
16181 71 : return false;
16182 :
16183 39 : case PRAGMA_OMP_ASSUMES:
16184 39 : if (context != pragma_external)
16185 : {
16186 1 : error_at (c_parser_peek_token (parser)->location,
16187 : "%<#pragma %s%> may only be used at file scope",
16188 : "omp assumes");
16189 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16190 1 : return false;
16191 : }
16192 38 : c_parser_omp_assumes (parser);
16193 38 : return false;
16194 :
16195 79 : case PRAGMA_OMP_NOTHING:
16196 79 : c_parser_omp_nothing (parser);
16197 79 : return false;
16198 :
16199 110 : case PRAGMA_OMP_METADIRECTIVE:
16200 110 : c_parser_omp_metadirective (parser, if_p);
16201 110 : return true;
16202 :
16203 126 : case PRAGMA_OMP_ERROR:
16204 126 : return c_parser_omp_error (parser, context);
16205 :
16206 545 : case PRAGMA_OMP_ORDERED:
16207 545 : return c_parser_omp_ordered (parser, context, if_p);
16208 :
16209 3311 : case PRAGMA_NOVECTOR:
16210 3311 : case PRAGMA_UNROLL:
16211 3311 : case PRAGMA_IVDEP:
16212 3311 : {
16213 3311 : bool novector = false;
16214 3311 : unsigned short unroll = 0;
16215 3311 : bool ivdep = false;
16216 :
16217 3311 : switch (id)
16218 : {
16219 2907 : case PRAGMA_NOVECTOR:
16220 2907 : novector = c_parse_pragma_novector (parser);
16221 2907 : break;
16222 279 : case PRAGMA_UNROLL:
16223 279 : unroll = c_parser_pragma_unroll (parser);
16224 279 : break;
16225 125 : case PRAGMA_IVDEP:
16226 125 : ivdep = c_parse_pragma_ivdep (parser);
16227 125 : break;
16228 : default:
16229 : gcc_unreachable ();
16230 : }
16231 :
16232 3311 : c_token *tok = c_parser_peek_token (parser);
16233 3311 : bool has_more = tok->type == CPP_PRAGMA;
16234 3327 : while (has_more)
16235 : {
16236 16 : switch (tok->pragma_kind)
16237 : {
16238 3 : case PRAGMA_IVDEP:
16239 3 : ivdep = c_parse_pragma_ivdep (parser);
16240 3 : break;
16241 9 : case PRAGMA_UNROLL:
16242 9 : unroll = c_parser_pragma_unroll (parser);
16243 9 : break;
16244 4 : case PRAGMA_NOVECTOR:
16245 4 : novector = c_parse_pragma_novector (parser);
16246 4 : break;
16247 : default:
16248 : has_more = false;
16249 : break;
16250 : }
16251 16 : tok = c_parser_peek_token (parser);
16252 16 : has_more = has_more && tok->type == CPP_PRAGMA;
16253 : }
16254 3311 : if (!c_parser_next_token_is_keyword (parser, RID_FOR)
16255 74 : && !c_parser_next_token_is_keyword (parser, RID_WHILE)
16256 3370 : && !c_parser_next_token_is_keyword (parser, RID_DO))
16257 : {
16258 0 : c_parser_error (parser, "for, while or do statement expected");
16259 0 : return false;
16260 : }
16261 3311 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
16262 3237 : c_parser_for_statement (parser, ivdep, unroll, novector, if_p,
16263 : before_labels);
16264 74 : else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
16265 15 : c_parser_while_statement (parser, ivdep, unroll, novector, if_p,
16266 : before_labels);
16267 : else
16268 59 : c_parser_do_statement (parser, ivdep, unroll, novector,
16269 : before_labels);
16270 : }
16271 : return true;
16272 :
16273 1 : case PRAGMA_GCC_PCH_PREPROCESS:
16274 1 : c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
16275 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16276 1 : return false;
16277 :
16278 89 : case PRAGMA_OACC_WAIT:
16279 89 : if (context != pragma_compound)
16280 : {
16281 3 : construct = "acc wait";
16282 3 : goto in_compound;
16283 : }
16284 : /* FALL THROUGH. */
16285 :
16286 1911585 : default:
16287 1911585 : if (id < PRAGMA_FIRST_EXTERNAL)
16288 : {
16289 17273 : if (context != pragma_stmt && context != pragma_compound)
16290 : {
16291 2 : bad_stmt:
16292 5 : c_parser_error (parser, "expected declaration specifiers");
16293 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16294 5 : return false;
16295 : }
16296 17271 : c_parser_omp_construct (parser, if_p);
16297 17271 : return true;
16298 : }
16299 1894312 : break;
16300 : }
16301 :
16302 1894312 : c_parser_consume_pragma (parser);
16303 1894312 : c_invoke_pragma_handler (id);
16304 :
16305 : /* Skip to EOL, but suppress any error message. Those will have been
16306 : generated by the handler routine through calling error, as opposed
16307 : to calling c_parser_error. */
16308 1894312 : parser->error = true;
16309 1894312 : c_parser_skip_to_pragma_eol (parser);
16310 :
16311 1894312 : return false;
16312 : }
16313 :
16314 : /* The interface the pragma parsers have to the lexer. */
16315 :
16316 : enum cpp_ttype
16317 3578951 : pragma_lex (tree *value, location_t *loc)
16318 : {
16319 3578951 : c_token *tok = c_parser_peek_token (the_parser);
16320 3578951 : enum cpp_ttype ret = tok->type;
16321 :
16322 3578951 : *value = tok->value;
16323 3578951 : if (loc)
16324 1498581 : *loc = tok->location;
16325 :
16326 3578951 : if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
16327 : ret = CPP_EOF;
16328 2021917 : else if (ret == CPP_STRING)
16329 634208 : *value = c_parser_string_literal (the_parser, false, false).value;
16330 : else
16331 : {
16332 1387709 : if (ret == CPP_KEYWORD)
16333 344 : ret = CPP_NAME;
16334 1387709 : c_parser_consume_token (the_parser);
16335 : }
16336 :
16337 3578951 : return ret;
16338 : }
16339 :
16340 : void
16341 9232 : pragma_lex_discard_to_eol ()
16342 : {
16343 9232 : cpp_ttype type;
16344 9232 : do
16345 : {
16346 9232 : type = c_parser_peek_token (the_parser)->type;
16347 9232 : gcc_assert (type != CPP_EOF);
16348 9232 : c_parser_consume_token (the_parser);
16349 9232 : } while (type != CPP_PRAGMA_EOL);
16350 9232 : }
16351 :
16352 : static void
16353 12 : c_parser_pragma_pch_preprocess (c_parser *parser)
16354 : {
16355 12 : tree name = NULL;
16356 :
16357 12 : parser->lex_joined_string = true;
16358 12 : c_parser_consume_pragma (parser);
16359 12 : if (c_parser_next_token_is (parser, CPP_STRING))
16360 : {
16361 12 : name = c_parser_peek_token (parser)->value;
16362 12 : c_parser_consume_token (parser);
16363 : }
16364 : else
16365 0 : c_parser_error (parser, "expected string literal");
16366 12 : c_parser_skip_to_pragma_eol (parser);
16367 12 : parser->lex_joined_string = false;
16368 :
16369 12 : if (name)
16370 12 : c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
16371 12 : }
16372 :
16373 : /* OpenACC and OpenMP parsing routines. */
16374 :
16375 : /* Returns name of the next clause.
16376 : If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
16377 : the token is not consumed. Otherwise appropriate pragma_omp_clause is
16378 : returned and the token is consumed. */
16379 :
16380 : static pragma_omp_clause
16381 34334 : c_parser_omp_clause_name (c_parser *parser)
16382 : {
16383 34334 : pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
16384 :
16385 34334 : if (c_parser_next_token_is_keyword (parser, RID_AUTO))
16386 : result = PRAGMA_OACC_CLAUSE_AUTO;
16387 34209 : else if (c_parser_next_token_is_keyword (parser, RID_IF))
16388 : result = PRAGMA_OMP_CLAUSE_IF;
16389 33325 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
16390 : result = PRAGMA_OMP_CLAUSE_DEFAULT;
16391 32596 : else if (c_parser_next_token_is_keyword (parser, RID_FOR))
16392 : result = PRAGMA_OMP_CLAUSE_FOR;
16393 32512 : else if (c_parser_next_token_is (parser, CPP_NAME))
16394 : {
16395 32426 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16396 :
16397 32426 : switch (p[0])
16398 : {
16399 1123 : case 'a':
16400 1123 : if (!strcmp ("affinity", p))
16401 : result = PRAGMA_OMP_CLAUSE_AFFINITY;
16402 977 : else if (!strcmp ("aligned", p))
16403 : result = PRAGMA_OMP_CLAUSE_ALIGNED;
16404 749 : else if (!strcmp ("allocate", p))
16405 : result = PRAGMA_OMP_CLAUSE_ALLOCATE;
16406 270 : else if (!strcmp ("async", p))
16407 : result = PRAGMA_OACC_CLAUSE_ASYNC;
16408 30 : else if (!strcmp ("attach", p))
16409 34334 : result = PRAGMA_OACC_CLAUSE_ATTACH;
16410 : break;
16411 118 : case 'b':
16412 118 : if (!strcmp ("bind", p))
16413 34334 : result = PRAGMA_OMP_CLAUSE_BIND;
16414 : break;
16415 4592 : case 'c':
16416 4592 : if (!strcmp ("collapse", p))
16417 : result = PRAGMA_OMP_CLAUSE_COLLAPSE;
16418 1638 : else if (!strcmp ("copy", p))
16419 : result = PRAGMA_OACC_CLAUSE_COPY;
16420 854 : else if (!strcmp ("copyin", p))
16421 : result = PRAGMA_OMP_CLAUSE_COPYIN;
16422 419 : else if (!strcmp ("copyout", p))
16423 : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16424 96 : else if (!strcmp ("copyprivate", p))
16425 : result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
16426 75 : else if (!strcmp ("create", p))
16427 34334 : result = PRAGMA_OACC_CLAUSE_CREATE;
16428 : break;
16429 3536 : case 'd':
16430 3536 : if (!strcmp ("defaultmap", p))
16431 : result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
16432 3298 : else if (!strcmp ("delete", p))
16433 : result = PRAGMA_OACC_CLAUSE_DELETE;
16434 3230 : else if (!strcmp ("depend", p))
16435 : result = PRAGMA_OMP_CLAUSE_DEPEND;
16436 2373 : else if (!strcmp ("destroy", p))
16437 : result = PRAGMA_OMP_CLAUSE_DESTROY;
16438 2332 : else if (!strcmp ("detach", p))
16439 : result = PRAGMA_OACC_CLAUSE_DETACH;
16440 2278 : else if (!strcmp ("device", p))
16441 : result = PRAGMA_OMP_CLAUSE_DEVICE;
16442 1873 : else if (!strcmp ("deviceptr", p))
16443 : result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
16444 1816 : else if (!strcmp ("device_resident", p))
16445 : result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
16446 1800 : else if (!strcmp ("device_type", p))
16447 : result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
16448 1749 : else if (!strcmp ("dist_schedule", p))
16449 : result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
16450 167 : else if (!strcmp ("doacross", p))
16451 : result = PRAGMA_OMP_CLAUSE_DOACROSS;
16452 22 : else if (!strcmp ("dyn_groupprivate", p))
16453 34334 : result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
16454 : break;
16455 46 : case 'e':
16456 46 : if (!strcmp ("enter", p))
16457 34334 : result = PRAGMA_OMP_CLAUSE_ENTER;
16458 : break;
16459 3488 : case 'f':
16460 3488 : if (!strcmp ("filter", p))
16461 : result = PRAGMA_OMP_CLAUSE_FILTER;
16462 3425 : else if (!strcmp ("final", p))
16463 : result = PRAGMA_OMP_CLAUSE_FINAL;
16464 3326 : else if (!strcmp ("finalize", p))
16465 : result = PRAGMA_OACC_CLAUSE_FINALIZE;
16466 3314 : else if (!strcmp ("firstprivate", p))
16467 : result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
16468 2523 : else if (!strcmp ("from", p))
16469 : result = PRAGMA_OMP_CLAUSE_FROM;
16470 73 : else if (!strcmp ("full", p))
16471 34334 : result = PRAGMA_OMP_CLAUSE_FULL;
16472 : break;
16473 651 : case 'g':
16474 651 : if (!strcmp ("gang", p))
16475 : result = PRAGMA_OACC_CLAUSE_GANG;
16476 62 : else if (!strcmp ("grainsize", p))
16477 34334 : result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
16478 : break;
16479 158 : case 'h':
16480 158 : if (!strcmp ("has_device_addr", p))
16481 : result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
16482 70 : else if (!strcmp ("hint", p))
16483 : result = PRAGMA_OMP_CLAUSE_HINT;
16484 41 : else if (!strcmp ("host", p))
16485 34334 : result = PRAGMA_OACC_CLAUSE_HOST;
16486 : break;
16487 805 : case 'i':
16488 805 : if (!strcmp ("if_present", p))
16489 : result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
16490 786 : else if (!strcmp ("in_reduction", p))
16491 : result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
16492 465 : else if (!strcmp ("inbranch", p))
16493 : result = PRAGMA_OMP_CLAUSE_INBRANCH;
16494 396 : else if (!strcmp ("independent", p))
16495 : result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
16496 351 : else if (!strcmp ("indirect", p))
16497 : result = PRAGMA_OMP_CLAUSE_INDIRECT;
16498 325 : else if (!strcmp ("init", p))
16499 : result = PRAGMA_OMP_CLAUSE_INIT;
16500 158 : else if (!strcmp ("is_device_ptr", p))
16501 : result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
16502 43 : else if (!strcmp ("interop", p))
16503 34334 : result = PRAGMA_OMP_CLAUSE_INTEROP;
16504 : break;
16505 1251 : case 'l':
16506 1251 : if (!strcmp ("lastprivate", p))
16507 : result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
16508 519 : else if (!strcmp ("linear", p))
16509 : result = PRAGMA_OMP_CLAUSE_LINEAR;
16510 43 : else if (!strcmp ("link", p))
16511 34334 : result = PRAGMA_OMP_CLAUSE_LINK;
16512 : break;
16513 1896 : case 'm':
16514 1896 : if (!strcmp ("map", p))
16515 : result = PRAGMA_OMP_CLAUSE_MAP;
16516 79 : else if (!strcmp ("mergeable", p))
16517 34334 : result = PRAGMA_OMP_CLAUSE_MERGEABLE;
16518 : break;
16519 1923 : case 'n':
16520 1923 : if (!strcmp ("no_create", p))
16521 : result = PRAGMA_OACC_CLAUSE_NO_CREATE;
16522 1913 : else if (!strcmp ("nocontext", p))
16523 : result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
16524 1890 : else if (!strcmp ("nogroup", p))
16525 : result = PRAGMA_OMP_CLAUSE_NOGROUP;
16526 1872 : else if (!strcmp ("nohost", p))
16527 : result = PRAGMA_OACC_CLAUSE_NOHOST;
16528 1847 : else if (!strcmp ("nontemporal", p))
16529 : result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
16530 1726 : else if (!strcmp ("notinbranch", p))
16531 : result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
16532 1590 : else if (!strcmp ("novariants", p))
16533 : result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
16534 1566 : else if (!strcmp ("nowait", p))
16535 : result = PRAGMA_OMP_CLAUSE_NOWAIT;
16536 1175 : else if (!strcmp ("num_gangs", p))
16537 : result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
16538 873 : else if (!strcmp ("num_tasks", p))
16539 : result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
16540 823 : else if (!strcmp ("num_teams", p))
16541 : result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
16542 633 : else if (!strcmp ("num_threads", p))
16543 : result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
16544 207 : else if (!strcmp ("num_workers", p))
16545 34334 : result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
16546 : break;
16547 692 : case 'o':
16548 692 : if (!strcmp ("ordered", p))
16549 : result = PRAGMA_OMP_CLAUSE_ORDERED;
16550 382 : else if (!strcmp ("order", p))
16551 34334 : result = PRAGMA_OMP_CLAUSE_ORDER;
16552 : break;
16553 1646 : case 'p':
16554 1646 : if (!strcmp ("parallel", p))
16555 : result = PRAGMA_OMP_CLAUSE_PARALLEL;
16556 1539 : else if (!strcmp ("partial", p))
16557 : result = PRAGMA_OMP_CLAUSE_PARTIAL;
16558 1309 : else if (!strcmp ("present", p))
16559 : result = PRAGMA_OACC_CLAUSE_PRESENT;
16560 : /* As of OpenACC 2.5, these are now aliases of the non-present_or
16561 : clauses. */
16562 1181 : else if (!strcmp ("present_or_copy", p)
16563 1168 : || !strcmp ("pcopy", p))
16564 : result = PRAGMA_OACC_CLAUSE_COPY;
16565 1159 : else if (!strcmp ("present_or_copyin", p)
16566 1143 : || !strcmp ("pcopyin", p))
16567 : result = PRAGMA_OACC_CLAUSE_COPYIN;
16568 1134 : else if (!strcmp ("present_or_copyout", p)
16569 1081 : || !strcmp ("pcopyout", p))
16570 : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16571 1067 : else if (!strcmp ("present_or_create", p)
16572 1053 : || !strcmp ("pcreate", p))
16573 : result = PRAGMA_OACC_CLAUSE_CREATE;
16574 1048 : else if (!strcmp ("priority", p))
16575 : result = PRAGMA_OMP_CLAUSE_PRIORITY;
16576 950 : else if (!strcmp ("private", p))
16577 : result = PRAGMA_OMP_CLAUSE_PRIVATE;
16578 205 : else if (!strcmp ("proc_bind", p))
16579 34334 : result = PRAGMA_OMP_CLAUSE_PROC_BIND;
16580 : break;
16581 2686 : case 'r':
16582 2686 : if (!strcmp ("reduction", p))
16583 34334 : result = PRAGMA_OMP_CLAUSE_REDUCTION;
16584 : break;
16585 5173 : case 's':
16586 5173 : if (!strcmp ("safelen", p))
16587 : result = PRAGMA_OMP_CLAUSE_SAFELEN;
16588 4946 : else if (!strcmp ("schedule", p))
16589 : result = PRAGMA_OMP_CLAUSE_SCHEDULE;
16590 1477 : else if (!strcmp ("sections", p))
16591 : result = PRAGMA_OMP_CLAUSE_SECTIONS;
16592 1399 : else if (!strcmp ("self", p))
16593 : result = PRAGMA_OACC_CLAUSE_SELF;
16594 1333 : else if (!strcmp ("seq", p))
16595 : result = PRAGMA_OACC_CLAUSE_SEQ;
16596 1072 : else if (!strcmp ("shared", p))
16597 : result = PRAGMA_OMP_CLAUSE_SHARED;
16598 381 : else if (!strcmp ("simd", p))
16599 : result = PRAGMA_OMP_CLAUSE_SIMD;
16600 324 : else if (!strcmp ("simdlen", p))
16601 34334 : result = PRAGMA_OMP_CLAUSE_SIMDLEN;
16602 : break;
16603 999 : case 't':
16604 999 : if (!strcmp ("task_reduction", p))
16605 : result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
16606 913 : else if (!strcmp ("taskgroup", p))
16607 : result = PRAGMA_OMP_CLAUSE_TASKGROUP;
16608 803 : else if (!strcmp ("thread_limit", p))
16609 : result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
16610 649 : else if (!strcmp ("threads", p))
16611 : result = PRAGMA_OMP_CLAUSE_THREADS;
16612 603 : else if (!strcmp ("tile", p))
16613 : result = PRAGMA_OACC_CLAUSE_TILE;
16614 480 : else if (!strcmp ("to", p))
16615 34334 : result = PRAGMA_OMP_CLAUSE_TO;
16616 : break;
16617 351 : case 'u':
16618 351 : if (!strcmp ("uniform", p))
16619 : result = PRAGMA_OMP_CLAUSE_UNIFORM;
16620 236 : else if (!strcmp ("untied", p))
16621 : result = PRAGMA_OMP_CLAUSE_UNTIED;
16622 139 : else if (!strcmp ("use", p))
16623 : result = PRAGMA_OMP_CLAUSE_USE;
16624 96 : else if (!strcmp ("use_device", p))
16625 : result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
16626 75 : else if (!strcmp ("use_device_addr", p))
16627 : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
16628 40 : else if (!strcmp ("use_device_ptr", p))
16629 : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
16630 30 : else if (!strcmp ("uses_allocators", p))
16631 34334 : result = PRAGMA_OMP_CLAUSE_USES_ALLOCATORS;
16632 : break;
16633 741 : case 'v':
16634 741 : if (!strcmp ("vector", p))
16635 : result = PRAGMA_OACC_CLAUSE_VECTOR;
16636 223 : else if (!strcmp ("vector_length", p))
16637 34334 : result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
16638 : break;
16639 550 : case 'w':
16640 550 : if (!strcmp ("wait", p))
16641 : result = PRAGMA_OACC_CLAUSE_WAIT;
16642 453 : else if (!strcmp ("worker", p))
16643 34334 : result = PRAGMA_OACC_CLAUSE_WORKER;
16644 : break;
16645 : }
16646 : }
16647 :
16648 34334 : if (result != PRAGMA_OMP_CLAUSE_NONE)
16649 34218 : c_parser_consume_token (parser);
16650 :
16651 34334 : return result;
16652 : }
16653 :
16654 : /* Validate that a clause of the given type does not already exist. */
16655 :
16656 : static void
16657 17592 : check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
16658 : const char *name)
16659 : {
16660 17592 : if (tree c = omp_find_clause (clauses, code))
16661 348 : error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
16662 17592 : }
16663 :
16664 : /* OpenACC 2.0
16665 : Parse wait clause or wait directive parameters. */
16666 :
16667 : static tree
16668 131 : c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
16669 : {
16670 131 : vec<tree, va_gc> *args;
16671 131 : tree t, args_tree;
16672 :
16673 131 : matching_parens parens;
16674 131 : if (!parens.require_open (parser))
16675 : return list;
16676 :
16677 131 : args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL);
16678 131 : args_tree = build_tree_list_vec (args);
16679 :
16680 305 : for (t = args_tree; t; t = TREE_CHAIN (t))
16681 : {
16682 174 : tree targ = TREE_VALUE (t);
16683 :
16684 174 : if (targ != error_mark_node)
16685 : {
16686 160 : if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
16687 : {
16688 6 : c_parser_error (parser, "expression must be integral");
16689 6 : targ = error_mark_node;
16690 : }
16691 : else
16692 : {
16693 154 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16694 :
16695 154 : OMP_CLAUSE_DECL (c) = targ;
16696 154 : OMP_CLAUSE_CHAIN (c) = list;
16697 154 : list = c;
16698 : }
16699 : }
16700 : }
16701 :
16702 131 : release_tree_vector (args);
16703 131 : parens.require_close (parser);
16704 131 : return list;
16705 : }
16706 :
16707 : /* OpenACC 2.0, OpenMP 2.5:
16708 : variable-list:
16709 : identifier
16710 : variable-list , identifier
16711 :
16712 : If KIND is nonzero, create the appropriate node and install the
16713 : decl in OMP_CLAUSE_DECL and add the node to the head of the list.
16714 : If KIND is nonzero, CLAUSE_LOC is the location of the clause.
16715 :
16716 : If KIND is zero (= OMP_CLAUSE_ERROR), create a TREE_LIST with the decl
16717 : in TREE_PURPOSE and the location in TREE_VALUE (accessible using
16718 : EXPR_LOCATION); return the list created.
16719 :
16720 : The optional ALLOW_DEREF argument is true if list items can use the deref
16721 : (->) operator. */
16722 :
16723 : struct omp_dim
16724 : {
16725 : tree low_bound, length;
16726 : location_t loc;
16727 : bool no_colon;
16728 3314 : omp_dim (tree lb, tree len, location_t lo, bool nc)
16729 3314 : : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
16730 : };
16731 :
16732 : static tree
16733 16404 : c_parser_omp_variable_list (c_parser *parser,
16734 : location_t clause_loc,
16735 : enum omp_clause_code kind, tree list,
16736 : bool map_lvalue = false)
16737 : {
16738 16404 : auto_vec<omp_dim> dims;
16739 16404 : bool array_section_p;
16740 16404 : auto_vec<c_token> tokens;
16741 16404 : unsigned int tokens_avail = 0;
16742 16404 : c_token *saved_tokens = NULL;
16743 :
16744 19597 : while (1)
16745 : {
16746 19597 : tree t = NULL_TREE;
16747 19597 : location_t tloc = c_parser_peek_token (parser)->location;
16748 :
16749 19597 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16750 : {
16751 888 : if (c_parser_next_token_is_not (parser, CPP_NAME)
16752 888 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
16753 : {
16754 29 : struct c_expr expr;
16755 29 : if (kind == OMP_CLAUSE_DEPEND
16756 27 : && c_parser_next_token_is_keyword (parser,
16757 : RID_OMP_ALL_MEMORY)
16758 45 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16759 13 : || (c_parser_peek_2nd_token (parser)->type
16760 : == CPP_CLOSE_PAREN)))
16761 : {
16762 15 : expr.value = ridpointers[RID_OMP_ALL_MEMORY];
16763 15 : c_parser_consume_token (parser);
16764 : }
16765 : else
16766 14 : expr = c_parser_expr_no_commas (parser, NULL);
16767 29 : if (expr.value != error_mark_node)
16768 : {
16769 27 : tree u = build_omp_clause (clause_loc, kind);
16770 27 : OMP_CLAUSE_DECL (u) = expr.value;
16771 27 : OMP_CLAUSE_CHAIN (u) = list;
16772 27 : list = u;
16773 : }
16774 :
16775 29 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
16776 : break;
16777 :
16778 4 : c_parser_consume_token (parser);
16779 4 : continue;
16780 4 : }
16781 :
16782 859 : tokens.truncate (0);
16783 859 : unsigned int nesting_depth = 0;
16784 11227 : while (1)
16785 : {
16786 6043 : c_token *token = c_parser_peek_token (parser);
16787 6043 : switch (token->type)
16788 : {
16789 : case CPP_EOF:
16790 : case CPP_PRAGMA_EOL:
16791 : break;
16792 930 : case CPP_OPEN_BRACE:
16793 930 : case CPP_OPEN_PAREN:
16794 930 : case CPP_OPEN_SQUARE:
16795 930 : ++nesting_depth;
16796 930 : goto add;
16797 1723 : case CPP_CLOSE_BRACE:
16798 1723 : case CPP_CLOSE_PAREN:
16799 1723 : case CPP_CLOSE_SQUARE:
16800 1723 : if (nesting_depth-- == 0)
16801 : break;
16802 930 : goto add;
16803 138 : case CPP_COMMA:
16804 138 : if (nesting_depth == 0)
16805 : break;
16806 72 : goto add;
16807 5184 : default:
16808 5184 : add:
16809 5184 : tokens.safe_push (*token);
16810 5184 : c_parser_consume_token (parser);
16811 5184 : continue;
16812 : }
16813 859 : break;
16814 5184 : }
16815 :
16816 : /* Make sure nothing tries to read past the end of the tokens. */
16817 859 : c_token eof_token;
16818 859 : memset (&eof_token, 0, sizeof (eof_token));
16819 859 : eof_token.type = CPP_EOF;
16820 859 : tokens.safe_push (eof_token);
16821 859 : tokens.safe_push (eof_token);
16822 :
16823 859 : saved_tokens = parser->tokens;
16824 859 : tokens_avail = parser->tokens_avail;
16825 859 : parser->tokens = tokens.address ();
16826 1718 : parser->tokens_avail = tokens.length ();
16827 : }
16828 18709 : else if (map_lvalue
16829 2209 : && (kind == OMP_CLAUSE_MAP
16830 : || kind == OMP_CLAUSE_TO
16831 2209 : || kind == OMP_CLAUSE_FROM))
16832 : {
16833 2209 : location_t loc = c_parser_peek_token (parser)->location;
16834 2209 : bool save_c_omp_array_section_p = c_omp_array_section_p;
16835 2209 : c_omp_array_section_p = true;
16836 2209 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
16837 2209 : if (expr.value != error_mark_node)
16838 2195 : mark_exp_read (expr.value);
16839 2209 : c_omp_array_section_p = save_c_omp_array_section_p;
16840 2209 : tree decl = expr.value;
16841 :
16842 : /* This code rewrites a parsed expression containing various tree
16843 : codes used to represent array accesses into a more uniform nest of
16844 : OMP_ARRAY_SECTION nodes before it is processed by
16845 : c-typeck.cc:handle_omp_array_sections_1. It might be more
16846 : efficient to move this logic to that function instead, analysing
16847 : the parsed expression directly rather than this preprocessed
16848 : form. (See also equivalent code in cp/parser.cc,
16849 : cp/semantics.cc). */
16850 2209 : dims.truncate (0);
16851 2209 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16852 : {
16853 1066 : while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16854 : {
16855 563 : tree low_bound = TREE_OPERAND (decl, 1);
16856 563 : tree length = TREE_OPERAND (decl, 2);
16857 563 : dims.safe_push (omp_dim (low_bound, length, loc, false));
16858 563 : decl = TREE_OPERAND (decl, 0);
16859 : }
16860 :
16861 536 : while (TREE_CODE (decl) == ARRAY_REF
16862 : || TREE_CODE (decl) == INDIRECT_REF
16863 536 : || TREE_CODE (decl) == COMPOUND_EXPR)
16864 : {
16865 33 : if (TREE_CODE (decl) == COMPOUND_EXPR)
16866 : {
16867 2 : decl = TREE_OPERAND (decl, 1);
16868 2 : STRIP_NOPS (decl);
16869 : }
16870 31 : else if (TREE_CODE (decl) == INDIRECT_REF)
16871 : {
16872 46 : dims.safe_push (omp_dim (integer_zero_node,
16873 23 : integer_one_node, loc, true));
16874 23 : decl = TREE_OPERAND (decl, 0);
16875 : }
16876 : else /* ARRAY_REF. */
16877 : {
16878 8 : tree index = TREE_OPERAND (decl, 1);
16879 16 : dims.safe_push (omp_dim (index, integer_one_node, loc,
16880 8 : true));
16881 8 : decl = TREE_OPERAND (decl, 0);
16882 : }
16883 : }
16884 :
16885 1600 : for (int i = dims.length () - 1; i >= 0; i--)
16886 594 : decl = build_omp_array_section (loc, decl, dims[i].low_bound,
16887 594 : dims[i].length);
16888 : }
16889 1706 : else if (TREE_CODE (decl) == INDIRECT_REF)
16890 : {
16891 : /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
16892 50 : decl = TREE_OPERAND (decl, 0);
16893 50 : STRIP_NOPS (decl);
16894 :
16895 50 : decl = build_omp_array_section (loc, decl, integer_zero_node,
16896 : integer_one_node);
16897 : }
16898 1656 : else if (TREE_CODE (decl) == ARRAY_REF)
16899 : {
16900 12 : tree idx = TREE_OPERAND (decl, 1);
16901 :
16902 12 : decl = TREE_OPERAND (decl, 0);
16903 12 : STRIP_NOPS (decl);
16904 :
16905 12 : decl = build_omp_array_section (loc, decl, idx, integer_one_node);
16906 : }
16907 1644 : else if (TREE_CODE (decl) == NON_LVALUE_EXPR
16908 1644 : || CONVERT_EXPR_P (decl))
16909 0 : decl = TREE_OPERAND (decl, 0);
16910 :
16911 2209 : tree u = build_omp_clause (loc, kind);
16912 2209 : OMP_CLAUSE_DECL (u) = decl;
16913 2209 : OMP_CLAUSE_CHAIN (u) = list;
16914 2209 : list = u;
16915 :
16916 2209 : goto next_item;
16917 : }
16918 :
16919 17359 : if (c_parser_next_token_is (parser, CPP_NAME)
16920 17359 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
16921 : {
16922 17322 : t = lookup_name (c_parser_peek_token (parser)->value);
16923 :
16924 17322 : if (t == NULL_TREE)
16925 : {
16926 14 : undeclared_variable (c_parser_peek_token (parser)->location,
16927 14 : c_parser_peek_token (parser)->value);
16928 14 : t = error_mark_node;
16929 : }
16930 :
16931 17322 : c_parser_consume_token (parser);
16932 : }
16933 37 : else if (c_parser_next_token_is (parser, CPP_KEYWORD)
16934 37 : && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
16935 15 : || (c_parser_peek_token (parser)->keyword
16936 : == RID_PRETTY_FUNCTION_NAME)
16937 9 : || (c_parser_peek_token (parser)->keyword
16938 : == RID_C99_FUNCTION_NAME)))
16939 20 : t = c_parser_predefined_identifier (parser).value;
16940 : else
16941 : {
16942 17 : c_parser_error (parser, "expected identifier");
16943 17 : break;
16944 : }
16945 :
16946 17342 : if (t == error_mark_node)
16947 : ;
16948 17324 : else if (kind != 0) /* kind != OMP_CLAUSE_ERROR */
16949 : {
16950 17092 : switch (kind)
16951 : {
16952 139 : case OMP_CLAUSE__CACHE_:
16953 : /* The OpenACC cache directive explicitly only allows "array
16954 : elements or subarrays". */
16955 139 : if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
16956 : {
16957 3 : c_parser_error (parser, "expected %<[%>");
16958 3 : t = error_mark_node;
16959 3 : break;
16960 : }
16961 : /* FALLTHROUGH */
16962 : case OMP_CLAUSE_MAP:
16963 : case OMP_CLAUSE_FROM:
16964 : case OMP_CLAUSE_TO:
16965 136 : start_component_ref:
16966 5963 : while (c_parser_next_token_is (parser, CPP_DOT)
16967 11719 : || c_parser_next_token_is (parser, CPP_DEREF))
16968 : {
16969 316 : location_t op_loc = c_parser_peek_token (parser)->location;
16970 316 : location_t arrow_loc = UNKNOWN_LOCATION;
16971 316 : if (c_parser_next_token_is (parser, CPP_DEREF))
16972 : {
16973 109 : c_expr t_expr;
16974 109 : t_expr.value = t;
16975 109 : t_expr.original_code = ERROR_MARK;
16976 109 : t_expr.original_type = NULL;
16977 109 : set_c_expr_source_range (&t_expr, op_loc, op_loc);
16978 109 : t_expr.m_decimal = 0;
16979 109 : t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
16980 : true, false);
16981 109 : t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
16982 109 : arrow_loc = t_expr.get_location ();
16983 : }
16984 316 : c_parser_consume_token (parser);
16985 316 : if (!c_parser_next_token_is (parser, CPP_NAME))
16986 : {
16987 0 : c_parser_error (parser, "expected identifier");
16988 0 : t = error_mark_node;
16989 0 : break;
16990 : }
16991 :
16992 316 : c_token *comp_tok = c_parser_peek_token (parser);
16993 316 : tree ident = comp_tok->value;
16994 316 : location_t comp_loc = comp_tok->location;
16995 316 : c_parser_consume_token (parser);
16996 316 : t = build_component_ref (op_loc, t, ident, comp_loc,
16997 : arrow_loc);
16998 : }
16999 : /* FALLTHROUGH */
17000 10297 : case OMP_CLAUSE_AFFINITY:
17001 10297 : case OMP_CLAUSE_DEPEND:
17002 10297 : case OMP_CLAUSE_REDUCTION:
17003 10297 : case OMP_CLAUSE_IN_REDUCTION:
17004 10297 : case OMP_CLAUSE_TASK_REDUCTION:
17005 10297 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
17006 10297 : array_section_p = false;
17007 10297 : dims.truncate (0);
17008 23314 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
17009 : {
17010 2720 : location_t loc = UNKNOWN_LOCATION;
17011 2720 : tree low_bound = NULL_TREE, length = NULL_TREE;
17012 2720 : bool no_colon = false;
17013 :
17014 2720 : c_parser_consume_token (parser);
17015 2720 : if (!c_parser_next_token_is (parser, CPP_COLON))
17016 : {
17017 2300 : location_t expr_loc
17018 2300 : = c_parser_peek_token (parser)->location;
17019 2300 : c_expr expr = c_parser_expression (parser);
17020 2300 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
17021 : false, true);
17022 2300 : low_bound = expr.value;
17023 2300 : loc = expr_loc;
17024 : }
17025 2720 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
17026 : {
17027 432 : length = integer_one_node;
17028 432 : no_colon = true;
17029 : }
17030 : else
17031 : {
17032 : /* Look for `:'. */
17033 2288 : if (!c_parser_require (parser, CPP_COLON,
17034 : "expected %<:%>"))
17035 : {
17036 0 : t = error_mark_node;
17037 0 : break;
17038 : }
17039 2288 : array_section_p = true;
17040 2288 : if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
17041 : {
17042 2103 : location_t expr_loc
17043 2103 : = c_parser_peek_token (parser)->location;
17044 2103 : c_expr expr = c_parser_expression (parser);
17045 2103 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
17046 : false, true);
17047 2103 : length = expr.value;
17048 : }
17049 : }
17050 : /* Look for the closing `]'. */
17051 2720 : if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
17052 : "expected %<]%>"))
17053 : {
17054 0 : t = error_mark_node;
17055 0 : break;
17056 : }
17057 :
17058 2720 : dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
17059 : }
17060 :
17061 10297 : if (t != error_mark_node)
17062 : {
17063 10297 : if ((kind == OMP_CLAUSE_MAP
17064 10297 : || kind == OMP_CLAUSE_FROM
17065 5193 : || kind == OMP_CLAUSE_TO)
17066 5511 : && !array_section_p
17067 14553 : && (c_parser_next_token_is (parser, CPP_DOT)
17068 4252 : || c_parser_next_token_is (parser, CPP_DEREF)))
17069 : {
17070 8 : for (unsigned i = 0; i < dims.length (); i++)
17071 : {
17072 4 : gcc_assert (dims[i].length == integer_one_node);
17073 4 : t = build_array_ref (dims[i].loc,
17074 4 : t, dims[i].low_bound);
17075 : }
17076 4 : goto start_component_ref;
17077 : }
17078 : else
17079 13009 : for (unsigned i = 0; i < dims.length (); i++)
17080 5432 : t = build_omp_array_section (clause_loc, t,
17081 2716 : dims[i].low_bound,
17082 2716 : dims[i].length);
17083 : }
17084 :
17085 10293 : if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
17086 855 : && t != error_mark_node
17087 855 : && parser->tokens_avail != 2)
17088 : {
17089 44 : if (array_section_p)
17090 : {
17091 12 : error_at (c_parser_peek_token (parser)->location,
17092 : "expected %<)%> or %<,%>");
17093 12 : t = error_mark_node;
17094 : }
17095 : else
17096 : {
17097 32 : parser->tokens = tokens.address ();
17098 32 : parser->tokens_avail = tokens.length ();
17099 :
17100 32 : t = c_parser_expr_no_commas (parser, NULL).value;
17101 32 : if (t != error_mark_node && parser->tokens_avail != 2)
17102 : {
17103 0 : error_at (c_parser_peek_token (parser)->location,
17104 : "expected %<)%> or %<,%>");
17105 0 : t = error_mark_node;
17106 : }
17107 : }
17108 : }
17109 : break;
17110 : default:
17111 : break;
17112 : }
17113 :
17114 17092 : if (t != error_mark_node)
17115 : {
17116 17077 : tree u = build_omp_clause (clause_loc, kind);
17117 17077 : OMP_CLAUSE_DECL (u) = t;
17118 17077 : OMP_CLAUSE_CHAIN (u) = list;
17119 17077 : list = u;
17120 : }
17121 : }
17122 : else /* kind == OMP_CLAUSE_ERROR */
17123 232 : list = tree_cons (t, build_empty_stmt (tloc), list);
17124 :
17125 17342 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
17126 : {
17127 859 : parser->tokens = saved_tokens;
17128 859 : parser->tokens_avail = tokens_avail;
17129 : }
17130 :
17131 16483 : next_item:
17132 19551 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
17133 : break;
17134 :
17135 3189 : c_parser_consume_token (parser);
17136 : }
17137 :
17138 16404 : return list;
17139 16404 : }
17140 :
17141 : /* Similarly, but expect leading and trailing parenthesis. This is a very
17142 : common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
17143 : argument is true if list items can use the deref (->) operator. */
17144 :
17145 : static tree
17146 3535 : c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
17147 : tree list, bool map_lvalue = false)
17148 : {
17149 : /* The clauses location. */
17150 3535 : location_t loc = c_parser_peek_token (parser)->location;
17151 :
17152 3535 : if (parser->in_omp_decl_attribute)
17153 : {
17154 42 : if (kind)
17155 : {
17156 22 : tree u = build_omp_clause (loc, kind);
17157 22 : OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
17158 22 : OMP_CLAUSE_CHAIN (u) = list;
17159 22 : return u;
17160 : }
17161 : else
17162 20 : return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
17163 : }
17164 :
17165 3493 : matching_parens parens;
17166 3493 : if (parens.require_open (parser))
17167 : {
17168 3489 : list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue);
17169 3489 : parens.skip_until_found_close (parser);
17170 : }
17171 : return list;
17172 : }
17173 :
17174 : /* OpenACC 2.0:
17175 : copy ( variable-list )
17176 : copyin ( variable-list )
17177 : copyout ( variable-list )
17178 : create ( variable-list )
17179 : delete ( variable-list )
17180 : present ( variable-list )
17181 :
17182 : OpenACC 2.6:
17183 : no_create ( variable-list )
17184 : attach ( variable-list )
17185 : detach ( variable-list )
17186 :
17187 : OpenACC 2.7:
17188 : copyin (readonly : variable-list )
17189 : */
17190 :
17191 : static tree
17192 2026 : c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
17193 : tree list)
17194 : {
17195 2026 : enum gomp_map_kind kind;
17196 2026 : switch (c_kind)
17197 : {
17198 : case PRAGMA_OACC_CLAUSE_ATTACH:
17199 : kind = GOMP_MAP_ATTACH;
17200 : break;
17201 806 : case PRAGMA_OACC_CLAUSE_COPY:
17202 806 : kind = GOMP_MAP_TOFROM;
17203 806 : break;
17204 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
17205 359 : kind = GOMP_MAP_TO;
17206 359 : break;
17207 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
17208 390 : kind = GOMP_MAP_FROM;
17209 390 : break;
17210 94 : case PRAGMA_OACC_CLAUSE_CREATE:
17211 94 : kind = GOMP_MAP_ALLOC;
17212 94 : break;
17213 68 : case PRAGMA_OACC_CLAUSE_DELETE:
17214 68 : kind = GOMP_MAP_RELEASE;
17215 68 : break;
17216 20 : case PRAGMA_OACC_CLAUSE_DETACH:
17217 20 : kind = GOMP_MAP_DETACH;
17218 20 : break;
17219 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
17220 36 : kind = GOMP_MAP_FORCE_TO;
17221 36 : break;
17222 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
17223 16 : kind = GOMP_MAP_DEVICE_RESIDENT;
17224 16 : break;
17225 13 : case PRAGMA_OACC_CLAUSE_LINK:
17226 13 : kind = GOMP_MAP_LINK;
17227 13 : break;
17228 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
17229 10 : kind = GOMP_MAP_IF_PRESENT;
17230 10 : break;
17231 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
17232 128 : kind = GOMP_MAP_FORCE_PRESENT;
17233 128 : break;
17234 59 : case PRAGMA_OACC_CLAUSE_SELF:
17235 : /* "The 'host' clause is a synonym for the 'self' clause." */
17236 59 : case PRAGMA_OACC_CLAUSE_HOST:
17237 59 : kind = GOMP_MAP_FORCE_FROM;
17238 59 : break;
17239 0 : default:
17240 0 : gcc_unreachable ();
17241 : }
17242 :
17243 2026 : tree nl = list;
17244 2026 : bool readonly = false;
17245 2026 : location_t open_loc = c_parser_peek_token (parser)->location;
17246 2026 : matching_parens parens;
17247 2026 : if (parens.require_open (parser))
17248 : {
17249 : /* Turn on readonly modifier parsing for copyin clause. */
17250 2026 : if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
17251 : {
17252 359 : c_token *token = c_parser_peek_token (parser);
17253 359 : if (token->type == CPP_NAME
17254 359 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
17255 366 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17256 : {
17257 7 : c_parser_consume_token (parser);
17258 7 : c_parser_consume_token (parser);
17259 7 : readonly = true;
17260 : }
17261 : }
17262 2026 : nl = c_parser_omp_variable_list (parser, open_loc, OMP_CLAUSE_MAP, list,
17263 : false);
17264 2026 : parens.skip_until_found_close (parser);
17265 : }
17266 :
17267 4671 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17268 : {
17269 2645 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
17270 2645 : if (readonly)
17271 13 : OMP_CLAUSE_MAP_READONLY (c) = 1;
17272 : }
17273 :
17274 2026 : return nl;
17275 : }
17276 :
17277 : /* OpenACC 2.0:
17278 : deviceptr ( variable-list ) */
17279 :
17280 : static tree
17281 57 : c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
17282 : {
17283 57 : tree vars, t;
17284 :
17285 : /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
17286 : c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
17287 : variable-list must only allow for pointer variables. */
17288 57 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
17289 118 : for (t = vars; t && t; t = TREE_CHAIN (t))
17290 : {
17291 61 : tree v = TREE_PURPOSE (t);
17292 61 : location_t loc = EXPR_LOCATION (TREE_VALUE (t));
17293 :
17294 61 : if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
17295 3 : error_at (loc, "%qD is not a variable", v);
17296 58 : else if (TREE_TYPE (v) == error_mark_node)
17297 : ;
17298 57 : else if (!POINTER_TYPE_P (TREE_TYPE (v)))
17299 7 : error_at (loc, "%qD is not a pointer variable", v);
17300 :
17301 61 : tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
17302 61 : OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
17303 61 : OMP_CLAUSE_DECL (u) = v;
17304 61 : OMP_CLAUSE_CHAIN (u) = list;
17305 61 : list = u;
17306 : }
17307 :
17308 57 : return list;
17309 : }
17310 :
17311 : /* OpenACC 2.0, OpenMP 3.0:
17312 : collapse ( constant-expression ) */
17313 :
17314 : static tree
17315 2954 : c_parser_omp_clause_collapse (c_parser *parser, tree list)
17316 : {
17317 2954 : tree c, num = error_mark_node;
17318 2954 : HOST_WIDE_INT n;
17319 2954 : location_t loc;
17320 :
17321 2954 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
17322 2954 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
17323 :
17324 2954 : loc = c_parser_peek_token (parser)->location;
17325 2954 : matching_parens parens;
17326 2954 : if (parens.require_open (parser))
17327 : {
17328 2954 : num = c_parser_expr_no_commas (parser, NULL).value;
17329 2954 : parens.skip_until_found_close (parser);
17330 : }
17331 2954 : if (num == error_mark_node)
17332 : return list;
17333 2954 : mark_exp_read (num);
17334 2954 : num = c_fully_fold (num, false, NULL);
17335 5908 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17336 2954 : || !tree_fits_shwi_p (num)
17337 2954 : || (n = tree_to_shwi (num)) <= 0
17338 5908 : || (int) n != n)
17339 : {
17340 0 : error_at (loc,
17341 : "collapse argument needs positive constant integer expression");
17342 0 : return list;
17343 : }
17344 2954 : c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
17345 2954 : OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
17346 2954 : OMP_CLAUSE_CHAIN (c) = list;
17347 2954 : return c;
17348 : }
17349 :
17350 : /* OpenMP 2.5:
17351 : copyin ( variable-list ) */
17352 :
17353 : static tree
17354 101 : c_parser_omp_clause_copyin (c_parser *parser, tree list)
17355 : {
17356 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
17357 : }
17358 :
17359 : /* OpenMP 2.5:
17360 : copyprivate ( variable-list ) */
17361 :
17362 : static tree
17363 21 : c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
17364 : {
17365 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
17366 : }
17367 :
17368 : /* OpenMP 2.5:
17369 : default ( none | shared )
17370 :
17371 : OpenMP 5.1:
17372 : default ( private | firstprivate )
17373 :
17374 : OpenACC:
17375 : default ( none | present ) */
17376 :
17377 : static tree
17378 729 : c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
17379 : {
17380 729 : enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
17381 729 : location_t loc = c_parser_peek_token (parser)->location;
17382 729 : tree c;
17383 :
17384 729 : matching_parens parens;
17385 729 : if (!parens.require_open (parser))
17386 : return list;
17387 726 : if (c_parser_next_token_is (parser, CPP_NAME))
17388 : {
17389 714 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17390 :
17391 714 : switch (p[0])
17392 : {
17393 391 : case 'n':
17394 391 : if (strcmp ("none", p) != 0)
17395 0 : goto invalid_kind;
17396 : kind = OMP_CLAUSE_DEFAULT_NONE;
17397 : break;
17398 :
17399 23 : case 'p':
17400 23 : if (is_oacc)
17401 : {
17402 18 : if (strcmp ("present", p) != 0)
17403 3 : goto invalid_kind;
17404 : kind = OMP_CLAUSE_DEFAULT_PRESENT;
17405 : }
17406 : else
17407 : {
17408 5 : if (strcmp ("private", p) != 0)
17409 0 : goto invalid_kind;
17410 : kind = OMP_CLAUSE_DEFAULT_PRIVATE;
17411 : }
17412 : break;
17413 :
17414 9 : case 'f':
17415 9 : if (strcmp ("firstprivate", p) != 0 || is_oacc)
17416 0 : goto invalid_kind;
17417 : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
17418 : break;
17419 :
17420 287 : case 's':
17421 287 : if (strcmp ("shared", p) != 0 || is_oacc)
17422 0 : goto invalid_kind;
17423 : kind = OMP_CLAUSE_DEFAULT_SHARED;
17424 : break;
17425 :
17426 4 : default:
17427 4 : goto invalid_kind;
17428 : }
17429 :
17430 701 : c_parser_consume_token (parser);
17431 : }
17432 : else
17433 : {
17434 25 : invalid_kind:
17435 25 : if (is_oacc)
17436 21 : c_parser_error (parser, "expected %<none%> or %<present%>");
17437 : else
17438 4 : c_parser_error (parser, "expected %<none%>, %<shared%>, "
17439 : "%<private%> or %<firstprivate%>");
17440 : }
17441 726 : parens.skip_until_found_close (parser);
17442 :
17443 726 : if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
17444 : return list;
17445 :
17446 701 : check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
17447 701 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
17448 701 : OMP_CLAUSE_CHAIN (c) = list;
17449 701 : OMP_CLAUSE_DEFAULT_KIND (c) = kind;
17450 :
17451 701 : return c;
17452 : }
17453 :
17454 : /* OpenMP 2.5:
17455 : firstprivate ( variable-list ) */
17456 :
17457 : static tree
17458 790 : c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
17459 : {
17460 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
17461 : }
17462 :
17463 : /* OpenMP 3.1:
17464 : final ( expression ) */
17465 :
17466 : static tree
17467 99 : c_parser_omp_clause_final (c_parser *parser, tree list)
17468 : {
17469 99 : location_t loc = c_parser_peek_token (parser)->location;
17470 99 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
17471 : {
17472 99 : matching_parens parens;
17473 99 : tree t, c;
17474 99 : if (!parens.require_open (parser))
17475 0 : t = error_mark_node;
17476 : else
17477 : {
17478 99 : location_t eloc = c_parser_peek_token (parser)->location;
17479 99 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17480 99 : t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
17481 99 : t = c_objc_common_truthvalue_conversion (eloc, t);
17482 99 : t = c_fully_fold (t, false, NULL);
17483 99 : parens.skip_until_found_close (parser);
17484 : }
17485 :
17486 99 : check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
17487 :
17488 99 : c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
17489 99 : OMP_CLAUSE_FINAL_EXPR (c) = t;
17490 99 : OMP_CLAUSE_CHAIN (c) = list;
17491 99 : list = c;
17492 : }
17493 : else
17494 0 : c_parser_error (parser, "expected %<(%>");
17495 :
17496 99 : return list;
17497 : }
17498 :
17499 : /* OpenMP 5.1:
17500 : indirect [( expression )]
17501 : */
17502 :
17503 : static tree
17504 26 : c_parser_omp_clause_indirect (c_parser *parser, tree list)
17505 : {
17506 26 : location_t location = c_parser_peek_token (parser)->location;
17507 26 : tree t;
17508 :
17509 26 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17510 : {
17511 17 : matching_parens parens;
17512 17 : if (!parens.require_open (parser))
17513 1 : return list;
17514 :
17515 17 : location_t loc = c_parser_peek_token (parser)->location;
17516 17 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17517 17 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17518 17 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
17519 17 : t = c_fully_fold (t, false, NULL);
17520 34 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17521 34 : || TREE_CODE (t) != INTEGER_CST)
17522 : {
17523 1 : c_parser_error (parser, "expected constant logical expression");
17524 1 : return list;
17525 : }
17526 16 : parens.skip_until_found_close (parser);
17527 : }
17528 : else
17529 9 : t = integer_one_node;
17530 :
17531 25 : check_no_duplicate_clause (list, OMP_CLAUSE_INDIRECT, "indirect");
17532 :
17533 25 : tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
17534 25 : OMP_CLAUSE_INDIRECT_EXPR (c) = t;
17535 25 : OMP_CLAUSE_CHAIN (c) = list;
17536 :
17537 25 : return c;
17538 : }
17539 :
17540 : /* OpenACC, OpenMP 2.5:
17541 : if ( expression )
17542 :
17543 : OpenMP 4.5:
17544 : if ( directive-name-modifier : expression )
17545 :
17546 : directive-name-modifier:
17547 : parallel | task | taskloop | target data | target | target update
17548 : | target enter data | target exit data
17549 :
17550 : OpenMP 5.0:
17551 : directive-name-modifier:
17552 : ... | simd | cancel */
17553 :
17554 : static tree
17555 884 : c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
17556 : {
17557 884 : location_t location = c_parser_peek_token (parser)->location;
17558 884 : enum tree_code if_modifier = ERROR_MARK;
17559 :
17560 884 : matching_parens parens;
17561 884 : if (!parens.require_open (parser))
17562 : return list;
17563 :
17564 1663 : if (is_omp && c_parser_next_token_is (parser, CPP_NAME))
17565 : {
17566 638 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17567 638 : int n = 2;
17568 638 : if (strcmp (p, "cancel") == 0)
17569 : if_modifier = VOID_CST;
17570 623 : else if (strcmp (p, "parallel") == 0)
17571 : if_modifier = OMP_PARALLEL;
17572 484 : else if (strcmp (p, "simd") == 0)
17573 : if_modifier = OMP_SIMD;
17574 378 : else if (strcmp (p, "task") == 0)
17575 : if_modifier = OMP_TASK;
17576 367 : else if (strcmp (p, "taskloop") == 0)
17577 : if_modifier = OMP_TASKLOOP;
17578 316 : else if (strcmp (p, "target") == 0)
17579 : {
17580 102 : if_modifier = OMP_TARGET;
17581 102 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17582 : {
17583 37 : p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
17584 37 : if (strcmp ("data", p) == 0)
17585 : if_modifier = OMP_TARGET_DATA;
17586 29 : else if (strcmp ("update", p) == 0)
17587 : if_modifier = OMP_TARGET_UPDATE;
17588 18 : else if (strcmp ("enter", p) == 0)
17589 : if_modifier = OMP_TARGET_ENTER_DATA;
17590 10 : else if (strcmp ("exit", p) == 0)
17591 : if_modifier = OMP_TARGET_EXIT_DATA;
17592 0 : if (if_modifier != OMP_TARGET)
17593 : {
17594 37 : n = 3;
17595 37 : c_parser_consume_token (parser);
17596 : }
17597 : else
17598 : {
17599 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17600 0 : error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
17601 : "or %<exit%>");
17602 0 : if_modifier = ERROR_MARK;
17603 : }
17604 0 : if (if_modifier == OMP_TARGET_ENTER_DATA
17605 37 : || if_modifier == OMP_TARGET_EXIT_DATA)
17606 : {
17607 18 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17608 : {
17609 18 : p = IDENTIFIER_POINTER
17610 : (c_parser_peek_2nd_token (parser)->value);
17611 18 : if (strcmp ("data", p) == 0)
17612 18 : n = 4;
17613 : }
17614 18 : if (n == 4)
17615 18 : c_parser_consume_token (parser);
17616 : else
17617 : {
17618 0 : location_t loc
17619 0 : = c_parser_peek_2nd_token (parser)->location;
17620 0 : error_at (loc, "expected %<data%>");
17621 0 : if_modifier = ERROR_MARK;
17622 : }
17623 : }
17624 : }
17625 : }
17626 37 : if (if_modifier != ERROR_MARK)
17627 : {
17628 424 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17629 : {
17630 423 : c_parser_consume_token (parser);
17631 423 : c_parser_consume_token (parser);
17632 : }
17633 : else
17634 : {
17635 1 : if (n > 2)
17636 : {
17637 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17638 0 : error_at (loc, "expected %<:%>");
17639 : }
17640 : if_modifier = ERROR_MARK;
17641 : }
17642 : }
17643 : }
17644 :
17645 884 : location_t loc = c_parser_peek_token (parser)->location;
17646 884 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17647 884 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17648 884 : tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
17649 884 : t = c_fully_fold (t, false, NULL);
17650 884 : parens.skip_until_found_close (parser);
17651 :
17652 3988 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17653 3144 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
17654 : {
17655 174 : if (if_modifier != ERROR_MARK
17656 174 : && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17657 : {
17658 9 : const char *p = NULL;
17659 9 : switch (if_modifier)
17660 : {
17661 : case VOID_CST: p = "cancel"; break;
17662 1 : case OMP_PARALLEL: p = "parallel"; break;
17663 0 : case OMP_SIMD: p = "simd"; break;
17664 1 : case OMP_TASK: p = "task"; break;
17665 1 : case OMP_TASKLOOP: p = "taskloop"; break;
17666 1 : case OMP_TARGET_DATA: p = "target data"; break;
17667 1 : case OMP_TARGET: p = "target"; break;
17668 1 : case OMP_TARGET_UPDATE: p = "target update"; break;
17669 1 : case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
17670 1 : case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
17671 0 : default: gcc_unreachable ();
17672 : }
17673 9 : error_at (location, "too many %<if%> clauses with %qs modifier",
17674 : p);
17675 9 : return list;
17676 : }
17677 165 : else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17678 : {
17679 13 : if (!is_omp)
17680 1 : error_at (location, "too many %<if%> clauses");
17681 : else
17682 12 : error_at (location, "too many %<if%> clauses without modifier");
17683 13 : return list;
17684 : }
17685 152 : else if (if_modifier == ERROR_MARK
17686 152 : || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
17687 : {
17688 18 : error_at (location, "if any %<if%> clause has modifier, then all "
17689 : "%<if%> clauses have to use modifier");
17690 18 : return list;
17691 : }
17692 : }
17693 :
17694 844 : c = build_omp_clause (location, OMP_CLAUSE_IF);
17695 844 : OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
17696 844 : OMP_CLAUSE_IF_EXPR (c) = t;
17697 844 : OMP_CLAUSE_CHAIN (c) = list;
17698 844 : return c;
17699 : }
17700 :
17701 : /* OpenMP 2.5:
17702 : lastprivate ( variable-list )
17703 :
17704 : OpenMP 5.0:
17705 : lastprivate ( [ lastprivate-modifier : ] variable-list ) */
17706 :
17707 : static tree
17708 732 : c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
17709 : {
17710 : /* The clauses location. */
17711 732 : location_t loc = c_parser_peek_token (parser)->location;
17712 :
17713 732 : if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
17714 : {
17715 732 : bool conditional = false;
17716 732 : if (c_parser_next_token_is (parser, CPP_NAME)
17717 732 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17718 : {
17719 107 : const char *p
17720 107 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17721 107 : if (strcmp (p, "conditional") == 0)
17722 : {
17723 107 : conditional = true;
17724 107 : c_parser_consume_token (parser);
17725 107 : c_parser_consume_token (parser);
17726 : }
17727 : }
17728 732 : tree nlist = c_parser_omp_variable_list (parser, loc,
17729 : OMP_CLAUSE_LASTPRIVATE, list);
17730 732 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
17731 732 : if (conditional)
17732 246 : for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
17733 139 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
17734 732 : return nlist;
17735 : }
17736 : return list;
17737 : }
17738 :
17739 : /* OpenMP 3.1:
17740 : mergeable */
17741 :
17742 : static tree
17743 79 : c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17744 : {
17745 79 : tree c;
17746 :
17747 : /* FIXME: Should we allow duplicates? */
17748 79 : check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
17749 :
17750 79 : c = build_omp_clause (c_parser_peek_token (parser)->location,
17751 : OMP_CLAUSE_MERGEABLE);
17752 79 : OMP_CLAUSE_CHAIN (c) = list;
17753 :
17754 79 : return c;
17755 : }
17756 :
17757 : /* OpenMP 2.5:
17758 : nowait */
17759 :
17760 : static tree
17761 391 : c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17762 : {
17763 391 : tree c;
17764 391 : location_t loc = c_parser_peek_token (parser)->location;
17765 :
17766 391 : check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
17767 :
17768 391 : c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
17769 391 : OMP_CLAUSE_CHAIN (c) = list;
17770 391 : return c;
17771 : }
17772 :
17773 : /* OpenMP 2.5:
17774 : num_threads ( expression ) */
17775 :
17776 : static tree
17777 426 : c_parser_omp_clause_num_threads (c_parser *parser, tree list)
17778 : {
17779 426 : location_t num_threads_loc = c_parser_peek_token (parser)->location;
17780 426 : matching_parens parens;
17781 426 : if (parens.require_open (parser))
17782 : {
17783 426 : location_t expr_loc = c_parser_peek_token (parser)->location;
17784 426 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17785 426 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17786 426 : tree c, t = expr.value;
17787 426 : t = c_fully_fold (t, false, NULL);
17788 :
17789 426 : parens.skip_until_found_close (parser);
17790 :
17791 426 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17792 : {
17793 0 : c_parser_error (parser, "expected integer expression");
17794 0 : return list;
17795 : }
17796 :
17797 : /* Attempt to statically determine when the number isn't positive. */
17798 426 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17799 426 : build_int_cst (TREE_TYPE (t), 0));
17800 426 : protected_set_expr_location (c, expr_loc);
17801 426 : if (c == boolean_true_node)
17802 : {
17803 1 : warning_at (expr_loc, OPT_Wopenmp,
17804 : "%<num_threads%> value must be positive");
17805 1 : t = integer_one_node;
17806 : }
17807 :
17808 426 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
17809 :
17810 426 : c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
17811 426 : OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
17812 426 : OMP_CLAUSE_CHAIN (c) = list;
17813 426 : list = c;
17814 : }
17815 :
17816 : return list;
17817 : }
17818 :
17819 : /* OpenMP 4.5:
17820 : num_tasks ( expression )
17821 :
17822 : OpenMP 5.1:
17823 : num_tasks ( strict : expression ) */
17824 :
17825 : static tree
17826 50 : c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
17827 : {
17828 50 : location_t num_tasks_loc = c_parser_peek_token (parser)->location;
17829 50 : matching_parens parens;
17830 50 : if (parens.require_open (parser))
17831 : {
17832 50 : bool strict = false;
17833 50 : if (c_parser_next_token_is (parser, CPP_NAME)
17834 40 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17835 51 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17836 : "strict") == 0)
17837 : {
17838 1 : strict = true;
17839 1 : c_parser_consume_token (parser);
17840 1 : c_parser_consume_token (parser);
17841 : }
17842 :
17843 50 : location_t expr_loc = c_parser_peek_token (parser)->location;
17844 50 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17845 50 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17846 50 : tree c, t = expr.value;
17847 50 : t = c_fully_fold (t, false, NULL);
17848 :
17849 50 : parens.skip_until_found_close (parser);
17850 :
17851 50 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17852 : {
17853 0 : c_parser_error (parser, "expected integer expression");
17854 0 : return list;
17855 : }
17856 :
17857 : /* Attempt to statically determine when the number isn't positive. */
17858 50 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17859 50 : build_int_cst (TREE_TYPE (t), 0));
17860 50 : if (CAN_HAVE_LOCATION_P (c))
17861 40 : SET_EXPR_LOCATION (c, expr_loc);
17862 50 : if (c == boolean_true_node)
17863 : {
17864 0 : warning_at (expr_loc, OPT_Wopenmp,
17865 : "%<num_tasks%> value must be positive");
17866 0 : t = integer_one_node;
17867 : }
17868 :
17869 50 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks");
17870 :
17871 50 : c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
17872 50 : OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
17873 50 : OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
17874 50 : OMP_CLAUSE_CHAIN (c) = list;
17875 50 : list = c;
17876 : }
17877 :
17878 : return list;
17879 : }
17880 :
17881 : /* OpenMP 4.5:
17882 : grainsize ( expression )
17883 :
17884 : OpenMP 5.1:
17885 : grainsize ( strict : expression ) */
17886 :
17887 : static tree
17888 62 : c_parser_omp_clause_grainsize (c_parser *parser, tree list)
17889 : {
17890 62 : location_t grainsize_loc = c_parser_peek_token (parser)->location;
17891 62 : matching_parens parens;
17892 62 : if (parens.require_open (parser))
17893 : {
17894 62 : bool strict = false;
17895 62 : if (c_parser_next_token_is (parser, CPP_NAME)
17896 47 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17897 63 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17898 : "strict") == 0)
17899 : {
17900 1 : strict = true;
17901 1 : c_parser_consume_token (parser);
17902 1 : c_parser_consume_token (parser);
17903 : }
17904 :
17905 62 : location_t expr_loc = c_parser_peek_token (parser)->location;
17906 62 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17907 62 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17908 62 : tree c, t = expr.value;
17909 62 : t = c_fully_fold (t, false, NULL);
17910 :
17911 62 : parens.skip_until_found_close (parser);
17912 :
17913 62 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17914 : {
17915 0 : c_parser_error (parser, "expected integer expression");
17916 0 : return list;
17917 : }
17918 :
17919 : /* Attempt to statically determine when the number isn't positive. */
17920 62 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17921 62 : build_int_cst (TREE_TYPE (t), 0));
17922 62 : if (CAN_HAVE_LOCATION_P (c))
17923 47 : SET_EXPR_LOCATION (c, expr_loc);
17924 62 : if (c == boolean_true_node)
17925 : {
17926 0 : warning_at (expr_loc, OPT_Wopenmp,
17927 : "%<grainsize%> value must be positive");
17928 0 : t = integer_one_node;
17929 : }
17930 :
17931 62 : check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize");
17932 :
17933 62 : c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
17934 62 : OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
17935 62 : OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
17936 62 : OMP_CLAUSE_CHAIN (c) = list;
17937 62 : list = c;
17938 : }
17939 :
17940 : return list;
17941 : }
17942 :
17943 : /* OpenMP 4.5:
17944 : priority ( expression ) */
17945 :
17946 : static tree
17947 98 : c_parser_omp_clause_priority (c_parser *parser, tree list)
17948 : {
17949 98 : location_t priority_loc = c_parser_peek_token (parser)->location;
17950 98 : matching_parens parens;
17951 98 : if (parens.require_open (parser))
17952 : {
17953 98 : location_t expr_loc = c_parser_peek_token (parser)->location;
17954 98 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17955 98 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17956 98 : tree c, t = expr.value;
17957 98 : t = c_fully_fold (t, false, NULL);
17958 :
17959 98 : parens.skip_until_found_close (parser);
17960 :
17961 98 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17962 : {
17963 0 : c_parser_error (parser, "expected integer expression");
17964 0 : return list;
17965 : }
17966 :
17967 : /* Attempt to statically determine when the number isn't
17968 : non-negative. */
17969 98 : c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
17970 98 : build_int_cst (TREE_TYPE (t), 0));
17971 98 : if (CAN_HAVE_LOCATION_P (c))
17972 87 : SET_EXPR_LOCATION (c, expr_loc);
17973 98 : if (c == boolean_true_node)
17974 : {
17975 0 : warning_at (expr_loc, OPT_Wopenmp,
17976 : "%<priority%> value must be non-negative");
17977 0 : t = integer_one_node;
17978 : }
17979 :
17980 98 : check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority");
17981 :
17982 98 : c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
17983 98 : OMP_CLAUSE_PRIORITY_EXPR (c) = t;
17984 98 : OMP_CLAUSE_CHAIN (c) = list;
17985 98 : list = c;
17986 : }
17987 :
17988 : return list;
17989 : }
17990 :
17991 : /* OpenMP 4.5:
17992 : hint ( expression ) */
17993 :
17994 : static tree
17995 58 : c_parser_omp_clause_hint (c_parser *parser, tree list)
17996 : {
17997 58 : location_t hint_loc = c_parser_peek_token (parser)->location;
17998 58 : matching_parens parens;
17999 58 : if (parens.require_open (parser))
18000 : {
18001 58 : location_t expr_loc = c_parser_peek_token (parser)->location;
18002 58 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18003 58 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18004 58 : tree c, t = expr.value;
18005 58 : t = c_fully_fold (t, false, NULL);
18006 116 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
18007 57 : || TREE_CODE (t) != INTEGER_CST
18008 111 : || tree_int_cst_sgn (t) == -1)
18009 : {
18010 6 : c_parser_error (parser, "expected constant integer expression "
18011 : "with valid sync-hint value");
18012 6 : return list;
18013 : }
18014 52 : parens.skip_until_found_close (parser);
18015 52 : check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
18016 :
18017 52 : c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
18018 52 : OMP_CLAUSE_HINT_EXPR (c) = t;
18019 52 : OMP_CLAUSE_CHAIN (c) = list;
18020 52 : list = c;
18021 : }
18022 :
18023 : return list;
18024 : }
18025 :
18026 : /* OpenMP 5.1:
18027 : filter ( integer-expression ) */
18028 :
18029 : static tree
18030 63 : c_parser_omp_clause_filter (c_parser *parser, tree list)
18031 : {
18032 63 : location_t hint_loc = c_parser_peek_token (parser)->location;
18033 63 : matching_parens parens;
18034 63 : if (parens.require_open (parser))
18035 : {
18036 63 : location_t expr_loc = c_parser_peek_token (parser)->location;
18037 63 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18038 63 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18039 63 : tree c, t = expr.value;
18040 63 : t = c_fully_fold (t, false, NULL);
18041 63 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18042 : {
18043 2 : c_parser_error (parser, "expected integer expression");
18044 2 : return list;
18045 : }
18046 61 : parens.skip_until_found_close (parser);
18047 61 : check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
18048 :
18049 61 : c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
18050 61 : OMP_CLAUSE_FILTER_EXPR (c) = t;
18051 61 : OMP_CLAUSE_CHAIN (c) = list;
18052 61 : list = c;
18053 : }
18054 :
18055 : return list;
18056 : }
18057 :
18058 : /* OpenMP 4.5:
18059 : defaultmap ( tofrom : scalar )
18060 :
18061 : OpenMP 5.0:
18062 : defaultmap ( implicit-behavior [ : variable-category ] ) */
18063 :
18064 : static tree
18065 238 : c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
18066 : {
18067 238 : location_t loc = c_parser_peek_token (parser)->location;
18068 238 : tree c;
18069 238 : const char *p;
18070 238 : enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
18071 238 : enum omp_clause_defaultmap_kind category
18072 : = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
18073 :
18074 238 : matching_parens parens;
18075 238 : if (!parens.require_open (parser))
18076 : return list;
18077 238 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
18078 : p = "default";
18079 231 : else if (!c_parser_next_token_is (parser, CPP_NAME))
18080 : {
18081 2 : invalid_behavior:
18082 3 : c_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
18083 : "%<tofrom%>, %<firstprivate%>, %<none%> "
18084 : "or %<default%>");
18085 3 : goto out_err;
18086 : }
18087 : else
18088 229 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18089 :
18090 236 : switch (p[0])
18091 : {
18092 7 : case 'a':
18093 7 : if (strcmp ("alloc", p) == 0)
18094 : behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
18095 : else
18096 0 : goto invalid_behavior;
18097 : break;
18098 :
18099 7 : case 'd':
18100 7 : if (strcmp ("default", p) == 0)
18101 : behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
18102 : else
18103 0 : goto invalid_behavior;
18104 : break;
18105 :
18106 27 : case 'f':
18107 27 : if (strcmp ("firstprivate", p) == 0)
18108 : behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
18109 3 : else if (strcmp ("from", p) == 0)
18110 : behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
18111 : else
18112 0 : goto invalid_behavior;
18113 : break;
18114 :
18115 101 : case 'n':
18116 101 : if (strcmp ("none", p) == 0)
18117 : behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
18118 : else
18119 0 : goto invalid_behavior;
18120 : break;
18121 :
18122 4 : case 'p':
18123 4 : if (strcmp ("present", p) == 0)
18124 : behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
18125 : else
18126 0 : goto invalid_behavior;
18127 : break;
18128 :
18129 89 : case 't':
18130 89 : if (strcmp ("tofrom", p) == 0)
18131 : behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
18132 4 : else if (strcmp ("to", p) == 0)
18133 : behavior = OMP_CLAUSE_DEFAULTMAP_TO;
18134 : else
18135 0 : goto invalid_behavior;
18136 : break;
18137 :
18138 1 : default:
18139 1 : goto invalid_behavior;
18140 : }
18141 235 : c_parser_consume_token (parser);
18142 :
18143 235 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
18144 : {
18145 131 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18146 3 : goto out_err;
18147 128 : if (!c_parser_next_token_is (parser, CPP_NAME))
18148 : {
18149 1 : invalid_category:
18150 2 : c_parser_error (parser, "expected %<scalar%>, %<aggregate%>, "
18151 : "%<pointer%> or %<all%>");
18152 2 : goto out_err;
18153 : }
18154 127 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18155 127 : switch (p[0])
18156 : {
18157 22 : case 'a':
18158 22 : if (strcmp ("aggregate", p) == 0)
18159 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
18160 8 : else if (strcmp ("all", p) == 0)
18161 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
18162 : else
18163 0 : goto invalid_category;
18164 : break;
18165 :
18166 14 : case 'p':
18167 14 : if (strcmp ("pointer", p) == 0)
18168 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
18169 : else
18170 0 : goto invalid_category;
18171 : break;
18172 :
18173 90 : case 's':
18174 90 : if (strcmp ("scalar", p) == 0)
18175 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
18176 : else
18177 0 : goto invalid_category;
18178 : break;
18179 :
18180 1 : default:
18181 1 : goto invalid_category;
18182 : }
18183 :
18184 126 : c_parser_consume_token (parser);
18185 : }
18186 230 : parens.skip_until_found_close (parser);
18187 :
18188 958 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
18189 511 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
18190 511 : && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
18191 : || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
18192 32 : || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
18193 31 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18194 : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
18195 29 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18196 : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
18197 : {
18198 13 : enum omp_clause_defaultmap_kind cat = category;
18199 13 : location_t loc = OMP_CLAUSE_LOCATION (c);
18200 13 : if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
18201 13 : || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
18202 3 : && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
18203 : != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
18204 8 : cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
18205 13 : p = NULL;
18206 13 : switch (cat)
18207 : {
18208 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
18209 : p = NULL;
18210 : break;
18211 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
18212 3 : p = "all";
18213 3 : break;
18214 2 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
18215 2 : p = "aggregate";
18216 2 : break;
18217 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
18218 3 : p = "pointer";
18219 3 : break;
18220 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
18221 : p = "scalar";
18222 : break;
18223 0 : default:
18224 0 : gcc_unreachable ();
18225 : }
18226 8 : if (p)
18227 10 : error_at (loc, "too many %<defaultmap%> clauses with %qs category",
18228 : p);
18229 : else
18230 3 : error_at (loc, "too many %<defaultmap%> clauses with unspecified "
18231 : "category");
18232 : break;
18233 : }
18234 :
18235 230 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
18236 230 : OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
18237 230 : OMP_CLAUSE_CHAIN (c) = list;
18238 230 : return c;
18239 :
18240 8 : out_err:
18241 8 : parens.skip_until_found_close (parser);
18242 8 : return list;
18243 : }
18244 :
18245 : /* OpenACC 2.0:
18246 : use_device ( variable-list )
18247 :
18248 : OpenMP 4.5:
18249 : use_device_ptr ( variable-list ) */
18250 :
18251 : static tree
18252 31 : c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
18253 : {
18254 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_PTR,
18255 0 : list);
18256 : }
18257 :
18258 : /* OpenMP 5.0:
18259 : use_device_addr ( variable-list ) */
18260 :
18261 : static tree
18262 35 : c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
18263 : {
18264 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_ADDR,
18265 0 : list);
18266 : }
18267 :
18268 : /* OpenMP 5.1:
18269 : has_device_addr ( variable-list ) */
18270 :
18271 : static tree
18272 88 : c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
18273 : {
18274 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_HAS_DEVICE_ADDR,
18275 0 : list);
18276 : }
18277 :
18278 : /* OpenMP 4.5:
18279 : is_device_ptr ( variable-list ) */
18280 :
18281 : static tree
18282 115 : c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
18283 : {
18284 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_IS_DEVICE_PTR, list);
18285 : }
18286 :
18287 : /* OpenACC:
18288 : num_gangs ( expression )
18289 : num_workers ( expression )
18290 : vector_length ( expression ) */
18291 :
18292 : static tree
18293 732 : c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
18294 : tree list)
18295 : {
18296 732 : location_t loc = c_parser_peek_token (parser)->location;
18297 :
18298 732 : matching_parens parens;
18299 732 : if (!parens.require_open (parser))
18300 : return list;
18301 :
18302 726 : location_t expr_loc = c_parser_peek_token (parser)->location;
18303 726 : c_expr expr = c_parser_expression (parser);
18304 726 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18305 726 : tree c, t = expr.value;
18306 726 : t = c_fully_fold (t, false, NULL);
18307 :
18308 726 : parens.skip_until_found_close (parser);
18309 :
18310 726 : if (t == error_mark_node)
18311 : return list;
18312 702 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18313 : {
18314 16 : error_at (expr_loc, "%qs expression must be integral",
18315 16 : omp_clause_code_name[code]);
18316 16 : return list;
18317 : }
18318 :
18319 : /* Attempt to statically determine when the number isn't positive. */
18320 686 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
18321 686 : build_int_cst (TREE_TYPE (t), 0));
18322 686 : protected_set_expr_location (c, expr_loc);
18323 686 : if (c == boolean_true_node)
18324 : {
18325 36 : warning_at (expr_loc, 0,
18326 : "%qs value must be positive",
18327 18 : omp_clause_code_name[code]);
18328 18 : t = integer_one_node;
18329 : }
18330 :
18331 686 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18332 :
18333 686 : c = build_omp_clause (loc, code);
18334 686 : OMP_CLAUSE_OPERAND (c, 0) = t;
18335 686 : OMP_CLAUSE_CHAIN (c) = list;
18336 686 : return c;
18337 : }
18338 :
18339 : /* OpenACC:
18340 :
18341 : gang [( gang-arg-list )]
18342 : worker [( [num:] int-expr )]
18343 : vector [( [length:] int-expr )]
18344 :
18345 : where gang-arg is one of:
18346 :
18347 : [num:] int-expr
18348 : static: size-expr
18349 :
18350 : and size-expr may be:
18351 :
18352 : *
18353 : int-expr
18354 : */
18355 :
18356 : static tree
18357 1560 : c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
18358 : omp_clause_code kind,
18359 : const char *str, tree list)
18360 : {
18361 1560 : const char *id = "num";
18362 1560 : tree ops[2] = { NULL_TREE, NULL_TREE }, c;
18363 :
18364 1560 : if (kind == OMP_CLAUSE_VECTOR)
18365 518 : id = "length";
18366 :
18367 1560 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18368 : {
18369 246 : c_parser_consume_token (parser);
18370 :
18371 276 : do
18372 : {
18373 261 : c_token *next = c_parser_peek_token (parser);
18374 261 : int idx = 0;
18375 :
18376 : /* Gang static argument. */
18377 261 : if (kind == OMP_CLAUSE_GANG
18378 403 : && c_parser_next_token_is_keyword (parser, RID_STATIC))
18379 : {
18380 70 : c_parser_consume_token (parser);
18381 :
18382 70 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18383 12 : goto cleanup_error;
18384 :
18385 70 : idx = 1;
18386 70 : if (ops[idx] != NULL_TREE)
18387 : {
18388 0 : c_parser_error (parser, "too many %<static%> arguments");
18389 0 : goto cleanup_error;
18390 : }
18391 :
18392 : /* Check for the '*' argument. */
18393 70 : if (c_parser_next_token_is (parser, CPP_MULT)
18394 70 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18395 30 : || c_parser_peek_2nd_token (parser)->type
18396 : == CPP_CLOSE_PAREN))
18397 : {
18398 29 : c_parser_consume_token (parser);
18399 29 : ops[idx] = integer_minus_one_node;
18400 :
18401 29 : if (c_parser_next_token_is (parser, CPP_COMMA))
18402 : {
18403 1 : c_parser_consume_token (parser);
18404 1 : continue;
18405 : }
18406 : else
18407 : break;
18408 : }
18409 : }
18410 : /* Worker num: argument and vector length: arguments. */
18411 191 : else if (c_parser_next_token_is (parser, CPP_NAME)
18412 149 : && strcmp (id, IDENTIFIER_POINTER (next->value)) == 0
18413 324 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18414 : {
18415 127 : c_parser_consume_token (parser); /* id */
18416 127 : c_parser_consume_token (parser); /* ':' */
18417 : }
18418 :
18419 : /* Now collect the actual argument. */
18420 232 : if (ops[idx] != NULL_TREE)
18421 : {
18422 5 : c_parser_error (parser, "unexpected argument");
18423 5 : goto cleanup_error;
18424 : }
18425 :
18426 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
18427 227 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18428 227 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18429 227 : tree expr = cexpr.value;
18430 227 : if (expr == error_mark_node)
18431 7 : goto cleanup_error;
18432 :
18433 220 : expr = c_fully_fold (expr, false, NULL);
18434 :
18435 : /* Attempt to statically determine when the number isn't a
18436 : positive integer. */
18437 :
18438 220 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
18439 : {
18440 14 : c_parser_error (parser, "expected integer expression");
18441 14 : return list;
18442 : }
18443 :
18444 206 : tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
18445 206 : build_int_cst (TREE_TYPE (expr), 0));
18446 206 : if (c == boolean_true_node)
18447 : {
18448 1 : warning_at (loc, 0,
18449 : "%qs value must be positive", str);
18450 1 : expr = integer_one_node;
18451 : }
18452 :
18453 206 : ops[idx] = expr;
18454 :
18455 220 : if (kind == OMP_CLAUSE_GANG
18456 305 : && c_parser_next_token_is (parser, CPP_COMMA))
18457 : {
18458 14 : c_parser_consume_token (parser);
18459 14 : continue;
18460 : }
18461 : break;
18462 15 : }
18463 : while (1);
18464 :
18465 220 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18466 7 : goto cleanup_error;
18467 : }
18468 :
18469 1527 : check_no_duplicate_clause (list, kind, str);
18470 :
18471 1527 : c = build_omp_clause (loc, kind);
18472 :
18473 1527 : if (ops[1])
18474 67 : OMP_CLAUSE_OPERAND (c, 1) = ops[1];
18475 :
18476 1527 : OMP_CLAUSE_OPERAND (c, 0) = ops[0];
18477 1527 : OMP_CLAUSE_CHAIN (c) = list;
18478 :
18479 1527 : return c;
18480 :
18481 19 : cleanup_error:
18482 19 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18483 19 : return list;
18484 : }
18485 :
18486 : /* OpenACC 2.5:
18487 : auto
18488 : finalize
18489 : independent
18490 : nohost
18491 : seq */
18492 :
18493 : static tree
18494 487 : c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
18495 : tree list)
18496 : {
18497 487 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18498 :
18499 487 : tree c = build_omp_clause (loc, code);
18500 487 : OMP_CLAUSE_CHAIN (c) = list;
18501 :
18502 487 : return c;
18503 : }
18504 :
18505 : /* OpenACC:
18506 : async [( int-expr )] */
18507 :
18508 : static tree
18509 240 : c_parser_oacc_clause_async (c_parser *parser, tree list)
18510 : {
18511 240 : tree c, t;
18512 240 : location_t loc = c_parser_peek_token (parser)->location;
18513 :
18514 240 : t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18515 :
18516 240 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18517 : {
18518 187 : c_parser_consume_token (parser);
18519 :
18520 187 : t = c_parser_expr_no_commas (parser, NULL).value;
18521 187 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18522 9 : c_parser_error (parser, "expected integer expression");
18523 178 : else if (t == error_mark_node
18524 178 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18525 14 : return list;
18526 : }
18527 : else
18528 53 : t = c_fully_fold (t, false, NULL);
18529 :
18530 226 : check_no_duplicate_clause (list, OMP_CLAUSE_ASYNC, "async");
18531 :
18532 226 : c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
18533 226 : OMP_CLAUSE_ASYNC_EXPR (c) = t;
18534 226 : OMP_CLAUSE_CHAIN (c) = list;
18535 226 : list = c;
18536 :
18537 226 : return list;
18538 : }
18539 :
18540 : /* OpenACC 2.0:
18541 : tile ( size-expr-list ) */
18542 :
18543 : static tree
18544 123 : c_parser_oacc_clause_tile (c_parser *parser, tree list)
18545 : {
18546 123 : tree c, expr = error_mark_node;
18547 123 : location_t loc;
18548 123 : tree tile = NULL_TREE;
18549 :
18550 123 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
18551 123 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
18552 :
18553 123 : loc = c_parser_peek_token (parser)->location;
18554 123 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
18555 : return list;
18556 :
18557 163 : do
18558 : {
18559 163 : if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
18560 : return list;
18561 :
18562 163 : if (c_parser_next_token_is (parser, CPP_MULT)
18563 163 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18564 53 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
18565 : {
18566 60 : c_parser_consume_token (parser);
18567 60 : expr = integer_zero_node;
18568 : }
18569 : else
18570 : {
18571 103 : location_t expr_loc = c_parser_peek_token (parser)->location;
18572 103 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18573 103 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18574 103 : expr = cexpr.value;
18575 :
18576 103 : if (expr == error_mark_node)
18577 : {
18578 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
18579 : "expected %<)%>");
18580 7 : return list;
18581 : }
18582 :
18583 96 : expr = c_fully_fold (expr, false, NULL);
18584 :
18585 192 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
18586 95 : || !tree_fits_shwi_p (expr)
18587 183 : || tree_to_shwi (expr) <= 0)
18588 : {
18589 16 : error_at (expr_loc, "%<tile%> argument needs positive"
18590 : " integral constant");
18591 16 : expr = integer_zero_node;
18592 : }
18593 : }
18594 :
18595 156 : tile = tree_cons (NULL_TREE, expr, tile);
18596 : }
18597 156 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
18598 :
18599 : /* Consume the trailing ')'. */
18600 111 : c_parser_consume_token (parser);
18601 :
18602 111 : c = build_omp_clause (loc, OMP_CLAUSE_TILE);
18603 111 : tile = nreverse (tile);
18604 111 : OMP_CLAUSE_TILE_LIST (c) = tile;
18605 111 : OMP_CLAUSE_CHAIN (c) = list;
18606 111 : return c;
18607 : }
18608 :
18609 : /* OpenACC:
18610 : wait [( int-expr-list )] */
18611 :
18612 : static tree
18613 97 : c_parser_oacc_clause_wait (c_parser *parser, tree list)
18614 : {
18615 97 : location_t clause_loc = c_parser_peek_token (parser)->location;
18616 :
18617 97 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18618 82 : list = c_parser_oacc_wait_list (parser, clause_loc, list);
18619 : else
18620 : {
18621 15 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
18622 :
18623 15 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18624 15 : OMP_CLAUSE_CHAIN (c) = list;
18625 15 : list = c;
18626 : }
18627 :
18628 97 : return list;
18629 : }
18630 :
18631 : /* OpenACC 2.7:
18632 : self [( expression )] */
18633 :
18634 : static tree
18635 48 : c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
18636 : {
18637 48 : tree t;
18638 48 : location_t location = c_parser_peek_token (parser)->location;
18639 48 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18640 : {
18641 42 : matching_parens parens;
18642 42 : parens.consume_open (parser);
18643 :
18644 42 : location_t loc = c_parser_peek_token (parser)->location;
18645 42 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18646 42 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
18647 42 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
18648 42 : t = c_fully_fold (t, false, NULL);
18649 42 : parens.skip_until_found_close (parser);
18650 : }
18651 : else
18652 6 : t = truthvalue_true_node;
18653 :
18654 78 : for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
18655 36 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
18656 : {
18657 6 : error_at (location, "too many %<self%> clauses");
18658 6 : return list;
18659 : }
18660 :
18661 42 : tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
18662 42 : OMP_CLAUSE_SELF_EXPR (c) = t;
18663 42 : OMP_CLAUSE_CHAIN (c) = list;
18664 42 : return c;
18665 : }
18666 :
18667 : /* OpenMP 5.0:
18668 : order ( concurrent )
18669 :
18670 : OpenMP 5.1:
18671 : order ( order-modifier : concurrent )
18672 :
18673 : order-modifier:
18674 : reproducible
18675 : unconstrained */
18676 :
18677 : static tree
18678 376 : c_parser_omp_clause_order (c_parser *parser, tree list)
18679 : {
18680 376 : location_t loc = c_parser_peek_token (parser)->location;
18681 376 : tree c;
18682 376 : const char *p;
18683 376 : bool unconstrained = false;
18684 376 : bool reproducible = false;
18685 :
18686 376 : matching_parens parens;
18687 376 : if (!parens.require_open (parser))
18688 : return list;
18689 374 : if (c_parser_next_token_is (parser, CPP_NAME)
18690 374 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18691 : {
18692 107 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18693 107 : if (strcmp (p, "unconstrained") == 0)
18694 : unconstrained = true;
18695 56 : else if (strcmp (p, "reproducible") == 0)
18696 : reproducible = true;
18697 : else
18698 : {
18699 1 : c_parser_error (parser, "expected %<reproducible%> or "
18700 : "%<unconstrained%>");
18701 1 : goto out_err;
18702 : }
18703 106 : c_parser_consume_token (parser);
18704 106 : c_parser_consume_token (parser);
18705 : }
18706 373 : if (!c_parser_next_token_is (parser, CPP_NAME))
18707 : {
18708 0 : c_parser_error (parser, "expected %<concurrent%>");
18709 0 : goto out_err;
18710 : }
18711 373 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18712 373 : if (strcmp (p, "concurrent") != 0)
18713 : {
18714 1 : c_parser_error (parser, "expected %<concurrent%>");
18715 1 : goto out_err;
18716 : }
18717 372 : c_parser_consume_token (parser);
18718 372 : parens.skip_until_found_close (parser);
18719 372 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
18720 372 : c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
18721 372 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
18722 372 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
18723 372 : OMP_CLAUSE_CHAIN (c) = list;
18724 372 : return c;
18725 :
18726 2 : out_err:
18727 2 : parens.skip_until_found_close (parser);
18728 2 : return list;
18729 : }
18730 :
18731 :
18732 : /* OpenMP 5.0:
18733 : bind ( teams | parallel | thread ) */
18734 :
18735 : static tree
18736 116 : c_parser_omp_clause_bind (c_parser *parser, tree list)
18737 : {
18738 116 : location_t loc = c_parser_peek_token (parser)->location;
18739 116 : tree c;
18740 116 : const char *p;
18741 116 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18742 :
18743 116 : matching_parens parens;
18744 116 : if (!parens.require_open (parser))
18745 : return list;
18746 114 : if (!c_parser_next_token_is (parser, CPP_NAME))
18747 : {
18748 3 : invalid:
18749 4 : c_parser_error (parser,
18750 : "expected %<teams%>, %<parallel%> or %<thread%>");
18751 4 : parens.skip_until_found_close (parser);
18752 4 : return list;
18753 : }
18754 111 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18755 111 : if (strcmp (p, "teams") == 0)
18756 : kind = OMP_CLAUSE_BIND_TEAMS;
18757 72 : else if (strcmp (p, "parallel") == 0)
18758 : kind = OMP_CLAUSE_BIND_PARALLEL;
18759 35 : else if (strcmp (p, "thread") != 0)
18760 1 : goto invalid;
18761 110 : c_parser_consume_token (parser);
18762 110 : parens.skip_until_found_close (parser);
18763 : /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
18764 110 : c = build_omp_clause (loc, OMP_CLAUSE_BIND);
18765 110 : OMP_CLAUSE_BIND_KIND (c) = kind;
18766 110 : OMP_CLAUSE_CHAIN (c) = list;
18767 110 : return c;
18768 : }
18769 :
18770 :
18771 : /* OpenMP 2.5:
18772 : ordered
18773 :
18774 : OpenMP 4.5:
18775 : ordered ( constant-expression ) */
18776 :
18777 : static tree
18778 310 : c_parser_omp_clause_ordered (c_parser *parser, tree list)
18779 : {
18780 310 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
18781 :
18782 310 : tree c, num = NULL_TREE;
18783 310 : HOST_WIDE_INT n;
18784 310 : location_t loc = c_parser_peek_token (parser)->location;
18785 310 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18786 : {
18787 169 : matching_parens parens;
18788 169 : parens.consume_open (parser);
18789 169 : num = c_parser_expr_no_commas (parser, NULL).value;
18790 169 : parens.skip_until_found_close (parser);
18791 : }
18792 310 : if (num == error_mark_node)
18793 : return list;
18794 310 : if (num)
18795 : {
18796 169 : mark_exp_read (num);
18797 169 : num = c_fully_fold (num, false, NULL);
18798 338 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
18799 169 : || !tree_fits_shwi_p (num)
18800 169 : || (n = tree_to_shwi (num)) <= 0
18801 338 : || (int) n != n)
18802 : {
18803 0 : error_at (loc, "ordered argument needs positive "
18804 : "constant integer expression");
18805 0 : return list;
18806 : }
18807 : }
18808 310 : c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
18809 310 : OMP_CLAUSE_ORDERED_EXPR (c) = num;
18810 310 : OMP_CLAUSE_CHAIN (c) = list;
18811 310 : return c;
18812 : }
18813 :
18814 : /* OpenMP 2.5:
18815 : private ( variable-list ) */
18816 :
18817 : static tree
18818 745 : c_parser_omp_clause_private (c_parser *parser, tree list)
18819 : {
18820 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
18821 : }
18822 :
18823 : /* OpenMP 2.5:
18824 : reduction ( reduction-operator : variable-list )
18825 :
18826 : reduction-operator:
18827 : One of: + * - & ^ | && ||
18828 :
18829 : OpenMP 3.1:
18830 :
18831 : reduction-operator:
18832 : One of: + * - & ^ | && || max min
18833 :
18834 : OpenMP 4.0:
18835 :
18836 : reduction-operator:
18837 : One of: + * - & ^ | && ||
18838 : identifier
18839 :
18840 : OpenMP 5.0:
18841 : reduction ( reduction-modifier, reduction-operator : variable-list )
18842 : in_reduction ( reduction-operator : variable-list )
18843 : task_reduction ( reduction-operator : variable-list ) */
18844 :
18845 : static tree
18846 3093 : c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
18847 : bool is_omp, tree list)
18848 : {
18849 3093 : location_t clause_loc = c_parser_peek_token (parser)->location;
18850 3093 : matching_parens parens;
18851 3093 : if (parens.require_open (parser))
18852 : {
18853 3093 : bool task = false;
18854 3093 : bool inscan = false;
18855 3093 : enum tree_code code = ERROR_MARK;
18856 3093 : tree reduc_id = NULL_TREE;
18857 :
18858 3093 : if (kind == OMP_CLAUSE_REDUCTION && is_omp)
18859 : {
18860 1781 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
18861 1781 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18862 : {
18863 87 : c_parser_consume_token (parser);
18864 87 : c_parser_consume_token (parser);
18865 : }
18866 1694 : else if (c_parser_next_token_is (parser, CPP_NAME)
18867 1694 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18868 : {
18869 465 : const char *p
18870 465 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18871 465 : if (strcmp (p, "task") == 0)
18872 : task = true;
18873 285 : else if (strcmp (p, "inscan") == 0)
18874 : inscan = true;
18875 : if (task || inscan)
18876 : {
18877 465 : c_parser_consume_token (parser);
18878 465 : c_parser_consume_token (parser);
18879 : }
18880 : }
18881 : }
18882 :
18883 3093 : switch (c_parser_peek_token (parser)->type)
18884 : {
18885 : case CPP_PLUS:
18886 : code = PLUS_EXPR;
18887 : break;
18888 253 : case CPP_MULT:
18889 253 : code = MULT_EXPR;
18890 253 : break;
18891 157 : case CPP_MINUS:
18892 157 : if (is_omp)
18893 : {
18894 4 : location_t loc = c_parser_peek_token (parser)->location;
18895 4 : gcc_rich_location richloc (loc);
18896 4 : richloc.add_fixit_replace ("+");
18897 4 : warning_at (&richloc, OPT_Wdeprecated_openmp,
18898 : "%<-%> operator for reductions deprecated in "
18899 : "OpenMP 5.2");
18900 4 : }
18901 : code = MINUS_EXPR;
18902 : break;
18903 27 : case CPP_AND:
18904 27 : code = BIT_AND_EXPR;
18905 27 : break;
18906 14 : case CPP_XOR:
18907 14 : code = BIT_XOR_EXPR;
18908 14 : break;
18909 82 : case CPP_OR:
18910 82 : code = BIT_IOR_EXPR;
18911 82 : break;
18912 67 : case CPP_AND_AND:
18913 67 : code = TRUTH_ANDIF_EXPR;
18914 67 : break;
18915 78 : case CPP_OR_OR:
18916 78 : code = TRUTH_ORIF_EXPR;
18917 78 : break;
18918 253 : case CPP_NAME:
18919 253 : {
18920 253 : const char *p
18921 253 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18922 253 : if (strcmp (p, "min") == 0)
18923 : {
18924 : code = MIN_EXPR;
18925 : break;
18926 : }
18927 213 : if (strcmp (p, "max") == 0)
18928 : {
18929 : code = MAX_EXPR;
18930 : break;
18931 : }
18932 130 : reduc_id = c_parser_peek_token (parser)->value;
18933 130 : break;
18934 : }
18935 0 : default:
18936 0 : c_parser_error (parser,
18937 : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
18938 : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
18939 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18940 0 : return list;
18941 : }
18942 3093 : c_parser_consume_token (parser);
18943 3093 : reduc_id = c_omp_reduction_id (code, reduc_id);
18944 3093 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18945 : {
18946 3093 : tree nl, c;
18947 :
18948 3093 : nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
18949 6799 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18950 : {
18951 3706 : tree d = OMP_CLAUSE_DECL (c), type;
18952 3706 : if (TREE_CODE (d) != OMP_ARRAY_SECTION)
18953 3187 : type = TREE_TYPE (d);
18954 : else
18955 : {
18956 : int cnt = 0;
18957 : tree t;
18958 636 : for (t = d;
18959 1155 : TREE_CODE (t) == OMP_ARRAY_SECTION;
18960 636 : t = TREE_OPERAND (t, 0))
18961 636 : cnt++;
18962 519 : type = TREE_TYPE (t);
18963 1153 : while (cnt > 0)
18964 : {
18965 636 : if (TREE_CODE (type) != POINTER_TYPE
18966 399 : && TREE_CODE (type) != ARRAY_TYPE)
18967 : break;
18968 634 : type = TREE_TYPE (type);
18969 634 : cnt--;
18970 : }
18971 : }
18972 3799 : while (TREE_CODE (type) == ARRAY_TYPE)
18973 93 : type = TREE_TYPE (type);
18974 3706 : OMP_CLAUSE_REDUCTION_CODE (c) = code;
18975 3706 : if (task)
18976 212 : OMP_CLAUSE_REDUCTION_TASK (c) = 1;
18977 3494 : else if (inscan)
18978 400 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
18979 3706 : if (code == ERROR_MARK
18980 219 : || !(INTEGRAL_TYPE_P (type)
18981 3566 : || SCALAR_FLOAT_TYPE_P (type)
18982 : || TREE_CODE (type) == COMPLEX_TYPE))
18983 273 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
18984 546 : = c_omp_reduction_lookup (reduc_id,
18985 273 : TYPE_MAIN_VARIANT (type));
18986 : }
18987 :
18988 : list = nl;
18989 : }
18990 3093 : parens.skip_until_found_close (parser);
18991 : }
18992 : return list;
18993 : }
18994 :
18995 : /* OpenMP 2.5:
18996 : schedule ( schedule-kind )
18997 : schedule ( schedule-kind , expression )
18998 :
18999 : schedule-kind:
19000 : static | dynamic | guided | runtime | auto
19001 :
19002 : OpenMP 4.5:
19003 : schedule ( schedule-modifier : schedule-kind )
19004 : schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
19005 :
19006 : schedule-modifier:
19007 : simd
19008 : monotonic
19009 : nonmonotonic */
19010 :
19011 : static tree
19012 3469 : c_parser_omp_clause_schedule (c_parser *parser, tree list)
19013 : {
19014 3469 : tree c, t;
19015 3469 : location_t loc = c_parser_peek_token (parser)->location;
19016 3469 : int modifiers = 0, nmodifiers = 0;
19017 :
19018 3469 : matching_parens parens;
19019 3469 : if (!parens.require_open (parser))
19020 : return list;
19021 :
19022 3467 : c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
19023 :
19024 3467 : location_t comma = UNKNOWN_LOCATION;
19025 6948 : while (c_parser_next_token_is (parser, CPP_NAME))
19026 : {
19027 1780 : tree kind = c_parser_peek_token (parser)->value;
19028 1780 : const char *p = IDENTIFIER_POINTER (kind);
19029 1780 : if (strcmp ("simd", p) == 0)
19030 31 : OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
19031 1749 : else if (strcmp ("monotonic", p) == 0)
19032 74 : modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
19033 1675 : else if (strcmp ("nonmonotonic", p) == 0)
19034 84 : modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
19035 : else
19036 : break;
19037 189 : comma = UNKNOWN_LOCATION;
19038 189 : c_parser_consume_token (parser);
19039 189 : if (nmodifiers++ == 0
19040 367 : && c_parser_next_token_is (parser, CPP_COMMA))
19041 : {
19042 14 : comma = c_parser_peek_token (parser)->location;
19043 14 : c_parser_consume_token (parser);
19044 : }
19045 : else
19046 : {
19047 175 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
19048 175 : break;
19049 : }
19050 : }
19051 3467 : if (comma != UNKNOWN_LOCATION)
19052 3 : error_at (comma, "expected %<:%>");
19053 :
19054 3467 : if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
19055 : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
19056 : == (OMP_CLAUSE_SCHEDULE_MONOTONIC
19057 : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
19058 : {
19059 2 : error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
19060 : "specified");
19061 2 : modifiers = 0;
19062 : }
19063 :
19064 3467 : if (c_parser_next_token_is (parser, CPP_NAME))
19065 : {
19066 1708 : tree kind = c_parser_peek_token (parser)->value;
19067 1708 : const char *p = IDENTIFIER_POINTER (kind);
19068 :
19069 1708 : switch (p[0])
19070 : {
19071 169 : case 'd':
19072 169 : if (strcmp ("dynamic", p) != 0)
19073 0 : goto invalid_kind;
19074 169 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
19075 169 : break;
19076 :
19077 761 : case 'g':
19078 761 : if (strcmp ("guided", p) != 0)
19079 0 : goto invalid_kind;
19080 761 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
19081 761 : break;
19082 :
19083 777 : case 'r':
19084 777 : if (strcmp ("runtime", p) != 0)
19085 0 : goto invalid_kind;
19086 777 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
19087 777 : break;
19088 :
19089 1 : default:
19090 1 : goto invalid_kind;
19091 : }
19092 : }
19093 1759 : else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
19094 1078 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
19095 681 : else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
19096 680 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
19097 : else
19098 1 : goto invalid_kind;
19099 :
19100 3465 : c_parser_consume_token (parser);
19101 3465 : if (c_parser_next_token_is (parser, CPP_COMMA))
19102 : {
19103 1797 : location_t here;
19104 1797 : c_parser_consume_token (parser);
19105 :
19106 1797 : here = c_parser_peek_token (parser)->location;
19107 1797 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19108 1797 : expr = convert_lvalue_to_rvalue (here, expr, false, true);
19109 1797 : t = expr.value;
19110 1797 : t = c_fully_fold (t, false, NULL);
19111 :
19112 1797 : if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
19113 1 : error_at (here, "schedule %<runtime%> does not take "
19114 : "a %<chunk_size%> parameter");
19115 1796 : else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
19116 0 : error_at (here,
19117 : "schedule %<auto%> does not take "
19118 : "a %<chunk_size%> parameter");
19119 1796 : else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
19120 1796 : || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
19121 : {
19122 : /* Attempt to statically determine when the number isn't
19123 : positive. */
19124 1795 : tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
19125 1795 : build_int_cst (TREE_TYPE (t), 0));
19126 1795 : protected_set_expr_location (s, loc);
19127 1795 : if (s == boolean_true_node)
19128 : {
19129 2 : warning_at (loc, OPT_Wopenmp,
19130 : "chunk size value must be positive");
19131 2 : t = integer_one_node;
19132 : }
19133 1795 : OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
19134 : }
19135 : else
19136 1 : c_parser_error (parser, "expected integer expression");
19137 :
19138 1797 : parens.skip_until_found_close (parser);
19139 : }
19140 : else
19141 1668 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
19142 : "expected %<,%> or %<)%>");
19143 :
19144 6930 : OMP_CLAUSE_SCHEDULE_KIND (c)
19145 6930 : = (enum omp_clause_schedule_kind)
19146 3465 : (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
19147 :
19148 3465 : check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
19149 3465 : OMP_CLAUSE_CHAIN (c) = list;
19150 3465 : return c;
19151 :
19152 2 : invalid_kind:
19153 2 : c_parser_error (parser, "invalid schedule kind");
19154 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
19155 2 : return list;
19156 : }
19157 :
19158 : /* OpenMP 2.5:
19159 : shared ( variable-list ) */
19160 :
19161 : static tree
19162 691 : c_parser_omp_clause_shared (c_parser *parser, tree list)
19163 : {
19164 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
19165 : }
19166 :
19167 : /* OpenMP 3.0:
19168 : untied */
19169 :
19170 : static tree
19171 97 : c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
19172 : {
19173 97 : tree c;
19174 :
19175 : /* FIXME: Should we allow duplicates? */
19176 97 : check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
19177 :
19178 97 : c = build_omp_clause (c_parser_peek_token (parser)->location,
19179 : OMP_CLAUSE_UNTIED);
19180 97 : OMP_CLAUSE_CHAIN (c) = list;
19181 :
19182 97 : return c;
19183 : }
19184 :
19185 : /* OpenMP 4.0:
19186 : inbranch
19187 : notinbranch */
19188 :
19189 : static tree
19190 205 : c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
19191 : enum omp_clause_code code, tree list)
19192 : {
19193 205 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
19194 :
19195 205 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19196 205 : OMP_CLAUSE_CHAIN (c) = list;
19197 :
19198 205 : return c;
19199 : }
19200 :
19201 : /* OpenMP 4.0:
19202 : parallel
19203 : for
19204 : sections
19205 : taskgroup */
19206 :
19207 : static tree
19208 379 : c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
19209 : enum omp_clause_code code, tree list)
19210 : {
19211 379 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19212 379 : OMP_CLAUSE_CHAIN (c) = list;
19213 :
19214 379 : return c;
19215 : }
19216 :
19217 : /* OpenMP 4.5:
19218 : nogroup */
19219 :
19220 : static tree
19221 18 : c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
19222 : {
19223 18 : check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup");
19224 18 : tree c = build_omp_clause (c_parser_peek_token (parser)->location,
19225 : OMP_CLAUSE_NOGROUP);
19226 18 : OMP_CLAUSE_CHAIN (c) = list;
19227 18 : return c;
19228 : }
19229 :
19230 : /* OpenMP 4.5:
19231 : simd
19232 : threads */
19233 :
19234 : static tree
19235 103 : c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
19236 : enum omp_clause_code code, tree list)
19237 : {
19238 103 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
19239 103 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
19240 103 : OMP_CLAUSE_CHAIN (c) = list;
19241 103 : return c;
19242 : }
19243 :
19244 : /* OpenMP 4.0:
19245 : num_teams ( expression )
19246 :
19247 : OpenMP 5.1:
19248 : num_teams ( expression : expression ) */
19249 :
19250 : static tree
19251 190 : c_parser_omp_clause_num_teams (c_parser *parser, tree list)
19252 : {
19253 190 : location_t num_teams_loc = c_parser_peek_token (parser)->location;
19254 190 : matching_parens parens;
19255 190 : if (parens.require_open (parser))
19256 : {
19257 190 : location_t upper_loc = c_parser_peek_token (parser)->location;
19258 190 : location_t lower_loc = UNKNOWN_LOCATION;
19259 190 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19260 190 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
19261 190 : tree c, upper = expr.value, lower = NULL_TREE;
19262 190 : upper = c_fully_fold (upper, false, NULL);
19263 :
19264 190 : if (c_parser_next_token_is (parser, CPP_COLON))
19265 : {
19266 51 : c_parser_consume_token (parser);
19267 51 : lower_loc = upper_loc;
19268 51 : lower = upper;
19269 51 : upper_loc = c_parser_peek_token (parser)->location;
19270 51 : expr = c_parser_expr_no_commas (parser, NULL);
19271 51 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
19272 51 : upper = expr.value;
19273 51 : upper = c_fully_fold (upper, false, NULL);
19274 : }
19275 :
19276 190 : parens.skip_until_found_close (parser);
19277 :
19278 380 : if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
19279 380 : || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
19280 : {
19281 0 : c_parser_error (parser, "expected integer expression");
19282 0 : return list;
19283 : }
19284 :
19285 : /* Attempt to statically determine when the number isn't positive. */
19286 190 : c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
19287 190 : build_int_cst (TREE_TYPE (upper), 0));
19288 190 : protected_set_expr_location (c, upper_loc);
19289 190 : if (c == boolean_true_node)
19290 : {
19291 4 : warning_at (upper_loc, OPT_Wopenmp,
19292 : "%<num_teams%> value must be positive");
19293 4 : upper = integer_one_node;
19294 : }
19295 190 : if (lower)
19296 : {
19297 51 : c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
19298 51 : build_int_cst (TREE_TYPE (lower), 0));
19299 51 : protected_set_expr_location (c, lower_loc);
19300 51 : if (c == boolean_true_node)
19301 : {
19302 2 : warning_at (lower_loc, OPT_Wopenmp,
19303 : "%<num_teams%> value must be positive");
19304 2 : lower = NULL_TREE;
19305 : }
19306 49 : else if (TREE_CODE (lower) == INTEGER_CST
19307 7 : && TREE_CODE (upper) == INTEGER_CST
19308 54 : && tree_int_cst_lt (upper, lower))
19309 : {
19310 2 : warning_at (lower_loc, OPT_Wopenmp,
19311 : "%<num_teams%> lower bound %qE bigger than upper "
19312 : "bound %qE", lower, upper);
19313 2 : lower = NULL_TREE;
19314 : }
19315 : }
19316 :
19317 190 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
19318 :
19319 190 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
19320 190 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
19321 190 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
19322 190 : OMP_CLAUSE_CHAIN (c) = list;
19323 190 : list = c;
19324 : }
19325 :
19326 : return list;
19327 : }
19328 :
19329 : /* OpenMP 4.0:
19330 : thread_limit ( expression ) */
19331 :
19332 : static tree
19333 154 : c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
19334 : {
19335 154 : location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
19336 154 : matching_parens parens;
19337 154 : if (parens.require_open (parser))
19338 : {
19339 154 : location_t expr_loc = c_parser_peek_token (parser)->location;
19340 154 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19341 154 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19342 154 : tree c, t = expr.value;
19343 154 : t = c_fully_fold (t, false, NULL);
19344 :
19345 154 : parens.skip_until_found_close (parser);
19346 :
19347 154 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
19348 : {
19349 0 : c_parser_error (parser, "expected integer expression");
19350 0 : return list;
19351 : }
19352 :
19353 : /* Attempt to statically determine when the number isn't positive. */
19354 154 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
19355 154 : build_int_cst (TREE_TYPE (t), 0));
19356 154 : protected_set_expr_location (c, expr_loc);
19357 154 : if (c == boolean_true_node)
19358 : {
19359 0 : warning_at (expr_loc, OPT_Wopenmp,
19360 : "%<thread_limit%> value must be positive");
19361 0 : t = integer_one_node;
19362 : }
19363 :
19364 154 : check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
19365 : "thread_limit");
19366 :
19367 154 : c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
19368 154 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
19369 154 : OMP_CLAUSE_CHAIN (c) = list;
19370 154 : list = c;
19371 : }
19372 :
19373 : return list;
19374 : }
19375 :
19376 : /* OpenMP 4.0:
19377 : aligned ( variable-list )
19378 : aligned ( variable-list : constant-expression ) */
19379 :
19380 : static tree
19381 228 : c_parser_omp_clause_aligned (c_parser *parser, tree list)
19382 : {
19383 228 : location_t clause_loc = c_parser_peek_token (parser)->location;
19384 228 : tree nl, c;
19385 :
19386 228 : matching_parens parens;
19387 228 : if (!parens.require_open (parser))
19388 : return list;
19389 :
19390 228 : nl = c_parser_omp_variable_list (parser, clause_loc,
19391 : OMP_CLAUSE_ALIGNED, list);
19392 :
19393 228 : if (c_parser_next_token_is (parser, CPP_COLON))
19394 : {
19395 212 : c_parser_consume_token (parser);
19396 212 : location_t expr_loc = c_parser_peek_token (parser)->location;
19397 212 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19398 212 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19399 212 : tree alignment = expr.value;
19400 212 : alignment = c_fully_fold (alignment, false, NULL);
19401 212 : if (TREE_CODE (alignment) != INTEGER_CST
19402 210 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
19403 422 : || tree_int_cst_sgn (alignment) != 1)
19404 : {
19405 4 : error_at (clause_loc, "%<aligned%> clause alignment expression must "
19406 : "be positive constant integer expression");
19407 4 : alignment = NULL_TREE;
19408 : }
19409 :
19410 444 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19411 232 : OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
19412 : }
19413 :
19414 228 : parens.skip_until_found_close (parser);
19415 228 : return nl;
19416 : }
19417 :
19418 : /* OpenMP 5.0:
19419 : allocate ( variable-list )
19420 : allocate ( expression : variable-list )
19421 :
19422 : OpenMP 5.1:
19423 : allocate ( allocator-modifier : variable-list )
19424 : allocate ( allocator-modifier , allocator-modifier : variable-list )
19425 :
19426 : allocator-modifier:
19427 : allocator ( expression )
19428 : align ( expression ) */
19429 :
19430 : static tree
19431 479 : c_parser_omp_clause_allocate (c_parser *parser, tree list)
19432 : {
19433 479 : location_t clause_loc = c_parser_peek_token (parser)->location;
19434 479 : tree nl, c;
19435 479 : tree allocator = NULL_TREE;
19436 479 : tree align = NULL_TREE;
19437 :
19438 479 : matching_parens parens;
19439 479 : if (!parens.require_open (parser))
19440 : return list;
19441 :
19442 479 : if ((c_parser_next_token_is_not (parser, CPP_NAME)
19443 5 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
19444 479 : || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
19445 460 : && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
19446 : {
19447 214 : bool has_modifiers = false;
19448 214 : tree orig_type = NULL_TREE;
19449 214 : if (c_parser_next_token_is (parser, CPP_NAME)
19450 214 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19451 : {
19452 73 : unsigned int n = 3;
19453 73 : const char *p
19454 73 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19455 29 : if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
19456 71 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
19457 144 : && (c_parser_peek_nth_token_raw (parser, n)->type
19458 : == CPP_CLOSE_PAREN))
19459 : {
19460 71 : if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19461 : == CPP_COLON)
19462 : has_modifiers = true;
19463 37 : else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19464 : == CPP_COMMA
19465 37 : && (c_parser_peek_nth_token_raw (parser, n + 2)->type
19466 : == CPP_NAME)
19467 74 : && (c_parser_peek_nth_token_raw (parser, n + 3)->type
19468 : == CPP_OPEN_PAREN))
19469 : {
19470 37 : c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
19471 37 : const char *q = IDENTIFIER_POINTER (tok->value);
19472 37 : n += 4;
19473 37 : if ((strcmp (q, "allocator") == 0
19474 24 : || strcmp (q, "align") == 0)
19475 37 : && c_parser_check_balanced_raw_token_sequence (parser,
19476 : &n)
19477 37 : && (c_parser_peek_nth_token_raw (parser, n)->type
19478 : == CPP_CLOSE_PAREN)
19479 74 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
19480 : == CPP_COLON))
19481 : has_modifiers = true;
19482 : }
19483 : }
19484 : if (has_modifiers)
19485 : {
19486 71 : c_parser_consume_token (parser);
19487 71 : matching_parens parens2;
19488 71 : parens2.require_open (parser);
19489 71 : location_t expr_loc = c_parser_peek_token (parser)->location;
19490 71 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19491 71 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19492 71 : if (expr.value == error_mark_node)
19493 : ;
19494 70 : else if (strcmp (p, "allocator") == 0)
19495 : {
19496 43 : allocator = expr.value;
19497 43 : allocator = c_fully_fold (allocator, false, NULL);
19498 3 : orig_type = expr.original_type
19499 43 : ? expr.original_type : TREE_TYPE (allocator);
19500 43 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19501 : }
19502 : else
19503 : {
19504 27 : align = expr.value;
19505 27 : align = c_fully_fold (align, false, NULL);
19506 : }
19507 71 : parens2.skip_until_found_close (parser);
19508 71 : if (c_parser_next_token_is (parser, CPP_COMMA))
19509 : {
19510 37 : c_parser_consume_token (parser);
19511 37 : c_token *tok = c_parser_peek_token (parser);
19512 37 : const char *q = "";
19513 37 : if (c_parser_next_token_is (parser, CPP_NAME))
19514 37 : q = IDENTIFIER_POINTER (tok->value);
19515 37 : if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
19516 : {
19517 0 : c_parser_error (parser, "expected %<allocator%> or "
19518 : "%<align%>");
19519 0 : parens.skip_until_found_close (parser);
19520 2 : return list;
19521 : }
19522 37 : else if (strcmp (p, q) == 0)
19523 : {
19524 2 : error_at (tok->location, "duplicate %qs modifier", p);
19525 2 : parens.skip_until_found_close (parser);
19526 2 : return list;
19527 : }
19528 35 : c_parser_consume_token (parser);
19529 35 : if (!parens2.require_open (parser))
19530 : {
19531 0 : parens.skip_until_found_close (parser);
19532 0 : return list;
19533 : }
19534 35 : expr_loc = c_parser_peek_token (parser)->location;
19535 35 : expr = c_parser_expr_no_commas (parser, NULL);
19536 35 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19537 : true);
19538 35 : if (strcmp (q, "allocator") == 0)
19539 : {
19540 12 : allocator = expr.value;
19541 12 : allocator = c_fully_fold (allocator, false, NULL);
19542 2 : orig_type = expr.original_type
19543 12 : ? expr.original_type : TREE_TYPE (allocator);
19544 12 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19545 : }
19546 : else
19547 : {
19548 23 : align = expr.value;
19549 23 : align = c_fully_fold (align, false, NULL);
19550 : }
19551 35 : parens2.skip_until_found_close (parser);
19552 : }
19553 : }
19554 : }
19555 71 : if (!has_modifiers)
19556 : {
19557 143 : location_t expr_loc = c_parser_peek_token (parser)->location;
19558 143 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19559 143 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19560 143 : allocator = expr.value;
19561 143 : allocator = c_fully_fold (allocator, false, NULL);
19562 7 : orig_type = expr.original_type
19563 143 : ? expr.original_type : TREE_TYPE (allocator);
19564 143 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19565 : }
19566 212 : if (allocator
19567 212 : && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
19568 195 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
19569 386 : || (TYPE_NAME (orig_type)
19570 193 : != get_identifier ("omp_allocator_handle_t"))))
19571 : {
19572 8 : error_at (clause_loc, "%<allocate%> clause allocator expression "
19573 : "has type %qT rather than "
19574 : "%<omp_allocator_handle_t%>",
19575 4 : TREE_TYPE (allocator));
19576 4 : allocator = NULL_TREE;
19577 : }
19578 212 : if (align
19579 212 : && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
19580 48 : || !tree_fits_uhwi_p (align)
19581 47 : || !integer_pow2p (align)))
19582 : {
19583 4 : error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
19584 : "argument needs to be positive constant "
19585 : "power of two integer expression");
19586 4 : align = NULL_TREE;
19587 : }
19588 212 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19589 : {
19590 0 : parens.skip_until_found_close (parser);
19591 0 : return list;
19592 : }
19593 : }
19594 :
19595 477 : nl = c_parser_omp_variable_list (parser, clause_loc,
19596 : OMP_CLAUSE_ALLOCATE, list);
19597 :
19598 477 : if (allocator || align)
19599 493 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19600 : {
19601 290 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
19602 290 : OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
19603 : }
19604 :
19605 477 : parens.skip_until_found_close (parser);
19606 477 : return nl;
19607 : }
19608 :
19609 : /* OpenMP 5.0:
19610 : uses_allocators ( allocator-list )
19611 :
19612 : allocator-list:
19613 : allocator
19614 : allocator , allocator-list
19615 : allocator ( traits-array )
19616 : allocator ( traits-array ) , allocator-list
19617 :
19618 : Deprecated in 5.2, removed in 6.0: 'allocator(trait-array)' syntax.
19619 :
19620 : OpenMP 5.2:
19621 :
19622 : uses_allocators ( modifier : allocator-list )
19623 : uses_allocators ( modifier , modifier : allocator-list )
19624 :
19625 : OpenMP 6.0:
19626 : uses_allocators ( [modifier-list :] allocator-list [; ...] )
19627 :
19628 : modifier:
19629 : traits ( traits-array )
19630 : memspace ( mem-space-handle ) */
19631 :
19632 : static tree
19633 30 : c_parser_omp_clause_uses_allocators (c_parser *parser, tree list)
19634 : {
19635 30 : location_t clause_loc = c_parser_peek_token (parser)->location;
19636 30 : tree nl = list;
19637 30 : matching_parens parens;
19638 30 : if (!parens.require_open (parser))
19639 : return list;
19640 :
19641 30 : parse_next:
19642 :
19643 34 : bool has_modifiers = false;
19644 34 : bool seen_allocators = false;
19645 34 : tree memspace_expr = NULL_TREE;
19646 34 : tree traits_var = NULL_TREE;
19647 :
19648 34 : if (c_parser_next_token_is (parser, CPP_NAME)
19649 34 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19650 : {
19651 22 : unsigned int n = 3;
19652 22 : const char *p
19653 22 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19654 17 : if ((strcmp (p, "traits") == 0 || strcmp (p, "memspace") == 0)
19655 13 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
19656 35 : && (c_parser_peek_nth_token_raw (parser, n)->type
19657 : == CPP_CLOSE_PAREN))
19658 : {
19659 13 : if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19660 : == CPP_COLON)
19661 : has_modifiers = true;
19662 2 : else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19663 : == CPP_COMMA
19664 2 : && (c_parser_peek_nth_token_raw (parser, n + 2)->type
19665 : == CPP_NAME)
19666 4 : && (c_parser_peek_nth_token_raw (parser, n + 3)->type
19667 : == CPP_OPEN_PAREN))
19668 : {
19669 2 : c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
19670 2 : const char *q = IDENTIFIER_POINTER (tok->value);
19671 2 : n += 4;
19672 2 : if ((strcmp (q, "traits") == 0
19673 1 : || strcmp (q, "memspace") == 0)
19674 2 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
19675 4 : && (c_parser_peek_nth_token_raw (parser, n)->type
19676 : == CPP_CLOSE_PAREN))
19677 : {
19678 2 : if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19679 : == CPP_COLON)
19680 1 : has_modifiers = true;
19681 2 : if ((c_parser_peek_nth_token_raw (parser, n + 1)->type
19682 : == CPP_COMMA)
19683 2 : && (c_parser_peek_nth_token_raw (parser, n + 2)->type
19684 : == CPP_NAME))
19685 : {
19686 1 : c_token *tok
19687 1 : = c_parser_peek_nth_token_raw (parser, n + 2);
19688 1 : const char *m = IDENTIFIER_POINTER (tok->value);
19689 1 : if (strcmp (p, m) == 0 || strcmp (q, m) == 0)
19690 : {
19691 1 : error_at (tok->location, "duplicate %qs modifier", m);
19692 1 : goto end;
19693 : }
19694 : }
19695 : }
19696 : }
19697 : }
19698 1 : if (has_modifiers)
19699 : {
19700 12 : c_parser_consume_token (parser);
19701 12 : matching_parens parens2;
19702 12 : parens2.require_open (parser);
19703 12 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19704 12 : if (expr.value == error_mark_node)
19705 : ;
19706 9 : else if (strcmp (p, "traits") == 0)
19707 : {
19708 4 : traits_var = expr.value;
19709 4 : traits_var = c_fully_fold (traits_var, false, NULL);
19710 : }
19711 : else
19712 : {
19713 5 : memspace_expr = expr.value;
19714 5 : memspace_expr = c_fully_fold (memspace_expr, false, NULL);
19715 : }
19716 12 : parens2.skip_until_found_close (parser);
19717 12 : if (c_parser_next_token_is (parser, CPP_COMMA))
19718 : {
19719 1 : c_parser_consume_token (parser);
19720 1 : c_token *tok = c_parser_peek_token (parser);
19721 1 : const char *q = "";
19722 1 : if (c_parser_next_token_is (parser, CPP_NAME))
19723 1 : q = IDENTIFIER_POINTER (tok->value);
19724 1 : if (strcmp (q, "traits") != 0 && strcmp (q, "memspace") != 0)
19725 : {
19726 0 : c_parser_error (parser, "expected %<traits%> or "
19727 : "%<memspace%>");
19728 0 : parens.skip_until_found_close (parser);
19729 0 : return list;
19730 : }
19731 1 : else if (strcmp (p, q) == 0)
19732 : {
19733 0 : error_at (tok->location, "duplicate %qs modifier", p);
19734 0 : parens.skip_until_found_close (parser);
19735 0 : return list;
19736 : }
19737 1 : c_parser_consume_token (parser);
19738 1 : if (!parens2.require_open (parser))
19739 : {
19740 0 : parens.skip_until_found_close (parser);
19741 0 : return list;
19742 : }
19743 1 : expr = c_parser_expr_no_commas (parser, NULL);
19744 1 : if (strcmp (q, "traits") == 0)
19745 : {
19746 0 : traits_var = expr.value;
19747 0 : traits_var = c_fully_fold (traits_var, false, NULL);
19748 : }
19749 : else
19750 : {
19751 1 : memspace_expr = expr.value;
19752 1 : memspace_expr = c_fully_fold (memspace_expr, false, NULL);
19753 : }
19754 1 : parens2.skip_until_found_close (parser);
19755 : }
19756 12 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19757 0 : goto end;
19758 : }
19759 : }
19760 :
19761 41 : while (c_parser_next_token_is (parser, CPP_NAME))
19762 : {
19763 41 : location_t alloc_loc = c_parser_peek_token (parser)->location;
19764 41 : c_token *tok = c_parser_peek_token (parser);
19765 41 : const char *tok_s = IDENTIFIER_POINTER (tok->value);
19766 41 : tree t = lookup_name (tok->value);
19767 41 : if (t == NULL_TREE)
19768 : {
19769 3 : undeclared_variable (tok->location, tok->value);
19770 3 : t = error_mark_node;
19771 : }
19772 41 : c_parser_consume_token (parser);
19773 :
19774 : /* Legacy traits syntax. */
19775 41 : tree legacy_traits = NULL_TREE;
19776 41 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
19777 13 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME
19778 54 : && c_parser_peek_nth_token_raw (parser, 3)->type == CPP_CLOSE_PAREN)
19779 : {
19780 13 : matching_parens parens2;
19781 13 : parens2.require_open (parser);
19782 13 : const char *tok_a
19783 13 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19784 13 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19785 13 : location_t close_loc = c_parser_peek_token (parser)->location;
19786 13 : parens2.skip_until_found_close (parser);
19787 :
19788 13 : if (has_modifiers)
19789 : {
19790 2 : error_at (make_location (alloc_loc, alloc_loc, close_loc),
19791 : "legacy %<%s(%s)%> traits syntax not allowed in "
19792 : "%<uses_allocators%> clause when using modifiers",
19793 : tok_s, tok_a);
19794 3 : goto end;
19795 : }
19796 11 : legacy_traits = c_fully_fold (expr.value, false, NULL);
19797 11 : if (legacy_traits == error_mark_node)
19798 1 : goto end;
19799 :
19800 10 : gcc_rich_location richloc (make_location (alloc_loc, alloc_loc, close_loc));
19801 10 : if (nl == list)
19802 : {
19803 : /* Fixit only works well if it is the only first item. */
19804 8 : richloc.add_fixit_replace (alloc_loc, "traits");
19805 8 : richloc.add_fixit_insert_after (close_loc, ": ");
19806 8 : richloc.add_fixit_insert_after (close_loc, tok_s);
19807 : }
19808 10 : warning_at (&richloc, OPT_Wdeprecated_openmp,
19809 : "the specification of arguments to %<uses_allocators%> "
19810 : "where each item is of the form %<allocator(traits)%> is "
19811 : "deprecated since OpenMP 5.2");
19812 10 : }
19813 :
19814 38 : if (seen_allocators && has_modifiers)
19815 : {
19816 2 : error_at (c_parser_peek_token (parser)->location,
19817 : "%<uses_allocators%> clause only accepts a single "
19818 : "allocator when using modifiers");
19819 2 : goto end;
19820 : }
19821 36 : seen_allocators = true;
19822 :
19823 36 : tree c = build_omp_clause (clause_loc,
19824 : OMP_CLAUSE_USES_ALLOCATORS);
19825 36 : OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c) = t;
19826 36 : OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (c) = memspace_expr;
19827 36 : OMP_CLAUSE_USES_ALLOCATORS_TRAITS (c) = (legacy_traits
19828 36 : ? legacy_traits : traits_var);
19829 36 : OMP_CLAUSE_CHAIN (c) = nl;
19830 36 : nl = c;
19831 :
19832 36 : if (c_parser_next_token_is (parser, CPP_COMMA))
19833 8 : c_parser_consume_token (parser);
19834 : else
19835 : break;
19836 : }
19837 :
19838 28 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
19839 : {
19840 4 : c_parser_consume_token (parser);
19841 4 : goto parse_next;
19842 : }
19843 :
19844 24 : end:
19845 30 : parens.skip_until_found_close (parser);
19846 30 : return nl;
19847 : }
19848 :
19849 : /* OpenMP 4.0:
19850 : linear ( variable-list )
19851 : linear ( variable-list : expression )
19852 :
19853 : OpenMP 4.5:
19854 : linear ( modifier ( variable-list ) )
19855 : linear ( modifier ( variable-list ) : expression )
19856 :
19857 : modifier:
19858 : val
19859 :
19860 : OpenMP 5.2:
19861 : linear ( variable-list : modifiers-list )
19862 :
19863 : modifiers:
19864 : val
19865 : step ( expression ) */
19866 :
19867 : static tree
19868 476 : c_parser_omp_clause_linear (c_parser *parser, tree list)
19869 : {
19870 476 : location_t clause_loc = c_parser_peek_token (parser)->location;
19871 476 : location_t rm1_loc = UNKNOWN_LOCATION, rm2_loc = UNKNOWN_LOCATION;
19872 476 : location_t after_colon_loc = UNKNOWN_LOCATION;
19873 476 : tree nl, c, step;
19874 476 : enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
19875 476 : bool old_linear_modifier = false;
19876 :
19877 476 : matching_parens parens;
19878 476 : if (!parens.require_open (parser))
19879 : return list;
19880 :
19881 476 : if (c_parser_next_token_is (parser, CPP_NAME))
19882 : {
19883 476 : c_token *tok = c_parser_peek_token (parser);
19884 476 : const char *p = IDENTIFIER_POINTER (tok->value);
19885 476 : if (strcmp ("val", p) == 0)
19886 12 : kind = OMP_CLAUSE_LINEAR_VAL;
19887 476 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
19888 : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19889 12 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19890 : {
19891 12 : old_linear_modifier = true;
19892 12 : rm1_loc = make_location (tok->location, tok->location,
19893 12 : c_parser_peek_2nd_token (parser)->location);
19894 12 : c_parser_consume_token (parser);
19895 12 : c_parser_consume_token (parser);
19896 : }
19897 : }
19898 :
19899 476 : nl = c_parser_omp_variable_list (parser, clause_loc,
19900 : OMP_CLAUSE_LINEAR, list);
19901 :
19902 476 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19903 : {
19904 12 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
19905 12 : rm2_loc = c_parser_peek_token (parser)->location;
19906 12 : parens.skip_until_found_close (parser);
19907 : }
19908 :
19909 476 : if (c_parser_next_token_is (parser, CPP_COLON))
19910 : {
19911 349 : c_parser_consume_token (parser);
19912 349 : location_t expr_loc = c_parser_peek_token (parser)->location;
19913 349 : after_colon_loc = expr_loc;
19914 349 : bool has_modifiers = false;
19915 349 : if (kind == OMP_CLAUSE_LINEAR_DEFAULT
19916 687 : && c_parser_next_token_is (parser, CPP_NAME))
19917 : {
19918 74 : c_token *tok = c_parser_peek_token (parser);
19919 74 : const char *p = IDENTIFIER_POINTER (tok->value);
19920 74 : unsigned int pos = 0;
19921 74 : if (strcmp ("val", p) == 0)
19922 9 : pos = 2;
19923 65 : else if (strcmp ("step", p) == 0
19924 65 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19925 : {
19926 13 : pos = 3;
19927 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &pos)
19928 13 : && (c_parser_peek_nth_token_raw (parser, pos)->type
19929 : == CPP_CLOSE_PAREN))
19930 13 : ++pos;
19931 : else
19932 0 : pos = 0;
19933 : }
19934 74 : if (pos)
19935 : {
19936 22 : tok = c_parser_peek_nth_token_raw (parser, pos);
19937 22 : if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
19938 19 : has_modifiers = true;
19939 : }
19940 : }
19941 74 : if (has_modifiers)
19942 : {
19943 : step = NULL_TREE;
19944 29 : while (c_parser_next_token_is (parser, CPP_NAME))
19945 : {
19946 29 : c_token *tok = c_parser_peek_token (parser);
19947 29 : const char *p = IDENTIFIER_POINTER (tok->value);
19948 29 : if (strcmp ("val", p) == 0)
19949 : {
19950 11 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19951 : error_at (tok->location, "multiple linear modifiers");
19952 11 : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19953 11 : c_parser_consume_token (parser);
19954 : }
19955 18 : else if (strcmp ("step", p) == 0)
19956 : {
19957 18 : c_parser_consume_token (parser);
19958 18 : matching_parens parens2;
19959 18 : if (parens2.require_open (parser))
19960 : {
19961 18 : if (step)
19962 0 : error_at (tok->location,
19963 : "multiple %<step%> modifiers");
19964 18 : expr_loc = c_parser_peek_token (parser)->location;
19965 18 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19966 18 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19967 : true);
19968 18 : step = c_fully_fold (expr.value, false, NULL);
19969 18 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19970 : {
19971 0 : error_at (clause_loc, "%<linear%> clause step "
19972 : "expression must be integral");
19973 0 : step = integer_one_node;
19974 : }
19975 18 : parens2.skip_until_found_close (parser);
19976 : }
19977 : else
19978 : break;
19979 : }
19980 : else
19981 : break;
19982 29 : if (c_parser_next_token_is (parser, CPP_COMMA))
19983 : {
19984 10 : c_parser_consume_token (parser);
19985 10 : continue;
19986 : }
19987 : break;
19988 : }
19989 19 : if (!step)
19990 1 : step = integer_one_node;
19991 : }
19992 : else
19993 : {
19994 330 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19995 330 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19996 330 : step = c_fully_fold (expr.value, false, NULL);
19997 330 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19998 : {
19999 2 : error_at (clause_loc, "%<linear%> clause step expression must "
20000 : "be integral");
20001 2 : step = integer_one_node;
20002 : }
20003 : }
20004 :
20005 : }
20006 : else
20007 127 : step = integer_one_node;
20008 :
20009 961 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20010 : {
20011 485 : OMP_CLAUSE_LINEAR_STEP (c) = step;
20012 485 : OMP_CLAUSE_LINEAR_KIND (c) = kind;
20013 485 : OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
20014 : }
20015 :
20016 476 : if (old_linear_modifier)
20017 : {
20018 12 : gcc_rich_location richloc (clause_loc);
20019 12 : if (rm2_loc != UNKNOWN_LOCATION)
20020 : {
20021 12 : richloc.add_fixit_remove (rm1_loc);
20022 12 : if (after_colon_loc != UNKNOWN_LOCATION)
20023 : {
20024 11 : richloc.add_fixit_remove (rm2_loc);
20025 11 : richloc.add_fixit_insert_before (after_colon_loc, "val, step (");
20026 11 : location_t close_loc = c_parser_peek_token (parser)->location;
20027 11 : richloc.add_fixit_insert_before (close_loc, ")");
20028 : }
20029 : else
20030 1 : richloc.add_fixit_replace (rm2_loc, " : val");
20031 : }
20032 12 : warning_at (&richloc, OPT_Wdeprecated_openmp,
20033 : "specifying the list items as arguments to the "
20034 : "modifiers is deprecated since OpenMP 5.2");
20035 12 : }
20036 :
20037 476 : parens.skip_until_found_close (parser);
20038 476 : return nl;
20039 : }
20040 :
20041 : /* OpenMP 5.0:
20042 : nontemporal ( variable-list ) */
20043 :
20044 : static tree
20045 121 : c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
20046 : {
20047 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_NONTEMPORAL, list);
20048 : }
20049 :
20050 : /* OpenMP 4.0:
20051 : safelen ( constant-expression ) */
20052 :
20053 : static tree
20054 227 : c_parser_omp_clause_safelen (c_parser *parser, tree list)
20055 : {
20056 227 : location_t clause_loc = c_parser_peek_token (parser)->location;
20057 227 : tree c, t;
20058 :
20059 227 : matching_parens parens;
20060 227 : if (!parens.require_open (parser))
20061 : return list;
20062 :
20063 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
20064 227 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20065 227 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20066 227 : t = expr.value;
20067 227 : t = c_fully_fold (t, false, NULL);
20068 227 : if (TREE_CODE (t) != INTEGER_CST
20069 225 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
20070 452 : || tree_int_cst_sgn (t) != 1)
20071 : {
20072 4 : error_at (clause_loc, "%<safelen%> clause expression must "
20073 : "be positive constant integer expression");
20074 4 : t = NULL_TREE;
20075 : }
20076 :
20077 227 : parens.skip_until_found_close (parser);
20078 227 : if (t == NULL_TREE || t == error_mark_node)
20079 : return list;
20080 :
20081 223 : check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen");
20082 :
20083 223 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
20084 223 : OMP_CLAUSE_SAFELEN_EXPR (c) = t;
20085 223 : OMP_CLAUSE_CHAIN (c) = list;
20086 223 : return c;
20087 : }
20088 :
20089 : /* OpenMP 4.0:
20090 : simdlen ( constant-expression ) */
20091 :
20092 : static tree
20093 324 : c_parser_omp_clause_simdlen (c_parser *parser, tree list)
20094 : {
20095 324 : location_t clause_loc = c_parser_peek_token (parser)->location;
20096 324 : tree c, t;
20097 :
20098 324 : matching_parens parens;
20099 324 : if (!parens.require_open (parser))
20100 : return list;
20101 :
20102 324 : location_t expr_loc = c_parser_peek_token (parser)->location;
20103 324 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20104 324 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20105 324 : t = expr.value;
20106 324 : t = c_fully_fold (t, false, NULL);
20107 324 : if (TREE_CODE (t) != INTEGER_CST
20108 322 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
20109 646 : || tree_int_cst_sgn (t) != 1)
20110 : {
20111 4 : error_at (clause_loc, "%<simdlen%> clause expression must "
20112 : "be positive constant integer expression");
20113 4 : t = NULL_TREE;
20114 : }
20115 :
20116 324 : parens.skip_until_found_close (parser);
20117 324 : if (t == NULL_TREE || t == error_mark_node)
20118 : return list;
20119 :
20120 320 : check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen");
20121 :
20122 320 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
20123 320 : OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
20124 320 : OMP_CLAUSE_CHAIN (c) = list;
20125 320 : return c;
20126 : }
20127 :
20128 : /* OpenMP 4.5:
20129 : vec:
20130 : identifier [+/- integer]
20131 : vec , identifier [+/- integer]
20132 : */
20133 :
20134 : static tree
20135 207 : c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
20136 : tree list, bool depend_p)
20137 : {
20138 207 : tree vec = NULL;
20139 207 : if (c_parser_next_token_is_not (parser, CPP_NAME)
20140 207 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
20141 : {
20142 0 : c_parser_error (parser, "expected identifier");
20143 0 : return list;
20144 : }
20145 :
20146 207 : if (!depend_p)
20147 : {
20148 83 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20149 83 : if (strcmp (p, "omp_cur_iteration") == 0
20150 36 : && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
20151 34 : && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
20152 116 : && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
20153 : {
20154 33 : tree val = c_parser_peek_nth_token (parser, 3)->value;
20155 33 : if (integer_onep (val))
20156 : {
20157 33 : c_parser_consume_token (parser);
20158 33 : c_parser_consume_token (parser);
20159 33 : c_parser_consume_token (parser);
20160 33 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20161 33 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
20162 33 : OMP_CLAUSE_CHAIN (u) = list;
20163 33 : return u;
20164 : }
20165 : }
20166 : }
20167 :
20168 :
20169 :
20170 1152 : while (c_parser_next_token_is (parser, CPP_NAME)
20171 1152 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
20172 : {
20173 1152 : tree t = lookup_name (c_parser_peek_token (parser)->value);
20174 1152 : tree addend = NULL;
20175 :
20176 1152 : if (t == NULL_TREE)
20177 : {
20178 6 : undeclared_variable (c_parser_peek_token (parser)->location,
20179 6 : c_parser_peek_token (parser)->value);
20180 6 : t = error_mark_node;
20181 : }
20182 :
20183 1152 : c_parser_consume_token (parser);
20184 :
20185 1152 : bool neg = false;
20186 1152 : if (c_parser_next_token_is (parser, CPP_MINUS))
20187 : neg = true;
20188 920 : else if (!c_parser_next_token_is (parser, CPP_PLUS))
20189 : {
20190 857 : addend = integer_zero_node;
20191 857 : neg = false;
20192 857 : goto add_to_vector;
20193 : }
20194 295 : c_parser_consume_token (parser);
20195 :
20196 295 : if (c_parser_next_token_is_not (parser, CPP_NUMBER))
20197 : {
20198 1 : c_parser_error (parser, "expected integer");
20199 1 : return list;
20200 : }
20201 :
20202 294 : addend = c_parser_peek_token (parser)->value;
20203 294 : if (TREE_CODE (addend) != INTEGER_CST)
20204 : {
20205 0 : c_parser_error (parser, "expected integer");
20206 0 : return list;
20207 : }
20208 294 : c_parser_consume_token (parser);
20209 :
20210 1151 : add_to_vector:
20211 1151 : if (t != error_mark_node)
20212 : {
20213 1146 : vec = tree_cons (addend, t, vec);
20214 1146 : if (neg)
20215 229 : OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
20216 : }
20217 :
20218 1151 : if (c_parser_next_token_is_not (parser, CPP_COMMA)
20219 979 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
20220 2129 : || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
20221 : break;
20222 :
20223 978 : c_parser_consume_token (parser);
20224 : }
20225 :
20226 173 : if (vec == NULL_TREE)
20227 : return list;
20228 :
20229 169 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20230 169 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
20231 169 : OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
20232 169 : OMP_CLAUSE_DECL (u) = nreverse (vec);
20233 169 : OMP_CLAUSE_CHAIN (u) = list;
20234 169 : return u;
20235 : }
20236 :
20237 : /* OpenMP 5.0:
20238 : iterators ( iterators-definition )
20239 :
20240 : iterators-definition:
20241 : iterator-specifier
20242 : iterator-specifier , iterators-definition
20243 :
20244 : iterator-specifier:
20245 : identifier = range-specification
20246 : iterator-type identifier = range-specification
20247 :
20248 : range-specification:
20249 : begin : end
20250 : begin : end : step */
20251 :
20252 : static tree
20253 150 : c_parser_omp_iterators (c_parser *parser)
20254 : {
20255 150 : tree ret = NULL_TREE, *last = &ret;
20256 150 : c_parser_consume_token (parser);
20257 :
20258 150 : push_scope ();
20259 :
20260 150 : matching_parens parens;
20261 150 : if (!parens.require_open (parser))
20262 1 : return error_mark_node;
20263 :
20264 215 : do
20265 : {
20266 182 : tree iter_type = NULL_TREE, type_expr = NULL_TREE;
20267 182 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
20268 : {
20269 50 : struct c_type_name *type = c_parser_type_name (parser);
20270 50 : if (type != NULL)
20271 50 : iter_type = groktypename (type, &type_expr, NULL);
20272 : }
20273 50 : if (iter_type == NULL_TREE)
20274 132 : iter_type = integer_type_node;
20275 :
20276 182 : location_t loc = c_parser_peek_token (parser)->location;
20277 182 : if (!c_parser_next_token_is (parser, CPP_NAME))
20278 : {
20279 8 : c_parser_error (parser, "expected identifier");
20280 8 : break;
20281 : }
20282 :
20283 174 : tree id = c_parser_peek_token (parser)->value;
20284 174 : c_parser_consume_token (parser);
20285 :
20286 174 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
20287 : break;
20288 :
20289 172 : location_t eloc = c_parser_peek_token (parser)->location;
20290 172 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20291 172 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20292 172 : tree begin = expr.value;
20293 :
20294 172 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20295 : break;
20296 :
20297 170 : eloc = c_parser_peek_token (parser)->location;
20298 170 : expr = c_parser_expr_no_commas (parser, NULL);
20299 170 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20300 170 : tree end = expr.value;
20301 :
20302 170 : tree step = integer_one_node;
20303 170 : if (c_parser_next_token_is (parser, CPP_COLON))
20304 : {
20305 58 : c_parser_consume_token (parser);
20306 58 : eloc = c_parser_peek_token (parser)->location;
20307 58 : expr = c_parser_expr_no_commas (parser, NULL);
20308 58 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
20309 58 : step = expr.value;
20310 : }
20311 :
20312 170 : tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
20313 170 : DECL_ARTIFICIAL (iter_var) = 1;
20314 170 : DECL_CONTEXT (iter_var) = current_function_decl;
20315 170 : pushdecl (iter_var);
20316 :
20317 170 : *last = make_tree_vec (6);
20318 170 : TREE_VEC_ELT (*last, 0) = iter_var;
20319 170 : TREE_VEC_ELT (*last, 1) = begin;
20320 170 : TREE_VEC_ELT (*last, 2) = end;
20321 170 : TREE_VEC_ELT (*last, 3) = step;
20322 170 : last = &TREE_CHAIN (*last);
20323 :
20324 170 : if (c_parser_next_token_is (parser, CPP_COMMA))
20325 : {
20326 33 : c_parser_consume_token (parser);
20327 33 : continue;
20328 : }
20329 : break;
20330 : }
20331 : while (1);
20332 :
20333 149 : parens.skip_until_found_close (parser);
20334 149 : return ret ? ret : error_mark_node;
20335 : }
20336 :
20337 : /* OpenMP 5.0:
20338 : affinity ( [aff-modifier :] variable-list )
20339 : aff-modifier:
20340 : iterator ( iterators-definition ) */
20341 :
20342 : static tree
20343 146 : c_parser_omp_clause_affinity (c_parser *parser, tree list)
20344 : {
20345 146 : location_t clause_loc = c_parser_peek_token (parser)->location;
20346 146 : tree nl, iterators = NULL_TREE;
20347 :
20348 146 : matching_parens parens;
20349 146 : if (!parens.require_open (parser))
20350 : return list;
20351 :
20352 146 : if (c_parser_next_token_is (parser, CPP_NAME))
20353 : {
20354 144 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20355 144 : bool parse_iter = ((strcmp ("iterator", p) == 0)
20356 144 : && (c_parser_peek_2nd_token (parser)->type
20357 50 : == CPP_OPEN_PAREN));
20358 50 : if (parse_iter)
20359 : {
20360 50 : unsigned n = 3;
20361 50 : parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, &n)
20362 50 : && (c_parser_peek_nth_token_raw (parser, n)->type
20363 : == CPP_CLOSE_PAREN)
20364 100 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
20365 : == CPP_COLON));
20366 : }
20367 3 : if (parse_iter)
20368 : {
20369 47 : iterators = c_parser_omp_iterators (parser);
20370 47 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20371 : {
20372 0 : if (iterators)
20373 0 : pop_scope ();
20374 0 : parens.skip_until_found_close (parser);
20375 0 : return list;
20376 : }
20377 : }
20378 : }
20379 146 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_AFFINITY,
20380 : list);
20381 146 : if (iterators)
20382 : {
20383 47 : tree block = pop_scope ();
20384 47 : if (iterators != error_mark_node)
20385 : {
20386 43 : TREE_VEC_ELT (iterators, 5) = block;
20387 99 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20388 112 : OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
20389 56 : OMP_CLAUSE_DECL (c));
20390 : }
20391 : }
20392 :
20393 146 : parens.skip_until_found_close (parser);
20394 146 : return nl;
20395 : }
20396 :
20397 :
20398 : /* OpenMP 4.0:
20399 : depend ( depend-kind: variable-list )
20400 :
20401 : depend-kind:
20402 : in | out | inout
20403 :
20404 : OpenMP 4.5:
20405 : depend ( source )
20406 :
20407 : depend ( sink : vec )
20408 :
20409 : OpenMP 5.0:
20410 : depend ( depend-modifier , depend-kind: variable-list )
20411 :
20412 : depend-kind:
20413 : in | out | inout | mutexinoutset | depobj | inoutset
20414 :
20415 : depend-modifier:
20416 : iterator ( iterators-definition ) */
20417 :
20418 : static tree
20419 895 : c_parser_omp_clause_depend (c_parser *parser, tree list, location_t here)
20420 : {
20421 895 : location_t clause_loc = c_parser_peek_token (parser)->location;
20422 895 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
20423 895 : enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
20424 895 : tree nl, c, iterators = NULL_TREE;
20425 :
20426 895 : matching_parens parens;
20427 895 : if (!parens.require_open (parser))
20428 : return list;
20429 :
20430 1049 : do
20431 : {
20432 972 : if (c_parser_next_token_is_not (parser, CPP_NAME))
20433 0 : goto invalid_kind;
20434 :
20435 972 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20436 972 : if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
20437 : {
20438 77 : iterators = c_parser_omp_iterators (parser);
20439 77 : c_parser_require (parser, CPP_COMMA, "expected %<,%>");
20440 77 : continue;
20441 : }
20442 895 : if (strcmp ("in", p) == 0)
20443 : kind = OMP_CLAUSE_DEPEND_IN;
20444 644 : else if (strcmp ("inout", p) == 0)
20445 : kind = OMP_CLAUSE_DEPEND_INOUT;
20446 425 : else if (strcmp ("inoutset", p) == 0)
20447 : kind = OMP_CLAUSE_DEPEND_INOUTSET;
20448 410 : else if (strcmp ("mutexinoutset", p) == 0)
20449 : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
20450 389 : else if (strcmp ("out", p) == 0)
20451 : kind = OMP_CLAUSE_DEPEND_OUT;
20452 244 : else if (strcmp ("depobj", p) == 0)
20453 : kind = OMP_CLAUSE_DEPEND_DEPOBJ;
20454 223 : else if (strcmp ("sink", p) == 0)
20455 : {
20456 124 : gcc_rich_location richloc (clause_loc);
20457 124 : richloc.add_fixit_replace (here, "doacross");
20458 124 : warning_at (&richloc, OPT_Wdeprecated_openmp,
20459 : "%<sink%> modifier with %<depend%> clause deprecated "
20460 : "since OpenMP 5.2, use with %<doacross%>");
20461 124 : dkind = OMP_CLAUSE_DOACROSS_SINK;
20462 124 : }
20463 99 : else if (strcmp ("source", p) == 0)
20464 : {
20465 97 : gcc_rich_location richloc (clause_loc);
20466 97 : richloc.add_fixit_replace (here, "doacross");
20467 97 : warning_at (&richloc, OPT_Wdeprecated_openmp,
20468 : "%<source%> modifier with %<depend%> clause deprecated "
20469 : "since OpenMP 5.2, use with %<doacross%>");
20470 97 : dkind = OMP_CLAUSE_DOACROSS_SOURCE;
20471 97 : }
20472 : else
20473 2 : goto invalid_kind;
20474 893 : break;
20475 77 : }
20476 : while (1);
20477 :
20478 893 : c_parser_consume_token (parser);
20479 :
20480 893 : if (iterators
20481 893 : && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
20482 893 : || dkind == OMP_CLAUSE_DOACROSS_SINK))
20483 : {
20484 2 : pop_scope ();
20485 2 : error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
20486 : dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
20487 2 : iterators = NULL_TREE;
20488 : }
20489 :
20490 893 : if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
20491 : {
20492 97 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20493 97 : OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
20494 97 : OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
20495 97 : OMP_CLAUSE_DECL (c) = NULL_TREE;
20496 97 : OMP_CLAUSE_CHAIN (c) = list;
20497 97 : parens.skip_until_found_close (parser);
20498 97 : return c;
20499 : }
20500 :
20501 796 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20502 0 : goto resync_fail;
20503 :
20504 796 : if (dkind == OMP_CLAUSE_DOACROSS_SINK)
20505 124 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
20506 : else
20507 : {
20508 672 : nl = c_parser_omp_variable_list (parser, clause_loc,
20509 : OMP_CLAUSE_DEPEND, list);
20510 :
20511 672 : if (iterators)
20512 : {
20513 73 : tree block = pop_scope ();
20514 73 : if (iterators == error_mark_node)
20515 : iterators = NULL_TREE;
20516 : else
20517 68 : TREE_VEC_ELT (iterators, 5) = block;
20518 : }
20519 :
20520 1385 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20521 : {
20522 713 : OMP_CLAUSE_DEPEND_KIND (c) = kind;
20523 713 : if (iterators)
20524 150 : OMP_CLAUSE_DECL (c)
20525 150 : = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
20526 : }
20527 : }
20528 :
20529 796 : parens.skip_until_found_close (parser);
20530 796 : return nl;
20531 :
20532 2 : invalid_kind:
20533 2 : c_parser_error (parser, "invalid depend kind");
20534 2 : resync_fail:
20535 2 : parens.skip_until_found_close (parser);
20536 2 : if (iterators)
20537 2 : pop_scope ();
20538 : return list;
20539 : }
20540 :
20541 : /* OpenMP 5.2:
20542 : doacross ( source : )
20543 : doacross ( source : omp_cur_iteration )
20544 :
20545 : doacross ( sink : vec )
20546 : doacross ( sink : omp_cur_iteration - logical_iteration ) */
20547 :
20548 : static tree
20549 145 : c_parser_omp_clause_doacross (c_parser *parser, tree list)
20550 : {
20551 145 : location_t clause_loc = c_parser_peek_token (parser)->location;
20552 145 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
20553 145 : tree nl;
20554 145 : const char *p;
20555 :
20556 145 : matching_parens parens;
20557 145 : if (!parens.require_open (parser))
20558 : return list;
20559 :
20560 145 : if (c_parser_next_token_is_not (parser, CPP_NAME))
20561 0 : goto invalid_kind;
20562 :
20563 145 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20564 145 : if (strcmp ("sink", p) == 0)
20565 : kind = OMP_CLAUSE_DOACROSS_SINK;
20566 60 : else if (strcmp ("source", p) == 0)
20567 : kind = OMP_CLAUSE_DOACROSS_SOURCE;
20568 : else
20569 0 : goto invalid_kind;
20570 :
20571 145 : c_parser_consume_token (parser);
20572 :
20573 145 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20574 4 : goto resync_fail;
20575 :
20576 141 : if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
20577 : {
20578 58 : if (c_parser_next_token_is (parser, CPP_NAME)
20579 58 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
20580 : "omp_cur_iteration") == 0)
20581 28 : c_parser_consume_token (parser);
20582 58 : nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20583 58 : OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
20584 58 : OMP_CLAUSE_DECL (nl) = NULL_TREE;
20585 58 : OMP_CLAUSE_CHAIN (nl) = list;
20586 : }
20587 : else
20588 83 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
20589 :
20590 141 : parens.skip_until_found_close (parser);
20591 141 : return nl;
20592 :
20593 0 : invalid_kind:
20594 0 : c_parser_error (parser, "invalid doacross kind");
20595 4 : resync_fail:
20596 4 : parens.skip_until_found_close (parser);
20597 4 : return list;
20598 : }
20599 :
20600 : /* OpenMP 6.1:
20601 : dyn_groupprivate ( [fallback-modifier : ] integer-expression )
20602 :
20603 : fallback-modifier
20604 : fallback( abort | default_mem | null ) */
20605 :
20606 : static tree
20607 21 : c_parser_omp_clause_dyn_groupprivate (c_parser *parser, tree list)
20608 : {
20609 21 : location_t clause_loc = c_parser_peek_token (parser)->location;
20610 21 : matching_parens parens;
20611 21 : if (!parens.require_open (parser))
20612 : return list;
20613 :
20614 21 : enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
20615 :
20616 21 : unsigned n = 3;
20617 21 : if (c_parser_next_token_is (parser, CPP_NAME)
20618 21 : && (c_parser_peek_2nd_token (parser)->type == CPP_COLON
20619 9 : || (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
20620 8 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
20621 8 : && (c_parser_peek_nth_token_raw (parser, n)->type
20622 : == CPP_CLOSE_PAREN)
20623 8 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
20624 : == CPP_COLON))))
20625 : {
20626 10 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20627 10 : if (strcmp (p, "fallback") != 0)
20628 : {
20629 3 : c_parser_error (parser, "expected %<fallback%> modifier");
20630 3 : return list;
20631 : }
20632 7 : c_parser_consume_token (parser);
20633 7 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
20634 : return list;
20635 6 : p = "";
20636 6 : if (c_parser_next_token_is (parser, CPP_NAME))
20637 5 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20638 6 : if (strcmp (p, "abort") == 0)
20639 : kind = OMP_CLAUSE_FALLBACK_ABORT;
20640 5 : else if (strcmp (p, "default_mem") == 0)
20641 : kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
20642 4 : else if (strcmp (p, "null") == 0)
20643 : kind = OMP_CLAUSE_FALLBACK_NULL;
20644 : else
20645 : {
20646 2 : c_parser_error (parser, "expected %<abort%>, %<default_mem%>, or "
20647 : "%<null%> as fallback mode");
20648 2 : return list;
20649 : }
20650 4 : c_parser_consume_token (parser);
20651 4 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
20652 : return list;
20653 3 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20654 : return list;
20655 : }
20656 14 : location_t expr_loc = c_parser_peek_token (parser)->location;
20657 14 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20658 14 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20659 14 : tree size = c_fully_fold (expr.value, false, NULL);
20660 14 : parens.skip_until_found_close (parser);
20661 :
20662 14 : if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
20663 : {
20664 2 : error_at (expr_loc, "expected integer expression");
20665 2 : return list;
20666 : }
20667 :
20668 : /* Attempt to statically determine when the number is negative. */
20669 12 : tree c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, size,
20670 12 : build_int_cst (TREE_TYPE (size), 0));
20671 12 : protected_set_expr_location (c, expr_loc);
20672 12 : if (c == boolean_true_node)
20673 : {
20674 3 : warning_at (expr_loc, OPT_Wopenmp,
20675 : "%<dyn_groupprivate%> value must be non-negative");
20676 3 : size = integer_zero_node;
20677 : }
20678 12 : check_no_duplicate_clause (list, OMP_CLAUSE_DYN_GROUPPRIVATE,
20679 : "dyn_groupprivate");
20680 :
20681 12 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DYN_GROUPPRIVATE);
20682 12 : OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
20683 12 : OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
20684 12 : OMP_CLAUSE_CHAIN (c) = list;
20685 12 : list = c;
20686 :
20687 12 : return list;
20688 : }
20689 :
20690 : /* OpenMP 4.0:
20691 : map ( map-kind: variable-list )
20692 : map ( variable-list )
20693 :
20694 : map-kind:
20695 : alloc | to | from | tofrom
20696 :
20697 : OpenMP 4.5:
20698 : map-kind:
20699 : alloc | to | from | tofrom | release | delete
20700 :
20701 : map ( always [,] map-kind: variable-list )
20702 :
20703 : OpenMP 5.0:
20704 : map ( [map-type-modifier[,] ...] map-kind: variable-list )
20705 :
20706 : map-type-modifier:
20707 : always | close | present | iterator (iterators-definition) */
20708 :
20709 : static tree
20710 1817 : c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
20711 : {
20712 1817 : location_t clause_loc = c_parser_peek_token (parser)->location;
20713 1817 : tree nl, c;
20714 1817 : enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
20715 :
20716 1817 : matching_parens parens;
20717 1817 : if (!parens.require_open (parser))
20718 : return list;
20719 :
20720 : int pos = 1;
20721 2396 : int map_kind_pos = 0;
20722 : int iterator_length = 0;
20723 2975 : for (;;)
20724 : {
20725 2396 : c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
20726 2396 : if (tok->type != CPP_NAME)
20727 : break;
20728 :
20729 2077 : const char *p = IDENTIFIER_POINTER (tok->value);
20730 2077 : c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
20731 2077 : if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
20732 : {
20733 16 : unsigned n = pos + 2;
20734 16 : if (c_parser_check_balanced_raw_token_sequence (parser, &n)
20735 16 : && c_parser_peek_nth_token_raw (parser, n)->type
20736 : == CPP_CLOSE_PAREN)
20737 : {
20738 16 : iterator_length = n - pos + 1;
20739 16 : pos = n;
20740 16 : next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
20741 : }
20742 : }
20743 :
20744 2077 : if (next_tok->type == CPP_COLON)
20745 : {
20746 : map_kind_pos = pos;
20747 : break;
20748 : }
20749 :
20750 579 : if (next_tok->type == CPP_COMMA)
20751 195 : pos++;
20752 384 : else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
20753 : == CPP_OPEN_PAREN)
20754 : {
20755 13 : unsigned int npos = pos + 2;
20756 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
20757 13 : && (c_parser_peek_nth_token_raw (parser, npos)->type
20758 : == CPP_CLOSE_PAREN)
20759 26 : && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
20760 : == CPP_COMMA))
20761 12 : pos = npos + 1;
20762 : }
20763 :
20764 579 : pos++;
20765 579 : }
20766 :
20767 1817 : int always_modifier = 0;
20768 1817 : int close_modifier = 0;
20769 1817 : int present_modifier = 0;
20770 1817 : int mapper_modifier = 0;
20771 1817 : int num_commas = 0;
20772 1817 : int num_identifiers = 0;
20773 1817 : tree mapper_name = NULL_TREE;
20774 1817 : tree iterators = NULL_TREE;
20775 2196 : for (int pos = 1; pos < map_kind_pos; ++pos)
20776 : {
20777 397 : c_token *tok = c_parser_peek_token (parser);
20778 :
20779 397 : if (tok->type == CPP_COMMA)
20780 : {
20781 166 : ++num_commas;
20782 166 : if (num_commas > num_identifiers)
20783 0 : c_parser_error (parser, "illegal comma");
20784 166 : c_parser_consume_token (parser);
20785 166 : continue;
20786 : }
20787 :
20788 231 : const char *p = IDENTIFIER_POINTER (tok->value);
20789 231 : if (strcmp ("always", p) == 0)
20790 : {
20791 78 : if (always_modifier)
20792 : {
20793 4 : c_parser_error (parser, "too many %<always%> modifiers");
20794 4 : parens.skip_until_found_close (parser);
20795 4 : return list;
20796 : }
20797 74 : always_modifier++;
20798 74 : c_parser_consume_token (parser);
20799 : }
20800 153 : else if (strcmp ("close", p) == 0)
20801 : {
20802 65 : if (close_modifier)
20803 : {
20804 4 : c_parser_error (parser, "too many %<close%> modifiers");
20805 4 : parens.skip_until_found_close (parser);
20806 4 : return list;
20807 : }
20808 61 : close_modifier++;
20809 61 : c_parser_consume_token (parser);
20810 : }
20811 88 : else if (strcmp ("iterator", p) == 0)
20812 : {
20813 16 : if (iterators)
20814 : {
20815 1 : c_parser_error (parser, "too many %<iterator%> modifiers");
20816 1 : parens.skip_until_found_close (parser);
20817 1 : return list;
20818 : }
20819 15 : iterators = c_parser_omp_iterators (parser);
20820 15 : pos += iterator_length - 1;
20821 : }
20822 72 : else if (strcmp ("mapper", p) == 0)
20823 : {
20824 12 : c_parser_consume_token (parser);
20825 :
20826 12 : matching_parens mparens;
20827 12 : if (mparens.require_open (parser))
20828 : {
20829 12 : if (mapper_modifier)
20830 : {
20831 0 : c_parser_error (parser, "too many %<mapper%> modifiers");
20832 : /* Assume it's a well-formed mapper modifier, even if it
20833 : seems to be in the wrong place. */
20834 0 : c_parser_consume_token (parser);
20835 0 : mparens.require_close (parser);
20836 0 : parens.skip_until_found_close (parser);
20837 0 : return list;
20838 : }
20839 :
20840 12 : tok = c_parser_peek_token (parser);
20841 :
20842 12 : switch (tok->type)
20843 : {
20844 5 : case CPP_NAME:
20845 5 : {
20846 5 : mapper_name = tok->value;
20847 5 : c_parser_consume_token (parser);
20848 5 : if (declare_mapper_p)
20849 : {
20850 1 : error_at (tok->location,
20851 : "in %<declare mapper%> directives, parameter "
20852 : "to %<mapper%> modifier must be %<default%>");
20853 : }
20854 : }
20855 : break;
20856 :
20857 7 : case CPP_KEYWORD:
20858 7 : if (tok->keyword == RID_DEFAULT)
20859 : {
20860 7 : c_parser_consume_token (parser);
20861 7 : break;
20862 : }
20863 : /* Fallthrough. */
20864 :
20865 0 : default:
20866 0 : error_at (tok->location,
20867 : "expected identifier or %<default%>");
20868 0 : return list;
20869 : }
20870 :
20871 12 : if (!mparens.require_close (parser))
20872 : {
20873 0 : parens.skip_until_found_close (parser);
20874 0 : return list;
20875 : }
20876 :
20877 12 : mapper_modifier++;
20878 12 : pos += 3;
20879 : }
20880 : }
20881 60 : else if (strcmp ("present", p) == 0)
20882 : {
20883 55 : if (present_modifier)
20884 : {
20885 4 : c_parser_error (parser, "too many %<present%> modifiers");
20886 4 : parens.skip_until_found_close (parser);
20887 4 : return list;
20888 : }
20889 51 : present_modifier++;
20890 51 : c_parser_consume_token (parser);
20891 : }
20892 : else
20893 : {
20894 5 : c_parser_error (parser, "%<map%> clause with map-type modifier other "
20895 : "than %<always%>, %<close%>, %<iterator%>, "
20896 : "%<mapper%> or %<present%>");
20897 5 : parens.skip_until_found_close (parser);
20898 5 : return list;
20899 : }
20900 213 : ++num_identifiers;
20901 213 : if (num_identifiers - 1 > num_commas)
20902 : {
20903 30 : gcc_rich_location richloc (clause_loc);
20904 30 : richloc.add_fixit_insert_before (tok->location, ",");
20905 30 : warning_at (&richloc, OPT_Wdeprecated_openmp,
20906 : "%<map%> clause modifiers without comma separation is "
20907 : "deprecated since OpenMP 5.2");
20908 30 : }
20909 : num_commas = num_identifiers - 1;
20910 : }
20911 :
20912 1799 : if (c_parser_next_token_is (parser, CPP_NAME)
20913 1799 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20914 : {
20915 1480 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20916 1480 : int always_present_modifier = always_modifier && present_modifier;
20917 :
20918 1480 : if (strcmp ("alloc", p) == 0)
20919 128 : kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
20920 1352 : else if (strcmp ("to", p) == 0)
20921 879 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
20922 451 : : present_modifier ? GOMP_MAP_PRESENT_TO
20923 443 : : always_modifier ? GOMP_MAP_ALWAYS_TO
20924 : : GOMP_MAP_TO);
20925 896 : else if (strcmp ("from", p) == 0)
20926 1106 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
20927 555 : : present_modifier ? GOMP_MAP_PRESENT_FROM
20928 552 : : always_modifier ? GOMP_MAP_ALWAYS_FROM
20929 : : GOMP_MAP_FROM);
20930 336 : else if (strcmp ("tofrom", p) == 0)
20931 545 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
20932 280 : : present_modifier ? GOMP_MAP_PRESENT_TOFROM
20933 274 : : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
20934 : : GOMP_MAP_TOFROM);
20935 50 : else if (strcmp ("release", p) == 0)
20936 : kind = GOMP_MAP_RELEASE;
20937 15 : else if (strcmp ("delete", p) == 0)
20938 : kind = GOMP_MAP_DELETE;
20939 : else
20940 : {
20941 0 : c_parser_error (parser, "invalid map kind");
20942 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20943 : "expected %<)%>");
20944 0 : return list;
20945 : }
20946 1480 : c_parser_consume_token (parser);
20947 1480 : c_parser_consume_token (parser);
20948 : }
20949 :
20950 1799 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
20951 : true);
20952 :
20953 1799 : tree last_new = NULL_TREE;
20954 :
20955 1799 : if (iterators)
20956 : {
20957 14 : tree block = pop_scope ();
20958 14 : if (iterators == error_mark_node)
20959 : iterators = NULL_TREE;
20960 : else
20961 14 : TREE_VEC_ELT (iterators, 5) = block;
20962 : }
20963 :
20964 4008 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20965 : {
20966 2209 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
20967 2209 : OMP_CLAUSE_ITERATORS (c) = iterators;
20968 2209 : last_new = c;
20969 : }
20970 :
20971 1799 : if (mapper_name)
20972 : {
20973 5 : tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20974 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
20975 5 : OMP_CLAUSE_DECL (name) = mapper_name;
20976 5 : OMP_CLAUSE_CHAIN (name) = nl;
20977 5 : nl = name;
20978 :
20979 5 : gcc_assert (last_new);
20980 :
20981 5 : name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20982 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
20983 5 : OMP_CLAUSE_DECL (name) = null_pointer_node;
20984 5 : OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
20985 5 : OMP_CLAUSE_CHAIN (last_new) = name;
20986 : }
20987 :
20988 1799 : parens.skip_until_found_close (parser);
20989 1799 : return nl;
20990 : }
20991 :
20992 : /* OpenMP 4.0:
20993 : device ( expression )
20994 :
20995 : OpenMP 5.0:
20996 : device ( [device-modifier :] integer-expression )
20997 :
20998 : device-modifier:
20999 : ancestor | device_num */
21000 :
21001 : static tree
21002 369 : c_parser_omp_clause_device (c_parser *parser, tree list)
21003 : {
21004 369 : location_t clause_loc = c_parser_peek_token (parser)->location;
21005 369 : location_t expr_loc;
21006 369 : c_expr expr;
21007 369 : tree c, t;
21008 369 : bool ancestor = false;
21009 :
21010 369 : matching_parens parens;
21011 369 : if (!parens.require_open (parser))
21012 : return list;
21013 :
21014 369 : if (c_parser_next_token_is (parser, CPP_NAME)
21015 369 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
21016 : {
21017 48 : c_token *tok = c_parser_peek_token (parser);
21018 48 : const char *p = IDENTIFIER_POINTER (tok->value);
21019 48 : if (strcmp ("ancestor", p) == 0)
21020 : {
21021 : /* A requires directive with the reverse_offload clause must be
21022 : specified. */
21023 25 : if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
21024 : {
21025 1 : error_at (tok->location, "%<ancestor%> device modifier not "
21026 : "preceded by %<requires%> directive "
21027 : "with %<reverse_offload%> clause");
21028 1 : parens.skip_until_found_close (parser);
21029 1 : return list;
21030 : }
21031 : ancestor = true;
21032 : }
21033 23 : else if (strcmp ("device_num", p) == 0)
21034 : ;
21035 : else
21036 : {
21037 1 : error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
21038 1 : parens.skip_until_found_close (parser);
21039 1 : return list;
21040 : }
21041 46 : c_parser_consume_token (parser);
21042 46 : c_parser_consume_token (parser);
21043 : }
21044 :
21045 367 : expr_loc = c_parser_peek_token (parser)->location;
21046 367 : expr = c_parser_expr_no_commas (parser, NULL);
21047 367 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
21048 367 : t = expr.value;
21049 367 : t = c_fully_fold (t, false, NULL);
21050 :
21051 367 : parens.skip_until_found_close (parser);
21052 :
21053 367 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
21054 : {
21055 2 : c_parser_error (parser, "expected integer expression");
21056 2 : return list;
21057 : }
21058 365 : if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
21059 : {
21060 1 : error_at (expr_loc, "the %<device%> clause expression must evaluate to "
21061 : "%<1%>");
21062 1 : return list;
21063 : }
21064 :
21065 364 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
21066 :
21067 364 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
21068 :
21069 364 : OMP_CLAUSE_DEVICE_ID (c) = t;
21070 364 : OMP_CLAUSE_CHAIN (c) = list;
21071 364 : OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
21072 :
21073 364 : list = c;
21074 364 : return list;
21075 : }
21076 :
21077 : /* OpenMP 4.0:
21078 : dist_schedule ( static )
21079 : dist_schedule ( static , expression ) */
21080 :
21081 : static tree
21082 1582 : c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
21083 : {
21084 1582 : tree c, t = NULL_TREE;
21085 1582 : location_t loc = c_parser_peek_token (parser)->location;
21086 :
21087 1582 : matching_parens parens;
21088 1582 : if (!parens.require_open (parser))
21089 : return list;
21090 :
21091 1582 : if (!c_parser_next_token_is_keyword (parser, RID_STATIC))
21092 : {
21093 0 : c_parser_error (parser, "invalid dist_schedule kind");
21094 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
21095 : "expected %<)%>");
21096 0 : return list;
21097 : }
21098 :
21099 1582 : c_parser_consume_token (parser);
21100 1582 : if (c_parser_next_token_is (parser, CPP_COMMA))
21101 : {
21102 1575 : c_parser_consume_token (parser);
21103 :
21104 1575 : location_t expr_loc = c_parser_peek_token (parser)->location;
21105 1575 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
21106 1575 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
21107 1575 : t = expr.value;
21108 1575 : t = c_fully_fold (t, false, NULL);
21109 1575 : parens.skip_until_found_close (parser);
21110 : }
21111 : else
21112 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
21113 : "expected %<,%> or %<)%>");
21114 :
21115 : /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
21116 : "dist_schedule"); */
21117 1582 : if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE))
21118 2 : warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
21119 1582 : if (t == error_mark_node)
21120 : return list;
21121 :
21122 1582 : c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
21123 1582 : OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
21124 1582 : OMP_CLAUSE_CHAIN (c) = list;
21125 1582 : return c;
21126 : }
21127 :
21128 : /* OpenMP 4.0:
21129 : proc_bind ( proc-bind-kind )
21130 :
21131 : proc-bind-kind:
21132 : primary | master | close | spread
21133 : where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
21134 :
21135 : static tree
21136 195 : c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
21137 : {
21138 195 : location_t clause_loc = c_parser_peek_token (parser)->location;
21139 195 : enum omp_clause_proc_bind_kind kind;
21140 195 : tree c;
21141 :
21142 195 : matching_parens parens;
21143 195 : if (!parens.require_open (parser))
21144 : return list;
21145 :
21146 195 : if (c_parser_next_token_is (parser, CPP_NAME))
21147 : {
21148 195 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21149 195 : if (strcmp ("primary", p) == 0)
21150 : kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
21151 194 : else if (strcmp ("master", p) == 0)
21152 : {
21153 17 : gcc_rich_location richloc (clause_loc);
21154 17 : richloc.add_fixit_replace (c_parser_peek_token (parser)->location,
21155 : "primary");
21156 17 : warning_at (&richloc, OPT_Wdeprecated_openmp,
21157 : "%<master%> affinity deprecated since OpenMP 5.1, "
21158 : "use %<primary%>");
21159 17 : kind = OMP_CLAUSE_PROC_BIND_MASTER;
21160 17 : }
21161 177 : else if (strcmp ("close", p) == 0)
21162 : kind = OMP_CLAUSE_PROC_BIND_CLOSE;
21163 165 : else if (strcmp ("spread", p) == 0)
21164 : kind = OMP_CLAUSE_PROC_BIND_SPREAD;
21165 : else
21166 0 : goto invalid_kind;
21167 : }
21168 : else
21169 0 : goto invalid_kind;
21170 :
21171 195 : check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind");
21172 195 : c_parser_consume_token (parser);
21173 195 : parens.skip_until_found_close (parser);
21174 195 : c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
21175 195 : OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
21176 195 : OMP_CLAUSE_CHAIN (c) = list;
21177 195 : return c;
21178 :
21179 0 : invalid_kind:
21180 0 : c_parser_error (parser, "invalid proc_bind kind");
21181 0 : parens.skip_until_found_close (parser);
21182 0 : return list;
21183 : }
21184 :
21185 : /* OpenMP 5.0:
21186 : device_type ( host | nohost | any ) */
21187 :
21188 : static tree
21189 51 : c_parser_omp_clause_device_type (c_parser *parser, tree list)
21190 : {
21191 51 : location_t clause_loc = c_parser_peek_token (parser)->location;
21192 51 : enum omp_clause_device_type_kind kind;
21193 51 : tree c;
21194 :
21195 51 : matching_parens parens;
21196 51 : if (!parens.require_open (parser))
21197 : return list;
21198 :
21199 51 : if (c_parser_next_token_is (parser, CPP_NAME))
21200 : {
21201 51 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
21202 51 : if (strcmp ("host", p) == 0)
21203 : kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
21204 32 : else if (strcmp ("nohost", p) == 0)
21205 : kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
21206 20 : else if (strcmp ("any", p) == 0)
21207 : kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
21208 : else
21209 0 : goto invalid_kind;
21210 : }
21211 : else
21212 0 : goto invalid_kind;
21213 :
21214 51 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
21215 : "device_type");
21216 51 : c_parser_consume_token (parser);
21217 51 : parens.skip_until_found_close (parser);
21218 51 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
21219 51 : OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
21220 51 : OMP_CLAUSE_CHAIN (c) = list;
21221 51 : return c;
21222 :
21223 0 : invalid_kind:
21224 0 : c_parser_error (parser, "expected %<host%>, %<nohost%> or %<any%>");
21225 0 : parens.skip_until_found_close (parser);
21226 0 : return list;
21227 : }
21228 :
21229 : /* OpenMP 4.0:
21230 : from ( variable-list )
21231 : to ( variable-list )
21232 :
21233 : OpenMP 5.1:
21234 : from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
21235 : to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
21236 :
21237 : motion-modifier:
21238 : present | iterator (iterators-definition) */
21239 :
21240 : static tree
21241 2842 : c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
21242 : tree list)
21243 : {
21244 2842 : location_t loc = c_parser_peek_token (parser)->location;
21245 2842 : matching_parens parens;
21246 2842 : if (!parens.require_open (parser))
21247 : return list;
21248 :
21249 5676 : int pos = 1, colon_pos = 0;
21250 : int iterator_length = 0;
21251 :
21252 5676 : while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
21253 : {
21254 2850 : const char *identifier =
21255 2850 : IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
21256 2850 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
21257 : == CPP_OPEN_PAREN)
21258 : {
21259 12 : unsigned int npos = pos + 2;
21260 12 : if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
21261 12 : && (c_parser_peek_nth_token_raw (parser, npos)->type
21262 : == CPP_CLOSE_PAREN))
21263 : {
21264 12 : if (strcmp (identifier, "iterator") == 0)
21265 12 : iterator_length = npos - pos + 1;
21266 12 : pos = npos;
21267 : }
21268 : }
21269 2850 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
21270 8 : pos += 2;
21271 : else
21272 : pos++;
21273 2850 : if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
21274 : {
21275 : colon_pos = pos;
21276 : break;
21277 : }
21278 : }
21279 :
21280 2842 : bool present = false;
21281 2842 : tree iterators = NULL_TREE;
21282 :
21283 2862 : for (int pos = 1; pos < colon_pos; ++pos)
21284 : {
21285 22 : c_token *token = c_parser_peek_token (parser);
21286 22 : if (token->type == CPP_COMMA)
21287 : {
21288 3 : c_parser_consume_token (parser);
21289 3 : continue;
21290 : }
21291 19 : const char *p = IDENTIFIER_POINTER (token->value);
21292 19 : if (strcmp ("present", p) == 0)
21293 : {
21294 6 : if (present)
21295 : {
21296 0 : c_parser_error (parser, "too many %<present%> modifiers");
21297 0 : parens.skip_until_found_close (parser);
21298 0 : return list;
21299 : }
21300 6 : present = true;
21301 6 : c_parser_consume_token (parser);
21302 : }
21303 13 : else if (strcmp ("iterator", p) == 0)
21304 : {
21305 12 : if (iterators)
21306 : {
21307 1 : c_parser_error (parser, "too many %<iterator%> modifiers");
21308 1 : parens.skip_until_found_close (parser);
21309 1 : return list;
21310 : }
21311 11 : iterators = c_parser_omp_iterators (parser);
21312 11 : pos += iterator_length - 1;
21313 : }
21314 : else
21315 : {
21316 2 : error_at (token->location,
21317 : "%qs clause with modifier other than %<iterator%> or "
21318 : "%<present%>",
21319 : kind == OMP_CLAUSE_TO ? "to" : "from");
21320 1 : parens.skip_until_found_close (parser);
21321 1 : return list;
21322 : }
21323 : }
21324 :
21325 2840 : if (colon_pos)
21326 14 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
21327 :
21328 2840 : tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
21329 2840 : parens.skip_until_found_close (parser);
21330 :
21331 2840 : if (present)
21332 12 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21333 6 : OMP_CLAUSE_MOTION_PRESENT (c) = 1;
21334 :
21335 2840 : if (iterators)
21336 : {
21337 9 : tree block = pop_scope ();
21338 9 : if (iterators == error_mark_node)
21339 : iterators = NULL_TREE;
21340 : else
21341 9 : TREE_VEC_ELT (iterators, 5) = block;
21342 : }
21343 :
21344 9 : if (iterators)
21345 22 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21346 13 : OMP_CLAUSE_ITERATORS (c) = iterators;
21347 :
21348 : return nl;
21349 : }
21350 :
21351 : /* OpenMP 4.0:
21352 : uniform ( variable-list ) */
21353 :
21354 : static tree
21355 115 : c_parser_omp_clause_uniform (c_parser *parser, tree list)
21356 : {
21357 : /* The clauses location. */
21358 115 : location_t loc = c_parser_peek_token (parser)->location;
21359 :
21360 115 : matching_parens parens;
21361 115 : if (parens.require_open (parser))
21362 : {
21363 115 : list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
21364 : list);
21365 115 : parens.skip_until_found_close (parser);
21366 : }
21367 115 : return list;
21368 : }
21369 :
21370 : /* OpenMP 5.1
21371 : full */
21372 :
21373 : static tree
21374 69 : c_parser_omp_clause_full (c_parser *parser, tree list)
21375 : {
21376 69 : check_no_duplicate_clause (list, OMP_CLAUSE_FULL, "full");
21377 :
21378 69 : location_t loc = c_parser_peek_token (parser)->location;
21379 69 : tree c = build_omp_clause (loc, OMP_CLAUSE_FULL);
21380 69 : OMP_CLAUSE_CHAIN (c) = list;
21381 69 : return c;
21382 : }
21383 :
21384 : /* OpenMP 5.1
21385 : partial ( constant-expression ) */
21386 :
21387 : static tree
21388 230 : c_parser_omp_clause_partial (c_parser *parser, tree list)
21389 : {
21390 230 : tree num = NULL_TREE;
21391 230 : location_t loc = c_parser_peek_token (parser)->location;
21392 :
21393 230 : check_no_duplicate_clause (list, OMP_CLAUSE_PARTIAL, "partial");
21394 :
21395 230 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
21396 : {
21397 173 : matching_parens parens;
21398 173 : parens.consume_open (parser);
21399 173 : num = c_parser_expr_no_commas (parser, NULL).value;
21400 173 : parens.skip_until_found_close (parser);
21401 :
21402 173 : if (num == error_mark_node)
21403 7 : return list;
21404 :
21405 171 : mark_exp_read (num);
21406 171 : num = c_fully_fold (num, false, NULL);
21407 171 : HOST_WIDE_INT n;
21408 342 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
21409 170 : || !tree_fits_shwi_p (num)
21410 168 : || (n = tree_to_shwi (num)) <= 0
21411 337 : || (int) n != n)
21412 : {
21413 5 : error_at (loc, "%<partial%> argument needs positive constant "
21414 : "integer expression");
21415 5 : return list;
21416 : }
21417 : }
21418 :
21419 223 : tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL);
21420 223 : OMP_CLAUSE_PARTIAL_EXPR (c) = num;
21421 223 : OMP_CLAUSE_CHAIN (c) = list;
21422 223 : return c;
21423 : }
21424 :
21425 : /* OpenMP 5.1
21426 : novariants ( scalar-expression ) */
21427 :
21428 : static tree
21429 24 : c_parser_omp_clause_novariants (c_parser *parser, tree list)
21430 : {
21431 24 : matching_parens parens;
21432 24 : if (!parens.require_open (parser))
21433 : return list;
21434 :
21435 24 : location_t loc = c_parser_peek_token (parser)->location;
21436 24 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
21437 24 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
21438 24 : t = c_objc_common_truthvalue_conversion (loc, t);
21439 24 : t = c_fully_fold (t, false, NULL);
21440 24 : parens.skip_until_found_close (parser);
21441 :
21442 24 : check_no_duplicate_clause (list, OMP_CLAUSE_NOVARIANTS, "novariants");
21443 :
21444 24 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
21445 24 : OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
21446 24 : OMP_CLAUSE_CHAIN (c) = list;
21447 24 : list = c;
21448 :
21449 24 : return list;
21450 : }
21451 :
21452 : /* OpenMP 5.1
21453 : nocontext ( scalar-expression ) */
21454 :
21455 : static tree
21456 23 : c_parser_omp_clause_nocontext (c_parser *parser, tree list)
21457 : {
21458 23 : matching_parens parens;
21459 23 : if (!parens.require_open (parser))
21460 : return list;
21461 :
21462 23 : location_t loc = c_parser_peek_token (parser)->location;
21463 23 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
21464 23 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
21465 23 : t = c_objc_common_truthvalue_conversion (loc, t);
21466 23 : t = c_fully_fold (t, false, NULL);
21467 23 : parens.skip_until_found_close (parser);
21468 :
21469 23 : check_no_duplicate_clause (list, OMP_CLAUSE_NOCONTEXT, "nocontext");
21470 :
21471 23 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
21472 23 : OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
21473 23 : OMP_CLAUSE_CHAIN (c) = list;
21474 23 : list = c;
21475 :
21476 23 : return list;
21477 : }
21478 :
21479 : /* OpenMP 5.0:
21480 : detach ( event-handle ) */
21481 :
21482 : static tree
21483 34 : c_parser_omp_clause_detach (c_parser *parser, tree list)
21484 : {
21485 34 : matching_parens parens;
21486 34 : location_t clause_loc = c_parser_peek_token (parser)->location;
21487 :
21488 34 : if (!parens.require_open (parser))
21489 : return list;
21490 :
21491 34 : if (c_parser_next_token_is_not (parser, CPP_NAME)
21492 34 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
21493 : {
21494 1 : c_parser_error (parser, "expected identifier");
21495 1 : parens.skip_until_found_close (parser);
21496 1 : return list;
21497 : }
21498 :
21499 33 : tree t = lookup_name (c_parser_peek_token (parser)->value);
21500 33 : if (t == NULL_TREE)
21501 : {
21502 0 : undeclared_variable (c_parser_peek_token (parser)->location,
21503 0 : c_parser_peek_token (parser)->value);
21504 0 : parens.skip_until_found_close (parser);
21505 0 : return list;
21506 : }
21507 33 : c_parser_consume_token (parser);
21508 :
21509 33 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
21510 33 : if (!INTEGRAL_TYPE_P (type)
21511 : || TREE_CODE (type) != ENUMERAL_TYPE
21512 33 : || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
21513 : {
21514 1 : error_at (clause_loc, "%<detach%> clause event handle "
21515 : "has type %qT rather than "
21516 : "%<omp_event_handle_t%>",
21517 : type);
21518 1 : parens.skip_until_found_close (parser);
21519 1 : return list;
21520 : }
21521 :
21522 32 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
21523 32 : OMP_CLAUSE_DECL (u) = t;
21524 32 : OMP_CLAUSE_CHAIN (u) = list;
21525 32 : parens.skip_until_found_close (parser);
21526 32 : return u;
21527 : }
21528 :
21529 : /* OpenMP 5.0:
21530 : destroy ( variable-list ) */
21531 :
21532 : static tree
21533 41 : c_parser_omp_clause_destroy (c_parser *parser, tree list)
21534 : {
21535 41 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_DESTROY, list);
21536 86 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21537 45 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21538 41 : return nl;
21539 : }
21540 :
21541 : /* OpenMP 5.1:
21542 : prefer_type ( const-int-expr-or-string-literal-list )
21543 :
21544 : OpenMP 6.0:
21545 : prefer_type ( { preference-selector-list }, { ... } )
21546 :
21547 : with preference-selector being:
21548 : fr ( identifier-or-string-literal-list )
21549 : attr ( string-list )
21550 :
21551 : Data format:
21552 : For the foreign runtime identifiers, string values are converted to
21553 : their integer value; unknown string or integer values are set to
21554 : GOMP_INTEROP_IFR_KNOWN.
21555 :
21556 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
21557 : (b) for any 'fr', its integer value.
21558 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
21559 : (c) GOMP_INTEROP_IFR_SEPARATOR
21560 : (d) list of \0-terminated non-empty strings for 'attr'
21561 : (e) '\0'
21562 : Tailing '\0'. */
21563 :
21564 : static tree
21565 125 : c_parser_omp_modifier_prefer_type (c_parser *parser)
21566 : {
21567 125 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
21568 2 : return error_mark_node;
21569 :
21570 123 : std::string str;
21571 :
21572 : /* Old Format: const-int-expr-or-string-literal-list */
21573 123 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
21574 240 : while (true)
21575 : {
21576 150 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21577 150 : if (c_parser_next_token_is (parser, CPP_STRING))
21578 : {
21579 117 : c_expr cval = c_parser_string_literal (parser, false, false);
21580 117 : if (cval.value == error_mark_node)
21581 1 : return error_mark_node;
21582 117 : if ((size_t) TREE_STRING_LENGTH (cval.value)
21583 117 : != strlen (TREE_STRING_POINTER (cval.value)) + 1)
21584 : {
21585 1 : error_at (cval.get_location (), "string literal must "
21586 : "not contain %<\\0%>");
21587 1 : parser->error = true;
21588 1 : return error_mark_node;
21589 : }
21590 :
21591 116 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (cval.value));
21592 116 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
21593 3 : warning_at (cval.get_location (), OPT_Wopenmp,
21594 : "unknown foreign runtime identifier %qs",
21595 3 : TREE_STRING_POINTER (cval.value));
21596 116 : str += c;
21597 : }
21598 : else
21599 : {
21600 33 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
21601 33 : tree value = c_fully_fold (cval.value, false, NULL);
21602 64 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
21603 61 : && TREE_CODE (value) != INTEGER_CST)
21604 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
21605 : false, true).value;
21606 33 : if (TREE_CODE (value) != INTEGER_CST
21607 28 : || !tree_fits_shwi_p (value))
21608 : {
21609 5 : c_parser_error (parser, "expected string literal or constant "
21610 : "integer expression");
21611 5 : return error_mark_node;
21612 : }
21613 28 : HOST_WIDE_INT n = tree_to_shwi (value);
21614 28 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
21615 : {
21616 3 : warning_at (cval.get_location (), OPT_Wopenmp,
21617 : "unknown foreign runtime identifier %qwd", n);
21618 3 : n = GOMP_INTEROP_IFR_UNKNOWN;
21619 : }
21620 28 : str += (char) n;
21621 : }
21622 144 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21623 144 : str += '\0';
21624 144 : if (c_parser_next_token_is (parser, CPP_COMMA))
21625 : {
21626 90 : c_parser_consume_token (parser);
21627 90 : continue;
21628 : }
21629 54 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
21630 : "expected %<,%> or %<)%>"))
21631 0 : return error_mark_node;
21632 54 : str += '\0';
21633 54 : tree res = build_string (str.length (), str.data ());
21634 54 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
21635 54 : str.length ());
21636 54 : return res;
21637 90 : }
21638 :
21639 : /* New format. */
21640 63 : std::string str2;
21641 128 : while (true)
21642 : {
21643 128 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
21644 1 : return error_mark_node;
21645 127 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21646 127 : str2.clear ();
21647 127 : bool has_fr = false;
21648 205 : while (true)
21649 : {
21650 166 : c_token *tok = c_parser_peek_token (parser);
21651 166 : if (tok->type != CPP_NAME
21652 166 : || (strcmp("fr", IDENTIFIER_POINTER (tok->value)) != 0
21653 63 : && strcmp("attr", IDENTIFIER_POINTER (tok->value)) != 0))
21654 : {
21655 0 : c_parser_error (parser, "expected %<fr%> or %<attr%> preference "
21656 : "selector");
21657 0 : return error_mark_node;
21658 : }
21659 166 : c_parser_consume_token (parser);
21660 166 : bool is_fr = IDENTIFIER_POINTER (tok->value)[0] == 'f';
21661 166 : if (is_fr && has_fr)
21662 : {
21663 1 : c_parser_error (parser, "duplicated %<fr%> preference selector");
21664 1 : return error_mark_node;
21665 : }
21666 165 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
21667 0 : return error_mark_node;
21668 175 : while (true)
21669 : {
21670 170 : if (c_parser_next_token_is (parser, CPP_STRING))
21671 : {
21672 133 : c_expr cval = c_parser_string_literal (parser, false, false);
21673 133 : tree value = cval.value;
21674 133 : if (value == error_mark_node)
21675 6 : return error_mark_node;
21676 133 : if ((size_t) TREE_STRING_LENGTH (value)
21677 133 : != strlen (TREE_STRING_POINTER (value)) + 1)
21678 : {
21679 2 : error_at (cval.get_location (), "string literal must "
21680 : "not contain %<\\0%>");
21681 2 : parser->error = true;
21682 2 : return error_mark_node;
21683 : }
21684 131 : if (!is_fr)
21685 : {
21686 67 : if (!startswith (TREE_STRING_POINTER (value), "ompx_"))
21687 : {
21688 1 : error_at (cval.get_location (),
21689 : "%<attr%> string literal must start with "
21690 : "%<ompx_%>");
21691 1 : parser->error = true;
21692 1 : return error_mark_node;
21693 : }
21694 66 : if (strchr (TREE_STRING_POINTER (value), ','))
21695 : {
21696 2 : error_at (cval.get_location (),
21697 : "%<attr%> string literal must not contain "
21698 : "a comma");
21699 2 : parser->error = true;
21700 2 : return error_mark_node;
21701 : }
21702 64 : str2 += TREE_STRING_POINTER (value);
21703 64 : str2 += '\0';
21704 : }
21705 : else
21706 : {
21707 64 : if (*TREE_STRING_POINTER (value) == '\0')
21708 : {
21709 1 : c_parser_error (parser, "non-empty string literal expected");
21710 1 : return error_mark_node;
21711 : }
21712 63 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (value));
21713 63 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
21714 3 : warning_at (cval.get_location (), OPT_Wopenmp,
21715 : "unknown foreign runtime identifier %qs",
21716 3 : TREE_STRING_POINTER (value));
21717 63 : str += c;
21718 63 : has_fr = true;
21719 : }
21720 : }
21721 37 : else if (!is_fr)
21722 : {
21723 1 : c_parser_error (parser, "expected string literal");
21724 1 : return error_mark_node;
21725 : }
21726 : else
21727 : {
21728 36 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
21729 36 : tree value = c_fully_fold (cval.value, false, NULL);
21730 70 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
21731 68 : && TREE_CODE (value) != INTEGER_CST)
21732 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
21733 : false, true).value;
21734 :
21735 36 : if (TREE_CODE (value) != INTEGER_CST
21736 32 : || !tree_fits_shwi_p (value))
21737 : {
21738 4 : c_parser_error (parser, "expected string literal or "
21739 : "constant integer expression");
21740 4 : return error_mark_node;
21741 : }
21742 32 : HOST_WIDE_INT n = tree_to_shwi (value);
21743 32 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
21744 : {
21745 0 : warning_at (cval.get_location (), OPT_Wopenmp,
21746 : "unknown foreign runtime identifier %qwd", n);
21747 0 : n = GOMP_INTEROP_IFR_UNKNOWN;
21748 : }
21749 32 : str += (char) n;
21750 32 : has_fr = true;
21751 : }
21752 164 : if (!is_fr
21753 223 : && c_parser_next_token_is (parser, CPP_COMMA))
21754 : {
21755 5 : c_parser_consume_token (parser);
21756 5 : continue;
21757 : }
21758 213 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
21759 : is_fr ? G_("expected %<)%>")
21760 : : G_("expected %<)%> or %<,%>")))
21761 4 : return error_mark_node;
21762 150 : break;
21763 5 : }
21764 150 : if (c_parser_next_token_is (parser, CPP_COMMA))
21765 : {
21766 39 : c_parser_consume_token (parser);
21767 39 : continue;
21768 : }
21769 111 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
21770 : break;
21771 2 : c_parser_error (parser, "expected %<,%> or %<}%>");
21772 2 : return error_mark_node;
21773 39 : }
21774 109 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21775 109 : str += str2;
21776 109 : str += '\0';
21777 109 : c_parser_consume_token (parser);
21778 109 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
21779 : break;
21780 66 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
21781 1 : return error_mark_node;
21782 : }
21783 43 : c_parser_consume_token (parser);
21784 43 : str += '\0';
21785 43 : tree res = build_string (str.length (), str.data ());
21786 43 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
21787 43 : str.length ());
21788 43 : return res;
21789 186 : }
21790 :
21791 : /* OpenMP 5.1
21792 : modifiers of the 'init' clause, used by the 'init' and the
21793 : 'append_args' clauses.
21794 :
21795 : Modifiers:
21796 : target
21797 : targetsync
21798 : prefer_type (preference-specification)
21799 :
21800 : Returns 'false' if an error has been issued. */
21801 :
21802 : static bool
21803 234 : c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target,
21804 : bool *targetsync, tree *prefer_type_tree)
21805 : {
21806 234 : *target = false;
21807 234 : *targetsync = false;
21808 234 : *prefer_type_tree = NULL_TREE;
21809 :
21810 540 : do
21811 : {
21812 387 : c_token *tok = c_parser_peek_token (parser);
21813 387 : if (tok->type != CPP_NAME)
21814 1 : goto fail;
21815 386 : const char *p = IDENTIFIER_POINTER (tok->value);
21816 386 : if (strcmp ("targetsync", p) == 0)
21817 : {
21818 105 : if (*targetsync)
21819 1 : error_at (tok->location, "duplicate %<targetsync%> modifier");
21820 105 : *targetsync = true;
21821 105 : c_parser_consume_token (parser);
21822 : }
21823 281 : else if (strcmp ("target", p) == 0)
21824 : {
21825 148 : if (*target)
21826 3 : error_at (tok->location, "duplicate %<target%> modifier");
21827 148 : *target = true;
21828 148 : c_parser_consume_token (parser);
21829 : }
21830 133 : else if (strcmp ("prefer_type", p) == 0)
21831 : {
21832 125 : if (*prefer_type_tree != NULL_TREE)
21833 1 : error_at (tok->location, "duplicate %<prefer_type%> modifier");
21834 125 : c_parser_consume_token (parser);
21835 125 : *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser);
21836 125 : if (*prefer_type_tree == error_mark_node)
21837 : return false;
21838 : }
21839 : else
21840 8 : goto fail;
21841 350 : tok = c_parser_peek_token (parser);
21842 350 : if (tok->type == CPP_COMMA)
21843 : {
21844 153 : c_parser_consume_token (parser);
21845 153 : continue;
21846 : }
21847 : /* Unknown token - either done or an error; handle it in the caller. */
21848 : return true;
21849 153 : }
21850 : while (true);
21851 :
21852 9 : fail:
21853 9 : c_parser_error (parser,
21854 : "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
21855 9 : return false;
21856 : }
21857 :
21858 : /* OpenMP 5.1:
21859 : init ( [init-modifier-list : ] variable-list )
21860 :
21861 : Modifiers:
21862 : target
21863 : targetsync
21864 : prefer_type (preference-specification) */
21865 :
21866 : static tree
21867 167 : c_parser_omp_clause_init (c_parser *parser, tree list)
21868 : {
21869 167 : location_t loc = c_parser_peek_token (parser)->location;
21870 :
21871 167 : matching_parens parens;
21872 167 : if (!parens.require_open (parser))
21873 : return list;
21874 :
21875 167 : bool target = false;
21876 167 : bool targetsync = false;
21877 167 : tree prefer_type_tree = NULL_TREE;
21878 :
21879 167 : if (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
21880 : &prefer_type_tree)
21881 167 : || !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
21882 : {
21883 39 : if (prefer_type_tree != error_mark_node)
21884 11 : parens.skip_until_found_close (parser);
21885 39 : return list;
21886 : }
21887 :
21888 128 : if (!target && !targetsync)
21889 2 : error_at (loc,
21890 : "missing required %<target%> and/or %<targetsync%> modifier");
21891 :
21892 128 : tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list,
21893 : false);
21894 128 : parens.skip_until_found_close (parser);
21895 :
21896 280 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21897 : {
21898 152 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21899 152 : if (target)
21900 90 : OMP_CLAUSE_INIT_TARGET (c) = 1;
21901 152 : if (targetsync)
21902 81 : OMP_CLAUSE_INIT_TARGETSYNC (c) = 1;
21903 152 : if (prefer_type_tree)
21904 73 : OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree;
21905 : }
21906 : return nl;
21907 : }
21908 :
21909 : /* OpenMP 5.0:
21910 : use ( variable-list ) */
21911 :
21912 : static tree
21913 43 : c_parser_omp_clause_use (c_parser *parser, tree list)
21914 : {
21915 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE, list);
21916 : }
21917 :
21918 : /* OpenMP 6.0:
21919 : interop ( variable-list ) */
21920 :
21921 : static tree
21922 43 : c_parser_omp_clause_interop (c_parser *parser, tree list)
21923 : {
21924 43 : check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop");
21925 43 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list);
21926 102 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21927 : {
21928 59 : TREE_USED (OMP_CLAUSE_DECL (c)) = 1;
21929 59 : DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1;
21930 : }
21931 43 : return nl;
21932 : }
21933 :
21934 : /* Parse all OpenACC clauses. The set clauses allowed by the directive
21935 : is a bitmask in MASK. Return the list of clauses found. */
21936 :
21937 : static tree
21938 5352 : c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
21939 : const char *where, bool finish_p = true,
21940 : bool target_p = false)
21941 : {
21942 5352 : tree clauses = NULL;
21943 5352 : bool first = true;
21944 :
21945 12079 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
21946 : {
21947 6773 : location_t here;
21948 6773 : pragma_omp_clause c_kind;
21949 6773 : const char *c_name;
21950 6773 : tree prev = clauses;
21951 :
21952 9391 : if (!first && c_parser_next_token_is (parser, CPP_COMMA))
21953 11 : c_parser_consume_token (parser);
21954 :
21955 6773 : here = c_parser_peek_token (parser)->location;
21956 6773 : c_kind = c_parser_omp_clause_name (parser);
21957 :
21958 6773 : switch (c_kind)
21959 : {
21960 240 : case PRAGMA_OACC_CLAUSE_ASYNC:
21961 240 : clauses = c_parser_oacc_clause_async (parser, clauses);
21962 240 : c_name = "async";
21963 240 : break;
21964 125 : case PRAGMA_OACC_CLAUSE_AUTO:
21965 125 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
21966 : clauses);
21967 125 : c_name = "auto";
21968 125 : break;
21969 27 : case PRAGMA_OACC_CLAUSE_ATTACH:
21970 27 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21971 27 : c_name = "attach";
21972 27 : break;
21973 59 : case PRAGMA_OACC_CLAUSE_COLLAPSE:
21974 59 : clauses = c_parser_omp_clause_collapse (parser, clauses);
21975 59 : c_name = "collapse";
21976 59 : break;
21977 806 : case PRAGMA_OACC_CLAUSE_COPY:
21978 806 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21979 806 : c_name = "copy";
21980 806 : break;
21981 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
21982 359 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21983 359 : c_name = "copyin";
21984 359 : break;
21985 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
21986 390 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21987 390 : c_name = "copyout";
21988 390 : break;
21989 94 : case PRAGMA_OACC_CLAUSE_CREATE:
21990 94 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21991 94 : c_name = "create";
21992 94 : break;
21993 68 : case PRAGMA_OACC_CLAUSE_DELETE:
21994 68 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21995 68 : c_name = "delete";
21996 68 : break;
21997 88 : case PRAGMA_OMP_CLAUSE_DEFAULT:
21998 88 : clauses = c_parser_omp_clause_default (parser, clauses, true);
21999 88 : c_name = "default";
22000 88 : break;
22001 20 : case PRAGMA_OACC_CLAUSE_DETACH:
22002 20 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22003 20 : c_name = "detach";
22004 20 : break;
22005 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
22006 36 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22007 36 : c_name = "device";
22008 36 : break;
22009 57 : case PRAGMA_OACC_CLAUSE_DEVICEPTR:
22010 57 : clauses = c_parser_oacc_data_clause_deviceptr (parser, clauses);
22011 57 : c_name = "deviceptr";
22012 57 : break;
22013 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
22014 16 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22015 16 : c_name = "device_resident";
22016 16 : break;
22017 12 : case PRAGMA_OACC_CLAUSE_FINALIZE:
22018 12 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
22019 : clauses);
22020 12 : c_name = "finalize";
22021 12 : break;
22022 113 : case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
22023 113 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
22024 113 : c_name = "firstprivate";
22025 113 : break;
22026 589 : case PRAGMA_OACC_CLAUSE_GANG:
22027 589 : c_name = "gang";
22028 589 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
22029 : c_name, clauses);
22030 589 : break;
22031 41 : case PRAGMA_OACC_CLAUSE_HOST:
22032 41 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22033 41 : c_name = "host";
22034 41 : break;
22035 105 : case PRAGMA_OACC_CLAUSE_IF:
22036 105 : clauses = c_parser_omp_clause_if (parser, clauses, false);
22037 105 : c_name = "if";
22038 105 : break;
22039 19 : case PRAGMA_OACC_CLAUSE_IF_PRESENT:
22040 19 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
22041 : clauses);
22042 19 : c_name = "if_present";
22043 19 : break;
22044 45 : case PRAGMA_OACC_CLAUSE_INDEPENDENT:
22045 45 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
22046 : clauses);
22047 45 : c_name = "independent";
22048 45 : break;
22049 13 : case PRAGMA_OACC_CLAUSE_LINK:
22050 13 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22051 13 : c_name = "link";
22052 13 : break;
22053 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
22054 10 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22055 10 : c_name = "no_create";
22056 10 : break;
22057 25 : case PRAGMA_OACC_CLAUSE_NOHOST:
22058 25 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST,
22059 : clauses);
22060 25 : c_name = "nohost";
22061 25 : break;
22062 302 : case PRAGMA_OACC_CLAUSE_NUM_GANGS:
22063 302 : clauses = c_parser_oacc_single_int_clause (parser,
22064 : OMP_CLAUSE_NUM_GANGS,
22065 : clauses);
22066 302 : c_name = "num_gangs";
22067 302 : break;
22068 207 : case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
22069 207 : clauses = c_parser_oacc_single_int_clause (parser,
22070 : OMP_CLAUSE_NUM_WORKERS,
22071 : clauses);
22072 207 : c_name = "num_workers";
22073 207 : break;
22074 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
22075 128 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22076 128 : c_name = "present";
22077 128 : break;
22078 66 : case PRAGMA_OACC_CLAUSE_PRIVATE:
22079 66 : clauses = c_parser_omp_clause_private (parser, clauses);
22080 66 : c_name = "private";
22081 66 : break;
22082 905 : case PRAGMA_OACC_CLAUSE_REDUCTION:
22083 905 : clauses
22084 905 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
22085 : false, clauses);
22086 905 : c_name = "reduction";
22087 905 : break;
22088 66 : case PRAGMA_OACC_CLAUSE_SELF:
22089 66 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
22090 : /* OpenACC compute construct */
22091 48 : clauses = c_parser_oacc_compute_clause_self (parser, clauses);
22092 : else
22093 : /* OpenACC 'update' directive */
22094 18 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
22095 : c_name = "self";
22096 : break;
22097 261 : case PRAGMA_OACC_CLAUSE_SEQ:
22098 261 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
22099 : clauses);
22100 261 : c_name = "seq";
22101 261 : break;
22102 123 : case PRAGMA_OACC_CLAUSE_TILE:
22103 123 : clauses = c_parser_oacc_clause_tile (parser, clauses);
22104 123 : c_name = "tile";
22105 123 : break;
22106 21 : case PRAGMA_OACC_CLAUSE_USE_DEVICE:
22107 21 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
22108 21 : c_name = "use_device";
22109 21 : break;
22110 518 : case PRAGMA_OACC_CLAUSE_VECTOR:
22111 518 : c_name = "vector";
22112 518 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_VECTOR,
22113 : c_name, clauses);
22114 518 : break;
22115 223 : case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
22116 223 : clauses = c_parser_oacc_single_int_clause (parser,
22117 : OMP_CLAUSE_VECTOR_LENGTH,
22118 : clauses);
22119 223 : c_name = "vector_length";
22120 223 : break;
22121 97 : case PRAGMA_OACC_CLAUSE_WAIT:
22122 97 : clauses = c_parser_oacc_clause_wait (parser, clauses);
22123 97 : c_name = "wait";
22124 97 : break;
22125 453 : case PRAGMA_OACC_CLAUSE_WORKER:
22126 453 : c_name = "worker";
22127 453 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_WORKER,
22128 : c_name, clauses);
22129 453 : break;
22130 46 : default:
22131 46 : c_parser_error (parser, "expected an OpenACC clause");
22132 46 : goto saw_error;
22133 : }
22134 :
22135 6727 : first = false;
22136 :
22137 6727 : if (((mask >> c_kind) & 1) == 0)
22138 : {
22139 : /* Remove the invalid clause(s) from the list to avoid
22140 : confusing the rest of the compiler. */
22141 18 : clauses = prev;
22142 18 : error_at (here, "%qs is not valid for %qs", c_name, where);
22143 : }
22144 : }
22145 :
22146 5306 : saw_error:
22147 5352 : c_parser_skip_to_pragma_eol (parser);
22148 :
22149 5352 : if (finish_p)
22150 7831 : return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
22151 4656 : : C_ORT_ACC);
22152 :
22153 : return clauses;
22154 : }
22155 :
22156 : /* Parse all OpenMP clauses. The set clauses allowed by the directive
22157 : is a bitmask in MASK. Return the list of clauses found.
22158 : FINISH_P set if c_finish_omp_clauses should be called.
22159 : NESTED non-zero if clauses should be terminated by closing paren instead
22160 : of end of pragma. If it is 2, additionally commas are required in between
22161 : the clauses. */
22162 :
22163 : static tree
22164 20140 : c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
22165 : const char *where, bool finish_p = true,
22166 : int nested = 0)
22167 : {
22168 20140 : tree clauses = NULL;
22169 20140 : bool first = true;
22170 :
22171 47561 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
22172 : {
22173 27513 : location_t here;
22174 27513 : pragma_omp_clause c_kind;
22175 27513 : const char *c_name;
22176 27513 : tree prev = clauses;
22177 :
22178 27610 : if (nested && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
22179 : break;
22180 :
22181 27491 : if (!first || nested != 2)
22182 : {
22183 27468 : if (c_parser_next_token_is (parser, CPP_COMMA))
22184 2697 : c_parser_consume_token (parser);
22185 24771 : else if (nested == 2)
22186 3 : error_at (c_parser_peek_token (parser)->location,
22187 : "clauses in %<simd%> trait should be separated "
22188 : "by %<,%>");
22189 : }
22190 :
22191 27491 : here = c_parser_peek_token (parser)->location;
22192 27491 : c_kind = c_parser_omp_clause_name (parser);
22193 :
22194 27491 : switch (c_kind)
22195 : {
22196 116 : case PRAGMA_OMP_CLAUSE_BIND:
22197 116 : clauses = c_parser_omp_clause_bind (parser, clauses);
22198 116 : c_name = "bind";
22199 116 : break;
22200 2895 : case PRAGMA_OMP_CLAUSE_COLLAPSE:
22201 2895 : clauses = c_parser_omp_clause_collapse (parser, clauses);
22202 2895 : c_name = "collapse";
22203 2895 : break;
22204 101 : case PRAGMA_OMP_CLAUSE_COPYIN:
22205 101 : clauses = c_parser_omp_clause_copyin (parser, clauses);
22206 101 : c_name = "copyin";
22207 101 : break;
22208 21 : case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
22209 21 : clauses = c_parser_omp_clause_copyprivate (parser, clauses);
22210 21 : c_name = "copyprivate";
22211 21 : break;
22212 641 : case PRAGMA_OMP_CLAUSE_DEFAULT:
22213 641 : clauses = c_parser_omp_clause_default (parser, clauses, false);
22214 641 : c_name = "default";
22215 641 : break;
22216 34 : case PRAGMA_OMP_CLAUSE_DETACH:
22217 34 : clauses = c_parser_omp_clause_detach (parser, clauses);
22218 34 : c_name = "detach";
22219 34 : break;
22220 63 : case PRAGMA_OMP_CLAUSE_FILTER:
22221 63 : clauses = c_parser_omp_clause_filter (parser, clauses);
22222 63 : c_name = "filter";
22223 63 : break;
22224 677 : case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
22225 677 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
22226 677 : c_name = "firstprivate";
22227 677 : break;
22228 99 : case PRAGMA_OMP_CLAUSE_FINAL:
22229 99 : clauses = c_parser_omp_clause_final (parser, clauses);
22230 99 : c_name = "final";
22231 99 : break;
22232 62 : case PRAGMA_OMP_CLAUSE_GRAINSIZE:
22233 62 : clauses = c_parser_omp_clause_grainsize (parser, clauses);
22234 62 : c_name = "grainsize";
22235 62 : break;
22236 29 : case PRAGMA_OMP_CLAUSE_HINT:
22237 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
22238 29 : c_name = "hint";
22239 29 : break;
22240 238 : case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
22241 238 : clauses = c_parser_omp_clause_defaultmap (parser, clauses);
22242 238 : c_name = "defaultmap";
22243 238 : break;
22244 779 : case PRAGMA_OMP_CLAUSE_IF:
22245 779 : clauses = c_parser_omp_clause_if (parser, clauses, true);
22246 779 : c_name = "if";
22247 779 : break;
22248 321 : case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
22249 321 : clauses
22250 321 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
22251 : true, clauses);
22252 321 : c_name = "in_reduction";
22253 321 : break;
22254 26 : case PRAGMA_OMP_CLAUSE_INDIRECT:
22255 26 : clauses = c_parser_omp_clause_indirect (parser, clauses);
22256 26 : c_name = "indirect";
22257 26 : break;
22258 732 : case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
22259 732 : clauses = c_parser_omp_clause_lastprivate (parser, clauses);
22260 732 : c_name = "lastprivate";
22261 732 : break;
22262 79 : case PRAGMA_OMP_CLAUSE_MERGEABLE:
22263 79 : clauses = c_parser_omp_clause_mergeable (parser, clauses);
22264 79 : c_name = "mergeable";
22265 79 : break;
22266 391 : case PRAGMA_OMP_CLAUSE_NOWAIT:
22267 391 : clauses = c_parser_omp_clause_nowait (parser, clauses);
22268 391 : c_name = "nowait";
22269 391 : break;
22270 50 : case PRAGMA_OMP_CLAUSE_NUM_TASKS:
22271 50 : clauses = c_parser_omp_clause_num_tasks (parser, clauses);
22272 50 : c_name = "num_tasks";
22273 50 : break;
22274 426 : case PRAGMA_OMP_CLAUSE_NUM_THREADS:
22275 426 : clauses = c_parser_omp_clause_num_threads (parser, clauses);
22276 426 : c_name = "num_threads";
22277 426 : break;
22278 376 : case PRAGMA_OMP_CLAUSE_ORDER:
22279 376 : clauses = c_parser_omp_clause_order (parser, clauses);
22280 376 : c_name = "order";
22281 376 : break;
22282 310 : case PRAGMA_OMP_CLAUSE_ORDERED:
22283 310 : clauses = c_parser_omp_clause_ordered (parser, clauses);
22284 310 : c_name = "ordered";
22285 310 : break;
22286 98 : case PRAGMA_OMP_CLAUSE_PRIORITY:
22287 98 : clauses = c_parser_omp_clause_priority (parser, clauses);
22288 98 : c_name = "priority";
22289 98 : break;
22290 679 : case PRAGMA_OMP_CLAUSE_PRIVATE:
22291 679 : clauses = c_parser_omp_clause_private (parser, clauses);
22292 679 : c_name = "private";
22293 679 : break;
22294 1781 : case PRAGMA_OMP_CLAUSE_REDUCTION:
22295 1781 : clauses
22296 1781 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
22297 : true, clauses);
22298 1781 : c_name = "reduction";
22299 1781 : break;
22300 3469 : case PRAGMA_OMP_CLAUSE_SCHEDULE:
22301 3469 : clauses = c_parser_omp_clause_schedule (parser, clauses);
22302 3469 : c_name = "schedule";
22303 3469 : break;
22304 691 : case PRAGMA_OMP_CLAUSE_SHARED:
22305 691 : clauses = c_parser_omp_clause_shared (parser, clauses);
22306 691 : c_name = "shared";
22307 691 : break;
22308 86 : case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
22309 86 : clauses
22310 86 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
22311 : true, clauses);
22312 86 : c_name = "task_reduction";
22313 86 : break;
22314 97 : case PRAGMA_OMP_CLAUSE_UNTIED:
22315 97 : clauses = c_parser_omp_clause_untied (parser, clauses);
22316 97 : c_name = "untied";
22317 97 : break;
22318 69 : case PRAGMA_OMP_CLAUSE_INBRANCH:
22319 69 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
22320 : clauses);
22321 69 : c_name = "inbranch";
22322 69 : break;
22323 121 : case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
22324 121 : clauses = c_parser_omp_clause_nontemporal (parser, clauses);
22325 121 : c_name = "nontemporal";
22326 121 : break;
22327 136 : case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
22328 136 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH,
22329 : clauses);
22330 136 : c_name = "notinbranch";
22331 136 : break;
22332 107 : case PRAGMA_OMP_CLAUSE_PARALLEL:
22333 107 : clauses
22334 107 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
22335 : clauses);
22336 107 : c_name = "parallel";
22337 107 : if (!first)
22338 : {
22339 0 : clause_not_first:
22340 0 : error_at (here, "%qs must be the first clause of %qs",
22341 : c_name, where);
22342 0 : clauses = prev;
22343 : }
22344 : break;
22345 84 : case PRAGMA_OMP_CLAUSE_FOR:
22346 84 : clauses
22347 84 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
22348 : clauses);
22349 84 : c_name = "for";
22350 84 : if (!first)
22351 0 : goto clause_not_first;
22352 : break;
22353 78 : case PRAGMA_OMP_CLAUSE_SECTIONS:
22354 78 : clauses
22355 78 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
22356 : clauses);
22357 78 : c_name = "sections";
22358 78 : if (!first)
22359 0 : goto clause_not_first;
22360 : break;
22361 110 : case PRAGMA_OMP_CLAUSE_TASKGROUP:
22362 110 : clauses
22363 110 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
22364 : clauses);
22365 110 : c_name = "taskgroup";
22366 110 : if (!first)
22367 0 : goto clause_not_first;
22368 : break;
22369 30 : case PRAGMA_OMP_CLAUSE_LINK:
22370 30 : clauses
22371 30 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LINK, clauses);
22372 30 : c_name = "link";
22373 30 : break;
22374 478 : case PRAGMA_OMP_CLAUSE_TO:
22375 478 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
22376 : {
22377 86 : gcc_rich_location richloc (here);
22378 86 : richloc.add_fixit_replace ("enter");
22379 86 : warning_at (&richloc, OPT_Wdeprecated_openmp,
22380 : "%<to%> clause with %<declare target%> deprecated "
22381 : "since OpenMP 5.2, use %<enter%>");
22382 86 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
22383 : clauses);
22384 191 : for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
22385 105 : OMP_CLAUSE_ENTER_TO (c) = 1;
22386 86 : clauses = nl;
22387 86 : }
22388 : else
22389 392 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_TO,
22390 : clauses);
22391 : c_name = "to";
22392 : break;
22393 2450 : case PRAGMA_OMP_CLAUSE_FROM:
22394 2450 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_FROM,
22395 : clauses);
22396 2450 : c_name = "from";
22397 2450 : break;
22398 115 : case PRAGMA_OMP_CLAUSE_UNIFORM:
22399 115 : clauses = c_parser_omp_clause_uniform (parser, clauses);
22400 115 : c_name = "uniform";
22401 115 : break;
22402 190 : case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
22403 190 : clauses = c_parser_omp_clause_num_teams (parser, clauses);
22404 190 : c_name = "num_teams";
22405 190 : break;
22406 154 : case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
22407 154 : clauses = c_parser_omp_clause_thread_limit (parser, clauses);
22408 154 : c_name = "thread_limit";
22409 154 : break;
22410 228 : case PRAGMA_OMP_CLAUSE_ALIGNED:
22411 228 : clauses = c_parser_omp_clause_aligned (parser, clauses);
22412 228 : c_name = "aligned";
22413 228 : break;
22414 479 : case PRAGMA_OMP_CLAUSE_ALLOCATE:
22415 479 : clauses = c_parser_omp_clause_allocate (parser, clauses);
22416 479 : c_name = "allocate";
22417 479 : break;
22418 476 : case PRAGMA_OMP_CLAUSE_LINEAR:
22419 476 : clauses = c_parser_omp_clause_linear (parser, clauses);
22420 476 : c_name = "linear";
22421 476 : break;
22422 30 : case PRAGMA_OMP_CLAUSE_USES_ALLOCATORS:
22423 30 : clauses = c_parser_omp_clause_uses_allocators (parser, clauses);
22424 30 : c_name = "uses_allocators";
22425 30 : break;
22426 146 : case PRAGMA_OMP_CLAUSE_AFFINITY:
22427 146 : clauses = c_parser_omp_clause_affinity (parser, clauses);
22428 146 : c_name = "affinity";
22429 146 : break;
22430 857 : case PRAGMA_OMP_CLAUSE_DEPEND:
22431 857 : clauses = c_parser_omp_clause_depend (parser, clauses, here);
22432 857 : c_name = "depend";
22433 857 : break;
22434 145 : case PRAGMA_OMP_CLAUSE_DOACROSS:
22435 145 : clauses = c_parser_omp_clause_doacross (parser, clauses);
22436 145 : c_name = "doacross";
22437 145 : break;
22438 41 : case PRAGMA_OMP_CLAUSE_DESTROY:
22439 41 : clauses = c_parser_omp_clause_destroy (parser, clauses);
22440 41 : c_name = "destroy";
22441 41 : break;
22442 21 : case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
22443 21 : clauses = c_parser_omp_clause_dyn_groupprivate (parser, clauses);
22444 21 : c_name = "dyn_groupprivate";
22445 21 : break;
22446 167 : case PRAGMA_OMP_CLAUSE_INIT:
22447 167 : clauses = c_parser_omp_clause_init (parser, clauses);
22448 167 : c_name = "init";
22449 167 : break;
22450 43 : case PRAGMA_OMP_CLAUSE_USE:
22451 43 : clauses = c_parser_omp_clause_use (parser, clauses);
22452 43 : c_name = "use";
22453 43 : break;
22454 43 : case PRAGMA_OMP_CLAUSE_INTEROP:
22455 43 : clauses = c_parser_omp_clause_interop (parser, clauses);
22456 43 : c_name = "interop";
22457 43 : break;
22458 1748 : case PRAGMA_OMP_CLAUSE_MAP:
22459 1748 : clauses = c_parser_omp_clause_map (parser, clauses, false);
22460 1748 : c_name = "map";
22461 1748 : break;
22462 10 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
22463 10 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
22464 10 : c_name = "use_device_ptr";
22465 10 : break;
22466 35 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
22467 35 : clauses = c_parser_omp_clause_use_device_addr (parser, clauses);
22468 35 : c_name = "use_device_addr";
22469 35 : break;
22470 88 : case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
22471 88 : clauses = c_parser_omp_clause_has_device_addr (parser, clauses);
22472 88 : c_name = "has_device_addr";
22473 88 : break;
22474 115 : case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
22475 115 : clauses = c_parser_omp_clause_is_device_ptr (parser, clauses);
22476 115 : c_name = "is_device_ptr";
22477 115 : break;
22478 369 : case PRAGMA_OMP_CLAUSE_DEVICE:
22479 369 : clauses = c_parser_omp_clause_device (parser, clauses);
22480 369 : c_name = "device";
22481 369 : break;
22482 1582 : case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
22483 1582 : clauses = c_parser_omp_clause_dist_schedule (parser, clauses);
22484 1582 : c_name = "dist_schedule";
22485 1582 : break;
22486 195 : case PRAGMA_OMP_CLAUSE_PROC_BIND:
22487 195 : clauses = c_parser_omp_clause_proc_bind (parser, clauses);
22488 195 : c_name = "proc_bind";
22489 195 : break;
22490 51 : case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
22491 51 : clauses = c_parser_omp_clause_device_type (parser, clauses);
22492 51 : c_name = "device_type";
22493 51 : break;
22494 227 : case PRAGMA_OMP_CLAUSE_SAFELEN:
22495 227 : clauses = c_parser_omp_clause_safelen (parser, clauses);
22496 227 : c_name = "safelen";
22497 227 : break;
22498 324 : case PRAGMA_OMP_CLAUSE_SIMDLEN:
22499 324 : clauses = c_parser_omp_clause_simdlen (parser, clauses);
22500 324 : c_name = "simdlen";
22501 324 : break;
22502 18 : case PRAGMA_OMP_CLAUSE_NOGROUP:
22503 18 : clauses = c_parser_omp_clause_nogroup (parser, clauses);
22504 18 : c_name = "nogroup";
22505 18 : break;
22506 46 : case PRAGMA_OMP_CLAUSE_THREADS:
22507 46 : clauses
22508 46 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS,
22509 : clauses);
22510 46 : c_name = "threads";
22511 46 : break;
22512 57 : case PRAGMA_OMP_CLAUSE_SIMD:
22513 57 : clauses
22514 57 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD,
22515 : clauses);
22516 57 : c_name = "simd";
22517 57 : break;
22518 45 : case PRAGMA_OMP_CLAUSE_ENTER:
22519 45 : clauses
22520 45 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
22521 : clauses);
22522 45 : c_name = "enter";
22523 45 : break;
22524 69 : case PRAGMA_OMP_CLAUSE_FULL:
22525 69 : c_name = "full";
22526 69 : clauses = c_parser_omp_clause_full (parser, clauses);
22527 69 : break;
22528 230 : case PRAGMA_OMP_CLAUSE_PARTIAL:
22529 230 : c_name = "partial";
22530 230 : clauses = c_parser_omp_clause_partial (parser, clauses);
22531 230 : break;
22532 24 : case PRAGMA_OMP_CLAUSE_NOVARIANTS:
22533 24 : c_name = "novariants";
22534 24 : clauses = c_parser_omp_clause_novariants (parser, clauses);
22535 24 : break;
22536 23 : case PRAGMA_OMP_CLAUSE_NOCONTEXT:
22537 23 : c_name = "nocontext";
22538 23 : clauses = c_parser_omp_clause_nocontext (parser, clauses);
22539 23 : break;
22540 70 : default:
22541 70 : c_parser_error (parser, "expected an OpenMP clause");
22542 70 : goto saw_error;
22543 : }
22544 :
22545 27421 : first = false;
22546 :
22547 27421 : if (((mask >> c_kind) & 1) == 0)
22548 : {
22549 : /* Remove the invalid clause(s) from the list to avoid
22550 : confusing the rest of the compiler. */
22551 24 : clauses = prev;
22552 24 : error_at (here, "%qs is not valid for %qs", c_name, where);
22553 : }
22554 : }
22555 :
22556 20048 : saw_error:
22557 20140 : if (!nested)
22558 20117 : c_parser_skip_to_pragma_eol (parser);
22559 :
22560 20140 : if (finish_p)
22561 : {
22562 11431 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
22563 399 : return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
22564 11032 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE)) != 0)
22565 183 : return c_finish_omp_clauses (clauses, C_ORT_OMP_INTEROP);
22566 10849 : return c_finish_omp_clauses (clauses, C_ORT_OMP);
22567 : }
22568 :
22569 : return clauses;
22570 : }
22571 :
22572 : /* OpenACC 2.0, OpenMP 2.5:
22573 : structured-block:
22574 : statement
22575 :
22576 : In practice, we're also interested in adding the statement to an
22577 : outer node. So it is convenient if we work around the fact that
22578 : c_parser_statement calls add_stmt. */
22579 :
22580 : static tree
22581 6703 : c_parser_omp_structured_block (c_parser *parser, bool *if_p)
22582 : {
22583 6703 : tree stmt = push_stmt_list ();
22584 6703 : parser->omp_attrs_forbidden_p = true;
22585 6703 : c_parser_statement (parser, if_p);
22586 6703 : return pop_stmt_list (stmt);
22587 : }
22588 :
22589 : /* OpenACC 2.0:
22590 : # pragma acc cache (variable-list) new-line
22591 :
22592 : OpenACC 2.7:
22593 : # pragma acc cache (readonly: variable-list) new-line
22594 :
22595 : LOC is the location of the #pragma token.
22596 : */
22597 :
22598 : static tree
22599 137 : c_parser_oacc_cache (location_t loc, c_parser *parser)
22600 : {
22601 137 : tree stmt, clauses = NULL_TREE;
22602 137 : bool readonly = false;
22603 137 : location_t open_loc = c_parser_peek_token (parser)->location;
22604 137 : matching_parens parens;
22605 137 : if (parens.require_open (parser))
22606 : {
22607 135 : c_token *token = c_parser_peek_token (parser);
22608 135 : if (token->type == CPP_NAME
22609 131 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
22610 139 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
22611 : {
22612 4 : c_parser_consume_token (parser);
22613 4 : c_parser_consume_token (parser);
22614 4 : readonly = true;
22615 : }
22616 135 : clauses = c_parser_omp_variable_list (parser, open_loc,
22617 : OMP_CLAUSE__CACHE_, NULL_TREE);
22618 135 : parens.skip_until_found_close (parser);
22619 : }
22620 :
22621 135 : if (readonly)
22622 8 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
22623 4 : OMP_CLAUSE__CACHE__READONLY (c) = 1;
22624 :
22625 137 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22626 :
22627 137 : c_parser_skip_to_pragma_eol (parser);
22628 :
22629 137 : stmt = make_node (OACC_CACHE);
22630 137 : TREE_TYPE (stmt) = void_type_node;
22631 137 : OACC_CACHE_CLAUSES (stmt) = clauses;
22632 137 : SET_EXPR_LOCATION (stmt, loc);
22633 137 : add_stmt (stmt);
22634 :
22635 137 : return stmt;
22636 : }
22637 :
22638 : /* OpenACC 2.0:
22639 : # pragma acc data oacc-data-clause[optseq] new-line
22640 : structured-block
22641 :
22642 : LOC is the location of the #pragma token.
22643 : */
22644 :
22645 : #define OACC_DATA_CLAUSE_MASK \
22646 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22647 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22648 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22649 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22650 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22651 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22652 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22653 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22654 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22655 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
22656 :
22657 : static tree
22658 497 : c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
22659 : {
22660 497 : tree stmt, clauses, block;
22661 :
22662 497 : clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
22663 : "#pragma acc data");
22664 :
22665 497 : block = c_begin_omp_parallel ();
22666 497 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22667 :
22668 497 : stmt = c_finish_oacc_data (loc, clauses, block);
22669 :
22670 497 : return stmt;
22671 : }
22672 :
22673 : /* OpenACC 2.0:
22674 : # pragma acc declare oacc-data-clause[optseq] new-line
22675 : */
22676 :
22677 : #define OACC_DECLARE_CLAUSE_MASK \
22678 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22679 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22680 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22681 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22682 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22683 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
22684 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
22685 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
22686 :
22687 : static void
22688 144 : c_parser_oacc_declare (c_parser *parser)
22689 : {
22690 144 : location_t pragma_loc = c_parser_peek_token (parser)->location;
22691 144 : tree clauses, stmt, t, decl;
22692 :
22693 144 : bool error = false;
22694 :
22695 144 : c_parser_consume_pragma (parser);
22696 :
22697 144 : clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
22698 : "#pragma acc declare");
22699 144 : if (!clauses)
22700 : {
22701 2 : error_at (pragma_loc,
22702 : "no valid clauses specified in %<#pragma acc declare%>");
22703 2 : return;
22704 : }
22705 :
22706 296 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
22707 : {
22708 154 : location_t loc = OMP_CLAUSE_LOCATION (t);
22709 154 : decl = OMP_CLAUSE_DECL (t);
22710 154 : if (!DECL_P (decl))
22711 : {
22712 1 : error_at (loc, "array section in %<#pragma acc declare%>");
22713 1 : error = true;
22714 1 : continue;
22715 : }
22716 :
22717 153 : switch (OMP_CLAUSE_MAP_KIND (t))
22718 : {
22719 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
22720 : case GOMP_MAP_ALLOC:
22721 : case GOMP_MAP_TO:
22722 : case GOMP_MAP_FORCE_DEVICEPTR:
22723 : case GOMP_MAP_DEVICE_RESIDENT:
22724 : break;
22725 :
22726 13 : case GOMP_MAP_LINK:
22727 13 : if (!global_bindings_p ()
22728 13 : && (TREE_STATIC (decl)
22729 6 : || !DECL_EXTERNAL (decl)))
22730 : {
22731 2 : error_at (loc,
22732 : "%qD must be a global variable in "
22733 : "%<#pragma acc declare link%>",
22734 : decl);
22735 2 : error = true;
22736 2 : continue;
22737 : }
22738 : break;
22739 :
22740 42 : default:
22741 42 : if (global_bindings_p ())
22742 : {
22743 5 : error_at (loc, "invalid OpenACC clause at file scope");
22744 5 : error = true;
22745 5 : continue;
22746 : }
22747 37 : if (DECL_EXTERNAL (decl))
22748 : {
22749 10 : error_at (loc,
22750 : "invalid use of %<extern%> variable %qD "
22751 : "in %<#pragma acc declare%>", decl);
22752 10 : error = true;
22753 10 : continue;
22754 : }
22755 27 : else if (TREE_PUBLIC (decl))
22756 : {
22757 2 : error_at (loc,
22758 : "invalid use of %<global%> variable %qD "
22759 : "in %<#pragma acc declare%>", decl);
22760 2 : error = true;
22761 2 : continue;
22762 : }
22763 : break;
22764 : }
22765 :
22766 134 : if (!c_check_in_current_scope (decl))
22767 : {
22768 2 : error_at (loc,
22769 : "%qD must be a variable declared in the same scope as "
22770 : "%<#pragma acc declare%>", decl);
22771 2 : error = true;
22772 2 : continue;
22773 : }
22774 :
22775 132 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
22776 250 : || lookup_attribute ("omp declare target link",
22777 118 : DECL_ATTRIBUTES (decl)))
22778 : {
22779 17 : error_at (loc, "variable %qD used more than once with "
22780 : "%<#pragma acc declare%>", decl);
22781 17 : error = true;
22782 17 : continue;
22783 : }
22784 :
22785 115 : if (!error)
22786 : {
22787 115 : tree id;
22788 :
22789 115 : if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
22790 7 : id = get_identifier ("omp declare target link");
22791 : else
22792 108 : id = get_identifier ("omp declare target");
22793 :
22794 115 : DECL_ATTRIBUTES (decl)
22795 115 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
22796 :
22797 115 : if (global_bindings_p ())
22798 : {
22799 45 : symtab_node *node = symtab_node::get (decl);
22800 45 : if (node != NULL)
22801 : {
22802 33 : node->offloadable = 1;
22803 33 : if (ENABLE_OFFLOADING)
22804 : {
22805 : g->have_offload = true;
22806 : if (is_a <varpool_node *> (node))
22807 : vec_safe_push (offload_vars, decl);
22808 : }
22809 : }
22810 : }
22811 : }
22812 : }
22813 :
22814 142 : if (error || global_bindings_p ())
22815 74 : return;
22816 :
22817 68 : stmt = make_node (OACC_DECLARE);
22818 68 : TREE_TYPE (stmt) = void_type_node;
22819 68 : OACC_DECLARE_CLAUSES (stmt) = clauses;
22820 68 : SET_EXPR_LOCATION (stmt, pragma_loc);
22821 :
22822 68 : add_stmt (stmt);
22823 :
22824 68 : return;
22825 : }
22826 :
22827 : /* OpenACC 2.0:
22828 : # pragma acc enter data oacc-enter-data-clause[optseq] new-line
22829 :
22830 : or
22831 :
22832 : # pragma acc exit data oacc-exit-data-clause[optseq] new-line
22833 :
22834 :
22835 : LOC is the location of the #pragma token.
22836 : */
22837 :
22838 : #define OACC_ENTER_DATA_CLAUSE_MASK \
22839 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22840 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22841 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22842 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22843 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22844 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22845 :
22846 : #define OACC_EXIT_DATA_CLAUSE_MASK \
22847 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22848 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22849 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22850 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
22851 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
22852 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
22853 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22854 :
22855 : static void
22856 261 : c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
22857 : {
22858 261 : location_t loc = c_parser_peek_token (parser)->location;
22859 261 : tree clauses, stmt;
22860 261 : const char *p = "";
22861 :
22862 261 : c_parser_consume_pragma (parser);
22863 :
22864 261 : if (c_parser_next_token_is (parser, CPP_NAME))
22865 : {
22866 258 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22867 258 : c_parser_consume_token (parser);
22868 : }
22869 :
22870 261 : if (strcmp (p, "data") != 0)
22871 : {
22872 8 : error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
22873 : enter ? "enter" : "exit");
22874 6 : parser->error = true;
22875 6 : c_parser_skip_to_pragma_eol (parser);
22876 6 : return;
22877 : }
22878 :
22879 255 : if (enter)
22880 129 : clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
22881 : "#pragma acc enter data");
22882 : else
22883 126 : clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
22884 : "#pragma acc exit data");
22885 :
22886 255 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
22887 : {
22888 15 : error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
22889 : enter ? "enter" : "exit");
22890 15 : return;
22891 : }
22892 :
22893 240 : stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
22894 240 : TREE_TYPE (stmt) = void_type_node;
22895 240 : OMP_STANDALONE_CLAUSES (stmt) = clauses;
22896 240 : SET_EXPR_LOCATION (stmt, loc);
22897 240 : add_stmt (stmt);
22898 : }
22899 :
22900 :
22901 : /* OpenACC 2.0:
22902 : # pragma acc host_data oacc-data-clause[optseq] new-line
22903 : structured-block
22904 : */
22905 :
22906 : #define OACC_HOST_DATA_CLAUSE_MASK \
22907 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
22908 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22909 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
22910 :
22911 : static tree
22912 23 : c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
22913 : {
22914 23 : tree stmt, clauses, block;
22915 :
22916 23 : clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
22917 : "#pragma acc host_data", false);
22918 23 : if (!omp_find_clause (clauses, OMP_CLAUSE_USE_DEVICE_PTR))
22919 : {
22920 2 : error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
22921 2 : return error_mark_node;
22922 : }
22923 21 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22924 21 : block = c_begin_omp_parallel ();
22925 21 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22926 21 : stmt = c_finish_oacc_host_data (loc, clauses, block);
22927 21 : return stmt;
22928 : }
22929 :
22930 :
22931 : /* OpenACC 2.0:
22932 :
22933 : # pragma acc loop oacc-loop-clause[optseq] new-line
22934 : structured-block
22935 :
22936 : LOC is the location of the #pragma token.
22937 : */
22938 :
22939 : #define OACC_LOOP_CLAUSE_MASK \
22940 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
22941 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22942 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22943 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22944 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22945 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22946 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
22947 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
22948 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22949 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
22950 : static tree
22951 2444 : c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
22952 : omp_clause_mask mask, tree *cclauses, bool *if_p)
22953 : {
22954 2444 : bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
22955 :
22956 2444 : strcat (p_name, " loop");
22957 2444 : mask |= OACC_LOOP_CLAUSE_MASK;
22958 :
22959 2444 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
22960 : /*finish_p=*/cclauses == NULL,
22961 : /*target=*/is_parallel);
22962 2444 : if (cclauses)
22963 : {
22964 673 : clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
22965 673 : if (*cclauses)
22966 152 : *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
22967 673 : if (clauses)
22968 271 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22969 : }
22970 :
22971 2444 : tree block = c_begin_compound_stmt (true);
22972 2444 : tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
22973 : if_p);
22974 2444 : block = c_end_compound_stmt (loc, block, true);
22975 2444 : add_stmt (block);
22976 :
22977 2444 : return stmt;
22978 : }
22979 :
22980 : /* OpenACC 2.0:
22981 : # pragma acc kernels oacc-kernels-clause[optseq] new-line
22982 : structured-block
22983 :
22984 : or
22985 :
22986 : # pragma acc parallel oacc-parallel-clause[optseq] new-line
22987 : structured-block
22988 :
22989 : OpenACC 2.6:
22990 :
22991 : # pragma acc serial oacc-serial-clause[optseq] new-line
22992 : structured-block
22993 :
22994 : LOC is the location of the #pragma token.
22995 : */
22996 :
22997 : #define OACC_KERNELS_CLAUSE_MASK \
22998 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22999 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23000 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23001 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23002 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23003 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23004 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23005 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23006 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23007 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23008 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
23009 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
23010 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23011 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23012 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
23013 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23014 :
23015 : #define OACC_PARALLEL_CLAUSE_MASK \
23016 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23017 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23018 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23019 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23020 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23021 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23022 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23023 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23024 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23025 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23026 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
23027 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
23028 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
23029 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
23030 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23031 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
23032 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23033 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
23034 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23035 :
23036 : #define OACC_SERIAL_CLAUSE_MASK \
23037 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23038 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
23039 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
23040 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
23041 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
23042 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
23043 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
23044 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
23045 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23046 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
23047 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
23048 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
23049 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
23050 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
23051 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23052 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23053 :
23054 : static tree
23055 2154 : c_parser_oacc_compute (location_t loc, c_parser *parser,
23056 : enum pragma_kind p_kind, char *p_name, bool *if_p)
23057 : {
23058 2154 : omp_clause_mask mask;
23059 2154 : enum tree_code code;
23060 2154 : switch (p_kind)
23061 : {
23062 522 : case PRAGMA_OACC_KERNELS:
23063 522 : strcat (p_name, " kernels");
23064 522 : mask = OACC_KERNELS_CLAUSE_MASK;
23065 522 : code = OACC_KERNELS;
23066 522 : break;
23067 1457 : case PRAGMA_OACC_PARALLEL:
23068 1457 : strcat (p_name, " parallel");
23069 1457 : mask = OACC_PARALLEL_CLAUSE_MASK;
23070 1457 : code = OACC_PARALLEL;
23071 1457 : break;
23072 175 : case PRAGMA_OACC_SERIAL:
23073 175 : strcat (p_name, " serial");
23074 175 : mask = OACC_SERIAL_CLAUSE_MASK;
23075 175 : code = OACC_SERIAL;
23076 175 : break;
23077 0 : default:
23078 0 : gcc_unreachable ();
23079 : }
23080 :
23081 2154 : if (c_parser_next_token_is (parser, CPP_NAME))
23082 : {
23083 1710 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23084 1710 : if (strcmp (p, "loop") == 0)
23085 : {
23086 673 : c_parser_consume_token (parser);
23087 673 : tree block = c_begin_omp_parallel ();
23088 673 : tree clauses;
23089 673 : c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
23090 673 : return c_finish_omp_construct (loc, code, block, clauses);
23091 : }
23092 : }
23093 :
23094 1481 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
23095 : /*finish_p=*/true,
23096 : /*target=*/true);
23097 :
23098 1481 : tree block = c_begin_omp_parallel ();
23099 1481 : add_stmt (c_parser_omp_structured_block (parser, if_p));
23100 :
23101 1481 : return c_finish_omp_construct (loc, code, block, clauses);
23102 : }
23103 :
23104 : /* OpenACC 2.0:
23105 : # pragma acc routine oacc-routine-clause[optseq] new-line
23106 : function-definition
23107 :
23108 : # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
23109 : */
23110 :
23111 : #define OACC_ROUTINE_CLAUSE_MASK \
23112 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
23113 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
23114 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
23115 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
23116 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
23117 :
23118 : /* Parse an OpenACC routine directive. For named directives, we apply
23119 : immediately to the named function. For unnamed ones we then parse
23120 : a declaration or definition, which must be for a function. */
23121 :
23122 : static void
23123 345 : c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
23124 : {
23125 345 : gcc_checking_assert (context == pragma_external);
23126 :
23127 345 : oacc_routine_data data;
23128 345 : data.error_seen = false;
23129 345 : data.fndecl_seen = false;
23130 345 : data.loc = c_parser_peek_token (parser)->location;
23131 :
23132 345 : c_parser_consume_pragma (parser);
23133 :
23134 : /* Look for optional '( name )'. */
23135 345 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
23136 : {
23137 143 : c_parser_consume_token (parser); /* '(' */
23138 :
23139 143 : tree decl = NULL_TREE;
23140 143 : c_token *name_token = c_parser_peek_token (parser);
23141 143 : location_t name_loc = name_token->location;
23142 143 : if (name_token->type == CPP_NAME
23143 135 : && (name_token->id_kind == C_ID_ID
23144 : || name_token->id_kind == C_ID_TYPENAME))
23145 : {
23146 135 : decl = lookup_name (name_token->value);
23147 135 : if (!decl)
23148 5 : error_at (name_loc,
23149 : "%qE has not been declared", name_token->value);
23150 135 : c_parser_consume_token (parser);
23151 : }
23152 : else
23153 8 : c_parser_error (parser, "expected function name");
23154 :
23155 8 : if (!decl
23156 135 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
23157 : {
23158 15 : c_parser_skip_to_pragma_eol (parser, false);
23159 43 : return;
23160 : }
23161 :
23162 128 : data.clauses
23163 128 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
23164 : "#pragma acc routine");
23165 : /* The clauses are in reverse order; fix that to make later diagnostic
23166 : emission easier. */
23167 128 : data.clauses = nreverse (data.clauses);
23168 :
23169 128 : if (TREE_CODE (decl) != FUNCTION_DECL)
23170 : {
23171 3 : error_at (name_loc, "%qD does not refer to a function", decl);
23172 3 : return;
23173 : }
23174 :
23175 125 : c_finish_oacc_routine (&data, decl, false);
23176 : }
23177 : else /* No optional '( name )'. */
23178 : {
23179 202 : data.clauses
23180 202 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
23181 : "#pragma acc routine");
23182 : /* The clauses are in reverse order; fix that to make later diagnostic
23183 : emission easier. */
23184 202 : data.clauses = nreverse (data.clauses);
23185 :
23186 : /* Emit a helpful diagnostic if there's another pragma following this
23187 : one. Also don't allow a static assertion declaration, as in the
23188 : following we'll just parse a *single* "declaration or function
23189 : definition", and the static assertion counts an one. */
23190 202 : if (c_parser_next_token_is (parser, CPP_PRAGMA)
23191 395 : || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
23192 : {
23193 10 : error_at (data.loc,
23194 : "%<#pragma acc routine%> not immediately followed by"
23195 : " function declaration or definition");
23196 : /* ..., and then just keep going. */
23197 10 : return;
23198 : }
23199 :
23200 : /* We only have to consider the pragma_external case here. */
23201 192 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
23202 192 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
23203 : {
23204 3 : int ext = disable_extension_diagnostics ();
23205 7 : do
23206 7 : c_parser_consume_token (parser);
23207 7 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
23208 10 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
23209 3 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
23210 : false, NULL, NULL, false, NULL, &data);
23211 3 : restore_extension_diagnostics (ext);
23212 : }
23213 : else
23214 189 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
23215 : false, NULL, NULL, false, NULL, &data);
23216 : }
23217 : }
23218 :
23219 : /* Finalize an OpenACC routine pragma, applying it to FNDECL.
23220 : IS_DEFN is true if we're applying it to the definition. */
23221 :
23222 : static void
23223 327 : c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
23224 : bool is_defn)
23225 : {
23226 : /* Keep going if we're in error reporting mode. */
23227 327 : if (data->error_seen
23228 321 : || fndecl == error_mark_node)
23229 : return;
23230 :
23231 321 : if (data->fndecl_seen)
23232 : {
23233 4 : error_at (data->loc,
23234 : "%<#pragma acc routine%> not immediately followed by"
23235 : " a single function declaration or definition");
23236 4 : data->error_seen = true;
23237 4 : return;
23238 : }
23239 317 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
23240 : {
23241 10 : error_at (data->loc,
23242 : "%<#pragma acc routine%> not immediately followed by"
23243 : " function declaration or definition");
23244 10 : data->error_seen = true;
23245 10 : return;
23246 : }
23247 :
23248 307 : int compatible
23249 307 : = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
23250 : "#pragma acc routine");
23251 307 : if (compatible < 0)
23252 : {
23253 47 : data->error_seen = true;
23254 47 : return;
23255 : }
23256 260 : if (compatible > 0)
23257 : {
23258 : }
23259 : else
23260 : {
23261 269 : if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
23262 : {
23263 3 : error_at (data->loc,
23264 : TREE_USED (fndecl)
23265 : ? G_("%<#pragma acc routine%> must be applied before use")
23266 : : G_("%<#pragma acc routine%> must be applied before"
23267 : " definition"));
23268 2 : data->error_seen = true;
23269 2 : return;
23270 : }
23271 :
23272 : /* Set the routine's level of parallelism. */
23273 197 : tree dims = oacc_build_routine_dims (data->clauses);
23274 197 : oacc_replace_fn_attrib (fndecl, dims);
23275 :
23276 : /* Add an "omp declare target" attribute. */
23277 197 : DECL_ATTRIBUTES (fndecl)
23278 394 : = tree_cons (get_identifier ("omp declare target"),
23279 197 : data->clauses, DECL_ATTRIBUTES (fndecl));
23280 : }
23281 :
23282 : /* Remember that we've used this "#pragma acc routine". */
23283 258 : data->fndecl_seen = true;
23284 : }
23285 :
23286 : /* OpenACC 2.0:
23287 : # pragma acc update oacc-update-clause[optseq] new-line
23288 : */
23289 :
23290 : #define OACC_UPDATE_CLAUSE_MASK \
23291 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23292 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
23293 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
23294 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
23295 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
23296 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
23297 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
23298 :
23299 : static void
23300 92 : c_parser_oacc_update (c_parser *parser)
23301 : {
23302 92 : location_t loc = c_parser_peek_token (parser)->location;
23303 :
23304 92 : c_parser_consume_pragma (parser);
23305 :
23306 92 : tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
23307 : "#pragma acc update");
23308 92 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
23309 : {
23310 1 : error_at (loc,
23311 : "%<#pragma acc update%> must contain at least one "
23312 : "%<device%> or %<host%> or %<self%> clause");
23313 1 : return;
23314 : }
23315 :
23316 91 : if (parser->error)
23317 : return;
23318 :
23319 91 : tree stmt = make_node (OACC_UPDATE);
23320 91 : TREE_TYPE (stmt) = void_type_node;
23321 91 : OACC_UPDATE_CLAUSES (stmt) = clauses;
23322 91 : SET_EXPR_LOCATION (stmt, loc);
23323 91 : add_stmt (stmt);
23324 : }
23325 :
23326 : /* OpenACC 2.0:
23327 : # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
23328 :
23329 : LOC is the location of the #pragma token.
23330 : */
23331 :
23332 : #define OACC_WAIT_CLAUSE_MASK \
23333 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
23334 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) )
23335 :
23336 : static tree
23337 86 : c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
23338 : {
23339 86 : tree clauses, list = NULL_TREE, stmt = NULL_TREE;
23340 :
23341 86 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
23342 49 : list = c_parser_oacc_wait_list (parser, loc, list);
23343 :
23344 86 : strcpy (p_name, " wait");
23345 86 : clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, p_name);
23346 86 : stmt = c_finish_oacc_wait (loc, list, clauses);
23347 86 : add_stmt (stmt);
23348 :
23349 86 : return stmt;
23350 : }
23351 :
23352 : struct c_omp_loc_tree
23353 : {
23354 : location_t loc;
23355 : tree var;
23356 : };
23357 :
23358 : /* Check whether the expression used in the allocator clause is declared or
23359 : modified between the variable declaration and its allocate directive. */
23360 : static tree
23361 50 : c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
23362 : {
23363 50 : tree var = ((struct c_omp_loc_tree *) data)->var;
23364 50 : location_t loc = ((struct c_omp_loc_tree *) data)->loc;
23365 50 : if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
23366 : {
23367 10 : if (linemap_location_before_p (line_table, DECL_SOURCE_LOCATION (var),
23368 10 : DECL_SOURCE_LOCATION (*tp)))
23369 : {
23370 2 : error_at (loc, "variable %qD used in the %<allocator%> clause must "
23371 : "be declared before %qD", *tp, var);
23372 2 : inform (DECL_SOURCE_LOCATION (*tp), "declared here");
23373 2 : inform (DECL_SOURCE_LOCATION (var),
23374 : "to be allocated variable declared here");
23375 2 : return *tp;
23376 : }
23377 : else
23378 : {
23379 8 : gcc_assert (cur_stmt_list
23380 : && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
23381 :
23382 8 : tree_stmt_iterator l = tsi_last (cur_stmt_list);
23383 9 : while (!tsi_end_p (l))
23384 : {
23385 9 : if (linemap_location_before_p (line_table, EXPR_LOCATION (*l),
23386 9 : DECL_SOURCE_LOCATION (var)))
23387 : break;
23388 3 : if (TREE_CODE (*l) == MODIFY_EXPR
23389 3 : && TREE_OPERAND (*l, 0) == *tp)
23390 : {
23391 2 : error_at (loc,
23392 : "variable %qD used in the %<allocator%> clause "
23393 : "must not be modified between declaration of %qD "
23394 : "and its %<allocate%> directive", *tp, var);
23395 2 : inform (EXPR_LOCATION (*l), "modified here");
23396 2 : inform (DECL_SOURCE_LOCATION (var),
23397 : "to be allocated variable declared here");
23398 2 : return *tp;
23399 : }
23400 1 : --l;
23401 : }
23402 : }
23403 : }
23404 : return NULL_TREE;
23405 : }
23406 :
23407 : /* OpenMP 5.x:
23408 : # pragma omp allocate (list) clauses
23409 :
23410 : OpenMP 5.0 clause:
23411 : allocator (omp_allocator_handle_t expression)
23412 :
23413 : OpenMP 5.1 additional clause:
23414 : align (constant-expression)] */
23415 :
23416 : static void
23417 71 : c_parser_omp_allocate (c_parser *parser)
23418 : {
23419 71 : tree alignment = NULL_TREE;
23420 71 : tree allocator = NULL_TREE;
23421 71 : c_parser_consume_pragma (parser);
23422 71 : location_t loc = c_parser_peek_token (parser)->location;
23423 71 : location_t allocator_loc = UNKNOWN_LOCATION;
23424 71 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
23425 221 : do
23426 : {
23427 146 : if (c_parser_next_token_is (parser, CPP_COMMA)
23428 146 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23429 9 : c_parser_consume_token (parser);
23430 146 : if (!c_parser_next_token_is (parser, CPP_NAME))
23431 : break;
23432 78 : matching_parens parens;
23433 78 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23434 78 : c_parser_consume_token (parser);
23435 78 : location_t expr_loc = c_parser_peek_token (parser)->location;
23436 78 : if (strcmp ("align", p) != 0 && strcmp ("allocator", p) != 0)
23437 : {
23438 1 : error_at (c_parser_peek_token (parser)->location,
23439 : "expected %<allocator%> or %<align%>");
23440 1 : break;
23441 : }
23442 77 : if (!parens.require_open (parser))
23443 : break;
23444 :
23445 77 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
23446 77 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
23447 77 : expr_loc = c_parser_peek_token (parser)->location;
23448 77 : if (expr.value == error_mark_node)
23449 : ;
23450 76 : else if (p[2] == 'i' && alignment)
23451 : {
23452 1 : error_at (expr_loc, "too many %qs clauses", "align");
23453 1 : break;
23454 : }
23455 75 : else if (p[2] == 'i')
23456 : {
23457 32 : alignment = c_fully_fold (expr.value, false, NULL);
23458 32 : if (TREE_CODE (alignment) != INTEGER_CST
23459 31 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
23460 31 : || tree_int_cst_sgn (alignment) != 1
23461 62 : || !integer_pow2p (alignment))
23462 : {
23463 4 : error_at (expr_loc, "%<align%> clause argument needs to be "
23464 : "positive constant power of two integer "
23465 : "expression");
23466 4 : alignment = NULL_TREE;
23467 : }
23468 : }
23469 43 : else if (allocator)
23470 : {
23471 1 : error_at (expr_loc, "too many %qs clauses", "allocator");
23472 1 : break;
23473 : }
23474 : else
23475 : {
23476 42 : allocator = c_fully_fold (expr.value, false, NULL);
23477 42 : allocator_loc = expr_loc;
23478 42 : tree orig_type
23479 42 : = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
23480 42 : orig_type = TYPE_MAIN_VARIANT (orig_type);
23481 43 : if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
23482 42 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
23483 124 : || TYPE_NAME (orig_type)
23484 41 : != get_identifier ("omp_allocator_handle_t"))
23485 : {
23486 1 : error_at (expr_loc,
23487 : "%<allocator%> clause allocator expression has type "
23488 : "%qT rather than %<omp_allocator_handle_t%>",
23489 1 : TREE_TYPE (allocator));
23490 1 : allocator = NULL_TREE;
23491 : }
23492 : }
23493 75 : parens.skip_until_found_close (parser);
23494 75 : } while (true);
23495 71 : c_parser_skip_to_pragma_eol (parser);
23496 :
23497 71 : c_mark_decl_jump_unsafe_in_current_scope ();
23498 153 : for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
23499 : {
23500 82 : tree var = OMP_CLAUSE_DECL (c);
23501 82 : if (TREE_CODE (var) == PARM_DECL)
23502 : {
23503 1 : error_at (OMP_CLAUSE_LOCATION (nl),
23504 : "function parameter %qD may not appear as list item in an "
23505 : "%<allocate%> directive", var);
23506 1 : continue;
23507 : }
23508 81 : if (!parser->in_omp_decl_attribute && !c_check_in_current_scope (var))
23509 : {
23510 2 : error_at (OMP_CLAUSE_LOCATION (nl),
23511 : "%<allocate%> directive must be in the same scope as %qD",
23512 : var);
23513 2 : inform (DECL_SOURCE_LOCATION (var), "declared here");
23514 2 : continue;
23515 : }
23516 79 : if (lookup_attribute ("omp allocate", DECL_ATTRIBUTES (var)))
23517 : {
23518 1 : error_at (OMP_CLAUSE_LOCATION (nl),
23519 : "%qD already appeared as list item in an "
23520 : "%<allocate%> directive", var);
23521 1 : continue;
23522 : }
23523 78 : if (TREE_STATIC (var))
23524 : {
23525 19 : if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
23526 : {
23527 3 : error_at (loc,
23528 : "%<allocator%> clause required for "
23529 : "static variable %qD", var);
23530 3 : continue;
23531 : }
23532 16 : else if (allocator
23533 16 : && (wi::to_widest (allocator) < 1
23534 15 : || wi::to_widest (allocator) > GOMP_OMP_PREDEF_ALLOC_MAX)
23535 23 : && (wi::to_widest (allocator) < GOMP_OMPX_PREDEF_ALLOC_MIN
23536 12 : || wi::to_widest (allocator) > GOMP_OMPX_PREDEF_ALLOC_MAX))
23537 : {
23538 6 : error_at (allocator_loc,
23539 : "%<allocator%> clause requires a predefined allocator as "
23540 : "%qD is static", var);
23541 : }
23542 : }
23543 75 : if (allocator)
23544 : {
23545 42 : struct c_omp_loc_tree data
23546 82 : = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), var};
23547 42 : walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
23548 : }
23549 75 : DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
23550 : build_tree_list (allocator, alignment),
23551 75 : DECL_ATTRIBUTES (var));
23552 : }
23553 71 : }
23554 :
23555 : /* OpenMP 2.5:
23556 : # pragma omp atomic new-line
23557 : expression-stmt
23558 :
23559 : expression-stmt:
23560 : x binop= expr | x++ | ++x | x-- | --x
23561 : binop:
23562 : +, *, -, /, &, ^, |, <<, >>
23563 :
23564 : where x is an lvalue expression with scalar type.
23565 :
23566 : OpenMP 3.1:
23567 : # pragma omp atomic new-line
23568 : update-stmt
23569 :
23570 : # pragma omp atomic read new-line
23571 : read-stmt
23572 :
23573 : # pragma omp atomic write new-line
23574 : write-stmt
23575 :
23576 : # pragma omp atomic update new-line
23577 : update-stmt
23578 :
23579 : # pragma omp atomic capture new-line
23580 : capture-stmt
23581 :
23582 : # pragma omp atomic capture new-line
23583 : capture-block
23584 :
23585 : read-stmt:
23586 : v = x
23587 : write-stmt:
23588 : x = expr
23589 : update-stmt:
23590 : expression-stmt | x = x binop expr
23591 : capture-stmt:
23592 : v = expression-stmt
23593 : capture-block:
23594 : { v = x; update-stmt; } | { update-stmt; v = x; }
23595 :
23596 : OpenMP 4.0:
23597 : update-stmt:
23598 : expression-stmt | x = x binop expr | x = expr binop x
23599 : capture-stmt:
23600 : v = update-stmt
23601 : capture-block:
23602 : { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
23603 :
23604 : OpenMP 5.1:
23605 : # pragma omp atomic compare new-line
23606 : conditional-update-atomic
23607 :
23608 : # pragma omp atomic compare capture new-line
23609 : conditional-update-capture-atomic
23610 :
23611 : conditional-update-atomic:
23612 : cond-expr-stmt | cond-update-stmt
23613 : cond-expr-stmt:
23614 : x = expr ordop x ? expr : x;
23615 : x = x ordop expr ? expr : x;
23616 : x = x == e ? d : x;
23617 : cond-update-stmt:
23618 : if (expr ordop x) { x = expr; }
23619 : if (x ordop expr) { x = expr; }
23620 : if (x == e) { x = d; }
23621 : ordop:
23622 : <, >
23623 : conditional-update-capture-atomic:
23624 : v = cond-expr-stmt
23625 : { v = x; cond-expr-stmt }
23626 : { cond-expr-stmt v = x; }
23627 : { v = x; cond-update-stmt }
23628 : { cond-update-stmt v = x; }
23629 : if (x == e) { x = d; } else { v = x; }
23630 : { r = x == e; if (r) { x = d; } }
23631 : { r = x == e; if (r) { x = d; } else { v = x; } }
23632 :
23633 : where x, r and v are lvalue expressions with scalar type,
23634 : expr, e and d are expressions with scalar type and e might be
23635 : the same as v.
23636 :
23637 : LOC is the location of the #pragma token. */
23638 :
23639 : static void
23640 1719 : c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
23641 : {
23642 1719 : tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
23643 1719 : tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
23644 1719 : tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
23645 1719 : enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
23646 1719 : enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
23647 1719 : struct c_expr expr;
23648 1719 : location_t eloc;
23649 1719 : bool structured_block = false;
23650 1719 : bool swapped = false;
23651 1719 : bool non_lvalue_p;
23652 1719 : tree clauses = NULL_TREE;
23653 1719 : bool capture = false;
23654 1719 : bool compare = false;
23655 1719 : bool weak = false;
23656 1719 : enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23657 1719 : bool no_semicolon = false;
23658 1719 : bool extra_scope = false;
23659 :
23660 3198 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
23661 : {
23662 1489 : if (c_parser_next_token_is (parser, CPP_COMMA)
23663 1489 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23664 82 : c_parser_consume_token (parser);
23665 :
23666 1489 : if (c_parser_next_token_is (parser, CPP_NAME))
23667 : {
23668 1485 : const char *p
23669 1485 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23670 1485 : location_t cloc = c_parser_peek_token (parser)->location;
23671 1485 : enum tree_code new_code = ERROR_MARK;
23672 1485 : enum omp_memory_order new_memory_order
23673 : = OMP_MEMORY_ORDER_UNSPECIFIED;
23674 1485 : bool new_capture = false;
23675 1485 : bool new_compare = false;
23676 1485 : bool new_weak = false;
23677 1485 : enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23678 :
23679 1485 : if (!strcmp (p, "read"))
23680 : new_code = OMP_ATOMIC_READ;
23681 1227 : else if (!strcmp (p, "write"))
23682 : new_code = NOP_EXPR;
23683 1050 : else if (!strcmp (p, "update"))
23684 : new_code = OMP_ATOMIC;
23685 890 : else if (openacc && !strcmp (p, "capture"))
23686 : new_code = OMP_ATOMIC_CAPTURE_NEW;
23687 4 : else if (openacc)
23688 : {
23689 4 : p = NULL;
23690 4 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23691 : "or %<capture%> clause");
23692 : }
23693 652 : else if (!strcmp (p, "capture"))
23694 : new_capture = true;
23695 408 : else if (!strcmp (p, "compare"))
23696 : new_compare = true;
23697 235 : else if (!strcmp (p, "weak"))
23698 : new_weak = true;
23699 222 : else if (!strcmp (p, "fail"))
23700 : {
23701 33 : matching_parens parens;
23702 :
23703 33 : c_parser_consume_token (parser);
23704 33 : if (!parens.require_open (parser))
23705 1 : continue;
23706 :
23707 32 : if (c_parser_next_token_is (parser, CPP_NAME))
23708 : {
23709 30 : const char *q
23710 30 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23711 :
23712 30 : if (!strcmp (q, "seq_cst"))
23713 : new_fail = OMP_MEMORY_ORDER_SEQ_CST;
23714 24 : else if (!strcmp (q, "acquire"))
23715 : new_fail = OMP_MEMORY_ORDER_ACQUIRE;
23716 17 : else if (!strcmp (q, "relaxed"))
23717 : new_fail = OMP_MEMORY_ORDER_RELAXED;
23718 : }
23719 :
23720 : if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23721 : {
23722 27 : c_parser_consume_token (parser);
23723 27 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23724 2 : error_at (cloc, "too many %qs clauses", "fail");
23725 : else
23726 : fail = new_fail;
23727 : }
23728 : else
23729 5 : c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
23730 : "or %<relaxed%>");
23731 32 : parens.skip_until_found_close (parser);
23732 32 : continue;
23733 32 : }
23734 189 : else if (!strcmp (p, "seq_cst"))
23735 : new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23736 112 : else if (!strcmp (p, "acq_rel"))
23737 : new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23738 100 : else if (!strcmp (p, "release"))
23739 : new_memory_order = OMP_MEMORY_ORDER_RELEASE;
23740 70 : else if (!strcmp (p, "acquire"))
23741 : new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23742 57 : else if (!strcmp (p, "relaxed"))
23743 : new_memory_order = OMP_MEMORY_ORDER_RELAXED;
23744 31 : else if (!strcmp (p, "hint"))
23745 : {
23746 29 : c_parser_consume_token (parser);
23747 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
23748 29 : continue;
23749 : }
23750 : else
23751 : {
23752 2 : p = NULL;
23753 2 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23754 : "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
23755 : "%<seq_cst%>, %<acq_rel%>, %<release%>, "
23756 : "%<relaxed%> or %<hint%> clause");
23757 : }
23758 6 : if (p)
23759 : {
23760 1417 : if (new_code != ERROR_MARK)
23761 : {
23762 : /* OpenACC permits 'update capture'. */
23763 829 : if (openacc
23764 829 : && code == OMP_ATOMIC
23765 4 : && new_code == OMP_ATOMIC_CAPTURE_NEW)
23766 : code = new_code;
23767 826 : else if (code != ERROR_MARK)
23768 5 : error_at (cloc, "too many atomic clauses");
23769 : else
23770 : code = new_code;
23771 : }
23772 588 : else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23773 : {
23774 158 : if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23775 35 : error_at (cloc, "too many memory order clauses");
23776 : else
23777 : memory_order = new_memory_order;
23778 : }
23779 430 : else if (new_capture)
23780 : {
23781 244 : if (capture)
23782 1 : error_at (cloc, "too many %qs clauses", "capture");
23783 : else
23784 : capture = true;
23785 : }
23786 186 : else if (new_compare)
23787 : {
23788 173 : if (compare)
23789 1 : error_at (cloc, "too many %qs clauses", "compare");
23790 : else
23791 : compare = true;
23792 : }
23793 13 : else if (new_weak)
23794 : {
23795 13 : if (weak)
23796 1 : error_at (cloc, "too many %qs clauses", "weak");
23797 : else
23798 : weak = true;
23799 : }
23800 1417 : c_parser_consume_token (parser);
23801 1417 : continue;
23802 : }
23803 : }
23804 : break;
23805 : }
23806 1719 : c_parser_skip_to_pragma_eol (parser);
23807 :
23808 1719 : if (code == ERROR_MARK)
23809 898 : code = OMP_ATOMIC;
23810 1719 : if (capture)
23811 : {
23812 243 : if (code != OMP_ATOMIC)
23813 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23814 : "clauses", "capture");
23815 : else
23816 : code = OMP_ATOMIC_CAPTURE_NEW;
23817 : }
23818 1719 : if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
23819 : {
23820 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23821 : "clauses", "compare");
23822 2 : compare = false;
23823 : }
23824 1719 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
23825 : {
23826 5 : error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
23827 5 : fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23828 : }
23829 1719 : if (weak && !compare)
23830 : {
23831 5 : error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
23832 5 : weak = false;
23833 : }
23834 1719 : if (openacc)
23835 : memory_order = OMP_MEMORY_ORDER_RELAXED;
23836 1410 : else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
23837 : {
23838 1287 : omp_requires_mask
23839 1287 : = (enum omp_requires) (omp_requires_mask
23840 : | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
23841 1287 : switch ((enum omp_memory_order)
23842 : (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
23843 : {
23844 : case OMP_MEMORY_ORDER_UNSPECIFIED:
23845 : case OMP_MEMORY_ORDER_RELAXED:
23846 : memory_order = OMP_MEMORY_ORDER_RELAXED;
23847 : break;
23848 : case OMP_MEMORY_ORDER_SEQ_CST:
23849 9 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23850 : break;
23851 4 : case OMP_MEMORY_ORDER_ACQUIRE:
23852 4 : if (code == NOP_EXPR) /* atomic write */
23853 : {
23854 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23855 : "%<acquire%> clause implicitly provided by a "
23856 : "%<requires%> directive");
23857 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23858 : }
23859 : else
23860 : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23861 : break;
23862 3 : case OMP_MEMORY_ORDER_RELEASE:
23863 3 : if (code == OMP_ATOMIC_READ)
23864 : {
23865 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23866 : "%<release%> clause implicitly provided by a "
23867 : "%<requires%> directive");
23868 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23869 : }
23870 : else
23871 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23872 : break;
23873 9 : case OMP_MEMORY_ORDER_ACQ_REL:
23874 9 : switch (code)
23875 : {
23876 : case OMP_ATOMIC_READ:
23877 : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23878 : break;
23879 : case NOP_EXPR: /* atomic write */
23880 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23881 : break;
23882 : default:
23883 1719 : memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23884 : break;
23885 : }
23886 : break;
23887 0 : default:
23888 0 : gcc_unreachable ();
23889 : }
23890 : }
23891 : else
23892 123 : switch (code)
23893 : {
23894 25 : case OMP_ATOMIC_READ:
23895 25 : if (memory_order == OMP_MEMORY_ORDER_RELEASE)
23896 : {
23897 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23898 : "%<release%> clause");
23899 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23900 : }
23901 24 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23902 6 : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23903 : break;
23904 16 : case NOP_EXPR: /* atomic write */
23905 16 : if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
23906 : {
23907 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23908 : "%<acquire%> clause");
23909 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23910 : }
23911 15 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23912 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23913 : break;
23914 : default:
23915 : break;
23916 : }
23917 1719 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23918 20 : memory_order
23919 20 : = (enum omp_memory_order) (memory_order
23920 : | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
23921 :
23922 1719 : switch (code)
23923 : {
23924 434 : case OMP_ATOMIC_READ:
23925 434 : case NOP_EXPR: /* atomic write */
23926 434 : v = c_parser_cast_expression (parser, NULL).value;
23927 434 : non_lvalue_p = !lvalue_p (v);
23928 434 : v = c_fully_fold (v, false, NULL, true);
23929 434 : if (v == error_mark_node)
23930 0 : goto saw_error;
23931 434 : if (non_lvalue_p)
23932 4 : v = non_lvalue (v);
23933 434 : loc = c_parser_peek_token (parser)->location;
23934 434 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23935 0 : goto saw_error;
23936 434 : if (code == NOP_EXPR)
23937 : {
23938 176 : eloc = c_parser_peek_token (parser)->location;
23939 176 : expr = c_parser_expression (parser);
23940 176 : expr = default_function_array_read_conversion (eloc, expr);
23941 : /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
23942 : opcode. */
23943 176 : code = OMP_ATOMIC;
23944 176 : lhs = v;
23945 176 : v = NULL_TREE;
23946 176 : rhs = c_fully_fold (expr.value, false, NULL);
23947 176 : if (rhs == error_mark_node)
23948 0 : goto saw_error;
23949 : }
23950 : else
23951 : {
23952 258 : lhs = c_parser_cast_expression (parser, NULL).value;
23953 258 : non_lvalue_p = !lvalue_p (lhs);
23954 258 : lhs = c_fully_fold (lhs, false, NULL, true);
23955 258 : if (lhs == error_mark_node)
23956 0 : goto saw_error;
23957 258 : if (non_lvalue_p)
23958 2 : lhs = non_lvalue (lhs);
23959 : }
23960 434 : goto done;
23961 473 : case OMP_ATOMIC_CAPTURE_NEW:
23962 473 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
23963 : {
23964 314 : c_parser_consume_token (parser);
23965 314 : structured_block = true;
23966 : }
23967 159 : else if (compare
23968 188 : && c_parser_next_token_is_keyword (parser, RID_IF))
23969 : break;
23970 : else
23971 : {
23972 142 : v = c_parser_cast_expression (parser, NULL).value;
23973 142 : non_lvalue_p = !lvalue_p (v);
23974 142 : v = c_fully_fold (v, false, NULL, true);
23975 142 : if (v == error_mark_node)
23976 0 : goto saw_error;
23977 142 : if (non_lvalue_p)
23978 2 : v = non_lvalue (v);
23979 142 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23980 0 : goto saw_error;
23981 154 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23982 : {
23983 1 : eloc = c_parser_peek_token (parser)->location;
23984 1 : error_at (eloc, "expected expression");
23985 1 : goto saw_error;
23986 : }
23987 : }
23988 : break;
23989 : default:
23990 : break;
23991 : }
23992 :
23993 : /* For structured_block case we don't know yet whether
23994 : old or new x should be captured. */
23995 1284 : restart:
23996 1676 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23997 : {
23998 85 : c_parser_consume_token (parser);
23999 :
24000 85 : matching_parens parens;
24001 85 : if (!parens.require_open (parser))
24002 34 : goto saw_error;
24003 84 : eloc = c_parser_peek_token (parser)->location;
24004 84 : c_expr cmp_expr;
24005 84 : if (r)
24006 : {
24007 17 : cmp_expr = c_parser_cast_expression (parser, NULL);
24008 17 : cmp_expr = default_function_array_conversion (eloc, cmp_expr);
24009 : }
24010 : else
24011 67 : cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
24012 84 : parens.skip_until_found_close (parser);
24013 84 : if (cmp_expr.value == error_mark_node)
24014 0 : goto saw_error;
24015 84 : if (r)
24016 : {
24017 17 : if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
24018 1 : goto bad_if;
24019 16 : cmp_expr.value = rhs1;
24020 16 : rhs1 = NULL_TREE;
24021 16 : gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
24022 : }
24023 83 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24024 : ;
24025 36 : else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
24026 : {
24027 4 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
24028 : "expected %<==%> comparison in %<if%> condition");
24029 2 : goto saw_error;
24030 : }
24031 34 : else if (TREE_CODE (cmp_expr.value) != GT_EXPR
24032 25 : && TREE_CODE (cmp_expr.value) != LT_EXPR)
24033 : {
24034 16 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
24035 : "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
24036 : "condition");
24037 10 : goto saw_error;
24038 : }
24039 71 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
24040 2 : goto saw_error;
24041 :
24042 69 : extra_scope = true;
24043 69 : eloc = c_parser_peek_token (parser)->location;
24044 69 : expr = c_parser_cast_expression (parser, NULL);
24045 69 : lhs = expr.value;
24046 69 : expr = default_function_array_conversion (eloc, expr);
24047 69 : unfolded_lhs = expr.value;
24048 69 : lhs = c_fully_fold (lhs, false, NULL, true);
24049 69 : orig_lhs = lhs;
24050 69 : if (lhs == error_mark_node)
24051 0 : goto saw_error;
24052 69 : if (!lvalue_p (unfolded_lhs))
24053 0 : lhs = non_lvalue (lhs);
24054 69 : if (!c_parser_next_token_is (parser, CPP_EQ))
24055 : {
24056 1 : c_parser_error (parser, "expected %<=%>");
24057 1 : goto saw_error;
24058 : }
24059 68 : c_parser_consume_token (parser);
24060 68 : eloc = c_parser_peek_token (parser)->location;
24061 68 : expr = c_parser_expr_no_commas (parser, NULL);
24062 68 : rhs1 = expr.value;
24063 :
24064 68 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
24065 1 : goto saw_error;
24066 :
24067 67 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
24068 1 : goto saw_error;
24069 :
24070 66 : extra_scope = false;
24071 66 : no_semicolon = true;
24072 :
24073 66 : if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
24074 : {
24075 59 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24076 : {
24077 44 : opcode = COND_EXPR;
24078 44 : rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
24079 : false, NULL, true);
24080 44 : rhs1 = c_fully_fold (rhs1, false, NULL, true);
24081 : }
24082 15 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
24083 : {
24084 7 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
24085 13 : ? MIN_EXPR : MAX_EXPR);
24086 13 : rhs = c_fully_fold (rhs1, false, NULL, true);
24087 13 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
24088 : false, NULL, true);
24089 : }
24090 : else
24091 2 : goto bad_if;
24092 : }
24093 7 : else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
24094 2 : goto bad_if;
24095 5 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
24096 5 : && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
24097 : {
24098 2 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
24099 3 : ? MAX_EXPR : MIN_EXPR);
24100 3 : rhs = c_fully_fold (rhs1, false, NULL, true);
24101 3 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
24102 : false, NULL, true);
24103 : }
24104 : else
24105 : {
24106 8 : bad_if:
24107 8 : c_parser_error (parser,
24108 : "invalid form of %<#pragma omp atomic compare%>");
24109 8 : goto saw_error;
24110 : }
24111 :
24112 60 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
24113 : {
24114 24 : if (code != OMP_ATOMIC_CAPTURE_NEW
24115 22 : || (structured_block && r == NULL_TREE)
24116 21 : || TREE_CODE (cmp_expr.value) != EQ_EXPR)
24117 : {
24118 3 : eloc = c_parser_peek_token (parser)->location;
24119 3 : error_at (eloc, "unexpected %<else%>");
24120 3 : goto saw_error;
24121 : }
24122 :
24123 21 : c_parser_consume_token (parser);
24124 :
24125 21 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
24126 1 : goto saw_error;
24127 :
24128 20 : extra_scope = true;
24129 20 : v = c_parser_cast_expression (parser, NULL).value;
24130 20 : non_lvalue_p = !lvalue_p (v);
24131 20 : v = c_fully_fold (v, false, NULL, true);
24132 20 : if (v == error_mark_node)
24133 0 : goto saw_error;
24134 20 : if (non_lvalue_p)
24135 0 : v = non_lvalue (v);
24136 20 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
24137 1 : goto saw_error;
24138 :
24139 19 : expr = c_parser_expr_no_commas (parser, NULL);
24140 :
24141 19 : if (!c_tree_equal (expr.value, unfolded_lhs))
24142 1 : goto bad_if;
24143 :
24144 18 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
24145 1 : goto saw_error;
24146 :
24147 17 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
24148 0 : goto saw_error;
24149 :
24150 17 : extra_scope = false;
24151 17 : code = OMP_ATOMIC_CAPTURE_OLD;
24152 17 : if (r == NULL_TREE)
24153 : /* Signal to c_finish_omp_atomic that in
24154 : if (x == e) { x = d; } else { v = x; }
24155 : case the store to v should be conditional. */
24156 10 : r = void_list_node;
24157 : }
24158 36 : else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24159 : {
24160 1 : c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
24161 1 : goto saw_error;
24162 : }
24163 35 : else if (code == OMP_ATOMIC_CAPTURE_NEW
24164 35 : && r != NULL_TREE
24165 9 : && v == NULL_TREE)
24166 52 : code = OMP_ATOMIC;
24167 52 : goto stmt_done;
24168 : }
24169 1383 : eloc = c_parser_peek_token (parser)->location;
24170 1383 : expr = c_parser_cast_expression (parser, NULL);
24171 1383 : lhs = expr.value;
24172 1383 : expr = default_function_array_conversion (eloc, expr);
24173 1383 : unfolded_lhs = expr.value;
24174 1383 : lhs = c_fully_fold (lhs, false, NULL, true);
24175 1383 : orig_lhs = lhs;
24176 1383 : switch (TREE_CODE (lhs))
24177 : {
24178 4 : invalid_compare:
24179 4 : error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
24180 : /* FALLTHRU */
24181 84 : case ERROR_MARK:
24182 84 : saw_error:
24183 84 : c_parser_skip_to_end_of_block_or_statement (parser);
24184 90 : if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24185 4 : c_parser_consume_token (parser);
24186 84 : if (structured_block)
24187 : {
24188 10 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24189 9 : c_parser_consume_token (parser);
24190 1 : else if (code == OMP_ATOMIC_CAPTURE_NEW)
24191 : {
24192 1 : c_parser_skip_to_end_of_block_or_statement (parser);
24193 1 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24194 1 : c_parser_consume_token (parser);
24195 : }
24196 : }
24197 84 : return;
24198 :
24199 159 : case POSTINCREMENT_EXPR:
24200 159 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24201 20 : code = OMP_ATOMIC_CAPTURE_OLD;
24202 : /* FALLTHROUGH */
24203 221 : case PREINCREMENT_EXPR:
24204 221 : lhs = TREE_OPERAND (lhs, 0);
24205 221 : unfolded_lhs = NULL_TREE;
24206 221 : opcode = PLUS_EXPR;
24207 221 : rhs = integer_one_node;
24208 221 : if (compare)
24209 2 : goto invalid_compare;
24210 : break;
24211 :
24212 24 : case POSTDECREMENT_EXPR:
24213 24 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
24214 2 : code = OMP_ATOMIC_CAPTURE_OLD;
24215 : /* FALLTHROUGH */
24216 52 : case PREDECREMENT_EXPR:
24217 52 : lhs = TREE_OPERAND (lhs, 0);
24218 52 : unfolded_lhs = NULL_TREE;
24219 52 : opcode = MINUS_EXPR;
24220 52 : rhs = integer_one_node;
24221 52 : if (compare)
24222 2 : goto invalid_compare;
24223 : break;
24224 :
24225 12 : case COMPOUND_EXPR:
24226 12 : if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
24227 12 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
24228 12 : && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
24229 12 : && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
24230 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
24231 : (TREE_OPERAND (lhs, 1), 0), 0))))
24232 : /* Undo effects of boolean_increment for post {in,de}crement. */
24233 12 : lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
24234 : /* FALLTHRU */
24235 24 : case MODIFY_EXPR:
24236 24 : if (TREE_CODE (lhs) == MODIFY_EXPR
24237 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
24238 : {
24239 : /* Undo effects of boolean_increment. */
24240 24 : if (integer_onep (TREE_OPERAND (lhs, 1)))
24241 : {
24242 : /* This is pre or post increment. */
24243 12 : rhs = TREE_OPERAND (lhs, 1);
24244 12 : lhs = TREE_OPERAND (lhs, 0);
24245 12 : unfolded_lhs = NULL_TREE;
24246 12 : opcode = NOP_EXPR;
24247 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
24248 12 : && !structured_block
24249 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
24250 1 : code = OMP_ATOMIC_CAPTURE_OLD;
24251 12 : if (compare)
24252 0 : goto invalid_compare;
24253 : break;
24254 : }
24255 12 : if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
24256 12 : && TREE_OPERAND (lhs, 0)
24257 12 : == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
24258 : {
24259 : /* This is pre or post decrement. */
24260 12 : rhs = TREE_OPERAND (lhs, 1);
24261 12 : lhs = TREE_OPERAND (lhs, 0);
24262 12 : unfolded_lhs = NULL_TREE;
24263 12 : opcode = NOP_EXPR;
24264 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
24265 12 : && !structured_block
24266 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
24267 1 : code = OMP_ATOMIC_CAPTURE_OLD;
24268 12 : if (compare)
24269 0 : goto invalid_compare;
24270 : break;
24271 : }
24272 : }
24273 : /* FALLTHRU */
24274 1082 : default:
24275 1082 : if (!lvalue_p (unfolded_lhs))
24276 5 : lhs = non_lvalue (lhs);
24277 1201 : if (compare && !c_parser_next_token_is (parser, CPP_EQ))
24278 : {
24279 7 : c_parser_error (parser, "expected %<=%>");
24280 7 : goto saw_error;
24281 : }
24282 1075 : switch (c_parser_peek_token (parser)->type)
24283 : {
24284 : case CPP_MULT_EQ:
24285 : opcode = MULT_EXPR;
24286 : break;
24287 : case CPP_DIV_EQ:
24288 : opcode = TRUNC_DIV_EXPR;
24289 : break;
24290 : case CPP_PLUS_EQ:
24291 : opcode = PLUS_EXPR;
24292 : break;
24293 : case CPP_MINUS_EQ:
24294 : opcode = MINUS_EXPR;
24295 : break;
24296 : case CPP_LSHIFT_EQ:
24297 : opcode = LSHIFT_EXPR;
24298 : break;
24299 : case CPP_RSHIFT_EQ:
24300 : opcode = RSHIFT_EXPR;
24301 : break;
24302 : case CPP_AND_EQ:
24303 : opcode = BIT_AND_EXPR;
24304 : break;
24305 : case CPP_OR_EQ:
24306 : opcode = BIT_IOR_EXPR;
24307 : break;
24308 : case CPP_XOR_EQ:
24309 : opcode = BIT_XOR_EXPR;
24310 : break;
24311 556 : case CPP_EQ:
24312 556 : c_parser_consume_token (parser);
24313 556 : eloc = c_parser_peek_token (parser)->location;
24314 556 : expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
24315 556 : rhs1 = expr.value;
24316 556 : switch (TREE_CODE (rhs1))
24317 : {
24318 289 : case MULT_EXPR:
24319 289 : case TRUNC_DIV_EXPR:
24320 289 : case RDIV_EXPR:
24321 289 : case PLUS_EXPR:
24322 289 : case MINUS_EXPR:
24323 289 : case LSHIFT_EXPR:
24324 289 : case RSHIFT_EXPR:
24325 289 : case BIT_AND_EXPR:
24326 289 : case BIT_IOR_EXPR:
24327 289 : case BIT_XOR_EXPR:
24328 289 : if (compare)
24329 : break;
24330 282 : if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
24331 : {
24332 147 : opcode = TREE_CODE (rhs1);
24333 147 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24334 : true);
24335 147 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
24336 : true);
24337 147 : goto stmt_done;
24338 : }
24339 135 : if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
24340 : {
24341 117 : opcode = TREE_CODE (rhs1);
24342 117 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
24343 : true);
24344 117 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24345 : true);
24346 117 : swapped = !commutative_tree_code (opcode);
24347 117 : goto stmt_done;
24348 : }
24349 : break;
24350 69 : case COND_EXPR:
24351 69 : if (!compare)
24352 : break;
24353 66 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
24354 44 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
24355 97 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
24356 : break;
24357 63 : if (!TREE_OPERAND (rhs1, 1))
24358 : break;
24359 63 : if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
24360 : break;
24361 58 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
24362 : unfolded_lhs))
24363 : {
24364 39 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
24365 : {
24366 23 : opcode = COND_EXPR;
24367 23 : rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24368 : 0), 1),
24369 : false, NULL, true);
24370 23 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
24371 : NULL, true);
24372 23 : goto stmt_done;
24373 : }
24374 16 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
24375 16 : TREE_OPERAND (rhs1, 1)))
24376 : {
24377 21 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
24378 14 : ? MIN_EXPR : MAX_EXPR);
24379 14 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24380 : true);
24381 14 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24382 : 0), 0),
24383 : false, NULL, true);
24384 14 : goto stmt_done;
24385 : }
24386 : }
24387 19 : else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
24388 : break;
24389 17 : else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
24390 : unfolded_lhs))
24391 : {
24392 15 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
24393 15 : TREE_OPERAND (rhs1, 1)))
24394 : {
24395 18 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
24396 15 : ? MAX_EXPR : MIN_EXPR);
24397 15 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
24398 : true);
24399 15 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
24400 : 0), 1),
24401 : false, NULL, true);
24402 15 : goto stmt_done;
24403 : }
24404 : }
24405 : break;
24406 17 : case EQ_EXPR:
24407 17 : if (!compare
24408 17 : || code != OMP_ATOMIC_CAPTURE_NEW
24409 17 : || !structured_block
24410 17 : || v
24411 17 : || r)
24412 : break;
24413 17 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
24414 17 : && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
24415 : {
24416 17 : r = lhs;
24417 17 : lhs = NULL_TREE;
24418 17 : c_parser_consume_token (parser);
24419 17 : goto restart;
24420 : }
24421 : break;
24422 0 : case ERROR_MARK:
24423 0 : goto saw_error;
24424 : default:
24425 : break;
24426 : }
24427 223 : if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
24428 : {
24429 223 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
24430 : {
24431 167 : code = OMP_ATOMIC_CAPTURE_OLD;
24432 167 : v = lhs;
24433 167 : lhs = NULL_TREE;
24434 167 : expr = default_function_array_read_conversion (eloc, expr);
24435 167 : unfolded_lhs1 = expr.value;
24436 167 : lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
24437 167 : rhs1 = NULL_TREE;
24438 167 : c_parser_consume_token (parser);
24439 167 : goto restart;
24440 : }
24441 56 : if (structured_block && !compare)
24442 : {
24443 26 : opcode = NOP_EXPR;
24444 26 : expr = default_function_array_read_conversion (eloc, expr);
24445 26 : rhs = c_fully_fold (expr.value, false, NULL, true);
24446 26 : rhs1 = NULL_TREE;
24447 26 : goto stmt_done;
24448 : }
24449 : }
24450 30 : c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
24451 30 : goto saw_error;
24452 5 : default:
24453 5 : c_parser_error (parser,
24454 : "invalid operator for %<#pragma omp atomic%>");
24455 5 : goto saw_error;
24456 : }
24457 :
24458 : /* Arrange to pass the location of the assignment operator to
24459 : c_finish_omp_atomic. */
24460 514 : loc = c_parser_peek_token (parser)->location;
24461 514 : c_parser_consume_token (parser);
24462 514 : eloc = c_parser_peek_token (parser)->location;
24463 514 : expr = c_parser_expression (parser);
24464 514 : expr = default_function_array_read_conversion (eloc, expr);
24465 514 : rhs = expr.value;
24466 514 : rhs = c_fully_fold (rhs, false, NULL, true);
24467 514 : break;
24468 : }
24469 1201 : stmt_done:
24470 1201 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
24471 : {
24472 129 : if (!no_semicolon
24473 129 : && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
24474 0 : goto saw_error;
24475 129 : no_semicolon = false;
24476 129 : v = c_parser_cast_expression (parser, NULL).value;
24477 129 : non_lvalue_p = !lvalue_p (v);
24478 129 : v = c_fully_fold (v, false, NULL, true);
24479 129 : if (v == error_mark_node)
24480 0 : goto saw_error;
24481 129 : if (non_lvalue_p)
24482 2 : v = non_lvalue (v);
24483 129 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
24484 0 : goto saw_error;
24485 129 : eloc = c_parser_peek_token (parser)->location;
24486 129 : expr = c_parser_cast_expression (parser, NULL);
24487 129 : lhs1 = expr.value;
24488 129 : expr = default_function_array_read_conversion (eloc, expr);
24489 129 : unfolded_lhs1 = expr.value;
24490 129 : lhs1 = c_fully_fold (lhs1, false, NULL, true);
24491 129 : if (lhs1 == error_mark_node)
24492 0 : goto saw_error;
24493 129 : if (!lvalue_p (unfolded_lhs1))
24494 2 : lhs1 = non_lvalue (lhs1);
24495 : }
24496 1201 : if (structured_block)
24497 : {
24498 304 : if (!no_semicolon)
24499 280 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24500 304 : c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
24501 : }
24502 897 : done:
24503 1635 : if (weak && opcode != COND_EXPR)
24504 : {
24505 1 : error_at (loc, "%<weak%> clause requires atomic equality comparison");
24506 1 : weak = false;
24507 : }
24508 1635 : if (unfolded_lhs && unfolded_lhs1
24509 1635 : && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
24510 : {
24511 5 : error ("%<#pragma omp atomic capture%> uses two different "
24512 : "expressions for memory");
24513 5 : stmt = error_mark_node;
24514 : }
24515 : else
24516 1630 : stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
24517 : swapped, memory_order, weak);
24518 1635 : if (stmt != error_mark_node)
24519 1605 : add_stmt (stmt);
24520 :
24521 1635 : if (!structured_block && !no_semicolon)
24522 1312 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24523 : }
24524 :
24525 :
24526 : /* OpenMP 2.5:
24527 : # pragma omp barrier new-line
24528 : */
24529 :
24530 : static void
24531 346 : c_parser_omp_barrier (c_parser *parser)
24532 : {
24533 346 : location_t loc = c_parser_peek_token (parser)->location;
24534 346 : c_parser_consume_pragma (parser);
24535 346 : c_parser_skip_to_pragma_eol (parser);
24536 :
24537 346 : c_finish_omp_barrier (loc);
24538 346 : }
24539 :
24540 : /* OpenMP 2.5:
24541 : # pragma omp critical [(name)] new-line
24542 : structured-block
24543 :
24544 : OpenMP 4.5:
24545 : # pragma omp critical [(name) [hint(expression)]] new-line
24546 :
24547 : LOC is the location of the #pragma itself. */
24548 :
24549 : #define OMP_CRITICAL_CLAUSE_MASK \
24550 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
24551 :
24552 : static tree
24553 144 : c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
24554 : {
24555 144 : tree stmt, name = NULL_TREE, clauses = NULL_TREE;
24556 :
24557 144 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
24558 : {
24559 49 : c_parser_consume_token (parser);
24560 49 : if (c_parser_next_token_is (parser, CPP_NAME))
24561 : {
24562 48 : name = c_parser_peek_token (parser)->value;
24563 48 : c_parser_consume_token (parser);
24564 48 : c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
24565 : }
24566 : else
24567 1 : c_parser_error (parser, "expected identifier");
24568 :
24569 49 : if (c_parser_next_token_is (parser, CPP_COMMA)
24570 49 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24571 4 : c_parser_consume_token (parser);
24572 : }
24573 144 : clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
24574 : "#pragma omp critical");
24575 144 : stmt = c_parser_omp_structured_block (parser, if_p);
24576 144 : return c_finish_omp_critical (loc, stmt, name, clauses);
24577 : }
24578 :
24579 : /* OpenMP 5.0:
24580 : # pragma omp depobj ( depobj ) depobj-clause new-line
24581 :
24582 : depobj-clause:
24583 : depend (dependence-type : locator)
24584 : destroy
24585 : update (dependence-type)
24586 :
24587 : OpenMP 5.2 additionally:
24588 : destroy ( depobj )
24589 :
24590 : dependence-type:
24591 : in
24592 : out
24593 : inout
24594 : mutexinout */
24595 :
24596 : static void
24597 75 : c_parser_omp_depobj (c_parser *parser)
24598 : {
24599 75 : location_t loc = c_parser_peek_token (parser)->location;
24600 75 : c_parser_consume_pragma (parser);
24601 75 : matching_parens parens;
24602 75 : if (!parens.require_open (parser))
24603 : {
24604 3 : c_parser_skip_to_pragma_eol (parser);
24605 3 : return;
24606 : }
24607 :
24608 72 : tree depobj = c_parser_expr_no_commas (parser, NULL).value;
24609 72 : if (depobj != error_mark_node)
24610 : {
24611 71 : if (!lvalue_p (depobj))
24612 : {
24613 1 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
24614 : "%<depobj%> expression is not lvalue expression");
24615 1 : depobj = error_mark_node;
24616 : }
24617 : else
24618 : {
24619 123 : tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
24620 : depobj, false);
24621 70 : if (addr == error_mark_node)
24622 : depobj = error_mark_node;
24623 : else
24624 123 : depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
24625 : addr, RO_UNARY_STAR);
24626 : }
24627 : }
24628 :
24629 72 : parens.skip_until_found_close (parser);
24630 72 : tree clause = NULL_TREE;
24631 72 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
24632 72 : if (c_parser_next_token_is (parser, CPP_COMMA))
24633 3 : c_parser_consume_token (parser);
24634 72 : location_t c_loc = c_parser_peek_token (parser)->location;
24635 72 : if (c_parser_next_token_is (parser, CPP_NAME))
24636 : {
24637 71 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24638 :
24639 71 : c_parser_consume_token (parser);
24640 71 : if (!strcmp ("depend", p))
24641 : {
24642 38 : clause = c_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
24643 38 : clause = c_finish_omp_clauses (clause, C_ORT_OMP);
24644 38 : if (!clause)
24645 2 : clause = error_mark_node;
24646 : }
24647 33 : else if (!strcmp ("destroy", p))
24648 : {
24649 22 : matching_parens c_parens;
24650 22 : kind = OMP_CLAUSE_DEPEND_LAST;
24651 22 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
24652 22 : && c_parens.require_open (parser))
24653 : {
24654 7 : tree destobj = c_parser_expr_no_commas (parser, NULL).value;
24655 7 : if (!lvalue_p (destobj))
24656 1 : error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
24657 : "%<destroy%> expression is not lvalue expression");
24658 6 : else if (depobj != error_mark_node
24659 6 : && !operand_equal_p (destobj, depobj,
24660 : OEP_MATCH_SIDE_EFFECTS
24661 : | OEP_LEXICOGRAPHIC))
24662 4 : warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
24663 : "the %<destroy%> expression %qE should be the same "
24664 : "as the %<depobj%> argument %qE", destobj, depobj);
24665 7 : c_parens.skip_until_found_close (parser);
24666 : }
24667 : }
24668 11 : else if (!strcmp ("update", p))
24669 : {
24670 10 : matching_parens c_parens;
24671 10 : if (c_parens.require_open (parser))
24672 : {
24673 10 : location_t c2_loc = c_parser_peek_token (parser)->location;
24674 10 : if (c_parser_next_token_is (parser, CPP_NAME))
24675 : {
24676 10 : const char *p2
24677 10 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24678 :
24679 10 : c_parser_consume_token (parser);
24680 10 : if (!strcmp ("in", p2))
24681 : kind = OMP_CLAUSE_DEPEND_IN;
24682 8 : else if (!strcmp ("out", p2))
24683 : kind = OMP_CLAUSE_DEPEND_OUT;
24684 7 : else if (!strcmp ("inout", p2))
24685 : kind = OMP_CLAUSE_DEPEND_INOUT;
24686 4 : else if (!strcmp ("mutexinoutset", p2))
24687 : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
24688 3 : else if (!strcmp ("inoutset", p2))
24689 : kind = OMP_CLAUSE_DEPEND_INOUTSET;
24690 : }
24691 : if (kind == OMP_CLAUSE_DEPEND_INVALID)
24692 : {
24693 1 : clause = error_mark_node;
24694 1 : error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
24695 : "%<mutexinoutset%> or %<inoutset%>");
24696 : }
24697 10 : c_parens.skip_until_found_close (parser);
24698 : }
24699 : else
24700 0 : clause = error_mark_node;
24701 : }
24702 : }
24703 72 : if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
24704 : {
24705 2 : clause = error_mark_node;
24706 2 : error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
24707 : }
24708 72 : c_parser_skip_to_pragma_eol (parser);
24709 :
24710 72 : c_finish_omp_depobj (loc, depobj, kind, clause);
24711 : }
24712 :
24713 :
24714 : /* OpenMP 2.5:
24715 : # pragma omp flush flush-vars[opt] new-line
24716 :
24717 : flush-vars:
24718 : ( variable-list )
24719 :
24720 : OpenMP 5.0:
24721 : # pragma omp flush memory-order-clause new-line */
24722 :
24723 : static void
24724 59 : c_parser_omp_flush (c_parser *parser)
24725 : {
24726 59 : location_t loc = c_parser_peek_token (parser)->location;
24727 59 : c_parser_consume_pragma (parser);
24728 59 : enum memmodel mo = MEMMODEL_LAST;
24729 59 : if (c_parser_next_token_is (parser, CPP_COMMA)
24730 59 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24731 8 : c_parser_consume_token (parser);
24732 59 : if (c_parser_next_token_is (parser, CPP_NAME))
24733 : {
24734 27 : const char *p
24735 27 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24736 :
24737 27 : if (!strcmp (p, "seq_cst"))
24738 : mo = MEMMODEL_SEQ_CST;
24739 21 : else if (!strcmp (p, "acq_rel"))
24740 : mo = MEMMODEL_ACQ_REL;
24741 15 : else if (!strcmp (p, "release"))
24742 : mo = MEMMODEL_RELEASE;
24743 9 : else if (!strcmp (p, "acquire"))
24744 : mo = MEMMODEL_ACQUIRE;
24745 : else
24746 3 : error_at (c_parser_peek_token (parser)->location,
24747 : "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
24748 : "%<acquire%>");
24749 27 : c_parser_consume_token (parser);
24750 : }
24751 59 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
24752 : {
24753 20 : if (mo != MEMMODEL_LAST)
24754 4 : error_at (c_parser_peek_token (parser)->location,
24755 : "%<flush%> list specified together with memory order "
24756 : "clause");
24757 20 : c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
24758 : }
24759 39 : else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
24760 1 : c_parser_error (parser, "expected %<(%> or end of line");
24761 59 : c_parser_skip_to_pragma_eol (parser);
24762 :
24763 59 : c_finish_omp_flush (loc, mo);
24764 59 : }
24765 :
24766 : /* Return true if next tokens contain a standard attribute that contains
24767 : omp::directive (DIRECTIVE). */
24768 :
24769 : static bool
24770 363 : c_parser_omp_section_scan (c_parser *parser, const char *directive,
24771 : bool tentative)
24772 : {
24773 363 : if (!c_parser_nth_token_starts_std_attributes (parser, 1))
24774 : return false;
24775 36 : unsigned int n = 3;
24776 36 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
24777 : return false;
24778 36 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
24779 36 : if (token->type != CPP_CLOSE_SQUARE)
24780 : return false;
24781 36 : token = c_parser_peek_nth_token_raw (parser, n + 1);
24782 36 : if (token->type != CPP_CLOSE_SQUARE)
24783 : return false;
24784 36 : if (n < 9)
24785 : return false;
24786 35 : if (c_parser_peek_nth_token_raw (parser, 3)->type == CPP_NAME
24787 35 : && c_parser_peek_nth_token_raw (parser, 4)->type == CPP_OPEN_PAREN
24788 35 : && c_parser_peek_nth_token_raw (parser, 5)->type == CPP_NAME)
24789 : {
24790 0 : tree first = c_parser_peek_nth_token_raw (parser, 3)->value;
24791 0 : tree second = c_parser_peek_nth_token_raw (parser, 5)->value;
24792 0 : if (strcmp (IDENTIFIER_POINTER (first), "directive")
24793 0 : && strcmp (IDENTIFIER_POINTER (first), "__directive__"))
24794 : return false;
24795 0 : if (strcmp (IDENTIFIER_POINTER (second), directive))
24796 : return false;
24797 : }
24798 35 : if (tentative)
24799 : return true;
24800 32 : location_t first_loc = c_parser_peek_token (parser)->location;
24801 32 : location_t last_loc = c_parser_peek_nth_token_raw (parser, n + 1)->location;
24802 32 : location_t middle_loc = UNKNOWN_LOCATION;
24803 32 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24804 32 : bool seen = false;
24805 32 : int cnt = 0;
24806 67 : for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
24807 35 : if (is_attribute_namespace_p ("omp", attr)
24808 35 : && is_attribute_p ("directive", get_attribute_name (attr)))
24809 : {
24810 68 : for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
24811 : {
24812 36 : tree d = TREE_VALUE (a);
24813 36 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
24814 36 : c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
24815 36 : cnt++;
24816 36 : if (first->type == CPP_NAME
24817 36 : && strcmp (IDENTIFIER_POINTER (first->value),
24818 : directive) == 0)
24819 : {
24820 31 : seen = true;
24821 31 : if (middle_loc == UNKNOWN_LOCATION)
24822 31 : middle_loc = first->location;
24823 : }
24824 : }
24825 : }
24826 32 : if (!seen)
24827 : return false;
24828 31 : if (cnt != 1 || TREE_CHAIN (std_attrs))
24829 : {
24830 7 : error_at (make_location (first_loc, last_loc, middle_loc),
24831 : "%<[[omp::directive(%s)]]%> must be the only specified "
24832 : "attribute on a statement", directive);
24833 7 : return false;
24834 : }
24835 24 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
24836 24 : return true;
24837 : }
24838 :
24839 : /* Parse an OpenMP structured block sequence. KIND is the corresponding
24840 : separating directive. */
24841 :
24842 : static tree
24843 815 : c_parser_omp_structured_block_sequence (c_parser *parser,
24844 : enum pragma_kind kind)
24845 : {
24846 815 : tree stmt = push_stmt_list ();
24847 815 : c_parser_statement (parser, NULL);
24848 909 : do
24849 : {
24850 862 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24851 : break;
24852 461 : if (c_parser_next_token_is (parser, CPP_EOF))
24853 : break;
24854 :
24855 461 : if (kind != PRAGMA_NONE
24856 461 : && c_parser_peek_token (parser)->pragma_kind == kind)
24857 : break;
24858 :
24859 69 : if (kind != PRAGMA_NONE
24860 104 : && c_parser_omp_section_scan (parser,
24861 : kind == PRAGMA_OMP_SCAN
24862 : ? "scan" : "section", false))
24863 : break;
24864 :
24865 47 : c_parser_statement (parser, NULL);
24866 : }
24867 : while (1);
24868 815 : return pop_stmt_list (stmt);
24869 : }
24870 :
24871 : /* OpenMP 5.0:
24872 :
24873 : scan-loop-body:
24874 : { structured-block scan-directive structured-block } */
24875 :
24876 : static void
24877 264 : c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
24878 : {
24879 264 : tree substmt;
24880 264 : location_t loc;
24881 264 : tree clauses = NULL_TREE;
24882 264 : bool found_scan = false;
24883 :
24884 264 : loc = c_parser_peek_token (parser)->location;
24885 264 : if (!open_brace_parsed
24886 264 : && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
24887 : {
24888 : /* Avoid skipping until the end of the block. */
24889 1 : parser->error = false;
24890 1 : return;
24891 : }
24892 :
24893 263 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
24894 261 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
24895 : else
24896 : {
24897 2 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24898 : "%<#pragma omp scan%> with zero preceding executable "
24899 : "statements");
24900 2 : substmt = build_empty_stmt (loc);
24901 : }
24902 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
24903 263 : SET_EXPR_LOCATION (substmt, loc);
24904 263 : add_stmt (substmt);
24905 :
24906 263 : loc = c_parser_peek_token (parser)->location;
24907 263 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
24908 : {
24909 256 : enum omp_clause_code clause = OMP_CLAUSE_ERROR;
24910 256 : found_scan = true;
24911 :
24912 256 : c_parser_consume_pragma (parser);
24913 :
24914 256 : if (c_parser_next_token_is (parser, CPP_COMMA))
24915 4 : c_parser_consume_token (parser);
24916 :
24917 256 : if (c_parser_next_token_is (parser, CPP_NAME))
24918 : {
24919 254 : const char *p
24920 254 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24921 254 : if (strcmp (p, "inclusive") == 0)
24922 : clause = OMP_CLAUSE_INCLUSIVE;
24923 126 : else if (strcmp (p, "exclusive") == 0)
24924 : clause = OMP_CLAUSE_EXCLUSIVE;
24925 : }
24926 : if (clause != OMP_CLAUSE_ERROR)
24927 : {
24928 254 : c_parser_consume_token (parser);
24929 254 : clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
24930 : }
24931 : else
24932 2 : c_parser_error (parser, "expected %<inclusive%> or "
24933 : "%<exclusive%> clause");
24934 256 : c_parser_skip_to_pragma_eol (parser);
24935 : }
24936 : else
24937 7 : error ("expected %<#pragma omp scan%>");
24938 :
24939 263 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24940 263 : if (!c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24941 254 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
24942 : else
24943 : {
24944 9 : if (found_scan)
24945 2 : warning_at (loc, OPT_Wopenmp,
24946 : "%<#pragma omp scan%> with zero succeeding executable "
24947 : "statements");
24948 9 : substmt = build_empty_stmt (loc);
24949 : }
24950 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
24951 263 : SET_EXPR_LOCATION (substmt, loc);
24952 263 : add_stmt (substmt);
24953 :
24954 263 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
24955 : "expected %<}%>");
24956 : }
24957 :
24958 :
24959 : /* Check if the next tokens can start a canonical loop. Return true if yes,
24960 : otherwise diagnose an error if ERROR_P is true, and return false. */
24961 : static bool
24962 17322 : c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser,
24963 : enum tree_code code,
24964 : bool error_p)
24965 : {
24966 17322 : if (code == OACC_LOOP)
24967 : {
24968 2581 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24969 : return true;
24970 27 : if (error_p)
24971 4 : c_parser_error (parser, "for statement expected");
24972 : }
24973 : else
24974 : {
24975 14741 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24976 : return true;
24977 :
24978 897 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
24979 582 : switch (c_parser_peek_token (parser)->pragma_kind)
24980 : {
24981 : case PRAGMA_OMP_UNROLL:
24982 : case PRAGMA_OMP_TILE:
24983 : return true;
24984 : default:
24985 : break;
24986 : }
24987 :
24988 : /* Skip standard attributes on next for in case they are
24989 : [[omp::directive (unroll partial (4))]] or
24990 : [[omp::directive (tile sizes (1, 2, 3))]] etc. */
24991 329 : size_t n = c_parser_skip_std_attribute_spec_seq (parser, 1);
24992 329 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
24993 : /* TOKEN is a raw token that hasn't been converted to a keyword yet,
24994 : we have to do the lookup explicitly. */
24995 329 : if (token->type == CPP_NAME
24996 108 : && C_IS_RESERVED_WORD (token->value)
24997 341 : && C_RID_CODE (token->value) == RID_FOR)
24998 : return true;
24999 317 : if (error_p)
25000 7 : c_parser_error (parser, "loop nest expected");
25001 : }
25002 :
25003 : return false;
25004 : }
25005 :
25006 : static tree c_parser_omp_tile (location_t, c_parser *, bool *);
25007 : static tree c_parser_omp_unroll (location_t, c_parser *, bool *);
25008 :
25009 : /* This function parses a single level of a loop nest, invoking itself
25010 : recursively if necessary.
25011 :
25012 : loop-nest :: for (...) loop-body
25013 : loop-body :: loop-nest
25014 : | { [intervening-code] loop-body [intervening-code] }
25015 : | final-loop-body
25016 : intervening-code :: structured-block-sequence
25017 : final-loop-body :: structured-block
25018 :
25019 : For a collapsed loop nest, only a single OMP_FOR is built, pulling out
25020 : all the iterator information from the inner loops into the
25021 : parser->omp_for_parse_state structure.
25022 :
25023 : The iterator decl, init, cond, and incr are stored in vectors.
25024 :
25025 : Initialization code for iterator variables is collected into
25026 : parser->omp_for_parse_state->pre_body and ends up inserted directly
25027 : into the OMP_FOR structure. */
25028 :
25029 : static tree
25030 16978 : c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
25031 : {
25032 16978 : tree decl = NULL_TREE, cond = NULL_TREE, incr = NULL_TREE, init = NULL_TREE;
25033 16978 : tree body = NULL_TREE;
25034 16978 : matching_parens parens;
25035 16978 : bool moreloops;
25036 16978 : unsigned char save_in_statement;
25037 16978 : tree loop_scope;
25038 16978 : location_t loc;
25039 16978 : struct omp_for_parse_data *omp_for_parse_state
25040 : = parser->omp_for_parse_state;
25041 16978 : gcc_assert (omp_for_parse_state);
25042 16978 : int depth = omp_for_parse_state->depth;
25043 :
25044 : /* Arrange for C23 standard attribute syntax to be parsed as regular
25045 : pragmas. */
25046 16978 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
25047 : {
25048 12 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
25049 12 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
25050 12 : if (std_attrs)
25051 0 : error_at (c_parser_peek_token (parser)->location,
25052 : "attributes other than OpenMP directives "
25053 : "are not allowed on %<for%> in loop nest");
25054 : }
25055 :
25056 16978 : loc = c_parser_peek_token (parser)->location;
25057 :
25058 : /* Handle loop transformations first. */
25059 16978 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
25060 : {
25061 576 : tree transform = NULL_TREE, sizes, body = NULL_TREE;
25062 576 : int count = 0;
25063 576 : switch (c_parser_peek_token (parser)->pragma_kind)
25064 : {
25065 208 : case PRAGMA_OMP_UNROLL:
25066 208 : c_parser_consume_pragma (parser);
25067 208 : body = push_stmt_list ();
25068 208 : transform = c_parser_omp_unroll (loc, parser, if_p);
25069 208 : body = pop_stmt_list (body);
25070 208 : if (transform == NULL_TREE || transform == error_mark_node)
25071 : {
25072 7 : transform = error_mark_node;
25073 7 : break;
25074 : }
25075 201 : gcc_assert (TREE_CODE (transform) == OMP_UNROLL);
25076 201 : if (omp_find_clause (OMP_FOR_CLAUSES (transform),
25077 : OMP_CLAUSE_PARTIAL))
25078 : {
25079 172 : if (omp_for_parse_state->count - depth > 1)
25080 : {
25081 10 : error_at (loc, "%<unroll%> construct with %<partial%> "
25082 : "clause generates just one loop with "
25083 : "canonical form but %d loops are needed",
25084 : omp_for_parse_state->count - depth);
25085 10 : transform = error_mark_node;
25086 : }
25087 : else
25088 576 : count = 1;
25089 : }
25090 : else
25091 : {
25092 29 : error_at (loc, "generated loop of %<unroll%> construct "
25093 : "without %<partial%> clause does not have "
25094 : "canonical form");
25095 29 : transform = error_mark_node;
25096 : }
25097 : break;
25098 366 : case PRAGMA_OMP_TILE:
25099 366 : c_parser_consume_pragma (parser);
25100 366 : body = push_stmt_list ();
25101 366 : transform = c_parser_omp_tile (loc, parser, if_p);
25102 366 : body = pop_stmt_list (body);
25103 366 : if (transform == NULL_TREE || transform == error_mark_node)
25104 : {
25105 40 : transform = error_mark_node;
25106 40 : break;
25107 : }
25108 326 : gcc_assert (TREE_CODE (transform) == OMP_TILE);
25109 326 : sizes = omp_find_clause (OMP_FOR_CLAUSES (transform),
25110 : OMP_CLAUSE_SIZES);
25111 326 : gcc_assert (sizes);
25112 326 : count = list_length (OMP_CLAUSE_SIZES_LIST (sizes));
25113 326 : if (depth + count < omp_for_parse_state->count)
25114 : {
25115 16 : error_at (loc, "%<tile%> construct generates %d loops "
25116 : "with canonical form but %d loops are needed",
25117 : count, omp_for_parse_state->count - depth);
25118 16 : transform = error_mark_node;
25119 : }
25120 : break;
25121 2 : default:
25122 2 : c_parser_pragma (parser, pragma_stmt, NULL, void_list_node);
25123 2 : break;
25124 : }
25125 576 : if (transform == NULL_TREE)
25126 2 : error_at (loc, "expected %<for%> loop or OpenMP loop "
25127 : "transformation construct");
25128 576 : if (transform == NULL_TREE || transform == error_mark_node)
25129 : {
25130 104 : omp_for_parse_state->fail = true;
25131 104 : return NULL_TREE;
25132 : }
25133 1030 : for (count = omp_for_parse_state->count; depth < count; ++depth)
25134 : {
25135 558 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE;
25136 558 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE;
25137 558 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE;
25138 558 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE;
25139 : }
25140 472 : omp_for_parse_state->want_nested_loop = false;
25141 472 : return body;
25142 : }
25143 :
25144 : /* We have already matched the FOR token but not consumed it yet. */
25145 16402 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
25146 16402 : c_parser_consume_token (parser);
25147 :
25148 : /* Forbid break/continue in the loop initializer, condition, and
25149 : increment expressions. */
25150 16402 : save_in_statement = in_statement;
25151 16402 : in_statement = IN_OMP_BLOCK;
25152 :
25153 : /* We are not in intervening code now. */
25154 16402 : omp_for_parse_state->in_intervening_code = false;
25155 :
25156 16402 : if (!parens.require_open (parser))
25157 : {
25158 0 : omp_for_parse_state->fail = true;
25159 0 : return NULL_TREE;
25160 : }
25161 :
25162 : /* An implicit scope block surrounds each level of FOR loop, for
25163 : declarations of iteration variables at this loop depth. */
25164 16402 : loop_scope = c_begin_compound_stmt (true);
25165 :
25166 : /* Parse the initialization declaration or expression. */
25167 16402 : if (c_parser_next_tokens_start_declaration (parser))
25168 : {
25169 : /* This is a declaration, which must be added to the pre_body code. */
25170 4753 : tree this_pre_body = push_stmt_list ();
25171 4753 : c_in_omp_for = true;
25172 4753 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
25173 : false);
25174 4753 : c_in_omp_for = false;
25175 4753 : this_pre_body = pop_stmt_list (this_pre_body);
25176 4753 : append_to_statement_list_force (this_pre_body,
25177 : &(omp_for_parse_state->pre_body));
25178 4753 : decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
25179 4753 : if (decl == NULL)
25180 0 : goto error_init;
25181 4753 : if (DECL_INITIAL (decl) == error_mark_node)
25182 1 : decl = error_mark_node;
25183 : init = decl;
25184 : }
25185 11649 : else if (c_parser_next_token_is (parser, CPP_NAME)
25186 11649 : && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
25187 : {
25188 11647 : struct c_expr decl_exp;
25189 11647 : struct c_expr init_exp;
25190 11647 : location_t init_loc;
25191 :
25192 11647 : decl_exp = c_parser_postfix_expression (parser);
25193 11647 : decl = decl_exp.value;
25194 :
25195 11647 : c_parser_require (parser, CPP_EQ, "expected %<=%>");
25196 :
25197 11647 : init_loc = c_parser_peek_token (parser)->location;
25198 11647 : init_exp = c_parser_expr_no_commas (parser, NULL);
25199 11647 : init_exp = default_function_array_read_conversion (init_loc,
25200 : init_exp);
25201 11647 : c_in_omp_for = true;
25202 11647 : init = build_modify_expr (init_loc, decl, decl_exp.original_type,
25203 : NOP_EXPR, init_loc, init_exp.value,
25204 : init_exp.original_type);
25205 11647 : c_in_omp_for = false;
25206 11647 : init = c_process_expr_stmt (init_loc, init);
25207 :
25208 11647 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
25209 : }
25210 : else
25211 : {
25212 2 : error_init:
25213 2 : c_parser_error (parser,
25214 : "expected iteration declaration or initialization");
25215 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
25216 : "expected %<)%>");
25217 2 : omp_for_parse_state->fail = true;
25218 2 : goto parse_next;
25219 : }
25220 :
25221 : /* Parse the loop condition. */
25222 16400 : if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
25223 : {
25224 16398 : location_t cond_loc = c_parser_peek_token (parser)->location;
25225 16398 : c_in_omp_for = true;
25226 16398 : struct c_expr cond_expr
25227 16398 : = c_parser_binary_expression (parser, NULL, NULL_TREE);
25228 16398 : c_in_omp_for = false;
25229 :
25230 16398 : cond = cond_expr.value;
25231 16398 : cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
25232 16398 : switch (cond_expr.original_code)
25233 : {
25234 : case GT_EXPR:
25235 : case GE_EXPR:
25236 : case LT_EXPR:
25237 : case LE_EXPR:
25238 : break;
25239 2425 : case NE_EXPR:
25240 2425 : if (omp_for_parse_state->code != OACC_LOOP)
25241 : break;
25242 : /* FALLTHRU. */
25243 7 : default:
25244 : /* Can't be cond = error_mark_node, because we want to preserve
25245 : the location until c_finish_omp_for. */
25246 7 : cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
25247 7 : break;
25248 : }
25249 16398 : protected_set_expr_location (cond, cond_loc);
25250 : }
25251 16400 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
25252 :
25253 : /* Parse the increment expression. */
25254 16400 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
25255 : {
25256 16400 : location_t incr_loc = c_parser_peek_token (parser)->location;
25257 :
25258 16400 : incr = c_process_expr_stmt (incr_loc,
25259 32800 : c_parser_expression (parser).value);
25260 : }
25261 16400 : parens.skip_until_found_close (parser);
25262 :
25263 16400 : if (decl == NULL || decl == error_mark_node || init == error_mark_node)
25264 3 : omp_for_parse_state->fail = true;
25265 : else
25266 : {
25267 16397 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
25268 16397 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
25269 16397 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
25270 16397 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
25271 : }
25272 :
25273 16402 : parse_next:
25274 16402 : moreloops = depth < omp_for_parse_state->count - 1;
25275 16402 : omp_for_parse_state->want_nested_loop = moreloops;
25276 16402 : if (moreloops
25277 16402 : && c_parser_omp_next_tokens_can_be_canon_loop (parser,
25278 : omp_for_parse_state->code,
25279 : false))
25280 : {
25281 5327 : omp_for_parse_state->depth++;
25282 5327 : body = c_parser_omp_loop_nest (parser, if_p);
25283 5327 : omp_for_parse_state->depth--;
25284 : }
25285 11221 : else if (moreloops && c_parser_next_token_is (parser, CPP_OPEN_BRACE))
25286 : {
25287 : /* This is the open brace in the loop-body grammar production. Rather
25288 : than trying to special-case braces, just parse it as a compound
25289 : statement and handle the nested loop-body case there. Note that
25290 : when we see a further open brace inside the compound statement
25291 : loop-body, we don't know whether it is the start of intervening
25292 : code that is a compound statement, or a level of braces
25293 : surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
25294 : bit to ensure we have only one nested loop at each level. */
25295 127 : omp_for_parse_state->in_intervening_code = true;
25296 127 : body = c_parser_compound_statement (parser, NULL);
25297 127 : omp_for_parse_state->in_intervening_code = false;
25298 127 : if (omp_for_parse_state->want_nested_loop)
25299 : {
25300 : /* We have already parsed the whole loop body and not found a
25301 : nested loop. */
25302 11 : error_at (omp_for_parse_state->for_loc,
25303 : "not enough nested loops");
25304 11 : omp_for_parse_state->fail = true;
25305 : }
25306 16402 : if_p = NULL;
25307 : }
25308 : else
25309 : {
25310 : /* This is the final-loop-body case in the grammar: we have
25311 : something that is not a FOR and not an open brace. */
25312 10948 : if (moreloops)
25313 : {
25314 : /* If we were expecting a nested loop, give an error and mark
25315 : that parsing has failed, and try to recover by parsing the
25316 : body as regular code without further collapsing. */
25317 19 : error_at (omp_for_parse_state->for_loc,
25318 : "not enough nested loops");
25319 19 : omp_for_parse_state->fail = true;
25320 : }
25321 10948 : in_statement = IN_OMP_FOR;
25322 10948 : parser->omp_for_parse_state = NULL;
25323 10948 : body = push_stmt_list ();
25324 10948 : if (omp_for_parse_state->inscan)
25325 264 : c_parser_omp_scan_loop_body (parser, false);
25326 : else
25327 10684 : add_stmt (c_parser_c99_block_statement (parser, if_p));
25328 10948 : body = pop_stmt_list (body);
25329 10948 : parser->omp_for_parse_state = omp_for_parse_state;
25330 : }
25331 16402 : in_statement = save_in_statement;
25332 16402 : omp_for_parse_state->want_nested_loop = false;
25333 16402 : omp_for_parse_state->in_intervening_code = true;
25334 :
25335 : /* Pop and return the implicit scope surrounding this level of loop.
25336 : If the iteration variable at this depth was bound in the for loop,
25337 : pull out and save the binding. Later in c_parser_omp_for_loop,
25338 : these bindings will be moved to the scope surrounding the entire
25339 : OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
25340 : we have already resolved all references to the iteration variable
25341 : in its true scope. */
25342 16402 : if (body)
25343 16396 : add_stmt (body);
25344 16402 : body = c_end_compound_stmt (loc, loop_scope, true);
25345 16402 : if (decl && TREE_CODE (body) == BIND_EXPR)
25346 : {
25347 5139 : tree t = BIND_EXPR_VARS (body);
25348 5139 : tree prev = NULL_TREE, next = NULL_TREE;
25349 5575 : while (t)
25350 : {
25351 5188 : next = DECL_CHAIN (t);
25352 5188 : if (t == decl)
25353 : {
25354 4752 : if (prev)
25355 0 : DECL_CHAIN (prev) = next;
25356 : else
25357 : {
25358 4752 : BIND_EXPR_VARS (body) = next;
25359 4752 : BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
25360 : }
25361 4752 : DECL_CHAIN (t) = omp_for_parse_state->bindings;
25362 4752 : omp_for_parse_state->bindings = t;
25363 4752 : break;
25364 : }
25365 : else
25366 : {
25367 : prev = t;
25368 : t = next;
25369 : }
25370 : }
25371 5139 : if (BIND_EXPR_VARS (body) == NULL_TREE)
25372 4752 : body = BIND_EXPR_BODY (body);
25373 : }
25374 :
25375 : return body;
25376 : }
25377 :
25378 : /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
25379 : The real trick here is to determine the loop control variable early
25380 : so that we can push a new decl if necessary to make it private.
25381 : LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
25382 : respectively. */
25383 :
25384 : static tree
25385 11546 : c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
25386 : tree clauses, tree *cclauses, bool *if_p)
25387 : {
25388 11546 : tree body, stmt, cl;
25389 11546 : tree ret = NULL_TREE;
25390 11546 : tree ordered_cl = NULL_TREE;
25391 11546 : int i, collapse = 1, ordered = 0, count;
25392 11546 : bool oacc_tiling = false;
25393 11546 : bool inscan = false;
25394 11546 : struct omp_for_parse_data data;
25395 11546 : struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
25396 :
25397 27488 : for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
25398 15942 : if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
25399 2954 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
25400 12988 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
25401 : {
25402 111 : oacc_tiling = true;
25403 111 : collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
25404 : }
25405 12877 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES)
25406 464 : collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl));
25407 12413 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
25408 12413 : && OMP_CLAUSE_ORDERED_EXPR (cl))
25409 : {
25410 161 : ordered_cl = cl;
25411 161 : ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
25412 : }
25413 12252 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
25414 2107 : && OMP_CLAUSE_REDUCTION_INSCAN (cl)
25415 12637 : && (code == OMP_SIMD || code == OMP_FOR))
25416 : inscan = true;
25417 :
25418 11546 : if (ordered && ordered < collapse)
25419 : {
25420 2 : error_at (OMP_CLAUSE_LOCATION (ordered_cl),
25421 : "%<ordered%> clause parameter is less than %<collapse%>");
25422 2 : OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
25423 2 : = build_int_cst (NULL_TREE, collapse);
25424 2 : ordered = collapse;
25425 : }
25426 :
25427 11546 : gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0));
25428 11546 : count = ordered ? ordered : collapse;
25429 :
25430 11546 : if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, true))
25431 : return NULL;
25432 :
25433 : /* Initialize parse state for recursive descent. */
25434 11535 : data.declv = make_tree_vec (count);
25435 11535 : data.initv = make_tree_vec (count);
25436 11535 : data.condv = make_tree_vec (count);
25437 11535 : data.incrv = make_tree_vec (count);
25438 11535 : data.pre_body = NULL_TREE;
25439 11535 : data.bindings = NULL_TREE;
25440 11535 : data.for_loc = c_parser_peek_token (parser)->location;
25441 11535 : data.count = count;
25442 11535 : data.depth = 0;
25443 11535 : data.want_nested_loop = true;
25444 11535 : data.ordered = ordered > 0;
25445 11535 : data.in_intervening_code = false;
25446 11535 : data.perfect_nesting_fail = false;
25447 11535 : data.fail = false;
25448 11535 : data.inscan = inscan;
25449 11535 : data.saw_intervening_code = false;
25450 11535 : data.code = code;
25451 11535 : parser->omp_for_parse_state = &data;
25452 :
25453 11535 : body = c_parser_omp_loop_nest (parser, if_p);
25454 :
25455 : /* Add saved bindings for iteration variables that were declared in
25456 : the nested for loop to the scope surrounding the entire loop. */
25457 16287 : for (tree t = data.bindings; t; )
25458 : {
25459 4752 : tree n = TREE_CHAIN (t);
25460 4752 : TREE_CHAIN (t) = NULL_TREE;
25461 4752 : pushdecl (t);
25462 4752 : t = n;
25463 : }
25464 :
25465 : /* Only bother calling c_finish_omp_for if we haven't already generated
25466 : an error from the initialization parsing. */
25467 11535 : if (!data.fail)
25468 : {
25469 11372 : c_in_omp_for = true;
25470 11372 : stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
25471 : data.condv, data.incrv,
25472 : body, data.pre_body, true);
25473 11372 : c_in_omp_for = false;
25474 :
25475 : /* Check for iterators appearing in lb, b or incr expressions. */
25476 11372 : if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
25477 : stmt = NULL_TREE;
25478 :
25479 : /* Check for errors involving lb/ub/incr expressions referencing
25480 : variables declared in intervening code. */
25481 11372 : if (data.saw_intervening_code
25482 42 : && stmt
25483 11414 : && !c_omp_check_loop_binding_exprs (stmt, NULL))
25484 : stmt = NULL_TREE;
25485 :
25486 11362 : if (stmt)
25487 : {
25488 11217 : add_stmt (stmt);
25489 :
25490 27317 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
25491 : {
25492 16558 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
25493 16558 : if (init == NULL_TREE)
25494 : break;
25495 16100 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
25496 16100 : tree decl = TREE_OPERAND (init, 0);
25497 16100 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
25498 16100 : gcc_assert (COMPARISON_CLASS_P (cond));
25499 16100 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
25500 :
25501 16100 : tree op0 = TREE_OPERAND (init, 1);
25502 16100 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
25503 16100 : || TREE_CODE (op0) != TREE_VEC)
25504 15913 : TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
25505 : else
25506 : {
25507 187 : TREE_VEC_ELT (op0, 1)
25508 187 : = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
25509 187 : TREE_VEC_ELT (op0, 2)
25510 374 : = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
25511 : }
25512 :
25513 16100 : tree op1 = TREE_OPERAND (cond, 1);
25514 16100 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
25515 16100 : || TREE_CODE (op1) != TREE_VEC)
25516 15894 : TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
25517 : else
25518 : {
25519 206 : TREE_VEC_ELT (op1, 1)
25520 206 : = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
25521 206 : TREE_VEC_ELT (op1, 2)
25522 412 : = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
25523 : }
25524 : }
25525 :
25526 11217 : if (cclauses != NULL
25527 5259 : && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
25528 : {
25529 757 : tree *c;
25530 3317 : for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
25531 2560 : if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
25532 2560 : && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
25533 1860 : c = &OMP_CLAUSE_CHAIN (*c);
25534 : else
25535 : {
25536 1441 : for (i = 0; i < count; i++)
25537 923 : if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
25538 : break;
25539 700 : if (i == count)
25540 518 : c = &OMP_CLAUSE_CHAIN (*c);
25541 182 : else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
25542 : {
25543 1 : error_at (loc,
25544 : "iteration variable %qD should not be firstprivate",
25545 1 : OMP_CLAUSE_DECL (*c));
25546 1 : *c = OMP_CLAUSE_CHAIN (*c);
25547 : }
25548 : else
25549 : {
25550 : /* Move lastprivate (decl) clause to
25551 : OMP_FOR_CLAUSES. */
25552 181 : tree l = *c;
25553 181 : *c = OMP_CLAUSE_CHAIN (*c);
25554 181 : if (code == OMP_SIMD)
25555 : {
25556 46 : OMP_CLAUSE_CHAIN (l)
25557 46 : = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25558 46 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
25559 : }
25560 : else
25561 : {
25562 135 : OMP_CLAUSE_CHAIN (l) = clauses;
25563 135 : clauses = l;
25564 : }
25565 : }
25566 : }
25567 : }
25568 11217 : OMP_FOR_CLAUSES (stmt) = clauses;
25569 : }
25570 : ret = stmt;
25571 : }
25572 :
25573 11535 : parser->omp_for_parse_state = save_data;
25574 11535 : return ret;
25575 : }
25576 :
25577 : /* Helper function for OpenMP parsing, split clauses and call
25578 : finish_omp_clauses on each of the set of clauses afterwards. */
25579 :
25580 : static void
25581 6573 : omp_split_clauses (location_t loc, enum tree_code code,
25582 : omp_clause_mask mask, tree clauses, tree *cclauses)
25583 : {
25584 6573 : int i;
25585 6573 : c_omp_split_clauses (loc, code, mask, clauses, cclauses);
25586 52584 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
25587 39438 : if (cclauses[i])
25588 20253 : cclauses[i] = c_finish_omp_clauses (cclauses[i],
25589 : i == C_OMP_CLAUSE_SPLIT_TARGET
25590 : ? C_ORT_OMP_TARGET : C_ORT_OMP);
25591 6573 : }
25592 :
25593 : /* OpenMP 5.0:
25594 : #pragma omp loop loop-clause[optseq] new-line
25595 : for-loop
25596 :
25597 : LOC is the location of the #pragma token.
25598 : */
25599 :
25600 : #define OMP_LOOP_CLAUSE_MASK \
25601 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25602 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25603 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25604 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25605 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
25606 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25607 :
25608 : static tree
25609 235 : c_parser_omp_loop (location_t loc, c_parser *parser,
25610 : char *p_name, omp_clause_mask mask, tree *cclauses,
25611 : bool *if_p)
25612 : {
25613 235 : tree block, clauses, ret;
25614 :
25615 235 : strcat (p_name, " loop");
25616 235 : mask |= OMP_LOOP_CLAUSE_MASK;
25617 :
25618 235 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25619 235 : if (cclauses)
25620 : {
25621 77 : omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses);
25622 77 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
25623 : }
25624 :
25625 235 : block = c_begin_compound_stmt (true);
25626 235 : ret = c_parser_omp_for_loop (loc, parser, OMP_LOOP, clauses, cclauses, if_p);
25627 235 : block = c_end_compound_stmt (loc, block, true);
25628 235 : add_stmt (block);
25629 :
25630 235 : return ret;
25631 : }
25632 :
25633 : /* OpenMP 4.0:
25634 : #pragma omp simd simd-clause[optseq] new-line
25635 : for-loop
25636 :
25637 : LOC is the location of the #pragma token.
25638 : */
25639 :
25640 : #define OMP_SIMD_CLAUSE_MASK \
25641 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
25642 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
25643 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
25644 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
25645 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25646 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25647 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25648 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25649 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25650 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
25651 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25652 :
25653 : static tree
25654 3514 : c_parser_omp_simd (location_t loc, c_parser *parser,
25655 : char *p_name, omp_clause_mask mask, tree *cclauses,
25656 : bool *if_p)
25657 : {
25658 3514 : tree block, clauses, ret;
25659 :
25660 3514 : strcat (p_name, " simd");
25661 3514 : mask |= OMP_SIMD_CLAUSE_MASK;
25662 :
25663 3514 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25664 3514 : if (cclauses)
25665 : {
25666 2783 : omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
25667 2783 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
25668 : }
25669 :
25670 3514 : block = c_begin_compound_stmt (true);
25671 3514 : ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
25672 3514 : block = c_end_compound_stmt (loc, block, true);
25673 3514 : add_stmt (block);
25674 :
25675 3514 : return ret;
25676 : }
25677 :
25678 : /* OpenMP 2.5:
25679 : #pragma omp for for-clause[optseq] new-line
25680 : for-loop
25681 :
25682 : OpenMP 4.0:
25683 : #pragma omp for simd for-simd-clause[optseq] new-line
25684 : for-loop
25685 :
25686 : LOC is the location of the #pragma token.
25687 : */
25688 :
25689 : #define OMP_FOR_CLAUSE_MASK \
25690 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25691 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25692 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25693 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
25694 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25695 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
25696 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
25697 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25698 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25699 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25700 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25701 :
25702 : static tree
25703 6191 : c_parser_omp_for (location_t loc, c_parser *parser,
25704 : char *p_name, omp_clause_mask mask, tree *cclauses,
25705 : bool *if_p)
25706 : {
25707 6191 : tree block, clauses, ret;
25708 :
25709 6191 : strcat (p_name, " for");
25710 6191 : mask |= OMP_FOR_CLAUSE_MASK;
25711 : /* parallel for{, simd} disallows nowait clause, but for
25712 : target {teams distribute ,}parallel for{, simd} it should be accepted. */
25713 6191 : if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
25714 3248 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25715 : /* Composite distribute parallel for{, simd} disallows ordered clause. */
25716 6191 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25717 2724 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
25718 :
25719 6191 : if (c_parser_next_token_is (parser, CPP_NAME))
25720 : {
25721 5440 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25722 :
25723 5440 : if (strcmp (p, "simd") == 0)
25724 : {
25725 2205 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25726 2205 : if (cclauses == NULL)
25727 301 : cclauses = cclauses_buf;
25728 :
25729 2205 : c_parser_consume_token (parser);
25730 2205 : if (!flag_openmp) /* flag_openmp_simd */
25731 14 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25732 14 : if_p);
25733 2191 : block = c_begin_compound_stmt (true);
25734 2191 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
25735 2191 : block = c_end_compound_stmt (loc, block, true);
25736 2191 : if (ret == NULL_TREE)
25737 : return ret;
25738 2180 : ret = make_node (OMP_FOR);
25739 2180 : TREE_TYPE (ret) = void_type_node;
25740 2180 : OMP_FOR_BODY (ret) = block;
25741 2180 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25742 2180 : SET_EXPR_LOCATION (ret, loc);
25743 2180 : add_stmt (ret);
25744 2180 : return ret;
25745 : }
25746 : }
25747 3986 : if (!flag_openmp) /* flag_openmp_simd */
25748 : {
25749 9 : c_parser_skip_to_pragma_eol (parser, false);
25750 9 : return NULL_TREE;
25751 : }
25752 :
25753 : /* Composite distribute parallel for disallows linear clause. */
25754 3977 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25755 1371 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
25756 :
25757 3977 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25758 3977 : if (cclauses)
25759 : {
25760 2462 : omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
25761 2462 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25762 : }
25763 :
25764 3977 : block = c_begin_compound_stmt (true);
25765 3977 : ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
25766 3977 : block = c_end_compound_stmt (loc, block, true);
25767 3977 : add_stmt (block);
25768 :
25769 3977 : return ret;
25770 : }
25771 :
25772 : static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
25773 : omp_clause_mask, tree *, bool *);
25774 :
25775 : /* OpenMP 2.5:
25776 : # pragma omp master new-line
25777 : structured-block
25778 :
25779 : LOC is the location of the #pragma token.
25780 : */
25781 :
25782 : static tree
25783 228 : c_parser_omp_master (location_t loc, c_parser *parser,
25784 : char *p_name, omp_clause_mask mask, tree *cclauses,
25785 : bool *if_p, location_t master_loc)
25786 : {
25787 228 : tree block, clauses, ret;
25788 228 : gcc_rich_location richloc (loc);
25789 228 : if (master_loc != UNKNOWN_LOCATION)
25790 91 : richloc.add_fixit_replace (master_loc, "masked");
25791 228 : warning_at (&richloc, OPT_Wdeprecated_openmp,
25792 : "%<master%> construct deprecated since OpenMP 5.1, use "
25793 : "%<masked%>");
25794 :
25795 228 : strcat (p_name, " master");
25796 :
25797 228 : if (c_parser_next_token_is (parser, CPP_NAME))
25798 : {
25799 123 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25800 :
25801 123 : if (strcmp (p, "taskloop") == 0)
25802 : {
25803 94 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25804 94 : if (cclauses == NULL)
25805 47 : cclauses = cclauses_buf;
25806 :
25807 94 : c_parser_consume_token (parser);
25808 94 : if (!flag_openmp) /* flag_openmp_simd */
25809 4 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25810 4 : if_p);
25811 90 : block = c_begin_compound_stmt (true);
25812 90 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25813 : if_p);
25814 90 : block = c_end_compound_stmt (loc, block, true);
25815 90 : if (ret == NULL_TREE)
25816 : return ret;
25817 90 : ret = c_finish_omp_master (loc, block);
25818 90 : OMP_MASTER_COMBINED (ret) = 1;
25819 90 : return ret;
25820 : }
25821 : }
25822 134 : if (!flag_openmp) /* flag_openmp_simd */
25823 : {
25824 2 : c_parser_skip_to_pragma_eol (parser, false);
25825 2 : return NULL_TREE;
25826 : }
25827 :
25828 132 : if (cclauses)
25829 : {
25830 43 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
25831 43 : omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
25832 : }
25833 : else
25834 89 : c_parser_skip_to_pragma_eol (parser);
25835 :
25836 132 : return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
25837 132 : if_p));
25838 228 : }
25839 :
25840 : /* OpenMP 5.1:
25841 : # pragma omp masked masked-clauses new-line
25842 : structured-block
25843 :
25844 : LOC is the location of the #pragma token.
25845 : */
25846 :
25847 : #define OMP_MASKED_CLAUSE_MASK \
25848 : (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
25849 :
25850 : static tree
25851 126 : c_parser_omp_masked (location_t loc, c_parser *parser,
25852 : char *p_name, omp_clause_mask mask, tree *cclauses,
25853 : bool *if_p)
25854 : {
25855 126 : tree block, clauses, ret;
25856 :
25857 126 : strcat (p_name, " masked");
25858 126 : mask |= OMP_MASKED_CLAUSE_MASK;
25859 :
25860 126 : if (c_parser_next_token_is (parser, CPP_NAME))
25861 : {
25862 87 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25863 :
25864 87 : if (strcmp (p, "taskloop") == 0)
25865 : {
25866 68 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25867 68 : if (cclauses == NULL)
25868 21 : cclauses = cclauses_buf;
25869 :
25870 68 : c_parser_consume_token (parser);
25871 68 : if (!flag_openmp) /* flag_openmp_simd */
25872 0 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25873 0 : if_p);
25874 68 : block = c_begin_compound_stmt (true);
25875 68 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25876 : if_p);
25877 68 : block = c_end_compound_stmt (loc, block, true);
25878 68 : if (ret == NULL_TREE)
25879 : return ret;
25880 68 : ret = c_finish_omp_masked (loc, block,
25881 : cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
25882 68 : OMP_MASKED_COMBINED (ret) = 1;
25883 68 : return ret;
25884 : }
25885 : }
25886 58 : if (!flag_openmp) /* flag_openmp_simd */
25887 : {
25888 0 : c_parser_skip_to_pragma_eol (parser, false);
25889 0 : return NULL_TREE;
25890 : }
25891 :
25892 58 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25893 58 : if (cclauses)
25894 : {
25895 9 : omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
25896 9 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
25897 : }
25898 :
25899 58 : return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
25900 : if_p),
25901 58 : clauses);
25902 : }
25903 :
25904 : /* OpenMP 5.1:
25905 : # pragma omp interop clauses[opt] new-line */
25906 :
25907 : #define OMP_INTEROP_CLAUSE_MASK \
25908 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25909 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DESTROY) \
25910 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25911 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INIT) \
25912 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25913 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE))
25914 :
25915 : static void
25916 183 : c_parser_omp_interop (c_parser *parser)
25917 : {
25918 183 : location_t loc = c_parser_peek_token (parser)->location;
25919 183 : c_parser_consume_pragma (parser);
25920 366 : tree clauses = c_parser_omp_all_clauses (parser,
25921 183 : OMP_INTEROP_CLAUSE_MASK,
25922 : "#pragma omp interop");
25923 183 : tree stmt = make_node (OMP_INTEROP);
25924 183 : TREE_TYPE (stmt) = void_type_node;
25925 183 : OMP_INTEROP_CLAUSES (stmt) = clauses;
25926 183 : SET_EXPR_LOCATION (stmt, loc);
25927 183 : add_stmt (stmt);
25928 183 : }
25929 :
25930 : /* OpenMP 2.5:
25931 : # pragma omp ordered new-line
25932 : structured-block
25933 :
25934 : OpenMP 4.5:
25935 : # pragma omp ordered ordered-clauses new-line
25936 : structured-block
25937 :
25938 : # pragma omp ordered depend-clauses new-line
25939 :
25940 : OpenMP 5.2
25941 : # pragma omp ordered doacross-clauses new-line */
25942 :
25943 : #define OMP_ORDERED_CLAUSE_MASK \
25944 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
25945 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
25946 :
25947 : #define OMP_ORDERED_DEPEND_CLAUSE_MASK \
25948 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25949 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
25950 :
25951 : static bool
25952 545 : c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
25953 : bool *if_p)
25954 : {
25955 545 : location_t loc = c_parser_peek_token (parser)->location;
25956 545 : c_parser_consume_pragma (parser);
25957 :
25958 545 : if (context != pragma_stmt && context != pragma_compound)
25959 : {
25960 1 : c_parser_error (parser, "expected declaration specifiers");
25961 1 : c_parser_skip_to_pragma_eol (parser, false);
25962 1 : return false;
25963 : }
25964 :
25965 544 : int n = 1;
25966 544 : if (c_parser_next_token_is (parser, CPP_COMMA))
25967 8 : n = 2;
25968 :
25969 544 : if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
25970 : {
25971 433 : const char *p
25972 433 : = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
25973 :
25974 433 : if (!strcmp ("depend", p) || !strcmp ("doacross", p))
25975 : {
25976 349 : if (!flag_openmp) /* flag_openmp_simd */
25977 : {
25978 2 : c_parser_skip_to_pragma_eol (parser, false);
25979 2 : return false;
25980 : }
25981 347 : if (context == pragma_stmt)
25982 : {
25983 16 : error_at (loc,
25984 : "%<#pragma omp ordered%> with %qs clause may "
25985 : "only be used in compound statements", p);
25986 16 : c_parser_skip_to_pragma_eol (parser, false);
25987 16 : return true;
25988 : }
25989 :
25990 331 : tree clauses
25991 662 : = c_parser_omp_all_clauses (parser,
25992 331 : OMP_ORDERED_DEPEND_CLAUSE_MASK,
25993 : "#pragma omp ordered");
25994 331 : c_finish_omp_ordered (loc, clauses, NULL_TREE);
25995 331 : return false;
25996 : }
25997 : }
25998 :
25999 195 : tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
26000 : "#pragma omp ordered");
26001 :
26002 195 : if (!flag_openmp /* flag_openmp_simd */
26003 195 : && omp_find_clause (clauses, OMP_CLAUSE_SIMD) == NULL_TREE)
26004 : return false;
26005 :
26006 193 : c_finish_omp_ordered (loc, clauses,
26007 : c_parser_omp_structured_block (parser, if_p));
26008 193 : return true;
26009 : }
26010 :
26011 : /* OpenMP 2.5:
26012 :
26013 : section-scope:
26014 : { section-sequence }
26015 :
26016 : section-sequence:
26017 : section-directive[opt] structured-block
26018 : section-sequence section-directive structured-block
26019 :
26020 : OpenMP 5.1 allows structured-block-sequence instead of structured-block.
26021 :
26022 : SECTIONS_LOC is the location of the #pragma omp sections. */
26023 :
26024 : static tree
26025 142 : c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
26026 : {
26027 142 : tree stmt, substmt;
26028 142 : bool error_suppress = false;
26029 142 : location_t loc;
26030 :
26031 142 : loc = c_parser_peek_token (parser)->location;
26032 142 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
26033 : {
26034 : /* Avoid skipping until the end of the block. */
26035 2 : parser->error = false;
26036 2 : return NULL_TREE;
26037 : }
26038 :
26039 140 : stmt = push_stmt_list ();
26040 :
26041 140 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
26042 140 : && !c_parser_omp_section_scan (parser, "section", true))
26043 : {
26044 81 : substmt = c_parser_omp_structured_block_sequence (parser,
26045 : PRAGMA_OMP_SECTION);
26046 81 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
26047 81 : SET_EXPR_LOCATION (substmt, loc);
26048 81 : add_stmt (substmt);
26049 : }
26050 :
26051 578 : while (1)
26052 : {
26053 359 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
26054 : break;
26055 219 : if (c_parser_next_token_is (parser, CPP_EOF))
26056 : break;
26057 :
26058 219 : loc = c_parser_peek_token (parser)->location;
26059 219 : c_parser_omp_section_scan (parser, "section", false);
26060 219 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
26061 : {
26062 218 : c_parser_consume_pragma (parser);
26063 218 : c_parser_skip_to_pragma_eol (parser);
26064 218 : error_suppress = false;
26065 : }
26066 1 : else if (!error_suppress)
26067 : {
26068 1 : error_at (loc, "expected %<#pragma omp section%> or %<}%>");
26069 1 : error_suppress = true;
26070 : }
26071 :
26072 219 : substmt = c_parser_omp_structured_block_sequence (parser,
26073 : PRAGMA_OMP_SECTION);
26074 219 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
26075 219 : SET_EXPR_LOCATION (substmt, loc);
26076 219 : add_stmt (substmt);
26077 : }
26078 140 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
26079 : "expected %<#pragma omp section%> or %<}%>");
26080 :
26081 140 : substmt = pop_stmt_list (stmt);
26082 :
26083 140 : stmt = make_node (OMP_SECTIONS);
26084 140 : SET_EXPR_LOCATION (stmt, sections_loc);
26085 140 : TREE_TYPE (stmt) = void_type_node;
26086 140 : OMP_SECTIONS_BODY (stmt) = substmt;
26087 :
26088 140 : return add_stmt (stmt);
26089 : }
26090 :
26091 : /* OpenMP 2.5:
26092 : # pragma omp sections sections-clause[optseq] newline
26093 : sections-scope
26094 :
26095 : LOC is the location of the #pragma token.
26096 : */
26097 :
26098 : #define OMP_SECTIONS_CLAUSE_MASK \
26099 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26100 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26101 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26102 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26103 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26104 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26105 :
26106 : static tree
26107 142 : c_parser_omp_sections (location_t loc, c_parser *parser,
26108 : char *p_name, omp_clause_mask mask, tree *cclauses)
26109 : {
26110 142 : tree block, clauses, ret;
26111 :
26112 142 : strcat (p_name, " sections");
26113 142 : mask |= OMP_SECTIONS_CLAUSE_MASK;
26114 142 : if (cclauses)
26115 36 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
26116 :
26117 142 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26118 142 : if (cclauses)
26119 : {
26120 36 : omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
26121 36 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
26122 : }
26123 :
26124 142 : block = c_begin_compound_stmt (true);
26125 142 : ret = c_parser_omp_sections_scope (loc, parser);
26126 142 : if (ret)
26127 140 : OMP_SECTIONS_CLAUSES (ret) = clauses;
26128 142 : block = c_end_compound_stmt (loc, block, true);
26129 142 : add_stmt (block);
26130 :
26131 142 : return ret;
26132 : }
26133 :
26134 : /* OpenMP 2.5:
26135 : # pragma omp parallel parallel-clause[optseq] new-line
26136 : structured-block
26137 : # pragma omp parallel for parallel-for-clause[optseq] new-line
26138 : structured-block
26139 : # pragma omp parallel sections parallel-sections-clause[optseq] new-line
26140 : structured-block
26141 :
26142 : OpenMP 4.0:
26143 : # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
26144 : structured-block
26145 :
26146 : LOC is the location of the #pragma token.
26147 : */
26148 :
26149 : #define OMP_PARALLEL_CLAUSE_MASK \
26150 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26151 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26152 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26153 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
26154 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26155 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
26156 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26157 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
26158 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26159 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
26160 :
26161 : static tree
26162 5704 : c_parser_omp_parallel (location_t loc, c_parser *parser,
26163 : char *p_name, omp_clause_mask mask, tree *cclauses,
26164 : bool *if_p)
26165 : {
26166 5704 : tree stmt, clauses, block;
26167 :
26168 5704 : strcat (p_name, " parallel");
26169 5704 : mask |= OMP_PARALLEL_CLAUSE_MASK;
26170 : /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
26171 5704 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
26172 1166 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
26173 490 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
26174 :
26175 5704 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
26176 : {
26177 4374 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26178 4374 : if (cclauses == NULL)
26179 1200 : cclauses = cclauses_buf;
26180 :
26181 4374 : c_parser_consume_token (parser);
26182 4374 : if (!flag_openmp) /* flag_openmp_simd */
26183 20 : return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
26184 4354 : block = c_begin_omp_parallel ();
26185 4354 : tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
26186 4354 : stmt
26187 4354 : = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26188 : block);
26189 4354 : if (ret == NULL_TREE)
26190 : return ret;
26191 4293 : OMP_PARALLEL_COMBINED (stmt) = 1;
26192 4293 : return stmt;
26193 : }
26194 : /* When combined with distribute, parallel has to be followed by for.
26195 : #pragma omp target parallel is allowed though. */
26196 1330 : else if (cclauses
26197 1330 : && (mask & (OMP_CLAUSE_MASK_1
26198 40 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
26199 : {
26200 0 : error_at (loc, "expected %<for%> after %qs", p_name);
26201 0 : c_parser_skip_to_pragma_eol (parser);
26202 0 : return NULL_TREE;
26203 : }
26204 1330 : else if (c_parser_next_token_is (parser, CPP_NAME))
26205 : {
26206 720 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26207 720 : location_t ploc = c_parser_peek_token (parser)->location;
26208 720 : if (cclauses == NULL && strcmp (p, "masked") == 0)
26209 : {
26210 56 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26211 56 : cclauses = cclauses_buf;
26212 :
26213 56 : c_parser_consume_token (parser);
26214 56 : if (!flag_openmp) /* flag_openmp_simd */
26215 0 : return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
26216 0 : if_p);
26217 56 : block = c_begin_omp_parallel ();
26218 56 : tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
26219 : if_p);
26220 56 : stmt = c_finish_omp_parallel (loc,
26221 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26222 : block);
26223 56 : if (ret == NULL)
26224 : return ret;
26225 : /* masked does have just filter clause, but during gimplification
26226 : isn't represented by a gimplification omp context, so for
26227 : #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
26228 : so that
26229 : #pragma omp parallel masked
26230 : #pragma omp taskloop simd lastprivate (x)
26231 : isn't confused with
26232 : #pragma omp parallel masked taskloop simd lastprivate (x) */
26233 56 : if (OMP_MASKED_COMBINED (ret))
26234 47 : OMP_PARALLEL_COMBINED (stmt) = 1;
26235 56 : return stmt;
26236 : }
26237 629 : else if (cclauses == NULL && strcmp (p, "master") == 0)
26238 : {
26239 91 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26240 91 : cclauses = cclauses_buf;
26241 :
26242 91 : c_parser_consume_token (parser);
26243 91 : if (!flag_openmp) /* flag_openmp_simd */
26244 3 : return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
26245 3 : if_p, ploc);
26246 88 : block = c_begin_omp_parallel ();
26247 88 : tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
26248 : if_p, ploc);
26249 88 : stmt = c_finish_omp_parallel (loc,
26250 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26251 : block);
26252 88 : if (ret == NULL)
26253 : return ret;
26254 : /* master doesn't have any clauses and during gimplification
26255 : isn't represented by a gimplification omp context, so for
26256 : #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
26257 : so that
26258 : #pragma omp parallel master
26259 : #pragma omp taskloop simd lastprivate (x)
26260 : isn't confused with
26261 : #pragma omp parallel master taskloop simd lastprivate (x) */
26262 88 : if (OMP_MASTER_COMBINED (ret))
26263 45 : OMP_PARALLEL_COMBINED (stmt) = 1;
26264 88 : return stmt;
26265 : }
26266 573 : else if (strcmp (p, "loop") == 0)
26267 : {
26268 43 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26269 43 : if (cclauses == NULL)
26270 24 : cclauses = cclauses_buf;
26271 :
26272 43 : c_parser_consume_token (parser);
26273 43 : if (!flag_openmp) /* flag_openmp_simd */
26274 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26275 2 : if_p);
26276 41 : block = c_begin_omp_parallel ();
26277 41 : tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26278 : if_p);
26279 41 : stmt
26280 41 : = c_finish_omp_parallel (loc,
26281 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26282 : block);
26283 41 : if (ret == NULL_TREE)
26284 : return ret;
26285 41 : OMP_PARALLEL_COMBINED (stmt) = 1;
26286 41 : return stmt;
26287 : }
26288 530 : else if (!flag_openmp) /* flag_openmp_simd */
26289 : {
26290 1 : c_parser_skip_to_pragma_eol (parser, false);
26291 1 : return NULL_TREE;
26292 : }
26293 529 : else if (cclauses == NULL && strcmp (p, "sections") == 0)
26294 : {
26295 36 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26296 36 : cclauses = cclauses_buf;
26297 :
26298 36 : c_parser_consume_token (parser);
26299 36 : block = c_begin_omp_parallel ();
26300 36 : c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
26301 36 : stmt = c_finish_omp_parallel (loc,
26302 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
26303 : block);
26304 36 : OMP_PARALLEL_COMBINED (stmt) = 1;
26305 36 : return stmt;
26306 : }
26307 : }
26308 610 : else if (!flag_openmp) /* flag_openmp_simd */
26309 : {
26310 1 : c_parser_skip_to_pragma_eol (parser, false);
26311 1 : return NULL_TREE;
26312 : }
26313 :
26314 1102 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26315 1102 : if (cclauses)
26316 : {
26317 20 : omp_split_clauses (loc, OMP_PARALLEL, mask, clauses, cclauses);
26318 20 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
26319 : }
26320 :
26321 1102 : block = c_begin_omp_parallel ();
26322 1102 : parser->omp_attrs_forbidden_p = true;
26323 1102 : c_parser_statement (parser, if_p);
26324 1102 : stmt = c_finish_omp_parallel (loc, clauses, block);
26325 :
26326 1102 : return stmt;
26327 : }
26328 :
26329 : /* OpenMP 2.5:
26330 : # pragma omp single single-clause[optseq] new-line
26331 : structured-block
26332 :
26333 : LOC is the location of the #pragma.
26334 : */
26335 :
26336 : #define OMP_SINGLE_CLAUSE_MASK \
26337 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26338 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26339 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
26340 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26341 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26342 :
26343 : static tree
26344 222 : c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
26345 : {
26346 222 : tree stmt = make_node (OMP_SINGLE);
26347 222 : SET_EXPR_LOCATION (stmt, loc);
26348 222 : TREE_TYPE (stmt) = void_type_node;
26349 :
26350 222 : OMP_SINGLE_CLAUSES (stmt)
26351 222 : = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
26352 : "#pragma omp single");
26353 222 : OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
26354 :
26355 222 : return add_stmt (stmt);
26356 : }
26357 :
26358 : /* OpenMP 5.1:
26359 : # pragma omp scope scope-clause[optseq] new-line
26360 : structured-block
26361 :
26362 : LOC is the location of the #pragma.
26363 : */
26364 :
26365 : #define OMP_SCOPE_CLAUSE_MASK \
26366 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26367 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26368 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26369 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26370 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26371 :
26372 : static tree
26373 61 : c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
26374 : {
26375 61 : tree stmt = make_node (OMP_SCOPE);
26376 61 : SET_EXPR_LOCATION (stmt, loc);
26377 61 : TREE_TYPE (stmt) = void_type_node;
26378 :
26379 61 : OMP_SCOPE_CLAUSES (stmt)
26380 61 : = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
26381 : "#pragma omp scope");
26382 61 : OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
26383 :
26384 61 : return add_stmt (stmt);
26385 : }
26386 :
26387 : /* Parse a function dispatch structured block:
26388 :
26389 : lvalue-expression = target-call ( [expression-list] );
26390 : or
26391 : target-call ( [expression-list] );
26392 :
26393 : Adapted from c_parser_expr_no_commas and c_parser_postfix_expression
26394 : (CPP_NAME/C_ID_ID) for the function name.
26395 : */
26396 : static tree
26397 155 : c_parser_omp_dispatch_body (c_parser *parser)
26398 : {
26399 155 : struct c_expr lhs, rhs, ret;
26400 155 : location_t expr_loc = c_parser_peek_token (parser)->location;
26401 155 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
26402 :
26403 155 : lhs = c_parser_conditional_expression (parser, NULL, NULL);
26404 155 : if (TREE_CODE (lhs.value) == CALL_EXPR)
26405 : return lhs.value;
26406 :
26407 56 : location_t op_location = c_parser_peek_token (parser)->location;
26408 56 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
26409 4 : return error_mark_node;
26410 :
26411 : /* Parse function name. */
26412 52 : if (!c_parser_next_token_is (parser, CPP_NAME))
26413 : {
26414 1 : c_parser_error (parser, "expected a function name");
26415 1 : return error_mark_node;
26416 : }
26417 51 : expr_loc = c_parser_peek_token (parser)->location;
26418 51 : tree id = c_parser_peek_token (parser)->value;
26419 51 : c_parser_consume_token (parser);
26420 51 : if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
26421 : {
26422 1 : c_parser_error (parser, "expected a function name");
26423 1 : return error_mark_node;
26424 : }
26425 :
26426 50 : rhs.value = build_external_ref (expr_loc, id, true, &rhs.original_type);
26427 50 : set_c_expr_source_range (&rhs, tok_range);
26428 :
26429 : /* Parse argument list. */
26430 50 : rhs = c_parser_postfix_expression_after_primary (
26431 50 : parser, EXPR_LOC_OR_LOC (rhs.value, expr_loc), rhs);
26432 50 : if (TREE_CODE (rhs.value) != CALL_EXPR)
26433 : {
26434 0 : error_at (EXPR_LOC_OR_LOC (rhs.value, expr_loc),
26435 : "expected target-function call");
26436 0 : return error_mark_node;
26437 : }
26438 :
26439 : /* Build assignment. */
26440 50 : rhs = convert_lvalue_to_rvalue (expr_loc, rhs, true, true);
26441 50 : ret.value
26442 50 : = build_modify_expr (op_location, lhs.value, lhs.original_type, NOP_EXPR,
26443 : expr_loc, rhs.value, rhs.original_type);
26444 50 : ret.m_decimal = 0;
26445 50 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
26446 50 : ret.original_code = MODIFY_EXPR;
26447 50 : ret.original_type = NULL;
26448 50 : return ret.value;
26449 : }
26450 :
26451 : /* OpenMP 5.1:
26452 : # pragma omp dispatch dispatch-clause[optseq] new-line
26453 : expression-stmt
26454 :
26455 : LOC is the location of the #pragma.
26456 : */
26457 :
26458 : #define OMP_DISPATCH_CLAUSE_MASK \
26459 : ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26460 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26461 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
26462 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
26463 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
26464 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \
26465 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
26466 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26467 :
26468 : static tree
26469 155 : c_parser_omp_dispatch (location_t loc, c_parser *parser)
26470 : {
26471 155 : tree stmt = make_node (OMP_DISPATCH);
26472 155 : SET_EXPR_LOCATION (stmt, loc);
26473 155 : TREE_TYPE (stmt) = void_type_node;
26474 :
26475 155 : OMP_DISPATCH_CLAUSES (stmt)
26476 155 : = c_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
26477 : "#pragma omp dispatch");
26478 :
26479 : // Extract depend clauses and create taskwait
26480 155 : tree depend_clauses = NULL_TREE;
26481 155 : tree *depend_clauses_ptr = &depend_clauses;
26482 342 : for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
26483 : {
26484 187 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
26485 : {
26486 5 : *depend_clauses_ptr = c;
26487 5 : depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
26488 : }
26489 : }
26490 155 : if (depend_clauses != NULL_TREE)
26491 : {
26492 5 : tree stmt = make_node (OMP_TASK);
26493 5 : TREE_TYPE (stmt) = void_node;
26494 5 : OMP_TASK_CLAUSES (stmt) = depend_clauses;
26495 5 : OMP_TASK_BODY (stmt) = NULL_TREE;
26496 5 : SET_EXPR_LOCATION (stmt, loc);
26497 5 : add_stmt (stmt);
26498 : }
26499 :
26500 : // Parse body as expression statement
26501 155 : loc = c_parser_peek_token (parser)->location;
26502 155 : tree dispatch_body = c_parser_omp_dispatch_body (parser);
26503 155 : if (dispatch_body == error_mark_node)
26504 : {
26505 6 : inform (loc, "%<#pragma omp dispatch%> must be followed by a function "
26506 : "call with optional assignment");
26507 6 : c_parser_skip_to_end_of_block_or_statement (parser);
26508 6 : return NULL_TREE;
26509 : }
26510 :
26511 : // Walk the tree to find the dispatch function call and wrap it into an IFN
26512 149 : gcc_assert (TREE_CODE (dispatch_body) == CALL_EXPR
26513 : || TREE_CODE (dispatch_body) == MODIFY_EXPR);
26514 149 : tree *dispatch_call = TREE_CODE (dispatch_body) == MODIFY_EXPR
26515 149 : ? &TREE_OPERAND (dispatch_body, 1)
26516 : : &dispatch_body;
26517 154 : while (TREE_CODE (*dispatch_call) == FLOAT_EXPR
26518 : || TREE_CODE (*dispatch_call) == CONVERT_EXPR
26519 154 : || TREE_CODE (*dispatch_call) == NOP_EXPR)
26520 5 : dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
26521 149 : *dispatch_call = build_call_expr_internal_loc (
26522 : loc, IFN_GOMP_DISPATCH,
26523 149 : TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*dispatch_call))), 1, *dispatch_call);
26524 :
26525 149 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
26526 149 : OMP_DISPATCH_BODY (stmt) = dispatch_body;
26527 :
26528 149 : return add_stmt (stmt);
26529 : }
26530 :
26531 : /* OpenMP 3.0:
26532 : # pragma omp task task-clause[optseq] new-line
26533 :
26534 : LOC is the location of the #pragma.
26535 : */
26536 :
26537 : #define OMP_TASK_CLAUSE_MASK \
26538 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26539 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
26540 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
26541 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26542 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26543 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26544 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
26545 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
26546 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26547 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
26548 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26549 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
26550 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
26551 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
26552 :
26553 : static tree
26554 898 : c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
26555 : {
26556 898 : tree clauses, block;
26557 :
26558 898 : clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
26559 : "#pragma omp task");
26560 :
26561 898 : block = c_begin_omp_task ();
26562 898 : parser->omp_attrs_forbidden_p = true;
26563 898 : c_parser_statement (parser, if_p);
26564 898 : return c_finish_omp_task (loc, clauses, block);
26565 : }
26566 :
26567 : /* OpenMP 3.0:
26568 : # pragma omp taskwait new-line
26569 :
26570 : OpenMP 5.0:
26571 : # pragma omp taskwait taskwait-clause[optseq] new-line
26572 : */
26573 :
26574 : #define OMP_TASKWAIT_CLAUSE_MASK \
26575 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26576 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26577 :
26578 : static void
26579 93 : c_parser_omp_taskwait (c_parser *parser)
26580 : {
26581 93 : location_t loc = c_parser_peek_token (parser)->location;
26582 93 : c_parser_consume_pragma (parser);
26583 :
26584 93 : tree clauses
26585 93 : = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
26586 : "#pragma omp taskwait");
26587 :
26588 93 : if (clauses)
26589 : {
26590 21 : tree stmt = make_node (OMP_TASK);
26591 21 : TREE_TYPE (stmt) = void_node;
26592 21 : OMP_TASK_CLAUSES (stmt) = clauses;
26593 21 : OMP_TASK_BODY (stmt) = NULL_TREE;
26594 21 : SET_EXPR_LOCATION (stmt, loc);
26595 21 : add_stmt (stmt);
26596 : }
26597 : else
26598 72 : c_finish_omp_taskwait (loc);
26599 93 : }
26600 :
26601 : /* OpenMP 3.1:
26602 : # pragma omp taskyield new-line
26603 : */
26604 :
26605 : static void
26606 6 : c_parser_omp_taskyield (c_parser *parser)
26607 : {
26608 6 : location_t loc = c_parser_peek_token (parser)->location;
26609 6 : c_parser_consume_pragma (parser);
26610 6 : c_parser_skip_to_pragma_eol (parser);
26611 :
26612 6 : c_finish_omp_taskyield (loc);
26613 6 : }
26614 :
26615 : /* OpenMP 4.0:
26616 : # pragma omp taskgroup new-line
26617 :
26618 : OpenMP 5.0:
26619 : # pragma omp taskgroup taskgroup-clause[optseq] new-line
26620 : */
26621 :
26622 : #define OMP_TASKGROUP_CLAUSE_MASK \
26623 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26624 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
26625 :
26626 : static tree
26627 138 : c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
26628 : {
26629 138 : tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
26630 : "#pragma omp taskgroup");
26631 :
26632 138 : tree body = c_parser_omp_structured_block (parser, if_p);
26633 138 : return c_finish_omp_taskgroup (loc, body, clauses);
26634 : }
26635 :
26636 : /* OpenMP 4.0:
26637 : # pragma omp cancel cancel-clause[optseq] new-line
26638 :
26639 : LOC is the location of the #pragma.
26640 : */
26641 :
26642 : #define OMP_CANCEL_CLAUSE_MASK \
26643 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
26644 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
26645 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
26646 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
26647 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
26648 :
26649 : static void
26650 213 : c_parser_omp_cancel (c_parser *parser)
26651 : {
26652 213 : location_t loc = c_parser_peek_token (parser)->location;
26653 :
26654 213 : c_parser_consume_pragma (parser);
26655 213 : tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
26656 : "#pragma omp cancel");
26657 :
26658 213 : c_finish_omp_cancel (loc, clauses);
26659 213 : }
26660 :
26661 : /* OpenMP 4.0:
26662 : # pragma omp cancellation point cancelpt-clause[optseq] new-line
26663 :
26664 : LOC is the location of the #pragma.
26665 : */
26666 :
26667 : #define OMP_CANCELLATION_POINT_CLAUSE_MASK \
26668 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
26669 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
26670 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
26671 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
26672 :
26673 : static bool
26674 179 : c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
26675 : {
26676 179 : location_t loc = c_parser_peek_token (parser)->location;
26677 179 : tree clauses;
26678 179 : bool point_seen = false;
26679 :
26680 179 : c_parser_consume_pragma (parser);
26681 179 : if (c_parser_next_token_is (parser, CPP_NAME))
26682 : {
26683 179 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26684 179 : if (strcmp (p, "point") == 0)
26685 : {
26686 177 : c_parser_consume_token (parser);
26687 177 : point_seen = true;
26688 : }
26689 : }
26690 177 : if (!point_seen)
26691 : {
26692 2 : c_parser_error (parser, "expected %<point%>");
26693 2 : c_parser_skip_to_pragma_eol (parser);
26694 2 : return false;
26695 : }
26696 :
26697 177 : if (context != pragma_compound)
26698 : {
26699 10 : if (context == pragma_stmt)
26700 9 : error_at (loc,
26701 : "%<#pragma %s%> may only be used in compound statements",
26702 : "omp cancellation point");
26703 : else
26704 1 : c_parser_error (parser, "expected declaration specifiers");
26705 10 : c_parser_skip_to_pragma_eol (parser, false);
26706 10 : return true;
26707 : }
26708 :
26709 167 : clauses
26710 167 : = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
26711 : "#pragma omp cancellation point");
26712 :
26713 167 : c_finish_omp_cancellation_point (loc, clauses);
26714 167 : return true;
26715 : }
26716 :
26717 : /* OpenMP 4.0:
26718 : #pragma omp distribute distribute-clause[optseq] new-line
26719 : for-loop */
26720 :
26721 : #define OMP_DISTRIBUTE_CLAUSE_MASK \
26722 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26723 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26724 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26725 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
26726 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26727 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
26728 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
26729 :
26730 : static tree
26731 3427 : c_parser_omp_distribute (location_t loc, c_parser *parser,
26732 : char *p_name, omp_clause_mask mask, tree *cclauses,
26733 : bool *if_p)
26734 : {
26735 3427 : tree clauses, block, ret;
26736 :
26737 3427 : strcat (p_name, " distribute");
26738 3427 : mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
26739 :
26740 3427 : if (c_parser_next_token_is (parser, CPP_NAME))
26741 : {
26742 3331 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26743 3331 : bool simd = false;
26744 3331 : bool parallel = false;
26745 :
26746 3331 : if (strcmp (p, "simd") == 0)
26747 : simd = true;
26748 : else
26749 2991 : parallel = strcmp (p, "parallel") == 0;
26750 2991 : if (parallel || simd)
26751 : {
26752 3064 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26753 3064 : if (cclauses == NULL)
26754 1147 : cclauses = cclauses_buf;
26755 3064 : c_parser_consume_token (parser);
26756 3064 : if (!flag_openmp) /* flag_openmp_simd */
26757 : {
26758 15 : if (simd)
26759 6 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26760 6 : if_p);
26761 : else
26762 9 : return c_parser_omp_parallel (loc, parser, p_name, mask,
26763 9 : cclauses, if_p);
26764 : }
26765 3049 : block = c_begin_compound_stmt (true);
26766 3049 : if (simd)
26767 334 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26768 : if_p);
26769 : else
26770 2715 : ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
26771 : if_p);
26772 3049 : block = c_end_compound_stmt (loc, block, true);
26773 3049 : if (ret == NULL)
26774 : return ret;
26775 3044 : ret = make_node (OMP_DISTRIBUTE);
26776 3044 : TREE_TYPE (ret) = void_type_node;
26777 3044 : OMP_FOR_BODY (ret) = block;
26778 3044 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26779 3044 : SET_EXPR_LOCATION (ret, loc);
26780 3044 : add_stmt (ret);
26781 3044 : return ret;
26782 : }
26783 : }
26784 363 : if (!flag_openmp) /* flag_openmp_simd */
26785 : {
26786 2 : c_parser_skip_to_pragma_eol (parser, false);
26787 2 : return NULL_TREE;
26788 : }
26789 :
26790 361 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26791 361 : if (cclauses)
26792 : {
26793 194 : omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
26794 194 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26795 : }
26796 :
26797 361 : block = c_begin_compound_stmt (true);
26798 361 : ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
26799 : if_p);
26800 361 : block = c_end_compound_stmt (loc, block, true);
26801 361 : add_stmt (block);
26802 :
26803 361 : return ret;
26804 : }
26805 :
26806 : /* OpenMP 4.0:
26807 : # pragma omp teams teams-clause[optseq] new-line
26808 : structured-block */
26809 :
26810 : #define OMP_TEAMS_CLAUSE_MASK \
26811 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26812 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26813 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26814 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26815 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
26816 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26817 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26818 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
26819 :
26820 : static tree
26821 3670 : c_parser_omp_teams (location_t loc, c_parser *parser,
26822 : char *p_name, omp_clause_mask mask, tree *cclauses,
26823 : bool *if_p)
26824 : {
26825 3670 : tree clauses, block, ret;
26826 :
26827 3670 : strcat (p_name, " teams");
26828 3670 : mask |= OMP_TEAMS_CLAUSE_MASK;
26829 :
26830 3670 : if (c_parser_next_token_is (parser, CPP_NAME))
26831 : {
26832 2341 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26833 2341 : if (strcmp (p, "distribute") == 0)
26834 : {
26835 2113 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26836 2113 : if (cclauses == NULL)
26837 1271 : cclauses = cclauses_buf;
26838 :
26839 2113 : c_parser_consume_token (parser);
26840 2113 : if (!flag_openmp) /* flag_openmp_simd */
26841 12 : return c_parser_omp_distribute (loc, parser, p_name, mask,
26842 12 : cclauses, if_p);
26843 2101 : block = c_begin_omp_parallel ();
26844 2101 : ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
26845 : if_p);
26846 2101 : block = c_end_compound_stmt (loc, block, true);
26847 2101 : if (ret == NULL)
26848 : return ret;
26849 2101 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26850 2101 : ret = make_node (OMP_TEAMS);
26851 2101 : TREE_TYPE (ret) = void_type_node;
26852 2101 : OMP_TEAMS_CLAUSES (ret) = clauses;
26853 2101 : OMP_TEAMS_BODY (ret) = block;
26854 2101 : OMP_TEAMS_COMBINED (ret) = 1;
26855 2101 : SET_EXPR_LOCATION (ret, loc);
26856 2101 : return add_stmt (ret);
26857 : }
26858 228 : else if (strcmp (p, "loop") == 0)
26859 : {
26860 34 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26861 34 : if (cclauses == NULL)
26862 16 : cclauses = cclauses_buf;
26863 :
26864 34 : c_parser_consume_token (parser);
26865 34 : if (!flag_openmp) /* flag_openmp_simd */
26866 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26867 2 : if_p);
26868 32 : block = c_begin_omp_parallel ();
26869 32 : ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
26870 32 : block = c_end_compound_stmt (loc, block, true);
26871 32 : if (ret == NULL)
26872 : return ret;
26873 32 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26874 32 : ret = make_node (OMP_TEAMS);
26875 32 : TREE_TYPE (ret) = void_type_node;
26876 32 : OMP_TEAMS_CLAUSES (ret) = clauses;
26877 32 : OMP_TEAMS_BODY (ret) = block;
26878 32 : OMP_TEAMS_COMBINED (ret) = 1;
26879 32 : SET_EXPR_LOCATION (ret, loc);
26880 32 : return add_stmt (ret);
26881 : }
26882 : }
26883 1523 : if (!flag_openmp) /* flag_openmp_simd */
26884 : {
26885 2 : c_parser_skip_to_pragma_eol (parser, false);
26886 2 : return NULL_TREE;
26887 : }
26888 :
26889 1521 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26890 1521 : if (cclauses)
26891 : {
26892 883 : omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
26893 883 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26894 : }
26895 :
26896 1521 : tree stmt = make_node (OMP_TEAMS);
26897 1521 : TREE_TYPE (stmt) = void_type_node;
26898 1521 : OMP_TEAMS_CLAUSES (stmt) = clauses;
26899 1521 : block = c_begin_omp_parallel ();
26900 1521 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26901 1521 : OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26902 1521 : SET_EXPR_LOCATION (stmt, loc);
26903 :
26904 1521 : return add_stmt (stmt);
26905 : }
26906 :
26907 : /* OpenMP 4.0:
26908 : # pragma omp target data target-data-clause[optseq] new-line
26909 : structured-block */
26910 :
26911 : #define OMP_TARGET_DATA_CLAUSE_MASK \
26912 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26913 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26914 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26915 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
26916 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
26917 :
26918 : static tree
26919 155 : c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
26920 : {
26921 155 : if (flag_openmp)
26922 155 : omp_requires_mask
26923 155 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26924 :
26925 155 : tree clauses
26926 155 : = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
26927 155 : "#pragma omp target data");
26928 155 : c_omp_adjust_map_clauses (clauses, false);
26929 155 : int map_seen = 0;
26930 455 : for (tree *pc = &clauses; *pc;)
26931 : {
26932 300 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26933 218 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26934 : {
26935 : case GOMP_MAP_TO:
26936 : case GOMP_MAP_ALWAYS_TO:
26937 : case GOMP_MAP_PRESENT_TO:
26938 : case GOMP_MAP_ALWAYS_PRESENT_TO:
26939 : case GOMP_MAP_FROM:
26940 : case GOMP_MAP_ALWAYS_FROM:
26941 : case GOMP_MAP_PRESENT_FROM:
26942 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26943 : case GOMP_MAP_TOFROM:
26944 : case GOMP_MAP_ALWAYS_TOFROM:
26945 : case GOMP_MAP_PRESENT_TOFROM:
26946 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26947 : case GOMP_MAP_ALLOC:
26948 : case GOMP_MAP_PRESENT_ALLOC:
26949 300 : map_seen = 3;
26950 : break;
26951 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26952 : case GOMP_MAP_ALWAYS_POINTER:
26953 : case GOMP_MAP_ATTACH_DETACH:
26954 : case GOMP_MAP_ATTACH:
26955 : break;
26956 0 : default:
26957 0 : map_seen |= 1;
26958 0 : error_at (OMP_CLAUSE_LOCATION (*pc),
26959 : "%<#pragma omp target data%> with map-type other "
26960 : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26961 : "on %<map%> clause");
26962 0 : *pc = OMP_CLAUSE_CHAIN (*pc);
26963 0 : continue;
26964 : }
26965 82 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
26966 82 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
26967 : map_seen = 3;
26968 300 : pc = &OMP_CLAUSE_CHAIN (*pc);
26969 : }
26970 :
26971 155 : if (map_seen != 3)
26972 : {
26973 3 : if (map_seen == 0)
26974 3 : error_at (loc,
26975 : "%<#pragma omp target data%> must contain at least "
26976 : "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
26977 : "clause");
26978 3 : return NULL_TREE;
26979 : }
26980 :
26981 152 : tree stmt = make_node (OMP_TARGET_DATA);
26982 152 : TREE_TYPE (stmt) = void_type_node;
26983 152 : OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
26984 152 : keep_next_level ();
26985 152 : tree block = c_begin_compound_stmt (true);
26986 152 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26987 152 : OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26988 :
26989 152 : SET_EXPR_LOCATION (stmt, loc);
26990 152 : return add_stmt (stmt);
26991 : }
26992 :
26993 : /* OpenMP 4.0:
26994 : # pragma omp target update target-update-clause[optseq] new-line */
26995 :
26996 : #define OMP_TARGET_UPDATE_CLAUSE_MASK \
26997 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
26998 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
26999 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27000 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27001 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27002 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27003 :
27004 : static bool
27005 2837 : c_parser_omp_target_update (location_t loc, c_parser *parser,
27006 : enum pragma_context context)
27007 : {
27008 2837 : if (context == pragma_stmt)
27009 : {
27010 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27011 : "omp target update");
27012 8 : c_parser_skip_to_pragma_eol (parser, false);
27013 8 : return true;
27014 : }
27015 :
27016 2829 : tree clauses
27017 2829 : = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
27018 : "#pragma omp target update");
27019 2829 : if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
27020 2829 : && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
27021 : {
27022 5 : error_at (loc,
27023 : "%<#pragma omp target update%> must contain at least one "
27024 : "%<from%> or %<to%> clauses");
27025 5 : return false;
27026 : }
27027 :
27028 2824 : if (flag_openmp)
27029 2824 : omp_requires_mask
27030 2824 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27031 :
27032 2824 : tree stmt = make_node (OMP_TARGET_UPDATE);
27033 2824 : TREE_TYPE (stmt) = void_type_node;
27034 2824 : OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
27035 2824 : SET_EXPR_LOCATION (stmt, loc);
27036 2824 : add_stmt (stmt);
27037 2824 : return false;
27038 : }
27039 :
27040 : /* OpenMP 4.5:
27041 : # pragma omp target enter data target-data-clause[optseq] new-line */
27042 :
27043 : #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
27044 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27045 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27046 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27047 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27048 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27049 :
27050 : static bool
27051 116 : c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
27052 : enum pragma_context context)
27053 : {
27054 116 : bool data_seen = false;
27055 116 : if (c_parser_next_token_is (parser, CPP_NAME))
27056 : {
27057 116 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27058 116 : if (strcmp (p, "data") == 0)
27059 : {
27060 116 : c_parser_consume_token (parser);
27061 116 : data_seen = true;
27062 : }
27063 : }
27064 116 : if (!data_seen)
27065 : {
27066 0 : c_parser_error (parser, "expected %<data%>");
27067 0 : c_parser_skip_to_pragma_eol (parser);
27068 0 : return false;
27069 : }
27070 :
27071 116 : if (context == pragma_stmt)
27072 : {
27073 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27074 : "omp target enter data");
27075 8 : c_parser_skip_to_pragma_eol (parser, false);
27076 8 : return true;
27077 : }
27078 :
27079 108 : if (flag_openmp)
27080 108 : omp_requires_mask
27081 108 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27082 :
27083 108 : tree clauses
27084 108 : = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
27085 108 : "#pragma omp target enter data");
27086 108 : c_omp_adjust_map_clauses (clauses, false);
27087 108 : int map_seen = 0;
27088 388 : for (tree *pc = &clauses; *pc;)
27089 : {
27090 280 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27091 237 : switch (OMP_CLAUSE_MAP_KIND (*pc))
27092 : {
27093 : case GOMP_MAP_TO:
27094 : case GOMP_MAP_ALWAYS_TO:
27095 : case GOMP_MAP_PRESENT_TO:
27096 : case GOMP_MAP_ALWAYS_PRESENT_TO:
27097 : case GOMP_MAP_ALLOC:
27098 : case GOMP_MAP_PRESENT_ALLOC:
27099 184 : map_seen = 3;
27100 : break;
27101 34 : case GOMP_MAP_TOFROM:
27102 34 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
27103 34 : map_seen = 3;
27104 34 : break;
27105 3 : case GOMP_MAP_ALWAYS_TOFROM:
27106 3 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
27107 3 : map_seen = 3;
27108 3 : break;
27109 2 : case GOMP_MAP_PRESENT_TOFROM:
27110 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
27111 2 : map_seen = 3;
27112 2 : break;
27113 2 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27114 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
27115 2 : map_seen = 3;
27116 2 : break;
27117 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
27118 : case GOMP_MAP_ALWAYS_POINTER:
27119 : case GOMP_MAP_ATTACH_DETACH:
27120 : case GOMP_MAP_ATTACH:
27121 : break;
27122 2 : default:
27123 2 : map_seen |= 1;
27124 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
27125 : "%<#pragma omp target enter data%> with map-type other "
27126 : "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
27127 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
27128 2 : continue;
27129 : }
27130 278 : pc = &OMP_CLAUSE_CHAIN (*pc);
27131 : }
27132 :
27133 108 : if (map_seen != 3)
27134 : {
27135 4 : if (map_seen == 0)
27136 2 : error_at (loc,
27137 : "%<#pragma omp target enter data%> must contain at least "
27138 : "one %<map%> clause");
27139 4 : return true;
27140 : }
27141 :
27142 104 : tree stmt = make_node (OMP_TARGET_ENTER_DATA);
27143 104 : TREE_TYPE (stmt) = void_type_node;
27144 104 : OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
27145 104 : SET_EXPR_LOCATION (stmt, loc);
27146 104 : add_stmt (stmt);
27147 104 : return true;
27148 : }
27149 :
27150 : /* OpenMP 4.5:
27151 : # pragma omp target exit data target-data-clause[optseq] new-line */
27152 :
27153 : #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
27154 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27155 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27156 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27157 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27158 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
27159 :
27160 : static bool
27161 107 : c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
27162 : enum pragma_context context)
27163 : {
27164 107 : bool data_seen = false;
27165 107 : if (c_parser_next_token_is (parser, CPP_NAME))
27166 : {
27167 107 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27168 107 : if (strcmp (p, "data") == 0)
27169 : {
27170 107 : c_parser_consume_token (parser);
27171 107 : data_seen = true;
27172 : }
27173 : }
27174 107 : if (!data_seen)
27175 : {
27176 0 : c_parser_error (parser, "expected %<data%>");
27177 0 : c_parser_skip_to_pragma_eol (parser);
27178 0 : return false;
27179 : }
27180 :
27181 107 : if (context == pragma_stmt)
27182 : {
27183 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
27184 : "omp target exit data");
27185 8 : c_parser_skip_to_pragma_eol (parser, false);
27186 8 : return true;
27187 : }
27188 :
27189 99 : if (flag_openmp)
27190 99 : omp_requires_mask
27191 99 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27192 :
27193 99 : tree clauses
27194 99 : = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
27195 : "#pragma omp target exit data", false);
27196 99 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
27197 99 : c_omp_adjust_map_clauses (clauses, false);
27198 99 : int map_seen = 0;
27199 349 : for (tree *pc = &clauses; *pc;)
27200 : {
27201 250 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27202 207 : switch (OMP_CLAUSE_MAP_KIND (*pc))
27203 : {
27204 : case GOMP_MAP_FROM:
27205 : case GOMP_MAP_ALWAYS_FROM:
27206 : case GOMP_MAP_PRESENT_FROM:
27207 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
27208 : case GOMP_MAP_RELEASE:
27209 : case GOMP_MAP_DELETE:
27210 158 : map_seen = 3;
27211 : break;
27212 30 : case GOMP_MAP_TOFROM:
27213 30 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
27214 30 : map_seen = 3;
27215 30 : break;
27216 1 : case GOMP_MAP_ALWAYS_TOFROM:
27217 1 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
27218 1 : map_seen = 3;
27219 1 : break;
27220 0 : case GOMP_MAP_PRESENT_TOFROM:
27221 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
27222 0 : map_seen = 3;
27223 0 : break;
27224 0 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27225 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
27226 0 : map_seen = 3;
27227 0 : break;
27228 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
27229 : case GOMP_MAP_ALWAYS_POINTER:
27230 : case GOMP_MAP_ATTACH_DETACH:
27231 : case GOMP_MAP_DETACH:
27232 : break;
27233 2 : default:
27234 2 : map_seen |= 1;
27235 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
27236 : "%<#pragma omp target exit data%> with map-type other "
27237 : "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
27238 : "on %<map%> clause");
27239 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
27240 2 : continue;
27241 : }
27242 248 : pc = &OMP_CLAUSE_CHAIN (*pc);
27243 : }
27244 :
27245 99 : if (map_seen != 3)
27246 : {
27247 2 : if (map_seen == 0)
27248 0 : error_at (loc,
27249 : "%<#pragma omp target exit data%> must contain at least one "
27250 : "%<map%> clause");
27251 2 : return true;
27252 : }
27253 :
27254 97 : tree stmt = make_node (OMP_TARGET_EXIT_DATA);
27255 97 : TREE_TYPE (stmt) = void_type_node;
27256 97 : OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
27257 97 : SET_EXPR_LOCATION (stmt, loc);
27258 97 : add_stmt (stmt);
27259 97 : return true;
27260 : }
27261 :
27262 : /* OpenMP 4.0:
27263 : # pragma omp target target-clause[optseq] new-line
27264 : structured-block */
27265 :
27266 : #define OMP_TARGET_CLAUSE_MASK \
27267 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
27268 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
27269 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
27270 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
27271 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27272 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
27273 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
27274 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
27275 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
27276 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
27277 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
27278 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
27279 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
27280 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
27281 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
27282 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USES_ALLOCATORS))
27283 :
27284 : static bool
27285 7549 : c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
27286 : {
27287 7549 : location_t loc = c_parser_peek_token (parser)->location;
27288 7549 : c_parser_consume_pragma (parser);
27289 7549 : tree *pc = NULL, stmt, block, body, clauses;
27290 :
27291 7549 : if (context != pragma_stmt && context != pragma_compound)
27292 : {
27293 2 : c_parser_error (parser, "expected declaration specifiers");
27294 2 : c_parser_skip_to_pragma_eol (parser);
27295 2 : return false;
27296 : }
27297 :
27298 7547 : if (flag_openmp)
27299 7533 : omp_requires_mask
27300 7533 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27301 :
27302 7547 : if (c_parser_next_token_is (parser, CPP_NAME))
27303 : {
27304 6616 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27305 6616 : enum tree_code ccode = ERROR_MARK;
27306 :
27307 6616 : if (strcmp (p, "teams") == 0)
27308 : ccode = OMP_TEAMS;
27309 4872 : else if (strcmp (p, "parallel") == 0)
27310 : ccode = OMP_PARALLEL;
27311 4382 : else if (strcmp (p, "simd") == 0)
27312 : ccode = OMP_SIMD;
27313 4322 : if (ccode != ERROR_MARK)
27314 : {
27315 2294 : tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
27316 2294 : char p_name[sizeof ("#pragma omp target teams distribute "
27317 : "parallel for simd")];
27318 :
27319 2294 : c_parser_consume_token (parser);
27320 2294 : strcpy (p_name, "#pragma omp target");
27321 2294 : if (!flag_openmp) /* flag_openmp_simd */
27322 : {
27323 13 : tree stmt;
27324 13 : switch (ccode)
27325 : {
27326 8 : case OMP_TEAMS:
27327 8 : stmt = c_parser_omp_teams (loc, parser, p_name,
27328 8 : OMP_TARGET_CLAUSE_MASK,
27329 : cclauses, if_p);
27330 8 : break;
27331 4 : case OMP_PARALLEL:
27332 4 : stmt = c_parser_omp_parallel (loc, parser, p_name,
27333 4 : OMP_TARGET_CLAUSE_MASK,
27334 : cclauses, if_p);
27335 4 : break;
27336 1 : case OMP_SIMD:
27337 1 : stmt = c_parser_omp_simd (loc, parser, p_name,
27338 1 : OMP_TARGET_CLAUSE_MASK,
27339 : cclauses, if_p);
27340 1 : break;
27341 0 : default:
27342 0 : gcc_unreachable ();
27343 : }
27344 21 : return stmt != NULL_TREE;
27345 : }
27346 2281 : keep_next_level ();
27347 2281 : tree block = c_begin_compound_stmt (true), ret;
27348 2281 : switch (ccode)
27349 : {
27350 1736 : case OMP_TEAMS:
27351 1736 : ret = c_parser_omp_teams (loc, parser, p_name,
27352 1736 : OMP_TARGET_CLAUSE_MASK, cclauses,
27353 : if_p);
27354 1736 : break;
27355 486 : case OMP_PARALLEL:
27356 486 : ret = c_parser_omp_parallel (loc, parser, p_name,
27357 486 : OMP_TARGET_CLAUSE_MASK, cclauses,
27358 : if_p);
27359 486 : break;
27360 59 : case OMP_SIMD:
27361 59 : ret = c_parser_omp_simd (loc, parser, p_name,
27362 59 : OMP_TARGET_CLAUSE_MASK, cclauses,
27363 : if_p);
27364 59 : break;
27365 0 : default:
27366 0 : gcc_unreachable ();
27367 : }
27368 2281 : block = c_end_compound_stmt (loc, block, true);
27369 2281 : if (ret == NULL_TREE)
27370 : return false;
27371 2273 : if (ccode == OMP_TEAMS)
27372 : /* For combined target teams, ensure the num_teams and
27373 : thread_limit clause expressions are evaluated on the host,
27374 : before entering the target construct. */
27375 2217 : for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
27376 2217 : c; c = OMP_CLAUSE_CHAIN (c))
27377 481 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
27378 481 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
27379 202 : for (int i = 0;
27380 332 : i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
27381 202 : if (OMP_CLAUSE_OPERAND (c, i)
27382 202 : && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
27383 : {
27384 129 : tree expr = OMP_CLAUSE_OPERAND (c, i);
27385 129 : tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
27386 129 : expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
27387 : expr, NULL_TREE, NULL_TREE);
27388 129 : add_stmt (expr);
27389 129 : OMP_CLAUSE_OPERAND (c, i) = expr;
27390 129 : tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
27391 : OMP_CLAUSE_FIRSTPRIVATE);
27392 129 : OMP_CLAUSE_DECL (tc) = tmp;
27393 129 : OMP_CLAUSE_CHAIN (tc)
27394 129 : = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
27395 129 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
27396 : }
27397 2273 : tree stmt = make_node (OMP_TARGET);
27398 2273 : TREE_TYPE (stmt) = void_type_node;
27399 2273 : OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
27400 2273 : c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
27401 2273 : OMP_TARGET_BODY (stmt) = block;
27402 2273 : OMP_TARGET_COMBINED (stmt) = 1;
27403 2273 : SET_EXPR_LOCATION (stmt, loc);
27404 2273 : add_stmt (stmt);
27405 2273 : pc = &OMP_TARGET_CLAUSES (stmt);
27406 2273 : goto check_clauses;
27407 : }
27408 4322 : else if (!flag_openmp) /* flag_openmp_simd */
27409 : {
27410 0 : c_parser_skip_to_pragma_eol (parser, false);
27411 0 : return false;
27412 : }
27413 4322 : else if (strcmp (p, "data") == 0)
27414 : {
27415 155 : c_parser_consume_token (parser);
27416 155 : c_parser_omp_target_data (loc, parser, if_p);
27417 155 : return true;
27418 : }
27419 4167 : else if (strcmp (p, "enter") == 0)
27420 : {
27421 116 : c_parser_consume_token (parser);
27422 116 : return c_parser_omp_target_enter_data (loc, parser, context);
27423 : }
27424 4051 : else if (strcmp (p, "exit") == 0)
27425 : {
27426 107 : c_parser_consume_token (parser);
27427 107 : return c_parser_omp_target_exit_data (loc, parser, context);
27428 : }
27429 3944 : else if (strcmp (p, "update") == 0)
27430 : {
27431 2837 : c_parser_consume_token (parser);
27432 2837 : return c_parser_omp_target_update (loc, parser, context);
27433 : }
27434 : }
27435 2038 : if (!flag_openmp) /* flag_openmp_simd */
27436 : {
27437 1 : c_parser_skip_to_pragma_eol (parser, false);
27438 1 : return false;
27439 : }
27440 :
27441 2037 : stmt = make_node (OMP_TARGET);
27442 2037 : TREE_TYPE (stmt) = void_type_node;
27443 :
27444 2037 : clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
27445 : "#pragma omp target", false);
27446 4010 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27447 1973 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
27448 : {
27449 50 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
27450 50 : OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
27451 50 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
27452 50 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
27453 50 : OMP_CLAUSE_CHAIN (c) = nc;
27454 : }
27455 2037 : clauses = c_omp_instantiate_mappers (clauses);
27456 2037 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
27457 2037 : c_omp_adjust_map_clauses (clauses, true);
27458 :
27459 2037 : keep_next_level ();
27460 2037 : block = c_begin_compound_stmt (true);
27461 2037 : body = c_parser_omp_structured_block (parser, if_p);
27462 :
27463 2037 : c_omp_scan_mapper_bindings (loc, &clauses, body);
27464 :
27465 2037 : add_stmt (body);
27466 2037 : OMP_TARGET_CLAUSES (stmt) = clauses;
27467 2037 : pc = &OMP_TARGET_CLAUSES (stmt);
27468 2037 : OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
27469 :
27470 2037 : SET_EXPR_LOCATION (stmt, loc);
27471 2037 : add_stmt (stmt);
27472 :
27473 : check_clauses:
27474 8061 : while (*pc)
27475 : {
27476 3751 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
27477 2085 : switch (OMP_CLAUSE_MAP_KIND (*pc))
27478 : {
27479 : case GOMP_MAP_TO:
27480 : case GOMP_MAP_ALWAYS_TO:
27481 : case GOMP_MAP_PRESENT_TO:
27482 : case GOMP_MAP_ALWAYS_PRESENT_TO:
27483 : case GOMP_MAP_FROM:
27484 : case GOMP_MAP_ALWAYS_FROM:
27485 : case GOMP_MAP_PRESENT_FROM:
27486 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
27487 : case GOMP_MAP_TOFROM:
27488 : case GOMP_MAP_ALWAYS_TOFROM:
27489 : case GOMP_MAP_PRESENT_TOFROM:
27490 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
27491 : case GOMP_MAP_ALLOC:
27492 : case GOMP_MAP_PRESENT_ALLOC:
27493 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
27494 : case GOMP_MAP_ALWAYS_POINTER:
27495 : case GOMP_MAP_POINTER:
27496 : case GOMP_MAP_ATTACH_DETACH:
27497 : case GOMP_MAP_ATTACH:
27498 : break;
27499 1 : default:
27500 1 : error_at (OMP_CLAUSE_LOCATION (*pc),
27501 : "%<#pragma omp target%> with map-type other "
27502 : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
27503 : "on %<map%> clause");
27504 1 : *pc = OMP_CLAUSE_CHAIN (*pc);
27505 1 : continue;
27506 : }
27507 3750 : pc = &OMP_CLAUSE_CHAIN (*pc);
27508 : }
27509 4310 : cfun->has_omp_target = true;
27510 4310 : return true;
27511 : }
27512 :
27513 : /* OpenMP 4.0:
27514 : # pragma omp declare simd declare-simd-clauses[optseq] new-line
27515 :
27516 : OpenMP 5.0:
27517 : # pragma omp declare variant (identifier) match(context-selector) new-line
27518 :
27519 : OpenMP 5.1
27520 : # pragma omp declare variant (identifier) match(context-selector) \
27521 : adjust_args(adjust-op:argument-list) append_args(interop-list) new-line
27522 : */
27523 :
27524 : #define OMP_DECLARE_SIMD_CLAUSE_MASK \
27525 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
27526 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
27527 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
27528 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
27529 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
27530 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
27531 :
27532 : static void
27533 781 : c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
27534 : {
27535 781 : c_token *token = c_parser_peek_token (parser);
27536 781 : gcc_assert (token->type == CPP_NAME);
27537 781 : tree kind = token->value;
27538 781 : gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
27539 : || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
27540 :
27541 781 : auto_vec<c_token> clauses;
27542 12670 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
27543 : {
27544 11889 : c_token *token = c_parser_peek_token (parser);
27545 11889 : if (token->type == CPP_EOF)
27546 : {
27547 0 : c_parser_skip_to_pragma_eol (parser);
27548 0 : return;
27549 : }
27550 11889 : clauses.safe_push (*token);
27551 11889 : c_parser_consume_token (parser);
27552 : }
27553 781 : clauses.safe_push (*c_parser_peek_token (parser));
27554 781 : c_parser_skip_to_pragma_eol (parser);
27555 :
27556 1851 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
27557 : {
27558 291 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
27559 289 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
27560 580 : || c_parser_peek_2nd_token (parser)->value != kind)
27561 : {
27562 2 : error ("%<#pragma omp declare %s%> must be followed by "
27563 : "function declaration or definition or another "
27564 : "%<#pragma omp declare %s%>",
27565 2 : IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
27566 2 : return;
27567 : }
27568 289 : c_parser_consume_pragma (parser);
27569 6282 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
27570 : {
27571 5704 : c_token *token = c_parser_peek_token (parser);
27572 5704 : if (token->type == CPP_EOF)
27573 : {
27574 0 : c_parser_skip_to_pragma_eol (parser);
27575 0 : return;
27576 : }
27577 5704 : clauses.safe_push (*token);
27578 5704 : c_parser_consume_token (parser);
27579 : }
27580 289 : clauses.safe_push (*c_parser_peek_token (parser));
27581 289 : c_parser_skip_to_pragma_eol (parser);
27582 : }
27583 :
27584 : /* Make sure nothing tries to read past the end of the tokens. */
27585 779 : c_token eof_token;
27586 779 : memset (&eof_token, 0, sizeof (eof_token));
27587 779 : eof_token.type = CPP_EOF;
27588 779 : clauses.safe_push (eof_token);
27589 779 : clauses.safe_push (eof_token);
27590 :
27591 779 : switch (context)
27592 : {
27593 762 : case pragma_external:
27594 762 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27595 762 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
27596 : {
27597 1 : int ext = disable_extension_diagnostics ();
27598 1 : do
27599 1 : c_parser_consume_token (parser);
27600 1 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
27601 2 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
27602 1 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
27603 : false, NULL, &clauses);
27604 1 : restore_extension_diagnostics (ext);
27605 : }
27606 : else
27607 761 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
27608 : false, NULL, &clauses);
27609 : break;
27610 6 : case pragma_struct:
27611 6 : case pragma_param:
27612 6 : case pragma_stmt:
27613 6 : error ("%<#pragma omp declare %s%> must be followed by "
27614 : "function declaration or definition",
27615 6 : IDENTIFIER_POINTER (kind));
27616 6 : break;
27617 11 : case pragma_compound:
27618 11 : bool have_std_attrs;
27619 11 : tree std_attrs;
27620 11 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
27621 11 : if (have_std_attrs)
27622 1 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
27623 : else
27624 : std_attrs = NULL_TREE;
27625 11 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27626 11 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
27627 : {
27628 1 : int ext = disable_extension_diagnostics ();
27629 3 : do
27630 3 : c_parser_consume_token (parser);
27631 3 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
27632 4 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
27633 1 : if (c_parser_next_tokens_start_declaration (parser)
27634 1 : || c_parser_nth_token_starts_std_attributes (parser, 1))
27635 : {
27636 1 : c_parser_declaration_or_fndef (parser, true, true, true, true,
27637 : true, false, NULL, &clauses,
27638 : have_std_attrs, std_attrs);
27639 1 : restore_extension_diagnostics (ext);
27640 1 : break;
27641 : }
27642 0 : restore_extension_diagnostics (ext);
27643 : }
27644 10 : else if (c_parser_next_tokens_start_declaration (parser))
27645 : {
27646 10 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
27647 : false, NULL, &clauses, have_std_attrs,
27648 : std_attrs);
27649 10 : break;
27650 : }
27651 0 : error ("%<#pragma omp declare %s%> must be followed by "
27652 : "function declaration or definition",
27653 0 : IDENTIFIER_POINTER (kind));
27654 0 : break;
27655 0 : default:
27656 0 : gcc_unreachable ();
27657 : }
27658 781 : }
27659 :
27660 : /* OpenMP 5.0:
27661 :
27662 : trait-selector:
27663 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
27664 :
27665 : trait-score:
27666 : score(score-expression)
27667 :
27668 : Note that this function returns a list of trait selectors for the
27669 : trait-selector-set SET. */
27670 :
27671 : static tree
27672 1256 : c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
27673 : tree parms)
27674 : {
27675 1256 : tree ret = NULL_TREE;
27676 1438 : do
27677 : {
27678 1438 : tree selector;
27679 1438 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27680 2815 : || c_parser_next_token_is (parser, CPP_NAME))
27681 1436 : selector = c_parser_peek_token (parser)->value;
27682 : else
27683 : {
27684 2 : c_parser_error (parser, "expected trait selector name");
27685 2 : return error_mark_node;
27686 : }
27687 1436 : enum omp_ts_code sel
27688 1436 : = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
27689 :
27690 1436 : if (sel == OMP_TRAIT_INVALID)
27691 : {
27692 : /* Per the spec, "Implementations can ignore specified selectors
27693 : that are not those described in this section"; however, we
27694 : must record such selectors because they cause match failures. */
27695 18 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
27696 : "unknown selector %qs for context selector set %qs",
27697 18 : IDENTIFIER_POINTER (selector), omp_tss_map[set]);
27698 18 : c_parser_consume_token (parser);
27699 18 : ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
27700 18 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27701 5 : c_parser_balanced_token_sequence (parser);
27702 18 : if (c_parser_next_token_is (parser, CPP_COMMA))
27703 : {
27704 1 : c_parser_consume_token (parser);
27705 1 : continue;
27706 : }
27707 : else
27708 : break;
27709 : }
27710 :
27711 1418 : c_parser_consume_token (parser);
27712 :
27713 1418 : tree properties = NULL_TREE;
27714 1418 : tree scoreval = NULL_TREE;
27715 1418 : enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
27716 1418 : bool allow_score = omp_ts_map[sel].allow_score;
27717 1418 : tree t;
27718 :
27719 1418 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27720 : {
27721 810 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
27722 : {
27723 12 : error_at (c_parser_peek_token (parser)->location,
27724 : "selector %qs does not accept any properties",
27725 6 : IDENTIFIER_POINTER (selector));
27726 16 : return error_mark_node;
27727 : }
27728 :
27729 804 : matching_parens parens;
27730 804 : parens.require_open (parser);
27731 :
27732 804 : c_token *token = c_parser_peek_token (parser);
27733 804 : if (c_parser_next_token_is (parser, CPP_NAME)
27734 612 : && strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
27735 897 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
27736 : {
27737 93 : c_parser_consume_token (parser);
27738 :
27739 93 : matching_parens parens2;
27740 93 : parens2.require_open (parser);
27741 93 : tree score = c_parser_expr_no_commas (parser, NULL).value;
27742 93 : parens2.skip_until_found_close (parser);
27743 93 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
27744 93 : if (!allow_score)
27745 13 : error_at (token->location,
27746 : "%<score%> cannot be specified in traits "
27747 : "in the %qs trait-selector-set",
27748 : omp_tss_map[set]);
27749 80 : else if (score != error_mark_node)
27750 : {
27751 80 : mark_exp_read (score);
27752 80 : score = c_fully_fold (score, false, NULL);
27753 160 : if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
27754 159 : || TREE_CODE (score) != INTEGER_CST)
27755 1 : error_at (token->location, "%<score%> argument must "
27756 : "be constant integer expression");
27757 79 : else if (tree_int_cst_sgn (score) < 0)
27758 1 : error_at (token->location, "%<score%> argument must "
27759 : "be non-negative");
27760 : else
27761 : scoreval = score;
27762 : }
27763 93 : token = c_parser_peek_token (parser);
27764 : }
27765 :
27766 804 : switch (property_kind)
27767 : {
27768 25 : case OMP_TRAIT_PROPERTY_ID:
27769 25 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27770 50 : || c_parser_next_token_is (parser, CPP_NAME))
27771 : {
27772 24 : tree prop = c_parser_peek_token (parser)->value;
27773 24 : c_parser_consume_token (parser);
27774 24 : properties = make_trait_property (prop, NULL_TREE,
27775 : properties);
27776 : }
27777 : else
27778 : {
27779 1 : c_parser_error (parser, "expected identifier");
27780 1 : return error_mark_node;
27781 : }
27782 24 : break;
27783 688 : case OMP_TRAIT_PROPERTY_NAME_LIST:
27784 746 : do
27785 : {
27786 688 : tree prop = OMP_TP_NAMELIST_NODE;
27787 688 : tree value = NULL_TREE;
27788 688 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27789 1376 : || c_parser_next_token_is (parser, CPP_NAME))
27790 : {
27791 524 : value = c_parser_peek_token (parser)->value;
27792 524 : c_parser_consume_token (parser);
27793 : }
27794 164 : else if (c_parser_next_token_is (parser, CPP_STRING))
27795 159 : value = c_parser_string_literal (parser, false,
27796 : false).value;
27797 : else
27798 : {
27799 5 : c_parser_error (parser, "expected identifier or "
27800 : "string literal");
27801 5 : return error_mark_node;
27802 : }
27803 :
27804 683 : properties = make_trait_property (prop, value, properties);
27805 :
27806 683 : if (c_parser_next_token_is (parser, CPP_COMMA))
27807 58 : c_parser_consume_token (parser);
27808 : else
27809 : break;
27810 58 : }
27811 : while (1);
27812 : break;
27813 126 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
27814 126 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
27815 126 : {
27816 126 : c_expr texpr = c_parser_expr_no_commas (parser, NULL);
27817 126 : texpr = convert_lvalue_to_rvalue (token->location, texpr,
27818 : true, true);
27819 126 : t = texpr.value;
27820 : }
27821 126 : if (t == error_mark_node)
27822 : return error_mark_node;
27823 124 : mark_exp_read (t);
27824 124 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
27825 : {
27826 101 : t = c_objc_common_truthvalue_conversion (token->location,
27827 : t,
27828 : boolean_type_node);
27829 101 : if (t == error_mark_node)
27830 : return error_mark_node;
27831 : }
27832 23 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
27833 : {
27834 0 : error_at (token->location,
27835 : "property must be integer expression");
27836 0 : return error_mark_node;
27837 : }
27838 122 : t = c_fully_fold (t, false, NULL);
27839 122 : properties = make_trait_property (NULL_TREE, t, properties);
27840 122 : break;
27841 23 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
27842 23 : if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
27843 : {
27844 23 : if (parms == NULL_TREE)
27845 : {
27846 0 : error_at (token->location, "properties for %<simd%> "
27847 : "selector may not be specified in "
27848 : "%<metadirective%>");
27849 0 : return error_mark_node;
27850 : }
27851 23 : tree c;
27852 46 : c = c_parser_omp_all_clauses (parser,
27853 23 : OMP_DECLARE_SIMD_CLAUSE_MASK,
27854 : "simd", true, 2);
27855 46 : c = c_omp_declare_simd_clauses_to_numbers (parms
27856 23 : == error_mark_node
27857 : ? NULL_TREE : parms,
27858 : c);
27859 23 : properties = c;
27860 : }
27861 0 : else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
27862 : {
27863 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
27864 : Currently only the now-deprecated syntax
27865 : from OpenMP 5.0 is supported. */
27866 0 : sorry_at (token->location,
27867 : "%<requires%> selector is not supported yet");
27868 0 : return error_mark_node;
27869 : }
27870 : else
27871 0 : gcc_unreachable ();
27872 23 : break;
27873 0 : default:
27874 0 : gcc_unreachable ();
27875 : }
27876 :
27877 794 : parens.skip_until_found_close (parser);
27878 794 : properties = nreverse (properties);
27879 : }
27880 608 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
27881 608 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
27882 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
27883 : {
27884 8 : c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
27885 8 : return error_mark_node;
27886 : }
27887 :
27888 1394 : ret = make_trait_selector (sel, scoreval, properties, ret);
27889 :
27890 1394 : if (c_parser_next_token_is (parser, CPP_COMMA))
27891 181 : c_parser_consume_token (parser);
27892 : else
27893 : break;
27894 : }
27895 : while (1);
27896 :
27897 1230 : return nreverse (ret);
27898 : }
27899 :
27900 : /* OpenMP 5.0:
27901 :
27902 : trait-set-selector[,trait-set-selector[,...]]
27903 :
27904 : trait-set-selector:
27905 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
27906 :
27907 : trait-set-selector-name:
27908 : constructor
27909 : device
27910 : implementation
27911 : user */
27912 :
27913 : static tree
27914 912 : c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
27915 : {
27916 912 : tree ret = NULL_TREE;
27917 1620 : do
27918 : {
27919 1266 : const char *setp = "";
27920 1266 : if (c_parser_next_token_is (parser, CPP_NAME))
27921 1264 : setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27922 1266 : enum omp_tss_code set = omp_lookup_tss_code (setp);
27923 :
27924 1266 : if (set == OMP_TRAIT_SET_INVALID)
27925 : {
27926 6 : c_parser_error (parser, "expected context selector set name");
27927 10 : return error_mark_node;
27928 : }
27929 :
27930 1260 : c_parser_consume_token (parser);
27931 :
27932 1260 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
27933 1 : return error_mark_node;
27934 :
27935 1259 : matching_braces braces;
27936 1259 : if (!braces.require_open (parser))
27937 3 : return error_mark_node;
27938 :
27939 1256 : tree selectors = c_parser_omp_context_selector (parser, set, parms);
27940 1256 : if (selectors == error_mark_node)
27941 : {
27942 26 : c_parser_skip_to_closing_brace (parser);
27943 26 : ret = error_mark_node;
27944 : }
27945 1230 : else if (ret != error_mark_node)
27946 1230 : ret = make_trait_set_selector (set, selectors, ret);
27947 :
27948 1256 : braces.require_close (parser);
27949 :
27950 1256 : if (c_parser_next_token_is (parser, CPP_COMMA))
27951 354 : c_parser_consume_token (parser);
27952 : else
27953 : break;
27954 354 : }
27955 : while (1);
27956 :
27957 902 : if (ret == error_mark_node)
27958 : return ret;
27959 876 : return nreverse (ret);
27960 : }
27961 :
27962 : /* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
27963 : that into "omp declare variant base" attribute. */
27964 :
27965 : static void
27966 763 : c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
27967 : {
27968 763 : matching_parens parens;
27969 763 : if (!parens.require_open (parser))
27970 : {
27971 3 : fail:
27972 50 : c_parser_skip_to_pragma_eol (parser, false);
27973 50 : return;
27974 : }
27975 :
27976 760 : if (c_parser_next_token_is_not (parser, CPP_NAME)
27977 760 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
27978 : {
27979 3 : c_parser_error (parser, "expected identifier");
27980 3 : goto fail;
27981 : }
27982 :
27983 757 : c_token *token = c_parser_peek_token (parser);
27984 757 : tree variant = lookup_name (token->value);
27985 :
27986 757 : if (variant == NULL_TREE)
27987 : {
27988 3 : undeclared_variable (token->location, token->value);
27989 3 : variant = error_mark_node;
27990 : }
27991 754 : else if (TREE_CODE (variant) != FUNCTION_DECL)
27992 : {
27993 1 : error_at (token->location, "variant %qD is not a function",
27994 : variant);
27995 1 : variant = error_mark_node;
27996 : }
27997 753 : else if (fndecl_built_in_p (variant)
27998 753 : && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27999 : "__builtin_", strlen ("__builtin_")) == 0
28000 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
28001 : "__sync_", strlen ("__sync_")) == 0
28002 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
28003 : "__atomic_", strlen ("__atomic_")) == 0))
28004 : {
28005 1 : error_at (token->location, "variant %qD is a built-in",
28006 : variant);
28007 1 : variant = error_mark_node;
28008 : }
28009 752 : else if (variant == fndecl)
28010 : {
28011 2 : error_at (token->location, "variant %qD is the same as base function",
28012 : variant);
28013 2 : variant = error_mark_node;
28014 : }
28015 :
28016 757 : c_parser_consume_token (parser);
28017 :
28018 757 : parens.require_close (parser);
28019 :
28020 757 : tree append_args_tree = NULL_TREE;
28021 757 : tree append_args_last;
28022 757 : vec<tree> adjust_args_list = vNULL;
28023 757 : bool has_match = false, has_adjust_args = false;
28024 757 : location_t adjust_args_loc = UNKNOWN_LOCATION;
28025 757 : location_t append_args_loc = UNKNOWN_LOCATION;
28026 757 : location_t match_loc = UNKNOWN_LOCATION;
28027 757 : tree need_device_ptr_list = NULL_TREE;
28028 757 : tree ctx = error_mark_node;
28029 :
28030 856 : do
28031 : {
28032 856 : if (c_parser_next_token_is (parser, CPP_COMMA)
28033 856 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28034 9 : c_parser_consume_token (parser);
28035 :
28036 856 : const char *clause = "";
28037 856 : location_t loc = c_parser_peek_token (parser)->location;
28038 856 : if (c_parser_next_token_is (parser, CPP_NAME))
28039 855 : clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28040 :
28041 856 : enum clause
28042 : {
28043 : match,
28044 : adjust_args,
28045 : append_args
28046 : } ccode;
28047 :
28048 856 : if (strcmp (clause, "match") == 0)
28049 : {
28050 : ccode = match;
28051 : match_loc = loc;
28052 : }
28053 102 : else if (strcmp (clause, "adjust_args") == 0)
28054 : {
28055 : ccode = adjust_args;
28056 : adjust_args_loc = loc;
28057 : }
28058 50 : else if (strcmp (clause, "append_args") == 0)
28059 : {
28060 : ccode = append_args;
28061 : append_args_loc = loc;
28062 : }
28063 : else
28064 : {
28065 2 : c_parser_error (parser, "expected %<match%>, %<adjust_args%> or "
28066 : "%<append_args%> clause");
28067 2 : goto fail;
28068 : }
28069 :
28070 854 : c_parser_consume_token (parser);
28071 :
28072 854 : if (!parens.require_open (parser))
28073 1 : goto fail;
28074 :
28075 853 : if (parms == NULL_TREE)
28076 594 : parms = error_mark_node;
28077 :
28078 853 : if (ccode == match)
28079 : {
28080 753 : if (has_match)
28081 1 : error_at (match_loc, "too many %<match%> clauses");
28082 753 : has_match = true;
28083 753 : ctx = c_parser_omp_context_selector_specification (parser, parms);
28084 753 : if (ctx == error_mark_node)
28085 32 : goto fail;
28086 721 : ctx = omp_check_context_selector (match_loc, ctx,
28087 : OMP_CTX_DECLARE_VARIANT);
28088 :
28089 : /* The OpenMP spec says the merging rules for enclosing
28090 : "begin declare variant" contexts apply to "declare variant
28091 : directives" -- the term it uses to refer to both directive
28092 : forms. */
28093 721 : if (ctx != error_mark_node
28094 721 : && !vec_safe_is_empty (current_omp_declare_variant_attribute))
28095 : {
28096 2 : c_omp_declare_variant_attr a
28097 2 : = current_omp_declare_variant_attribute->last ();
28098 2 : tree outer_ctx = a.selector;
28099 2 : ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx,
28100 : OMP_CTX_DECLARE_VARIANT);
28101 : }
28102 : }
28103 100 : else if (ccode == adjust_args)
28104 : {
28105 52 : has_adjust_args = true;
28106 52 : if (c_parser_next_token_is (parser, CPP_NAME)
28107 52 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
28108 : {
28109 50 : const char *p
28110 50 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28111 50 : if (strcmp (p, "need_device_ptr") == 0
28112 15 : || strcmp (p, "nothing") == 0)
28113 : {
28114 48 : c_parser_consume_token (parser); // need_device_ptr
28115 48 : c_parser_consume_token (parser); // :
28116 :
28117 48 : loc = c_parser_peek_token (parser)->location;
28118 48 : tree list
28119 48 : = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_ERROR,
28120 : NULL_TREE);
28121 :
28122 48 : tree arg;
28123 48 : if (variant != error_mark_node)
28124 103 : for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
28125 : {
28126 61 : tree decl = TREE_PURPOSE (c);
28127 61 : location_t arg_loc = EXPR_LOCATION (TREE_VALUE (c));
28128 61 : int idx;
28129 111 : for (arg = parms, idx = 0; arg != NULL;
28130 50 : arg = TREE_CHAIN (arg), idx++)
28131 110 : if (arg == decl)
28132 : break;
28133 61 : if (arg == NULL_TREE)
28134 : {
28135 1 : error_at (arg_loc,
28136 : "%qD is not a function argument",
28137 : decl);
28138 5 : goto fail;
28139 : }
28140 60 : if (adjust_args_list.contains (arg))
28141 : {
28142 3 : error_at (arg_loc,
28143 : "%qD is specified more than once",
28144 : decl);
28145 3 : goto fail;
28146 : }
28147 57 : if (strcmp (p, "need_device_ptr") == 0
28148 57 : && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
28149 : {
28150 1 : error_at (loc, "%qD is not of pointer type", decl);
28151 1 : goto fail;
28152 : }
28153 56 : adjust_args_list.safe_push (arg);
28154 56 : if (strcmp (p, "need_device_ptr") == 0)
28155 : {
28156 46 : need_device_ptr_list = chainon (
28157 : need_device_ptr_list,
28158 : build_tree_list (
28159 : NULL_TREE,
28160 : build_int_cst (
28161 : integer_type_node,
28162 46 : idx))); // Store 0-based argument index,
28163 : // as in gimplify_call_expr
28164 : }
28165 : }
28166 43 : }
28167 : else
28168 : {
28169 2 : error_at (c_parser_peek_token (parser)->location,
28170 : "expected %<nothing%> or %<need_device_ptr%>");
28171 2 : if (strcmp (p, "need_device_addr") == 0)
28172 1 : inform (c_parser_peek_token (parser)->location,
28173 : "%<need_device_addr%> is not valid for C");
28174 2 : goto fail;
28175 : }
28176 : }
28177 : else
28178 : {
28179 2 : error_at (c_parser_peek_token (parser)->location,
28180 : "expected %<nothing%> or %<need_device_ptr%> "
28181 : "followed by %<:%>");
28182 2 : goto fail;
28183 : }
28184 : }
28185 48 : else if (ccode == append_args)
28186 : {
28187 48 : if (append_args_tree)
28188 : {
28189 1 : error_at (append_args_loc, "too many %qs clauses", "append_args");
28190 1 : append_args_tree = NULL_TREE;
28191 : }
28192 86 : do
28193 : {
28194 67 : location_t loc = c_parser_peek_token (parser)->location;
28195 67 : if (!c_parser_next_token_is (parser, CPP_NAME)
28196 67 : || strcmp ("interop",
28197 67 : IDENTIFIER_POINTER (
28198 : c_parser_peek_token (parser)->value)))
28199 : {
28200 0 : error_at (loc, "expected %<interop%>");
28201 0 : goto fail;
28202 : }
28203 67 : c_parser_consume_token (parser);
28204 :
28205 67 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28206 0 : goto fail;
28207 67 : bool target = false;
28208 67 : bool targetsync = false;
28209 67 : tree prefer_type_tree = NULL_TREE;
28210 67 : if (!c_parser_omp_clause_init_modifiers (parser, &target,
28211 : &targetsync,
28212 : &prefer_type_tree)
28213 67 : || !c_parser_require (parser, CPP_CLOSE_PAREN,
28214 : "expected %<)%> or %<,%>"))
28215 0 : goto fail;
28216 67 : if (!target && !targetsync)
28217 3 : error_at (loc,
28218 : "missing required %<target%> and/or "
28219 : "%<targetsync%> modifier");
28220 67 : tree t = build_tree_list (target ? boolean_true_node
28221 : : boolean_false_node,
28222 : targetsync ? boolean_true_node
28223 : : boolean_false_node);
28224 67 : t = build1_loc (loc, NOP_EXPR, void_type_node, t);
28225 67 : t = build_tree_list (t, prefer_type_tree);
28226 67 : if (append_args_tree)
28227 : {
28228 19 : TREE_CHAIN (append_args_last) = t;
28229 19 : append_args_last = t;
28230 : }
28231 : else
28232 : append_args_tree = append_args_last = t;
28233 67 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
28234 : break;
28235 19 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
28236 0 : goto fail;
28237 19 : }
28238 : while (true);
28239 : }
28240 :
28241 812 : parens.require_close (parser);
28242 812 : } while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL));
28243 713 : if (variant != error_mark_node && !has_match)
28244 : {
28245 1 : c_parser_error (parser, "expected %<match%> clause");
28246 1 : variant = error_mark_node;
28247 : }
28248 713 : c_parser_skip_to_pragma_eol (parser);
28249 :
28250 : /* At this point, we have completed parsing of the pragma, now it's
28251 : on to error checking. */
28252 713 : if (variant == error_mark_node || ctx == error_mark_node)
28253 : /* Previously diagnosed error. */
28254 : return;
28255 :
28256 683 : if ((has_adjust_args || append_args_tree)
28257 683 : && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
28258 : OMP_TRAIT_CONSTRUCT_DISPATCH))
28259 : {
28260 1 : error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
28261 : "an %qs clause can only be specified if the "
28262 : "%<dispatch%> selector of the %<construct%> selector "
28263 : "set appears in the %<match%> clause",
28264 : has_adjust_args ? "adjust_args" : "append_args");
28265 1 : return;
28266 : }
28267 :
28268 682 : if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
28269 : OMP_TRAIT_CONSTRUCT_SIMD))
28270 : /* Check that the base and variant have compatible types. */
28271 : {
28272 659 : tree base_type = TREE_TYPE (fndecl);
28273 659 : tree variant_type = TREE_TYPE (variant);
28274 659 : bool unprototyped_variant
28275 659 : = (TYPE_ARG_TYPES (variant_type) == NULL_TREE
28276 659 : && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type));
28277 :
28278 659 : if (append_args_tree
28279 47 : && TYPE_ARG_TYPES (base_type) == NULL_TREE
28280 667 : && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type))
28281 : {
28282 : /* The base function is a pre-C23 unprototyped function. Without
28283 : a prototype, we don't know the offset where the append_args go.
28284 : That offset needs to be stored with the append_args in the
28285 : variant function attributes, so we cannot presently handle
28286 : this case. */
28287 6 : sorry_at (append_args_loc,
28288 : "%<append_args%> with unprototyped base function "
28289 : "is not supported yet");
28290 6 : inform (DECL_SOURCE_LOCATION (fndecl),
28291 : "base function %qD declared here", fndecl);
28292 6 : return;
28293 : }
28294 653 : else if (append_args_tree)
28295 : {
28296 : /* Find nbase_args, the number of fixed arguments in the base
28297 : function. */
28298 41 : int nappend_args = 0;
28299 41 : int nbase_args = 0;
28300 41 : for (tree t = TYPE_ARG_TYPES (base_type);
28301 183 : t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
28302 55 : nbase_args++;
28303 101 : for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
28304 60 : nappend_args++;
28305 :
28306 : /* Store as purpose = arg number after which to append
28307 : and value = list of interop items. */
28308 41 : append_args_tree = build_tree_list (build_int_cst (integer_type_node,
28309 41 : nbase_args),
28310 : append_args_tree);
28311 :
28312 : /* Give a specific diagnostic if the append_args parameters
28313 : of the variant are of the wrong type, or missing. The
28314 : compatible types test below could fail to detect this if
28315 : the variant is a varargs function. */
28316 41 : if (!unprototyped_variant)
28317 : {
28318 39 : tree args = TYPE_ARG_TYPES (variant_type);
28319 90 : for (int i = 0; args && i < nbase_args;
28320 51 : i++, args = TREE_CHAIN (args))
28321 : ;
28322 89 : for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args))
28323 109 : if (!args || !c_omp_interop_t_p (TREE_VALUE (args)))
28324 : {
28325 5 : error_at (DECL_SOURCE_LOCATION (variant),
28326 : "argument %d of %qD must be of "
28327 : "%<omp_interop_t%>",
28328 5 : nbase_args + i + 1, variant);
28329 5 : inform (append_args_loc,
28330 : "%<append_args%> specified here");
28331 100 : return;
28332 : }
28333 : }
28334 :
28335 : /* Perform the "implementation defined transformation" on the type
28336 : of the base function to add the append_args before checking it
28337 : for compatibility with the function variant's type. */
28338 36 : tree args = TYPE_ARG_TYPES (base_type);
28339 36 : tree newargs = NULL_TREE;
28340 36 : tree lastarg = NULL_TREE;
28341 89 : for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args))
28342 : {
28343 53 : tree t = tree_cons (TREE_PURPOSE (args),
28344 53 : TREE_VALUE (args), NULL_TREE);
28345 53 : if (lastarg)
28346 31 : TREE_CHAIN (lastarg) = t;
28347 : else
28348 : newargs = t;
28349 53 : lastarg = t;
28350 : }
28351 36 : tree type = lookup_name (get_identifier ("omp_interop_t"));
28352 36 : type = type ? TREE_TYPE (type) : pointer_sized_int_node;
28353 87 : for (int j = 0; j < nappend_args; j++)
28354 : {
28355 51 : tree t = tree_cons (NULL_TREE, type, NULL_TREE);
28356 51 : if (lastarg)
28357 37 : TREE_CHAIN (lastarg) = t;
28358 : else
28359 : newargs = t;
28360 51 : lastarg = t;
28361 : }
28362 36 : TREE_CHAIN (lastarg) = args;
28363 :
28364 : /* Temporarily stuff newargs into the original base_type. */
28365 36 : tree saveargs = TYPE_ARG_TYPES (base_type);
28366 36 : TYPE_ARG_TYPES (base_type) = newargs;
28367 36 : bool fail = !comptypes (base_type, variant_type);
28368 36 : TYPE_ARG_TYPES (base_type) = saveargs;
28369 :
28370 36 : if (fail)
28371 : {
28372 2 : error_at (token->location,
28373 : "variant %qD and base %qD have incompatible types "
28374 : "after %<append_args%> adjustment",
28375 : variant, fndecl);
28376 2 : inform (DECL_SOURCE_LOCATION (variant),
28377 : "%<declare variant%> candidate %qD declared here",
28378 : variant);
28379 2 : return;
28380 : }
28381 34 : else if (unprototyped_variant)
28382 : /* If we've got an unprototyped variant, copy the transformed
28383 : base arg types to the variant. This is needed later by
28384 : modify_call_for_omp_dispatch. */
28385 2 : TYPE_ARG_TYPES (variant_type) = newargs;
28386 : }
28387 : else /* No append_args present. */
28388 : {
28389 612 : if (!comptypes (base_type, variant_type))
28390 : {
28391 1 : error_at (token->location,
28392 : "variant %qD and base %qD have incompatible types",
28393 : variant, fndecl);
28394 1 : inform (DECL_SOURCE_LOCATION (variant),
28395 : "%<declare variant%> candidate %qD declared here",
28396 : variant);
28397 1 : return;
28398 : }
28399 611 : else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE
28400 3 : && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)
28401 613 : && TYPE_ARG_TYPES (base_type) != NULL_TREE)
28402 : /* If we've got an unprototyped variant but the base has
28403 : a prototype, copy the base arg types to the variant. */
28404 1 : TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type);
28405 : }
28406 : }
28407 :
28408 : /* If we made it here, store the parsed information. */
28409 668 : C_DECL_USED (variant) = 1;
28410 668 : tree construct = omp_get_context_selector_list (ctx,
28411 : OMP_TRAIT_SET_CONSTRUCT);
28412 668 : omp_mark_declare_variant (match_loc, variant, construct);
28413 668 : if (omp_context_selector_matches (ctx, NULL_TREE, false))
28414 : {
28415 245 : tree attr = tree_cons (get_identifier ("omp declare variant base"),
28416 : build_tree_list (variant, ctx),
28417 245 : DECL_ATTRIBUTES (fndecl));
28418 245 : DECL_ATTRIBUTES (fndecl) = attr;
28419 : }
28420 :
28421 668 : if (need_device_ptr_list || append_args_tree)
28422 : {
28423 49 : tree variant_decl = tree_strip_nop_conversions (variant);
28424 49 : tree t = build_tree_list (need_device_ptr_list,
28425 : NULL_TREE /* need_device_addr */);
28426 49 : TREE_CHAIN (t) = append_args_tree;
28427 49 : DECL_ATTRIBUTES (variant_decl)
28428 98 : = tree_cons (get_identifier ("omp declare variant variant args"), t,
28429 49 : DECL_ATTRIBUTES (variant_decl));
28430 : }
28431 : }
28432 :
28433 : /* Finalize #pragma omp declare simd or #pragma omp declare variant
28434 : clauses after FNDECL has been parsed, and put that into "omp declare simd"
28435 : or "omp declare variant base" attribute. */
28436 :
28437 : static void
28438 853 : c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
28439 : vec<c_token> *pclauses)
28440 : {
28441 853 : vec<c_token> &clauses = *pclauses;
28442 :
28443 : /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
28444 : indicates error has been reported and CPP_PRAGMA that
28445 : c_finish_omp_declare_simd has already processed the tokens. */
28446 1706 : if (clauses.exists () && clauses[0].type == CPP_EOF)
28447 : return;
28448 849 : const char *kind = "simd";
28449 849 : if (clauses.exists ()
28450 1698 : && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
28451 849 : kind = IDENTIFIER_POINTER (clauses[0].value);
28452 849 : gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
28453 849 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
28454 : {
28455 15 : error ("%<#pragma omp declare %s%> not immediately followed by "
28456 : "a function declaration or definition", kind);
28457 15 : clauses[0].type = CPP_EOF;
28458 15 : return;
28459 : }
28460 1668 : if (clauses.exists () && clauses[0].type != CPP_NAME)
28461 : {
28462 2 : error_at (DECL_SOURCE_LOCATION (fndecl),
28463 : "%<#pragma omp declare %s%> not immediately followed by "
28464 : "a single function declaration or definition", kind);
28465 2 : clauses[0].type = CPP_EOF;
28466 2 : return;
28467 : }
28468 832 : if (DECL_FUNCTION_VERSIONED (fndecl))
28469 : {
28470 0 : error_at (DECL_SOURCE_LOCATION (fndecl),
28471 : "%<#pragma omp declare %s%> cannot be used with function "
28472 : "multi-versioning", kind);
28473 0 : return;
28474 : }
28475 :
28476 832 : if (parms == NULL_TREE)
28477 587 : parms = DECL_ARGUMENTS (fndecl);
28478 :
28479 832 : unsigned int tokens_avail = parser->tokens_avail;
28480 832 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
28481 :
28482 832 : parser->tokens = clauses.address ();
28483 832 : parser->tokens_avail = clauses.length ();
28484 :
28485 : /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
28486 1971 : while (parser->tokens_avail > 3)
28487 : {
28488 1139 : c_token *token = c_parser_peek_token (parser);
28489 1139 : gcc_assert (token->type == CPP_NAME);
28490 1139 : kind = IDENTIFIER_POINTER (token->value);
28491 1139 : c_parser_consume_token (parser);
28492 1139 : parser->in_pragma = true;
28493 :
28494 1139 : if (strcmp (kind, "simd") == 0)
28495 : {
28496 376 : tree c;
28497 376 : c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
28498 : "#pragma omp declare simd");
28499 376 : c = c_omp_declare_simd_clauses_to_numbers (parms, c);
28500 376 : if (c != NULL_TREE)
28501 267 : c = tree_cons (NULL_TREE, c, NULL_TREE);
28502 376 : c = build_tree_list (get_identifier ("omp declare simd"), c);
28503 376 : TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
28504 376 : DECL_ATTRIBUTES (fndecl) = c;
28505 : }
28506 : else
28507 : {
28508 763 : gcc_assert (strcmp (kind, "variant") == 0);
28509 763 : c_finish_omp_declare_variant (parser, fndecl, parms);
28510 : }
28511 : }
28512 :
28513 832 : parser->tokens = &parser->tokens_buf[0];
28514 832 : parser->tokens_avail = tokens_avail;
28515 832 : if (clauses.exists ())
28516 832 : clauses[0].type = CPP_PRAGMA;
28517 : }
28518 :
28519 : /* This is consistent with the C++ front end. */
28520 :
28521 : #if !defined (NO_DOT_IN_LABEL)
28522 : #define JOIN_STR "."
28523 : #elif !defined (NO_DOLLAR_IN_LABEL)
28524 : #define JOIN_STR "$"
28525 : #else
28526 : #define JOIN_STR "_"
28527 : #endif
28528 :
28529 : /* Helper function for OpenMP "begin declare variant" directives.
28530 : Function definitions inside the construct need to have their names
28531 : mangled according to the context selector CTX. The DECLARATOR is
28532 : modified in place to point to a new identifier; the original name of
28533 : the function is returned. */
28534 : static tree
28535 24 : omp_start_variant_function (c_declarator *declarator, tree ctx)
28536 : {
28537 24 : c_declarator *id = declarator;
28538 48 : while (id->kind != cdk_id)
28539 : {
28540 24 : id = id->declarator;
28541 24 : gcc_assert (id);
28542 : }
28543 24 : tree name = id->u.id.id;
28544 24 : id->u.id.id = omp_mangle_variant_name (name, ctx, JOIN_STR);
28545 24 : return name;
28546 : }
28547 :
28548 : /* Helper function for OpenMP "begin declare variant" directives. Now
28549 : that we have a DECL for the variant function, and BASE_NAME for the
28550 : base function, add an "omp declare variant base" attribute pointing
28551 : at CTX to the base decl, and an "omp declare variant variant"
28552 : attribute to the variant DECL. */
28553 : static void
28554 24 : omp_finish_variant_function (tree decl, tree base_name, tree ctx)
28555 : {
28556 : /* First look up BASE_NAME and ensure it matches DECL. */
28557 24 : tree base_decl = lookup_name (base_name);
28558 24 : if (base_decl == error_mark_node)
28559 : base_decl = NULL_TREE;
28560 24 : if (!base_decl)
28561 : {
28562 1 : error_at (DECL_SOURCE_LOCATION (decl),
28563 : "no declaration of base function %qs",
28564 1 : IDENTIFIER_POINTER (base_name));
28565 1 : return;
28566 : }
28567 :
28568 23 : if (!comptypes (TREE_TYPE (decl), TREE_TYPE (base_decl)))
28569 : {
28570 2 : error_at (DECL_SOURCE_LOCATION (decl),
28571 : "variant function definition does not match "
28572 : "declaration of %qE", base_decl);
28573 2 : inform (DECL_SOURCE_LOCATION (base_decl),
28574 : "%qE declared here", base_decl);
28575 2 : return;
28576 : }
28577 :
28578 : /* Now set the attributes on the base and variant decls for the middle
28579 : end. */
28580 21 : omp_check_for_duplicate_variant (DECL_SOURCE_LOCATION (decl),
28581 : base_decl, ctx);
28582 21 : tree construct
28583 21 : = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
28584 21 : omp_mark_declare_variant (DECL_SOURCE_LOCATION (decl), decl, construct);
28585 21 : tree attrs = DECL_ATTRIBUTES (base_decl);
28586 21 : tree match_loc_node
28587 21 : = maybe_wrap_with_location (integer_zero_node,
28588 21 : DECL_SOURCE_LOCATION (base_decl));
28589 21 : tree loc_node = tree_cons (match_loc_node, integer_zero_node,
28590 : build_tree_list (match_loc_node,
28591 : integer_zero_node));
28592 21 : attrs = tree_cons (get_identifier ("omp declare variant base"),
28593 : tree_cons (decl, ctx, loc_node), attrs);
28594 21 : DECL_ATTRIBUTES (base_decl) = attrs;
28595 :
28596 : /* Variant functions are essentially anonymous and cannot be referenced
28597 : outside the compilation unit. */
28598 21 : TREE_PUBLIC (decl) = 0;
28599 21 : DECL_COMDAT (decl) = 0;
28600 : }
28601 :
28602 :
28603 : /* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
28604 : a threadprivate, groupprivate, allocate or declare target directive,
28605 : return true and parse it for DECL. */
28606 :
28607 : bool
28608 43 : c_maybe_parse_omp_decl (tree decl, tree d)
28609 : {
28610 43 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
28611 43 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
28612 43 : c_token *first = toks->address ();
28613 43 : c_token *last = first + toks->length ();
28614 43 : const char *directive[3] = {};
28615 119 : for (int j = 0; j < 3; j++)
28616 : {
28617 107 : tree id = NULL_TREE;
28618 107 : if (first + j == last)
28619 : break;
28620 86 : if (first[j].type == CPP_NAME)
28621 76 : id = first[j].value;
28622 10 : else if (first[j].type == CPP_KEYWORD)
28623 0 : id = ridpointers[(int) first[j].keyword];
28624 : else
28625 : break;
28626 76 : directive[j] = IDENTIFIER_POINTER (id);
28627 : }
28628 43 : const c_omp_directive *dir = NULL;
28629 43 : if (directive[0])
28630 43 : dir = c_omp_categorize_directive (directive[0], directive[1],
28631 : directive[2]);
28632 43 : if (dir == NULL)
28633 : {
28634 0 : error_at (first->location,
28635 : "unknown OpenMP directive name in "
28636 : "%qs attribute argument", "omp::decl");
28637 0 : return false;
28638 : }
28639 43 : if (dir->id != PRAGMA_OMP_THREADPRIVATE
28640 28 : && dir->id != PRAGMA_OMP_GROUPPRIVATE
28641 23 : && dir->id != PRAGMA_OMP_ALLOCATE
28642 21 : && (dir->id != PRAGMA_OMP_DECLARE
28643 21 : || strcmp (directive[1], "target") != 0))
28644 : return false;
28645 :
28646 43 : if (!flag_openmp && !dir->simd)
28647 : return true;
28648 :
28649 43 : c_parser *parser = the_parser;
28650 43 : unsigned int tokens_avail = parser->tokens_avail;
28651 43 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
28652 43 : toks = NULL;
28653 43 : vec_safe_reserve (toks, last - first + 2, true);
28654 43 : c_token tok = {};
28655 43 : tok.type = CPP_PRAGMA;
28656 43 : tok.keyword = RID_MAX;
28657 43 : tok.pragma_kind = pragma_kind (dir->id);
28658 43 : tok.location = first->location;
28659 43 : toks->quick_push (tok);
28660 201 : while (++first < last)
28661 115 : toks->quick_push (*first);
28662 43 : tok = {};
28663 43 : tok.type = CPP_PRAGMA_EOL;
28664 43 : tok.keyword = RID_MAX;
28665 43 : tok.location = last[-1].location;
28666 43 : toks->quick_push (tok);
28667 43 : tok = {};
28668 43 : tok.type = CPP_EOF;
28669 43 : tok.keyword = RID_MAX;
28670 43 : tok.location = last[-1].location;
28671 43 : toks->quick_push (tok);
28672 43 : parser->in_omp_decl_attribute = decl;
28673 43 : gcc_assert (!parser->in_omp_attribute_pragma);
28674 43 : parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
28675 43 : parser->in_omp_attribute_pragma->token_vec = toks;
28676 43 : parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
28677 43 : parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
28678 43 : parser->tokens = toks->address ();
28679 43 : parser->tokens_avail = toks->length ();
28680 43 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
28681 43 : parser->in_omp_decl_attribute = NULL_TREE;
28682 43 : return true;
28683 : }
28684 :
28685 : /* OpenMP 4.0:
28686 : # pragma omp declare target new-line
28687 : declarations and definitions
28688 : # pragma omp end declare target new-line
28689 :
28690 : OpenMP 4.5:
28691 : # pragma omp declare target ( extended-list ) new-line
28692 :
28693 : # pragma omp declare target declare-target-clauses[seq] new-line */
28694 :
28695 : #define OMP_DECLARE_TARGET_CLAUSE_MASK \
28696 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
28697 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
28698 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
28699 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
28700 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
28701 :
28702 : static void
28703 270 : c_parser_omp_declare_target (c_parser *parser)
28704 : {
28705 270 : tree clauses = NULL_TREE;
28706 270 : int device_type = 0;
28707 270 : bool indirect = false;
28708 270 : bool only_device_type_or_indirect = true;
28709 270 : if (flag_openmp)
28710 270 : omp_requires_mask
28711 270 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
28712 270 : if (c_parser_next_token_is (parser, CPP_NAME)
28713 396 : || (c_parser_next_token_is (parser, CPP_COMMA)
28714 5 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
28715 148 : clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
28716 : "#pragma omp declare target");
28717 122 : else if (parser->in_omp_decl_attribute
28718 238 : || c_parser_next_token_is (parser, CPP_OPEN_PAREN))
28719 : {
28720 20 : clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
28721 : clauses);
28722 20 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
28723 20 : c_parser_skip_to_pragma_eol (parser);
28724 : }
28725 : else
28726 : {
28727 102 : warning_at (c_parser_peek_token (parser)->location,
28728 102 : OPT_Wdeprecated_openmp,
28729 : "use of %<omp declare target%> as a synonym for "
28730 : "%<omp begin declare target%> has been deprecated since "
28731 : "OpenMP 5.2");
28732 102 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28733 102 : c_parser_skip_to_pragma_eol (parser);
28734 102 : c_omp_declare_target_attr attr = { attr_syntax, -1, 0 };
28735 102 : vec_safe_push (current_omp_declare_target_attribute, attr);
28736 102 : return;
28737 : }
28738 420 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28739 : {
28740 252 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
28741 27 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
28742 252 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28743 16 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
28744 : }
28745 420 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28746 : {
28747 252 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
28748 252 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28749 252 : continue;
28750 209 : tree t = OMP_CLAUSE_DECL (c), id;
28751 209 : tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
28752 209 : tree at2 = lookup_attribute ("omp declare target link",
28753 209 : DECL_ATTRIBUTES (t));
28754 209 : only_device_type_or_indirect = false;
28755 209 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
28756 : {
28757 30 : id = get_identifier ("omp declare target link");
28758 30 : std::swap (at1, at2);
28759 : }
28760 : else
28761 179 : id = get_identifier ("omp declare target");
28762 209 : if (at2)
28763 : {
28764 6 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
28765 3 : error_at (OMP_CLAUSE_LOCATION (c),
28766 : "%qD specified both in declare target %<link%> and %qs"
28767 3 : " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
28768 : else
28769 3 : error_at (OMP_CLAUSE_LOCATION (c),
28770 : "%qD specified both in declare target %<link%> and "
28771 : "%<to%> or %<enter%> clauses", t);
28772 6 : continue;
28773 : }
28774 203 : if (!at1)
28775 : {
28776 174 : DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28777 174 : if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
28778 1 : continue;
28779 :
28780 173 : symtab_node *node = symtab_node::get (t);
28781 173 : if (node != NULL)
28782 : {
28783 126 : node->offloadable = 1;
28784 126 : if (ENABLE_OFFLOADING)
28785 : {
28786 : g->have_offload = true;
28787 : if (is_a <varpool_node *> (node))
28788 : vec_safe_push (offload_vars, t);
28789 : }
28790 : }
28791 : }
28792 202 : if (TREE_CODE (t) != FUNCTION_DECL)
28793 121 : continue;
28794 81 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
28795 : {
28796 13 : tree at3 = lookup_attribute ("omp declare target host",
28797 13 : DECL_ATTRIBUTES (t));
28798 13 : if (at3 == NULL_TREE)
28799 : {
28800 11 : id = get_identifier ("omp declare target host");
28801 11 : DECL_ATTRIBUTES (t)
28802 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28803 : }
28804 : }
28805 81 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
28806 : {
28807 13 : tree at3 = lookup_attribute ("omp declare target nohost",
28808 13 : DECL_ATTRIBUTES (t));
28809 13 : if (at3 == NULL_TREE)
28810 : {
28811 11 : id = get_identifier ("omp declare target nohost");
28812 11 : DECL_ATTRIBUTES (t)
28813 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28814 : }
28815 : }
28816 81 : if (indirect)
28817 : {
28818 9 : tree at4 = lookup_attribute ("omp declare target indirect",
28819 9 : DECL_ATTRIBUTES (t));
28820 9 : if (at4 == NULL_TREE)
28821 : {
28822 9 : id = get_identifier ("omp declare target indirect");
28823 9 : DECL_ATTRIBUTES (t)
28824 18 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28825 : }
28826 : }
28827 : }
28828 168 : if ((device_type || indirect) && only_device_type_or_indirect)
28829 3 : error_at (OMP_CLAUSE_LOCATION (clauses),
28830 : "directive with only %<device_type%> or %<indirect%> clauses");
28831 168 : if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
28832 1 : error_at (OMP_CLAUSE_LOCATION (clauses),
28833 : "%<device_type%> clause must specify 'any' when used with "
28834 : "an %<indirect%> clause");
28835 : }
28836 :
28837 : /* OpenMP 5.1
28838 : #pragma omp begin assumes clauses[optseq] new-line
28839 :
28840 : #pragma omp begin declare target clauses[optseq] new-line
28841 :
28842 : #pragma omp begin declare variant match (context-selector) new-line */
28843 :
28844 : #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
28845 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
28846 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
28847 :
28848 : static void
28849 128 : c_parser_omp_begin (c_parser *parser)
28850 : {
28851 128 : const char *p = "";
28852 128 : c_parser_consume_pragma (parser);
28853 128 : if (c_parser_next_token_is (parser, CPP_NAME))
28854 128 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28855 128 : if (strcmp (p, "declare") == 0)
28856 : {
28857 82 : c_parser_consume_token (parser);
28858 82 : p = "";
28859 82 : if (c_parser_next_token_is (parser, CPP_NAME))
28860 82 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28861 82 : if (strcmp (p, "target") == 0)
28862 : {
28863 52 : c_parser_consume_token (parser);
28864 52 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28865 52 : tree clauses
28866 52 : = c_parser_omp_all_clauses (parser,
28867 52 : OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
28868 : "#pragma omp begin declare target");
28869 52 : int device_type = 0;
28870 52 : int indirect = 0;
28871 76 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28872 : {
28873 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
28874 15 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
28875 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28876 9 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
28877 : }
28878 52 : c_omp_declare_target_attr attr = { attr_syntax, device_type,
28879 52 : indirect };
28880 52 : vec_safe_push (current_omp_declare_target_attribute, attr);
28881 : }
28882 30 : else if (strcmp (p, "variant") == 0)
28883 : {
28884 30 : c_parser_consume_token (parser);
28885 30 : const char *clause = "";
28886 30 : matching_parens parens;
28887 30 : location_t match_loc = c_parser_peek_token (parser)->location;
28888 30 : if (c_parser_next_token_is (parser, CPP_COMMA))
28889 1 : c_parser_consume_token (parser);
28890 30 : if (c_parser_next_token_is (parser, CPP_NAME))
28891 : {
28892 30 : tree id = c_parser_peek_token (parser)->value;
28893 30 : clause = IDENTIFIER_POINTER (id);
28894 : }
28895 30 : if (strcmp (clause, "match") != 0)
28896 : {
28897 0 : c_parser_error (parser, "expected %<match%>");
28898 0 : c_parser_skip_to_pragma_eol (parser);
28899 6 : return;
28900 : }
28901 :
28902 30 : c_parser_consume_token (parser);
28903 :
28904 30 : if (!parens.require_open (parser))
28905 : {
28906 0 : c_parser_skip_to_pragma_eol (parser, false);
28907 0 : return;
28908 : }
28909 :
28910 30 : tree ctx =
28911 30 : c_parser_omp_context_selector_specification (parser, NULL_TREE);
28912 30 : if (ctx != error_mark_node)
28913 28 : ctx = omp_check_context_selector (match_loc, ctx,
28914 : OMP_CTX_BEGIN_DECLARE_VARIANT);
28915 :
28916 30 : if (ctx != error_mark_node
28917 30 : && !vec_safe_is_empty (current_omp_declare_variant_attribute))
28918 : {
28919 7 : c_omp_declare_variant_attr a
28920 7 : = current_omp_declare_variant_attribute->last ();
28921 7 : tree outer_ctx = a.selector;
28922 7 : ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx,
28923 : OMP_CTX_BEGIN_DECLARE_VARIANT);
28924 : }
28925 :
28926 30 : if (ctx == error_mark_node
28927 30 : || !omp_context_selector_matches (ctx, NULL_TREE, false, true))
28928 : {
28929 : /* The context is either invalid or cannot possibly match.
28930 : In the latter case the spec says all code in the begin/end
28931 : sequence will be elided. In the former case we'll get bogus
28932 : errors from trying to parse it without a valid context to
28933 : use for name-mangling, so elide that too. */
28934 6 : c_parser_skip_to_pragma_eol (parser, false);
28935 6 : c_parser_skip_to_pragma_omp_end_declare_variant (parser);
28936 6 : return;
28937 : }
28938 : else
28939 : {
28940 24 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28941 24 : c_omp_declare_variant_attr a = { attr_syntax, ctx };
28942 24 : vec_safe_push (current_omp_declare_variant_attribute, a);
28943 : }
28944 :
28945 24 : parens.require_close (parser);
28946 24 : c_parser_skip_to_pragma_eol (parser);
28947 : }
28948 : else
28949 : {
28950 0 : c_parser_error (parser, "expected %<target%> or %<variant%>");
28951 0 : c_parser_skip_to_pragma_eol (parser, false);
28952 : }
28953 : }
28954 46 : else if (strcmp (p, "assumes") == 0)
28955 : {
28956 46 : c_parser_consume_token (parser);
28957 46 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28958 46 : c_parser_omp_assumption_clauses (parser, false);
28959 46 : struct c_omp_begin_assumes_data a = { attr_syntax };
28960 46 : vec_safe_push (current_omp_begin_assumes, a);
28961 : }
28962 : else
28963 : {
28964 0 : c_parser_error (parser, "expected %<declare target%>, "
28965 : "%<declare variant%>, or %<assumes%>");
28966 0 : c_parser_skip_to_pragma_eol (parser);
28967 : }
28968 : }
28969 :
28970 : /* OpenMP 4.0
28971 : #pragma omp end declare target
28972 :
28973 : OpenMP 5.1
28974 : #pragma omp end assumes
28975 : #pragma omp end declare variant */
28976 :
28977 : static void
28978 222 : c_parser_omp_end (c_parser *parser)
28979 : {
28980 222 : location_t loc = c_parser_peek_token (parser)->location;
28981 222 : const char *p = "";
28982 222 : c_parser_consume_pragma (parser);
28983 222 : if (c_parser_next_token_is (parser, CPP_NAME))
28984 222 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28985 222 : if (strcmp (p, "declare") == 0)
28986 : {
28987 176 : c_parser_consume_token (parser);
28988 176 : p = "";
28989 176 : if (c_parser_next_token_is (parser, CPP_NAME))
28990 176 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28991 176 : if (strcmp (p, "target") == 0)
28992 : {
28993 152 : c_parser_consume_token (parser);
28994 152 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28995 152 : c_parser_skip_to_pragma_eol (parser);
28996 152 : if (!vec_safe_length (current_omp_declare_target_attribute))
28997 2 : error_at (loc, "%<#pragma omp end declare target%> without "
28998 : "corresponding %<#pragma omp declare target%> or "
28999 : "%<#pragma omp begin declare target%>");
29000 : else
29001 : {
29002 150 : c_omp_declare_target_attr
29003 150 : a = current_omp_declare_target_attribute->pop ();
29004 150 : if (a.attr_syntax != attr_syntax)
29005 : {
29006 16 : if (a.attr_syntax)
29007 12 : error_at (loc,
29008 : "%qs in attribute syntax terminated "
29009 : "with %qs in pragma syntax",
29010 : a.device_type >= 0 ? "begin declare target"
29011 : : "declare target",
29012 : "end declare target");
29013 : else
29014 12 : error_at (loc,
29015 : "%qs in pragma syntax terminated "
29016 : "with %qs in attribute syntax",
29017 : a.device_type >= 0 ? "begin declare target"
29018 : : "declare target",
29019 : "end declare target");
29020 : }
29021 : }
29022 : }
29023 24 : else if (strcmp (p, "variant") == 0)
29024 : {
29025 24 : c_parser_consume_token (parser);
29026 24 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
29027 24 : c_parser_skip_to_pragma_eol (parser);
29028 24 : if (!vec_safe_length (current_omp_declare_variant_attribute))
29029 0 : error_at (loc, "%<#pragma omp end declare variant%> without "
29030 : "corresponding %<#pragma omp begin declare variant%>");
29031 : else
29032 : {
29033 24 : c_omp_declare_variant_attr
29034 24 : a = current_omp_declare_variant_attribute->pop ();
29035 24 : if (a.attr_syntax != attr_syntax)
29036 : {
29037 2 : if (a.attr_syntax)
29038 1 : error_at (loc,
29039 : "%<begin declare variant%> in attribute syntax "
29040 : "terminated with "
29041 : "%<end declare variant%> in pragma syntax");
29042 : else
29043 1 : error_at (loc,
29044 : "%<begin declare variant%> in pragma syntax "
29045 : "terminated with "
29046 : "%<end declare variant%> in attribute syntax");
29047 : }
29048 : }
29049 : }
29050 : else
29051 : {
29052 0 : c_parser_error (parser, "expected %<target%> or %<variant%>");
29053 0 : c_parser_skip_to_pragma_eol (parser);
29054 0 : return;
29055 : }
29056 : }
29057 46 : else if (strcmp (p, "assumes") == 0)
29058 : {
29059 46 : c_parser_consume_token (parser);
29060 46 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
29061 46 : c_parser_skip_to_pragma_eol (parser);
29062 46 : if (!vec_safe_length (current_omp_begin_assumes))
29063 1 : error_at (loc, "%qs without corresponding %qs",
29064 : "#pragma omp end assumes", "#pragma omp begin assumes");
29065 : else
29066 : {
29067 45 : c_omp_begin_assumes_data
29068 45 : a = current_omp_begin_assumes->pop ();
29069 45 : if (a.attr_syntax != attr_syntax)
29070 : {
29071 8 : if (a.attr_syntax)
29072 4 : error_at (loc,
29073 : "%qs in attribute syntax terminated "
29074 : "with %qs in pragma syntax",
29075 : "begin assumes", "end assumes");
29076 : else
29077 4 : error_at (loc,
29078 : "%qs in pragma syntax terminated "
29079 : "with %qs in attribute syntax",
29080 : "begin assumes", "end assumes");
29081 : }
29082 : }
29083 : }
29084 : else
29085 : {
29086 0 : c_parser_error (parser, "expected %<declare%> or %<assumes%>");
29087 0 : c_parser_skip_to_pragma_eol (parser);
29088 : }
29089 : }
29090 :
29091 : /* OpenMP 5.0
29092 : #pragma omp declare mapper ([mapper-identifier :] type var) \
29093 : [clause [ [,] clause ] ... ] new-line */
29094 :
29095 : static void
29096 65 : c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
29097 : {
29098 65 : tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
29099 65 : tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
29100 65 : c_token *token;
29101 :
29102 65 : if (context == pragma_struct || context == pragma_param)
29103 : {
29104 2 : error ("%<#pragma omp declare mapper%> not at file or block scope");
29105 2 : goto fail;
29106 : }
29107 :
29108 63 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
29109 0 : goto fail;
29110 :
29111 63 : token = c_parser_peek_token (parser);
29112 :
29113 63 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
29114 : {
29115 22 : switch (token->type)
29116 : {
29117 15 : case CPP_NAME:
29118 15 : mapper_name = token->value;
29119 15 : c_parser_consume_token (parser);
29120 15 : break;
29121 7 : case CPP_KEYWORD:
29122 7 : if (token->keyword == RID_DEFAULT)
29123 : {
29124 6 : mapper_name = NULL_TREE;
29125 6 : c_parser_consume_token (parser);
29126 6 : break;
29127 : }
29128 : /* Fallthrough. */
29129 1 : default:
29130 1 : error_at (token->location, "expected identifier or %<default%>");
29131 1 : c_parser_skip_to_pragma_eol (parser, false);
29132 1 : return;
29133 : }
29134 :
29135 21 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
29136 0 : goto fail;
29137 : }
29138 :
29139 62 : mapper_id = c_omp_mapper_id (mapper_name);
29140 62 : mapper_decl = c_omp_mapper_decl (mapper_id);
29141 :
29142 62 : {
29143 62 : location_t loc = c_parser_peek_token (parser)->location;
29144 62 : struct c_type_name *ctype = c_parser_type_name (parser);
29145 62 : type = groktypename (ctype, NULL, NULL);
29146 62 : if (type == error_mark_node)
29147 3 : goto fail;
29148 59 : if (!RECORD_OR_UNION_TYPE_P (type))
29149 : {
29150 4 : error_at (loc, "%qT is not a struct or union type in "
29151 : "%<#pragma omp declare mapper%>", type);
29152 4 : c_parser_skip_to_pragma_eol (parser, false);
29153 4 : return;
29154 : }
29155 65 : for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
29156 17 : if (comptypes (TREE_PURPOSE (t), type))
29157 : {
29158 7 : error_at (loc, "redeclaration of %qs %<#pragma omp declare "
29159 7 : "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
29160 : + sizeof ("omp declare mapper ") - 1,
29161 : type);
29162 7 : tree prevmapper = TREE_VALUE (t);
29163 : /* Hmm, this location might not be very accurate. */
29164 7 : location_t ploc
29165 7 : = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
29166 7 : inform (ploc, "%<#pragma omp declare mapper%> "
29167 : "previously declared here");
29168 7 : c_parser_skip_to_pragma_eol (parser, false);
29169 7 : return;
29170 : }
29171 : }
29172 :
29173 48 : token = c_parser_peek_token (parser);
29174 48 : if (token->type == CPP_NAME)
29175 : {
29176 46 : var = build_decl (token->location, VAR_DECL, token->value, type);
29177 46 : c_parser_consume_token (parser);
29178 46 : DECL_ARTIFICIAL (var) = 1;
29179 : }
29180 : else
29181 : {
29182 2 : error_at (token->location, "expected identifier");
29183 2 : goto fail;
29184 : }
29185 :
29186 46 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
29187 0 : goto fail;
29188 :
29189 46 : push_scope ();
29190 46 : stmtlist = push_stmt_list ();
29191 46 : pushdecl (var);
29192 46 : DECL_CONTEXT (var) = current_function_decl;
29193 :
29194 115 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29195 : {
29196 70 : location_t here;
29197 70 : pragma_omp_clause c_kind;
29198 70 : here = c_parser_peek_token (parser)->location;
29199 70 : c_kind = c_parser_omp_clause_name (parser);
29200 70 : if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
29201 : {
29202 1 : error_at (here, "unexpected clause");
29203 1 : goto fail;
29204 : }
29205 69 : maplist = c_parser_omp_clause_map (parser, maplist, true);
29206 : }
29207 :
29208 45 : if (maplist == NULL_TREE)
29209 : {
29210 1 : error_at (input_location, "missing %<map%> clause");
29211 1 : goto fail;
29212 : }
29213 :
29214 44 : stmt = make_node (OMP_DECLARE_MAPPER);
29215 44 : TREE_TYPE (stmt) = type;
29216 44 : OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
29217 44 : OMP_DECLARE_MAPPER_DECL (stmt) = var;
29218 44 : OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
29219 :
29220 44 : add_stmt (stmt);
29221 :
29222 44 : pop_stmt_list (stmtlist);
29223 44 : pop_scope ();
29224 :
29225 44 : c_parser_skip_to_pragma_eol (parser);
29226 :
29227 44 : t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
29228 44 : DECL_INITIAL (mapper_decl) = t;
29229 :
29230 44 : return;
29231 :
29232 9 : fail:
29233 9 : c_parser_skip_to_pragma_eol (parser);
29234 : }
29235 :
29236 : /* OpenMP 4.0
29237 : #pragma omp declare reduction (reduction-id : typename-list : expression) \
29238 : initializer-clause[opt] new-line
29239 :
29240 : initializer-clause:
29241 : initializer (omp_priv = initializer)
29242 : initializer (function-name (argument-list)) */
29243 :
29244 : static void
29245 164 : c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
29246 : {
29247 164 : unsigned int tokens_avail = 0, i;
29248 164 : c_token *saved_tokens = NULL;
29249 164 : vec<tree> types = vNULL;
29250 164 : vec<c_token> clauses = vNULL;
29251 164 : enum tree_code reduc_code = ERROR_MARK;
29252 164 : tree reduc_id = NULL_TREE;
29253 164 : tree type;
29254 164 : location_t rloc = c_parser_peek_token (parser)->location;
29255 :
29256 164 : if (context == pragma_struct || context == pragma_param)
29257 : {
29258 2 : error ("%<#pragma omp declare reduction%> not at file or block scope");
29259 2 : goto fail;
29260 : }
29261 :
29262 162 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
29263 1 : goto fail;
29264 :
29265 161 : switch (c_parser_peek_token (parser)->type)
29266 : {
29267 : case CPP_PLUS:
29268 : reduc_code = PLUS_EXPR;
29269 : break;
29270 14 : case CPP_MULT:
29271 14 : reduc_code = MULT_EXPR;
29272 14 : break;
29273 0 : case CPP_MINUS:
29274 0 : reduc_code = MINUS_EXPR;
29275 0 : break;
29276 4 : case CPP_AND:
29277 4 : reduc_code = BIT_AND_EXPR;
29278 4 : break;
29279 0 : case CPP_XOR:
29280 0 : reduc_code = BIT_XOR_EXPR;
29281 0 : break;
29282 10 : case CPP_OR:
29283 10 : reduc_code = BIT_IOR_EXPR;
29284 10 : break;
29285 0 : case CPP_AND_AND:
29286 0 : reduc_code = TRUTH_ANDIF_EXPR;
29287 0 : break;
29288 0 : case CPP_OR_OR:
29289 0 : reduc_code = TRUTH_ORIF_EXPR;
29290 0 : break;
29291 89 : case CPP_NAME:
29292 89 : const char *p;
29293 89 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29294 89 : if (strcmp (p, "min") == 0)
29295 : {
29296 : reduc_code = MIN_EXPR;
29297 : break;
29298 : }
29299 83 : if (strcmp (p, "max") == 0)
29300 : {
29301 : reduc_code = MAX_EXPR;
29302 : break;
29303 : }
29304 83 : reduc_id = c_parser_peek_token (parser)->value;
29305 83 : break;
29306 0 : default:
29307 0 : c_parser_error (parser,
29308 : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
29309 : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
29310 0 : goto fail;
29311 : }
29312 :
29313 161 : tree orig_reduc_id, reduc_decl;
29314 161 : orig_reduc_id = reduc_id;
29315 161 : reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
29316 161 : reduc_decl = c_omp_reduction_decl (reduc_id);
29317 161 : c_parser_consume_token (parser);
29318 :
29319 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
29320 0 : goto fail;
29321 :
29322 165 : while (true)
29323 : {
29324 163 : location_t loc = c_parser_peek_token (parser)->location;
29325 163 : struct c_type_name *ctype = c_parser_type_name (parser);
29326 163 : if (ctype != NULL)
29327 : {
29328 163 : type = groktypename (ctype, NULL, NULL);
29329 163 : if (type == error_mark_node)
29330 : ;
29331 163 : else if ((INTEGRAL_TYPE_P (type)
29332 163 : || SCALAR_FLOAT_TYPE_P (type)
29333 98 : || TREE_CODE (type) == COMPLEX_TYPE)
29334 69 : && orig_reduc_id == NULL_TREE)
29335 8 : error_at (loc, "predeclared arithmetic type in "
29336 : "%<#pragma omp declare reduction%>");
29337 155 : else if (TREE_CODE (type) == FUNCTION_TYPE
29338 150 : || TREE_CODE (type) == ARRAY_TYPE)
29339 8 : error_at (loc, "function or array type in "
29340 : "%<#pragma omp declare reduction%>");
29341 147 : else if (TYPE_ATOMIC (type))
29342 1 : error_at (loc, "%<_Atomic%> qualified type in "
29343 : "%<#pragma omp declare reduction%>");
29344 146 : else if (TYPE_QUALS_NO_ADDR_SPACE (type))
29345 8 : error_at (loc, "const, volatile or restrict qualified type in "
29346 : "%<#pragma omp declare reduction%>");
29347 : else
29348 : {
29349 138 : tree t;
29350 200 : for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
29351 66 : if (comptypes (TREE_PURPOSE (t), type))
29352 : {
29353 4 : error_at (loc, "redeclaration of %qs "
29354 : "%<#pragma omp declare reduction%> for "
29355 : "type %qT",
29356 4 : IDENTIFIER_POINTER (reduc_id)
29357 : + sizeof ("omp declare reduction ") - 1,
29358 : type);
29359 4 : location_t ploc
29360 4 : = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
29361 : 0));
29362 4 : inform (ploc, "%<#pragma omp declare reduction%> "
29363 : "previously declared here");
29364 4 : break;
29365 : }
29366 4 : if (t == NULL_TREE)
29367 134 : types.safe_push (type);
29368 : }
29369 163 : if (c_parser_next_token_is (parser, CPP_COMMA))
29370 2 : c_parser_consume_token (parser);
29371 : else
29372 : break;
29373 : }
29374 : else
29375 : break;
29376 2 : }
29377 :
29378 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
29379 161 : || types.is_empty ())
29380 : {
29381 34 : fail:
29382 34 : clauses.release ();
29383 34 : types.release ();
29384 460 : while (true)
29385 : {
29386 247 : c_token *token = c_parser_peek_token (parser);
29387 247 : if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
29388 : break;
29389 213 : c_parser_consume_token (parser);
29390 213 : }
29391 34 : c_parser_skip_to_pragma_eol (parser);
29392 34 : return;
29393 : }
29394 :
29395 132 : if (types.length () > 1)
29396 : {
29397 13 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29398 : {
29399 12 : c_token *token = c_parser_peek_token (parser);
29400 12 : if (token->type == CPP_EOF)
29401 0 : goto fail;
29402 12 : clauses.safe_push (*token);
29403 12 : c_parser_consume_token (parser);
29404 : }
29405 1 : clauses.safe_push (*c_parser_peek_token (parser));
29406 1 : c_parser_skip_to_pragma_eol (parser);
29407 :
29408 : /* Make sure nothing tries to read past the end of the tokens. */
29409 1 : c_token eof_token;
29410 1 : memset (&eof_token, 0, sizeof (eof_token));
29411 1 : eof_token.type = CPP_EOF;
29412 1 : clauses.safe_push (eof_token);
29413 1 : clauses.safe_push (eof_token);
29414 : }
29415 :
29416 132 : int errs = errorcount;
29417 238 : FOR_EACH_VEC_ELT (types, i, type)
29418 : {
29419 134 : saved_tokens = parser->tokens;
29420 134 : tokens_avail = parser->tokens_avail;
29421 134 : if (!clauses.is_empty ())
29422 : {
29423 3 : parser->tokens = clauses.address ();
29424 3 : parser->tokens_avail = clauses.length ();
29425 3 : parser->in_pragma = true;
29426 : }
29427 :
29428 134 : bool nested = current_function_decl != NULL_TREE;
29429 134 : if (nested)
29430 27 : c_push_function_context ();
29431 134 : tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
29432 : reduc_id, default_function_type);
29433 134 : current_function_decl = fndecl;
29434 134 : allocate_struct_function (fndecl, true);
29435 134 : push_scope ();
29436 134 : tree stmt = push_stmt_list ();
29437 : /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
29438 : warn about these. */
29439 134 : tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
29440 : get_identifier ("omp_out"), type);
29441 134 : DECL_ARTIFICIAL (omp_out) = 1;
29442 134 : DECL_CONTEXT (omp_out) = fndecl;
29443 134 : pushdecl (omp_out);
29444 134 : tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
29445 : get_identifier ("omp_in"), type);
29446 134 : DECL_ARTIFICIAL (omp_in) = 1;
29447 134 : DECL_CONTEXT (omp_in) = fndecl;
29448 134 : pushdecl (omp_in);
29449 134 : struct c_expr combiner = c_parser_expression (parser);
29450 134 : struct c_expr initializer;
29451 134 : tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
29452 134 : bool bad = false;
29453 134 : initializer.set_error ();
29454 134 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
29455 : bad = true;
29456 134 : else if (c_parser_next_token_is (parser, CPP_COMMA)
29457 134 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29458 2 : c_parser_consume_token (parser);
29459 2 : if (!bad
29460 134 : && (c_parser_next_token_is (parser, CPP_NAME)
29461 77 : && strcmp (IDENTIFIER_POINTER
29462 : (c_parser_peek_token (parser)->value),
29463 : "initializer") == 0))
29464 : {
29465 77 : c_parser_consume_token (parser);
29466 77 : pop_scope ();
29467 77 : push_scope ();
29468 77 : omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
29469 : get_identifier ("omp_priv"), type);
29470 77 : DECL_ARTIFICIAL (omp_priv) = 1;
29471 77 : DECL_INITIAL (omp_priv) = error_mark_node;
29472 77 : DECL_CONTEXT (omp_priv) = fndecl;
29473 77 : pushdecl (omp_priv);
29474 77 : omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
29475 : get_identifier ("omp_orig"), type);
29476 77 : DECL_ARTIFICIAL (omp_orig) = 1;
29477 77 : DECL_CONTEXT (omp_orig) = fndecl;
29478 77 : pushdecl (omp_orig);
29479 77 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
29480 : bad = true;
29481 77 : else if (!c_parser_next_token_is (parser, CPP_NAME))
29482 : {
29483 0 : c_parser_error (parser, "expected %<omp_priv%> or "
29484 : "function-name");
29485 0 : bad = true;
29486 : }
29487 77 : else if (strcmp (IDENTIFIER_POINTER
29488 : (c_parser_peek_token (parser)->value),
29489 : "omp_priv") != 0)
29490 : {
29491 20 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
29492 20 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
29493 : {
29494 0 : c_parser_error (parser, "expected function-name %<(%>");
29495 0 : bad = true;
29496 : }
29497 : else
29498 20 : initializer = c_parser_postfix_expression (parser);
29499 20 : if (initializer.value
29500 20 : && TREE_CODE (initializer.value) == CALL_EXPR)
29501 : {
29502 : int j;
29503 : tree c = initializer.value;
29504 21 : for (j = 0; j < call_expr_nargs (c); j++)
29505 : {
29506 20 : tree a = CALL_EXPR_ARG (c, j);
29507 20 : STRIP_NOPS (a);
29508 20 : if (TREE_CODE (a) == ADDR_EXPR
29509 20 : && TREE_OPERAND (a, 0) == omp_priv)
29510 : break;
29511 : }
29512 20 : if (j == call_expr_nargs (c))
29513 1 : error ("one of the initializer call arguments should be "
29514 : "%<&omp_priv%>");
29515 : }
29516 : }
29517 : else
29518 : {
29519 57 : c_parser_consume_token (parser);
29520 57 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
29521 : bad = true;
29522 : else
29523 : {
29524 55 : tree st = push_stmt_list ();
29525 55 : location_t loc = c_parser_peek_token (parser)->location;
29526 55 : rich_location richloc (line_table, loc);
29527 55 : start_init (omp_priv, NULL_TREE, false, false, &richloc);
29528 55 : struct c_expr init = c_parser_initializer (parser, omp_priv);
29529 55 : finish_init ();
29530 55 : finish_decl (omp_priv, loc, init.value,
29531 : init.original_type, NULL_TREE);
29532 55 : pop_stmt_list (st);
29533 55 : }
29534 : }
29535 0 : if (!bad
29536 75 : && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
29537 : bad = true;
29538 : }
29539 :
29540 134 : if (!bad)
29541 : {
29542 132 : c_parser_skip_to_pragma_eol (parser);
29543 :
29544 189 : tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
29545 132 : DECL_INITIAL (reduc_decl));
29546 132 : DECL_INITIAL (reduc_decl) = t;
29547 132 : DECL_SOURCE_LOCATION (omp_out) = rloc;
29548 132 : TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
29549 132 : TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
29550 132 : TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
29551 132 : walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
29552 : &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
29553 132 : if (omp_priv)
29554 : {
29555 75 : DECL_SOURCE_LOCATION (omp_priv) = rloc;
29556 75 : TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
29557 75 : TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
29558 75 : TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
29559 75 : walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
29560 : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
29561 75 : walk_tree (&DECL_INITIAL (omp_priv),
29562 : c_check_omp_declare_reduction_r,
29563 : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
29564 : }
29565 : }
29566 :
29567 134 : pop_stmt_list (stmt);
29568 134 : pop_scope ();
29569 134 : if (cfun->language != NULL)
29570 : {
29571 0 : ggc_free (cfun->language);
29572 0 : cfun->language = NULL;
29573 : }
29574 134 : set_cfun (NULL);
29575 134 : current_function_decl = NULL_TREE;
29576 134 : if (nested)
29577 27 : c_pop_function_context ();
29578 :
29579 134 : if (!clauses.is_empty ())
29580 : {
29581 3 : parser->tokens = saved_tokens;
29582 3 : parser->tokens_avail = tokens_avail;
29583 : }
29584 134 : if (bad)
29585 2 : goto fail;
29586 132 : if (errs != errorcount)
29587 : break;
29588 : }
29589 :
29590 130 : clauses.release ();
29591 130 : types.release ();
29592 : }
29593 :
29594 : /* OpenMP 4.0
29595 : #pragma omp declare simd declare-simd-clauses[optseq] new-line
29596 : #pragma omp declare reduction (reduction-id : typename-list : expression) \
29597 : initializer-clause[opt] new-line
29598 : #pragma omp declare target new-line
29599 :
29600 : OpenMP 5.0
29601 : #pragma omp declare variant (identifier) match (context-selector)
29602 :
29603 : OpenMP 5.1
29604 : #pragma omp declare variant (identifier) match (context-selector) \
29605 : adjust_args(adjust-op:argument-list) */
29606 :
29607 : static bool
29608 1280 : c_parser_omp_declare (c_parser *parser, enum pragma_context context)
29609 : {
29610 1280 : c_parser_consume_pragma (parser);
29611 1280 : if (c_parser_next_token_is (parser, CPP_NAME))
29612 : {
29613 1280 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29614 1280 : if (strcmp (p, "simd") == 0)
29615 : {
29616 : /* c_parser_consume_token (parser); done in
29617 : c_parser_omp_declare_simd. */
29618 280 : c_parser_omp_declare_simd (parser, context);
29619 280 : return true;
29620 : }
29621 1000 : if (strcmp (p, "reduction") == 0)
29622 : {
29623 164 : c_parser_consume_token (parser);
29624 164 : c_parser_omp_declare_reduction (parser, context);
29625 164 : return false;
29626 : }
29627 836 : if (strcmp (p, "mapper") == 0)
29628 : {
29629 65 : c_parser_consume_token (parser);
29630 65 : c_parser_omp_declare_mapper (parser, context);
29631 65 : return false;
29632 : }
29633 771 : if (!flag_openmp) /* flag_openmp_simd */
29634 : {
29635 0 : c_parser_skip_to_pragma_eol (parser, false);
29636 0 : return false;
29637 : }
29638 771 : if (strcmp (p, "target") == 0)
29639 : {
29640 270 : c_parser_consume_token (parser);
29641 270 : c_parser_omp_declare_target (parser);
29642 270 : return false;
29643 : }
29644 501 : if (strcmp (p, "variant") == 0)
29645 : {
29646 : /* c_parser_consume_token (parser); done in
29647 : c_parser_omp_declare_simd. */
29648 501 : c_parser_omp_declare_simd (parser, context);
29649 501 : return true;
29650 : }
29651 : }
29652 :
29653 0 : c_parser_error (parser, "expected %<simd%>, %<reduction%>, "
29654 : "%<target%> or %<variant%>");
29655 0 : c_parser_skip_to_pragma_eol (parser);
29656 0 : return false;
29657 : }
29658 :
29659 : /* OpenMP 5.0
29660 : #pragma omp requires clauses[optseq] new-line */
29661 :
29662 : static void
29663 59 : c_parser_omp_requires (c_parser *parser)
29664 : {
29665 59 : enum omp_requires new_req = (enum omp_requires) 0;
29666 :
29667 59 : c_parser_consume_pragma (parser);
29668 :
29669 59 : location_t loc = c_parser_peek_token (parser)->location;
29670 132 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29671 : {
29672 77 : if (c_parser_next_token_is (parser, CPP_COMMA)
29673 77 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29674 14 : c_parser_consume_token (parser);
29675 :
29676 77 : if (c_parser_next_token_is (parser, CPP_NAME))
29677 : {
29678 76 : const char *p
29679 76 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29680 76 : location_t cloc = c_parser_peek_token (parser)->location;
29681 76 : enum omp_requires this_req = (enum omp_requires) 0;
29682 :
29683 76 : if (!strcmp (p, "unified_address"))
29684 : this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
29685 62 : else if (!strcmp (p, "unified_shared_memory"))
29686 : this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
29687 50 : else if (!strcmp (p, "self_maps"))
29688 : this_req = OMP_REQUIRES_SELF_MAPS;
29689 49 : else if (!strcmp (p, "dynamic_allocators"))
29690 : this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
29691 38 : else if (!strcmp (p, "reverse_offload"))
29692 : this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
29693 21 : else if (!strcmp (p, "atomic_default_mem_order"))
29694 : {
29695 20 : c_parser_consume_token (parser);
29696 :
29697 20 : matching_parens parens;
29698 20 : if (parens.require_open (parser))
29699 : {
29700 20 : if (c_parser_next_token_is (parser, CPP_NAME))
29701 : {
29702 19 : tree v = c_parser_peek_token (parser)->value;
29703 19 : p = IDENTIFIER_POINTER (v);
29704 :
29705 19 : if (!strcmp (p, "seq_cst"))
29706 : this_req
29707 : = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
29708 10 : else if (!strcmp (p, "relaxed"))
29709 : this_req
29710 : = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
29711 9 : else if (!strcmp (p, "release"))
29712 : this_req
29713 : = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
29714 7 : else if (!strcmp (p, "acq_rel"))
29715 : this_req
29716 : = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
29717 4 : else if (!strcmp (p, "acquire"))
29718 : this_req
29719 : = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
29720 : }
29721 : if (this_req == 0)
29722 : {
29723 2 : error_at (c_parser_peek_token (parser)->location,
29724 : "expected %<acq_rel%>, %<acquire%>, "
29725 : "%<relaxed%>, %<release%> or %<seq_cst%>");
29726 2 : switch (c_parser_peek_token (parser)->type)
29727 : {
29728 : case CPP_EOF:
29729 : case CPP_PRAGMA_EOL:
29730 : case CPP_CLOSE_PAREN:
29731 : break;
29732 1 : default:
29733 1 : if (c_parser_peek_2nd_token (parser)->type
29734 : == CPP_CLOSE_PAREN)
29735 1 : c_parser_consume_token (parser);
29736 : break;
29737 : }
29738 : }
29739 : else
29740 18 : c_parser_consume_token (parser);
29741 :
29742 20 : parens.skip_until_found_close (parser);
29743 20 : if (this_req == 0)
29744 : {
29745 2 : c_parser_skip_to_pragma_eol (parser, false);
29746 2 : return;
29747 : }
29748 : }
29749 18 : p = NULL;
29750 : }
29751 : else
29752 : {
29753 1 : error_at (cloc, "expected %<unified_address%>, "
29754 : "%<unified_shared_memory%>, "
29755 : "%<self_maps%>, "
29756 : "%<dynamic_allocators%>, "
29757 : "%<reverse_offload%> "
29758 : "or %<atomic_default_mem_order%> clause");
29759 1 : c_parser_skip_to_pragma_eol (parser, false);
29760 1 : return;
29761 : }
29762 18 : if (p)
29763 55 : c_parser_consume_token (parser);
29764 73 : if (this_req)
29765 : {
29766 73 : if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29767 : {
29768 55 : if ((this_req & new_req) != 0)
29769 4 : error_at (cloc, "too many %qs clauses", p);
29770 55 : if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
29771 44 : && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
29772 4 : error_at (cloc, "%qs clause used lexically after first "
29773 : "target construct or offloading API", p);
29774 : }
29775 18 : else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29776 : {
29777 1 : error_at (cloc, "too many %qs clauses",
29778 : "atomic_default_mem_order");
29779 1 : this_req = (enum omp_requires) 0;
29780 : }
29781 17 : else if ((omp_requires_mask
29782 : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
29783 : {
29784 2 : error_at (cloc, "more than one %<atomic_default_mem_order%>"
29785 : " clause in a single compilation unit");
29786 2 : this_req
29787 2 : = (enum omp_requires)
29788 2 : (omp_requires_mask
29789 : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
29790 : }
29791 15 : else if ((omp_requires_mask
29792 : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
29793 1 : error_at (cloc, "%<atomic_default_mem_order%> clause used "
29794 : "lexically after first %<atomic%> construct "
29795 : "without memory order clause");
29796 73 : new_req = (enum omp_requires) (new_req | this_req);
29797 73 : omp_requires_mask
29798 73 : = (enum omp_requires) (omp_requires_mask | this_req);
29799 73 : continue;
29800 : }
29801 : }
29802 : break;
29803 : }
29804 56 : c_parser_skip_to_pragma_eol (parser);
29805 :
29806 56 : if (new_req == 0)
29807 1 : error_at (loc, "%<pragma omp requires%> requires at least one clause");
29808 : }
29809 :
29810 : /* Helper function for c_parser_omp_taskloop.
29811 : Disallow zero sized or potentially zero sized task reductions. */
29812 :
29813 : static tree
29814 413 : c_finish_taskloop_clauses (tree clauses)
29815 : {
29816 413 : tree *pc = &clauses;
29817 2064 : for (tree c = clauses; c; c = *pc)
29818 : {
29819 1651 : bool remove = false;
29820 1651 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
29821 : {
29822 143 : tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
29823 143 : if (integer_zerop (TYPE_SIZE_UNIT (type)))
29824 : {
29825 2 : error_at (OMP_CLAUSE_LOCATION (c),
29826 : "zero sized type %qT in %<reduction%> clause", type);
29827 2 : remove = true;
29828 : }
29829 141 : else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
29830 : {
29831 0 : error_at (OMP_CLAUSE_LOCATION (c),
29832 : "variable sized type %qT in %<reduction%> clause",
29833 : type);
29834 0 : remove = true;
29835 : }
29836 : }
29837 2 : if (remove)
29838 2 : *pc = OMP_CLAUSE_CHAIN (c);
29839 : else
29840 1649 : pc = &OMP_CLAUSE_CHAIN (c);
29841 : }
29842 413 : return clauses;
29843 : }
29844 :
29845 : /* OpenMP 4.5:
29846 : #pragma omp taskloop taskloop-clause[optseq] new-line
29847 : for-loop
29848 :
29849 : #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
29850 : for-loop */
29851 :
29852 : #define OMP_TASKLOOP_CLAUSE_MASK \
29853 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
29854 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
29855 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
29856 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
29857 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
29858 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
29859 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
29860 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
29861 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
29862 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
29863 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
29864 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
29865 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
29866 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
29867 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
29868 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
29869 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
29870 :
29871 : static tree
29872 418 : c_parser_omp_taskloop (location_t loc, c_parser *parser,
29873 : char *p_name, omp_clause_mask mask, tree *cclauses,
29874 : bool *if_p)
29875 : {
29876 418 : tree clauses, block, ret;
29877 :
29878 418 : strcat (p_name, " taskloop");
29879 418 : mask |= OMP_TASKLOOP_CLAUSE_MASK;
29880 : /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
29881 : clause. */
29882 418 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
29883 94 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
29884 :
29885 418 : if (c_parser_next_token_is (parser, CPP_NAME))
29886 : {
29887 342 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29888 :
29889 342 : if (strcmp (p, "simd") == 0)
29890 : {
29891 178 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
29892 178 : if (cclauses == NULL)
29893 84 : cclauses = cclauses_buf;
29894 178 : c_parser_consume_token (parser);
29895 178 : if (!flag_openmp) /* flag_openmp_simd */
29896 3 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
29897 3 : if_p);
29898 175 : block = c_begin_compound_stmt (true);
29899 175 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
29900 175 : block = c_end_compound_stmt (loc, block, true);
29901 175 : if (ret == NULL)
29902 : return ret;
29903 175 : ret = make_node (OMP_TASKLOOP);
29904 175 : TREE_TYPE (ret) = void_type_node;
29905 175 : OMP_FOR_BODY (ret) = block;
29906 175 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29907 175 : OMP_FOR_CLAUSES (ret)
29908 175 : = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
29909 175 : SET_EXPR_LOCATION (ret, loc);
29910 175 : add_stmt (ret);
29911 175 : return ret;
29912 : }
29913 : }
29914 240 : if (!flag_openmp) /* flag_openmp_simd */
29915 : {
29916 2 : c_parser_skip_to_pragma_eol (parser, false);
29917 2 : return NULL_TREE;
29918 : }
29919 :
29920 238 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
29921 238 : if (cclauses)
29922 : {
29923 66 : omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses);
29924 66 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29925 : }
29926 :
29927 238 : clauses = c_finish_taskloop_clauses (clauses);
29928 238 : block = c_begin_compound_stmt (true);
29929 238 : ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
29930 238 : block = c_end_compound_stmt (loc, block, true);
29931 238 : add_stmt (block);
29932 :
29933 238 : return ret;
29934 : }
29935 :
29936 : /* OpenMP 5.1: Parse sizes list for "omp tile sizes"
29937 : sizes ( size-expr-list ) */
29938 : static tree
29939 476 : c_parser_omp_tile_sizes (c_parser *parser, location_t loc)
29940 : {
29941 476 : tree sizes = NULL_TREE;
29942 :
29943 476 : if (c_parser_next_token_is (parser, CPP_COMMA))
29944 2 : c_parser_consume_token (parser);
29945 :
29946 476 : c_token *tok = c_parser_peek_token (parser);
29947 476 : if (tok->type != CPP_NAME
29948 476 : || strcmp ("sizes", IDENTIFIER_POINTER (tok->value)))
29949 : {
29950 1 : c_parser_error (parser, "expected %<sizes%>");
29951 1 : return error_mark_node;
29952 : }
29953 475 : c_parser_consume_token (parser);
29954 :
29955 475 : matching_parens parens;
29956 475 : if (!parens.require_open (parser))
29957 4 : return error_mark_node;
29958 :
29959 471 : vec<tree, va_gc> *sizes_vec
29960 471 : = c_parser_expr_list (parser, true, true, NULL, NULL, NULL, NULL);
29961 471 : sizes = build_tree_list_vec (sizes_vec);
29962 471 : release_tree_vector (sizes_vec);
29963 :
29964 1198 : for (tree s = sizes; s; s = TREE_CHAIN (s))
29965 : {
29966 734 : tree expr = TREE_VALUE (s);
29967 734 : if (expr == error_mark_node)
29968 : {
29969 7 : parens.skip_until_found_close (parser);
29970 7 : return error_mark_node;
29971 : }
29972 :
29973 727 : HOST_WIDE_INT n;
29974 1454 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
29975 724 : || !tree_fits_shwi_p (expr)
29976 722 : || (n = tree_to_shwi (expr)) <= 0
29977 1440 : || (int) n != n)
29978 : {
29979 14 : c_parser_error (parser, "%<sizes%> argument needs positive"
29980 : " integral constant");
29981 14 : TREE_VALUE (s) = integer_one_node;
29982 : }
29983 : }
29984 464 : parens.require_close (parser);
29985 :
29986 464 : gcc_assert (sizes);
29987 464 : tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES);
29988 464 : OMP_CLAUSE_SIZES_LIST (c) = sizes;
29989 :
29990 464 : return c;
29991 : }
29992 :
29993 : /* OpenMP 5.1:
29994 : #pragma omp tile sizes ( size-expr-list ) new-line
29995 : for-loop
29996 :
29997 : LOC is the location of the #pragma token. */
29998 :
29999 : static tree
30000 476 : c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p)
30001 : {
30002 476 : tree clauses = c_parser_omp_tile_sizes (parser, loc);
30003 476 : c_parser_skip_to_pragma_eol (parser);
30004 :
30005 476 : if (!clauses || clauses == error_mark_node)
30006 12 : return error_mark_node;
30007 :
30008 464 : tree block = c_begin_compound_stmt (true);
30009 464 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_TILE, clauses,
30010 : NULL, if_p);
30011 464 : block = c_end_compound_stmt (loc, block, true);
30012 464 : add_stmt (block);
30013 :
30014 464 : return ret;
30015 : }
30016 :
30017 : #define OMP_UNROLL_CLAUSE_MASK \
30018 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \
30019 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL))
30020 :
30021 : /* OpenMP 5.1
30022 : #pragma omp unroll unroll-clause[optseq] new-line
30023 : for-loop
30024 :
30025 : LOC is the location of the #pragma token. */
30026 :
30027 : static tree
30028 313 : c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p)
30029 : {
30030 313 : tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK,
30031 : "#pragma omp unroll", true);
30032 :
30033 313 : tree block = c_begin_compound_stmt (true);
30034 313 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_UNROLL, clauses,
30035 : NULL, if_p);
30036 313 : block = c_end_compound_stmt (loc, block, true);
30037 313 : add_stmt (block);
30038 :
30039 313 : return ret;
30040 : }
30041 :
30042 : /* OpenMP 5.1
30043 : #pragma omp nothing new-line */
30044 :
30045 : static void
30046 79 : c_parser_omp_nothing (c_parser *parser)
30047 : {
30048 79 : c_parser_consume_pragma (parser);
30049 79 : c_parser_skip_to_pragma_eol (parser);
30050 79 : }
30051 :
30052 : /* OpenMP 5.1
30053 : #pragma omp error clauses[optseq] new-line */
30054 :
30055 : static bool
30056 126 : c_parser_omp_error (c_parser *parser, enum pragma_context context)
30057 : {
30058 126 : int at_compilation = -1;
30059 126 : int severity_fatal = -1;
30060 126 : tree message = NULL_TREE;
30061 126 : bool bad = false;
30062 126 : location_t loc = c_parser_peek_token (parser)->location;
30063 :
30064 126 : c_parser_consume_pragma (parser);
30065 :
30066 463 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
30067 : {
30068 214 : if (c_parser_next_token_is (parser, CPP_COMMA)
30069 214 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
30070 21 : c_parser_consume_token (parser);
30071 :
30072 214 : if (!c_parser_next_token_is (parser, CPP_NAME))
30073 : break;
30074 :
30075 213 : const char *p
30076 213 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30077 213 : location_t cloc = c_parser_peek_token (parser)->location;
30078 213 : static const char *args[] = {
30079 : "execution", "compilation", "warning", "fatal"
30080 : };
30081 213 : int *v = NULL;
30082 213 : int idx = 0, n = -1;
30083 213 : tree m = NULL_TREE;
30084 :
30085 213 : if (!strcmp (p, "at"))
30086 : v = &at_compilation;
30087 127 : else if (!strcmp (p, "severity"))
30088 : {
30089 : v = &severity_fatal;
30090 : idx += 2;
30091 : }
30092 82 : else if (strcmp (p, "message"))
30093 : {
30094 2 : error_at (cloc,
30095 : "expected %<at%>, %<severity%> or %<message%> clause");
30096 2 : c_parser_skip_to_pragma_eol (parser, false);
30097 2 : return false;
30098 : }
30099 :
30100 211 : c_parser_consume_token (parser);
30101 :
30102 211 : matching_parens parens;
30103 211 : if (parens.require_open (parser))
30104 : {
30105 208 : if (v == NULL)
30106 : {
30107 79 : location_t expr_loc = c_parser_peek_token (parser)->location;
30108 79 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
30109 79 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
30110 79 : m = convert (const_string_type_node, expr.value);
30111 79 : m = c_fully_fold (m, false, NULL);
30112 : }
30113 : else
30114 : {
30115 129 : if (c_parser_next_token_is (parser, CPP_NAME))
30116 : {
30117 125 : tree val = c_parser_peek_token (parser)->value;
30118 125 : const char *q = IDENTIFIER_POINTER (val);
30119 :
30120 125 : if (!strcmp (q, args[idx]))
30121 : n = 0;
30122 41 : else if (!strcmp (q, args[idx + 1]))
30123 : n = 1;
30124 : }
30125 : if (n == -1)
30126 : {
30127 6 : error_at (c_parser_peek_token (parser)->location,
30128 6 : "expected %qs or %qs", args[idx], args[idx + 1]);
30129 6 : bad = true;
30130 6 : switch (c_parser_peek_token (parser)->type)
30131 : {
30132 : case CPP_EOF:
30133 : case CPP_PRAGMA_EOL:
30134 : case CPP_CLOSE_PAREN:
30135 : break;
30136 4 : default:
30137 4 : if (c_parser_peek_2nd_token (parser)->type
30138 : == CPP_CLOSE_PAREN)
30139 2 : c_parser_consume_token (parser);
30140 : break;
30141 : }
30142 : }
30143 : else
30144 123 : c_parser_consume_token (parser);
30145 : }
30146 :
30147 208 : parens.skip_until_found_close (parser);
30148 :
30149 208 : if (v == NULL)
30150 : {
30151 79 : if (message)
30152 : {
30153 1 : error_at (cloc, "too many %qs clauses", p);
30154 1 : bad = true;
30155 : }
30156 : else
30157 : message = m;
30158 : }
30159 129 : else if (n != -1)
30160 : {
30161 123 : if (*v != -1)
30162 : {
30163 2 : error_at (cloc, "too many %qs clauses", p);
30164 2 : bad = true;
30165 : }
30166 : else
30167 121 : *v = n;
30168 : }
30169 : }
30170 : else
30171 : bad = true;
30172 : }
30173 124 : c_parser_skip_to_pragma_eol (parser);
30174 124 : if (bad)
30175 : return true;
30176 :
30177 112 : if (at_compilation == -1)
30178 33 : at_compilation = 1;
30179 112 : if (severity_fatal == -1)
30180 74 : severity_fatal = 1;
30181 112 : if (!at_compilation)
30182 : {
30183 58 : if (context != pragma_compound)
30184 : {
30185 7 : error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
30186 : "may only be used in compound statements");
30187 7 : return true;
30188 : }
30189 51 : if (parser->omp_for_parse_state
30190 1 : && parser->omp_for_parse_state->in_intervening_code)
30191 : {
30192 1 : error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
30193 : "may not be used in intervening code");
30194 1 : parser->omp_for_parse_state->fail = true;
30195 1 : return true;
30196 : }
30197 50 : tree fndecl
30198 58 : = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
30199 : : BUILT_IN_GOMP_WARNING);
30200 50 : if (!message)
30201 4 : message = build_zero_cst (const_string_type_node);
30202 50 : tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
30203 : build_all_ones_cst (size_type_node));
30204 50 : add_stmt (stmt);
30205 50 : return true;
30206 : }
30207 54 : const char *msg = NULL;
30208 54 : if (message)
30209 : {
30210 27 : msg = c_getstr (message);
30211 27 : if (msg == NULL)
30212 6 : msg = _("<message unknown at compile time>");
30213 : }
30214 15 : const enum diagnostics::kind diag_kind = (severity_fatal
30215 54 : ? diagnostics::kind::error
30216 : : diagnostics::kind::warning);
30217 54 : if (msg)
30218 27 : emit_diagnostic (diag_kind, loc, 0,
30219 : "%<pragma omp error%> encountered: %s", msg);
30220 : else
30221 27 : emit_diagnostic (diag_kind, loc, 0,
30222 : "%<pragma omp error%> encountered");
30223 : return false;
30224 : }
30225 :
30226 : /* Assumption clauses
30227 : OpenMP 5.1:
30228 : absent (directive-name-list)
30229 : contains (directive-name-list)
30230 : holds (expression)
30231 : no_openmp
30232 : no_openmp_routines
30233 : no_parallelism
30234 :
30235 : OpenMP 6.0:
30236 : no_openmp_constructs */
30237 :
30238 : static void
30239 130 : c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
30240 : {
30241 130 : bool no_openmp = false;
30242 130 : bool no_openmp_constructs = false;
30243 130 : bool no_openmp_routines = false;
30244 130 : bool no_parallelism = false;
30245 130 : bitmap_head absent_head, contains_head;
30246 :
30247 130 : bitmap_obstack_initialize (NULL);
30248 130 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
30249 130 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
30250 :
30251 130 : if (c_parser_next_token_is (parser, CPP_PRAGMA_EOL))
30252 3 : error_at (c_parser_peek_token (parser)->location,
30253 : "expected at least one assumption clause");
30254 :
30255 359 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
30256 : {
30257 233 : if (c_parser_next_token_is (parser, CPP_COMMA)
30258 233 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
30259 53 : c_parser_consume_token (parser);
30260 :
30261 233 : if (!c_parser_next_token_is (parser, CPP_NAME))
30262 : break;
30263 :
30264 233 : const char *p
30265 233 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30266 233 : location_t cloc = c_parser_peek_token (parser)->location;
30267 :
30268 233 : if (!strcmp (p, "no_openmp"))
30269 : {
30270 18 : c_parser_consume_token (parser);
30271 18 : if (no_openmp)
30272 3 : error_at (cloc, "too many %qs clauses", "no_openmp");
30273 : no_openmp = true;
30274 : }
30275 215 : else if (!strcmp (p, "no_openmp_constructs"))
30276 : {
30277 4 : c_parser_consume_token (parser);
30278 4 : if (no_openmp_constructs)
30279 1 : error_at (cloc, "too many %qs clauses", "no_openmp_constructs");
30280 : no_openmp_constructs = true;
30281 : }
30282 211 : else if (!strcmp (p, "no_openmp_routines"))
30283 : {
30284 17 : c_parser_consume_token (parser);
30285 17 : if (no_openmp_routines)
30286 3 : error_at (cloc, "too many %qs clauses", "no_openmp_routines");
30287 : no_openmp_routines = true;
30288 : }
30289 194 : else if (!strcmp (p, "no_parallelism"))
30290 : {
30291 19 : c_parser_consume_token (parser);
30292 19 : if (no_parallelism)
30293 3 : error_at (cloc, "too many %qs clauses", "no_parallelism");
30294 : no_parallelism = true;
30295 : }
30296 175 : else if (!strcmp (p, "holds"))
30297 : {
30298 19 : c_parser_consume_token (parser);
30299 19 : matching_parens parens;
30300 19 : if (parens.require_open (parser))
30301 : {
30302 19 : location_t eloc = c_parser_peek_token (parser)->location;
30303 19 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
30304 19 : tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
30305 19 : t = c_objc_common_truthvalue_conversion (eloc, t);
30306 19 : t = c_fully_fold (t, false, NULL);
30307 19 : if (is_assume && t != error_mark_node)
30308 : {
30309 11 : tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
30310 : void_type_node, 1,
30311 : t);
30312 11 : add_stmt (fn);
30313 : }
30314 19 : parens.skip_until_found_close (parser);
30315 : }
30316 : }
30317 156 : else if (!strcmp (p, "absent") || !strcmp (p, "contains"))
30318 : {
30319 146 : c_parser_consume_token (parser);
30320 146 : matching_parens parens;
30321 146 : if (parens.require_open (parser))
30322 : {
30323 604 : do
30324 : {
30325 375 : const char *directive[3] = {};
30326 375 : int i;
30327 375 : location_t dloc = c_parser_peek_token (parser)->location;
30328 844 : for (i = 0; i < 3; i++)
30329 : {
30330 811 : tree id;
30331 811 : if (c_parser_peek_nth_token (parser, i + 1)->type
30332 : == CPP_NAME)
30333 457 : id = c_parser_peek_nth_token (parser, i + 1)->value;
30334 354 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
30335 : != RID_MAX)
30336 : {
30337 12 : enum rid rid
30338 12 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
30339 12 : id = ridpointers[rid];
30340 : }
30341 : else
30342 : break;
30343 469 : directive[i] = IDENTIFIER_POINTER (id);
30344 : }
30345 375 : if (i == 0)
30346 0 : error_at (dloc, "expected directive name");
30347 : else
30348 : {
30349 375 : const struct c_omp_directive *dir
30350 375 : = c_omp_categorize_directive (directive[0],
30351 : directive[1],
30352 : directive[2]);
30353 375 : if (dir
30354 372 : && dir->id != PRAGMA_OMP_END
30355 369 : && (dir->kind == C_OMP_DIR_DECLARATIVE
30356 365 : || dir->kind == C_OMP_DIR_INFORMATIONAL
30357 356 : || dir->kind == C_OMP_DIR_META))
30358 13 : error_at (dloc, "invalid OpenMP directive name in "
30359 : "%qs clause argument: declarative, "
30360 : "informational, and meta directives "
30361 : "not permitted", p);
30362 : else if (dir == NULL
30363 359 : || dir->id == PRAGMA_OMP_END
30364 356 : || (!dir->second && directive[1])
30365 347 : || (!dir->third && directive[2]))
30366 15 : error_at (dloc, "unknown OpenMP directive name in "
30367 : "%qs clause argument", p);
30368 : else
30369 : {
30370 347 : int id = dir - c_omp_directives;
30371 392 : if (bitmap_bit_p (p[0] == 'a' ? &contains_head
30372 : : &absent_head, id))
30373 18 : error_at (dloc, "%<%s%s%s%s%s%> directive "
30374 : "mentioned in both %<absent%> and "
30375 : "%<contains%> clauses",
30376 : directive[0],
30377 : directive[1] ? " " : "",
30378 : directive[1] ? directive[1] : "",
30379 : directive[2] ? " " : "",
30380 : directive[2] ? directive[2] : "");
30381 383 : else if (!bitmap_set_bit (p[0] == 'a'
30382 : ? &absent_head
30383 : : &contains_head, id))
30384 36 : error_at (dloc, "%<%s%s%s%s%s%> directive "
30385 : "mentioned multiple times in %qs "
30386 : "clauses",
30387 : directive[0],
30388 : directive[1] ? " " : "",
30389 : directive[1] ? directive[1] : "",
30390 : directive[2] ? " " : "",
30391 : directive[2] ? directive[2] : "", p);
30392 : }
30393 844 : for (; i; --i)
30394 469 : c_parser_consume_token (parser);
30395 : }
30396 375 : if (c_parser_next_token_is (parser, CPP_COMMA))
30397 229 : c_parser_consume_token (parser);
30398 : else
30399 : break;
30400 229 : }
30401 : while (1);
30402 146 : parens.skip_until_found_close (parser);
30403 : }
30404 146 : }
30405 10 : else if (startswith (p, "ext_"))
30406 : {
30407 6 : warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
30408 6 : c_parser_consume_token (parser);
30409 6 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
30410 : {
30411 3 : matching_parens parens;
30412 3 : parens.consume_open (parser);
30413 3 : c_parser_balanced_token_sequence (parser);
30414 3 : parens.require_close (parser);
30415 : }
30416 : }
30417 : else
30418 : {
30419 4 : c_parser_consume_token (parser);
30420 4 : error_at (cloc, "expected assumption clause");
30421 4 : break;
30422 : }
30423 : }
30424 130 : c_parser_skip_to_pragma_eol (parser);
30425 130 : }
30426 :
30427 : /* OpenMP 5.1
30428 : #pragma omp assume clauses[optseq] new-line */
30429 :
30430 : static void
30431 46 : c_parser_omp_assume (c_parser *parser, bool *if_p)
30432 : {
30433 46 : c_parser_omp_assumption_clauses (parser, true);
30434 46 : add_stmt (c_parser_omp_structured_block (parser, if_p));
30435 46 : }
30436 :
30437 : /* OpenMP 5.1
30438 : #pragma omp assumes clauses[optseq] new-line */
30439 :
30440 : static void
30441 38 : c_parser_omp_assumes (c_parser *parser)
30442 : {
30443 38 : c_parser_consume_pragma (parser);
30444 38 : c_parser_omp_assumption_clauses (parser, false);
30445 38 : }
30446 :
30447 : /* Helper function for c_parser_omp_metadirective. */
30448 :
30449 : static void
30450 58 : analyze_metadirective_body (c_parser *parser,
30451 : vec<c_token> &tokens,
30452 : vec<tree> &labels)
30453 : {
30454 58 : int nesting_depth = 0;
30455 58 : int bracket_depth = 0;
30456 58 : bool ignore_label = false;
30457 :
30458 : /* Read in the body tokens to the tokens for each candidate directive. */
30459 3242 : while (1)
30460 : {
30461 1650 : c_token *token = c_parser_peek_token (parser);
30462 1650 : bool stop = false;
30463 :
30464 1650 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
30465 0 : ignore_label = true;
30466 :
30467 1650 : switch (token->type)
30468 : {
30469 : case CPP_EOF:
30470 : break;
30471 531 : case CPP_NAME:
30472 531 : if (!ignore_label
30473 531 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
30474 0 : labels.safe_push (token->value);
30475 531 : goto add;
30476 21 : case CPP_OPEN_BRACE:
30477 21 : ++nesting_depth;
30478 21 : goto add;
30479 21 : case CPP_CLOSE_BRACE:
30480 21 : if (--nesting_depth == 0 && bracket_depth == 0)
30481 21 : stop = true;
30482 21 : goto add;
30483 85 : case CPP_OPEN_PAREN:
30484 85 : ++bracket_depth;
30485 85 : goto add;
30486 85 : case CPP_CLOSE_PAREN:
30487 85 : --bracket_depth;
30488 85 : goto add;
30489 9 : case CPP_COLON:
30490 9 : ignore_label = false;
30491 9 : goto add;
30492 185 : case CPP_SEMICOLON:
30493 185 : if (nesting_depth == 0 && bracket_depth == 0)
30494 50 : stop = true;
30495 185 : goto add;
30496 1650 : default:
30497 1650 : add:
30498 1650 : tokens.safe_push (*token);
30499 1650 : if (token->type == CPP_PRAGMA)
30500 5 : c_parser_consume_pragma (parser);
30501 1645 : else if (token->type == CPP_PRAGMA_EOL)
30502 5 : c_parser_skip_to_pragma_eol (parser);
30503 : else
30504 1640 : c_parser_consume_token (parser);
30505 1650 : if (stop)
30506 : break;
30507 1592 : continue;
30508 : }
30509 58 : break;
30510 1592 : }
30511 58 : }
30512 :
30513 : /* OpenMP 5.0:
30514 :
30515 : # pragma omp metadirective [clause[, clause]]
30516 : */
30517 :
30518 : static void
30519 110 : c_parser_omp_metadirective (c_parser *parser, bool *if_p)
30520 : {
30521 110 : static unsigned int metadirective_region_count = 0;
30522 :
30523 110 : tree ret;
30524 110 : auto_vec<c_token> directive_tokens;
30525 110 : auto_vec<c_token> body_tokens;
30526 110 : auto_vec<tree> body_labels;
30527 110 : auto_vec<const struct c_omp_directive *> directives;
30528 110 : auto_vec<tree> ctxs;
30529 110 : vec<struct omp_variant> candidates;
30530 110 : bool default_seen = false;
30531 110 : int directive_token_idx = 0;
30532 110 : tree standalone_body = NULL_TREE;
30533 110 : location_t pragma_loc = c_parser_peek_token (parser)->location;
30534 110 : bool requires_body = false;
30535 :
30536 110 : ret = make_node (OMP_METADIRECTIVE);
30537 110 : SET_EXPR_LOCATION (ret, pragma_loc);
30538 110 : TREE_TYPE (ret) = void_type_node;
30539 110 : OMP_METADIRECTIVE_VARIANTS (ret) = NULL_TREE;
30540 :
30541 110 : c_parser_consume_pragma (parser);
30542 418 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
30543 : {
30544 214 : if (c_parser_next_token_is (parser, CPP_COMMA))
30545 15 : c_parser_consume_token (parser);
30546 214 : if (c_parser_next_token_is_not (parser, CPP_NAME)
30547 278 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
30548 : {
30549 0 : c_parser_error (parser, "expected %<when%>, "
30550 : "%<otherwise%>, or %<default%> clause");
30551 0 : goto error;
30552 : }
30553 :
30554 214 : location_t match_loc = c_parser_peek_token (parser)->location;
30555 214 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
30556 214 : if (strcmp (p, "default") == 0)
30557 : {
30558 64 : gcc_rich_location richloc (pragma_loc);
30559 64 : richloc.add_fixit_replace (match_loc, "otherwise");
30560 64 : warning_at (&richloc, OPT_Wdeprecated_openmp,
30561 : "%<default%> clause on metadirectives deprecated since "
30562 : "OpenMP 5.2, use %<otherwise%>");
30563 64 : }
30564 214 : c_parser_consume_token (parser);
30565 428 : bool default_p
30566 214 : = strcmp (p, "default") == 0 || strcmp (p, "otherwise") == 0;
30567 133 : if (default_p)
30568 : {
30569 81 : if (default_seen)
30570 : {
30571 4 : error_at (match_loc, "too many %<otherwise%> or %<default%> "
30572 : "clauses in %<metadirective%>");
30573 4 : goto error;
30574 : }
30575 : default_seen = true;
30576 : }
30577 133 : else if (default_seen)
30578 : {
30579 2 : error_at (match_loc, "%<otherwise%> or %<default%> clause "
30580 : "must appear last in %<metadirective%>");
30581 2 : goto error;
30582 : }
30583 208 : if (!default_p && strcmp (p, "when") != 0)
30584 : {
30585 2 : error_at (match_loc, "%qs is not valid for %qs",
30586 : p, "metadirective");
30587 2 : goto error;
30588 : }
30589 :
30590 206 : matching_parens parens;
30591 206 : tree ctx = NULL_TREE;
30592 206 : bool skip = false;
30593 :
30594 206 : if (!parens.require_open (parser))
30595 0 : goto error;
30596 :
30597 206 : if (!default_p)
30598 : {
30599 129 : ctx = c_parser_omp_context_selector_specification (parser,
30600 : NULL_TREE);
30601 129 : if (ctx == error_mark_node)
30602 2 : goto error;
30603 127 : ctx = omp_check_context_selector (match_loc, ctx,
30604 : OMP_CTX_METADIRECTIVE);
30605 127 : if (ctx == error_mark_node)
30606 0 : goto error;
30607 :
30608 : /* Remove the selector from further consideration if it can be
30609 : evaluated as a non-match at this point. */
30610 127 : skip = (omp_context_selector_matches (ctx, NULL_TREE, false) == 0);
30611 :
30612 127 : if (c_parser_next_token_is_not (parser, CPP_COLON))
30613 : {
30614 2 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
30615 2 : goto error;
30616 : }
30617 125 : c_parser_consume_token (parser);
30618 : }
30619 :
30620 : /* Read in the directive type and create a dummy pragma token for
30621 : it. */
30622 202 : location_t loc = c_parser_peek_token (parser)->location;
30623 :
30624 202 : const char *directive[3] = {};
30625 202 : int i;
30626 561 : for (i = 0; i < 3; i++)
30627 : {
30628 541 : tree id;
30629 541 : if (c_parser_peek_nth_token (parser, i + 1)->type
30630 : == CPP_CLOSE_PAREN)
30631 : {
30632 118 : if (i == 0)
30633 2 : directive[i++] = "nothing";
30634 : break;
30635 : }
30636 423 : else if (c_parser_peek_nth_token (parser, i + 1)->type
30637 : == CPP_NAME)
30638 282 : id = c_parser_peek_nth_token (parser, i + 1)->value;
30639 141 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
30640 : != RID_MAX)
30641 : {
30642 77 : enum rid rid
30643 77 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
30644 77 : id = ridpointers[rid];
30645 : }
30646 : else
30647 : break;
30648 :
30649 359 : directive[i] = IDENTIFIER_POINTER (id);
30650 : }
30651 86 : if (i == 0)
30652 : {
30653 0 : error_at (loc, "expected directive name");
30654 0 : goto error;
30655 : }
30656 :
30657 202 : const struct c_omp_directive *omp_directive
30658 202 : = c_omp_categorize_directive (directive[0],
30659 : directive[1],
30660 202 : directive[2]);
30661 :
30662 202 : if (omp_directive == NULL)
30663 : {
30664 4 : for (int j = 0; j < i; j++)
30665 2 : c_parser_consume_token (parser);
30666 2 : c_parser_error (parser, "unknown directive name");
30667 2 : goto error;
30668 : }
30669 : else
30670 : {
30671 200 : int token_count = 0;
30672 200 : if (omp_directive->first) token_count++;
30673 200 : if (omp_directive->second) token_count++;
30674 200 : if (omp_directive->third) token_count++;
30675 400 : for (int j = 0; j < token_count; j++)
30676 200 : c_parser_consume_token (parser);
30677 : }
30678 200 : if (omp_directive->id == PRAGMA_OMP_METADIRECTIVE)
30679 : {
30680 2 : c_parser_error (parser,
30681 : "metadirectives cannot be used as variants of a "
30682 : "%<metadirective%>");
30683 2 : goto error;
30684 : }
30685 198 : if (omp_directive->kind == C_OMP_DIR_DECLARATIVE)
30686 : {
30687 0 : sorry_at (loc, "declarative directive variants of a "
30688 : "%<metadirective%> are not supported");
30689 0 : goto error;
30690 : }
30691 198 : if (omp_directive->kind == C_OMP_DIR_CONSTRUCT)
30692 117 : requires_body = true;
30693 :
30694 198 : if (!skip)
30695 : {
30696 163 : c_token pragma_token;
30697 163 : pragma_token.type = CPP_PRAGMA;
30698 163 : pragma_token.location = loc;
30699 163 : pragma_token.pragma_kind = (enum pragma_kind) omp_directive->id;
30700 :
30701 163 : directives.safe_push (omp_directive);
30702 163 : directive_tokens.safe_push (pragma_token);
30703 163 : ctxs.safe_push (ctx);
30704 : }
30705 :
30706 : /* Read in tokens for the directive clauses. */
30707 : int nesting_depth = 0;
30708 1484 : while (1)
30709 : {
30710 841 : c_token *token = c_parser_peek_token (parser);
30711 841 : switch (token->type)
30712 : {
30713 : case CPP_EOF:
30714 : case CPP_PRAGMA_EOL:
30715 : break;
30716 117 : case CPP_OPEN_PAREN:
30717 117 : ++nesting_depth;
30718 117 : goto add;
30719 313 : case CPP_CLOSE_PAREN:
30720 313 : if (nesting_depth-- == 0)
30721 : {
30722 196 : c_parser_consume_token (parser);
30723 196 : break;
30724 : }
30725 117 : goto add;
30726 643 : default:
30727 643 : add:
30728 643 : if (!skip)
30729 550 : directive_tokens.safe_push (*token);
30730 643 : c_parser_consume_token (parser);
30731 643 : continue;
30732 : }
30733 198 : break;
30734 643 : }
30735 :
30736 198 : if (!skip)
30737 : {
30738 163 : c_token eol_token;
30739 163 : memset (&eol_token, 0, sizeof (eol_token));
30740 163 : eol_token.type = CPP_PRAGMA_EOL;
30741 163 : directive_tokens.safe_push (eol_token);
30742 : }
30743 : }
30744 94 : c_parser_skip_to_pragma_eol (parser);
30745 :
30746 : /* If only one selector matches and it evaluates to 'omp nothing', no need to
30747 : proceed. */
30748 94 : if (ctxs.length () == 1)
30749 : {
30750 37 : tree ctx = ctxs[0];
30751 37 : if (ctx == NULL_TREE
30752 37 : || (omp_context_selector_matches (ctx, NULL_TREE, false) == 1
30753 13 : && directive_tokens[0].pragma_kind == PRAGMA_OMP_NOTHING))
30754 22 : return;
30755 : }
30756 :
30757 72 : if (!default_seen)
30758 : {
30759 : /* Add a default clause that evaluates to 'omp nothing'. */
30760 27 : const struct c_omp_directive *omp_directive
30761 27 : = c_omp_categorize_directive ("nothing", NULL, NULL);
30762 :
30763 27 : c_token pragma_token;
30764 27 : pragma_token.type = CPP_PRAGMA;
30765 27 : pragma_token.location = UNKNOWN_LOCATION;
30766 27 : pragma_token.pragma_kind = PRAGMA_OMP_NOTHING;
30767 :
30768 27 : directives.safe_push (omp_directive);
30769 27 : directive_tokens.safe_push (pragma_token);
30770 27 : ctxs.safe_push (NULL_TREE);
30771 :
30772 27 : c_token eol_token;
30773 27 : memset (&eol_token, 0, sizeof (eol_token));
30774 27 : eol_token.type = CPP_PRAGMA_EOL;
30775 27 : directive_tokens.safe_push (eol_token);
30776 : }
30777 :
30778 72 : if (requires_body)
30779 58 : analyze_metadirective_body (parser, body_tokens, body_labels);
30780 :
30781 : /* Process each candidate directive. */
30782 : unsigned i;
30783 : tree ctx;
30784 :
30785 234 : FOR_EACH_VEC_ELT (ctxs, i, ctx)
30786 : {
30787 162 : auto_vec<c_token> tokens;
30788 :
30789 : /* Add the directive tokens. */
30790 842 : do
30791 842 : tokens.safe_push (directive_tokens [directive_token_idx++]);
30792 842 : while (tokens.last ().type != CPP_PRAGMA_EOL);
30793 :
30794 : /* Add the body tokens. */
30795 162 : gcc_assert (requires_body || body_tokens.is_empty ());
30796 3670 : for (unsigned j = 0; j < body_tokens.length (); j++)
30797 3508 : tokens.safe_push (body_tokens[j]);
30798 :
30799 : /* Make sure nothing tries to read past the end of the tokens. */
30800 162 : c_token eof_token;
30801 162 : memset (&eof_token, 0, sizeof (eof_token));
30802 162 : eof_token.type = CPP_EOF;
30803 162 : tokens.safe_push (eof_token);
30804 162 : tokens.safe_push (eof_token);
30805 :
30806 162 : unsigned int old_tokens_avail = parser->tokens_avail;
30807 162 : c_token *old_tokens = parser->tokens;
30808 162 : struct omp_attribute_pragma_state *old_in_omp_attribute_pragma
30809 : = parser->in_omp_attribute_pragma;
30810 162 : struct omp_metadirective_parse_data *old_state
30811 : = parser->omp_metadirective_state;
30812 :
30813 162 : struct omp_metadirective_parse_data new_state;
30814 162 : new_state.body_labels = &body_labels;
30815 162 : new_state.region_num = ++metadirective_region_count;
30816 :
30817 162 : parser->tokens = tokens.address ();
30818 162 : parser->tokens_avail = tokens.length ();
30819 162 : parser->in_omp_attribute_pragma = NULL;
30820 162 : parser->omp_metadirective_state = &new_state;
30821 :
30822 162 : int prev_errorcount = errorcount;
30823 162 : tree directive = c_begin_compound_stmt (true);
30824 :
30825 162 : c_parser_pragma (parser, pragma_compound, if_p, NULL_TREE);
30826 162 : directive = c_end_compound_stmt (pragma_loc, directive, true);
30827 162 : bool standalone_p
30828 162 : = directives[i]->kind == C_OMP_DIR_STANDALONE
30829 162 : || directives[i]->kind == C_OMP_DIR_UTILITY;
30830 89 : if (standalone_p && requires_body)
30831 : {
30832 : /* Parsing standalone directives will not consume the body
30833 : tokens, so do that here. */
30834 53 : if (standalone_body == NULL_TREE)
30835 : {
30836 51 : standalone_body = push_stmt_list ();
30837 51 : c_parser_statement (parser, if_p); // TODO skip this
30838 51 : standalone_body = pop_stmt_list (standalone_body);
30839 : }
30840 : else
30841 2 : c_parser_skip_to_end_of_block_or_statement (parser, true);
30842 : }
30843 :
30844 162 : tree body = standalone_p ? standalone_body : NULL_TREE;
30845 162 : tree variant = make_omp_metadirective_variant (ctx, directive, body);
30846 324 : OMP_METADIRECTIVE_VARIANTS (ret)
30847 162 : = chainon (OMP_METADIRECTIVE_VARIANTS (ret), variant);
30848 :
30849 : /* Check that all valid tokens have been consumed if no parse errors
30850 : encountered. */
30851 162 : if (errorcount == prev_errorcount)
30852 : {
30853 160 : gcc_assert (parser->tokens_avail == 2);
30854 160 : gcc_assert (c_parser_next_token_is (parser, CPP_EOF));
30855 160 : gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF);
30856 : }
30857 :
30858 162 : parser->tokens = old_tokens;
30859 162 : parser->tokens_avail = old_tokens_avail;
30860 162 : parser->in_omp_attribute_pragma = old_in_omp_attribute_pragma;
30861 162 : parser->omp_metadirective_state = old_state;
30862 162 : }
30863 :
30864 : /* Try to resolve the metadirective early. */
30865 72 : candidates = omp_early_resolve_metadirective (ret);
30866 72 : if (!candidates.is_empty ())
30867 48 : ret = c_omp_expand_variant_construct (candidates);
30868 :
30869 72 : add_stmt (ret);
30870 72 : return;
30871 :
30872 16 : error:
30873 : /* Skip the metadirective pragma. Do not skip the metadirective body. */
30874 16 : if (parser->in_pragma)
30875 16 : c_parser_skip_to_pragma_eol (parser, false);
30876 110 : }
30877 :
30878 : /* Main entry point to parsing most OpenMP pragmas. */
30879 :
30880 : static void
30881 17271 : c_parser_omp_construct (c_parser *parser, bool *if_p)
30882 : {
30883 17271 : enum pragma_kind p_kind;
30884 17271 : location_t loc;
30885 17271 : tree stmt;
30886 17271 : char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
30887 17271 : omp_clause_mask mask (0);
30888 :
30889 17271 : loc = c_parser_peek_token (parser)->location;
30890 17271 : p_kind = c_parser_peek_token (parser)->pragma_kind;
30891 17271 : c_parser_consume_pragma (parser);
30892 :
30893 17271 : switch (p_kind)
30894 : {
30895 309 : case PRAGMA_OACC_ATOMIC:
30896 309 : c_parser_omp_atomic (loc, parser, true);
30897 2074 : return;
30898 137 : case PRAGMA_OACC_CACHE:
30899 137 : strcpy (p_name, "#pragma acc");
30900 137 : stmt = c_parser_oacc_cache (loc, parser);
30901 137 : break;
30902 497 : case PRAGMA_OACC_DATA:
30903 497 : stmt = c_parser_oacc_data (loc, parser, if_p);
30904 497 : break;
30905 23 : case PRAGMA_OACC_HOST_DATA:
30906 23 : stmt = c_parser_oacc_host_data (loc, parser, if_p);
30907 23 : break;
30908 2154 : case PRAGMA_OACC_KERNELS:
30909 2154 : case PRAGMA_OACC_PARALLEL:
30910 2154 : case PRAGMA_OACC_SERIAL:
30911 2154 : strcpy (p_name, "#pragma acc");
30912 2154 : stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
30913 2154 : break;
30914 1771 : case PRAGMA_OACC_LOOP:
30915 1771 : strcpy (p_name, "#pragma acc");
30916 1771 : stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
30917 1771 : break;
30918 86 : case PRAGMA_OACC_WAIT:
30919 86 : strcpy (p_name, "#pragma wait");
30920 86 : stmt = c_parser_oacc_wait (loc, parser, p_name);
30921 86 : break;
30922 1410 : case PRAGMA_OMP_ATOMIC:
30923 1410 : c_parser_omp_atomic (loc, parser, false);
30924 1410 : return;
30925 144 : case PRAGMA_OMP_CRITICAL:
30926 144 : stmt = c_parser_omp_critical (loc, parser, if_p);
30927 144 : break;
30928 1314 : case PRAGMA_OMP_DISTRIBUTE:
30929 1314 : strcpy (p_name, "#pragma omp");
30930 1314 : stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
30931 1314 : break;
30932 1817 : case PRAGMA_OMP_FOR:
30933 1817 : strcpy (p_name, "#pragma omp");
30934 1817 : stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
30935 1817 : break;
30936 158 : case PRAGMA_OMP_LOOP:
30937 158 : strcpy (p_name, "#pragma omp");
30938 158 : stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
30939 158 : break;
30940 70 : case PRAGMA_OMP_MASKED:
30941 70 : strcpy (p_name, "#pragma omp");
30942 70 : stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
30943 70 : break;
30944 137 : case PRAGMA_OMP_MASTER:
30945 137 : strcpy (p_name, "#pragma omp");
30946 137 : stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p,
30947 : UNKNOWN_LOCATION);
30948 137 : break;
30949 2490 : case PRAGMA_OMP_PARALLEL:
30950 2490 : strcpy (p_name, "#pragma omp");
30951 2490 : stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
30952 2490 : break;
30953 61 : case PRAGMA_OMP_SCOPE:
30954 61 : stmt = c_parser_omp_scope (loc, parser, if_p);
30955 61 : break;
30956 106 : case PRAGMA_OMP_SECTIONS:
30957 106 : strcpy (p_name, "#pragma omp");
30958 106 : stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
30959 106 : break;
30960 731 : case PRAGMA_OMP_SIMD:
30961 731 : strcpy (p_name, "#pragma omp");
30962 731 : stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
30963 731 : break;
30964 222 : case PRAGMA_OMP_SINGLE:
30965 222 : stmt = c_parser_omp_single (loc, parser, if_p);
30966 222 : break;
30967 898 : case PRAGMA_OMP_TASK:
30968 898 : stmt = c_parser_omp_task (loc, parser, if_p);
30969 898 : break;
30970 138 : case PRAGMA_OMP_TASKGROUP:
30971 138 : stmt = c_parser_omp_taskgroup (loc, parser, if_p);
30972 138 : break;
30973 256 : case PRAGMA_OMP_TASKLOOP:
30974 256 : strcpy (p_name, "#pragma omp");
30975 256 : stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
30976 256 : break;
30977 1926 : case PRAGMA_OMP_TEAMS:
30978 1926 : strcpy (p_name, "#pragma omp");
30979 1926 : stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
30980 1926 : break;
30981 46 : case PRAGMA_OMP_ASSUME:
30982 46 : c_parser_omp_assume (parser, if_p);
30983 46 : return;
30984 110 : case PRAGMA_OMP_TILE:
30985 110 : stmt = c_parser_omp_tile (loc, parser, if_p);
30986 110 : break;
30987 105 : case PRAGMA_OMP_UNROLL:
30988 105 : stmt = c_parser_omp_unroll (loc, parser, if_p);
30989 105 : break;
30990 155 : case PRAGMA_OMP_DISPATCH:
30991 155 : stmt = c_parser_omp_dispatch (loc, parser);
30992 155 : break;
30993 0 : default:
30994 0 : gcc_unreachable ();
30995 : }
30996 :
30997 15506 : if (stmt && stmt != error_mark_node)
30998 15197 : gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
30999 : }
31000 :
31001 : /* OpenMP 6.0:
31002 : # pragma omp groupprivate (variable-list) [device_type(...)] */
31003 :
31004 : #define OMP_GROUPPRIVATE_CLAUSE_MASK \
31005 : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) )
31006 :
31007 : static void
31008 9 : c_parser_omp_groupprivate (c_parser *parser)
31009 : {
31010 9 : location_t loc = c_parser_peek_token (parser)->location;
31011 9 : c_parser_consume_pragma (parser);
31012 9 : tree vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
31013 9 : tree clauses = c_parser_omp_all_clauses (parser, OMP_GROUPPRIVATE_CLAUSE_MASK,
31014 : "#pragma omp groupprivate");
31015 : /* TODO: Implies 'declare target local' with specified device_type, check for
31016 : conflicts. Check for other restrictions. */
31017 9 : (void) vars;
31018 9 : (void) clauses;
31019 9 : sorry_at (loc, "%<omp groupprivate%>");
31020 9 : }
31021 :
31022 : /* OpenMP 2.5:
31023 : # pragma omp threadprivate (variable-list) */
31024 :
31025 : static void
31026 78 : c_parser_omp_threadprivate (c_parser *parser)
31027 : {
31028 78 : tree vars, t;
31029 78 : location_t loc;
31030 :
31031 78 : c_parser_consume_pragma (parser);
31032 78 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
31033 :
31034 : /* Mark every variable in VARS to be assigned thread local storage. */
31035 167 : for (t = vars; t; t = TREE_CHAIN (t))
31036 : {
31037 89 : tree v = TREE_PURPOSE (t);
31038 89 : loc = EXPR_LOCATION (TREE_VALUE (t));
31039 :
31040 : /* If V had already been marked threadprivate, it doesn't matter
31041 : whether it had been used prior to this point. */
31042 89 : if (!VAR_P (v))
31043 1 : error_at (loc, "%qD is not a variable", v);
31044 88 : else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
31045 2 : error_at (loc, "%qE declared %<threadprivate%> after first use", v);
31046 86 : else if (! is_global_var (v))
31047 2 : error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
31048 84 : else if (TREE_TYPE (v) == error_mark_node)
31049 : ;
31050 83 : else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
31051 1 : error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
31052 : else
31053 : {
31054 82 : if (! DECL_THREAD_LOCAL_P (v))
31055 : {
31056 82 : set_decl_tls_model (v, decl_default_tls_model (v));
31057 : /* If rtl has been already set for this var, call
31058 : make_decl_rtl once again, so that encode_section_info
31059 : has a chance to look at the new decl flags. */
31060 82 : if (DECL_RTL_SET_P (v))
31061 0 : make_decl_rtl (v);
31062 : }
31063 82 : C_DECL_THREADPRIVATE_P (v) = 1;
31064 : }
31065 : }
31066 :
31067 78 : c_parser_skip_to_pragma_eol (parser);
31068 78 : }
31069 :
31070 : /* Parse a transaction attribute (GCC Extension).
31071 :
31072 : transaction-attribute:
31073 : gnu-attributes
31074 : attribute-specifier
31075 : */
31076 :
31077 : static tree
31078 139 : c_parser_transaction_attributes (c_parser *parser)
31079 : {
31080 139 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
31081 0 : return c_parser_gnu_attributes (parser);
31082 :
31083 139 : if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
31084 : return NULL_TREE;
31085 20 : return c_parser_std_attribute_specifier (parser, true);
31086 : }
31087 :
31088 : /* Parse a __transaction_atomic or __transaction_relaxed statement
31089 : (GCC Extension).
31090 :
31091 : transaction-statement:
31092 : __transaction_atomic transaction-attribute[opt] compound-statement
31093 : __transaction_relaxed compound-statement
31094 :
31095 : Note that the only valid attribute is: "outer".
31096 : */
31097 :
31098 : static tree
31099 137 : c_parser_transaction (c_parser *parser, enum rid keyword)
31100 : {
31101 137 : unsigned int old_in = parser->in_transaction;
31102 137 : unsigned int this_in = 1, new_in;
31103 137 : location_t loc = c_parser_peek_token (parser)->location;
31104 137 : tree stmt, attrs;
31105 :
31106 274 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
31107 : || keyword == RID_TRANSACTION_RELAXED)
31108 : && c_parser_next_token_is_keyword (parser, keyword));
31109 137 : c_parser_consume_token (parser);
31110 :
31111 137 : if (keyword == RID_TRANSACTION_RELAXED)
31112 : this_in |= TM_STMT_ATTR_RELAXED;
31113 : else
31114 : {
31115 106 : attrs = c_parser_transaction_attributes (parser);
31116 106 : if (attrs)
31117 14 : this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
31118 : }
31119 :
31120 : /* Keep track if we're in the lexical scope of an outer transaction. */
31121 137 : new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
31122 :
31123 137 : parser->in_transaction = new_in;
31124 137 : stmt = c_parser_compound_statement (parser);
31125 137 : parser->in_transaction = old_in;
31126 :
31127 137 : if (flag_tm)
31128 135 : stmt = c_finish_transaction (loc, stmt, this_in);
31129 : else
31130 2 : error_at (loc,
31131 : keyword == RID_TRANSACTION_ATOMIC
31132 : ? G_("%<__transaction_atomic%> without transactional memory "
31133 : "support enabled")
31134 : : G_("%<__transaction_relaxed%> without transactional memory "
31135 : "support enabled"));
31136 :
31137 137 : return stmt;
31138 : }
31139 :
31140 : /* Parse a __transaction_atomic or __transaction_relaxed expression
31141 : (GCC Extension).
31142 :
31143 : transaction-expression:
31144 : __transaction_atomic ( expression )
31145 : __transaction_relaxed ( expression )
31146 : */
31147 :
31148 : static struct c_expr
31149 7 : c_parser_transaction_expression (c_parser *parser, enum rid keyword)
31150 : {
31151 7 : struct c_expr ret;
31152 7 : unsigned int old_in = parser->in_transaction;
31153 7 : unsigned int this_in = 1;
31154 7 : location_t loc = c_parser_peek_token (parser)->location;
31155 7 : tree attrs;
31156 :
31157 14 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
31158 : || keyword == RID_TRANSACTION_RELAXED)
31159 : && c_parser_next_token_is_keyword (parser, keyword));
31160 7 : c_parser_consume_token (parser);
31161 :
31162 7 : if (keyword == RID_TRANSACTION_RELAXED)
31163 : this_in |= TM_STMT_ATTR_RELAXED;
31164 : else
31165 : {
31166 5 : attrs = c_parser_transaction_attributes (parser);
31167 5 : if (attrs)
31168 0 : this_in |= parse_tm_stmt_attr (attrs, 0);
31169 : }
31170 :
31171 7 : parser->in_transaction = this_in;
31172 7 : matching_parens parens;
31173 7 : if (parens.require_open (parser))
31174 : {
31175 7 : tree expr = c_parser_expression (parser).value;
31176 7 : ret.original_type = TREE_TYPE (expr);
31177 7 : ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
31178 7 : if (this_in & TM_STMT_ATTR_RELAXED)
31179 2 : TRANSACTION_EXPR_RELAXED (ret.value) = 1;
31180 7 : SET_EXPR_LOCATION (ret.value, loc);
31181 7 : ret.original_code = TRANSACTION_EXPR;
31182 7 : ret.m_decimal = 0;
31183 7 : if (!parens.require_close (parser))
31184 : {
31185 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
31186 0 : goto error;
31187 : }
31188 : }
31189 : else
31190 : {
31191 0 : error:
31192 0 : ret.set_error ();
31193 0 : ret.original_code = ERROR_MARK;
31194 0 : ret.original_type = NULL;
31195 : }
31196 7 : parser->in_transaction = old_in;
31197 :
31198 7 : if (!flag_tm)
31199 6 : error_at (loc,
31200 : keyword == RID_TRANSACTION_ATOMIC
31201 : ? G_("%<__transaction_atomic%> without transactional memory "
31202 : "support enabled")
31203 : : G_("%<__transaction_relaxed%> without transactional memory "
31204 : "support enabled"));
31205 :
31206 7 : set_c_expr_source_range (&ret, loc, loc);
31207 :
31208 7 : return ret;
31209 : }
31210 :
31211 : /* Parse a __transaction_cancel statement (GCC Extension).
31212 :
31213 : transaction-cancel-statement:
31214 : __transaction_cancel transaction-attribute[opt] ;
31215 :
31216 : Note that the only valid attribute is "outer".
31217 : */
31218 :
31219 : static tree
31220 28 : c_parser_transaction_cancel (c_parser *parser)
31221 : {
31222 28 : location_t loc = c_parser_peek_token (parser)->location;
31223 28 : tree attrs;
31224 28 : bool is_outer = false;
31225 :
31226 28 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
31227 28 : c_parser_consume_token (parser);
31228 :
31229 28 : attrs = c_parser_transaction_attributes (parser);
31230 28 : if (attrs)
31231 5 : is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
31232 :
31233 28 : if (!flag_tm)
31234 : {
31235 2 : error_at (loc, "%<__transaction_cancel%> without "
31236 : "transactional memory support enabled");
31237 2 : goto ret_error;
31238 : }
31239 26 : else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
31240 : {
31241 0 : error_at (loc, "%<__transaction_cancel%> within a "
31242 : "%<__transaction_relaxed%>");
31243 0 : goto ret_error;
31244 : }
31245 26 : else if (is_outer)
31246 : {
31247 5 : if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
31248 5 : && !is_tm_may_cancel_outer (current_function_decl))
31249 : {
31250 0 : error_at (loc, "outer %<__transaction_cancel%> not "
31251 : "within outer %<__transaction_atomic%> or "
31252 : "a %<transaction_may_cancel_outer%> function");
31253 0 : goto ret_error;
31254 : }
31255 : }
31256 21 : else if (parser->in_transaction == 0)
31257 : {
31258 0 : error_at (loc, "%<__transaction_cancel%> not within "
31259 : "%<__transaction_atomic%>");
31260 0 : goto ret_error;
31261 : }
31262 :
31263 26 : return add_stmt (build_tm_abort_call (loc, is_outer));
31264 :
31265 2 : ret_error:
31266 2 : return build1 (NOP_EXPR, void_type_node, error_mark_node);
31267 : }
31268 :
31269 : /* Parse a single source file. */
31270 :
31271 : void
31272 105368 : c_parse_file (void)
31273 : {
31274 : /* Use local storage to begin. If the first token is a pragma, parse it.
31275 : If it is #pragma GCC pch_preprocess, then this will load a PCH file
31276 : which will cause garbage collection. */
31277 105368 : c_parser tparser;
31278 :
31279 105368 : memset (&tparser, 0, sizeof tparser);
31280 105368 : tparser.translate_strings_p = true;
31281 105368 : tparser.tokens = &tparser.tokens_buf[0];
31282 105368 : the_parser = &tparser;
31283 :
31284 105368 : if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
31285 12 : c_parser_pragma_pch_preprocess (&tparser);
31286 : else
31287 105284 : c_common_no_more_pch ();
31288 :
31289 105296 : the_parser = ggc_alloc<c_parser> ();
31290 105296 : *the_parser = tparser;
31291 105296 : if (tparser.tokens == &tparser.tokens_buf[0])
31292 105296 : the_parser->tokens = &the_parser->tokens_buf[0];
31293 :
31294 : /* Initialize EH, if we've been told to do so. */
31295 105296 : if (flag_exceptions)
31296 511 : using_eh_for_cleanups ();
31297 :
31298 105296 : c_parser_translation_unit (the_parser);
31299 105206 : the_parser = NULL;
31300 105206 : }
31301 :
31302 : void
31303 5407 : c_init_preprocess (void)
31304 : {
31305 : /* Create a parser for use by pragma_lex during preprocessing. */
31306 5407 : the_parser = ggc_alloc<c_parser> ();
31307 5407 : memset (the_parser, 0, sizeof (c_parser));
31308 5407 : the_parser->tokens = &the_parser->tokens_buf[0];
31309 5407 : }
31310 :
31311 : /* Parse the body of a function declaration marked with "__RTL".
31312 :
31313 : The RTL parser works on the level of characters read from a
31314 : FILE *, whereas c_parser works at the level of tokens.
31315 : Square this circle by consuming all of the tokens up to and
31316 : including the closing brace, recording the start/end of the RTL
31317 : fragment, and reopening the file and re-reading the relevant
31318 : lines within the RTL parser.
31319 :
31320 : This requires the opening and closing braces of the C function
31321 : to be on separate lines from the RTL they wrap.
31322 :
31323 : Take ownership of START_WITH_PASS, if non-NULL. */
31324 :
31325 : location_t
31326 25 : c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
31327 : {
31328 25 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
31329 : {
31330 0 : free (start_with_pass);
31331 0 : return c_parser_peek_token (parser)->location;
31332 : }
31333 :
31334 25 : location_t start_loc = c_parser_peek_token (parser)->location;
31335 :
31336 : /* Consume all tokens, up to the closing brace, handling
31337 : matching pairs of braces in the rtl dump. */
31338 25 : int num_open_braces = 1;
31339 25239 : while (1)
31340 : {
31341 12632 : switch (c_parser_peek_token (parser)->type)
31342 : {
31343 1 : case CPP_OPEN_BRACE:
31344 1 : num_open_braces++;
31345 1 : break;
31346 25 : case CPP_CLOSE_BRACE:
31347 25 : if (--num_open_braces == 0)
31348 24 : goto found_closing_brace;
31349 : break;
31350 1 : case CPP_EOF:
31351 1 : error_at (start_loc, "no closing brace");
31352 1 : free (start_with_pass);
31353 1 : return c_parser_peek_token (parser)->location;
31354 : default:
31355 : break;
31356 : }
31357 12607 : c_parser_consume_token (parser);
31358 : }
31359 :
31360 24 : found_closing_brace:
31361 : /* At the closing brace; record its location. */
31362 24 : location_t end_loc = c_parser_peek_token (parser)->location;
31363 :
31364 : /* Consume the closing brace. */
31365 24 : c_parser_consume_token (parser);
31366 :
31367 : /* Invoke the RTL parser. */
31368 24 : if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
31369 : {
31370 0 : free (start_with_pass);
31371 0 : return end_loc;
31372 : }
31373 :
31374 : /* Run the backend on the cfun created above, transferring ownership of
31375 : START_WITH_PASS. */
31376 23 : run_rtl_passes (start_with_pass);
31377 23 : return end_loc;
31378 : }
31379 :
31380 : #include "gt-c-c-parser.h"
|