Branch data Line data Source code
1 : : /* Parser for C and Objective-C.
2 : : Copyright (C) 1987-2025 Free Software Foundation, Inc.
3 : :
4 : : Parser actions based on the old Bison parser; structure somewhat
5 : : influenced by and fragments based on the C++ parser.
6 : :
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 : 203079331 : set_c_expr_source_range (c_expr *expr,
92 : : location_t start, location_t finish)
93 : : {
94 : 203079331 : expr->src_range.m_start = start;
95 : 203079331 : expr->src_range.m_finish = finish;
96 : 203079331 : if (expr->value)
97 : 203079205 : set_source_range (expr->value, start, finish);
98 : 203079331 : }
99 : :
100 : : void
101 : 225425815 : set_c_expr_source_range (c_expr *expr,
102 : : source_range src_range)
103 : : {
104 : 225425815 : expr->src_range = src_range;
105 : 225425815 : if (expr->value)
106 : 225425810 : set_source_range (expr->value, src_range);
107 : 225425815 : }
108 : :
109 : :
110 : : /* Initialization routine for this file. */
111 : :
112 : : void
113 : 110990 : c_parse_init (void)
114 : : {
115 : : /* The only initialization required is of the reserved word
116 : : identifiers. */
117 : 110990 : unsigned int i;
118 : 110990 : tree id;
119 : 110990 : 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 : 110990 : gcc_assert (RID_MAX <= 255);
124 : :
125 : 110990 : mask |= D_CXXONLY;
126 : 110990 : if (!flag_isoc99)
127 : 6385 : mask |= D_C99;
128 : 110990 : if (!flag_isoc23)
129 : 12581 : mask |= D_C23;
130 : 110990 : if (flag_no_asm)
131 : : {
132 : 5519 : mask |= D_ASM | D_EXT;
133 : 5519 : if (!flag_isoc99)
134 : 3436 : mask |= D_EXT89;
135 : 5519 : if (!flag_isoc23)
136 : 4555 : mask |= D_EXT11;
137 : : }
138 : 110990 : if (!c_dialect_objc ())
139 : 110990 : mask |= D_OBJC | D_CXX_OBJC;
140 : :
141 : 110990 : ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
142 : 25416710 : 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 : 25305720 : if (c_common_reswords[i].disable & mask)
147 : : {
148 : 9719983 : if (warn_cxx_compat
149 : 108583 : && (c_common_reswords[i].disable & D_CXXWARN))
150 : : {
151 : 50751 : id = get_identifier (c_common_reswords[i].word);
152 : 50751 : C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
153 : 50751 : C_IS_RESERVED_WORD (id) = 1;
154 : : }
155 : 9719983 : continue;
156 : : }
157 : :
158 : 15585737 : id = get_identifier (c_common_reswords[i].word);
159 : 15585737 : C_SET_RID_CODE (id, c_common_reswords[i].rid);
160 : 15585737 : C_IS_RESERVED_WORD (id) = 1;
161 : 15585737 : ridpointers [(int) c_common_reswords[i].rid] = id;
162 : : }
163 : :
164 : 221980 : for (i = 0; i < NUM_INT_N_ENTS; i++)
165 : : {
166 : : /* We always create the symbols but they aren't always supported. */
167 : 110990 : char name[50];
168 : 110990 : sprintf (name, "__int%d", int_n_data[i].bitsize);
169 : 110990 : id = get_identifier (name);
170 : 110990 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
171 : 110990 : C_IS_RESERVED_WORD (id) = 1;
172 : :
173 : 110990 : sprintf (name, "__int%d__", int_n_data[i].bitsize);
174 : 110990 : id = get_identifier (name);
175 : 110990 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
176 : 110990 : C_IS_RESERVED_WORD (id) = 1;
177 : : }
178 : :
179 : 110990 : if (flag_openmp)
180 : : {
181 : 2175 : id = get_identifier ("omp_all_memory");
182 : 2175 : C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
183 : 2175 : C_IS_RESERVED_WORD (id) = 1;
184 : 2175 : ridpointers [RID_OMP_ALL_MEMORY] = id;
185 : : }
186 : 110990 : }
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 : : /* Return a pointer to the Nth token in PARSERs tokens_buf. */
290 : :
291 : : c_token *
292 : 195 : c_parser_tokens_buf (c_parser *parser, unsigned n)
293 : : {
294 : 195 : return &parser->tokens_buf[n];
295 : : }
296 : :
297 : : /* Return the error state of PARSER. */
298 : :
299 : : bool
300 : 3907 : c_parser_error (c_parser *parser)
301 : : {
302 : 3907 : return parser->error;
303 : : }
304 : :
305 : : /* Set the error state of PARSER to ERR. */
306 : :
307 : : void
308 : 0 : c_parser_set_error (c_parser *parser, bool err)
309 : : {
310 : 0 : parser->error = err;
311 : 0 : }
312 : :
313 : :
314 : : /* The actual parser and external interface. ??? Does this need to be
315 : : garbage-collected? */
316 : :
317 : : static GTY (()) c_parser *the_parser;
318 : :
319 : : /* Read in and lex a single token, storing it in *TOKEN. If RAW,
320 : : context-sensitive postprocessing of the token is not done. */
321 : :
322 : : static void
323 : 2251799642 : c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
324 : : {
325 : 2251799642 : timevar_push (TV_LEX);
326 : :
327 : 2251799642 : if (raw || vec_safe_length (parser->raw_tokens) == 0)
328 : : {
329 : 2251745744 : token->type = c_lex_with_flags (&token->value, &token->location,
330 : : &token->flags,
331 : 2251745744 : (parser->lex_joined_string
332 : : ? 0 : C_LEX_STRING_NO_JOIN));
333 : 2251745596 : token->id_kind = C_ID_NONE;
334 : 2251745596 : token->keyword = RID_MAX;
335 : 2251745596 : token->pragma_kind = PRAGMA_NONE;
336 : : }
337 : : else
338 : : {
339 : : /* Use a token previously lexed as a raw look-ahead token, and
340 : : complete the processing on it. */
341 : 53898 : *token = (*parser->raw_tokens)[parser->raw_tokens_used];
342 : 53898 : ++parser->raw_tokens_used;
343 : 53898 : if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
344 : : {
345 : 11192 : vec_free (parser->raw_tokens);
346 : 11192 : parser->raw_tokens_used = 0;
347 : : }
348 : : }
349 : :
350 : 2251799494 : if (raw)
351 : 53898 : goto out;
352 : :
353 : 2251745596 : switch (token->type)
354 : : {
355 : 1012093852 : case CPP_NAME:
356 : 1012093852 : {
357 : 1012093852 : tree decl;
358 : :
359 : 1012093852 : bool objc_force_identifier = parser->objc_need_raw_identifier;
360 : 1012093852 : if (c_dialect_objc ())
361 : 0 : parser->objc_need_raw_identifier = false;
362 : :
363 : 1012093852 : if (C_IS_RESERVED_WORD (token->value))
364 : : {
365 : 279732469 : enum rid rid_code = C_RID_CODE (token->value);
366 : :
367 : 279732469 : if (rid_code == RID_CXX_COMPAT_WARN)
368 : : {
369 : 35 : warning_at (token->location,
370 : 35 : OPT_Wc___compat,
371 : : "identifier %qE conflicts with C++ keyword",
372 : : token->value);
373 : : }
374 : 279732434 : else if (rid_code >= RID_FIRST_ADDR_SPACE
375 : 279732434 : && rid_code <= RID_LAST_ADDR_SPACE)
376 : : {
377 : 174 : addr_space_t as;
378 : 174 : as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
379 : 174 : targetm.addr_space.diagnose_usage (as, token->location);
380 : 174 : token->id_kind = C_ID_ADDRSPACE;
381 : 174 : token->keyword = rid_code;
382 : 174 : break;
383 : : }
384 : 279732260 : else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
385 : : {
386 : : /* We found an Objective-C "pq" keyword (in, out,
387 : : inout, bycopy, byref, oneway). They need special
388 : : care because the interpretation depends on the
389 : : context. */
390 : 0 : if (parser->objc_pq_context)
391 : : {
392 : 0 : token->type = CPP_KEYWORD;
393 : 0 : token->keyword = rid_code;
394 : 0 : break;
395 : : }
396 : 0 : else if (parser->objc_could_be_foreach_context
397 : 0 : && rid_code == RID_IN)
398 : : {
399 : : /* We are in Objective-C, inside a (potential)
400 : : foreach context (which means after having
401 : : parsed 'for (', but before having parsed ';'),
402 : : and we found 'in'. We consider it the keyword
403 : : which terminates the declaration at the
404 : : beginning of a foreach-statement. Note that
405 : : this means you can't use 'in' for anything else
406 : : in that context; in particular, in Objective-C
407 : : you can't use 'in' as the name of the running
408 : : variable in a C for loop. We could potentially
409 : : try to add code here to disambiguate, but it
410 : : seems a reasonable limitation. */
411 : 0 : token->type = CPP_KEYWORD;
412 : 0 : token->keyword = rid_code;
413 : 0 : break;
414 : : }
415 : : /* Else, "pq" keywords outside of the "pq" context are
416 : : not keywords, and we fall through to the code for
417 : : normal tokens. */
418 : : }
419 : 279732260 : else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
420 : : {
421 : : /* We found an Objective-C "property attribute"
422 : : keyword (getter, setter, readonly, etc). These are
423 : : only valid in the property context. */
424 : 0 : if (parser->objc_property_attr_context)
425 : : {
426 : 0 : token->type = CPP_KEYWORD;
427 : 0 : token->keyword = rid_code;
428 : 0 : break;
429 : : }
430 : : /* Else they are not special keywords.
431 : : */
432 : : }
433 : 279732260 : else if (c_dialect_objc ()
434 : 0 : && (OBJC_IS_AT_KEYWORD (rid_code)
435 : : || OBJC_IS_CXX_KEYWORD (rid_code)))
436 : : {
437 : : /* We found one of the Objective-C "@" keywords (defs,
438 : : selector, synchronized, etc) or one of the
439 : : Objective-C "cxx" keywords (class, private,
440 : : protected, public, try, catch, throw) without a
441 : : preceding '@' sign. Do nothing and fall through to
442 : : the code for normal tokens (in C++ we would still
443 : : consider the CXX ones keywords, but not in C). */
444 : : ;
445 : : }
446 : : else
447 : : {
448 : 279732260 : token->type = CPP_KEYWORD;
449 : 279732260 : token->keyword = rid_code;
450 : 279732260 : break;
451 : : }
452 : : }
453 : :
454 : 732361418 : decl = lookup_name (token->value);
455 : 732361418 : if (decl)
456 : : {
457 : 411064907 : if (TREE_CODE (decl) == TYPE_DECL)
458 : : {
459 : 239396836 : token->id_kind = C_ID_TYPENAME;
460 : 239396836 : break;
461 : : }
462 : : }
463 : 321296511 : else if (c_dialect_objc ())
464 : : {
465 : 0 : tree objc_interface_decl = objc_is_class_name (token->value);
466 : : /* Objective-C class names are in the same namespace as
467 : : variables and typedefs, and hence are shadowed by local
468 : : declarations. */
469 : 0 : if (objc_interface_decl
470 : 0 : && (!objc_force_identifier || global_bindings_p ()))
471 : : {
472 : 0 : token->value = objc_interface_decl;
473 : 0 : token->id_kind = C_ID_CLASSNAME;
474 : 0 : break;
475 : : }
476 : : }
477 : 492964582 : token->id_kind = C_ID_ID;
478 : : }
479 : 492964582 : break;
480 : 0 : case CPP_AT_NAME:
481 : : /* This only happens in Objective-C; it must be a keyword. */
482 : 0 : token->type = CPP_KEYWORD;
483 : 0 : switch (C_RID_CODE (token->value))
484 : : {
485 : : /* Replace 'class' with '@class', 'private' with '@private',
486 : : etc. This prevents confusion with the C++ keyword
487 : : 'class', and makes the tokens consistent with other
488 : : Objective-C 'AT' keywords. For example '@class' is
489 : : reported as RID_AT_CLASS which is consistent with
490 : : '@synchronized', which is reported as
491 : : RID_AT_SYNCHRONIZED.
492 : : */
493 : 0 : case RID_CLASS: token->keyword = RID_AT_CLASS; break;
494 : 0 : case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
495 : 0 : case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
496 : 0 : case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
497 : 0 : case RID_THROW: token->keyword = RID_AT_THROW; break;
498 : 0 : case RID_TRY: token->keyword = RID_AT_TRY; break;
499 : 0 : case RID_CATCH: token->keyword = RID_AT_CATCH; break;
500 : 0 : case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
501 : 0 : default: token->keyword = C_RID_CODE (token->value);
502 : : }
503 : : break;
504 : 679271070 : case CPP_COLON:
505 : 679271070 : case CPP_COMMA:
506 : 679271070 : case CPP_CLOSE_PAREN:
507 : 679271070 : case CPP_SEMICOLON:
508 : : /* These tokens may affect the interpretation of any identifiers
509 : : following, if doing Objective-C. */
510 : 679271070 : if (c_dialect_objc ())
511 : 0 : parser->objc_need_raw_identifier = false;
512 : : break;
513 : 1946826 : case CPP_PRAGMA:
514 : : /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
515 : 1946826 : token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
516 : 1946826 : token->value = NULL;
517 : 1946826 : break;
518 : : default:
519 : : break;
520 : : }
521 : 2251799494 : out:
522 : 2251799494 : timevar_pop (TV_LEX);
523 : 2251799494 : }
524 : :
525 : : /* Return a pointer to the next token from PARSER, reading it in if
526 : : necessary. */
527 : :
528 : : c_token *
529 : 17158497211 : c_parser_peek_token (c_parser *parser)
530 : : {
531 : 17158497211 : if (parser->tokens_avail == 0)
532 : : {
533 : 1846081587 : c_lex_one_token (parser, &parser->tokens[0]);
534 : 1846081439 : parser->tokens_avail = 1;
535 : : }
536 : 17158497063 : return &parser->tokens[0];
537 : : }
538 : :
539 : : /* Return a pointer to the next-but-one token from PARSER, reading it
540 : : in if necessary. The next token is already read in. */
541 : :
542 : : c_token *
543 : 177582404 : c_parser_peek_2nd_token (c_parser *parser)
544 : : {
545 : 177582404 : if (parser->tokens_avail >= 2)
546 : 29965319 : return &parser->tokens[1];
547 : 147617085 : gcc_assert (parser->tokens_avail == 1);
548 : 147617085 : gcc_assert (parser->tokens[0].type != CPP_EOF);
549 : 147617085 : gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
550 : 147617085 : c_lex_one_token (parser, &parser->tokens[1]);
551 : 147617085 : parser->tokens_avail = 2;
552 : 147617085 : return &parser->tokens[1];
553 : : }
554 : :
555 : : /* Return a pointer to the Nth token from PARSER, reading it
556 : : in if necessary. The N-1th token is already read in. */
557 : :
558 : : c_token *
559 : 867909858 : c_parser_peek_nth_token (c_parser *parser, unsigned int n)
560 : : {
561 : : /* N is 1-based, not zero-based. */
562 : 867909858 : gcc_assert (n > 0);
563 : :
564 : 867909858 : if (parser->tokens_avail >= n)
565 : 609862786 : return &parser->tokens[n - 1];
566 : 258047072 : gcc_assert (parser->tokens_avail == n - 1);
567 : 258047072 : c_lex_one_token (parser, &parser->tokens[n - 1]);
568 : 258047072 : parser->tokens_avail = n;
569 : 258047072 : return &parser->tokens[n - 1];
570 : : }
571 : :
572 : : /* Return a pointer to the Nth token from PARSER, reading it in as a
573 : : raw look-ahead token if necessary. The N-1th token is already read
574 : : in. Raw look-ahead tokens remain available for when the non-raw
575 : : functions above are called. */
576 : :
577 : : c_token *
578 : 70103 : c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
579 : : {
580 : : /* N is 1-based, not zero-based. */
581 : 70103 : gcc_assert (n > 0);
582 : :
583 : 70103 : if (parser->tokens_avail >= n)
584 : 10272 : return &parser->tokens[n - 1];
585 : 59831 : unsigned int raw_len = vec_safe_length (parser->raw_tokens);
586 : 59831 : unsigned int raw_avail
587 : 59831 : = parser->tokens_avail + raw_len - parser->raw_tokens_used;
588 : 59831 : gcc_assert (raw_avail >= n - 1);
589 : 59831 : if (raw_avail >= n)
590 : 5933 : return &(*parser->raw_tokens)[parser->raw_tokens_used
591 : 5933 : + n - 1 - parser->tokens_avail];
592 : 53898 : vec_safe_reserve (parser->raw_tokens, 1);
593 : 53898 : parser->raw_tokens->quick_grow (raw_len + 1);
594 : 53898 : c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
595 : 53898 : return &(*parser->raw_tokens)[raw_len];
596 : : }
597 : :
598 : : bool
599 : 43657017 : c_keyword_starts_typename (enum rid keyword)
600 : : {
601 : 43657017 : switch (keyword)
602 : : {
603 : : case RID_UNSIGNED:
604 : : case RID_LONG:
605 : : case RID_SHORT:
606 : : case RID_SIGNED:
607 : : case RID_COMPLEX:
608 : : case RID_INT:
609 : : case RID_CHAR:
610 : : case RID_FLOAT:
611 : : case RID_DOUBLE:
612 : : case RID_VOID:
613 : : case RID_DFLOAT32:
614 : : case RID_DFLOAT64:
615 : : case RID_DFLOAT128:
616 : : case RID_DFLOAT64X:
617 : : CASE_RID_FLOATN_NX:
618 : : case RID_BOOL:
619 : : case RID_BITINT:
620 : : case RID_ENUM:
621 : : case RID_STRUCT:
622 : : case RID_UNION:
623 : : case RID_TYPEOF:
624 : : case RID_TYPEOF_UNQUAL:
625 : : case RID_CONST:
626 : : case RID_ATOMIC:
627 : : case RID_VOLATILE:
628 : : case RID_RESTRICT:
629 : : case RID_ATTRIBUTE:
630 : : case RID_FRACT:
631 : : case RID_ACCUM:
632 : : case RID_SAT:
633 : : case RID_AUTO_TYPE:
634 : : case RID_ALIGNAS:
635 : : return true;
636 : 35737163 : default:
637 : 35737163 : if (keyword >= RID_FIRST_INT_N
638 : : && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
639 : 496 : && int_n_enabled_p[keyword - RID_FIRST_INT_N])
640 : : return true;
641 : : return false;
642 : : }
643 : : }
644 : :
645 : : /* Return true if TOKEN can start a type name,
646 : : false otherwise. */
647 : : bool
648 : 436843154 : c_token_starts_typename (c_token *token)
649 : : {
650 : 436843154 : switch (token->type)
651 : : {
652 : 386754615 : case CPP_NAME:
653 : 386754615 : switch (token->id_kind)
654 : : {
655 : : case C_ID_ID:
656 : : return false;
657 : : case C_ID_ADDRSPACE:
658 : : return true;
659 : : case C_ID_TYPENAME:
660 : : return true;
661 : 0 : case C_ID_CLASSNAME:
662 : 0 : gcc_assert (c_dialect_objc ());
663 : : return true;
664 : 0 : default:
665 : 0 : gcc_unreachable ();
666 : : }
667 : 43603209 : case CPP_KEYWORD:
668 : 43603209 : return c_keyword_starts_typename (token->keyword);
669 : 0 : case CPP_LESS:
670 : 0 : if (c_dialect_objc ())
671 : : return true;
672 : : return false;
673 : : default:
674 : : return false;
675 : : }
676 : : }
677 : :
678 : : /* Return true if the next token from PARSER can start a type name,
679 : : false otherwise. LA specifies how to do lookahead in order to
680 : : detect unknown type names. If unsure, pick CLA_PREFER_ID. */
681 : :
682 : : static inline bool
683 : 311215064 : c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
684 : : {
685 : 311215064 : c_token *token = c_parser_peek_token (parser);
686 : 311215064 : if (c_token_starts_typename (token))
687 : : return true;
688 : :
689 : : /* Try a bit harder to detect an unknown typename. */
690 : 68105100 : if (la != cla_prefer_id
691 : 43304624 : && token->type == CPP_NAME
692 : 6340602 : && token->id_kind == C_ID_ID
693 : :
694 : : /* Do not try too hard when we could have "object in array". */
695 : 6340602 : && !parser->objc_could_be_foreach_context
696 : :
697 : 6340602 : && (la == cla_prefer_type
698 : 6340511 : || c_parser_peek_2nd_token (parser)->type == CPP_NAME
699 : 6340427 : || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
700 : :
701 : : /* Only unknown identifiers. */
702 : 68106532 : && !lookup_name (token->value))
703 : : return true;
704 : :
705 : : return false;
706 : : }
707 : :
708 : : /* Return true if TOKEN, after an open parenthesis, can start a
709 : : compound literal (either a storage class specifier allowed in that
710 : : context, or a type name), false otherwise. */
711 : : static bool
712 : 125624391 : c_token_starts_compound_literal (c_token *token)
713 : : {
714 : 125624391 : switch (token->type)
715 : : {
716 : 4429794 : case CPP_KEYWORD:
717 : 4429794 : switch (token->keyword)
718 : : {
719 : : case RID_CONSTEXPR:
720 : : case RID_REGISTER:
721 : : case RID_STATIC:
722 : : case RID_THREAD:
723 : : return true;
724 : : default:
725 : : break;
726 : : }
727 : : /* Fall through. */
728 : 125624102 : default:
729 : 125624102 : return c_token_starts_typename (token);
730 : : }
731 : : }
732 : :
733 : : /* Return true if TOKEN is a type qualifier, false otherwise. */
734 : : static bool
735 : 424714724 : c_token_is_qualifier (c_token *token)
736 : : {
737 : 424714724 : switch (token->type)
738 : : {
739 : 420951004 : case CPP_NAME:
740 : 420951004 : switch (token->id_kind)
741 : : {
742 : : case C_ID_ADDRSPACE:
743 : : return true;
744 : : default:
745 : : return false;
746 : : }
747 : 3763720 : case CPP_KEYWORD:
748 : 3763720 : switch (token->keyword)
749 : : {
750 : : case RID_CONST:
751 : : case RID_VOLATILE:
752 : : case RID_RESTRICT:
753 : : case RID_ATTRIBUTE:
754 : : case RID_ATOMIC:
755 : : return true;
756 : : default:
757 : : return false;
758 : : }
759 : : case CPP_LESS:
760 : : return false;
761 : 0 : default:
762 : 0 : gcc_unreachable ();
763 : : }
764 : : }
765 : :
766 : : /* Return true if the next token from PARSER is a type qualifier,
767 : : false otherwise. */
768 : : static inline bool
769 : 424714724 : c_parser_next_token_is_qualifier (c_parser *parser)
770 : : {
771 : 424714724 : c_token *token = c_parser_peek_token (parser);
772 : 424714724 : return c_token_is_qualifier (token);
773 : : }
774 : :
775 : : /* Return true if TOKEN can start declaration specifiers (not
776 : : including standard attributes), false otherwise. */
777 : : static bool
778 : 171033252 : c_token_starts_declspecs (c_token *token)
779 : : {
780 : 171033252 : switch (token->type)
781 : : {
782 : 95747497 : case CPP_NAME:
783 : 95747497 : switch (token->id_kind)
784 : : {
785 : : case C_ID_ID:
786 : : return false;
787 : : case C_ID_ADDRSPACE:
788 : : return true;
789 : : case C_ID_TYPENAME:
790 : : return true;
791 : 0 : case C_ID_CLASSNAME:
792 : 0 : gcc_assert (c_dialect_objc ());
793 : : return true;
794 : 0 : default:
795 : 0 : gcc_unreachable ();
796 : : }
797 : 73633285 : case CPP_KEYWORD:
798 : 73633285 : switch (token->keyword)
799 : : {
800 : : case RID_STATIC:
801 : : case RID_EXTERN:
802 : : case RID_REGISTER:
803 : : case RID_TYPEDEF:
804 : : case RID_INLINE:
805 : : case RID_NORETURN:
806 : : case RID_AUTO:
807 : : case RID_THREAD:
808 : : case RID_UNSIGNED:
809 : : case RID_LONG:
810 : : case RID_SHORT:
811 : : case RID_SIGNED:
812 : : case RID_COMPLEX:
813 : : case RID_INT:
814 : : case RID_CHAR:
815 : : case RID_FLOAT:
816 : : case RID_DOUBLE:
817 : : case RID_VOID:
818 : : case RID_DFLOAT32:
819 : : case RID_DFLOAT64:
820 : : case RID_DFLOAT128:
821 : : case RID_DFLOAT64X:
822 : : CASE_RID_FLOATN_NX:
823 : : case RID_BOOL:
824 : : case RID_BITINT:
825 : : case RID_ENUM:
826 : : case RID_STRUCT:
827 : : case RID_UNION:
828 : : case RID_TYPEOF:
829 : : case RID_TYPEOF_UNQUAL:
830 : : case RID_CONST:
831 : : case RID_VOLATILE:
832 : : case RID_RESTRICT:
833 : : case RID_ATTRIBUTE:
834 : : case RID_FRACT:
835 : : case RID_ACCUM:
836 : : case RID_SAT:
837 : : case RID_ALIGNAS:
838 : : case RID_ATOMIC:
839 : : case RID_AUTO_TYPE:
840 : : case RID_CONSTEXPR:
841 : : return true;
842 : 35396928 : default:
843 : 35396928 : if (token->keyword >= RID_FIRST_INT_N
844 : : && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
845 : 411 : && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
846 : : return true;
847 : : return false;
848 : : }
849 : 2 : case CPP_LESS:
850 : 2 : if (c_dialect_objc ())
851 : : return true;
852 : : return false;
853 : : default:
854 : : return false;
855 : : }
856 : : }
857 : :
858 : :
859 : : /* Return true if TOKEN can start declaration specifiers (not
860 : : including standard attributes) or a static assertion, false
861 : : otherwise. */
862 : : static bool
863 : 49878315 : c_token_starts_declaration (c_token *token)
864 : : {
865 : 49878315 : if (c_token_starts_declspecs (token)
866 : 49878315 : || token->keyword == RID_STATIC_ASSERT)
867 : 7491485 : return true;
868 : : else
869 : : return false;
870 : : }
871 : :
872 : : /* Return true if the next token from PARSER can start declaration
873 : : specifiers (not including standard attributes), false
874 : : otherwise. */
875 : : bool
876 : 121154937 : c_parser_next_token_starts_declspecs (c_parser *parser)
877 : : {
878 : 121154937 : c_token *token = c_parser_peek_token (parser);
879 : :
880 : : /* In Objective-C, a classname normally starts a declspecs unless it
881 : : is immediately followed by a dot. In that case, it is the
882 : : Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
883 : : setter/getter on the class. c_token_starts_declspecs() can't
884 : : differentiate between the two cases because it only checks the
885 : : current token, so we have a special check here. */
886 : 121154937 : if (c_dialect_objc ()
887 : 0 : && token->type == CPP_NAME
888 : 0 : && token->id_kind == C_ID_CLASSNAME
889 : 121154937 : && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
890 : : return false;
891 : :
892 : 121154937 : return c_token_starts_declspecs (token);
893 : : }
894 : :
895 : : /* Return true if the next tokens from PARSER can start declaration
896 : : specifiers (not including standard attributes) or a static
897 : : assertion, false otherwise. */
898 : : bool
899 : 49877553 : c_parser_next_tokens_start_declaration (c_parser *parser)
900 : : {
901 : 49877553 : c_token *token = c_parser_peek_token (parser);
902 : :
903 : : /* Same as above. */
904 : 49877553 : if (c_dialect_objc ()
905 : 0 : && token->type == CPP_NAME
906 : 0 : && token->id_kind == C_ID_CLASSNAME
907 : 49877553 : && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
908 : : return false;
909 : :
910 : : /* Labels do not start declarations. */
911 : 49877553 : if (token->type == CPP_NAME
912 : 49877553 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
913 : : return false;
914 : :
915 : 49877535 : if (c_token_starts_declaration (token))
916 : : return true;
917 : :
918 : 42386121 : if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
919 : : return true;
920 : :
921 : : return false;
922 : : }
923 : :
924 : : /* Consume the next token from PARSER. */
925 : :
926 : : void
927 : 2249735430 : c_parser_consume_token (c_parser *parser)
928 : : {
929 : 2249735430 : gcc_assert (parser->tokens_avail >= 1);
930 : 2249735430 : gcc_assert (parser->tokens[0].type != CPP_EOF);
931 : 2249735430 : gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
932 : 2249735430 : gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
933 : 2249735430 : parser->last_token_location = parser->tokens[0].location;
934 : 2249735430 : if (parser->tokens != &parser->tokens_buf[0])
935 : 42566 : parser->tokens++;
936 : 2249692864 : else if (parser->tokens_avail >= 2)
937 : : {
938 : 148776135 : parser->tokens[0] = parser->tokens[1];
939 : 148776135 : if (parser->tokens_avail >= 3)
940 : : {
941 : 31926 : parser->tokens[1] = parser->tokens[2];
942 : 31926 : if (parser->tokens_avail >= 4)
943 : 12572 : parser->tokens[2] = parser->tokens[3];
944 : : }
945 : : }
946 : 2249735430 : parser->tokens_avail--;
947 : 2249735430 : parser->seen_string_literal = false;
948 : 2249735430 : }
949 : :
950 : : /* Expect the current token to be a #pragma. Consume it and remember
951 : : that we've begun parsing a pragma. */
952 : :
953 : : static void
954 : 1947648 : c_parser_consume_pragma (c_parser *parser)
955 : : {
956 : 1947648 : gcc_assert (!parser->in_pragma);
957 : 1947648 : gcc_assert (parser->tokens_avail >= 1);
958 : 1947648 : gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
959 : 1947648 : if (parser->tokens != &parser->tokens_buf[0])
960 : 932 : parser->tokens++;
961 : 1946716 : else if (parser->tokens_avail >= 2)
962 : : {
963 : 204 : parser->tokens[0] = parser->tokens[1];
964 : 204 : if (parser->tokens_avail >= 3)
965 : 0 : parser->tokens[1] = parser->tokens[2];
966 : : }
967 : 1947648 : parser->tokens_avail--;
968 : 1947648 : parser->in_pragma = true;
969 : 1947648 : }
970 : :
971 : : /* Update the global input_location from TOKEN. */
972 : : static inline void
973 : 7936214 : c_parser_set_source_position_from_token (c_token *token)
974 : : {
975 : 7936214 : if (token->type != CPP_EOF)
976 : : {
977 : 7936139 : input_location = token->location;
978 : : }
979 : : }
980 : :
981 : : /* Helper function for c_parser_error.
982 : : Having peeked a token of kind TOK1_KIND that might signify
983 : : a conflict marker, peek successor tokens to determine
984 : : if we actually do have a conflict marker.
985 : : Specifically, we consider a run of 7 '<', '=' or '>' characters
986 : : at the start of a line as a conflict marker.
987 : : These come through the lexer as three pairs and a single,
988 : : e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
989 : : If it returns true, *OUT_LOC is written to with the location/range
990 : : of the marker. */
991 : :
992 : : static bool
993 : 30 : c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
994 : : location_t *out_loc)
995 : : {
996 : 30 : c_token *token2 = c_parser_peek_2nd_token (parser);
997 : 30 : if (token2->type != tok1_kind)
998 : : return false;
999 : 25 : c_token *token3 = c_parser_peek_nth_token (parser, 3);
1000 : 25 : if (token3->type != tok1_kind)
1001 : : return false;
1002 : 22 : c_token *token4 = c_parser_peek_nth_token (parser, 4);
1003 : 22 : if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
1004 : : return false;
1005 : :
1006 : : /* It must be at the start of the line. */
1007 : 15 : location_t start_loc = c_parser_peek_token (parser)->location;
1008 : 15 : if (LOCATION_COLUMN (start_loc) != 1)
1009 : : return false;
1010 : :
1011 : : /* We have a conflict marker. Construct a location of the form:
1012 : : <<<<<<<
1013 : : ^~~~~~~
1014 : : with start == caret, finishing at the end of the marker. */
1015 : 12 : location_t finish_loc = get_finish (token4->location);
1016 : 12 : *out_loc = make_location (start_loc, start_loc, finish_loc);
1017 : :
1018 : 12 : return true;
1019 : : }
1020 : :
1021 : : /* Issue a diagnostic of the form
1022 : : FILE:LINE: MESSAGE before TOKEN
1023 : : where TOKEN is the next token in the input stream of PARSER.
1024 : : MESSAGE (specified by the caller) is usually of the form "expected
1025 : : OTHER-TOKEN".
1026 : :
1027 : : Use RICHLOC as the location of the diagnostic.
1028 : :
1029 : : Do not issue a diagnostic if still recovering from an error.
1030 : :
1031 : : Return true iff an error was actually emitted.
1032 : :
1033 : : ??? This is taken from the C++ parser, but building up messages in
1034 : : this way is not i18n-friendly and some other approach should be
1035 : : used. */
1036 : :
1037 : : static bool
1038 : 3027 : c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1039 : : rich_location *richloc)
1040 : : {
1041 : 3027 : c_token *token = c_parser_peek_token (parser);
1042 : 3027 : if (parser->error)
1043 : : return false;
1044 : 2314 : parser->error = true;
1045 : 2314 : if (!gmsgid)
1046 : : return false;
1047 : :
1048 : : /* If this is actually a conflict marker, report it as such. */
1049 : 2198 : if (token->type == CPP_LSHIFT
1050 : 2198 : || token->type == CPP_RSHIFT
1051 : 2179 : || token->type == CPP_EQ_EQ)
1052 : : {
1053 : 30 : location_t loc;
1054 : 30 : if (c_parser_peek_conflict_marker (parser, token->type, &loc))
1055 : : {
1056 : 12 : error_at (loc, "version control conflict marker in file");
1057 : 12 : return true;
1058 : : }
1059 : : }
1060 : :
1061 : : /* If we were parsing a string-literal and there is an unknown name
1062 : : token right after, then check to see if that could also have been
1063 : : a literal string by checking the name against a list of known
1064 : : standard string literal constants defined in header files. If
1065 : : there is one, then add that as an hint to the error message. */
1066 : 2186 : auto_diagnostic_group d;
1067 : 2186 : name_hint h;
1068 : 2186 : if (parser->seen_string_literal && token->type == CPP_NAME)
1069 : : {
1070 : 16 : tree name = token->value;
1071 : 16 : const char *token_name = IDENTIFIER_POINTER (name);
1072 : 16 : const char *header_hint
1073 : 16 : = get_c_stdlib_header_for_string_macro_name (token_name);
1074 : 16 : if (header_hint != NULL)
1075 : 48 : h = name_hint (nullptr,
1076 : : std::make_unique<suggest_missing_header>
1077 : 32 : (token->location,
1078 : : token_name,
1079 : 16 : header_hint));
1080 : : }
1081 : :
1082 : 2186 : c_parse_error (gmsgid,
1083 : : /* Because c_parse_error does not understand
1084 : : CPP_KEYWORD, keywords are treated like
1085 : : identifiers. */
1086 : 2186 : (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
1087 : : /* ??? The C parser does not save the cpp flags of a
1088 : : token, we need to pass 0 here and we will not get
1089 : : the source spelling of some tokens but rather the
1090 : : canonical spelling. */
1091 : : token->value, /*flags=*/0, richloc);
1092 : 2186 : return true;
1093 : 2186 : }
1094 : :
1095 : : /* As c_parser_error_richloc, but issue the message at the
1096 : : location of PARSER's next token, or at input_location
1097 : : if the next token is EOF. */
1098 : :
1099 : : bool
1100 : 1921 : c_parser_error (c_parser *parser, const char *gmsgid)
1101 : : {
1102 : 1921 : c_token *token = c_parser_peek_token (parser);
1103 : 1921 : c_parser_set_source_position_from_token (token);
1104 : 1921 : rich_location richloc (line_table, input_location);
1105 : 1921 : return c_parser_error_richloc (parser, gmsgid, &richloc);
1106 : 1921 : }
1107 : :
1108 : : /* Some tokens naturally come in pairs e.g.'(' and ')'.
1109 : : This class is for tracking such a matching pair of symbols.
1110 : : In particular, it tracks the location of the first token,
1111 : : so that if the second token is missing, we can highlight the
1112 : : location of the first token when notifying the user about the
1113 : : problem. */
1114 : :
1115 : : template <typename traits_t>
1116 : : class token_pair
1117 : : {
1118 : : public:
1119 : : /* token_pair's ctor. */
1120 : 172500053 : token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
1121 : :
1122 : : /* If the next token is the opening symbol for this pair, consume it and
1123 : : return true.
1124 : : Otherwise, issue an error and return false.
1125 : : In either case, record the location of the opening token. */
1126 : :
1127 : 4435844 : bool require_open (c_parser *parser)
1128 : : {
1129 : 4435844 : c_token *token = c_parser_peek_token (parser);
1130 : 4435844 : if (token)
1131 : 4435844 : m_open_loc = token->location;
1132 : :
1133 : 4435844 : return c_parser_require (parser, traits_t::open_token_type,
1134 : 4435844 : traits_t::open_gmsgid);
1135 : : }
1136 : :
1137 : : /* Consume the next token from PARSER, recording its location as
1138 : : that of the opening token within the pair. */
1139 : :
1140 : 168064342 : void consume_open (c_parser *parser)
1141 : : {
1142 : 168064342 : c_token *token = c_parser_peek_token (parser);
1143 : 168064342 : gcc_assert (token->type == traits_t::open_token_type);
1144 : 168064342 : m_open_loc = token->location;
1145 : 168064342 : c_parser_consume_token (parser);
1146 : 168064342 : }
1147 : :
1148 : : /* If the next token is the closing symbol for this pair, consume it
1149 : : and return true.
1150 : : Otherwise, issue an error, highlighting the location of the
1151 : : corresponding opening token, and return false. */
1152 : :
1153 : 1754874 : bool require_close (c_parser *parser) const
1154 : : {
1155 : 1754874 : return c_parser_require (parser, traits_t::close_token_type,
1156 : 1754874 : traits_t::close_gmsgid, m_open_loc);
1157 : : }
1158 : :
1159 : : /* Like token_pair::require_close, except that tokens will be skipped
1160 : : until the desired token is found. An error message is still produced
1161 : : if the next token is not as expected. */
1162 : :
1163 : 169378019 : void skip_until_found_close (c_parser *parser) const
1164 : : {
1165 : 169378019 : c_parser_skip_until_found (parser, traits_t::close_token_type,
1166 : 169378019 : traits_t::close_gmsgid, m_open_loc);
1167 : 48402 : }
1168 : :
1169 : : private:
1170 : : location_t m_open_loc;
1171 : : };
1172 : :
1173 : : /* Traits for token_pair<T> for tracking matching pairs of parentheses. */
1174 : :
1175 : : struct matching_paren_traits
1176 : : {
1177 : : static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
1178 : : static const char * const open_gmsgid;
1179 : : static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
1180 : : static const char * const close_gmsgid;
1181 : : };
1182 : :
1183 : : const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
1184 : : const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
1185 : :
1186 : : /* "matching_parens" is a token_pair<T> class for tracking matching
1187 : : pairs of parentheses. */
1188 : :
1189 : : typedef token_pair<matching_paren_traits> matching_parens;
1190 : :
1191 : : /* Traits for token_pair<T> for tracking matching pairs of braces. */
1192 : :
1193 : : struct matching_brace_traits
1194 : : {
1195 : : static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
1196 : : static const char * const open_gmsgid;
1197 : : static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
1198 : : static const char * const close_gmsgid;
1199 : : };
1200 : :
1201 : : const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
1202 : : const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
1203 : :
1204 : : /* "matching_braces" is a token_pair<T> class for tracking matching
1205 : : pairs of braces. */
1206 : :
1207 : : typedef token_pair<matching_brace_traits> matching_braces;
1208 : :
1209 : : /* Get a description of the matching symbol to TYPE e.g. "(" for
1210 : : CPP_CLOSE_PAREN. */
1211 : :
1212 : : static const char *
1213 : 4 : get_matching_symbol (enum cpp_ttype type)
1214 : : {
1215 : 4 : switch (type)
1216 : : {
1217 : 0 : default:
1218 : 0 : gcc_unreachable ();
1219 : : case CPP_CLOSE_PAREN:
1220 : : return "(";
1221 : 1 : case CPP_CLOSE_BRACE:
1222 : 1 : return "{";
1223 : : }
1224 : : }
1225 : :
1226 : : /* If the next token is of the indicated TYPE, consume it. Otherwise,
1227 : : issue the error MSGID. If MSGID is NULL then a message has already
1228 : : been produced and no message will be produced this time. Returns
1229 : : true if found, false otherwise.
1230 : :
1231 : : If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1232 : : within any error as the location of an "opening" token matching
1233 : : the close token TYPE (e.g. the location of the '(' when TYPE is
1234 : : CPP_CLOSE_PAREN).
1235 : :
1236 : : If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
1237 : : one type (e.g. "expected %<)%>") and thus it may be reasonable to
1238 : : attempt to generate a fix-it hint for the problem.
1239 : : Otherwise msgid describes multiple token types (e.g.
1240 : : "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
1241 : : generate a fix-it hint. */
1242 : :
1243 : : bool
1244 : 440388952 : c_parser_require (c_parser *parser,
1245 : : enum cpp_ttype type,
1246 : : const char *msgid,
1247 : : location_t matching_location,
1248 : : bool type_is_unique)
1249 : : {
1250 : 440388952 : if (c_parser_next_token_is (parser, type))
1251 : : {
1252 : 440387846 : c_parser_consume_token (parser);
1253 : 440387846 : return true;
1254 : : }
1255 : : else
1256 : : {
1257 : 1106 : location_t next_token_loc = c_parser_peek_token (parser)->location;
1258 : 1106 : gcc_rich_location richloc (next_token_loc);
1259 : :
1260 : : /* Potentially supply a fix-it hint, suggesting to add the
1261 : : missing token immediately after the *previous* token.
1262 : : This may move the primary location within richloc. */
1263 : 1106 : if (!parser->error && type_is_unique)
1264 : 645 : maybe_suggest_missing_token_insertion (&richloc, type,
1265 : : parser->last_token_location);
1266 : :
1267 : : /* If matching_location != UNKNOWN_LOCATION, highlight it.
1268 : : Attempt to consolidate diagnostics by printing it as a
1269 : : secondary range within the main diagnostic. */
1270 : 1106 : bool added_matching_location = false;
1271 : 1106 : if (matching_location != UNKNOWN_LOCATION)
1272 : 394 : added_matching_location
1273 : 394 : = richloc.add_location_if_nearby (*global_dc, matching_location);
1274 : :
1275 : 1106 : if (c_parser_error_richloc (parser, msgid, &richloc))
1276 : : /* If we weren't able to consolidate matching_location, then
1277 : : print it as a secondary diagnostic. */
1278 : 537 : if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1279 : 4 : inform (matching_location, "to match this %qs",
1280 : : get_matching_symbol (type));
1281 : :
1282 : 1106 : return false;
1283 : 1106 : }
1284 : : }
1285 : :
1286 : : /* If the next token is the indicated keyword, consume it. Otherwise,
1287 : : issue the error MSGID. Returns true if found, false otherwise. */
1288 : :
1289 : : static bool
1290 : 144499 : c_parser_require_keyword (c_parser *parser,
1291 : : enum rid keyword,
1292 : : const char *msgid)
1293 : : {
1294 : 144499 : if (c_parser_next_token_is_keyword (parser, keyword))
1295 : : {
1296 : 144498 : c_parser_consume_token (parser);
1297 : 144498 : return true;
1298 : : }
1299 : : else
1300 : : {
1301 : 1 : c_parser_error (parser, msgid);
1302 : 1 : return false;
1303 : : }
1304 : : }
1305 : :
1306 : : /* Like c_parser_require, except that tokens will be skipped until the
1307 : : desired token is found. An error message is still produced if the
1308 : : next token is not as expected. If MSGID is NULL then a message has
1309 : : already been produced and no message will be produced this
1310 : : time.
1311 : :
1312 : : If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1313 : : within any error as the location of an "opening" token matching
1314 : : the close token TYPE (e.g. the location of the '(' when TYPE is
1315 : : CPP_CLOSE_PAREN). */
1316 : :
1317 : : void
1318 : 220230486 : c_parser_skip_until_found (c_parser *parser,
1319 : : enum cpp_ttype type,
1320 : : const char *msgid,
1321 : : location_t matching_location)
1322 : : {
1323 : 220230486 : unsigned nesting_depth = 0;
1324 : :
1325 : 220230486 : if (c_parser_require (parser, type, msgid, matching_location))
1326 : : {
1327 : 220229607 : if (UNLIKELY (type == CPP_PRAGMA_EOL) && parser->in_omp_attribute_pragma)
1328 : : {
1329 : 0 : c_token *token = c_parser_peek_token (parser);
1330 : 0 : if (token->type == CPP_EOF)
1331 : : {
1332 : 0 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1333 : 0 : parser->tokens_avail
1334 : 0 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1335 : 0 : parser->in_omp_attribute_pragma = NULL;
1336 : : }
1337 : : }
1338 : 220229607 : return;
1339 : : }
1340 : :
1341 : : /* Skip tokens until the desired token is found. */
1342 : 5771 : while (true)
1343 : : {
1344 : : /* Peek at the next token. */
1345 : 3325 : c_token *token = c_parser_peek_token (parser);
1346 : : /* If we've reached the token we want, consume it and stop. */
1347 : 3325 : if (token->type == type && !nesting_depth)
1348 : : {
1349 : 676 : c_parser_consume_token (parser);
1350 : 676 : if (UNLIKELY (type == CPP_PRAGMA_EOL)
1351 : 109 : && parser->in_omp_attribute_pragma)
1352 : : {
1353 : 1 : c_token *token = c_parser_peek_token (parser);
1354 : 1 : if (token->type == CPP_EOF)
1355 : : {
1356 : 1 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1357 : 1 : parser->tokens_avail
1358 : 1 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1359 : 1 : parser->in_omp_attribute_pragma = NULL;
1360 : : }
1361 : : }
1362 : : break;
1363 : : }
1364 : :
1365 : : /* If we've run out of tokens, stop. */
1366 : 2649 : if (token->type == CPP_EOF)
1367 : : return;
1368 : 2630 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1369 : : return;
1370 : 2564 : if (token->type == CPP_OPEN_BRACE
1371 : : || token->type == CPP_OPEN_PAREN
1372 : : || token->type == CPP_OPEN_SQUARE)
1373 : 280 : ++nesting_depth;
1374 : : else if (token->type == CPP_CLOSE_BRACE
1375 : : || token->type == CPP_CLOSE_PAREN
1376 : : || token->type == CPP_CLOSE_SQUARE)
1377 : : {
1378 : 398 : if (nesting_depth-- == 0)
1379 : : break;
1380 : : }
1381 : : /* Consume this token. */
1382 : 2446 : c_parser_consume_token (parser);
1383 : 2446 : }
1384 : 794 : parser->error = false;
1385 : : }
1386 : :
1387 : : /* Skip tokens until the end of a parameter is found, but do not
1388 : : consume the comma, semicolon or closing delimiter. */
1389 : :
1390 : : static void
1391 : 95 : c_parser_skip_to_end_of_parameter (c_parser *parser)
1392 : : {
1393 : 95 : unsigned nesting_depth = 0;
1394 : :
1395 : 491 : while (true)
1396 : : {
1397 : 293 : c_token *token = c_parser_peek_token (parser);
1398 : 293 : if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1399 : 24 : && !nesting_depth)
1400 : : break;
1401 : : /* If we've run out of tokens, stop. */
1402 : 269 : if (token->type == CPP_EOF)
1403 : : return;
1404 : 269 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1405 : : return;
1406 : 269 : if (token->type == CPP_OPEN_BRACE
1407 : : || token->type == CPP_OPEN_PAREN
1408 : : || token->type == CPP_OPEN_SQUARE)
1409 : 3 : ++nesting_depth;
1410 : : else if (token->type == CPP_CLOSE_BRACE
1411 : : || token->type == CPP_CLOSE_PAREN
1412 : : || token->type == CPP_CLOSE_SQUARE)
1413 : : {
1414 : 74 : if (nesting_depth-- == 0)
1415 : : break;
1416 : : }
1417 : : /* Consume this token. */
1418 : 198 : c_parser_consume_token (parser);
1419 : 198 : }
1420 : 95 : parser->error = false;
1421 : : }
1422 : :
1423 : : /* Skip tokens until a non-nested closing curly brace is the next
1424 : : token, or there are no more tokens. Return true in the first case,
1425 : : false otherwise. */
1426 : :
1427 : : static bool
1428 : 26 : c_parser_skip_to_closing_brace (c_parser *parser)
1429 : : {
1430 : 26 : unsigned nesting_depth = 0;
1431 : :
1432 : 96 : while (true)
1433 : : {
1434 : 61 : c_token *token = c_parser_peek_token (parser);
1435 : :
1436 : 61 : switch (token->type)
1437 : : {
1438 : 2 : case CPP_PRAGMA_EOL:
1439 : 2 : if (!parser->in_pragma)
1440 : : break;
1441 : : /* FALLTHRU */
1442 : : case CPP_EOF:
1443 : : /* If we've run out of tokens, stop. */
1444 : : return false;
1445 : :
1446 : 24 : case CPP_CLOSE_BRACE:
1447 : : /* If the next token is a non-nested `}', then we have reached
1448 : : the end of the current block. */
1449 : 24 : if (nesting_depth-- == 0)
1450 : : return true;
1451 : : break;
1452 : :
1453 : 0 : case CPP_OPEN_BRACE:
1454 : : /* If it the next token is a `{', then we are entering a new
1455 : : block. Consume the entire block. */
1456 : 0 : ++nesting_depth;
1457 : 0 : break;
1458 : :
1459 : : default:
1460 : : break;
1461 : : }
1462 : :
1463 : : /* Consume the token. */
1464 : 35 : c_parser_consume_token (parser);
1465 : 35 : }
1466 : : }
1467 : :
1468 : : /* Expect to be at the end of the pragma directive and consume an
1469 : : end of line marker. */
1470 : :
1471 : : static void
1472 : 1948624 : c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1473 : : {
1474 : 1948624 : gcc_assert (parser->in_pragma);
1475 : 1948624 : parser->in_pragma = false;
1476 : :
1477 : 1948624 : if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
1478 : 190 : c_parser_error (parser, "expected end of line");
1479 : :
1480 : 1949914 : cpp_ttype token_type;
1481 : 1949914 : do
1482 : : {
1483 : 1949914 : c_token *token = c_parser_peek_token (parser);
1484 : 1949914 : token_type = token->type;
1485 : 1949914 : if (token_type == CPP_EOF)
1486 : : break;
1487 : 1949914 : c_parser_consume_token (parser);
1488 : : }
1489 : 1949914 : while (token_type != CPP_PRAGMA_EOL);
1490 : :
1491 : 1948624 : if (parser->in_omp_attribute_pragma)
1492 : : {
1493 : 743 : c_token *token = c_parser_peek_token (parser);
1494 : 743 : if (token->type == CPP_EOF)
1495 : : {
1496 : 596 : parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1497 : 596 : parser->tokens_avail
1498 : 596 : = parser->in_omp_attribute_pragma->save_tokens_avail;
1499 : 596 : parser->in_omp_attribute_pragma = NULL;
1500 : : }
1501 : : }
1502 : :
1503 : 1948624 : parser->error = false;
1504 : 1948624 : }
1505 : :
1506 : : /* Skip tokens until we have consumed an entire block, or until we
1507 : : have consumed a non-nested ';'. */
1508 : :
1509 : : static void
1510 : 489 : c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
1511 : : bool metadirective_p = false)
1512 : : {
1513 : 489 : unsigned nesting_depth = 0;
1514 : 489 : int bracket_depth = 0;
1515 : 489 : bool save_error = parser->error;
1516 : :
1517 : 1774 : while (true)
1518 : : {
1519 : 1774 : c_token *token;
1520 : :
1521 : : /* Peek at the next token. */
1522 : 1774 : token = c_parser_peek_token (parser);
1523 : :
1524 : 1774 : switch (token->type)
1525 : : {
1526 : : case CPP_EOF:
1527 : : return;
1528 : :
1529 : 0 : case CPP_PRAGMA_EOL:
1530 : 0 : if (parser->in_pragma)
1531 : : return;
1532 : : break;
1533 : :
1534 : 427 : case CPP_SEMICOLON:
1535 : : /* If the next token is a ';', we have reached the
1536 : : end of the statement. */
1537 : 427 : if (!nesting_depth && (!metadirective_p || bracket_depth <= 0))
1538 : : {
1539 : : /* Consume the ';'. */
1540 : 363 : c_parser_consume_token (parser);
1541 : 363 : goto finished;
1542 : : }
1543 : : break;
1544 : :
1545 : 109 : case CPP_CLOSE_BRACE:
1546 : : /* If the next token is a non-nested '}', then we have
1547 : : reached the end of the current block. */
1548 : 60 : if ((nesting_depth == 0 || --nesting_depth == 0)
1549 : 169 : && (!metadirective_p || bracket_depth <= 0))
1550 : : {
1551 : 109 : c_parser_consume_token (parser);
1552 : 109 : goto finished;
1553 : : }
1554 : : break;
1555 : :
1556 : 60 : case CPP_OPEN_BRACE:
1557 : : /* If it the next token is a '{', then we are entering a new
1558 : : block. Consume the entire block. */
1559 : 60 : ++nesting_depth;
1560 : 60 : break;
1561 : :
1562 : 60 : case CPP_OPEN_PAREN:
1563 : : /* Track parentheses in case the statement is a standalone 'for'
1564 : : statement - we want to skip over the semicolons separating the
1565 : : operands. */
1566 : 60 : if (metadirective_p && nesting_depth == 0)
1567 : 2 : ++bracket_depth;
1568 : : break;
1569 : :
1570 : 86 : case CPP_CLOSE_PAREN:
1571 : 86 : if (metadirective_p && nesting_depth == 0)
1572 : 2 : --bracket_depth;
1573 : : break;
1574 : :
1575 : 7 : case CPP_PRAGMA:
1576 : : /* If we see a pragma, consume the whole thing at once. We
1577 : : have some safeguards against consuming pragmas willy-nilly.
1578 : : Normally, we'd expect to be here with parser->error set,
1579 : : which disables these safeguards. But it's possible to get
1580 : : here for secondary error recovery, after parser->error has
1581 : : been cleared. */
1582 : 7 : c_parser_consume_pragma (parser);
1583 : 7 : c_parser_skip_to_pragma_eol (parser, false);
1584 : 7 : parser->error = save_error;
1585 : 7 : continue;
1586 : :
1587 : : default:
1588 : : break;
1589 : : }
1590 : :
1591 : 1278 : c_parser_consume_token (parser);
1592 : : }
1593 : :
1594 : 472 : finished:
1595 : 472 : parser->error = false;
1596 : : }
1597 : :
1598 : : /* CPP's options (initialized by c-opts.cc). */
1599 : : extern cpp_options *cpp_opts;
1600 : :
1601 : : /* Save the warning flags which are controlled by __extension__. */
1602 : :
1603 : : static inline int
1604 : 951315 : disable_extension_diagnostics (void)
1605 : : {
1606 : 1902630 : int ret = (pedantic
1607 : 951315 : | (warn_pointer_arith << 1)
1608 : 951315 : | (warn_traditional << 2)
1609 : 951315 : | (flag_iso << 3)
1610 : 951315 : | (warn_long_long << 4)
1611 : 951315 : | (warn_cxx_compat << 5)
1612 : 951315 : | (warn_overlength_strings << 6)
1613 : : /* warn_c90_c99_compat has three states: -1/0/1, so we must
1614 : : play tricks to properly restore it. */
1615 : 951315 : | ((warn_c90_c99_compat == 1) << 7)
1616 : 951315 : | ((warn_c90_c99_compat == -1) << 8)
1617 : : /* Similarly for warn_c99_c11_compat. */
1618 : 951315 : | ((warn_c99_c11_compat == 1) << 9)
1619 : 951315 : | ((warn_c99_c11_compat == -1) << 10)
1620 : : /* Similarly for warn_c11_c23_compat. */
1621 : 951315 : | ((warn_c11_c23_compat == 1) << 11)
1622 : 951315 : | ((warn_c11_c23_compat == -1) << 12)
1623 : : /* Similarly for warn_c23_c2y_compat. */
1624 : 951315 : | ((warn_c23_c2y_compat == 1) << 13)
1625 : 951315 : | ((warn_c23_c2y_compat == -1) << 14)
1626 : : );
1627 : 951315 : cpp_opts->cpp_pedantic = pedantic = 0;
1628 : 951315 : warn_pointer_arith = 0;
1629 : 951315 : cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1630 : 951315 : flag_iso = 0;
1631 : 951315 : cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1632 : 951315 : warn_cxx_compat = 0;
1633 : 951315 : warn_overlength_strings = 0;
1634 : 951315 : warn_c90_c99_compat = 0;
1635 : 951315 : warn_c99_c11_compat = 0;
1636 : 951315 : warn_c11_c23_compat = 0;
1637 : 951315 : warn_c23_c2y_compat = 0;
1638 : 951315 : return ret;
1639 : : }
1640 : :
1641 : : /* Restore the warning flags which are controlled by __extension__.
1642 : : FLAGS is the return value from disable_extension_diagnostics. */
1643 : :
1644 : : static inline void
1645 : 951315 : restore_extension_diagnostics (int flags)
1646 : : {
1647 : 951315 : cpp_opts->cpp_pedantic = pedantic = flags & 1;
1648 : 951315 : warn_pointer_arith = (flags >> 1) & 1;
1649 : 951315 : cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1650 : 951315 : flag_iso = (flags >> 3) & 1;
1651 : 951315 : cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1652 : 951315 : warn_cxx_compat = (flags >> 5) & 1;
1653 : 951315 : warn_overlength_strings = (flags >> 6) & 1;
1654 : : /* See above for why is this needed. */
1655 : 951315 : warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1656 : 951315 : warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1657 : 951315 : warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1658 : 951315 : warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
1659 : 951315 : }
1660 : :
1661 : : /* Helper data structure for parsing #pragma acc routine. */
1662 : : struct oacc_routine_data {
1663 : : bool error_seen; /* Set if error has been reported. */
1664 : : bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
1665 : : tree clauses;
1666 : : location_t loc;
1667 : : };
1668 : :
1669 : : /* Used for parsing objc foreach statements. */
1670 : : static tree objc_foreach_break_label, objc_foreach_continue_label;
1671 : :
1672 : : /* Used for parsing OMP for loops.
1673 : :
1674 : : Some notes on flags used for context:
1675 : : parser->omp_for_parse_state is non-null anywhere inside the OMP FOR
1676 : : construct, except for the final-loop-body.
1677 : : The want_nested_loop flag is true if inside a {} sequence where
1678 : : a loop-nest (or another {} sequence containing a loop-nest) is expected,
1679 : : but has not yet been seen. It's false when parsing intervening code
1680 : : statements or their substatements that cannot contain a loop-nest.
1681 : : The in_intervening_code flag is true when parsing any intervening code,
1682 : : including substatements, and whether or not want_nested_loop is true.
1683 : :
1684 : : And, about error handling:
1685 : : The saw_intervening_code flag is set if the loop is not perfectly
1686 : : nested, even in the usual case where this is not an error.
1687 : : perfect_nesting_fail is set if an error has been diagnosed because an
1688 : : imperfectly-nested loop was found where a perfectly-nested one is
1689 : : required (we diagnose this only once).
1690 : : fail is set if any kind of structural error in the loop nest
1691 : : has been found and diagnosed.
1692 : : */
1693 : : struct omp_for_parse_data {
1694 : : enum tree_code code;
1695 : : tree declv, condv, incrv, initv;
1696 : : tree pre_body;
1697 : : tree bindings;
1698 : : int count; /* Expected nesting depth. */
1699 : : int depth; /* Current nesting depth. */
1700 : : location_t for_loc;
1701 : : bool ordered : 1;
1702 : : bool inscan : 1;
1703 : : bool want_nested_loop : 1;
1704 : : bool in_intervening_code : 1;
1705 : : bool saw_intervening_code: 1;
1706 : : bool perfect_nesting_fail : 1;
1707 : : bool fail : 1;
1708 : : };
1709 : :
1710 : : struct attr_state
1711 : : {
1712 : : /* True if we parsed a musttail attribute for return. */
1713 : : bool musttail_p;
1714 : : };
1715 : :
1716 : : static bool c_parser_nth_token_starts_std_attributes (c_parser *,
1717 : : unsigned int);
1718 : : static tree c_parser_std_attribute_specifier_sequence (c_parser *);
1719 : : static void c_parser_external_declaration (c_parser *);
1720 : : static void c_parser_asm_definition (c_parser *);
1721 : : static tree c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
1722 : : bool, bool, bool, tree * = NULL,
1723 : : vec<c_token> * = NULL,
1724 : : bool have_attrs = false,
1725 : : tree attrs = NULL,
1726 : : struct oacc_routine_data * = NULL,
1727 : : bool * = NULL);
1728 : : static bool c_parser_handle_statement_omp_attributes (c_parser *, tree &,
1729 : : bool *);
1730 : : static void c_parser_static_assert_declaration_no_semi (c_parser *);
1731 : : static void c_parser_static_assert_declaration (c_parser *);
1732 : : static struct c_typespec c_parser_enum_specifier (c_parser *);
1733 : : static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
1734 : : static tree c_parser_struct_declaration (c_parser *, tree *);
1735 : : static struct c_typespec c_parser_typeof_specifier (c_parser *);
1736 : : static tree c_parser_alignas_specifier (c_parser *);
1737 : : static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
1738 : : c_dtr_syn, bool *);
1739 : : static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
1740 : : bool,
1741 : : struct c_declarator *);
1742 : : static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
1743 : : bool);
1744 : : static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
1745 : : tree, bool);
1746 : : static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
1747 : : static tree c_parser_asm_string_literal (c_parser *);
1748 : : static tree c_parser_simple_asm_expr (c_parser *);
1749 : : static tree c_parser_gnu_attributes (c_parser *);
1750 : : static struct c_expr c_parser_initializer (c_parser *, tree);
1751 : : static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
1752 : : struct obstack *, tree);
1753 : : static void c_parser_initelt (c_parser *, struct obstack *);
1754 : : static void c_parser_initval (c_parser *, struct c_expr *,
1755 : : struct obstack *);
1756 : : static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
1757 : : static location_t c_parser_compound_statement_nostart (c_parser *);
1758 : : static void c_parser_label (c_parser *, tree);
1759 : : static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
1760 : : static void c_parser_statement_after_labels (c_parser *, bool *, tree,
1761 : : vec<tree> * = NULL,
1762 : : attr_state = {});
1763 : : static tree c_parser_c99_block_statement (c_parser *, bool *,
1764 : : location_t * = NULL);
1765 : : static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
1766 : : static void c_parser_switch_statement (c_parser *, bool *, tree);
1767 : : static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
1768 : : bool *, tree);
1769 : : static void c_parser_do_statement (c_parser *, bool, unsigned short, bool,
1770 : : tree);
1771 : : static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
1772 : : bool *, tree);
1773 : : static tree c_parser_asm_statement (c_parser *);
1774 : : static tree c_parser_asm_operands (c_parser *);
1775 : : static tree c_parser_asm_goto_operands (c_parser *);
1776 : : static tree c_parser_asm_clobbers (c_parser *);
1777 : : static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
1778 : : tree = NULL_TREE);
1779 : : static struct c_expr c_parser_conditional_expression (c_parser *,
1780 : : struct c_expr *, tree);
1781 : : static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
1782 : : tree);
1783 : : static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
1784 : : static struct c_expr c_parser_unary_expression (c_parser *);
1785 : : static inline struct c_expr c_parser_sizeof_expression (c_parser *);
1786 : : static inline struct c_expr c_parser_countof_expression (c_parser *);
1787 : : static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
1788 : : enum rid);
1789 : : static struct c_expr c_parser_alignof_expression (c_parser *);
1790 : : static struct c_expr c_parser_postfix_expression (c_parser *);
1791 : : static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
1792 : : struct c_declspecs *,
1793 : : struct c_type_name *,
1794 : : location_t);
1795 : : static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
1796 : : location_t loc,
1797 : : struct c_expr);
1798 : : static tree c_parser_transaction (c_parser *, enum rid);
1799 : : static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
1800 : : static tree c_parser_transaction_cancel (c_parser *);
1801 : : static struct c_expr c_parser_expression (c_parser *);
1802 : : static struct c_expr c_parser_expression_conv (c_parser *);
1803 : : static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
1804 : : vec<tree, va_gc> **, location_t *,
1805 : : tree *, vec<location_t> *,
1806 : : unsigned int * = NULL);
1807 : : static struct c_expr c_parser_has_attribute_expression (c_parser *);
1808 : :
1809 : : static void c_parser_oacc_declare (c_parser *);
1810 : : static void c_parser_oacc_enter_exit_data (c_parser *, bool);
1811 : : static void c_parser_oacc_update (c_parser *);
1812 : : static void c_parser_omp_construct (c_parser *, bool *);
1813 : : static void c_parser_omp_threadprivate (c_parser *);
1814 : : static void c_parser_omp_barrier (c_parser *);
1815 : : static void c_parser_omp_depobj (c_parser *);
1816 : : static void c_parser_omp_flush (c_parser *);
1817 : : static bool c_parser_omp_next_tokens_can_be_canon_loop (c_parser *,
1818 : : enum tree_code, bool);
1819 : : static tree c_parser_omp_loop_nest (c_parser *, bool *);
1820 : : static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
1821 : : tree, tree *, bool *);
1822 : : static void c_parser_omp_taskwait (c_parser *);
1823 : : static void c_parser_omp_taskyield (c_parser *);
1824 : : static void c_parser_omp_cancel (c_parser *);
1825 : : static void c_parser_omp_nothing (c_parser *);
1826 : : static void c_parser_omp_metadirective (c_parser *, bool *);
1827 : :
1828 : : enum pragma_context { pragma_external, pragma_struct, pragma_param,
1829 : : pragma_stmt, pragma_compound };
1830 : : static bool c_parser_pragma (c_parser *, enum pragma_context, bool *, tree);
1831 : : static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
1832 : : static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
1833 : : static void c_parser_omp_begin (c_parser *);
1834 : : static void c_parser_omp_end (c_parser *);
1835 : : static bool c_parser_omp_declare (c_parser *, enum pragma_context);
1836 : : static void c_parser_omp_requires (c_parser *);
1837 : : static bool c_parser_omp_error (c_parser *, enum pragma_context);
1838 : : static void c_parser_omp_assumption_clauses (c_parser *, bool);
1839 : : static void c_parser_omp_allocate (c_parser *);
1840 : : static void c_parser_omp_assumes (c_parser *);
1841 : : static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
1842 : : static tree c_parser_omp_dispatch (location_t, c_parser *);
1843 : : static void c_parser_omp_interop (c_parser *);
1844 : : static void c_parser_oacc_routine (c_parser *, enum pragma_context);
1845 : :
1846 : : /* These Objective-C parser functions are only ever called when
1847 : : compiling Objective-C. */
1848 : : static void c_parser_objc_class_definition (c_parser *, tree);
1849 : : static void c_parser_objc_class_instance_variables (c_parser *);
1850 : : static void c_parser_objc_class_declaration (c_parser *);
1851 : : static void c_parser_objc_alias_declaration (c_parser *);
1852 : : static void c_parser_objc_protocol_definition (c_parser *, tree);
1853 : : static bool c_parser_objc_method_type (c_parser *);
1854 : : static void c_parser_objc_method_definition (c_parser *);
1855 : : static void c_parser_objc_methodprotolist (c_parser *);
1856 : : static void c_parser_objc_methodproto (c_parser *);
1857 : : static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
1858 : : static tree c_parser_objc_type_name (c_parser *);
1859 : : static tree c_parser_objc_protocol_refs (c_parser *);
1860 : : static void c_parser_objc_try_catch_finally_statement (c_parser *);
1861 : : static void c_parser_objc_synchronized_statement (c_parser *);
1862 : : static tree c_parser_objc_selector (c_parser *);
1863 : : static tree c_parser_objc_selector_arg (c_parser *);
1864 : : static tree c_parser_objc_receiver (c_parser *);
1865 : : static tree c_parser_objc_message_args (c_parser *);
1866 : : static tree c_parser_objc_keywordexpr (c_parser *);
1867 : : static void c_parser_objc_at_property_declaration (c_parser *);
1868 : : static void c_parser_objc_at_synthesize_declaration (c_parser *);
1869 : : static void c_parser_objc_at_dynamic_declaration (c_parser *);
1870 : : static bool c_parser_objc_diagnose_bad_element_prefix
1871 : : (c_parser *, struct c_declspecs *);
1872 : : static location_t c_parser_parse_rtl_body (c_parser *, char *);
1873 : : static tree c_parser_handle_musttail (c_parser *, tree, attr_state &);
1874 : :
1875 : : #if ENABLE_ANALYZER
1876 : :
1877 : : namespace ana {
1878 : :
1879 : : /* Concrete implementation of ana::translation_unit for the C frontend. */
1880 : :
1881 : : class c_translation_unit : public translation_unit
1882 : : {
1883 : : public:
1884 : : /* Implementation of translation_unit::lookup_constant_by_id for use by the
1885 : : analyzer to look up named constants in the user's source code. */
1886 : 7080 : tree lookup_constant_by_id (tree id) const final override
1887 : : {
1888 : : /* Consider decls. */
1889 : 7080 : if (tree decl = lookup_name (id))
1890 : 42 : if (TREE_CODE (decl) == CONST_DECL)
1891 : 42 : if (tree value = DECL_INITIAL (decl))
1892 : 42 : if (TREE_CODE (value) == INTEGER_CST)
1893 : : return value;
1894 : :
1895 : : /* Consider macros. */
1896 : 7038 : cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1897 : 7038 : if (cpp_macro_p (hashnode))
1898 : 48 : if (tree value = consider_macro (hashnode->value.macro))
1899 : : return value;
1900 : :
1901 : : return NULL_TREE;
1902 : : }
1903 : :
1904 : : tree
1905 : 4 : lookup_type_by_id (tree id) const final override
1906 : : {
1907 : 4 : if (tree type_decl = lookup_name (id))
1908 : 0 : if (TREE_CODE (type_decl) == TYPE_DECL)
1909 : : {
1910 : 0 : tree record_type = TREE_TYPE (type_decl);
1911 : 0 : if (TREE_CODE (record_type) == RECORD_TYPE)
1912 : 0 : return record_type;
1913 : : }
1914 : :
1915 : : return NULL_TREE;
1916 : : }
1917 : :
1918 : : tree
1919 : 2 : lookup_global_var_by_id (tree id) const final override
1920 : : {
1921 : 2 : if (tree var_decl = lookup_name (id))
1922 : 0 : if (TREE_CODE (var_decl) == VAR_DECL)
1923 : 0 : return var_decl;
1924 : :
1925 : : return NULL_TREE;
1926 : : }
1927 : :
1928 : : private:
1929 : : /* Attempt to get an INTEGER_CST from MACRO.
1930 : : Only handle the simplest cases: where MACRO's definition is a single
1931 : : token containing a number, by lexing the number again.
1932 : : This will handle e.g.
1933 : : #define NAME 42
1934 : : and other bases but not negative numbers, parentheses or e.g.
1935 : : #define NAME 1 << 7
1936 : : as doing so would require a parser. */
1937 : 48 : tree consider_macro (cpp_macro *macro) const
1938 : : {
1939 : 48 : if (macro->paramc > 0)
1940 : : return NULL_TREE;
1941 : 45 : if (macro->kind != cmk_macro)
1942 : : return NULL_TREE;
1943 : 45 : if (macro->count != 1)
1944 : : return NULL_TREE;
1945 : 39 : const cpp_token &tok = macro->exp.tokens[0];
1946 : 39 : if (tok.type != CPP_NUMBER)
1947 : : return NULL_TREE;
1948 : :
1949 : 36 : cpp_reader *old_parse_in = parse_in;
1950 : 36 : parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
1951 : :
1952 : 36 : pretty_printer pp;
1953 : 36 : pp_string (&pp, (const char *) tok.val.str.text);
1954 : 36 : pp_newline (&pp);
1955 : 72 : cpp_push_buffer (parse_in,
1956 : 36 : (const unsigned char *) pp_formatted_text (&pp),
1957 : : strlen (pp_formatted_text (&pp)),
1958 : : 0);
1959 : :
1960 : 36 : tree value;
1961 : 36 : location_t loc;
1962 : 36 : unsigned char cpp_flags;
1963 : 36 : c_lex_with_flags (&value, &loc, &cpp_flags, 0);
1964 : :
1965 : 36 : cpp_destroy (parse_in);
1966 : 36 : parse_in = old_parse_in;
1967 : :
1968 : 36 : if (value && TREE_CODE (value) == INTEGER_CST)
1969 : 36 : return value;
1970 : :
1971 : : return NULL_TREE;
1972 : 36 : }
1973 : : };
1974 : :
1975 : : } // namespace ana
1976 : :
1977 : : #endif /* #if ENABLE_ANALYZER */
1978 : :
1979 : : /* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
1980 : :
1981 : : translation-unit:
1982 : : external-declarations
1983 : :
1984 : : external-declarations:
1985 : : external-declaration
1986 : : external-declarations external-declaration
1987 : :
1988 : : GNU extensions:
1989 : :
1990 : : translation-unit:
1991 : : empty
1992 : : */
1993 : :
1994 : : static void
1995 : 106102 : c_parser_translation_unit (c_parser *parser)
1996 : : {
1997 : 106102 : if (c_parser_next_token_is (parser, CPP_EOF))
1998 : : {
1999 : 1245 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2000 : : "ISO C forbids an empty translation unit");
2001 : : }
2002 : : else
2003 : : {
2004 : 104857 : void *obstack_position = obstack_alloc (&parser_obstack, 0);
2005 : 104857 : mark_valid_location_for_stdc_pragma (false);
2006 : 56968948 : do
2007 : : {
2008 : 56968948 : ggc_collect ();
2009 : 56968948 : c_parser_external_declaration (parser);
2010 : 56968943 : obstack_free (&parser_obstack, obstack_position);
2011 : : }
2012 : 56968943 : while (c_parser_next_token_is_not (parser, CPP_EOF));
2013 : : }
2014 : :
2015 : : unsigned int i;
2016 : : tree decl;
2017 : 106107 : FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
2018 : 95 : if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
2019 : 17 : error ("storage size of %q+D isn%'t known", decl);
2020 : :
2021 : 106012 : if (vec_safe_length (current_omp_declare_target_attribute))
2022 : : {
2023 : 4 : c_omp_declare_target_attr
2024 : 4 : a = current_omp_declare_target_attribute->pop ();
2025 : 4 : if (!errorcount)
2026 : 3 : error ("%qs without corresponding %qs",
2027 : : a.device_type >= 0 ? "#pragma omp begin declare target"
2028 : : : "#pragma omp declare target",
2029 : : "#pragma omp end declare target");
2030 : 8 : vec_safe_truncate (current_omp_declare_target_attribute, 0);
2031 : : }
2032 : 106012 : if (vec_safe_length (current_omp_begin_assumes))
2033 : : {
2034 : 1 : if (!errorcount)
2035 : 1 : error ("%qs without corresponding %qs",
2036 : : "#pragma omp begin assumes", "#pragma omp end assumes");
2037 : 1 : vec_safe_truncate (current_omp_begin_assumes, 0);
2038 : : }
2039 : :
2040 : : #if ENABLE_ANALYZER
2041 : 106012 : if (flag_analyzer)
2042 : : {
2043 : 1416 : ana::c_translation_unit tu;
2044 : 1416 : ana::on_finish_translation_unit (tu);
2045 : : }
2046 : : #endif
2047 : 106012 : }
2048 : :
2049 : : /* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
2050 : :
2051 : : external-declaration:
2052 : : function-definition
2053 : : declaration
2054 : :
2055 : : GNU extensions:
2056 : :
2057 : : external-declaration:
2058 : : asm-definition
2059 : : ;
2060 : : __extension__ external-declaration
2061 : :
2062 : : Objective-C:
2063 : :
2064 : : external-declaration:
2065 : : objc-class-definition
2066 : : objc-class-declaration
2067 : : objc-alias-declaration
2068 : : objc-protocol-definition
2069 : : objc-method-definition
2070 : : @end
2071 : : */
2072 : :
2073 : : static void
2074 : 57408304 : c_parser_external_declaration (c_parser *parser)
2075 : : {
2076 : 57408304 : int ext;
2077 : 57408304 : switch (c_parser_peek_token (parser)->type)
2078 : : {
2079 : 55005537 : case CPP_KEYWORD:
2080 : 55005537 : switch (c_parser_peek_token (parser)->keyword)
2081 : : {
2082 : 439356 : case RID_EXTENSION:
2083 : 439356 : ext = disable_extension_diagnostics ();
2084 : 439356 : c_parser_consume_token (parser);
2085 : 439356 : c_parser_external_declaration (parser);
2086 : 439356 : restore_extension_diagnostics (ext);
2087 : 439356 : break;
2088 : 172 : case RID_ASM:
2089 : 172 : c_parser_asm_definition (parser);
2090 : 172 : break;
2091 : 0 : case RID_AT_INTERFACE:
2092 : 0 : case RID_AT_IMPLEMENTATION:
2093 : 0 : gcc_assert (c_dialect_objc ());
2094 : 0 : c_parser_objc_class_definition (parser, NULL_TREE);
2095 : 0 : break;
2096 : 0 : case RID_AT_CLASS:
2097 : 0 : gcc_assert (c_dialect_objc ());
2098 : 0 : c_parser_objc_class_declaration (parser);
2099 : 0 : break;
2100 : 0 : case RID_AT_ALIAS:
2101 : 0 : gcc_assert (c_dialect_objc ());
2102 : 0 : c_parser_objc_alias_declaration (parser);
2103 : 0 : break;
2104 : 0 : case RID_AT_PROTOCOL:
2105 : 0 : gcc_assert (c_dialect_objc ());
2106 : 0 : c_parser_objc_protocol_definition (parser, NULL_TREE);
2107 : 0 : break;
2108 : 0 : case RID_AT_PROPERTY:
2109 : 0 : gcc_assert (c_dialect_objc ());
2110 : 0 : c_parser_objc_at_property_declaration (parser);
2111 : 0 : break;
2112 : 0 : case RID_AT_SYNTHESIZE:
2113 : 0 : gcc_assert (c_dialect_objc ());
2114 : 0 : c_parser_objc_at_synthesize_declaration (parser);
2115 : 0 : break;
2116 : 0 : case RID_AT_DYNAMIC:
2117 : 0 : gcc_assert (c_dialect_objc ());
2118 : 0 : c_parser_objc_at_dynamic_declaration (parser);
2119 : 0 : break;
2120 : 0 : case RID_AT_END:
2121 : 0 : gcc_assert (c_dialect_objc ());
2122 : 0 : c_parser_consume_token (parser);
2123 : 0 : objc_finish_implementation ();
2124 : 0 : break;
2125 : 54566009 : default:
2126 : 54566009 : goto decl_or_fndef;
2127 : : }
2128 : : break;
2129 : 566385 : case CPP_SEMICOLON:
2130 : 566385 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2131 : : "ISO C does not allow extra %<;%> outside of a function");
2132 : 566385 : c_parser_consume_token (parser);
2133 : 566385 : break;
2134 : 1615625 : case CPP_PRAGMA:
2135 : 1615625 : mark_valid_location_for_stdc_pragma (true);
2136 : 1615625 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2137 : 1615625 : mark_valid_location_for_stdc_pragma (false);
2138 : 1615625 : break;
2139 : 1 : case CPP_PLUS:
2140 : 1 : case CPP_MINUS:
2141 : 1 : if (c_dialect_objc ())
2142 : : {
2143 : 0 : c_parser_objc_method_definition (parser);
2144 : 0 : break;
2145 : : }
2146 : : /* Else fall through, and yield a syntax error trying to parse
2147 : : as a declaration or function definition. */
2148 : : /* FALLTHRU */
2149 : 54786766 : default:
2150 : 1 : decl_or_fndef:
2151 : : /* A declaration or a function definition (or, in Objective-C,
2152 : : an @interface or @protocol with prefix attributes). We can
2153 : : only tell which after parsing the declaration specifiers, if
2154 : : any, and the first declarator. */
2155 : 54786766 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
2156 : : false);
2157 : 54786766 : break;
2158 : : }
2159 : 57408299 : }
2160 : :
2161 : : static void c_parser_handle_directive_omp_attributes (tree &, vec<c_token> *&,
2162 : : vec<c_token> *);
2163 : : static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
2164 : : static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
2165 : :
2166 : : /* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
2167 : :
2168 : : static void
2169 : 103961161 : add_debug_begin_stmt (location_t loc)
2170 : : {
2171 : : /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2172 : 103961161 : if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2173 : 101238217 : return;
2174 : :
2175 : 2722944 : tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2176 : 2722944 : SET_EXPR_LOCATION (stmt, loc);
2177 : 2722944 : add_stmt (stmt);
2178 : : }
2179 : :
2180 : : /* Helper function for c_parser_declaration_or_fndef and
2181 : : Handle assume attribute(s). */
2182 : :
2183 : : static tree
2184 : 38 : handle_assume_attribute (location_t here, tree attrs, bool nested)
2185 : : {
2186 : 38 : if (nested)
2187 : 78 : for (tree attr = lookup_attribute ("gnu", "assume", attrs); attr;
2188 : 41 : attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr)))
2189 : : {
2190 : 41 : tree args = TREE_VALUE (attr);
2191 : 41 : int nargs = list_length (args);
2192 : 41 : if (nargs != 1)
2193 : : {
2194 : 6 : error_at (here, "wrong number of arguments specified "
2195 : : "for %qE attribute",
2196 : : get_attribute_name (attr));
2197 : 6 : inform (here, "expected %i, found %i", 1, nargs);
2198 : : }
2199 : : else
2200 : : {
2201 : 35 : tree arg = TREE_VALUE (args);
2202 : 35 : arg = c_objc_common_truthvalue_conversion (here, arg);
2203 : 35 : arg = c_fully_fold (arg, false, NULL);
2204 : 35 : if (arg != error_mark_node)
2205 : : {
2206 : 33 : tree fn = build_call_expr_internal_loc (here, IFN_ASSUME,
2207 : : void_type_node, 1,
2208 : : arg);
2209 : 33 : add_stmt (fn);
2210 : : }
2211 : : }
2212 : : }
2213 : : else
2214 : 1 : pedwarn (here, OPT_Wattributes,
2215 : : "%<assume%> attribute at top level");
2216 : :
2217 : 38 : return remove_attribute ("gnu", "assume", attrs);
2218 : : }
2219 : :
2220 : : /* We might need to reclassify any previously-lexed identifier, e.g.
2221 : : when we've left a for loop with an if-statement without else in the
2222 : : body - we might have used a wrong scope for the token. See PR67784. */
2223 : :
2224 : : static void
2225 : 36947537 : c_parser_maybe_reclassify_token (c_parser *parser)
2226 : : {
2227 : 36947537 : if (c_parser_next_token_is (parser, CPP_NAME))
2228 : : {
2229 : 199481 : c_token *token = c_parser_peek_token (parser);
2230 : :
2231 : 199481 : if (token->id_kind != C_ID_CLASSNAME)
2232 : : {
2233 : 199481 : tree decl = lookup_name (token->value);
2234 : :
2235 : 199481 : token->id_kind = C_ID_ID;
2236 : 199481 : if (decl)
2237 : : {
2238 : 196601 : if (TREE_CODE (decl) == TYPE_DECL)
2239 : 2159 : token->id_kind = C_ID_TYPENAME;
2240 : : }
2241 : 2880 : else if (c_dialect_objc ())
2242 : : {
2243 : 0 : tree objc_interface_decl = objc_is_class_name (token->value);
2244 : : /* Objective-C class names are in the same namespace as
2245 : : variables and typedefs, and hence are shadowed by local
2246 : : declarations. */
2247 : 0 : if (objc_interface_decl)
2248 : : {
2249 : 0 : token->value = objc_interface_decl;
2250 : 0 : token->id_kind = C_ID_CLASSNAME;
2251 : : }
2252 : : }
2253 : : }
2254 : : }
2255 : 36947537 : }
2256 : :
2257 : : /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
2258 : : 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
2259 : : is accepted; otherwise (old-style parameter declarations) only other
2260 : : declarations are accepted. If STATIC_ASSERT_OK is true, a static
2261 : : assertion is accepted; otherwise (old-style parameter declarations)
2262 : : it is not. If NESTED is true, we are inside a function or parsing
2263 : : old-style parameter declarations; any functions encountered are
2264 : : nested functions and declaration specifiers are required; otherwise
2265 : : we are at top level and functions are normal functions and
2266 : : declaration specifiers may be optional. If EMPTY_OK is true, empty
2267 : : declarations are OK (subject to all other constraints); otherwise
2268 : : (old-style parameter declarations) they are diagnosed. If
2269 : : START_ATTR_OK is true, the declaration specifiers may start with
2270 : : attributes (GNU or standard); otherwise they may not.
2271 : : OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
2272 : : declaration when parsing an Objective-C foreach statement.
2273 : : FALLTHRU_ATTR_P is used to signal whether this function parsed
2274 : : "__attribute__((fallthrough));". ATTRS are any standard attributes
2275 : : parsed in the caller (in contexts where such attributes had to be
2276 : : parsed to determine whether what follows is a declaration or a
2277 : : statement); HAVE_ATTRS says whether there were any such attributes
2278 : : (even empty). If SIMPLE_OK, the construct can be a simple-declaration;
2279 : : in that case, the ';' is not consumed (left to the caller so that it
2280 : : can figure out if there was a simple-declaration or not), there must
2281 : : be an initializer, and only one object may be declared. When SIMPLE_OK
2282 : : is true we are called from c_parser_selection_header.
2283 : :
2284 : : Returns the resulting declaration, if there was any with an initializer.
2285 : :
2286 : : declaration:
2287 : : declaration-specifiers init-declarator-list[opt] ;
2288 : : static_assert-declaration
2289 : :
2290 : : function-definition:
2291 : : declaration-specifiers[opt] declarator declaration-list[opt]
2292 : : compound-statement
2293 : :
2294 : : declaration-list:
2295 : : declaration
2296 : : declaration-list declaration
2297 : :
2298 : : init-declarator-list:
2299 : : init-declarator
2300 : : init-declarator-list , init-declarator
2301 : :
2302 : : init-declarator:
2303 : : declarator simple-asm-expr[opt] gnu-attributes[opt]
2304 : : declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
2305 : :
2306 : : simple-declaration:
2307 : : attribute-specifier-sequence[opt] declaration-specifiers declarator
2308 : : = initializer
2309 : :
2310 : : GNU extensions:
2311 : :
2312 : : nested-function-definition:
2313 : : declaration-specifiers declarator declaration-list[opt]
2314 : : compound-statement
2315 : :
2316 : : attribute ;
2317 : :
2318 : : Objective-C:
2319 : : gnu-attributes objc-class-definition
2320 : : gnu-attributes objc-category-definition
2321 : : gnu-attributes objc-protocol-definition
2322 : :
2323 : : The simple-asm-expr and gnu-attributes are GNU extensions.
2324 : :
2325 : : This function does not handle __extension__; that is handled in its
2326 : : callers. ??? Following the old parser, __extension__ may start
2327 : : external declarations, declarations in functions and declarations
2328 : : at the start of "for" loops, but not old-style parameter
2329 : : declarations.
2330 : :
2331 : : C99 requires declaration specifiers in a function definition; the
2332 : : absence is diagnosed through the diagnosis of implicit int. In GNU
2333 : : C we also allow but diagnose declarations without declaration
2334 : : specifiers, but only at top level (elsewhere they conflict with
2335 : : other syntax).
2336 : :
2337 : : In Objective-C, declarations of the looping variable in a foreach
2338 : : statement are exceptionally terminated by 'in' (for example, 'for
2339 : : (NSObject *object in array) { ... }').
2340 : :
2341 : : OpenMP:
2342 : :
2343 : : declaration:
2344 : : threadprivate-directive
2345 : :
2346 : : GIMPLE:
2347 : :
2348 : : gimple-function-definition:
2349 : : declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
2350 : : declaration-list[opt] compound-statement
2351 : :
2352 : : rtl-function-definition:
2353 : : declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
2354 : : declaration-list[opt] compound-statement */
2355 : :
2356 : : static tree
2357 : 62291270 : c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
2358 : : bool static_assert_ok, bool empty_ok,
2359 : : bool nested, bool start_attr_ok,
2360 : : bool simple_ok,
2361 : : tree *objc_foreach_object_declaration
2362 : : /* = NULL */,
2363 : : vec<c_token> *omp_declare_simd_clauses
2364 : : /* = NULL */,
2365 : : bool have_attrs /* = false */,
2366 : : tree attrs /* = NULL_TREE */,
2367 : : struct oacc_routine_data *oacc_routine_data
2368 : : /* = NULL */,
2369 : : bool *fallthru_attr_p /* = NULL */)
2370 : : {
2371 : 62291270 : struct c_declspecs *specs;
2372 : 62291270 : tree prefix_attrs;
2373 : 62291270 : tree all_prefix_attrs;
2374 : 62291270 : bool diagnosed_no_specs = false;
2375 : 62291270 : location_t here = c_parser_peek_token (parser)->location;
2376 : 62291270 : tree result = NULL_TREE;
2377 : :
2378 : 62291270 : add_debug_begin_stmt (c_parser_peek_token (parser)->location);
2379 : :
2380 : 62291270 : if (static_assert_ok
2381 : 124569202 : && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
2382 : : {
2383 : 1831 : c_parser_static_assert_declaration (parser);
2384 : 1831 : return result;
2385 : : }
2386 : 62289439 : specs = build_null_declspecs ();
2387 : :
2388 : : /* Handle any standard attributes parsed in the caller. */
2389 : 62289439 : if (have_attrs)
2390 : : {
2391 : 135 : declspecs_add_attrs (here, specs, attrs);
2392 : 135 : specs->non_std_attrs_seen_p = false;
2393 : : }
2394 : :
2395 : : /* Try to detect an unknown type name when we have "A B" or "A *B". */
2396 : 62289439 : if (c_parser_peek_token (parser)->type == CPP_NAME
2397 : 5760756 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
2398 : 9293 : && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2399 : 9185 : || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2400 : 62289571 : && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2401 : : {
2402 : 130 : tree name = c_parser_peek_token (parser)->value;
2403 : :
2404 : : /* Issue a warning about NAME being an unknown type name, perhaps
2405 : : with some kind of hint.
2406 : : If the user forgot a "struct" etc, suggest inserting
2407 : : it. Otherwise, attempt to look for misspellings. */
2408 : 130 : gcc_rich_location richloc (here);
2409 : 130 : if (tag_exists_p (RECORD_TYPE, name))
2410 : : {
2411 : : /* This is not C++ with its implicit typedef. */
2412 : 3 : richloc.add_fixit_insert_before ("struct ");
2413 : 3 : error_at (&richloc,
2414 : : "unknown type name %qE;"
2415 : : " use %<struct%> keyword to refer to the type",
2416 : : name);
2417 : : }
2418 : 127 : else if (tag_exists_p (UNION_TYPE, name))
2419 : : {
2420 : 3 : richloc.add_fixit_insert_before ("union ");
2421 : 3 : error_at (&richloc,
2422 : : "unknown type name %qE;"
2423 : : " use %<union%> keyword to refer to the type",
2424 : : name);
2425 : : }
2426 : 124 : else if (tag_exists_p (ENUMERAL_TYPE, name))
2427 : : {
2428 : 3 : richloc.add_fixit_insert_before ("enum ");
2429 : 3 : error_at (&richloc,
2430 : : "unknown type name %qE;"
2431 : : " use %<enum%> keyword to refer to the type",
2432 : : name);
2433 : : }
2434 : : else
2435 : : {
2436 : 121 : auto_diagnostic_group d;
2437 : 121 : name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2438 : 121 : here);
2439 : 121 : if (const char *suggestion = hint.suggestion ())
2440 : : {
2441 : 12 : richloc.add_fixit_replace (suggestion);
2442 : 12 : error_at (&richloc,
2443 : : "unknown type name %qE; did you mean %qs?",
2444 : : name, suggestion);
2445 : : }
2446 : : else
2447 : 109 : error_at (here, "unknown type name %qE", name);
2448 : 121 : }
2449 : :
2450 : : /* Parse declspecs normally to get a correct pointer type, but avoid
2451 : : a further "fails to be a type name" error. Refuse nested functions
2452 : : since it is not how the user likely wants us to recover. */
2453 : 130 : c_parser_peek_token (parser)->type = CPP_KEYWORD;
2454 : 130 : c_parser_peek_token (parser)->keyword = RID_VOID;
2455 : 130 : c_parser_peek_token (parser)->value = error_mark_node;
2456 : 130 : fndef_ok = !nested;
2457 : 130 : }
2458 : :
2459 : : /* When there are standard attributes at the start of the
2460 : : declaration (to apply to the entity being declared), an
2461 : : init-declarator-list or function definition must be present. */
2462 : 62289439 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
2463 : 462 : have_attrs = true;
2464 : :
2465 : 62289439 : c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2466 : : true, true, start_attr_ok, true, cla_nonabstract_decl);
2467 : 62289439 : if (parser->error)
2468 : : {
2469 : 33 : c_parser_skip_to_end_of_block_or_statement (parser);
2470 : 33 : return result;
2471 : : }
2472 : 62289406 : if (nested && !specs->declspecs_seen_p)
2473 : : {
2474 : 63 : c_parser_error (parser, "expected declaration specifiers");
2475 : 63 : c_parser_skip_to_end_of_block_or_statement (parser);
2476 : 63 : return result;
2477 : : }
2478 : :
2479 : 62289343 : finish_declspecs (specs);
2480 : 62289343 : bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2481 : 62289343 : bool std_auto_type_p = specs->c23_auto_p;
2482 : 62289343 : bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2483 : 62289343 : gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2484 : 62289343 : const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2485 : 62289343 : if (specs->constexpr_p)
2486 : : {
2487 : : /* An underspecified declaration may not declare tags or members
2488 : : or structures or unions; it is undefined behavior to declare
2489 : : the members of an enumeration. Where the structure, union or
2490 : : enumeration type is declared within an initializer, this is
2491 : : diagnosed elsewhere. Diagnose here the case of declaring
2492 : : such a type in the type specifiers of a constexpr
2493 : : declaration. */
2494 : 356 : switch (specs->typespec_kind)
2495 : : {
2496 : 6 : case ctsk_tagfirstref:
2497 : 6 : case ctsk_tagfirstref_attrs:
2498 : 6 : error_at (here, "%qT declared in underspecified object declaration",
2499 : : specs->type);
2500 : 6 : break;
2501 : :
2502 : 10 : case ctsk_tagdef:
2503 : 10 : error_at (here, "%qT defined in underspecified object declaration",
2504 : : specs->type);
2505 : 10 : break;
2506 : :
2507 : : default:
2508 : : break;
2509 : : }
2510 : : }
2511 : :
2512 : 62289343 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
2513 : : {
2514 : 489747 : bool handled_assume = false;
2515 : 489747 : if (specs->attrs
2516 : 490 : && !nested
2517 : 121 : && specs->typespec_kind == ctsk_none
2518 : 489850 : && c_parser_handle_statement_omp_attributes (parser, specs->attrs,
2519 : : NULL))
2520 : : {
2521 : 82 : if (specs->attrs)
2522 : 0 : c_warn_unused_attributes (specs->attrs);
2523 : 165 : while (parser->in_omp_attribute_pragma)
2524 : : {
2525 : 83 : gcc_assert (c_parser_next_token_is (parser, CPP_PRAGMA));
2526 : 83 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2527 : : }
2528 : 82 : c_parser_consume_token (parser);
2529 : 82 : return result;
2530 : : }
2531 : 489665 : if (specs->typespec_kind == ctsk_none
2532 : 489665 : && lookup_attribute ("gnu", "assume", specs->attrs))
2533 : : {
2534 : 38 : handled_assume = true;
2535 : 38 : specs->attrs
2536 : 38 : = handle_assume_attribute (here, specs->attrs, nested);
2537 : : }
2538 : 489665 : if (any_auto_type_p)
2539 : 6 : error_at (here, "%qs in empty declaration", auto_type_keyword);
2540 : 489659 : else if (specs->typespec_kind == ctsk_none
2541 : 489659 : && attribute_fallthrough_p (specs->attrs))
2542 : : {
2543 : 320 : if (fallthru_attr_p != NULL)
2544 : 319 : *fallthru_attr_p = true;
2545 : 320 : if (nested)
2546 : : {
2547 : 319 : tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2548 : : void_type_node, 0);
2549 : 319 : add_stmt (fn);
2550 : : }
2551 : : else
2552 : 1 : pedwarn (here, OPT_Wattributes,
2553 : : "%<fallthrough%> attribute at top level");
2554 : : }
2555 : 489339 : else if (empty_ok
2556 : 489322 : && !(have_attrs && specs->non_std_attrs_seen_p)
2557 : 489319 : && !handled_assume)
2558 : 489281 : shadow_tag (specs);
2559 : : else
2560 : : {
2561 : 58 : shadow_tag_warned (specs, 1);
2562 : 58 : if (!handled_assume)
2563 : 20 : pedwarn (here, 0, "empty declaration");
2564 : : }
2565 : : /* We still have to evaluate size expressions. */
2566 : 489665 : if (specs->expr)
2567 : 106 : add_stmt (fold_convert (void_type_node, specs->expr));
2568 : 489665 : c_parser_consume_token (parser);
2569 : 489665 : if (oacc_routine_data)
2570 : 0 : c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2571 : 489665 : return result;
2572 : : }
2573 : 61799596 : else if (specs->typespec_kind == ctsk_none
2574 : : && nested
2575 : : /* Only parse __attribute__((musttail)) when called from
2576 : : c_parser_compound_statement_nostart. This certainly isn't
2577 : : a declaration in that case, but we don't do tentative parsing
2578 : : of GNU attributes right now. */
2579 : 9771 : && fallthru_attr_p
2580 : 61799677 : && c_parser_next_token_is_keyword (parser, RID_RETURN))
2581 : : {
2582 : 12 : attr_state astate = {};
2583 : 12 : specs->attrs = c_parser_handle_musttail (parser, specs->attrs, astate);
2584 : 12 : if (astate.musttail_p)
2585 : : {
2586 : 12 : if (specs->attrs)
2587 : : {
2588 : 0 : auto_urlify_attributes sentinel;
2589 : 0 : warning_at (c_parser_peek_token (parser)->location,
2590 : 0 : OPT_Wattributes,
2591 : : "attribute %<musttail%> mixed with other attributes "
2592 : : "on %<return%> statement");
2593 : 0 : }
2594 : 12 : c_parser_statement_after_labels (parser, NULL, NULL_TREE, NULL,
2595 : : astate);
2596 : 12 : return result;
2597 : : }
2598 : : }
2599 : :
2600 : : /* Provide better error recovery. Note that a type name here is usually
2601 : : better diagnosed as a redeclaration. */
2602 : 61799584 : if (empty_ok
2603 : 61786452 : && specs->typespec_kind == ctsk_tagdef
2604 : 760057 : && c_parser_next_token_starts_declspecs (parser)
2605 : 61799614 : && !c_parser_next_token_is (parser, CPP_NAME))
2606 : : {
2607 : 9 : c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
2608 : 9 : parser->error = false;
2609 : 9 : shadow_tag_warned (specs, 1);
2610 : 9 : return result;
2611 : : }
2612 : 61799575 : else if (c_dialect_objc () && !any_auto_type_p)
2613 : : {
2614 : : /* Prefix attributes are an error on method decls. */
2615 : 0 : switch (c_parser_peek_token (parser)->type)
2616 : : {
2617 : 0 : case CPP_PLUS:
2618 : 0 : case CPP_MINUS:
2619 : 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2620 : : return result;
2621 : 0 : if (specs->attrs)
2622 : : {
2623 : 0 : warning_at (c_parser_peek_token (parser)->location,
2624 : 0 : OPT_Wattributes,
2625 : : "prefix attributes are ignored for methods");
2626 : 0 : specs->attrs = NULL_TREE;
2627 : : }
2628 : 0 : if (fndef_ok)
2629 : 0 : c_parser_objc_method_definition (parser);
2630 : : else
2631 : 0 : c_parser_objc_methodproto (parser);
2632 : 0 : return result;
2633 : 0 : break;
2634 : 0 : default:
2635 : 0 : break;
2636 : : }
2637 : : /* This is where we parse 'attributes @interface ...',
2638 : : 'attributes @implementation ...', 'attributes @protocol ...'
2639 : : (where attributes could be, for example, __attribute__
2640 : : ((deprecated)).
2641 : : */
2642 : 0 : switch (c_parser_peek_token (parser)->keyword)
2643 : : {
2644 : 0 : case RID_AT_INTERFACE:
2645 : 0 : {
2646 : 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2647 : : return result;
2648 : 0 : c_parser_objc_class_definition (parser, specs->attrs);
2649 : 0 : return result;
2650 : : }
2651 : 0 : break;
2652 : 0 : case RID_AT_IMPLEMENTATION:
2653 : 0 : {
2654 : 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2655 : : return result;
2656 : 0 : if (specs->attrs)
2657 : : {
2658 : 0 : warning_at (c_parser_peek_token (parser)->location,
2659 : 0 : OPT_Wattributes,
2660 : : "prefix attributes are ignored for implementations");
2661 : 0 : specs->attrs = NULL_TREE;
2662 : : }
2663 : 0 : c_parser_objc_class_definition (parser, NULL_TREE);
2664 : 0 : return result;
2665 : : }
2666 : 0 : break;
2667 : 0 : case RID_AT_PROTOCOL:
2668 : 0 : {
2669 : 0 : if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2670 : : return result;
2671 : 0 : c_parser_objc_protocol_definition (parser, specs->attrs);
2672 : 0 : return result;
2673 : : }
2674 : 0 : break;
2675 : 0 : case RID_AT_ALIAS:
2676 : 0 : case RID_AT_CLASS:
2677 : 0 : case RID_AT_END:
2678 : 0 : case RID_AT_PROPERTY:
2679 : 0 : if (specs->attrs)
2680 : : {
2681 : 0 : c_parser_error (parser, "unexpected attribute");
2682 : 0 : specs->attrs = NULL;
2683 : : }
2684 : : break;
2685 : : default:
2686 : : break;
2687 : : }
2688 : : }
2689 : 61799575 : else if (attribute_fallthrough_p (specs->attrs))
2690 : 5 : warning_at (here, OPT_Wattributes,
2691 : : "%<fallthrough%> attribute not followed by %<;%>");
2692 : 61799570 : else if (lookup_attribute ("gnu", "assume", specs->attrs))
2693 : 2 : warning_at (here, OPT_Wattributes,
2694 : : "%<assume%> attribute not followed by %<;%>");
2695 : :
2696 : 123599145 : auto_vec<c_token> omp_declare_simd_attr_clauses;
2697 : 61799575 : c_parser_handle_directive_omp_attributes (specs->attrs,
2698 : : omp_declare_simd_clauses,
2699 : : &omp_declare_simd_attr_clauses);
2700 : 61799575 : pending_xref_error ();
2701 : 61799575 : prefix_attrs = specs->attrs;
2702 : 61799575 : all_prefix_attrs = prefix_attrs;
2703 : 61799575 : specs->attrs = NULL_TREE;
2704 : 61799575 : bool more_than_one_decl = false;
2705 : 62636823 : while (true)
2706 : : {
2707 : 62218199 : struct c_declarator *declarator;
2708 : 62218199 : bool dummy = false;
2709 : 62218199 : timevar_id_t tv;
2710 : 62218199 : tree fnbody = NULL_TREE;
2711 : 62218199 : tree underspec_name = NULL_TREE;
2712 : 62218199 : auto_vec<c_token> omp_dsimd_idattr_clauses;
2713 : : /* Declaring either one or more declarators (in which case we
2714 : : should diagnose if there were no declaration specifiers) or a
2715 : : function definition (in which case the diagnostic for
2716 : : implicit int suffices). */
2717 : 124436398 : declarator = c_parser_declarator (parser,
2718 : 62218199 : specs->typespec_kind != ctsk_none,
2719 : : C_DTR_NORMAL, &dummy);
2720 : 62218199 : if (declarator == NULL)
2721 : : {
2722 : 213 : if (omp_declare_simd_clauses)
2723 : 1 : c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2724 : : omp_declare_simd_clauses);
2725 : 213 : if (oacc_routine_data)
2726 : 0 : c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2727 : : /* This check is here purely to improve the diagnostic. */
2728 : 213 : if (!simple_ok)
2729 : 193 : c_parser_skip_to_end_of_block_or_statement (parser);
2730 : 213 : return result;
2731 : : }
2732 : 62217986 : if (flag_openmp || flag_openmp_simd)
2733 : : {
2734 : : struct c_declarator *d = declarator;
2735 : 833156 : while (d->kind != cdk_id)
2736 : 361259 : d = d->declarator;
2737 : 471897 : vec<c_token> *dummy = NULL;
2738 : 471897 : c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2739 : : &omp_dsimd_idattr_clauses);
2740 : : }
2741 : 62217986 : if (gnu_auto_type_p && declarator->kind != cdk_id)
2742 : : {
2743 : 1 : error_at (here,
2744 : : "%<__auto_type%> requires a plain identifier"
2745 : : " as declarator");
2746 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2747 : 1 : return result;
2748 : : }
2749 : 62217985 : if (std_auto_type_p)
2750 : : {
2751 : : struct c_declarator *d = declarator;
2752 : 82 : while (d->kind == cdk_attrs)
2753 : 0 : d = d->declarator;
2754 : 82 : if (d->kind != cdk_id)
2755 : : {
2756 : 1 : error_at (here,
2757 : : "%<auto%> requires a plain identifier, possibly with"
2758 : : " attributes, as declarator");
2759 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2760 : 1 : return result;
2761 : : }
2762 : 81 : underspec_name = d->u.id.id;
2763 : : }
2764 : 62217903 : else if (specs->constexpr_p)
2765 : : {
2766 : : struct c_declarator *d = declarator;
2767 : 418 : while (d->kind != cdk_id)
2768 : 77 : d = d->declarator;
2769 : 341 : underspec_name = d->u.id.id;
2770 : : }
2771 : 62217984 : if (c_parser_next_token_is (parser, CPP_EQ)
2772 : 56028654 : || c_parser_next_token_is (parser, CPP_COMMA)
2773 : 55726084 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
2774 : 47820275 : || c_parser_next_token_is_keyword (parser, RID_ASM)
2775 : 46964287 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
2776 : 97567767 : || c_parser_next_token_is_keyword (parser, RID_IN))
2777 : : {
2778 : 26868201 : tree asm_name = NULL_TREE;
2779 : 26868201 : tree postfix_attrs = NULL_TREE;
2780 : 26868201 : if (!diagnosed_no_specs && !specs->declspecs_seen_p)
2781 : : {
2782 : 78 : diagnosed_no_specs = true;
2783 : 78 : pedwarn (here, 0, "data definition has no type or storage class");
2784 : : }
2785 : : /* Having seen a data definition, there cannot now be a
2786 : : function definition. */
2787 : 26868201 : fndef_ok = false;
2788 : 26868201 : if (c_parser_next_token_is_keyword (parser, RID_ASM))
2789 : 855988 : asm_name = c_parser_simple_asm_expr (parser);
2790 : 26868201 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
2791 : : {
2792 : 12424496 : postfix_attrs = c_parser_gnu_attributes (parser);
2793 : 12424496 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
2794 : : {
2795 : : /* This means there is an attribute specifier after
2796 : : the declarator in a function definition. Provide
2797 : : some more information for the user. */
2798 : 1 : error_at (here, "attributes should be specified before the "
2799 : : "declarator in a function definition");
2800 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
2801 : 1 : return result;
2802 : : }
2803 : : }
2804 : 26868200 : if (c_parser_next_token_is (parser, CPP_EQ))
2805 : : {
2806 : 6190760 : tree d;
2807 : 6190760 : struct c_expr init;
2808 : 6190760 : location_t init_loc;
2809 : 6190760 : c_parser_consume_token (parser);
2810 : 6190760 : if (any_auto_type_p)
2811 : : {
2812 : 1908 : init_loc = c_parser_peek_token (parser)->location;
2813 : 1908 : rich_location richloc (line_table, init_loc);
2814 : 1908 : unsigned int underspec_state = 0;
2815 : 1908 : if (std_auto_type_p)
2816 : 79 : underspec_state =
2817 : 79 : start_underspecified_init (init_loc, underspec_name);
2818 : 1908 : start_init (NULL_TREE, asm_name,
2819 : 1908 : (global_bindings_p ()
2820 : 1844 : || specs->storage_class == csc_static
2821 : 3750 : || specs->constexpr_p),
2822 : 1908 : specs->constexpr_p, &richloc);
2823 : : /* A parameter is initialized, which is invalid. Don't
2824 : : attempt to instrument the initializer. */
2825 : 1908 : int flag_sanitize_save = flag_sanitize;
2826 : 1908 : if (nested && !empty_ok)
2827 : 30 : flag_sanitize = 0;
2828 : 1908 : init = c_parser_expr_no_commas (parser, NULL);
2829 : 1908 : if (std_auto_type_p)
2830 : 79 : finish_underspecified_init (underspec_name,
2831 : : underspec_state);
2832 : 1908 : flag_sanitize = flag_sanitize_save;
2833 : 1908 : if (gnu_auto_type_p
2834 : 1829 : && TREE_CODE (init.value) == COMPONENT_REF
2835 : 1909 : && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
2836 : 1 : error_at (here,
2837 : : "%<__auto_type%> used with a bit-field"
2838 : : " initializer");
2839 : 1908 : init = convert_lvalue_to_rvalue (init_loc, init, true, true,
2840 : : true);
2841 : 1908 : tree init_type = TREE_TYPE (init.value);
2842 : 1908 : bool vm_type = c_type_variably_modified_p (init_type);
2843 : 1908 : if (vm_type)
2844 : 95 : init.value = save_expr (init.value);
2845 : 1908 : finish_init ();
2846 : 1908 : specs->typespec_kind = ctsk_typeof;
2847 : 1908 : specs->locations[cdw_typedef] = init_loc;
2848 : 1908 : specs->typedef_p = true;
2849 : 1908 : specs->type = init_type;
2850 : 1908 : if (specs->postfix_attrs)
2851 : : {
2852 : : /* Postfix [[]] attributes are valid with C23
2853 : : auto, although not with __auto_type, and
2854 : : modify the type given by the initializer. */
2855 : 2 : specs->postfix_attrs
2856 : 2 : = c_warn_type_attributes (specs->type,
2857 : : specs->postfix_attrs);
2858 : 2 : decl_attributes (&specs->type, specs->postfix_attrs, 0);
2859 : 2 : specs->postfix_attrs = NULL_TREE;
2860 : : }
2861 : 1908 : if (vm_type)
2862 : : {
2863 : 95 : bool maybe_const = true;
2864 : 95 : tree type_expr = c_fully_fold (init.value, false,
2865 : : &maybe_const);
2866 : 95 : specs->expr_const_operands &= maybe_const;
2867 : 95 : if (specs->expr)
2868 : 0 : specs->expr = build2 (COMPOUND_EXPR,
2869 : 0 : TREE_TYPE (type_expr),
2870 : : specs->expr, type_expr);
2871 : : else
2872 : 95 : specs->expr = type_expr;
2873 : : }
2874 : 1908 : d = start_decl (declarator, specs, true,
2875 : : chainon (postfix_attrs, all_prefix_attrs));
2876 : 1908 : if (!d)
2877 : 12 : d = error_mark_node;
2878 : 1908 : if (omp_declare_simd_clauses)
2879 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2880 : : omp_declare_simd_clauses);
2881 : 1908 : if (!omp_dsimd_idattr_clauses.is_empty ())
2882 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2883 : : &omp_dsimd_idattr_clauses);
2884 : 1908 : }
2885 : : else
2886 : : {
2887 : : /* The declaration of the variable is in effect while
2888 : : its initializer is parsed, except for a constexpr
2889 : : variable. */
2890 : 6188852 : init_loc = c_parser_peek_token (parser)->location;
2891 : 6188852 : rich_location richloc (line_table, init_loc);
2892 : 6188852 : unsigned int underspec_state = 0;
2893 : 6188852 : if (specs->constexpr_p)
2894 : 337 : underspec_state =
2895 : 337 : start_underspecified_init (init_loc, underspec_name);
2896 : 6188852 : d = start_decl (declarator, specs, true,
2897 : : chainon (postfix_attrs,
2898 : : all_prefix_attrs),
2899 : 6188852 : !specs->constexpr_p);
2900 : 6188852 : if (!d)
2901 : 4 : d = error_mark_node;
2902 : 6188852 : if (!specs->constexpr_p && omp_declare_simd_clauses)
2903 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2904 : : omp_declare_simd_clauses);
2905 : 6188852 : if (!specs->constexpr_p
2906 : 6188852 : && !omp_dsimd_idattr_clauses.is_empty ())
2907 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2908 : : &omp_dsimd_idattr_clauses);
2909 : 6188852 : start_init (d, asm_name,
2910 : 6012464 : TREE_STATIC (d) || specs->constexpr_p,
2911 : 6188852 : specs->constexpr_p, &richloc);
2912 : : /* A parameter is initialized, which is invalid. Don't
2913 : : attempt to instrument the initializer. */
2914 : 6188852 : int flag_sanitize_save = flag_sanitize;
2915 : 6188852 : if (TREE_CODE (d) == PARM_DECL)
2916 : 35 : flag_sanitize = 0;
2917 : 6188852 : init = c_parser_initializer (parser, d);
2918 : 6188850 : flag_sanitize = flag_sanitize_save;
2919 : 6188850 : if (specs->constexpr_p)
2920 : : {
2921 : 337 : finish_underspecified_init (underspec_name,
2922 : : underspec_state);
2923 : 337 : d = pushdecl (d);
2924 : 337 : if (omp_declare_simd_clauses)
2925 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2926 : : omp_declare_simd_clauses);
2927 : 337 : if (!specs->constexpr_p
2928 : 337 : && !omp_dsimd_idattr_clauses.is_empty ())
2929 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2930 : : &omp_dsimd_idattr_clauses);
2931 : : }
2932 : 6188850 : finish_init ();
2933 : 6188850 : }
2934 : 6190758 : if (oacc_routine_data)
2935 : 0 : c_finish_oacc_routine (oacc_routine_data, d, false);
2936 : 6190758 : if (d != error_mark_node)
2937 : : {
2938 : 6190742 : maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
2939 : 6190742 : finish_decl (d, init_loc, init.value,
2940 : : init.original_type, asm_name);
2941 : 6190742 : result = d;
2942 : : }
2943 : : }
2944 : : else
2945 : : {
2946 : 20677440 : if (any_auto_type_p || specs->constexpr_p)
2947 : : {
2948 : 6 : error_at (here,
2949 : : "%qs requires an initialized data declaration",
2950 : : any_auto_type_p ? auto_type_keyword : "constexpr");
2951 : 4 : c_parser_skip_to_end_of_block_or_statement (parser);
2952 : 4 : return result;
2953 : : }
2954 : :
2955 : 20677436 : location_t lastloc = UNKNOWN_LOCATION;
2956 : 20677436 : tree attrs = chainon (postfix_attrs, all_prefix_attrs);
2957 : 20677436 : tree d = start_decl (declarator, specs, false, attrs, true,
2958 : : &lastloc);
2959 : 20677435 : if (d && TREE_CODE (d) == FUNCTION_DECL)
2960 : : {
2961 : : /* Find the innermost declarator that is neither cdk_id
2962 : : nor cdk_attrs. */
2963 : : const struct c_declarator *decl = declarator;
2964 : : const struct c_declarator *last_non_id_attrs = NULL;
2965 : :
2966 : 28141580 : while (decl)
2967 : 28141580 : switch (decl->kind)
2968 : : {
2969 : 14243265 : case cdk_array:
2970 : 14243265 : case cdk_function:
2971 : 14243265 : case cdk_pointer:
2972 : 14243265 : last_non_id_attrs = decl;
2973 : 14243265 : decl = decl->declarator;
2974 : 14243265 : break;
2975 : :
2976 : 111 : case cdk_attrs:
2977 : 111 : decl = decl->declarator;
2978 : 111 : break;
2979 : :
2980 : : case cdk_id:
2981 : : decl = 0;
2982 : : break;
2983 : :
2984 : 0 : default:
2985 : 0 : gcc_unreachable ();
2986 : : }
2987 : :
2988 : : /* If it exists and is cdk_function declaration whose
2989 : : arguments have not been set yet, use its arguments. */
2990 : 13898204 : if (last_non_id_attrs
2991 : 13289578 : && last_non_id_attrs->kind == cdk_function)
2992 : : {
2993 : 13289578 : tree parms = last_non_id_attrs->u.arg_info->parms;
2994 : 13289578 : if (DECL_ARGUMENTS (d) == NULL_TREE
2995 : 13289578 : && DECL_INITIAL (d) == NULL_TREE)
2996 : 13081475 : DECL_ARGUMENTS (d) = parms;
2997 : :
2998 : 13289578 : warn_parm_array_mismatch (lastloc, d, parms);
2999 : : }
3000 : : }
3001 : 20677435 : if (omp_declare_simd_clauses
3002 : 20677435 : || !omp_dsimd_idattr_clauses.is_empty ())
3003 : : {
3004 : 477 : tree parms = NULL_TREE;
3005 : 477 : if (d && TREE_CODE (d) == FUNCTION_DECL)
3006 : : {
3007 : : struct c_declarator *ce = declarator;
3008 : 466 : while (ce != NULL)
3009 : 466 : if (ce->kind == cdk_function)
3010 : : {
3011 : 463 : parms = ce->u.arg_info->parms;
3012 : 463 : break;
3013 : : }
3014 : : else
3015 : 3 : ce = ce->declarator;
3016 : : }
3017 : 463 : if (parms)
3018 : 238 : temp_store_parm_decls (d, parms);
3019 : 477 : if (omp_declare_simd_clauses)
3020 : 457 : c_finish_omp_declare_simd (parser, d, parms,
3021 : : omp_declare_simd_clauses);
3022 : 477 : if (!specs->constexpr_p
3023 : 477 : && !omp_dsimd_idattr_clauses.is_empty ())
3024 : 22 : c_finish_omp_declare_simd (parser, d, parms,
3025 : : &omp_dsimd_idattr_clauses);
3026 : 477 : if (parms)
3027 : 238 : temp_pop_parm_decls ();
3028 : : }
3029 : 20677435 : if (oacc_routine_data)
3030 : 72 : c_finish_oacc_routine (oacc_routine_data, d, false);
3031 : 20677435 : if (d)
3032 : 20677428 : finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
3033 : : NULL_TREE, asm_name);
3034 : :
3035 : 20677435 : if (c_parser_next_token_is_keyword (parser, RID_IN))
3036 : : {
3037 : 0 : if (d)
3038 : 0 : *objc_foreach_object_declaration = d;
3039 : : else
3040 : 0 : *objc_foreach_object_declaration = error_mark_node;
3041 : : }
3042 : : }
3043 : 26868193 : if (c_parser_next_token_is (parser, CPP_COMMA))
3044 : : {
3045 : 418627 : more_than_one_decl = true;
3046 : 418627 : if (any_auto_type_p || specs->constexpr_p)
3047 : : {
3048 : 4 : error_at (here,
3049 : : "%qs may only be used with a single declarator",
3050 : : any_auto_type_p ? auto_type_keyword : "constexpr");
3051 : 3 : c_parser_skip_to_end_of_block_or_statement (parser);
3052 : 3 : return result;
3053 : : }
3054 : 418624 : c_parser_consume_token (parser);
3055 : 418624 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
3056 : 19 : all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
3057 : : prefix_attrs);
3058 : : else
3059 : : all_prefix_attrs = prefix_attrs;
3060 : 418624 : continue;
3061 : : }
3062 : 26449566 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
3063 : : {
3064 : 26449426 : if (!simple_ok)
3065 : 26449327 : c_parser_consume_token (parser);
3066 : 26449426 : return result;
3067 : : }
3068 : 140 : else if (c_parser_next_token_is_keyword (parser, RID_IN))
3069 : : {
3070 : : /* This can only happen in Objective-C: we found the
3071 : : 'in' that terminates the declaration inside an
3072 : : Objective-C foreach statement. Do not consume the
3073 : : token, so that the caller can use it to determine
3074 : : that this indeed is a foreach context. */
3075 : : return result;
3076 : : }
3077 : : else
3078 : : {
3079 : 140 : if (!simple_ok)
3080 : : {
3081 : 48 : c_parser_error (parser, "expected %<,%> or %<;%>");
3082 : 48 : c_parser_skip_to_end_of_block_or_statement (parser);
3083 : : }
3084 : : /* It's not valid to use if (int i = 2, j = 3). */
3085 : 92 : else if (more_than_one_decl)
3086 : 4 : error_at (here, "declaration in condition can only declare "
3087 : : "a single object");
3088 : 140 : return result;
3089 : : }
3090 : : }
3091 : 35349783 : else if (any_auto_type_p || specs->constexpr_p)
3092 : : {
3093 : 4 : error_at (here,
3094 : : "%qs requires an initialized data declaration",
3095 : : any_auto_type_p ? auto_type_keyword : "constexpr");
3096 : 4 : c_parser_skip_to_end_of_block_or_statement (parser);
3097 : 4 : return result;
3098 : : }
3099 : 35349779 : else if (!fndef_ok)
3100 : : {
3101 : 76 : if (simple_ok && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3102 : : /* Let c_parser_selection_header emit the error. */;
3103 : : else
3104 : : {
3105 : 36 : c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
3106 : : "%<asm%> or %<__attribute__%>");
3107 : 36 : c_parser_skip_to_end_of_block_or_statement (parser);
3108 : : }
3109 : 56 : return result;
3110 : : }
3111 : : /* Function definition (nested or otherwise). */
3112 : 35349723 : if (nested)
3113 : : {
3114 : 1531 : pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
3115 : 1531 : c_push_function_context ();
3116 : : }
3117 : 35349723 : if (!start_function (specs, declarator, all_prefix_attrs))
3118 : : {
3119 : : /* At this point we've consumed:
3120 : : declaration-specifiers declarator
3121 : : and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
3122 : : RID_ASM, RID_ATTRIBUTE, or RID_IN,
3123 : : but the
3124 : : declaration-specifiers declarator
3125 : : aren't grokkable as a function definition, so we have
3126 : : an error. */
3127 : 38 : gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
3128 : 38 : if (c_parser_next_token_starts_declspecs (parser))
3129 : : {
3130 : : /* If we have
3131 : : declaration-specifiers declarator decl-specs
3132 : : then assume we have a missing semicolon, which would
3133 : : give us:
3134 : : declaration-specifiers declarator decl-specs
3135 : : ^
3136 : : ;
3137 : : <~~~~~~~~~ declaration ~~~~~~~~~~>
3138 : : Use c_parser_require to get an error with a fix-it hint. */
3139 : 13 : c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>");
3140 : 13 : parser->error = false;
3141 : : }
3142 : : else
3143 : : {
3144 : : /* This can appear in many cases looking nothing like a
3145 : : function definition, so we don't give a more specific
3146 : : error suggesting there was one. */
3147 : 25 : c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
3148 : : "or %<__attribute__%>");
3149 : : }
3150 : 38 : if (nested)
3151 : 1 : c_pop_function_context ();
3152 : : break;
3153 : : }
3154 : :
3155 : 35349685 : if (DECL_DECLARED_INLINE_P (current_function_decl))
3156 : : tv = TV_PARSE_INLINE;
3157 : : else
3158 : 674529 : tv = TV_PARSE_FUNC;
3159 : 35349685 : auto_timevar at (g_timer, tv);
3160 : :
3161 : : /* Parse old-style parameter declarations. ??? Attributes are
3162 : : not allowed to start declaration specifiers here because of a
3163 : : syntax conflict between a function declaration with attribute
3164 : : suffix and a function definition with an attribute prefix on
3165 : : first old-style parameter declaration. Following the old
3166 : : parser, they are not accepted on subsequent old-style
3167 : : parameter declarations either. However, there is no
3168 : : ambiguity after the first declaration, nor indeed on the
3169 : : first as long as we don't allow postfix attributes after a
3170 : : declarator with a nonempty identifier list in a definition;
3171 : : and postfix attributes have never been accepted here in
3172 : : function definitions either. */
3173 : 35349685 : int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
3174 : 35349685 : debug_nonbind_markers_p = 0;
3175 : 35349685 : c_parser_maybe_reclassify_token (parser);
3176 : 35349685 : while (c_parser_next_token_is_not (parser, CPP_EOF)
3177 : 70725308 : && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
3178 : 12977 : c_parser_declaration_or_fndef (parser, false, false, false,
3179 : : true, false, false);
3180 : 35349685 : debug_nonbind_markers_p = save_debug_nonbind_markers_p;
3181 : 35349685 : store_parm_decls ();
3182 : 35349685 : if (omp_declare_simd_clauses)
3183 : 288 : c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3184 : : omp_declare_simd_clauses);
3185 : 35349685 : if (!omp_dsimd_idattr_clauses.is_empty ())
3186 : 4 : c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3187 : : &omp_dsimd_idattr_clauses);
3188 : 35349685 : if (oacc_routine_data)
3189 : 130 : c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
3190 : 35349685 : location_t startloc = c_parser_peek_token (parser)->location;
3191 : 35349685 : DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
3192 : 35349685 : = startloc;
3193 : 35349685 : location_t endloc = startloc;
3194 : :
3195 : : /* If the definition was marked with __RTL, use the RTL parser now,
3196 : : consuming the function body. */
3197 : 35349685 : if (specs->declspec_il == cdil_rtl)
3198 : : {
3199 : 25 : endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
3200 : :
3201 : : /* Normally, store_parm_decls sets next_is_function_body,
3202 : : anticipating a function body. We need a push_scope/pop_scope
3203 : : pair to flush out this state, or subsequent function parsing
3204 : : will go wrong. */
3205 : 24 : push_scope ();
3206 : 24 : pop_scope ();
3207 : :
3208 : 24 : finish_function (endloc);
3209 : 24 : return result;
3210 : : }
3211 : : /* If the definition was marked with __GIMPLE then parse the
3212 : : function body as GIMPLE. */
3213 : 35349660 : else if (specs->declspec_il != cdil_none)
3214 : : {
3215 : 239 : bool saved = in_late_binary_op;
3216 : 239 : in_late_binary_op = true;
3217 : 239 : c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3218 : 239 : specs->declspec_il,
3219 : : specs->entry_bb_count);
3220 : 239 : in_late_binary_op = saved;
3221 : : }
3222 : : else
3223 : 35349421 : fnbody = c_parser_compound_statement (parser, &endloc);
3224 : 35349659 : tree fndecl = current_function_decl;
3225 : 35349659 : if (nested)
3226 : : {
3227 : 1530 : tree decl = current_function_decl;
3228 : : /* Mark nested functions as needing static-chain initially.
3229 : : lower_nested_functions will recompute it but the
3230 : : DECL_STATIC_CHAIN flag is also used before that happens,
3231 : : by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
3232 : 1530 : DECL_STATIC_CHAIN (decl) = 1;
3233 : 1530 : add_stmt (fnbody);
3234 : 1530 : finish_function (endloc);
3235 : 1530 : c_pop_function_context ();
3236 : 1530 : add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
3237 : : }
3238 : : else
3239 : : {
3240 : 35348129 : if (fnbody)
3241 : 35347890 : add_stmt (fnbody);
3242 : 35348129 : finish_function (endloc);
3243 : : }
3244 : : /* Get rid of the empty stmt list for GIMPLE/RTL. */
3245 : 35349659 : if (specs->declspec_il != cdil_none)
3246 : 239 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
3247 : :
3248 : 35349659 : break;
3249 : 26868497 : }
3250 : :
3251 : 35349697 : return result;
3252 : : }
3253 : :
3254 : : /* Parse an asm-definition (asm() outside a function body). This is a
3255 : : GNU extension.
3256 : :
3257 : : asm-definition:
3258 : : simple-asm-expr ;
3259 : : asm ( toplevel-asm-argument ) ;
3260 : :
3261 : : toplevel-asm-argument:
3262 : : asm-string-literal
3263 : : asm-string-literal : asm-operands[opt]
3264 : : asm-string-literal : asm-operands[opt] : asm-operands[opt]
3265 : :
3266 : : The :: token is considered equivalent to two consecutive : tokens. */
3267 : :
3268 : : static void
3269 : 172 : c_parser_asm_definition (c_parser *parser)
3270 : : {
3271 : 172 : location_t asm_loc = c_parser_peek_token (parser)->location;
3272 : 172 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
3273 : 172 : c_parser_consume_token (parser);
3274 : 172 : matching_parens parens;
3275 : 172 : tree asm_str = NULL_TREE;
3276 : 172 : tree outputs = NULL_TREE, inputs = NULL_TREE;
3277 : 172 : if (!parens.require_open (parser))
3278 : 5 : goto done;
3279 : 167 : asm_str = c_parser_asm_string_literal (parser);
3280 : 167 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3281 : : {
3282 : 135 : parens.require_close (parser);
3283 : 135 : goto done;
3284 : : }
3285 : 50 : for (int section = 0; section < 2; ++section)
3286 : : {
3287 : 48 : if (c_parser_next_token_is (parser, CPP_SCOPE))
3288 : : {
3289 : 6 : ++section;
3290 : 6 : if (section == 2)
3291 : : {
3292 : 0 : c_parser_error (parser, "expected %<)%>");
3293 : 1 : error_close_paren:
3294 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
3295 : 1 : asm_str = NULL_TREE;
3296 : 1 : goto done;
3297 : : }
3298 : 6 : c_parser_consume_token (parser);
3299 : : }
3300 : 42 : else if (!c_parser_require (parser, CPP_COLON,
3301 : : "expected %<:%> or %<)%>",
3302 : : UNKNOWN_LOCATION, false))
3303 : 1 : goto error_close_paren;
3304 : 47 : if (!c_parser_next_token_is (parser, CPP_COLON)
3305 : 33 : && !c_parser_next_token_is (parser, CPP_SCOPE)
3306 : 80 : && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3307 : : {
3308 : 33 : if (section)
3309 : 22 : inputs = c_parser_asm_operands (parser);
3310 : : else
3311 : 11 : outputs = c_parser_asm_operands (parser);
3312 : : }
3313 : 47 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
3314 : : break;
3315 : : }
3316 : :
3317 : 31 : if (!parens.require_close (parser))
3318 : : {
3319 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
3320 : 2 : asm_str = NULL_TREE;
3321 : : }
3322 : :
3323 : 31 : if (asm_str)
3324 : 29 : asm_str = build_asm_expr (asm_loc, asm_str, outputs, inputs,
3325 : : NULL_TREE, NULL_TREE, false, false);
3326 : 170 : done:
3327 : 170 : if (asm_str)
3328 : 164 : symtab->finalize_toplevel_asm (asm_str);
3329 : 172 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
3330 : 172 : }
3331 : :
3332 : : /* Parse a static assertion (C11 6.7.10).
3333 : :
3334 : : static_assert-declaration:
3335 : : static_assert-declaration-no-semi ;
3336 : : */
3337 : :
3338 : : static void
3339 : 1831 : c_parser_static_assert_declaration (c_parser *parser)
3340 : : {
3341 : 1831 : c_parser_static_assert_declaration_no_semi (parser);
3342 : 1831 : if (parser->error
3343 : 1831 : || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
3344 : 8 : c_parser_skip_to_end_of_block_or_statement (parser);
3345 : 1831 : }
3346 : :
3347 : : /* Parse a static assertion (C11 6.7.10), without the trailing
3348 : : semicolon.
3349 : :
3350 : : static_assert-declaration-no-semi:
3351 : : _Static_assert ( constant-expression , string-literal )
3352 : :
3353 : : C23:
3354 : : static_assert-declaration-no-semi:
3355 : : _Static_assert ( constant-expression )
3356 : : */
3357 : :
3358 : : static void
3359 : 1841 : c_parser_static_assert_declaration_no_semi (c_parser *parser)
3360 : : {
3361 : 1841 : location_t assert_loc, value_loc;
3362 : 1841 : tree value;
3363 : 1841 : tree string = NULL_TREE;
3364 : :
3365 : 1841 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3366 : 1841 : tree spelling = c_parser_peek_token (parser)->value;
3367 : 1841 : assert_loc = c_parser_peek_token (parser)->location;
3368 : 1841 : if (flag_isoc99)
3369 : 1838 : pedwarn_c99 (assert_loc, OPT_Wpedantic,
3370 : : "ISO C99 does not support %qE", spelling);
3371 : : else
3372 : 3 : pedwarn_c99 (assert_loc, OPT_Wpedantic,
3373 : : "ISO C90 does not support %qE", spelling);
3374 : 1841 : c_parser_consume_token (parser);
3375 : 1841 : matching_parens parens;
3376 : 1841 : if (!parens.require_open (parser))
3377 : 12 : return;
3378 : 1840 : location_t value_tok_loc = c_parser_peek_token (parser)->location;
3379 : 1840 : value = convert_lvalue_to_rvalue (value_tok_loc,
3380 : : c_parser_expr_no_commas (parser, NULL),
3381 : : true, true).value;
3382 : 1840 : value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3383 : 1840 : if (c_parser_next_token_is (parser, CPP_COMMA))
3384 : : {
3385 : 1466 : c_parser_consume_token (parser);
3386 : 1466 : switch (c_parser_peek_token (parser)->type)
3387 : : {
3388 : 1463 : case CPP_STRING:
3389 : 1463 : case CPP_STRING16:
3390 : 1463 : case CPP_STRING32:
3391 : 1463 : case CPP_WSTRING:
3392 : 1463 : case CPP_UTF8STRING:
3393 : 1463 : string = c_parser_string_literal (parser, false, true).value;
3394 : 1463 : break;
3395 : 3 : default:
3396 : 3 : c_parser_error (parser, "expected string literal");
3397 : 3 : return;
3398 : : }
3399 : : }
3400 : 374 : else if (flag_isoc11)
3401 : : /* If pedantic for pre-C11, the use of _Static_assert itself will
3402 : : have been diagnosed, so do not also diagnose the use of this
3403 : : new C23 feature of _Static_assert. */
3404 : 373 : pedwarn_c11 (assert_loc, OPT_Wpedantic,
3405 : : "ISO C11 does not support omitting the string in "
3406 : : "%qE", spelling);
3407 : 1837 : parens.require_close (parser);
3408 : :
3409 : 1837 : if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
3410 : : {
3411 : 3 : error_at (value_loc, "expression in static assertion is not an integer");
3412 : 3 : return;
3413 : : }
3414 : 1834 : if (TREE_CODE (value) != INTEGER_CST)
3415 : : {
3416 : 10 : value = c_fully_fold (value, false, NULL);
3417 : : /* Strip no-op conversions. */
3418 : 20 : STRIP_TYPE_NOPS (value);
3419 : 10 : if (TREE_CODE (value) == INTEGER_CST)
3420 : 5 : pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
3421 : : "is not an integer constant expression");
3422 : : }
3423 : 1834 : if (TREE_CODE (value) != INTEGER_CST)
3424 : : {
3425 : 5 : error_at (value_loc, "expression in static assertion is not constant");
3426 : 5 : return;
3427 : : }
3428 : 1829 : constant_expression_warning (value);
3429 : 1829 : if (integer_zerop (value))
3430 : : {
3431 : 11 : if (string)
3432 : 9 : error_at (assert_loc, "static assertion failed: %E", string);
3433 : : else
3434 : 2 : error_at (assert_loc, "static assertion failed");
3435 : : }
3436 : : }
3437 : :
3438 : : /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
3439 : : 6.7, C11 6.7), adding them to SPECS (which may already include some).
3440 : : Storage class specifiers are accepted iff SCSPEC_OK; type
3441 : : specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
3442 : : accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
3443 : : iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
3444 : : addition to the syntax shown, standard attributes are accepted at
3445 : : the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
3446 : : unlike gnu-attributes, they are not accepted in the middle of the
3447 : : list. (This combines various different syntax productions in the C
3448 : : standard, and in some cases gnu-attributes and standard attributes
3449 : : at the start may already have been parsed before this function is
3450 : : called.)
3451 : :
3452 : : declaration-specifiers:
3453 : : storage-class-specifier declaration-specifiers[opt]
3454 : : type-specifier declaration-specifiers[opt]
3455 : : type-qualifier declaration-specifiers[opt]
3456 : : function-specifier declaration-specifiers[opt]
3457 : : alignment-specifier declaration-specifiers[opt]
3458 : :
3459 : : Function specifiers (inline) are from C99, and are currently
3460 : : handled as storage class specifiers, as is __thread. Alignment
3461 : : specifiers are from C11.
3462 : :
3463 : : C90 6.5.1, C99 6.7.1, C11 6.7.1:
3464 : : storage-class-specifier:
3465 : : typedef
3466 : : extern
3467 : : static
3468 : : auto
3469 : : register
3470 : : _Thread_local
3471 : :
3472 : : (_Thread_local is new in C11.)
3473 : :
3474 : : C99 6.7.4, C11 6.7.4:
3475 : : function-specifier:
3476 : : inline
3477 : : _Noreturn
3478 : :
3479 : : (_Noreturn is new in C11.)
3480 : :
3481 : : C90 6.5.2, C99 6.7.2, C11 6.7.2:
3482 : : type-specifier:
3483 : : void
3484 : : char
3485 : : short
3486 : : int
3487 : : long
3488 : : float
3489 : : double
3490 : : signed
3491 : : unsigned
3492 : : _Bool
3493 : : _Complex
3494 : : [_Imaginary removed in C99 TC2]
3495 : : _BitInt ( constant-expression )
3496 : : struct-or-union-specifier
3497 : : enum-specifier
3498 : : typedef-name
3499 : : atomic-type-specifier
3500 : :
3501 : : (_Bool and _Complex are new in C99.)
3502 : : (atomic-type-specifier is new in C11.)
3503 : : (_BitInt is new in C23.)
3504 : :
3505 : : C90 6.5.3, C99 6.7.3, C11 6.7.3:
3506 : :
3507 : : type-qualifier:
3508 : : const
3509 : : restrict
3510 : : volatile
3511 : : address-space-qualifier
3512 : : _Atomic
3513 : :
3514 : : (restrict is new in C99.)
3515 : : (_Atomic is new in C11.)
3516 : :
3517 : : GNU extensions:
3518 : :
3519 : : declaration-specifiers:
3520 : : gnu-attributes declaration-specifiers[opt]
3521 : :
3522 : : type-qualifier:
3523 : : address-space
3524 : :
3525 : : address-space:
3526 : : identifier recognized by the target
3527 : :
3528 : : storage-class-specifier:
3529 : : __thread
3530 : :
3531 : : type-specifier:
3532 : : typeof-specifier
3533 : : __auto_type
3534 : : __intN
3535 : : _Decimal32
3536 : : _Decimal64
3537 : : _Decimal128
3538 : : _Fract
3539 : : _Accum
3540 : : _Sat
3541 : :
3542 : : (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
3543 : : http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
3544 : :
3545 : : atomic-type-specifier
3546 : : _Atomic ( type-name )
3547 : :
3548 : : Objective-C:
3549 : :
3550 : : type-specifier:
3551 : : class-name objc-protocol-refs[opt]
3552 : : typedef-name objc-protocol-refs
3553 : : objc-protocol-refs
3554 : : */
3555 : :
3556 : : void
3557 : 323828926 : c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
3558 : : bool scspec_ok, bool typespec_ok, bool start_attr_ok,
3559 : : bool alignspec_ok, bool auto_type_ok,
3560 : : bool start_std_attr_ok, bool end_std_attr_ok,
3561 : : enum c_lookahead_kind la)
3562 : : {
3563 : 323828926 : bool attrs_ok = start_attr_ok;
3564 : 323828926 : bool seen_type = specs->typespec_kind != ctsk_none;
3565 : :
3566 : 323828926 : if (!typespec_ok)
3567 : 19001039 : gcc_assert (la == cla_prefer_id);
3568 : :
3569 : 323828926 : if (start_std_attr_ok
3570 : 323828926 : && c_parser_nth_token_starts_std_attributes (parser, 1))
3571 : : {
3572 : 497 : gcc_assert (!specs->non_std_attrs_seen_p);
3573 : 497 : location_t loc = c_parser_peek_token (parser)->location;
3574 : 497 : tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3575 : 497 : declspecs_add_attrs (loc, specs, attrs);
3576 : 497 : specs->non_std_attrs_seen_p = false;
3577 : : }
3578 : :
3579 : 784089273 : while (c_parser_next_token_is (parser, CPP_NAME)
3580 : 363138096 : || c_parser_next_token_is (parser, CPP_KEYWORD)
3581 : 926309305 : || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
3582 : : {
3583 : 641869241 : struct c_typespec t;
3584 : 641869241 : tree attrs;
3585 : 641869241 : tree align;
3586 : 641869241 : location_t loc = c_parser_peek_token (parser)->location;
3587 : :
3588 : : /* If we cannot accept a type, exit if the next token must start
3589 : : one. Also, if we already have seen a tagged definition,
3590 : : a typename would be an error anyway and likely the user
3591 : : has simply forgotten a semicolon, so we exit. */
3592 : 626108178 : if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3593 : 16669760 : && c_parser_next_tokens_start_typename (parser, la)
3594 : 3763770 : && !c_parser_next_token_is_qualifier (parser)
3595 : 641869311 : && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS))
3596 : : break;
3597 : :
3598 : 641869180 : if (c_parser_next_token_is (parser, CPP_NAME))
3599 : : {
3600 : 420951128 : c_token *name_token = c_parser_peek_token (parser);
3601 : 420951128 : tree value = name_token->value;
3602 : 420951128 : c_id_kind kind = name_token->id_kind;
3603 : :
3604 : 420951128 : if (kind == C_ID_ADDRSPACE)
3605 : : {
3606 : 174 : addr_space_t as
3607 : 174 : = name_token->keyword - RID_FIRST_ADDR_SPACE;
3608 : 174 : declspecs_add_addrspace (name_token->location, specs, as);
3609 : 174 : c_parser_consume_token (parser);
3610 : 174 : attrs_ok = true;
3611 : 239345344 : continue;
3612 : 174 : }
3613 : :
3614 : 420950954 : gcc_assert (!c_parser_next_token_is_qualifier (parser));
3615 : :
3616 : : /* If we cannot accept a type, and the next token must start one,
3617 : : exit. Do the same if we already have seen a tagged definition,
3618 : : since it would be an error anyway and likely the user has simply
3619 : : forgotten a semicolon. */
3620 : 420950954 : if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
3621 : : break;
3622 : :
3623 : : /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
3624 : : a C_ID_CLASSNAME. */
3625 : 239345170 : c_parser_consume_token (parser);
3626 : 239345170 : seen_type = true;
3627 : 239345170 : attrs_ok = true;
3628 : 239345170 : if (kind == C_ID_ID)
3629 : : {
3630 : 51 : auto_diagnostic_group d;
3631 : 51 : name_hint hint = lookup_name_fuzzy (value, FUZZY_LOOKUP_TYPENAME,
3632 : 51 : loc);
3633 : 51 : if (const char *suggestion = hint.suggestion ())
3634 : : {
3635 : 2 : gcc_rich_location richloc (loc);
3636 : 2 : richloc.add_fixit_replace (suggestion);
3637 : 2 : error_at (&richloc,
3638 : : "unknown type name %qE; did you mean %qs?",
3639 : : value, suggestion);
3640 : 2 : }
3641 : : else
3642 : 49 : error_at (loc, "unknown type name %qE", value);
3643 : 51 : t.kind = ctsk_typedef;
3644 : 51 : t.spec = error_mark_node;
3645 : 51 : }
3646 : 239345119 : else if (kind == C_ID_TYPENAME
3647 : 239345119 : && (!c_dialect_objc ()
3648 : 0 : || c_parser_next_token_is_not (parser, CPP_LESS)))
3649 : : {
3650 : 239345119 : t.kind = ctsk_typedef;
3651 : : /* For a typedef name, record the meaning, not the name.
3652 : : In case of 'foo foo, bar;'. */
3653 : 239345119 : t.spec = lookup_name (value);
3654 : : }
3655 : : else
3656 : : {
3657 : 0 : tree proto = NULL_TREE;
3658 : 0 : gcc_assert (c_dialect_objc ());
3659 : 0 : t.kind = ctsk_objc;
3660 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
3661 : 0 : proto = c_parser_objc_protocol_refs (parser);
3662 : 0 : t.spec = objc_get_protocol_qualified_type (value, proto);
3663 : : }
3664 : 239345170 : t.expr = NULL_TREE;
3665 : 239345170 : t.expr_const_operands = true;
3666 : 239345170 : t.has_enum_type_specifier = false;
3667 : 239345170 : declspecs_add_type (name_token->location, specs, t);
3668 : 239345170 : continue;
3669 : 239345170 : }
3670 : 220918052 : if (c_parser_next_token_is (parser, CPP_LESS))
3671 : : {
3672 : : /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
3673 : : nisse@lysator.liu.se. */
3674 : 0 : tree proto;
3675 : 0 : gcc_assert (c_dialect_objc ());
3676 : 0 : if (!typespec_ok || seen_type)
3677 : : break;
3678 : 0 : proto = c_parser_objc_protocol_refs (parser);
3679 : 0 : t.kind = ctsk_objc;
3680 : 0 : t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
3681 : 0 : t.expr = NULL_TREE;
3682 : 0 : t.expr_const_operands = true;
3683 : 0 : t.has_enum_type_specifier = false;
3684 : 0 : declspecs_add_type (loc, specs, t);
3685 : 0 : continue;
3686 : 0 : }
3687 : 220918052 : gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3688 : 220918052 : switch (c_parser_peek_token (parser)->keyword)
3689 : : {
3690 : 87588672 : case RID_STATIC:
3691 : 87588672 : case RID_EXTERN:
3692 : 87588672 : case RID_REGISTER:
3693 : 87588672 : case RID_TYPEDEF:
3694 : 87588672 : case RID_INLINE:
3695 : 87588672 : case RID_NORETURN:
3696 : 87588672 : case RID_AUTO:
3697 : 87588672 : case RID_THREAD:
3698 : 87588672 : case RID_CONSTEXPR:
3699 : 87588672 : if (!scspec_ok)
3700 : 3049 : goto out;
3701 : 87588539 : attrs_ok = true;
3702 : : /* TODO: Distinguish between function specifiers (inline, noreturn)
3703 : : and storage class specifiers, either here or in
3704 : : declspecs_add_scspec. */
3705 : 87588539 : declspecs_add_scspec (loc, specs,
3706 : 87588539 : c_parser_peek_token (parser)->value);
3707 : 87588539 : c_parser_consume_token (parser);
3708 : 87588539 : break;
3709 : 1839 : case RID_AUTO_TYPE:
3710 : 1839 : if (!auto_type_ok)
3711 : 0 : goto out;
3712 : : /* Fall through. */
3713 : 78861765 : case RID_UNSIGNED:
3714 : 78861765 : case RID_LONG:
3715 : 78861765 : case RID_SHORT:
3716 : 78861765 : case RID_SIGNED:
3717 : 78861765 : case RID_COMPLEX:
3718 : 78861765 : case RID_INT:
3719 : 78861765 : case RID_CHAR:
3720 : 78861765 : case RID_FLOAT:
3721 : 78861765 : case RID_DOUBLE:
3722 : 78861765 : case RID_VOID:
3723 : 78861765 : case RID_DFLOAT32:
3724 : 78861765 : case RID_DFLOAT64:
3725 : 78861765 : case RID_DFLOAT128:
3726 : 78861765 : case RID_DFLOAT64X:
3727 : 78861765 : CASE_RID_FLOATN_NX:
3728 : 78861765 : case RID_BOOL:
3729 : 78861765 : case RID_FRACT:
3730 : 78861765 : case RID_ACCUM:
3731 : 78861765 : case RID_SAT:
3732 : 78861765 : case RID_INT_N_0:
3733 : 78861765 : case RID_INT_N_1:
3734 : 78861765 : case RID_INT_N_2:
3735 : 78861765 : case RID_INT_N_3:
3736 : 78861765 : if (!typespec_ok)
3737 : 0 : goto out;
3738 : 78861765 : attrs_ok = true;
3739 : 78861765 : seen_type = true;
3740 : 78861765 : if (c_dialect_objc ())
3741 : 0 : parser->objc_need_raw_identifier = true;
3742 : 78861765 : t.kind = ctsk_resword;
3743 : 78861765 : t.spec = c_parser_peek_token (parser)->value;
3744 : 78861765 : t.expr = NULL_TREE;
3745 : 78861765 : t.expr_const_operands = true;
3746 : 78861765 : t.has_enum_type_specifier = false;
3747 : 78861765 : declspecs_add_type (loc, specs, t);
3748 : 78861765 : c_parser_consume_token (parser);
3749 : 78861765 : break;
3750 : 230954 : case RID_ENUM:
3751 : 230954 : if (!typespec_ok)
3752 : 0 : goto out;
3753 : 230954 : attrs_ok = true;
3754 : 230954 : seen_type = true;
3755 : 230954 : t = c_parser_enum_specifier (parser);
3756 : 230954 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3757 : 230954 : declspecs_add_type (loc, specs, t);
3758 : 230954 : break;
3759 : 2156157 : case RID_STRUCT:
3760 : 2156157 : case RID_UNION:
3761 : 2156157 : if (!typespec_ok)
3762 : 0 : goto out;
3763 : 2156157 : attrs_ok = true;
3764 : 2156157 : seen_type = true;
3765 : 2156157 : t = c_parser_struct_or_union_specifier (parser);
3766 : 2156157 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3767 : 2156157 : declspecs_add_type (loc, specs, t);
3768 : 2156157 : break;
3769 : 806304 : case RID_TYPEOF:
3770 : 806304 : case RID_TYPEOF_UNQUAL:
3771 : : /* ??? The old parser rejected typeof after other type
3772 : : specifiers, but is a syntax error the best way of
3773 : : handling this? */
3774 : 806304 : if (!typespec_ok || seen_type)
3775 : 2 : goto out;
3776 : 806302 : attrs_ok = true;
3777 : 806302 : seen_type = true;
3778 : 806302 : t = c_parser_typeof_specifier (parser);
3779 : 806302 : declspecs_add_type (loc, specs, t);
3780 : 806302 : break;
3781 : 45466 : case RID_BITINT:
3782 : 45466 : if (!typespec_ok)
3783 : 0 : goto out;
3784 : : else
3785 : : {
3786 : 45466 : attrs_ok = true;
3787 : 45466 : seen_type = true;
3788 : 45466 : t.kind = ctsk_resword;
3789 : 45466 : t.spec = c_parser_peek_token (parser)->value;
3790 : 45466 : t.expr = error_mark_node;
3791 : 45466 : t.expr_const_operands = true;
3792 : 45466 : t.has_enum_type_specifier = false;
3793 : 45466 : c_parser_consume_token (parser);
3794 : 45466 : matching_parens parens;
3795 : 45466 : if (parens.require_open (parser))
3796 : : {
3797 : 45466 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
3798 : 45466 : t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3799 : 45466 : true).value;
3800 : 45466 : parens.skip_until_found_close (parser);
3801 : : }
3802 : 45466 : declspecs_add_type (loc, specs, t);
3803 : : }
3804 : 45466 : break;
3805 : 32300 : case RID_ATOMIC:
3806 : : /* C parser handling of Objective-C constructs needs
3807 : : checking for correct lvalue-to-rvalue conversions, and
3808 : : the code in build_modify_expr handling various
3809 : : Objective-C cases, and that in build_unary_op handling
3810 : : Objective-C cases for increment / decrement, also needs
3811 : : updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
3812 : : and objc_types_are_equivalent may also need updates. */
3813 : 32300 : if (c_dialect_objc ())
3814 : 0 : sorry ("%<_Atomic%> in Objective-C");
3815 : 32300 : if (flag_isoc99)
3816 : 32249 : pedwarn_c99 (loc, OPT_Wpedantic,
3817 : : "ISO C99 does not support the %<_Atomic%> qualifier");
3818 : : else
3819 : 51 : pedwarn_c99 (loc, OPT_Wpedantic,
3820 : : "ISO C90 does not support the %<_Atomic%> qualifier");
3821 : 32300 : attrs_ok = true;
3822 : 32300 : tree value;
3823 : 32300 : value = c_parser_peek_token (parser)->value;
3824 : 32300 : c_parser_consume_token (parser);
3825 : 64397 : if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN))
3826 : : {
3827 : : /* _Atomic ( type-name ). */
3828 : 13430 : seen_type = true;
3829 : 13430 : c_parser_consume_token (parser);
3830 : 13430 : struct c_type_name *type = c_parser_type_name (parser);
3831 : 13430 : t.kind = ctsk_typeof;
3832 : 13430 : t.spec = error_mark_node;
3833 : 13430 : t.expr = NULL_TREE;
3834 : 13430 : t.expr_const_operands = true;
3835 : 13430 : t.has_enum_type_specifier = false;
3836 : 13430 : if (type != NULL)
3837 : 13429 : t.spec = groktypename (type, &t.expr,
3838 : : &t.expr_const_operands);
3839 : 13430 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
3840 : : "expected %<)%>");
3841 : 13430 : if (t.spec != error_mark_node)
3842 : : {
3843 : 13429 : if (TREE_CODE (t.spec) == ARRAY_TYPE)
3844 : 1 : error_at (loc, "%<_Atomic%>-qualified array type");
3845 : 13428 : else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
3846 : 1 : error_at (loc, "%<_Atomic%>-qualified function type");
3847 : 13427 : else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
3848 : 4 : error_at (loc, "%<_Atomic%> applied to a qualified type");
3849 : : else
3850 : 13423 : t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
3851 : : }
3852 : 13430 : declspecs_add_type (loc, specs, t);
3853 : : }
3854 : : else
3855 : 18870 : declspecs_add_qual (loc, specs, value);
3856 : : break;
3857 : 16215428 : case RID_CONST:
3858 : 16215428 : case RID_VOLATILE:
3859 : 16215428 : case RID_RESTRICT:
3860 : 16215428 : attrs_ok = true;
3861 : 16215428 : declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3862 : 16215428 : c_parser_consume_token (parser);
3863 : 16215428 : break;
3864 : 34977627 : case RID_ATTRIBUTE:
3865 : 34977627 : if (!attrs_ok)
3866 : 0 : goto out;
3867 : 34977627 : attrs = c_parser_gnu_attributes (parser);
3868 : 34977627 : declspecs_add_attrs (loc, specs, attrs);
3869 : 34977627 : break;
3870 : 216 : case RID_ALIGNAS:
3871 : 216 : if (!alignspec_ok)
3872 : 16 : goto out;
3873 : 200 : align = c_parser_alignas_specifier (parser);
3874 : 200 : declspecs_add_alignas (loc, specs, align);
3875 : 200 : break;
3876 : 240 : case RID_GIMPLE:
3877 : 240 : if (! flag_gimple)
3878 : 0 : error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
3879 : 240 : c_parser_consume_token (parser);
3880 : 240 : specs->declspec_il = cdil_gimple;
3881 : 240 : specs->locations[cdw_gimple] = loc;
3882 : 240 : c_parser_gimple_or_rtl_pass_list (parser, specs);
3883 : 240 : break;
3884 : 25 : case RID_RTL:
3885 : 25 : c_parser_consume_token (parser);
3886 : 25 : specs->declspec_il = cdil_rtl;
3887 : 25 : specs->locations[cdw_rtl] = loc;
3888 : 25 : c_parser_gimple_or_rtl_pass_list (parser, specs);
3889 : 25 : break;
3890 : 2898 : default:
3891 : 2898 : goto out;
3892 : : }
3893 : : }
3894 : 323828926 : out:
3895 : 323828926 : if (end_std_attr_ok
3896 : 323828926 : && c_parser_nth_token_starts_std_attributes (parser, 1))
3897 : 115 : specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
3898 : 323828926 : }
3899 : :
3900 : : /* Complain about a non-CPP_NAME within an enumerator list. */
3901 : :
3902 : : static void
3903 : 11 : report_bad_enum_name (c_parser *parser)
3904 : : {
3905 : 11 : if (!parser->error)
3906 : : {
3907 : 11 : c_token *token = c_parser_peek_token (parser);
3908 : 11 : switch (token->type)
3909 : : {
3910 : : default:
3911 : : break;
3912 : 6 : case CPP_CLOSE_BRACE:
3913 : : /* Give a nicer error for "enum {}". */
3914 : 6 : error_at (token->location,
3915 : : "empty enum is invalid");
3916 : 6 : parser->error = true;
3917 : 6 : return;
3918 : 3 : case CPP_KEYWORD:
3919 : : /* Give a nicer error for attempts to use "true" and "false"
3920 : : in enums with C23 onwards. */
3921 : 3 : if (token->keyword == RID_FALSE
3922 : 2 : || token->keyword == RID_TRUE)
3923 : : {
3924 : 2 : auto_diagnostic_group d;
3925 : 4 : error_at (token->location,
3926 : : "cannot use keyword %qs as enumeration constant",
3927 : 2 : IDENTIFIER_POINTER (token->value));
3928 : 2 : add_note_about_new_keyword (token->location,
3929 : : token->value);
3930 : 2 : parser->error = true;
3931 : 2 : return;
3932 : 2 : }
3933 : : break;
3934 : : }
3935 : : }
3936 : :
3937 : : /* Otherwise, a more generic error message. */
3938 : 3 : c_parser_error (parser, "expected identifier");
3939 : : }
3940 : :
3941 : : /* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
3942 : :
3943 : : enum-specifier:
3944 : : enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3945 : : { enumerator-list } gnu-attributes[opt]
3946 : : enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3947 : : { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
3948 : : enum gnu-attributes[opt] identifier
3949 : :
3950 : : The form with trailing comma is new in C99; enum-type-specifiers
3951 : : are new in C23. The forms with gnu-attributes are GNU extensions.
3952 : : In GNU C, we accept any expression without commas in the syntax
3953 : : (assignment expressions, not just conditional expressions);
3954 : : assignment expressions will be diagnosed as non-constant.
3955 : :
3956 : : enum-type-specifier:
3957 : : : specifier-qualifier-list
3958 : :
3959 : : enumerator-list:
3960 : : enumerator
3961 : : enumerator-list , enumerator
3962 : :
3963 : : enumerator:
3964 : : enumeration-constant attribute-specifier-sequence[opt]
3965 : : enumeration-constant attribute-specifier-sequence[opt]
3966 : : = constant-expression
3967 : :
3968 : : GNU Extensions:
3969 : :
3970 : : enumerator:
3971 : : enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3972 : : enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3973 : : = constant-expression
3974 : :
3975 : : */
3976 : :
3977 : : static struct c_typespec
3978 : 230954 : c_parser_enum_specifier (c_parser *parser)
3979 : : {
3980 : 230954 : struct c_typespec ret;
3981 : 230954 : bool have_std_attrs;
3982 : 230954 : bool potential_nesting_p = false;
3983 : 230954 : tree std_attrs = NULL_TREE;
3984 : 230954 : tree attrs;
3985 : 230954 : tree ident = NULL_TREE;
3986 : 230954 : tree fixed_underlying_type = NULL_TREE;
3987 : 230954 : location_t enum_loc;
3988 : 230954 : location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3989 : 230954 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
3990 : 230954 : c_parser_consume_token (parser);
3991 : 230954 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3992 : 230954 : if (have_std_attrs)
3993 : 14 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3994 : 230954 : attrs = c_parser_gnu_attributes (parser);
3995 : 230954 : enum_loc = c_parser_peek_token (parser)->location;
3996 : : /* Set the location in case we create a decl now. */
3997 : 230954 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
3998 : 230954 : if (c_parser_next_token_is (parser, CPP_NAME))
3999 : : {
4000 : 125845 : ident = c_parser_peek_token (parser)->value;
4001 : 125845 : ident_loc = c_parser_peek_token (parser)->location;
4002 : 125845 : enum_loc = ident_loc;
4003 : 125845 : c_parser_consume_token (parser);
4004 : : }
4005 : 230954 : if (c_parser_next_token_is (parser, CPP_COLON)
4006 : : /* Distinguish an enum-type-specifier from a bit-field
4007 : : declaration of the form "enum e : constant-expression;". */
4008 : 230954 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
4009 : : {
4010 : 166 : pedwarn_c11 (enum_loc, OPT_Wpedantic,
4011 : : "ISO C does not support specifying %<enum%> underlying "
4012 : : "types before C23");
4013 : 166 : if (ident)
4014 : : {
4015 : : /* The tag is in scope during the enum-type-specifier (which
4016 : : may refer to the tag inside typeof). */
4017 : 162 : ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
4018 : : have_std_attrs, std_attrs, true);
4019 : 162 : if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
4020 : 3 : error_at (enum_loc, "%<enum%> declared both with and without "
4021 : : "fixed underlying type");
4022 : 162 : potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
4023 : : }
4024 : : else
4025 : : {
4026 : : /* There must be an enum definition, so this initialization
4027 : : (to avoid possible warnings about uninitialized data)
4028 : : will be replaced later (either with the results of that
4029 : : definition, or with the results of error handling for the
4030 : : case of no tag and no definition). */
4031 : 4 : ret.spec = NULL_TREE;
4032 : 4 : ret.kind = ctsk_tagdef;
4033 : 4 : ret.expr = NULL_TREE;
4034 : 4 : ret.expr_const_operands = true;
4035 : 4 : ret.has_enum_type_specifier = true;
4036 : : }
4037 : 166 : c_parser_consume_token (parser);
4038 : 166 : struct c_declspecs *specs = build_null_declspecs ();
4039 : 166 : c_parser_declspecs (parser, specs, false, true, false, false, false,
4040 : : false, true, cla_prefer_id);
4041 : 166 : finish_declspecs (specs);
4042 : 166 : if (specs->default_int_p)
4043 : 1 : error_at (enum_loc, "no %<enum%> underlying type specified");
4044 : 165 : else if (TREE_CODE (specs->type) != INTEGER_TYPE
4045 : 165 : && TREE_CODE (specs->type) != BOOLEAN_TYPE)
4046 : : {
4047 : 9 : error_at (enum_loc, "invalid %<enum%> underlying type");
4048 : 9 : specs->type = integer_type_node;
4049 : : }
4050 : 156 : else if (specs->restrict_p)
4051 : 1 : error_at (enum_loc, "invalid use of %<restrict%>");
4052 : 166 : fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
4053 : 166 : if (ident)
4054 : : {
4055 : : /* The type specified must be consistent with any previously
4056 : : specified underlying type. If this is a newly declared
4057 : : type, it is now a complete type. */
4058 : 162 : if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4059 : 162 : && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
4060 : : {
4061 : 423 : TYPE_MIN_VALUE (ret.spec) =
4062 : 141 : TYPE_MIN_VALUE (fixed_underlying_type);
4063 : 423 : TYPE_MAX_VALUE (ret.spec) =
4064 : 141 : TYPE_MAX_VALUE (fixed_underlying_type);
4065 : 141 : TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
4066 : 141 : SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
4067 : 141 : TYPE_SIZE (ret.spec) = NULL_TREE;
4068 : 141 : TYPE_PRECISION (ret.spec) =
4069 : 141 : TYPE_PRECISION (fixed_underlying_type);
4070 : 141 : ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
4071 : 141 : layout_type (ret.spec);
4072 : : }
4073 : 21 : else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4074 : 37 : && !comptypes (fixed_underlying_type,
4075 : 16 : ENUM_UNDERLYING_TYPE (ret.spec)))
4076 : : {
4077 : 3 : error_at (enum_loc, "%<enum%> underlying type incompatible with "
4078 : : "previous declaration");
4079 : 3 : fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
4080 : : }
4081 : : }
4082 : : }
4083 : 230954 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
4084 : : {
4085 : : /* Parse an enum definition. */
4086 : 174178 : struct c_enum_contents the_enum;
4087 : 174178 : tree type;
4088 : 174178 : tree postfix_attrs;
4089 : : /* We chain the enumerators in reverse order, then put them in
4090 : : forward order at the end. */
4091 : 174178 : tree values;
4092 : 174178 : timevar_push (TV_PARSE_ENUM);
4093 : 174178 : type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
4094 : : potential_nesting_p);
4095 : 174178 : values = NULL_TREE;
4096 : 174178 : c_parser_consume_token (parser);
4097 : 5547098 : while (true)
4098 : : {
4099 : 5547098 : tree enum_id;
4100 : 5547098 : tree enum_value;
4101 : 5547098 : tree enum_decl;
4102 : 5547098 : bool seen_comma;
4103 : 5547098 : c_token *token;
4104 : 5547098 : location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4105 : 5547098 : location_t decl_loc, value_loc;
4106 : 5547098 : if (c_parser_next_token_is_not (parser, CPP_NAME))
4107 : : {
4108 : 11 : report_bad_enum_name (parser);
4109 : 11 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4110 : 11 : values = error_mark_node;
4111 : 11 : break;
4112 : : }
4113 : 5547087 : token = c_parser_peek_token (parser);
4114 : 5547087 : enum_id = token->value;
4115 : : /* Set the location in case we create a decl now. */
4116 : 5547087 : c_parser_set_source_position_from_token (token);
4117 : 5547087 : decl_loc = value_loc = token->location;
4118 : 5547087 : c_parser_consume_token (parser);
4119 : : /* Parse any specified attributes. */
4120 : 5547087 : tree std_attrs = NULL_TREE;
4121 : 5547087 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
4122 : 12 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4123 : 5547087 : tree enum_attrs = chainon (std_attrs,
4124 : : c_parser_gnu_attributes (parser));
4125 : 5547087 : if (c_parser_next_token_is (parser, CPP_EQ))
4126 : : {
4127 : 3425615 : c_parser_consume_token (parser);
4128 : 3425615 : value_loc = c_parser_peek_token (parser)->location;
4129 : 3425615 : enum_value = convert_lvalue_to_rvalue (value_loc,
4130 : : (c_parser_expr_no_commas
4131 : : (parser, NULL)),
4132 : : true, true).value;
4133 : : }
4134 : : else
4135 : : enum_value = NULL_TREE;
4136 : 5547087 : enum_decl = build_enumerator (decl_loc, value_loc,
4137 : : &the_enum, enum_id, enum_value);
4138 : 5547087 : if (enum_attrs)
4139 : 20 : decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
4140 : 5547087 : TREE_CHAIN (enum_decl) = values;
4141 : 5547087 : values = enum_decl;
4142 : 5547087 : seen_comma = false;
4143 : 5547087 : if (c_parser_next_token_is (parser, CPP_COMMA))
4144 : : {
4145 : 5393113 : comma_loc = c_parser_peek_token (parser)->location;
4146 : 5393113 : seen_comma = true;
4147 : 5393113 : c_parser_consume_token (parser);
4148 : : }
4149 : 5547087 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4150 : : {
4151 : 174152 : if (seen_comma)
4152 : 20193 : pedwarn_c90 (comma_loc, OPT_Wpedantic,
4153 : : "comma at end of enumerator list");
4154 : 174152 : c_parser_consume_token (parser);
4155 : 174152 : break;
4156 : : }
4157 : 5372935 : if (!seen_comma)
4158 : : {
4159 : 15 : c_parser_error (parser, "expected %<,%> or %<}%>");
4160 : 15 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4161 : 15 : values = error_mark_node;
4162 : 15 : break;
4163 : : }
4164 : : }
4165 : 174178 : postfix_attrs = c_parser_gnu_attributes (parser);
4166 : 174178 : ret.spec = finish_enum (type, nreverse (values),
4167 : : chainon (std_attrs,
4168 : : chainon (attrs, postfix_attrs)));
4169 : 174178 : ret.kind = ctsk_tagdef;
4170 : 174178 : ret.expr = NULL_TREE;
4171 : 174178 : ret.expr_const_operands = true;
4172 : 174178 : ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
4173 : 174178 : timevar_pop (TV_PARSE_ENUM);
4174 : 174178 : return ret;
4175 : : }
4176 : 56776 : else if (!ident)
4177 : : {
4178 : 1 : c_parser_error (parser, "expected %<{%>");
4179 : 1 : ret.spec = error_mark_node;
4180 : 1 : ret.kind = ctsk_tagref;
4181 : 1 : ret.expr = NULL_TREE;
4182 : 1 : ret.expr_const_operands = true;
4183 : 1 : ret.has_enum_type_specifier = false;
4184 : 1 : return ret;
4185 : : }
4186 : : /* Attributes may only appear when the members are defined or in
4187 : : certain forward declarations (treat enum forward declarations in
4188 : : GNU C analogously to struct and union forward declarations in
4189 : : standard C). */
4190 : 56776 : if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
4191 : 1 : c_parser_error (parser, "expected %<;%>");
4192 : 56775 : if (fixed_underlying_type == NULL_TREE)
4193 : : {
4194 : 56726 : ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
4195 : : std_attrs, false);
4196 : : /* In ISO C, enumerated types without a fixed underlying type
4197 : : can be referred to only if already defined. */
4198 : 56726 : if (pedantic && !COMPLETE_TYPE_P (ret.spec))
4199 : : {
4200 : 11 : gcc_assert (ident);
4201 : 11 : pedwarn (enum_loc, OPT_Wpedantic,
4202 : : "ISO C forbids forward references to %<enum%> types");
4203 : : }
4204 : : }
4205 : : return ret;
4206 : : }
4207 : :
4208 : : /* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
4209 : :
4210 : : struct-or-union-specifier:
4211 : : struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4212 : : identifier[opt] { struct-contents } gnu-attributes[opt]
4213 : : struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4214 : : identifier
4215 : :
4216 : : struct-contents:
4217 : : struct-declaration-list
4218 : :
4219 : : struct-declaration-list:
4220 : : struct-declaration ;
4221 : : struct-declaration-list struct-declaration ;
4222 : :
4223 : : GNU extensions:
4224 : :
4225 : : struct-contents:
4226 : : empty
4227 : : struct-declaration
4228 : : struct-declaration-list struct-declaration
4229 : :
4230 : : struct-declaration-list:
4231 : : struct-declaration-list ;
4232 : : ;
4233 : :
4234 : : (Note that in the syntax here, unlike that in ISO C, the semicolons
4235 : : are included here rather than in struct-declaration, in order to
4236 : : describe the syntax with extra semicolons and missing semicolon at
4237 : : end.)
4238 : :
4239 : : Objective-C:
4240 : :
4241 : : struct-declaration-list:
4242 : : @defs ( class-name )
4243 : :
4244 : : (Note this does not include a trailing semicolon, but can be
4245 : : followed by further declarations, and gets a pedwarn-if-pedantic
4246 : : when followed by a semicolon.) */
4247 : :
4248 : : static struct c_typespec
4249 : 2156157 : c_parser_struct_or_union_specifier (c_parser *parser)
4250 : : {
4251 : 2156157 : struct c_typespec ret;
4252 : 2156157 : bool have_std_attrs;
4253 : 2156157 : tree std_attrs = NULL_TREE;
4254 : 2156157 : tree attrs;
4255 : 2156157 : tree ident = NULL_TREE;
4256 : 2156157 : location_t struct_loc;
4257 : 2156157 : location_t ident_loc = UNKNOWN_LOCATION;
4258 : 2156157 : enum tree_code code;
4259 : 2156157 : switch (c_parser_peek_token (parser)->keyword)
4260 : : {
4261 : : case RID_STRUCT:
4262 : : code = RECORD_TYPE;
4263 : : break;
4264 : 405954 : case RID_UNION:
4265 : 405954 : code = UNION_TYPE;
4266 : 405954 : break;
4267 : 0 : default:
4268 : 0 : gcc_unreachable ();
4269 : : }
4270 : 2156157 : struct_loc = c_parser_peek_token (parser)->location;
4271 : 2156157 : c_parser_consume_token (parser);
4272 : 2156157 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4273 : 2156157 : if (have_std_attrs)
4274 : 34 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4275 : 2156157 : attrs = c_parser_gnu_attributes (parser);
4276 : :
4277 : : /* Set the location in case we create a decl now. */
4278 : 2156157 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
4279 : :
4280 : 2156157 : if (c_parser_next_token_is (parser, CPP_NAME))
4281 : : {
4282 : 1481058 : ident = c_parser_peek_token (parser)->value;
4283 : 1481058 : ident_loc = c_parser_peek_token (parser)->location;
4284 : 1481058 : struct_loc = ident_loc;
4285 : 1481058 : c_parser_consume_token (parser);
4286 : : }
4287 : 2156157 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
4288 : : {
4289 : : /* Parse a struct or union definition. Start the scope of the
4290 : : tag before parsing components. */
4291 : 1149636 : class c_struct_parse_info *struct_info;
4292 : 1149636 : tree type = start_struct (struct_loc, code, ident, &struct_info);
4293 : 1149636 : tree postfix_attrs;
4294 : : /* We chain the components in reverse order, then put them in
4295 : : forward order at the end. Each struct-declaration may
4296 : : declare multiple components (comma-separated), so we must use
4297 : : chainon to join them, although when parsing each
4298 : : struct-declaration we can use TREE_CHAIN directly.
4299 : :
4300 : : The theory behind all this is that there will be more
4301 : : semicolon separated fields than comma separated fields, and
4302 : : so we'll be minimizing the number of node traversals required
4303 : : by chainon. */
4304 : 1149636 : tree contents;
4305 : 1149636 : tree expr = NULL;
4306 : 1149636 : timevar_push (TV_PARSE_STRUCT);
4307 : 1149636 : contents = NULL_TREE;
4308 : 1149636 : c_parser_consume_token (parser);
4309 : : /* Handle the Objective-C @defs construct,
4310 : : e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4311 : 1149636 : if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
4312 : : {
4313 : 0 : tree name;
4314 : 0 : gcc_assert (c_dialect_objc ());
4315 : 0 : c_parser_consume_token (parser);
4316 : 0 : matching_parens parens;
4317 : 0 : if (!parens.require_open (parser))
4318 : 0 : goto end_at_defs;
4319 : 0 : if (c_parser_next_token_is (parser, CPP_NAME)
4320 : 0 : && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4321 : : {
4322 : 0 : name = c_parser_peek_token (parser)->value;
4323 : 0 : c_parser_consume_token (parser);
4324 : : }
4325 : : else
4326 : : {
4327 : 0 : c_parser_error (parser, "expected class name");
4328 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
4329 : 0 : goto end_at_defs;
4330 : : }
4331 : 0 : parens.skip_until_found_close (parser);
4332 : 0 : contents = nreverse (objc_get_class_ivars (name));
4333 : : }
4334 : 1149636 : end_at_defs:
4335 : : /* Parse the struct-declarations and semicolons. Problems with
4336 : : semicolons are diagnosed here; empty structures are diagnosed
4337 : : elsewhere. */
4338 : 5250705 : while (true)
4339 : : {
4340 : 5250705 : tree decls;
4341 : : /* Parse any stray semicolon. */
4342 : 5250705 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
4343 : : {
4344 : 13 : location_t semicolon_loc
4345 : 13 : = c_parser_peek_token (parser)->location;
4346 : 13 : gcc_rich_location richloc (semicolon_loc);
4347 : 13 : richloc.add_fixit_remove ();
4348 : 13 : pedwarn (&richloc, OPT_Wpedantic,
4349 : : "extra semicolon in struct or union specified");
4350 : 13 : c_parser_consume_token (parser);
4351 : 13 : continue;
4352 : 13 : }
4353 : : /* Stop if at the end of the struct or union contents. */
4354 : 5250692 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4355 : : {
4356 : 1149627 : c_parser_consume_token (parser);
4357 : 1149627 : break;
4358 : : }
4359 : : /* Accept #pragmas at struct scope. */
4360 : 4101065 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
4361 : : {
4362 : 20 : c_parser_pragma (parser, pragma_struct, NULL, NULL_TREE);
4363 : 20 : continue;
4364 : : }
4365 : : /* Parse some comma-separated declarations, but not the
4366 : : trailing semicolon if any. */
4367 : 4101045 : decls = c_parser_struct_declaration (parser, &expr);
4368 : 4101045 : contents = chainon (decls, contents);
4369 : : /* If no semicolon follows, either we have a parse error or
4370 : : are at the end of the struct or union and should
4371 : : pedwarn. */
4372 : 4101045 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
4373 : 4101009 : c_parser_consume_token (parser);
4374 : : else
4375 : : {
4376 : 36 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4377 : 25 : pedwarn (c_parser_peek_token (parser)->location, 0,
4378 : : "no semicolon at end of struct or union");
4379 : 11 : else if (parser->error
4380 : 11 : || !c_parser_next_token_starts_declspecs (parser))
4381 : : {
4382 : 9 : c_parser_error (parser, "expected %<;%>");
4383 : 9 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
4384 : 9 : break;
4385 : : }
4386 : :
4387 : : /* If we come here, we have already emitted an error
4388 : : for an expected `;', identifier or `(', and we also
4389 : : recovered already. Go on with the next field. */
4390 : : }
4391 : : }
4392 : 1149636 : postfix_attrs = c_parser_gnu_attributes (parser);
4393 : 1149636 : ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4394 : : chainon (std_attrs,
4395 : : chainon (attrs, postfix_attrs)),
4396 : : struct_info, &expr);
4397 : 1149636 : ret.kind = ctsk_tagdef;
4398 : 1149636 : ret.expr = expr;
4399 : 1149636 : ret.expr_const_operands = true;
4400 : 1149636 : ret.has_enum_type_specifier = false;
4401 : 1149636 : timevar_pop (TV_PARSE_STRUCT);
4402 : 1149636 : return ret;
4403 : : }
4404 : 1006521 : else if (!ident)
4405 : : {
4406 : 10 : c_parser_error (parser, "expected %<{%>");
4407 : 10 : ret.spec = error_mark_node;
4408 : 10 : ret.kind = ctsk_tagref;
4409 : 10 : ret.expr = NULL_TREE;
4410 : 10 : ret.expr_const_operands = true;
4411 : 10 : ret.has_enum_type_specifier = false;
4412 : 10 : return ret;
4413 : : }
4414 : : /* Attributes may only appear when the members are defined or in
4415 : : certain forward declarations. */
4416 : 1006521 : if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
4417 : 2 : c_parser_error (parser, "expected %<;%>");
4418 : : /* ??? Existing practice is that GNU attributes are ignored after
4419 : : the struct or union keyword when not defining the members. */
4420 : 1006511 : ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4421 : : false);
4422 : 1006511 : return ret;
4423 : : }
4424 : :
4425 : : /* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4426 : : *without* the trailing semicolon.
4427 : :
4428 : : struct-declaration:
4429 : : attribute-specifier-sequence[opt] specifier-qualifier-list
4430 : : attribute-specifier-sequence[opt] struct-declarator-list
4431 : : static_assert-declaration-no-semi
4432 : :
4433 : : specifier-qualifier-list:
4434 : : type-specifier specifier-qualifier-list[opt]
4435 : : type-qualifier specifier-qualifier-list[opt]
4436 : : alignment-specifier specifier-qualifier-list[opt]
4437 : : gnu-attributes specifier-qualifier-list[opt]
4438 : :
4439 : : struct-declarator-list:
4440 : : struct-declarator
4441 : : struct-declarator-list , gnu-attributes[opt] struct-declarator
4442 : :
4443 : : struct-declarator:
4444 : : declarator gnu-attributes[opt]
4445 : : declarator[opt] : constant-expression gnu-attributes[opt]
4446 : :
4447 : : GNU extensions:
4448 : :
4449 : : struct-declaration:
4450 : : __extension__ struct-declaration
4451 : : specifier-qualifier-list
4452 : :
4453 : : Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4454 : : of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4455 : : any expression without commas in the syntax (assignment
4456 : : expressions, not just conditional expressions); assignment
4457 : : expressions will be diagnosed as non-constant. */
4458 : :
4459 : : static tree
4460 : 4164518 : c_parser_struct_declaration (c_parser *parser, tree *expr)
4461 : : {
4462 : 4164518 : struct c_declspecs *specs;
4463 : 4164518 : tree prefix_attrs;
4464 : 4164518 : tree all_prefix_attrs;
4465 : 4164518 : tree decls;
4466 : 4164518 : location_t decl_loc;
4467 : 4164518 : if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
4468 : : {
4469 : 63473 : int ext;
4470 : 63473 : tree decl;
4471 : 63473 : ext = disable_extension_diagnostics ();
4472 : 63473 : c_parser_consume_token (parser);
4473 : 63473 : decl = c_parser_struct_declaration (parser, expr);
4474 : 63473 : restore_extension_diagnostics (ext);
4475 : 63473 : return decl;
4476 : : }
4477 : 4101045 : if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
4478 : : {
4479 : 10 : c_parser_static_assert_declaration_no_semi (parser);
4480 : 10 : return NULL_TREE;
4481 : : }
4482 : 4101035 : specs = build_null_declspecs ();
4483 : 4101035 : decl_loc = c_parser_peek_token (parser)->location;
4484 : : /* Strictly by the standard, we shouldn't allow _Alignas here,
4485 : : but it appears to have been intended to allow it there, so
4486 : : we're keeping it as it is until WG14 reaches a conclusion
4487 : : of N1731.
4488 : : <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4489 : 4101035 : c_parser_declspecs (parser, specs, false, true, true,
4490 : : true, false, true, true, cla_nonabstract_decl);
4491 : 4101035 : if (parser->error)
4492 : : return NULL_TREE;
4493 : 4101027 : if (!specs->declspecs_seen_p)
4494 : : {
4495 : 1 : c_parser_error (parser, "expected specifier-qualifier-list");
4496 : 1 : return NULL_TREE;
4497 : : }
4498 : 4101026 : finish_declspecs (specs);
4499 : 4101026 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4500 : 8191583 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4501 : : {
4502 : 10473 : tree ret;
4503 : 10473 : if (specs->typespec_kind == ctsk_none)
4504 : : {
4505 : 3 : pedwarn (decl_loc, OPT_Wpedantic,
4506 : : "ISO C forbids member declarations with no members");
4507 : 3 : shadow_tag_warned (specs, pedantic);
4508 : 3 : ret = NULL_TREE;
4509 : : }
4510 : : else
4511 : : {
4512 : : /* Support for unnamed structs or unions as members of
4513 : : structs or unions (which is [a] useful and [b] supports
4514 : : MS P-SDK). */
4515 : 10470 : tree attrs = NULL;
4516 : :
4517 : 10470 : ret = grokfield (c_parser_peek_token (parser)->location,
4518 : : build_id_declarator (NULL_TREE), specs,
4519 : : NULL_TREE, &attrs, expr);
4520 : 10470 : if (ret)
4521 : 10441 : decl_attributes (&ret, attrs, 0);
4522 : : }
4523 : 10473 : return ret;
4524 : : }
4525 : :
4526 : : /* Provide better error recovery. Note that a type name here is valid,
4527 : : and will be treated as a field name. */
4528 : 4090553 : if (specs->typespec_kind == ctsk_tagdef
4529 : 149478 : && TREE_CODE (specs->type) != ENUMERAL_TYPE
4530 : 149325 : && c_parser_next_token_starts_declspecs (parser)
4531 : 4090555 : && !c_parser_next_token_is (parser, CPP_NAME))
4532 : : {
4533 : 2 : c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
4534 : 2 : parser->error = false;
4535 : 2 : return NULL_TREE;
4536 : : }
4537 : :
4538 : 4090551 : pending_xref_error ();
4539 : 4090551 : prefix_attrs = specs->attrs;
4540 : 4090551 : all_prefix_attrs = prefix_attrs;
4541 : 4090551 : specs->attrs = NULL_TREE;
4542 : 4090551 : decls = NULL_TREE;
4543 : 57293 : while (true)
4544 : : {
4545 : : /* Declaring one or more declarators or un-named bit-fields. */
4546 : 4147844 : struct c_declarator *declarator;
4547 : 4147844 : bool dummy = false;
4548 : 4147844 : if (c_parser_next_token_is (parser, CPP_COLON))
4549 : 9186 : declarator = build_id_declarator (NULL_TREE);
4550 : : else
4551 : 4138658 : declarator = c_parser_declarator (parser,
4552 : 4138658 : specs->typespec_kind != ctsk_none,
4553 : : C_DTR_NORMAL, &dummy);
4554 : 4147844 : if (declarator == NULL)
4555 : : {
4556 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
4557 : 1 : break;
4558 : : }
4559 : 4147843 : if (c_parser_next_token_is (parser, CPP_COLON)
4560 : 4096052 : || c_parser_next_token_is (parser, CPP_COMMA)
4561 : 4040957 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
4562 : 32480 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
4563 : 4180303 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4564 : : {
4565 : 4147843 : tree postfix_attrs = NULL_TREE;
4566 : 4147843 : tree width = NULL_TREE;
4567 : 4147843 : tree d;
4568 : 4147843 : if (c_parser_next_token_is (parser, CPP_COLON))
4569 : : {
4570 : 51791 : c_parser_consume_token (parser);
4571 : 51791 : location_t loc = c_parser_peek_token (parser)->location;
4572 : 51791 : width = convert_lvalue_to_rvalue (loc,
4573 : : (c_parser_expr_no_commas
4574 : : (parser, NULL)),
4575 : : true, true).value;
4576 : : }
4577 : 4147843 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4578 : 32641 : postfix_attrs = c_parser_gnu_attributes (parser);
4579 : 4147843 : d = grokfield (c_parser_peek_token (parser)->location,
4580 : : declarator, specs, width, &all_prefix_attrs, expr);
4581 : 4147843 : decl_attributes (&d, chainon (postfix_attrs,
4582 : : all_prefix_attrs), 0);
4583 : 4147843 : DECL_CHAIN (d) = decls;
4584 : 4147843 : decls = d;
4585 : 4147843 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4586 : 0 : all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4587 : : prefix_attrs);
4588 : : else
4589 : 4147843 : all_prefix_attrs = prefix_attrs;
4590 : 4147843 : if (c_parser_next_token_is (parser, CPP_COMMA))
4591 : 57293 : c_parser_consume_token (parser);
4592 : 4090550 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4593 : 4090570 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4594 : : {
4595 : : /* Semicolon consumed in caller. */
4596 : : break;
4597 : : }
4598 : : else
4599 : : {
4600 : 0 : c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
4601 : 0 : break;
4602 : : }
4603 : : }
4604 : : else
4605 : : {
4606 : 0 : c_parser_error (parser,
4607 : : "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4608 : : "%<__attribute__%>");
4609 : 0 : break;
4610 : : }
4611 : : }
4612 : 4090551 : return decls;
4613 : : }
4614 : :
4615 : : /* Parse a typeof specifier (a GNU extension adopted in C23).
4616 : :
4617 : : typeof-specifier:
4618 : : typeof ( expression )
4619 : : typeof ( type-name )
4620 : : typeof_unqual ( expression )
4621 : : typeof_unqual ( type-name )
4622 : : */
4623 : :
4624 : : static struct c_typespec
4625 : 806302 : c_parser_typeof_specifier (c_parser *parser)
4626 : : {
4627 : 806302 : bool is_unqual;
4628 : 806302 : bool is_std;
4629 : 806302 : struct c_typespec ret;
4630 : 806302 : ret.kind = ctsk_typeof;
4631 : 806302 : ret.spec = error_mark_node;
4632 : 806302 : ret.expr = NULL_TREE;
4633 : 806302 : ret.expr_const_operands = true;
4634 : 806302 : ret.has_enum_type_specifier = false;
4635 : 806302 : if (c_parser_next_token_is_keyword (parser, RID_TYPEOF))
4636 : : {
4637 : 806210 : is_unqual = false;
4638 : 806210 : tree spelling = c_parser_peek_token (parser)->value;
4639 : 806210 : is_std = (flag_isoc23
4640 : 897302 : && strcmp (IDENTIFIER_POINTER (spelling), "typeof") == 0);
4641 : : }
4642 : : else
4643 : : {
4644 : 92 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4645 : 92 : is_unqual = true;
4646 : 92 : tree spelling = c_parser_peek_token (parser)->value;
4647 : 92 : is_std = strcmp (IDENTIFIER_POINTER (spelling), "typeof_unqual") == 0;
4648 : : }
4649 : 806302 : c_parser_consume_token (parser);
4650 : 806302 : c_inhibit_evaluation_warnings++;
4651 : 806302 : in_typeof++;
4652 : 806302 : matching_parens parens;
4653 : 806302 : if (!parens.require_open (parser))
4654 : : {
4655 : 0 : c_inhibit_evaluation_warnings--;
4656 : 0 : in_typeof--;
4657 : 0 : return ret;
4658 : : }
4659 : 806302 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
4660 : : {
4661 : 685 : struct c_type_name *type = c_parser_type_name (parser);
4662 : 685 : c_inhibit_evaluation_warnings--;
4663 : 685 : in_typeof--;
4664 : 685 : if (type != NULL)
4665 : : {
4666 : 685 : ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4667 : 685 : pop_maybe_used (c_type_variably_modified_p (ret.spec));
4668 : : }
4669 : : }
4670 : : else
4671 : : {
4672 : 805617 : bool was_vm;
4673 : 805617 : location_t here = c_parser_peek_token (parser)->location;
4674 : 805617 : struct c_expr expr = c_parser_expression (parser);
4675 : 805617 : c_inhibit_evaluation_warnings--;
4676 : 805617 : in_typeof--;
4677 : 805617 : if (TREE_CODE (expr.value) == COMPONENT_REF
4678 : 805617 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4679 : 13 : error_at (here, "%<typeof%> applied to a bit-field");
4680 : 805617 : mark_exp_read (expr.value);
4681 : 805617 : ret.spec = TREE_TYPE (expr.value);
4682 : 805617 : was_vm = c_type_variably_modified_p (ret.spec);
4683 : : /* This is returned with the type so that when the type is
4684 : : evaluated, this can be evaluated. */
4685 : 805617 : if (was_vm)
4686 : 215 : ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4687 : 805617 : pop_maybe_used (was_vm);
4688 : : }
4689 : 806302 : parens.skip_until_found_close (parser);
4690 : 806302 : if (ret.spec != error_mark_node)
4691 : : {
4692 : 806291 : if (is_unqual)
4693 : : {
4694 : 92 : bool is_array = TREE_CODE (ret.spec) == ARRAY_TYPE;
4695 : 92 : int quals = TYPE_QUALS (strip_array_types (ret.spec));
4696 : 92 : if ((is_array ? quals & ~TYPE_QUAL_ATOMIC : quals)
4697 : : != TYPE_UNQUALIFIED)
4698 : : {
4699 : 51 : ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4700 : 51 : if (quals & TYPE_QUAL_ATOMIC && is_array)
4701 : 4 : ret.spec = c_build_qualified_type (ret.spec,
4702 : : TYPE_QUAL_ATOMIC);
4703 : : }
4704 : : }
4705 : 806291 : if (is_std)
4706 : : {
4707 : : /* In ISO C terms, _Noreturn is not part of the type of
4708 : : expressions such as &abort, but in GCC it is represented
4709 : : internally as a type qualifier. */
4710 : 4243 : if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4711 : 4243 : && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4712 : 2 : ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4713 : 2899 : else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4714 : 7069 : && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4715 : 2 : ret.spec
4716 : 2 : = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4717 : : }
4718 : : }
4719 : : return ret;
4720 : : }
4721 : :
4722 : : /* Parse an alignment-specifier.
4723 : :
4724 : : C11 6.7.5:
4725 : :
4726 : : alignment-specifier:
4727 : : _Alignas ( type-name )
4728 : : _Alignas ( constant-expression )
4729 : : */
4730 : :
4731 : : static tree
4732 : 200 : c_parser_alignas_specifier (c_parser * parser)
4733 : : {
4734 : 200 : tree ret = error_mark_node;
4735 : 200 : location_t loc = c_parser_peek_token (parser)->location;
4736 : 200 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4737 : 200 : tree spelling = c_parser_peek_token (parser)->value;
4738 : 200 : c_parser_consume_token (parser);
4739 : 200 : if (flag_isoc99)
4740 : 197 : pedwarn_c99 (loc, OPT_Wpedantic,
4741 : : "ISO C99 does not support %qE", spelling);
4742 : : else
4743 : 3 : pedwarn_c99 (loc, OPT_Wpedantic,
4744 : : "ISO C90 does not support %qE", spelling);
4745 : 200 : matching_parens parens;
4746 : 200 : if (!parens.require_open (parser))
4747 : : return ret;
4748 : 200 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
4749 : : {
4750 : 132 : struct c_type_name *type = c_parser_type_name (parser);
4751 : 132 : if (type != NULL)
4752 : 131 : ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4753 : : false, true, 1);
4754 : : }
4755 : : else
4756 : 68 : ret = convert_lvalue_to_rvalue (loc,
4757 : : c_parser_expr_no_commas (parser, NULL),
4758 : : true, true).value;
4759 : 200 : parens.skip_until_found_close (parser);
4760 : 200 : return ret;
4761 : : }
4762 : :
4763 : : /* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4764 : : 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4765 : : a typedef name may be redeclared; otherwise it may not. KIND
4766 : : indicates which kind of declarator is wanted. Returns a valid
4767 : : declarator except in the case of a syntax error in which case NULL is
4768 : : returned. *SEEN_ID is set to true if an identifier being declared is
4769 : : seen; this is used to diagnose bad forms of abstract array declarators
4770 : : and to determine whether an identifier list is syntactically permitted.
4771 : :
4772 : : declarator:
4773 : : pointer[opt] direct-declarator
4774 : :
4775 : : direct-declarator:
4776 : : identifier
4777 : : ( gnu-attributes[opt] declarator )
4778 : : direct-declarator array-declarator
4779 : : direct-declarator ( parameter-type-list )
4780 : : direct-declarator ( identifier-list[opt] )
4781 : :
4782 : : pointer:
4783 : : * type-qualifier-list[opt]
4784 : : * type-qualifier-list[opt] pointer
4785 : :
4786 : : type-qualifier-list:
4787 : : type-qualifier
4788 : : gnu-attributes
4789 : : type-qualifier-list type-qualifier
4790 : : type-qualifier-list gnu-attributes
4791 : :
4792 : : array-declarator:
4793 : : [ type-qualifier-list[opt] assignment-expression[opt] ]
4794 : : [ static type-qualifier-list[opt] assignment-expression ]
4795 : : [ type-qualifier-list static assignment-expression ]
4796 : : [ type-qualifier-list[opt] * ]
4797 : :
4798 : : parameter-type-list:
4799 : : parameter-list
4800 : : parameter-list , ...
4801 : :
4802 : : parameter-list:
4803 : : parameter-declaration
4804 : : parameter-list , parameter-declaration
4805 : :
4806 : : parameter-declaration:
4807 : : declaration-specifiers declarator gnu-attributes[opt]
4808 : : declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4809 : :
4810 : : identifier-list:
4811 : : identifier
4812 : : identifier-list , identifier
4813 : :
4814 : : abstract-declarator:
4815 : : pointer
4816 : : pointer[opt] direct-abstract-declarator
4817 : :
4818 : : direct-abstract-declarator:
4819 : : ( gnu-attributes[opt] abstract-declarator )
4820 : : direct-abstract-declarator[opt] array-declarator
4821 : : direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4822 : :
4823 : : GNU extensions:
4824 : :
4825 : : direct-declarator:
4826 : : direct-declarator ( parameter-forward-declarations
4827 : : parameter-type-list[opt] )
4828 : :
4829 : : direct-abstract-declarator:
4830 : : direct-abstract-declarator[opt] ( parameter-forward-declarations
4831 : : parameter-type-list[opt] )
4832 : :
4833 : : parameter-forward-declarations:
4834 : : parameter-list ;
4835 : : parameter-forward-declarations parameter-list ;
4836 : :
4837 : : The uses of gnu-attributes shown above are GNU extensions.
4838 : :
4839 : : Some forms of array declarator are not included in C99 in the
4840 : : syntax for abstract declarators; these are disallowed elsewhere.
4841 : : This may be a defect (DR#289).
4842 : :
4843 : : This function also accepts an omitted abstract declarator as being
4844 : : an abstract declarator, although not part of the formal syntax. */
4845 : :
4846 : : struct c_declarator *
4847 : 322891427 : c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4848 : : bool *seen_id)
4849 : : {
4850 : : /* Parse any initial pointer part. */
4851 : 322891427 : if (c_parser_next_token_is (parser, CPP_MULT))
4852 : : {
4853 : 17875777 : struct c_declspecs *quals_attrs = build_null_declspecs ();
4854 : 17875777 : struct c_declarator *inner;
4855 : 17875777 : c_parser_consume_token (parser);
4856 : 17875777 : c_parser_declspecs (parser, quals_attrs, false, false, true,
4857 : : false, false, true, false, cla_prefer_id);
4858 : 17875777 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4859 : 17875777 : if (inner == NULL)
4860 : : return NULL;
4861 : : else
4862 : 17875768 : return make_pointer_declarator (quals_attrs, inner);
4863 : : }
4864 : : /* Now we have a direct declarator, direct abstract declarator or
4865 : : nothing (which counts as a direct abstract declarator here). */
4866 : 305015650 : return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
4867 : : }
4868 : :
4869 : : /* Parse a direct declarator or direct abstract declarator; arguments
4870 : : as c_parser_declarator. */
4871 : :
4872 : : static struct c_declarator *
4873 : 305015650 : c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4874 : : bool *seen_id)
4875 : : {
4876 : : /* The direct declarator must start with an identifier (possibly
4877 : : omitted) or a parenthesized declarator (possibly abstract). In
4878 : : an ordinary declarator, initial parentheses must start a
4879 : : parenthesized declarator. In an abstract declarator or parameter
4880 : : declarator, they could start a parenthesized declarator or a
4881 : : parameter list. To tell which, the open parenthesis and any
4882 : : following gnu-attributes must be read. If a declaration
4883 : : specifier or standard attributes follow, then it is a parameter
4884 : : list; if the specifier is a typedef name, there might be an
4885 : : ambiguity about redeclaring it, which is resolved in the
4886 : : direction of treating it as a typedef name. If a close
4887 : : parenthesis follows, it is also an empty parameter list, as the
4888 : : syntax does not permit empty abstract declarators. Otherwise, it
4889 : : is a parenthesized declarator (in which case the analysis may be
4890 : : repeated inside it, recursively).
4891 : :
4892 : : ??? There is an ambiguity in a parameter declaration "int
4893 : : (__attribute__((foo)) x)", where x is not a typedef name: it
4894 : : could be an abstract declarator for a function, or declare x with
4895 : : parentheses. The proper resolution of this ambiguity needs
4896 : : documenting. At present we follow an accident of the old
4897 : : parser's implementation, whereby the first parameter must have
4898 : : some declaration specifiers other than just gnu-attributes. Thus as
4899 : : a parameter declaration it is treated as a parenthesized
4900 : : parameter named x, and as an abstract declarator it is
4901 : : rejected.
4902 : :
4903 : : ??? Also following the old parser, gnu-attributes inside an empty
4904 : : parameter list are ignored, making it a list not yielding a
4905 : : prototype, rather than giving an error or making it have one
4906 : : parameter with implicit type int.
4907 : :
4908 : : ??? Also following the old parser, typedef names may be
4909 : : redeclared in declarators, but not Objective-C class names. */
4910 : :
4911 : 305015650 : if (kind != C_DTR_ABSTRACT
4912 : 186736173 : && c_parser_next_token_is (parser, CPP_NAME)
4913 : 487055994 : && ((type_seen_p
4914 : 182030485 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
4915 : 181984653 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
4916 : 181994512 : || c_parser_peek_token (parser)->id_kind == C_ID_ID))
4917 : : {
4918 : 182040344 : struct c_declarator *inner
4919 : 182040344 : = build_id_declarator (c_parser_peek_token (parser)->value);
4920 : 182040344 : *seen_id = true;
4921 : 182040344 : inner->id_loc = c_parser_peek_token (parser)->location;
4922 : 182040344 : c_parser_consume_token (parser);
4923 : 182040344 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
4924 : 84 : inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
4925 : 182040344 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4926 : : }
4927 : :
4928 : 122975306 : if (kind != C_DTR_NORMAL
4929 : 122835743 : && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
4930 : 122999109 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
4931 : : {
4932 : 23803 : struct c_declarator *inner = build_id_declarator (NULL_TREE);
4933 : 23803 : inner->id_loc = c_parser_peek_token (parser)->location;
4934 : 23803 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4935 : : }
4936 : :
4937 : : /* Either we are at the end of an abstract declarator, or we have
4938 : : parentheses. */
4939 : :
4940 : 122951503 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
4941 : : {
4942 : 221614 : tree attrs;
4943 : 221614 : struct c_declarator *inner;
4944 : 221614 : c_parser_consume_token (parser);
4945 : 221614 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4946 : : RID_ATTRIBUTE);
4947 : 221614 : attrs = c_parser_gnu_attributes (parser);
4948 : 221614 : if (kind != C_DTR_NORMAL
4949 : 221614 : && (c_parser_next_token_starts_declspecs (parser)
4950 : 82118 : || (!have_gnu_attrs
4951 : 81959 : && (c_parser_nth_token_starts_std_attributes (parser, 1)
4952 : 81959 : || c_parser_next_token_is (parser, CPP_ELLIPSIS)))
4953 : 82113 : || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
4954 : : {
4955 : 64 : struct c_arg_info *args
4956 : 64 : = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
4957 : : attrs, have_gnu_attrs);
4958 : 64 : if (args == NULL)
4959 : : return NULL;
4960 : : else
4961 : : {
4962 : 64 : inner = build_id_declarator (NULL_TREE);
4963 : 89 : if (!(args->types
4964 : 25 : && args->types != error_mark_node
4965 : 25 : && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4966 : 89 : && c_parser_nth_token_starts_std_attributes (parser, 1))
4967 : : {
4968 : 4 : tree std_attrs
4969 : 4 : = c_parser_std_attribute_specifier_sequence (parser);
4970 : 4 : if (std_attrs)
4971 : 2 : inner = build_attrs_declarator (std_attrs, inner);
4972 : : }
4973 : 64 : inner = build_function_declarator (args, inner);
4974 : 64 : return c_parser_direct_declarator_inner (parser, *seen_id,
4975 : 64 : inner);
4976 : : }
4977 : : }
4978 : : /* A parenthesized declarator. */
4979 : 221550 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4980 : 221550 : if (inner != NULL && attrs != NULL)
4981 : 181 : inner = build_attrs_declarator (attrs, inner);
4982 : 221550 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
4983 : : {
4984 : 221536 : c_parser_consume_token (parser);
4985 : 221536 : if (inner == NULL)
4986 : : return NULL;
4987 : : else
4988 : 221536 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4989 : : }
4990 : : else
4991 : : {
4992 : 14 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
4993 : : "expected %<)%>");
4994 : 14 : return NULL;
4995 : : }
4996 : : }
4997 : : else
4998 : : {
4999 : 122729889 : if (kind == C_DTR_NORMAL)
5000 : : {
5001 : 92 : c_parser_error (parser, "expected identifier or %<(%>");
5002 : 92 : return NULL;
5003 : : }
5004 : : else
5005 : 122729797 : return build_id_declarator (NULL_TREE);
5006 : : }
5007 : : }
5008 : :
5009 : : /* Parse part of a direct declarator or direct abstract declarator,
5010 : : given that some (in INNER) has already been parsed; ID_PRESENT is
5011 : : true if an identifier is present, false for an abstract
5012 : : declarator. */
5013 : :
5014 : : static struct c_declarator *
5015 : 232239454 : c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
5016 : : struct c_declarator *inner)
5017 : : {
5018 : : /* Parse a sequence of array declarators and parameter lists. */
5019 : 232239454 : if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
5020 : 232239454 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5021 : : {
5022 : 1125151 : location_t brace_loc = c_parser_peek_token (parser)->location;
5023 : 1125151 : struct c_declarator *declarator;
5024 : 1125151 : struct c_declspecs *quals_attrs = build_null_declspecs ();
5025 : 1125151 : struct c_expr dimen;
5026 : 1125151 : dimen.value = NULL_TREE;
5027 : 1125151 : dimen.original_code = ERROR_MARK;
5028 : 1125151 : dimen.original_type = NULL_TREE;
5029 : 1125151 : c_parser_consume_token (parser);
5030 : 1125151 : c_parser_declspecs (parser, quals_attrs, false, false, true,
5031 : : false, false, false, false, cla_prefer_id);
5032 : :
5033 : 1125151 : location_t static_loc = UNKNOWN_LOCATION;
5034 : 1125151 : if (c_parser_next_token_is_keyword (parser, RID_STATIC))
5035 : : {
5036 : 131 : static_loc = c_parser_peek_token (parser)->location;
5037 : 131 : c_parser_consume_token (parser);
5038 : 131 : if (!quals_attrs->declspecs_seen_p)
5039 : 111 : c_parser_declspecs (parser, quals_attrs, false, false, true,
5040 : : false, false, false, false, cla_prefer_id);
5041 : : }
5042 : 1125151 : if (!quals_attrs->declspecs_seen_p)
5043 : 1124215 : quals_attrs = NULL;
5044 : : /* If "static" is present, there must be an array dimension.
5045 : : Otherwise, there may be a dimension, "*", or no
5046 : : dimension. */
5047 : 1125151 : const bool static_seen = (static_loc != UNKNOWN_LOCATION);
5048 : 1125151 : bool star_seen = false;
5049 : 1125151 : if (c_parser_next_token_is (parser, CPP_MULT)
5050 : 1125151 : && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
5051 : : {
5052 : 150 : star_seen = true;
5053 : 150 : c_parser_consume_token (parser);
5054 : : }
5055 : 1125001 : else if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5056 : 956937 : dimen = c_parser_expr_no_commas (parser, NULL);
5057 : :
5058 : 1125151 : if (static_seen)
5059 : : {
5060 : 131 : if (star_seen)
5061 : : {
5062 : 3 : error_at (static_loc,
5063 : : "%<static%> may not be used with an unspecified "
5064 : : "variable length array size");
5065 : : /* Prevent further errors. */
5066 : 3 : star_seen = false;
5067 : 3 : dimen.value = error_mark_node;
5068 : : }
5069 : 128 : else if (!dimen.value)
5070 : 2 : error_at (static_loc,
5071 : : "%<static%> may not be used without an array size");
5072 : : }
5073 : :
5074 : 1125151 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5075 : 1125136 : c_parser_consume_token (parser);
5076 : : else
5077 : : {
5078 : 15 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
5079 : : "expected %<]%>");
5080 : 15 : return NULL;
5081 : : }
5082 : 1125136 : if (dimen.value)
5083 : 956925 : dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
5084 : 1125136 : declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
5085 : : static_seen, star_seen);
5086 : 1125136 : if (declarator == NULL)
5087 : : return NULL;
5088 : 1125132 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
5089 : : {
5090 : 16 : tree std_attrs
5091 : 16 : = c_parser_std_attribute_specifier_sequence (parser);
5092 : 16 : if (std_attrs)
5093 : 10 : inner = build_attrs_declarator (std_attrs, inner);
5094 : : }
5095 : 1125132 : inner = set_array_declarator_inner (declarator, inner);
5096 : 1125132 : return c_parser_direct_declarator_inner (parser, id_present, inner);
5097 : : }
5098 : 231114303 : else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
5099 : : {
5100 : 48828682 : tree attrs;
5101 : 48828682 : struct c_arg_info *args;
5102 : 48828682 : c_parser_consume_token (parser);
5103 : 48828682 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5104 : : RID_ATTRIBUTE);
5105 : 48828682 : attrs = c_parser_gnu_attributes (parser);
5106 : 48828682 : args = c_parser_parms_declarator (parser, id_present, attrs,
5107 : : have_gnu_attrs);
5108 : 48828682 : if (args == NULL)
5109 : : return NULL;
5110 : : else
5111 : : {
5112 : 96885685 : if (!(args->types
5113 : 48057110 : && args->types != error_mark_node
5114 : 48057110 : && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5115 : 96876999 : && c_parser_nth_token_starts_std_attributes (parser, 1))
5116 : : {
5117 : 98 : tree std_attrs
5118 : 98 : = c_parser_std_attribute_specifier_sequence (parser);
5119 : 98 : if (std_attrs)
5120 : 81 : inner = build_attrs_declarator (std_attrs, inner);
5121 : : }
5122 : 48828575 : inner = build_function_declarator (args, inner);
5123 : 48828575 : return c_parser_direct_declarator_inner (parser, id_present, inner);
5124 : : }
5125 : : }
5126 : : return inner;
5127 : : }
5128 : :
5129 : : /* Parse a parameter list or identifier list, including the closing
5130 : : parenthesis but not the opening one. ATTRS are the gnu-attributes
5131 : : at the start of the list. ID_LIST_OK is true if an identifier list
5132 : : is acceptable; such a list must not have attributes at the start.
5133 : : HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
5134 : : attributes) were present (in which case standard attributes cannot
5135 : : occur). */
5136 : :
5137 : : static struct c_arg_info *
5138 : 48828746 : c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
5139 : : bool have_gnu_attrs)
5140 : : {
5141 : 48828746 : push_scope ();
5142 : 48828746 : declare_parm_level ();
5143 : : /* If the list starts with an identifier, it is an identifier list.
5144 : : Otherwise, it is either a prototype list or an empty list. */
5145 : 48828746 : if (id_list_ok
5146 : 48828746 : && !attrs
5147 : 48816868 : && c_parser_next_token_is (parser, CPP_NAME)
5148 : 32922732 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
5149 : :
5150 : : /* Look ahead to detect typos in type names. */
5151 : 8696 : && c_parser_peek_2nd_token (parser)->type != CPP_NAME
5152 : 8690 : && c_parser_peek_2nd_token (parser)->type != CPP_MULT
5153 : 8689 : && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
5154 : 8688 : && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
5155 : 48837433 : && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
5156 : : {
5157 : 8686 : tree list = NULL_TREE, *nextp = &list;
5158 : 8686 : while (c_parser_next_token_is (parser, CPP_NAME)
5159 : 34286 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
5160 : : {
5161 : 34286 : *nextp = build_tree_list (NULL_TREE,
5162 : 34286 : c_parser_peek_token (parser)->value);
5163 : 34286 : nextp = & TREE_CHAIN (*nextp);
5164 : 34286 : c_parser_consume_token (parser);
5165 : 34286 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
5166 : : break;
5167 : 25600 : c_parser_consume_token (parser);
5168 : 25600 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5169 : : {
5170 : 0 : c_parser_error (parser, "expected identifier");
5171 : 0 : break;
5172 : : }
5173 : : }
5174 : 8686 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5175 : : {
5176 : 8686 : struct c_arg_info *ret = build_arg_info ();
5177 : 8686 : ret->types = list;
5178 : 8686 : c_parser_consume_token (parser);
5179 : 8686 : pop_scope ();
5180 : 8686 : return ret;
5181 : : }
5182 : : else
5183 : : {
5184 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5185 : : "expected %<)%>");
5186 : 0 : pop_scope ();
5187 : 0 : return NULL;
5188 : : }
5189 : : }
5190 : : else
5191 : : {
5192 : 48820060 : struct c_arg_info *ret
5193 : 48820060 : = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
5194 : 48820060 : pop_scope ();
5195 : 48820060 : return ret;
5196 : : }
5197 : : }
5198 : :
5199 : : /* Parse a parameter list (possibly empty), including the closing
5200 : : parenthesis but not the opening one. ATTRS are the gnu-attributes
5201 : : at the start of the list; if HAVE_GNU_ATTRS, there were some such
5202 : : attributes (possibly empty, in which case ATTRS is NULL_TREE),
5203 : : which means standard attributes cannot start the list. EXPR is
5204 : : NULL or an expression that needs to be evaluated for the side
5205 : : effects of array size expressions in the parameters. */
5206 : :
5207 : : static struct c_arg_info *
5208 : 48820097 : c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
5209 : : bool have_gnu_attrs)
5210 : : {
5211 : 48820097 : bool bad_parm = false;
5212 : :
5213 : : /* ??? Following the old parser, forward parameter declarations may
5214 : : use abstract declarators, and if no real parameter declarations
5215 : : follow the forward declarations then this is not diagnosed. Also
5216 : : note as above that gnu-attributes are ignored as the only contents of
5217 : : the parentheses, or as the only contents after forward
5218 : : declarations. */
5219 : 48820097 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5220 : : {
5221 : 771346 : struct c_arg_info *ret = build_arg_info ();
5222 : 771346 : c_parser_consume_token (parser);
5223 : 771346 : return ret;
5224 : : }
5225 : 48048751 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS) && !have_gnu_attrs)
5226 : : {
5227 : 135 : struct c_arg_info *ret = build_arg_info ();
5228 : :
5229 : 135 : ret->types = NULL_TREE;
5230 : 135 : pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
5231 : : "ISO C requires a named argument before %<...%> "
5232 : : "before C23");
5233 : 135 : c_parser_consume_token (parser);
5234 : 135 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5235 : : {
5236 : 135 : ret->no_named_args_stdarg_p = true;
5237 : 135 : c_parser_consume_token (parser);
5238 : 135 : return ret;
5239 : : }
5240 : : else
5241 : : {
5242 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5243 : : "expected %<)%>");
5244 : 0 : return NULL;
5245 : : }
5246 : : }
5247 : : /* Nonempty list of parameters, either terminated with semicolon
5248 : : (forward declarations; recurse) or with close parenthesis (normal
5249 : : function) or with ", ... )" (variadic function). */
5250 : 120162402 : while (true)
5251 : : {
5252 : : /* Parse a parameter. */
5253 : 120162402 : struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
5254 : : have_gnu_attrs);
5255 : 120162402 : attrs = NULL_TREE;
5256 : 120162402 : have_gnu_attrs = false;
5257 : 120162402 : if (parm == NULL)
5258 : : bad_parm = true;
5259 : : else
5260 : 120162295 : push_parm_decl (parm, &expr);
5261 : 120162402 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
5262 : : {
5263 : 37 : tree new_attrs;
5264 : 37 : c_parser_consume_token (parser);
5265 : 37 : mark_forward_parm_decls ();
5266 : 37 : bool new_have_gnu_attrs
5267 : 37 : = c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE);
5268 : 37 : new_attrs = c_parser_gnu_attributes (parser);
5269 : 37 : return c_parser_parms_list_declarator (parser, new_attrs, expr,
5270 : 37 : new_have_gnu_attrs);
5271 : : }
5272 : 120162365 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5273 : : {
5274 : 47838254 : c_parser_consume_token (parser);
5275 : 47838254 : if (bad_parm)
5276 : : return NULL;
5277 : : else
5278 : 47838170 : return get_parm_info (false, expr);
5279 : : }
5280 : 72324111 : if (!c_parser_require (parser, CPP_COMMA,
5281 : : "expected %<;%>, %<,%> or %<)%>",
5282 : : UNKNOWN_LOCATION, false))
5283 : : {
5284 : 8 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5285 : 8 : return NULL;
5286 : : }
5287 : 72324103 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
5288 : : {
5289 : 210317 : c_parser_consume_token (parser);
5290 : 210317 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5291 : : {
5292 : 210310 : c_parser_consume_token (parser);
5293 : 210310 : if (bad_parm)
5294 : : return NULL;
5295 : : else
5296 : 210302 : return get_parm_info (true, expr);
5297 : : }
5298 : : else
5299 : : {
5300 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5301 : : "expected %<)%>");
5302 : 7 : return NULL;
5303 : : }
5304 : : }
5305 : : }
5306 : : }
5307 : :
5308 : : /* Parse a parameter declaration. ATTRS are the gnu-attributes at the
5309 : : start of the declaration if it is the first parameter;
5310 : : HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
5311 : : empty) there. */
5312 : :
5313 : : static struct c_parm *
5314 : 120162402 : c_parser_parameter_declaration (c_parser *parser, tree attrs,
5315 : : bool have_gnu_attrs)
5316 : : {
5317 : 120162402 : struct c_declspecs *specs;
5318 : 120162402 : struct c_declarator *declarator;
5319 : 120162402 : tree prefix_attrs;
5320 : 120162402 : tree postfix_attrs = NULL_TREE;
5321 : 120162402 : bool dummy = false;
5322 : :
5323 : : /* Accept #pragmas between parameter declarations. */
5324 : 120162404 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
5325 : 2 : c_parser_pragma (parser, pragma_param, NULL, NULL_TREE);
5326 : :
5327 : 120162402 : if (!c_parser_next_token_starts_declspecs (parser)
5328 : 120162402 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5329 : : {
5330 : 95 : c_token *token = c_parser_peek_token (parser);
5331 : 95 : if (parser->error)
5332 : : return NULL;
5333 : 95 : c_parser_set_source_position_from_token (token);
5334 : 95 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
5335 : : {
5336 : 77 : auto_diagnostic_group d;
5337 : 77 : name_hint hint = lookup_name_fuzzy (token->value,
5338 : : FUZZY_LOOKUP_TYPENAME,
5339 : 77 : token->location);
5340 : 77 : if (const char *suggestion = hint.suggestion ())
5341 : : {
5342 : 30 : gcc_rich_location richloc (token->location);
5343 : 30 : richloc.add_fixit_replace (suggestion);
5344 : 30 : error_at (&richloc,
5345 : : "unknown type name %qE; did you mean %qs?",
5346 : : token->value, suggestion);
5347 : 30 : }
5348 : : else
5349 : 47 : error_at (token->location, "unknown type name %qE", token->value);
5350 : 77 : parser->error = true;
5351 : 77 : }
5352 : : /* ??? In some Objective-C cases '...' isn't applicable so there
5353 : : should be a different message. */
5354 : : else
5355 : 18 : c_parser_error (parser,
5356 : : "expected declaration specifiers or %<...%>");
5357 : 95 : c_parser_skip_to_end_of_parameter (parser);
5358 : 95 : return NULL;
5359 : : }
5360 : :
5361 : 120162307 : location_t start_loc = c_parser_peek_token (parser)->location;
5362 : :
5363 : 120162307 : specs = build_null_declspecs ();
5364 : 120162307 : if (attrs)
5365 : : {
5366 : 337 : declspecs_add_attrs (input_location, specs, attrs);
5367 : 337 : attrs = NULL_TREE;
5368 : : }
5369 : 120162307 : c_parser_declspecs (parser, specs, true, true, true, true, false,
5370 : 120162307 : !have_gnu_attrs, true, cla_nonabstract_decl);
5371 : 120162307 : finish_declspecs (specs);
5372 : 120162307 : pending_xref_error ();
5373 : 120162307 : prefix_attrs = specs->attrs;
5374 : 120162307 : specs->attrs = NULL_TREE;
5375 : 240324614 : declarator = c_parser_declarator (parser,
5376 : 120162307 : specs->typespec_kind != ctsk_none,
5377 : : C_DTR_PARM, &dummy);
5378 : 120162307 : if (declarator == NULL)
5379 : : {
5380 : 12 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
5381 : 12 : return NULL;
5382 : : }
5383 : 120162295 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
5384 : 17128 : postfix_attrs = c_parser_gnu_attributes (parser);
5385 : :
5386 : : /* Generate a location for the parameter, ranging from the start of the
5387 : : initial token to the end of the final token.
5388 : :
5389 : : If we have a identifier, then use it for the caret location, e.g.
5390 : :
5391 : : extern int callee (int one, int (*two)(int, int), float three);
5392 : : ~~~~~~^~~~~~~~~~~~~~
5393 : :
5394 : : otherwise, reuse the start location for the caret location e.g.:
5395 : :
5396 : : extern int callee (int one, int (*)(int, int), float three);
5397 : : ^~~~~~~~~~~~~~~~~
5398 : : */
5399 : 120162295 : location_t end_loc = parser->last_token_location;
5400 : :
5401 : : /* Find any cdk_id declarator; determine if we have an identifier. */
5402 : 120162295 : c_declarator *id_declarator = declarator;
5403 : 132796927 : while (id_declarator && id_declarator->kind != cdk_id)
5404 : 12634632 : id_declarator = id_declarator->declarator;
5405 : 115682604 : location_t caret_loc = (id_declarator->u.id.id
5406 : 120162295 : ? id_declarator->id_loc
5407 : : : start_loc);
5408 : 120162295 : location_t param_loc = make_location (caret_loc, start_loc, end_loc);
5409 : :
5410 : 120162295 : return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5411 : 120162295 : declarator, param_loc);
5412 : : }
5413 : :
5414 : : /* Parse a string literal in an asm expression. It should not be
5415 : : translated, and wide string literals are an error although
5416 : : permitted by the syntax. This is a GNU extension.
5417 : :
5418 : : asm-string-literal:
5419 : : string-literal
5420 : : */
5421 : :
5422 : : static tree
5423 : 1925973 : c_parser_asm_string_literal (c_parser *parser)
5424 : : {
5425 : 1925973 : tree str;
5426 : 1925973 : int save_flag = warn_overlength_strings;
5427 : 1925973 : warn_overlength_strings = 0;
5428 : 1925973 : str = c_parser_string_literal (parser, false, false).value;
5429 : 1925973 : warn_overlength_strings = save_flag;
5430 : 1925973 : return str;
5431 : : }
5432 : :
5433 : : /* Parse a simple asm expression. This is used in restricted
5434 : : contexts, where a full expression with inputs and outputs does not
5435 : : make sense. This is a GNU extension.
5436 : :
5437 : : simple-asm-expr:
5438 : : asm ( asm-string-literal )
5439 : : */
5440 : :
5441 : : static tree
5442 : 855988 : c_parser_simple_asm_expr (c_parser *parser)
5443 : : {
5444 : 855988 : tree str;
5445 : 855988 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5446 : 855988 : c_parser_consume_token (parser);
5447 : 855988 : matching_parens parens;
5448 : 855988 : if (!parens.require_open (parser))
5449 : : return NULL_TREE;
5450 : 855988 : str = c_parser_asm_string_literal (parser);
5451 : 855988 : if (!parens.require_close (parser))
5452 : : {
5453 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5454 : 0 : return NULL_TREE;
5455 : : }
5456 : : return str;
5457 : : }
5458 : :
5459 : : static tree
5460 : 131012032 : c_parser_gnu_attribute_any_word (c_parser *parser)
5461 : : {
5462 : 131012032 : tree attr_name = NULL_TREE;
5463 : :
5464 : 131012032 : if (c_parser_next_token_is (parser, CPP_KEYWORD))
5465 : : {
5466 : : /* ??? See comment above about what keywords are accepted here. */
5467 : 840102 : bool ok;
5468 : 840102 : switch (c_parser_peek_token (parser)->keyword)
5469 : : {
5470 : : case RID_STATIC:
5471 : : case RID_UNSIGNED:
5472 : : case RID_LONG:
5473 : : case RID_CONST:
5474 : : case RID_EXTERN:
5475 : : case RID_REGISTER:
5476 : : case RID_TYPEDEF:
5477 : : case RID_SHORT:
5478 : : case RID_INLINE:
5479 : : case RID_NORETURN:
5480 : : case RID_VOLATILE:
5481 : : case RID_SIGNED:
5482 : : case RID_AUTO:
5483 : : case RID_RESTRICT:
5484 : : case RID_COMPLEX:
5485 : : case RID_THREAD:
5486 : : case RID_INT:
5487 : : case RID_CHAR:
5488 : : case RID_FLOAT:
5489 : : case RID_DOUBLE:
5490 : : case RID_VOID:
5491 : : case RID_DFLOAT32:
5492 : : case RID_DFLOAT64:
5493 : : case RID_DFLOAT128:
5494 : : case RID_DFLOAT64X:
5495 : : CASE_RID_FLOATN_NX:
5496 : : case RID_BOOL:
5497 : : case RID_BITINT:
5498 : : case RID_FRACT:
5499 : : case RID_ACCUM:
5500 : : case RID_SAT:
5501 : : case RID_TRANSACTION_ATOMIC:
5502 : : case RID_TRANSACTION_CANCEL:
5503 : : case RID_ATOMIC:
5504 : : case RID_AUTO_TYPE:
5505 : : case RID_CONSTEXPR:
5506 : : case RID_INT_N_0:
5507 : : case RID_INT_N_1:
5508 : : case RID_INT_N_2:
5509 : : case RID_INT_N_3:
5510 : : ok = true;
5511 : : break;
5512 : : default:
5513 : : ok = false;
5514 : : break;
5515 : : }
5516 : 840102 : if (!ok)
5517 : : return NULL_TREE;
5518 : :
5519 : : /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5520 : 840102 : attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5521 : : }
5522 : 130171930 : else if (c_parser_next_token_is (parser, CPP_NAME))
5523 : 130171927 : attr_name = c_parser_peek_token (parser)->value;
5524 : :
5525 : : return attr_name;
5526 : : }
5527 : :
5528 : : /* Parse attribute arguments. This is a common form of syntax
5529 : : covering all currently valid GNU and standard attributes.
5530 : :
5531 : : gnu-attribute-arguments:
5532 : : identifier
5533 : : identifier , nonempty-expr-list
5534 : : expr-list
5535 : :
5536 : : where the "identifier" must not be declared as a type. ??? Why not
5537 : : allow identifiers declared as types to start the arguments? */
5538 : :
5539 : : static tree
5540 : 4449894 : c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5541 : : bool require_string, bool assume_attr,
5542 : : bool allow_empty_args)
5543 : : {
5544 : 4449894 : vec<tree, va_gc> *expr_list;
5545 : 4449894 : tree attr_args;
5546 : : /* Parse the attribute contents. If they start with an
5547 : : identifier which is followed by a comma or close
5548 : : parenthesis, then the arguments start with that
5549 : : identifier; otherwise they are an expression list.
5550 : : In objective-c the identifier may be a classname. */
5551 : 4449894 : if (c_parser_next_token_is (parser, CPP_NAME)
5552 : 562414 : && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5553 : 1 : || (c_dialect_objc ()
5554 : 0 : && c_parser_peek_token (parser)->id_kind
5555 : : == C_ID_CLASSNAME))
5556 : 562413 : && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5557 : 38732 : || (c_parser_peek_2nd_token (parser)->type
5558 : : == CPP_CLOSE_PAREN))
5559 : 5012268 : && (takes_identifier
5560 : 141784 : || (c_dialect_objc ()
5561 : 0 : && !assume_attr
5562 : 0 : && c_parser_peek_token (parser)->id_kind
5563 : : == C_ID_CLASSNAME)))
5564 : : {
5565 : 420590 : tree arg1 = c_parser_peek_token (parser)->value;
5566 : 420590 : c_parser_consume_token (parser);
5567 : 420590 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5568 : 35010 : attr_args = build_tree_list (NULL_TREE, arg1);
5569 : : else
5570 : : {
5571 : 385580 : tree tree_list;
5572 : 385580 : c_parser_consume_token (parser);
5573 : 385580 : expr_list = c_parser_expr_list (parser, false, true,
5574 : : NULL, NULL, NULL, NULL);
5575 : 385580 : tree_list = build_tree_list_vec (expr_list);
5576 : 385580 : attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5577 : 385580 : release_tree_vector (expr_list);
5578 : : }
5579 : : }
5580 : : else
5581 : : {
5582 : 4029304 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5583 : : {
5584 : 16 : if (!allow_empty_args)
5585 : 3 : error_at (c_parser_peek_token (parser)->location,
5586 : : "parentheses must be omitted if "
5587 : : "attribute argument list is empty");
5588 : : attr_args = NULL_TREE;
5589 : : }
5590 : 4029288 : else if (require_string)
5591 : : {
5592 : : /* The only valid argument for this attribute is a string
5593 : : literal. Handle this specially here to avoid accepting
5594 : : string literals with excess parentheses. */
5595 : 19 : tree string = c_parser_string_literal (parser, false, true).value;
5596 : 19 : attr_args = build_tree_list (NULL_TREE, string);
5597 : : }
5598 : 4029269 : else if (assume_attr)
5599 : : {
5600 : 45 : tree cond
5601 : 45 : = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5602 : 45 : if (!c_parser_next_token_is (parser, CPP_COMMA))
5603 : 43 : attr_args = build_tree_list (NULL_TREE, cond);
5604 : : else
5605 : : {
5606 : 2 : tree tree_list;
5607 : 2 : c_parser_consume_token (parser);
5608 : 2 : expr_list = c_parser_expr_list (parser, false, true,
5609 : : NULL, NULL, NULL, NULL);
5610 : 2 : tree_list = build_tree_list_vec (expr_list);
5611 : 2 : attr_args = tree_cons (NULL_TREE, cond, tree_list);
5612 : 2 : release_tree_vector (expr_list);
5613 : : }
5614 : : }
5615 : : else
5616 : : {
5617 : 4029224 : expr_list = c_parser_expr_list (parser, false, true,
5618 : : NULL, NULL, NULL, NULL);
5619 : 4029224 : attr_args = build_tree_list_vec (expr_list);
5620 : 4029224 : release_tree_vector (expr_list);
5621 : : }
5622 : : }
5623 : 4449894 : return attr_args;
5624 : : }
5625 : :
5626 : : /* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5627 : :
5628 : : gnu-attributes:
5629 : : empty
5630 : : gnu-attributes gnu-attribute
5631 : :
5632 : : gnu-attribute:
5633 : : __attribute__ ( ( gnu-attribute-list ) )
5634 : :
5635 : : gnu-attribute-list:
5636 : : gnu-attrib
5637 : : gnu-attribute_list , gnu-attrib
5638 : :
5639 : : gnu-attrib:
5640 : : empty
5641 : : any-word
5642 : : any-word ( gnu-attribute-arguments )
5643 : :
5644 : : where "any-word" may be any identifier (including one declared as a
5645 : : type), a reserved word storage class specifier, type specifier or
5646 : : type qualifier. ??? This still leaves out most reserved keywords
5647 : : (following the old parser), shouldn't we include them?
5648 : : When EXPECT_COMMA is true, expect the attribute to be preceded
5649 : : by a comma and fail if it isn't.
5650 : : When EMPTY_OK is true, allow and consume any number of consecutive
5651 : : commas with no attributes in between. */
5652 : :
5653 : : static tree
5654 : 182285523 : c_parser_gnu_attribute (c_parser *parser, tree attrs,
5655 : : bool expect_comma = false, bool empty_ok = true)
5656 : : {
5657 : 182285523 : bool comma_first = c_parser_next_token_is (parser, CPP_COMMA);
5658 : 182285523 : if (!comma_first
5659 : 102547741 : && !c_parser_next_token_is (parser, CPP_NAME)
5660 : 234399009 : && !c_parser_next_token_is (parser, CPP_KEYWORD))
5661 : : return NULL_TREE;
5662 : :
5663 : 210749821 : while (c_parser_next_token_is (parser, CPP_COMMA))
5664 : : {
5665 : 79737789 : c_parser_consume_token (parser);
5666 : 79737789 : if (!empty_ok)
5667 : : return attrs;
5668 : : }
5669 : :
5670 : 131012032 : tree attr_name = c_parser_gnu_attribute_any_word (parser);
5671 : 131012032 : if (attr_name == NULL_TREE)
5672 : : return NULL_TREE;
5673 : :
5674 : 131012029 : attr_name = canonicalize_attr_name (attr_name);
5675 : 131012029 : c_parser_consume_token (parser);
5676 : :
5677 : 131012029 : tree attr;
5678 : 131012029 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
5679 : : {
5680 : 126562224 : if (expect_comma && !comma_first)
5681 : : {
5682 : : /* A comma is missing between the last attribute on the chain
5683 : : and this one. */
5684 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5685 : : "expected %<)%>");
5686 : 7 : return error_mark_node;
5687 : : }
5688 : 126562217 : attr = build_tree_list (attr_name, NULL_TREE);
5689 : : /* Add this attribute to the list. */
5690 : 126562217 : attrs = chainon (attrs, attr);
5691 : 126562217 : return attrs;
5692 : : }
5693 : 4449805 : c_parser_consume_token (parser);
5694 : :
5695 : 4449805 : tree attr_args
5696 : 4449805 : = c_parser_attribute_arguments (parser,
5697 : 4449805 : attribute_takes_identifier_p (attr_name),
5698 : : false,
5699 : 4449805 : is_attribute_p ("assume", attr_name),
5700 : : true);
5701 : :
5702 : 4449805 : attr = build_tree_list (attr_name, attr_args);
5703 : 4449805 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5704 : 4449803 : c_parser_consume_token (parser);
5705 : : else
5706 : : {
5707 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5708 : : "expected %<)%>");
5709 : 2 : return error_mark_node;
5710 : : }
5711 : :
5712 : 4449803 : if (expect_comma && !comma_first)
5713 : : {
5714 : : /* A comma is missing between the last attribute on the chain
5715 : : and this one. */
5716 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5717 : : "expected %<)%>");
5718 : 0 : return error_mark_node;
5719 : : }
5720 : :
5721 : : /* Add this attribute to the list. */
5722 : 4449803 : attrs = chainon (attrs, attr);
5723 : 4449803 : return attrs;
5724 : : }
5725 : :
5726 : : static tree
5727 : 105783416 : c_parser_gnu_attributes (c_parser *parser)
5728 : : {
5729 : 105783416 : tree attrs = NULL_TREE;
5730 : 157056906 : while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
5731 : : {
5732 : 51273500 : bool save_translate_strings_p = parser->translate_strings_p;
5733 : 51273500 : parser->translate_strings_p = false;
5734 : : /* Consume the `__attribute__' keyword. */
5735 : 51273500 : c_parser_consume_token (parser);
5736 : : /* Look for the two `(' tokens. */
5737 : 51273500 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
5738 : : {
5739 : 0 : parser->translate_strings_p = save_translate_strings_p;
5740 : 0 : return attrs;
5741 : : }
5742 : 51273500 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
5743 : : {
5744 : 0 : parser->translate_strings_p = save_translate_strings_p;
5745 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
5746 : 0 : return attrs;
5747 : : }
5748 : : /* Parse the attribute list. Require a comma between successive
5749 : : (possibly empty) attributes. */
5750 : : for (bool expect_comma = false; ; expect_comma = true)
5751 : : {
5752 : : /* Parse a single attribute. */
5753 : 182284763 : tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5754 : 182284763 : if (attr == error_mark_node)
5755 : : return attrs;
5756 : 182284754 : if (!attr)
5757 : : break;
5758 : : attrs = attr;
5759 : : }
5760 : :
5761 : : /* Look for the two `)' tokens. */
5762 : 51273491 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5763 : 51273491 : c_parser_consume_token (parser);
5764 : : else
5765 : : {
5766 : 0 : parser->translate_strings_p = save_translate_strings_p;
5767 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5768 : : "expected %<)%>");
5769 : 0 : return attrs;
5770 : : }
5771 : 51273491 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5772 : 51273490 : c_parser_consume_token (parser);
5773 : : else
5774 : : {
5775 : 1 : parser->translate_strings_p = save_translate_strings_p;
5776 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
5777 : : "expected %<)%>");
5778 : 1 : return attrs;
5779 : : }
5780 : 51273490 : parser->translate_strings_p = save_translate_strings_p;
5781 : : }
5782 : :
5783 : : return attrs;
5784 : : }
5785 : :
5786 : : /* Parse an optional balanced token sequence.
5787 : :
5788 : : balanced-token-sequence:
5789 : : balanced-token
5790 : : balanced-token-sequence balanced-token
5791 : :
5792 : : balanced-token:
5793 : : ( balanced-token-sequence[opt] )
5794 : : [ balanced-token-sequence[opt] ]
5795 : : { balanced-token-sequence[opt] }
5796 : : any token other than ()[]{}
5797 : : */
5798 : :
5799 : : static void
5800 : 142 : c_parser_balanced_token_sequence (c_parser *parser)
5801 : : {
5802 : 551 : while (true)
5803 : : {
5804 : 551 : c_token *token = c_parser_peek_token (parser);
5805 : 551 : switch (token->type)
5806 : : {
5807 : 4 : case CPP_OPEN_BRACE:
5808 : 4 : {
5809 : 4 : matching_braces braces;
5810 : 4 : braces.consume_open (parser);
5811 : 4 : c_parser_balanced_token_sequence (parser);
5812 : 4 : braces.require_close (parser);
5813 : 4 : break;
5814 : : }
5815 : :
5816 : 42 : case CPP_OPEN_PAREN:
5817 : 42 : {
5818 : 42 : matching_parens parens;
5819 : 42 : parens.consume_open (parser);
5820 : 42 : c_parser_balanced_token_sequence (parser);
5821 : 42 : parens.require_close (parser);
5822 : 42 : break;
5823 : : }
5824 : :
5825 : 33 : case CPP_OPEN_SQUARE:
5826 : 33 : c_parser_consume_token (parser);
5827 : 33 : c_parser_balanced_token_sequence (parser);
5828 : 33 : c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
5829 : 33 : break;
5830 : :
5831 : 142 : case CPP_CLOSE_BRACE:
5832 : 142 : case CPP_CLOSE_PAREN:
5833 : 142 : case CPP_CLOSE_SQUARE:
5834 : 142 : case CPP_EOF:
5835 : 142 : return;
5836 : :
5837 : 1 : case CPP_PRAGMA:
5838 : 1 : c_parser_consume_pragma (parser);
5839 : 1 : c_parser_skip_to_pragma_eol (parser, false);
5840 : 1 : break;
5841 : :
5842 : 329 : default:
5843 : 329 : c_parser_consume_token (parser);
5844 : 329 : break;
5845 : : }
5846 : : }
5847 : : }
5848 : :
5849 : : static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
5850 : : unsigned int *);
5851 : :
5852 : : /* Parse arguments of omp::directive or omp::decl attribute.
5853 : :
5854 : : directive-name ,[opt] clause-list[opt]
5855 : :
5856 : : For directive just remember the tokens in a vector for subsequent
5857 : : parsing. */
5858 : :
5859 : : static void
5860 : 904 : c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5861 : : {
5862 : 904 : unsigned int n = 1;
5863 : 904 : c_token *first = c_parser_peek_token (parser);
5864 : 904 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
5865 : 904 : || (c_parser_peek_nth_token_raw (parser, n)->type
5866 : : != CPP_CLOSE_PAREN))
5867 : : {
5868 : 1 : c_parser_balanced_token_sequence (parser);
5869 : 1 : TREE_VALUE (attribute) = NULL_TREE;
5870 : 3 : return;
5871 : : }
5872 : 903 : if (n == 1)
5873 : : {
5874 : 2 : error_at (first->location, "expected OpenMP directive name");
5875 : 2 : TREE_VALUE (attribute) = NULL_TREE;
5876 : 2 : return;
5877 : : }
5878 : 901 : vec<c_token, va_gc> *v;
5879 : 901 : vec_alloc (v, n - 1);
5880 : 18697 : for (--n; n; --n)
5881 : : {
5882 : 17796 : c_token *tok = c_parser_peek_token (parser);
5883 : 17796 : v->quick_push (*tok);
5884 : 17796 : c_parser_consume_token (parser);
5885 : : }
5886 : 901 : tree arg = make_node (C_TOKEN_VEC);
5887 : 901 : C_TOKEN_VEC_TOKENS (arg) = v;
5888 : 901 : if (decl_p)
5889 : 54 : TREE_PUBLIC (arg) = 1;
5890 : 901 : TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
5891 : : }
5892 : :
5893 : : /* Parse arguments of omp::sequence attribute.
5894 : :
5895 : : omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
5896 : :
5897 : : static void
5898 : 157 : c_parser_omp_sequence_args (c_parser *parser, tree attribute)
5899 : : {
5900 : 314 : do
5901 : : {
5902 : 314 : c_token *token = c_parser_peek_token (parser);
5903 : 314 : if (token->type == CPP_NAME
5904 : 313 : && strcmp (IDENTIFIER_POINTER (token->value), "omp") == 0
5905 : 378 : && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
5906 : : {
5907 : 64 : c_parser_consume_token (parser);
5908 : 64 : c_parser_consume_token (parser);
5909 : 64 : token = c_parser_peek_token (parser);
5910 : : }
5911 : 314 : bool directive = false;
5912 : 314 : const char *p;
5913 : 314 : if (token->type != CPP_NAME)
5914 : : p = "";
5915 : : else
5916 : 313 : p = IDENTIFIER_POINTER (token->value);
5917 : 314 : if (strcmp (p, "directive") == 0)
5918 : : directive = true;
5919 : 12 : else if (strcmp (p, "sequence") != 0)
5920 : : {
5921 : 7 : error_at (token->location, "expected %<directive%> or %<sequence%>");
5922 : 7 : unsigned nesting_depth = 0;
5923 : :
5924 : 47 : while (true)
5925 : : {
5926 : : /* Peek at the next token. */
5927 : 27 : token = c_parser_peek_token (parser);
5928 : : /* If we've reached the token we want, consume it and stop. */
5929 : 27 : if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
5930 : 13 : && !nesting_depth)
5931 : : break;
5932 : : /* If we've run out of tokens, stop. */
5933 : 20 : if (token->type == CPP_EOF)
5934 : : break;
5935 : 20 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
5936 : : break;
5937 : 20 : if (token->type == CPP_OPEN_BRACE
5938 : : || token->type == CPP_OPEN_PAREN
5939 : : || token->type == CPP_OPEN_SQUARE)
5940 : 6 : ++nesting_depth;
5941 : : else if (token->type == CPP_CLOSE_BRACE
5942 : : || token->type == CPP_CLOSE_PAREN
5943 : : || token->type == CPP_CLOSE_SQUARE)
5944 : : {
5945 : 6 : if (nesting_depth-- == 0)
5946 : : break;
5947 : : }
5948 : : /* Consume this token. */
5949 : 20 : c_parser_consume_token (parser);
5950 : : }
5951 : 7 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
5952 : : break;
5953 : 0 : c_parser_consume_token (parser);
5954 : 0 : continue;
5955 : 0 : }
5956 : 307 : c_parser_consume_token (parser);
5957 : 307 : matching_parens parens;
5958 : 307 : if (parens.require_open (parser))
5959 : : {
5960 : 305 : if (directive)
5961 : 301 : c_parser_omp_directive_args (parser, attribute, false);
5962 : : else
5963 : 4 : c_parser_omp_sequence_args (parser, attribute);
5964 : 305 : parens.skip_until_found_close (parser);
5965 : 305 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
5966 : : break;
5967 : 157 : c_parser_consume_token (parser);
5968 : : }
5969 : 2 : else if (c_parser_next_token_is_not (parser, CPP_COMMA))
5970 : : break;
5971 : : else
5972 : 0 : c_parser_consume_token (parser);
5973 : : }
5974 : : while (1);
5975 : 157 : }
5976 : :
5977 : : /* Parse standard (C23) attributes (including GNU attributes in the
5978 : : gnu:: namespace).
5979 : :
5980 : : attribute-specifier-sequence:
5981 : : attribute-specifier-sequence[opt] attribute-specifier
5982 : :
5983 : : attribute-specifier:
5984 : : [ [ attribute-list ] ]
5985 : :
5986 : : attribute-list:
5987 : : attribute[opt]
5988 : : attribute-list, attribute[opt]
5989 : :
5990 : : attribute:
5991 : : attribute-token attribute-argument-clause[opt]
5992 : :
5993 : : attribute-token:
5994 : : standard-attribute
5995 : : attribute-prefixed-token
5996 : :
5997 : : standard-attribute:
5998 : : identifier
5999 : :
6000 : : attribute-prefixed-token:
6001 : : attribute-prefix :: identifier
6002 : :
6003 : : attribute-prefix:
6004 : : identifier
6005 : :
6006 : : attribute-argument-clause:
6007 : : ( balanced-token-sequence[opt] )
6008 : :
6009 : : Keywords are accepted as identifiers for this purpose.
6010 : :
6011 : : As an extension, we permit an attribute-specifier to be:
6012 : :
6013 : : [ [ __extension__ attribute-list ] ]
6014 : :
6015 : : Two colons are then accepted as a synonym for ::. No attempt is made
6016 : : to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
6017 : : indicates whether this relaxation is in effect. */
6018 : :
6019 : : static tree
6020 : 1775 : c_parser_std_attribute (c_parser *parser, bool for_tm)
6021 : : {
6022 : 1775 : c_token *token = c_parser_peek_token (parser);
6023 : 1775 : tree ns, name, attribute;
6024 : :
6025 : : /* Parse the attribute-token. */
6026 : 1775 : if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6027 : : {
6028 : 2 : c_parser_error (parser, "expected identifier");
6029 : 2 : return error_mark_node;
6030 : : }
6031 : 1773 : name = canonicalize_attr_name (token->value);
6032 : 1773 : c_parser_consume_token (parser);
6033 : 1773 : if (c_parser_next_token_is (parser, CPP_SCOPE)
6034 : 2218 : || (c_parser_next_token_is (parser, CPP_COLON)
6035 : 36 : && (c_parser_peek_token (parser)->flags & COLON_SCOPE) != 0
6036 : 10 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
6037 : : {
6038 : 1338 : ns = name;
6039 : 1338 : if (c_parser_next_token_is (parser, CPP_COLON))
6040 : 10 : c_parser_consume_token (parser);
6041 : 1338 : c_parser_consume_token (parser);
6042 : 1338 : token = c_parser_peek_token (parser);
6043 : 1338 : if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6044 : : {
6045 : 0 : c_parser_error (parser, "expected identifier");
6046 : 0 : return error_mark_node;
6047 : : }
6048 : 1338 : name = canonicalize_attr_name (token->value);
6049 : 1338 : c_parser_consume_token (parser);
6050 : : }
6051 : : else
6052 : : ns = NULL_TREE;
6053 : 1773 : attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
6054 : :
6055 : : /* Parse the arguments, if any. */
6056 : 1773 : const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
6057 : 1773 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
6058 : : {
6059 : 841 : if ((flag_openmp || flag_openmp_simd)
6060 : 9 : && ns
6061 : 7 : && is_attribute_p ("omp", ns)
6062 : 853 : && (is_attribute_p ("directive", name)
6063 : 2 : || is_attribute_p ("sequence", name)
6064 : 1 : || is_attribute_p ("decl", name)))
6065 : : {
6066 : 3 : error ("%<omp::%E%> attribute requires argument", name);
6067 : 3 : return error_mark_node;
6068 : : }
6069 : 847 : goto out;
6070 : : }
6071 : 923 : {
6072 : 923 : location_t open_loc = c_parser_peek_token (parser)->location;
6073 : 923 : matching_parens parens;
6074 : 923 : parens.consume_open (parser);
6075 : 125 : if ((as && as->max_length == 0)
6076 : : /* Special-case the transactional-memory attribute "outer",
6077 : : which is specially handled but not registered as an
6078 : : attribute, to avoid allowing arbitrary balanced token
6079 : : sequences as arguments. */
6080 : 1025 : || is_attribute_p ("outer", name))
6081 : : {
6082 : 24 : error_at (open_loc, "%qE attribute does not take any arguments", name);
6083 : 24 : parens.skip_until_found_close (parser);
6084 : 780 : return error_mark_node;
6085 : : }
6086 : : /* If this is a fake attribute created to handle -Wno-attributes,
6087 : : we must skip parsing the arguments. */
6088 : 899 : if (as && !attribute_ignored_p (as))
6089 : : {
6090 : 89 : bool takes_identifier
6091 : : = (ns != NULL_TREE
6092 : 68 : && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
6093 : 157 : && attribute_takes_identifier_p (name));
6094 : 21 : bool require_string
6095 : : = (ns == NULL_TREE
6096 : 21 : && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0
6097 : 11 : || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0));
6098 : 68 : bool assume_attr
6099 : : = (ns != NULL_TREE
6100 : 68 : && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
6101 : 68 : && strcmp (IDENTIFIER_POINTER (name), "assume") == 0);
6102 : 178 : TREE_VALUE (attribute)
6103 : 89 : = c_parser_attribute_arguments (parser, takes_identifier,
6104 : : require_string, assume_attr, false);
6105 : : }
6106 : : else
6107 : : {
6108 : 54 : if ((flag_openmp || flag_openmp_simd)
6109 : 756 : && ns
6110 : 1566 : && is_attribute_p ("omp", ns))
6111 : : {
6112 : 756 : if (is_attribute_p ("directive", name))
6113 : : {
6114 : 548 : c_parser_omp_directive_args (parser, attribute, false);
6115 : 548 : parens.skip_until_found_close (parser);
6116 : 548 : return attribute;
6117 : : }
6118 : 208 : else if (is_attribute_p ("decl", name))
6119 : : {
6120 : 55 : TREE_VALUE (TREE_PURPOSE (attribute))
6121 : 55 : = get_identifier ("directive");
6122 : 55 : c_parser_omp_directive_args (parser, attribute, true);
6123 : 55 : parens.skip_until_found_close (parser);
6124 : 55 : return attribute;
6125 : : }
6126 : 153 : else if (is_attribute_p ("sequence", name))
6127 : : {
6128 : 153 : TREE_VALUE (TREE_PURPOSE (attribute))
6129 : 153 : = get_identifier ("directive");
6130 : 153 : c_parser_omp_sequence_args (parser, attribute);
6131 : 153 : parens.skip_until_found_close (parser);
6132 : 153 : TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
6133 : 153 : return attribute;
6134 : : }
6135 : : }
6136 : 54 : c_parser_balanced_token_sequence (parser);
6137 : : }
6138 : 143 : parens.require_close (parser);
6139 : : }
6140 : 990 : out:
6141 : 990 : if (ns == NULL_TREE && !for_tm && !as)
6142 : : {
6143 : : /* An attribute with standard syntax and no namespace specified
6144 : : is a constraint violation if it is not one of the known
6145 : : standard attributes. Diagnose it here with a pedwarn and
6146 : : then discard it to prevent a duplicate warning later. */
6147 : 72 : pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
6148 : : name);
6149 : 72 : return error_mark_node;
6150 : : }
6151 : : return attribute;
6152 : : }
6153 : :
6154 : : static tree
6155 : 1890 : c_parser_std_attribute_list (c_parser *parser, bool for_tm)
6156 : : {
6157 : 1890 : tree attributes = NULL_TREE;
6158 : 2114 : while (true)
6159 : : {
6160 : 2114 : c_token *token = c_parser_peek_token (parser);
6161 : 2114 : if (token->type == CPP_CLOSE_SQUARE)
6162 : : break;
6163 : 1898 : if (token->type == CPP_COMMA)
6164 : : {
6165 : 123 : c_parser_consume_token (parser);
6166 : 123 : continue;
6167 : : }
6168 : 1775 : tree attribute = c_parser_std_attribute (parser, for_tm);
6169 : 1775 : if (attribute != error_mark_node)
6170 : : {
6171 : 1674 : TREE_CHAIN (attribute) = attributes;
6172 : 1674 : attributes = attribute;
6173 : : }
6174 : 1775 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
6175 : : break;
6176 : : }
6177 : 1890 : return attributes;
6178 : : }
6179 : :
6180 : : static tree
6181 : 1890 : c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
6182 : : {
6183 : 1890 : location_t loc = c_parser_peek_token (parser)->location;
6184 : 1890 : if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
6185 : : return NULL_TREE;
6186 : 1890 : if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
6187 : : {
6188 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6189 : 0 : return NULL_TREE;
6190 : : }
6191 : 1890 : tree attributes;
6192 : 1890 : if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
6193 : : {
6194 : 42 : auto ext = disable_extension_diagnostics ();
6195 : 42 : c_parser_consume_token (parser);
6196 : 42 : attributes = c_parser_std_attribute_list (parser, for_tm);
6197 : 42 : restore_extension_diagnostics (ext);
6198 : : }
6199 : : else
6200 : : {
6201 : 1848 : if (!for_tm)
6202 : 1828 : pedwarn_c11 (loc, OPT_Wpedantic,
6203 : : "ISO C does not support %<[[]]%> attributes before C23");
6204 : 1848 : attributes = c_parser_std_attribute_list (parser, for_tm);
6205 : : }
6206 : 1890 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6207 : 1890 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6208 : 1890 : return nreverse (attributes);
6209 : : }
6210 : :
6211 : : /* Look past an optional balanced token sequence of raw look-ahead
6212 : : tokens starting with the *Nth token. *N is updated to point to the
6213 : : following token. Return true if such a sequence was found, false
6214 : : if the tokens parsed were not balanced. */
6215 : :
6216 : : static bool
6217 : 4344 : c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
6218 : : {
6219 : 20098 : while (true)
6220 : : {
6221 : 20098 : c_token *token = c_parser_peek_nth_token_raw (parser, *n);
6222 : 20098 : switch (token->type)
6223 : : {
6224 : 44 : case CPP_OPEN_BRACE:
6225 : 44 : {
6226 : 44 : ++*n;
6227 : 44 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6228 : : {
6229 : 44 : token = c_parser_peek_nth_token_raw (parser, *n);
6230 : 44 : if (token->type == CPP_CLOSE_BRACE)
6231 : 44 : ++*n;
6232 : : else
6233 : : return false;
6234 : : }
6235 : : else
6236 : : return false;
6237 : 44 : break;
6238 : : }
6239 : :
6240 : 3127 : case CPP_OPEN_PAREN:
6241 : 3127 : {
6242 : 3127 : ++*n;
6243 : 3127 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6244 : : {
6245 : 3127 : token = c_parser_peek_nth_token_raw (parser, *n);
6246 : 3127 : if (token->type == CPP_CLOSE_PAREN)
6247 : 3127 : ++*n;
6248 : : else
6249 : : return false;
6250 : : }
6251 : : else
6252 : : return false;
6253 : 3127 : break;
6254 : : }
6255 : :
6256 : 55 : case CPP_OPEN_SQUARE:
6257 : 55 : {
6258 : 55 : ++*n;
6259 : 55 : if (c_parser_check_balanced_raw_token_sequence (parser, n))
6260 : : {
6261 : 55 : token = c_parser_peek_nth_token_raw (parser, *n);
6262 : 55 : if (token->type == CPP_CLOSE_SQUARE)
6263 : 55 : ++*n;
6264 : : else
6265 : : return false;
6266 : : }
6267 : : else
6268 : : return false;
6269 : 55 : break;
6270 : : }
6271 : :
6272 : : case CPP_CLOSE_BRACE:
6273 : : case CPP_CLOSE_PAREN:
6274 : : case CPP_CLOSE_SQUARE:
6275 : : case CPP_EOF:
6276 : : return true;
6277 : :
6278 : 12528 : default:
6279 : 12528 : ++*n;
6280 : 12528 : break;
6281 : : }
6282 : : }
6283 : : }
6284 : :
6285 : : /* Return whether standard attributes start with the Nth token. */
6286 : :
6287 : : static bool
6288 : 865604598 : c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
6289 : : {
6290 : 865604598 : if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
6291 : 2269409 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
6292 : 865602242 : return false;
6293 : : /* In C, '[[' must start attributes. In Objective-C, we need to
6294 : : check whether '[[' is matched by ']]'. */
6295 : 2356 : if (!c_dialect_objc ())
6296 : : return true;
6297 : 0 : n += 2;
6298 : 0 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
6299 : : return false;
6300 : 0 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
6301 : 0 : if (token->type != CPP_CLOSE_SQUARE)
6302 : : return false;
6303 : 0 : token = c_parser_peek_nth_token_raw (parser, n + 1);
6304 : 0 : return token->type == CPP_CLOSE_SQUARE;
6305 : : }
6306 : :
6307 : : /* Skip standard attribute tokens starting at Nth token (with 1 as the
6308 : : next token), return index of the first token after the standard
6309 : : attribute tokens, or N on failure. */
6310 : :
6311 : : static size_t
6312 : 319 : c_parser_skip_std_attribute_spec_seq (c_parser *parser, size_t n)
6313 : : {
6314 : 319 : size_t orig_n = n;
6315 : 351 : while (true)
6316 : : {
6317 : 335 : if (c_parser_peek_nth_token_raw (parser, n)->type == CPP_OPEN_SQUARE
6318 : 335 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
6319 : : == CPP_OPEN_SQUARE))
6320 : : {
6321 : 16 : unsigned int m = n + 2;
6322 : 16 : if (!c_parser_check_balanced_raw_token_sequence (parser, &m))
6323 : 0 : return orig_n;
6324 : 16 : c_token *token = c_parser_peek_nth_token_raw (parser, m);
6325 : 16 : if (token->type != CPP_CLOSE_SQUARE)
6326 : : return orig_n;
6327 : 16 : token = c_parser_peek_nth_token_raw (parser, m + 1);
6328 : 16 : if (token->type != CPP_CLOSE_SQUARE)
6329 : : return orig_n;
6330 : 16 : n = m + 2;
6331 : : }
6332 : : else
6333 : : break;
6334 : 16 : }
6335 : : return n;
6336 : : }
6337 : :
6338 : : static tree
6339 : 1810 : c_parser_std_attribute_specifier_sequence (c_parser *parser)
6340 : : {
6341 : 1810 : tree attributes = NULL_TREE;
6342 : 1870 : do
6343 : : {
6344 : 1870 : tree attrs = c_parser_std_attribute_specifier (parser, false);
6345 : 1870 : attributes = chainon (attributes, attrs);
6346 : : }
6347 : 1870 : while (c_parser_nth_token_starts_std_attributes (parser, 1));
6348 : 1810 : return attributes;
6349 : : }
6350 : :
6351 : : /* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6352 : : says whether alignment specifiers are OK (only in cases that might
6353 : : be the type name of a compound literal).
6354 : :
6355 : : type-name:
6356 : : specifier-qualifier-list abstract-declarator[opt]
6357 : : */
6358 : :
6359 : : struct c_type_name *
6360 : 118273970 : c_parser_type_name (c_parser *parser, bool alignas_ok)
6361 : : {
6362 : 118273970 : struct c_declspecs *specs = build_null_declspecs ();
6363 : 118273970 : struct c_declarator *declarator;
6364 : 118273970 : struct c_type_name *ret;
6365 : 118273970 : bool dummy = false;
6366 : 118273970 : c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false,
6367 : : false, true, cla_prefer_type);
6368 : 118273970 : if (!specs->declspecs_seen_p)
6369 : : {
6370 : 4 : c_parser_error (parser, "expected specifier-qualifier-list");
6371 : 4 : return NULL;
6372 : : }
6373 : 118273966 : if (specs->type != error_mark_node)
6374 : : {
6375 : 118273949 : pending_xref_error ();
6376 : 118273949 : finish_declspecs (specs);
6377 : : }
6378 : 236547932 : declarator = c_parser_declarator (parser,
6379 : 118273966 : specs->typespec_kind != ctsk_none,
6380 : : C_DTR_ABSTRACT, &dummy);
6381 : 118273966 : if (declarator == NULL)
6382 : : return NULL;
6383 : 118273963 : ret = XOBNEW (&parser_obstack, struct c_type_name);
6384 : 118273963 : ret->specs = specs;
6385 : 118273963 : ret->declarator = declarator;
6386 : 118273963 : return ret;
6387 : : }
6388 : :
6389 : : /* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6390 : :
6391 : : initializer:
6392 : : assignment-expression
6393 : : { initializer-list }
6394 : : { initializer-list , }
6395 : :
6396 : : initializer-list:
6397 : : designation[opt] initializer
6398 : : initializer-list , designation[opt] initializer
6399 : :
6400 : : designation:
6401 : : designator-list =
6402 : :
6403 : : designator-list:
6404 : : designator
6405 : : designator-list designator
6406 : :
6407 : : designator:
6408 : : array-designator
6409 : : . identifier
6410 : :
6411 : : array-designator:
6412 : : [ constant-expression ]
6413 : :
6414 : : GNU extensions:
6415 : :
6416 : : initializer:
6417 : : { }
6418 : :
6419 : : designation:
6420 : : array-designator
6421 : : identifier :
6422 : :
6423 : : array-designator:
6424 : : [ constant-expression ... constant-expression ]
6425 : :
6426 : : Any expression without commas is accepted in the syntax for the
6427 : : constant-expressions, with non-constant expressions rejected later.
6428 : :
6429 : : DECL is the declaration we're parsing this initializer for.
6430 : :
6431 : : This function is only used for top-level initializers; for nested
6432 : : ones, see c_parser_initval. */
6433 : :
6434 : : static struct c_expr
6435 : 6188907 : c_parser_initializer (c_parser *parser, tree decl)
6436 : : {
6437 : 6188907 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
6438 : 104069 : return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
6439 : : else
6440 : : {
6441 : 6084838 : struct c_expr ret;
6442 : 6084838 : location_t loc = c_parser_peek_token (parser)->location;
6443 : 6084838 : ret = c_parser_expr_no_commas (parser, NULL);
6444 : 6084836 : if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6445 : : {
6446 : 2 : error_at (loc,
6447 : : "variable-sized object may not be initialized except "
6448 : : "with an empty initializer");
6449 : 2 : ret.set_error ();
6450 : : }
6451 : : /* This is handled mostly by gimplify.cc, but we have to deal with
6452 : : not warning about int x = x; as it is a GCC extension to turn off
6453 : : this warning but only if warn_init_self is zero. */
6454 : 6084836 : if (VAR_P (decl)
6455 : 6084788 : && !DECL_EXTERNAL (decl)
6456 : 6084788 : && !TREE_STATIC (decl)
6457 : 5965758 : && ret.value == decl
6458 : 6171984 : && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), OPT_Winit_self))
6459 : 87141 : suppress_warning (decl, OPT_Winit_self);
6460 : 6084836 : if (TREE_CODE (ret.value) != STRING_CST
6461 : 6084836 : && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6462 : 93176 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6463 : : (ret.value))))
6464 : 5977765 : ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6465 : 6084836 : return ret;
6466 : : }
6467 : : }
6468 : :
6469 : : /* The location of the last comma within the current initializer list,
6470 : : or UNKNOWN_LOCATION if not within one. */
6471 : :
6472 : : location_t last_init_list_comma;
6473 : :
6474 : : /* Parse a braced initializer list. TYPE is the type specified for a
6475 : : compound literal, and NULL_TREE for other initializers and for
6476 : : nested braced lists. NESTED_P is true for nested braced lists,
6477 : : false for the list of a compound literal or the list that is the
6478 : : top-level initializer in a declaration. DECL is the declaration for
6479 : : the top-level initializer for a declaration, otherwise NULL_TREE. */
6480 : :
6481 : : static struct c_expr
6482 : 1340696 : c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6483 : : struct obstack *outer_obstack, tree decl)
6484 : : {
6485 : 1340696 : struct c_expr ret;
6486 : 1340696 : struct obstack braced_init_obstack;
6487 : 1340696 : location_t brace_loc = c_parser_peek_token (parser)->location;
6488 : 1340696 : gcc_obstack_init (&braced_init_obstack);
6489 : 1340696 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6490 : 1340696 : bool save_c_omp_array_section_p = c_omp_array_section_p;
6491 : 1340696 : c_omp_array_section_p = false;
6492 : 1340696 : bool zero_init_padding_bits = false;
6493 : 1340696 : matching_braces braces;
6494 : 1340696 : braces.consume_open (parser);
6495 : 1340696 : if (nested_p)
6496 : : {
6497 : 339340 : finish_implicit_inits (brace_loc, outer_obstack);
6498 : 339340 : push_init_level (brace_loc, 0, &braced_init_obstack);
6499 : : }
6500 : : else
6501 : 1001356 : really_start_incremental_init (type);
6502 : 1340696 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6503 : : {
6504 : 2459 : pedwarn_c11 (brace_loc, OPT_Wpedantic,
6505 : : "ISO C forbids empty initializer braces before C23");
6506 : 2459 : if (flag_isoc23)
6507 : 1340696 : zero_init_padding_bits = true;
6508 : : }
6509 : : else
6510 : : {
6511 : 1338237 : if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6512 : 51 : error_at (brace_loc,
6513 : : "variable-sized object may not be initialized except "
6514 : : "with an empty initializer");
6515 : : /* Parse a non-empty initializer list, possibly with a trailing
6516 : : comma. */
6517 : 8739762 : while (true)
6518 : : {
6519 : 8739762 : c_parser_initelt (parser, &braced_init_obstack);
6520 : 8739762 : if (parser->error)
6521 : : break;
6522 : 8739732 : if (c_parser_next_token_is (parser, CPP_COMMA))
6523 : : {
6524 : 7404180 : last_init_list_comma = c_parser_peek_token (parser)->location;
6525 : 7404180 : c_parser_consume_token (parser);
6526 : : /* CPP_EMBED should be always in between two CPP_COMMA
6527 : : tokens. */
6528 : 14808463 : while (c_parser_next_token_is (parser, CPP_EMBED))
6529 : : {
6530 : 103 : c_token *embed = c_parser_peek_token (parser);
6531 : 103 : c_parser_consume_token (parser);
6532 : 103 : c_expr embed_val;
6533 : 103 : embed_val.value = embed->value;
6534 : 103 : embed_val.original_code = RAW_DATA_CST;
6535 : 103 : embed_val.original_type = integer_type_node;
6536 : 103 : set_c_expr_source_range (&embed_val, embed->get_range ());
6537 : 103 : embed_val.m_decimal = 0;
6538 : 103 : process_init_element (embed->location, embed_val, false,
6539 : : &braced_init_obstack);
6540 : 103 : gcc_checking_assert (c_parser_next_token_is (parser,
6541 : : CPP_COMMA));
6542 : 103 : last_init_list_comma = c_parser_peek_token (parser)->location;
6543 : 103 : c_parser_consume_token (parser);
6544 : : }
6545 : : }
6546 : : else
6547 : : break;
6548 : 7404180 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6549 : : break;
6550 : : }
6551 : : }
6552 : 1340696 : c_omp_array_section_p = save_c_omp_array_section_p;
6553 : 1340696 : c_token *next_tok = c_parser_peek_token (parser);
6554 : 1340696 : if (next_tok->type != CPP_CLOSE_BRACE)
6555 : : {
6556 : 31 : ret.set_error ();
6557 : 31 : ret.original_code = ERROR_MARK;
6558 : 31 : ret.original_type = NULL;
6559 : 31 : braces.skip_until_found_close (parser);
6560 : 31 : pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6561 : 31 : obstack_free (&braced_init_obstack, NULL);
6562 : : return ret;
6563 : : }
6564 : 1340665 : location_t close_loc = next_tok->location;
6565 : 1340665 : c_parser_consume_token (parser);
6566 : 1340665 : ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6567 : 1340665 : if (zero_init_padding_bits
6568 : 2202 : && ret.value
6569 : 2135 : && TREE_CODE (ret.value) == CONSTRUCTOR)
6570 : 2042 : CONSTRUCTOR_ZERO_PADDING_BITS (ret.value) = 1;
6571 : 1340665 : obstack_free (&braced_init_obstack, NULL);
6572 : 1340665 : set_c_expr_source_range (&ret, brace_loc, close_loc);
6573 : 1340665 : return ret;
6574 : : }
6575 : :
6576 : : /* Parse a nested initializer, including designators. */
6577 : :
6578 : : static void
6579 : 8739762 : c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6580 : : {
6581 : : /* Parse any designator or designator list. A single array
6582 : : designator may have the subsequent "=" omitted in GNU C, but a
6583 : : longer list or a structure member designator may not. */
6584 : 8739762 : if (c_parser_next_token_is (parser, CPP_NAME)
6585 : 8739762 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6586 : : {
6587 : : /* Old-style structure member designator. */
6588 : 156 : set_init_label (c_parser_peek_token (parser)->location,
6589 : 156 : c_parser_peek_token (parser)->value,
6590 : 156 : c_parser_peek_token (parser)->location,
6591 : : braced_init_obstack);
6592 : : /* Use the colon as the error location. */
6593 : 156 : pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6594 : : "obsolete use of designated initializer with %<:%>");
6595 : 156 : c_parser_consume_token (parser);
6596 : 156 : c_parser_consume_token (parser);
6597 : : }
6598 : : else
6599 : : {
6600 : : /* des_seen is 0 if there have been no designators, 1 if there
6601 : : has been a single array designator and 2 otherwise. */
6602 : : int des_seen = 0;
6603 : : /* Location of a designator. */
6604 : : location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6605 : 8772465 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
6606 : 17543787 : || c_parser_next_token_is (parser, CPP_DOT))
6607 : : {
6608 : 32859 : int des_prev = des_seen;
6609 : 32859 : if (!des_seen)
6610 : 32281 : des_loc = c_parser_peek_token (parser)->location;
6611 : 32859 : if (des_seen < 2)
6612 : 32359 : des_seen++;
6613 : 32859 : if (c_parser_next_token_is (parser, CPP_DOT))
6614 : : {
6615 : 31716 : des_seen = 2;
6616 : 31716 : c_parser_consume_token (parser);
6617 : 31716 : if (c_parser_next_token_is (parser, CPP_NAME))
6618 : : {
6619 : 31716 : set_init_label (des_loc, c_parser_peek_token (parser)->value,
6620 : 31716 : c_parser_peek_token (parser)->location,
6621 : : braced_init_obstack);
6622 : 31716 : c_parser_consume_token (parser);
6623 : : }
6624 : : else
6625 : : {
6626 : 0 : struct c_expr init;
6627 : 0 : init.set_error ();
6628 : 0 : init.original_code = ERROR_MARK;
6629 : 0 : init.original_type = NULL;
6630 : 0 : c_parser_error (parser, "expected identifier");
6631 : 0 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
6632 : 0 : process_init_element (input_location, init, false,
6633 : : braced_init_obstack);
6634 : 0 : return;
6635 : : }
6636 : : }
6637 : : else
6638 : : {
6639 : 1143 : struct c_expr first_expr;
6640 : 1143 : tree first, second;
6641 : 1143 : location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6642 : 1143 : location_t array_index_loc = UNKNOWN_LOCATION;
6643 : : /* ??? Following the old parser, [ objc-receiver
6644 : : objc-message-args ] is accepted as an initializer,
6645 : : being distinguished from a designator by what follows
6646 : : the first assignment expression inside the square
6647 : : brackets, but after a first array designator a
6648 : : subsequent square bracket is for Objective-C taken to
6649 : : start an expression, using the obsolete form of
6650 : : designated initializer without '=', rather than
6651 : : possibly being a second level of designation: in LALR
6652 : : terms, the '[' is shifted rather than reducing
6653 : : designator to designator-list. */
6654 : 1143 : if (des_prev == 1 && c_dialect_objc ())
6655 : : {
6656 : 0 : des_seen = des_prev;
6657 : 0 : break;
6658 : : }
6659 : 1143 : if (des_prev == 0 && c_dialect_objc ())
6660 : : {
6661 : : /* This might be an array designator or an
6662 : : Objective-C message expression. If the former,
6663 : : continue parsing here; if the latter, parse the
6664 : : remainder of the initializer given the starting
6665 : : primary-expression. ??? It might make sense to
6666 : : distinguish when des_prev == 1 as well; see
6667 : : previous comment. */
6668 : 0 : tree rec, args;
6669 : 0 : struct c_expr mexpr;
6670 : 0 : c_parser_consume_token (parser);
6671 : 0 : if (c_parser_peek_token (parser)->type == CPP_NAME
6672 : 0 : && ((c_parser_peek_token (parser)->id_kind
6673 : : == C_ID_TYPENAME)
6674 : 0 : || (c_parser_peek_token (parser)->id_kind
6675 : : == C_ID_CLASSNAME)))
6676 : : {
6677 : : /* Type name receiver. */
6678 : 0 : tree id = c_parser_peek_token (parser)->value;
6679 : 0 : c_parser_consume_token (parser);
6680 : 0 : rec = objc_get_class_reference (id);
6681 : 0 : goto parse_message_args;
6682 : : }
6683 : 0 : array_index_loc = c_parser_peek_token (parser)->location;
6684 : 0 : first_expr = c_parser_expr_no_commas (parser, NULL);
6685 : 0 : mark_exp_read (first_expr.value);
6686 : 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
6687 : 0 : || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
6688 : 0 : goto array_desig_after_first;
6689 : 0 : first = first_expr.value;
6690 : : /* Expression receiver. So far only one part
6691 : : without commas has been parsed; there might be
6692 : : more of the expression. */
6693 : : rec = first;
6694 : 0 : while (c_parser_next_token_is (parser, CPP_COMMA))
6695 : : {
6696 : 0 : struct c_expr next;
6697 : 0 : location_t comma_loc, exp_loc;
6698 : 0 : comma_loc = c_parser_peek_token (parser)->location;
6699 : 0 : c_parser_consume_token (parser);
6700 : 0 : exp_loc = c_parser_peek_token (parser)->location;
6701 : 0 : next = c_parser_expr_no_commas (parser, NULL);
6702 : 0 : next = convert_lvalue_to_rvalue (exp_loc, next,
6703 : : true, true);
6704 : 0 : rec = build_compound_expr (comma_loc, rec, next.value);
6705 : : }
6706 : 0 : parse_message_args:
6707 : : /* Now parse the objc-message-args. */
6708 : 0 : args = c_parser_objc_message_args (parser);
6709 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
6710 : : "expected %<]%>");
6711 : 0 : mexpr.value
6712 : 0 : = objc_build_message_expr (rec, args);
6713 : 0 : mexpr.original_code = ERROR_MARK;
6714 : 0 : mexpr.original_type = NULL;
6715 : 0 : mexpr.m_decimal = 0;
6716 : : /* Now parse and process the remainder of the
6717 : : initializer, starting with this message
6718 : : expression as a primary-expression. */
6719 : 0 : c_parser_initval (parser, &mexpr, braced_init_obstack);
6720 : 0 : return;
6721 : : }
6722 : 1143 : c_parser_consume_token (parser);
6723 : 1143 : array_index_loc = c_parser_peek_token (parser)->location;
6724 : 1143 : first_expr = c_parser_expr_no_commas (parser, NULL);
6725 : 1143 : mark_exp_read (first_expr.value);
6726 : 1143 : array_desig_after_first:
6727 : 1143 : first_expr = convert_lvalue_to_rvalue (array_index_loc,
6728 : : first_expr,
6729 : : true, true);
6730 : 1143 : first = first_expr.value;
6731 : 1143 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
6732 : : {
6733 : 391 : ellipsis_loc = c_parser_peek_token (parser)->location;
6734 : 391 : c_parser_consume_token (parser);
6735 : 391 : second = convert_lvalue_to_rvalue (ellipsis_loc,
6736 : : (c_parser_expr_no_commas
6737 : : (parser, NULL)),
6738 : : true, true).value;
6739 : 391 : mark_exp_read (second);
6740 : : }
6741 : : else
6742 : : second = NULL_TREE;
6743 : 1143 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
6744 : : {
6745 : 1143 : c_parser_consume_token (parser);
6746 : 1143 : set_init_index (array_index_loc, first, second,
6747 : : braced_init_obstack);
6748 : 1143 : if (second)
6749 : 391 : pedwarn (ellipsis_loc, OPT_Wpedantic,
6750 : : "ISO C forbids specifying range of elements to initialize");
6751 : : }
6752 : : else
6753 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
6754 : : "expected %<]%>");
6755 : : }
6756 : : }
6757 : 8739606 : if (des_seen >= 1)
6758 : : {
6759 : 32281 : if (c_parser_next_token_is (parser, CPP_EQ))
6760 : : {
6761 : 32260 : pedwarn_c90 (des_loc, OPT_Wpedantic,
6762 : : "ISO C90 forbids specifying subobject "
6763 : : "to initialize");
6764 : 32260 : c_parser_consume_token (parser);
6765 : : }
6766 : : else
6767 : : {
6768 : 21 : if (des_seen == 1)
6769 : 19 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6770 : : "obsolete use of designated initializer without %<=%>");
6771 : : else
6772 : : {
6773 : 2 : struct c_expr init;
6774 : 2 : init.set_error ();
6775 : 2 : init.original_code = ERROR_MARK;
6776 : 2 : init.original_type = NULL;
6777 : 2 : c_parser_error (parser, "expected %<=%>");
6778 : 2 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
6779 : 2 : process_init_element (input_location, init, false,
6780 : : braced_init_obstack);
6781 : 2 : return;
6782 : : }
6783 : : }
6784 : : }
6785 : : }
6786 : 8739760 : c_parser_initval (parser, NULL, braced_init_obstack);
6787 : : }
6788 : :
6789 : : /* Parse a nested initializer; as c_parser_initializer but parses
6790 : : initializers within braced lists, after any designators have been
6791 : : applied. If AFTER is not NULL then it is an Objective-C message
6792 : : expression which is the primary-expression starting the
6793 : : initializer. */
6794 : :
6795 : : static void
6796 : 8739760 : c_parser_initval (c_parser *parser, struct c_expr *after,
6797 : : struct obstack * braced_init_obstack)
6798 : : {
6799 : 8739760 : struct c_expr init;
6800 : 8739760 : gcc_assert (!after || c_dialect_objc ());
6801 : 8739760 : location_t loc = c_parser_peek_token (parser)->location;
6802 : :
6803 : 8739760 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
6804 : 339340 : init = c_parser_braced_init (parser, NULL_TREE, true,
6805 : : braced_init_obstack, NULL_TREE);
6806 : : else
6807 : : {
6808 : 8400420 : init = c_parser_expr_no_commas (parser, after);
6809 : 8400420 : if (init.value != NULL_TREE
6810 : 8400420 : && TREE_CODE (init.value) != STRING_CST
6811 : 16759375 : && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6812 : 173 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6813 : : (init.value))))
6814 : 8358787 : init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6815 : : }
6816 : 8739760 : tree val = init.value;
6817 : 8739760 : process_init_element (loc, init, false, braced_init_obstack);
6818 : :
6819 : : /* Attempt to optimize large char array initializers into RAW_DATA_CST
6820 : : to save compile time and memory even when not using #embed. */
6821 : 8739760 : static unsigned vals_to_ignore;
6822 : 8739760 : if (vals_to_ignore)
6823 : : /* If earlier call determined there is certain number of CPP_COMMA
6824 : : CPP_NUMBER tokens with 0-255 int values, but not enough for
6825 : : RAW_DATA_CST to be beneficial, don't try to check it again until
6826 : : they are all parsed. */
6827 : 6022 : --vals_to_ignore;
6828 : 8733738 : else if (val
6829 : 8733612 : && TREE_CODE (val) == INTEGER_CST
6830 : 4122523 : && TREE_TYPE (val) == integer_type_node
6831 : 12307783 : && c_parser_next_token_is (parser, CPP_COMMA))
6832 : 2928579 : if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
6833 : : {
6834 : 8525 : char buf1[64];
6835 : 8525 : unsigned int i;
6836 : 8525 : gcc_checking_assert (len >= 64);
6837 : : location_t last_loc = UNKNOWN_LOCATION;
6838 : 20115 : for (i = 0; i < 64; ++i)
6839 : : {
6840 : 20022 : c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
6841 : 20022 : if (tok->type != CPP_COMMA)
6842 : : break;
6843 : 19225 : tok = c_parser_peek_nth_token_raw (parser, 2 + 2 * i);
6844 : 19225 : if (tok->type != CPP_NUMBER
6845 : 11590 : || TREE_CODE (tok->value) != INTEGER_CST
6846 : 11590 : || TREE_TYPE (tok->value) != integer_type_node
6847 : 11590 : || wi::neg_p (wi::to_wide (tok->value))
6848 : 30815 : || wi::to_widest (tok->value) > UCHAR_MAX)
6849 : : break;
6850 : 11590 : buf1[i] = (char) tree_to_uhwi (tok->value);
6851 : 11590 : if (i == 0)
6852 : 1108 : loc = tok->location;
6853 : 11590 : last_loc = tok->location;
6854 : : }
6855 : 8525 : if (i < 64)
6856 : : {
6857 : 8432 : vals_to_ignore = i;
6858 : 8438 : return;
6859 : : }
6860 : 93 : c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
6861 : : /* If 64 CPP_COMMA CPP_NUMBER pairs are followed by CPP_CLOSE_BRACE,
6862 : : punt if len is INT_MAX as that can mean this is a flexible array
6863 : : member and in that case we need one CPP_NUMBER afterwards
6864 : : (as guaranteed for CPP_EMBED). */
6865 : 93 : if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
6866 : : len = i;
6867 : 91 : else if (tok->type != CPP_COMMA
6868 : 91 : || (c_parser_peek_nth_token_raw (parser, 2 + 2 * i)->type
6869 : : != CPP_NUMBER))
6870 : : {
6871 : 6 : vals_to_ignore = i;
6872 : 6 : return;
6873 : : }
6874 : : /* Ensure the STRING_CST fits into 128K. */
6875 : 87 : unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
6876 : 87 : unsigned int orig_len = len;
6877 : 87 : unsigned int off = 0, last = 0;
6878 : 87 : if (!wi::neg_p (wi::to_wide (val)) && wi::to_widest (val) <= UCHAR_MAX)
6879 : 79 : off = 1;
6880 : 87 : len = MIN (len, max_len - off);
6881 : 87 : char *buf2 = XNEWVEC (char, len + off);
6882 : 87 : if (off)
6883 : 79 : buf2[0] = (char) tree_to_uhwi (val);
6884 : 87 : memcpy (buf2 + off, buf1, i);
6885 : 5655 : for (unsigned int j = 0; j < i; ++j)
6886 : : {
6887 : 5568 : c_parser_peek_token (parser);
6888 : 5568 : c_parser_consume_token (parser);
6889 : 5568 : c_parser_peek_token (parser);
6890 : 5568 : c_parser_consume_token (parser);
6891 : : }
6892 : 18780 : for (; i < len; ++i)
6893 : : {
6894 : 18743 : if (!c_parser_next_token_is (parser, CPP_COMMA))
6895 : : break;
6896 : 18741 : tok = c_parser_peek_2nd_token (parser);
6897 : 18741 : if (tok->type != CPP_NUMBER
6898 : 18733 : || TREE_CODE (tok->value) != INTEGER_CST
6899 : 18733 : || TREE_TYPE (tok->value) != integer_type_node
6900 : 18733 : || wi::neg_p (wi::to_wide (tok->value))
6901 : 37474 : || wi::to_widest (tok->value) > UCHAR_MAX)
6902 : : break;
6903 : 18733 : c_token *tok2 = c_parser_peek_nth_token (parser, 3);
6904 : 18733 : if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
6905 : : break;
6906 : 18730 : buf2[i + off] = (char) tree_to_uhwi (tok->value);
6907 : : /* If orig_len is INT_MAX, this can be flexible array member and
6908 : : in that case we need to ensure another element which
6909 : : for CPP_EMBED is normally guaranteed after it. Include
6910 : : that byte in the RAW_DATA_OWNER though, so it can be optimized
6911 : : later. */
6912 : 18730 : if (orig_len == INT_MAX
6913 : 18730 : && (tok2->type == CPP_CLOSE_BRACE
6914 : 12517 : || (c_parser_peek_nth_token (parser, 4)->type
6915 : : != CPP_NUMBER)))
6916 : : {
6917 : : last = 1;
6918 : : break;
6919 : : }
6920 : 18693 : last_loc = tok->location;
6921 : 18693 : c_parser_consume_token (parser);
6922 : 18693 : c_parser_consume_token (parser);
6923 : : }
6924 : 87 : val = make_node (RAW_DATA_CST);
6925 : 87 : TREE_TYPE (val) = integer_type_node;
6926 : 87 : RAW_DATA_LENGTH (val) = i;
6927 : 87 : tree owner = build_string (i + off + last, buf2);
6928 : 87 : XDELETEVEC (buf2);
6929 : 87 : TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
6930 : 87 : i + off + last);
6931 : 87 : RAW_DATA_OWNER (val) = owner;
6932 : 87 : RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
6933 : 87 : init.value = val;
6934 : 87 : set_c_expr_source_range (&init, loc, last_loc);
6935 : 87 : init.original_code = RAW_DATA_CST;
6936 : 87 : init.original_type = integer_type_node;
6937 : 87 : init.m_decimal = 0;
6938 : 87 : process_init_element (loc, init, false, braced_init_obstack);
6939 : : }
6940 : : }
6941 : :
6942 : : /* Parse a compound statement (possibly a function body) (C90 6.6.2,
6943 : : C99 6.8.2, C11 6.8.2, C23 6.8.2).
6944 : :
6945 : : compound-statement:
6946 : : { block-item-list[opt] }
6947 : : { label-declarations block-item-list }
6948 : :
6949 : : block-item-list:
6950 : : block-item
6951 : : block-item-list block-item
6952 : :
6953 : : block-item:
6954 : : label
6955 : : nested-declaration
6956 : : statement
6957 : :
6958 : : nested-declaration:
6959 : : declaration
6960 : :
6961 : : GNU extensions:
6962 : :
6963 : : compound-statement:
6964 : : { label-declarations block-item-list }
6965 : :
6966 : : nested-declaration:
6967 : : __extension__ nested-declaration
6968 : : nested-function-definition
6969 : :
6970 : : label-declarations:
6971 : : label-declaration
6972 : : label-declarations label-declaration
6973 : :
6974 : : label-declaration:
6975 : : __label__ identifier-list ;
6976 : :
6977 : : Allowing the mixing of declarations and code is new in C99. The
6978 : : GNU syntax also permits (not shown above) labels at the end of
6979 : : compound statements, which yield an error. We don't allow labels
6980 : : on declarations; this might seem like a natural extension, but
6981 : : there would be a conflict between gnu-attributes on the label and
6982 : : prefix gnu-attributes on the declaration. ??? The syntax follows the
6983 : : old parser in requiring something after label declarations.
6984 : : Although they are erroneous if the labels declared aren't defined,
6985 : : is it useful for the syntax to be this way?
6986 : :
6987 : : OpenACC:
6988 : :
6989 : : block-item:
6990 : : openacc-directive
6991 : :
6992 : : openacc-directive:
6993 : : update-directive
6994 : :
6995 : : OpenMP:
6996 : :
6997 : : block-item:
6998 : : openmp-directive
6999 : :
7000 : : openmp-directive:
7001 : : barrier-directive
7002 : : flush-directive
7003 : : taskwait-directive
7004 : : taskyield-directive
7005 : : cancel-directive
7006 : : cancellation-point-directive */
7007 : :
7008 : : static tree
7009 : 36235185 : c_parser_compound_statement (c_parser *parser, location_t *endlocp)
7010 : : {
7011 : 36235185 : tree stmt;
7012 : 36235185 : location_t brace_loc;
7013 : 36235185 : brace_loc = c_parser_peek_token (parser)->location;
7014 : 36235185 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
7015 : : {
7016 : : /* Ensure a scope is entered and left anyway to avoid confusion
7017 : : if we have just prepared to enter a function body. */
7018 : 16 : stmt = c_begin_compound_stmt (true);
7019 : 16 : c_end_compound_stmt (brace_loc, stmt, true);
7020 : 16 : return error_mark_node;
7021 : : }
7022 : 36235169 : stmt = c_begin_compound_stmt (true);
7023 : 36235169 : location_t end_loc = c_parser_compound_statement_nostart (parser);
7024 : 36235168 : if (endlocp)
7025 : 35349404 : *endlocp = end_loc;
7026 : :
7027 : 36235168 : return c_end_compound_stmt (brace_loc, stmt, true);
7028 : : }
7029 : :
7030 : : /* Diagnose errors related to imperfectly nested loops in an OMP
7031 : : loop construct. This function is called when such code is seen.
7032 : : Only issue one such diagnostic no matter how much invalid
7033 : : intervening code there is in the loop.
7034 : : FIXME: maybe the location associated with the diagnostic should
7035 : : be the current parser token instead of the location of the outer loop
7036 : : nest. */
7037 : :
7038 : : static void
7039 : 294 : check_omp_intervening_code (c_parser *parser)
7040 : : {
7041 : 294 : struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
7042 : 294 : gcc_assert (omp_for_parse_state);
7043 : :
7044 : 294 : if (!omp_for_parse_state->in_intervening_code)
7045 : : return;
7046 : 273 : omp_for_parse_state->saw_intervening_code = true;
7047 : :
7048 : : /* Only diagnose errors related to perfect nesting once. */
7049 : 273 : if (!omp_for_parse_state->perfect_nesting_fail)
7050 : : {
7051 : :
7052 : : /* OpenACC does not (yet) permit intervening code, in
7053 : : addition to situations forbidden by the OpenMP spec. */
7054 : 251 : if (omp_for_parse_state->code == OACC_LOOP)
7055 : : {
7056 : 3 : error_at (omp_for_parse_state->for_loc,
7057 : : "inner loops must be perfectly nested in "
7058 : : "%<#pragma acc loop%>");
7059 : 3 : omp_for_parse_state->perfect_nesting_fail = true;
7060 : : }
7061 : 248 : else if (omp_for_parse_state->ordered)
7062 : : {
7063 : 11 : error_at (omp_for_parse_state->for_loc,
7064 : : "inner loops must be perfectly nested with "
7065 : : "%<ordered%> clause");
7066 : 11 : omp_for_parse_state->perfect_nesting_fail = true;
7067 : : }
7068 : 237 : else if (omp_for_parse_state->inscan)
7069 : : {
7070 : 2 : error_at (omp_for_parse_state->for_loc,
7071 : : "inner loops must be perfectly nested with "
7072 : : "%<reduction%> %<inscan%> clause");
7073 : 2 : omp_for_parse_state->perfect_nesting_fail = true;
7074 : : }
7075 : 235 : else if (omp_for_parse_state->code == OMP_TILE)
7076 : : {
7077 : 9 : error_at (omp_for_parse_state->for_loc,
7078 : : "inner loops must be perfectly nested in "
7079 : : "%<pragma omp tile%>");
7080 : 9 : omp_for_parse_state->perfect_nesting_fail = true;
7081 : : }
7082 : 251 : if (omp_for_parse_state->perfect_nesting_fail)
7083 : 25 : omp_for_parse_state->fail = true;
7084 : : }
7085 : : }
7086 : :
7087 : : /* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
7088 : : and add the statement to the current list. If SL is an empty statement
7089 : : list, do nothing. */
7090 : : static void
7091 : 282 : add_structured_block_stmt (tree sl)
7092 : : {
7093 : 282 : if (TREE_CODE (sl) != STATEMENT_LIST
7094 : 282 : || !tsi_end_p (tsi_start (sl)))
7095 : 149 : add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
7096 : 282 : }
7097 : :
7098 : : struct c_omp_attribute_data
7099 : : {
7100 : : vec<c_token, va_gc> *tokens;
7101 : : const c_omp_directive *dir;
7102 : : c_omp_directive_kind kind;
7103 : : };
7104 : :
7105 : : /* Handle omp::directive and omp::sequence attributes in ATTRS
7106 : : (if any) at the start of a statement or in attribute-declaration. */
7107 : :
7108 : : static bool
7109 : 830 : c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
7110 : : bool *have_std_attrs)
7111 : : {
7112 : 830 : if (!flag_openmp && !flag_openmp_simd)
7113 : : return false;
7114 : :
7115 : 604 : auto_vec<c_omp_attribute_data, 16> vd;
7116 : 604 : int cnt = 0;
7117 : 604 : int tokens = 0;
7118 : 604 : bool bad = false;
7119 : 1208 : for (tree *pa = &attrs; *pa; )
7120 : 604 : if (is_attribute_namespace_p ("omp", *pa)
7121 : 604 : && is_attribute_p ("directive", get_attribute_name (*pa)))
7122 : : {
7123 : 603 : cnt++;
7124 : 1346 : for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
7125 : : {
7126 : 743 : tree d = TREE_VALUE (a);
7127 : 743 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7128 : 743 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7129 : 743 : c_token *first = toks->address ();
7130 : 743 : c_token *last = first + toks->length ();
7131 : 743 : if (parser->omp_attrs_forbidden_p)
7132 : : {
7133 : 14 : error_at (first->location,
7134 : : "mixing OpenMP directives with attribute and pragma "
7135 : : "syntax on the same statement");
7136 : 14 : parser->omp_attrs_forbidden_p = false;
7137 : 14 : bad = true;
7138 : : }
7139 : 729 : else if (TREE_PUBLIC (d))
7140 : : {
7141 : 3 : error_at (first->location,
7142 : : "OpenMP %<omp::decl%> attribute on a statement");
7143 : 3 : bad = true;
7144 : : }
7145 : 743 : const char *directive[3] = {};
7146 : 2184 : for (int i = 0; i < 3; i++)
7147 : : {
7148 : 2008 : tree id = NULL_TREE;
7149 : 2008 : if (first + i == last)
7150 : : break;
7151 : 1763 : if (first[i].type == CPP_NAME)
7152 : 1323 : id = first[i].value;
7153 : 440 : else if (first[i].type == CPP_KEYWORD)
7154 : 118 : id = ridpointers[(int) first[i].keyword];
7155 : : else
7156 : : break;
7157 : 1441 : directive[i] = IDENTIFIER_POINTER (id);
7158 : : }
7159 : 743 : const c_omp_directive *dir = NULL;
7160 : 743 : if (directive[0])
7161 : 743 : dir = c_omp_categorize_directive (directive[0], directive[1],
7162 : : directive[2]);
7163 : 743 : if (dir == NULL)
7164 : : {
7165 : 1 : error_at (first->location,
7166 : : "unknown OpenMP directive name in %qs attribute "
7167 : : "argument",
7168 : 1 : TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7169 : 1 : continue;
7170 : : }
7171 : 742 : c_omp_directive_kind kind = dir->kind;
7172 : 742 : if (dir->id == PRAGMA_OMP_ORDERED)
7173 : : {
7174 : : /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
7175 : : depend/doacross clause. */
7176 : 8 : if (directive[1]
7177 : 4 : && (strcmp (directive[1], "depend") == 0
7178 : 2 : || strcmp (directive[1], "doacross") == 0))
7179 : : kind = C_OMP_DIR_STANDALONE;
7180 : 6 : else if (first + 2 < last
7181 : 4 : && first[1].type == CPP_COMMA
7182 : 4 : && first[2].type == CPP_NAME
7183 : 10 : && (strcmp (IDENTIFIER_POINTER (first[2].value),
7184 : : "depend") == 0
7185 : 2 : || strcmp (IDENTIFIER_POINTER (first[2].value),
7186 : : "doacross") == 0))
7187 : : kind = C_OMP_DIR_STANDALONE;
7188 : : }
7189 : 734 : else if (dir->id == PRAGMA_OMP_ERROR)
7190 : : {
7191 : : /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
7192 : : int paren_depth = 0;
7193 : 99 : for (int i = 1; first + i < last; i++)
7194 : 84 : if (first[i].type == CPP_OPEN_PAREN)
7195 : 18 : paren_depth++;
7196 : 66 : else if (first[i].type == CPP_CLOSE_PAREN)
7197 : 18 : paren_depth--;
7198 : 48 : else if (paren_depth == 0
7199 : 30 : && first + i + 2 < last
7200 : 30 : && first[i].type == CPP_NAME
7201 : 21 : && first[i + 1].type == CPP_OPEN_PAREN
7202 : 21 : && first[i + 2].type == CPP_NAME
7203 : 15 : && !strcmp (IDENTIFIER_POINTER (first[i].value),
7204 : : "at")
7205 : 57 : && !strcmp (IDENTIFIER_POINTER (first[i
7206 : : + 2].value),
7207 : : "execution"))
7208 : : {
7209 : : kind = C_OMP_DIR_STANDALONE;
7210 : : break;
7211 : : }
7212 : : }
7213 : 742 : c_omp_attribute_data v = { toks, dir, kind };
7214 : 742 : vd.safe_push (v);
7215 : 742 : if (flag_openmp || dir->simd)
7216 : 742 : tokens += (last - first) + 1;
7217 : : }
7218 : 603 : c_omp_attribute_data v = {};
7219 : 603 : vd.safe_push (v);
7220 : 603 : *pa = TREE_CHAIN (*pa);
7221 : : }
7222 : : else
7223 : 1 : pa = &TREE_CHAIN (*pa);
7224 : :
7225 : 604 : if (bad)
7226 : : {
7227 : 17 : fail:
7228 : 29 : if (have_std_attrs && attrs == NULL)
7229 : 26 : *have_std_attrs = false;
7230 : 29 : return false;
7231 : : }
7232 : :
7233 : : unsigned int i;
7234 : : c_omp_attribute_data *v;
7235 : : c_omp_attribute_data *construct_seen = nullptr;
7236 : : c_omp_attribute_data *standalone_seen = nullptr;
7237 : : c_omp_attribute_data *prev_standalone_seen = nullptr;
7238 : 1897 : FOR_EACH_VEC_ELT (vd, i, v)
7239 : 1310 : if (v->tokens)
7240 : : {
7241 : 724 : if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
7242 : : construct_seen = v;
7243 : 353 : else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
7244 : 71 : standalone_seen = v;
7245 : : }
7246 : : else
7247 : : {
7248 : 586 : if (standalone_seen && !prev_standalone_seen)
7249 : : {
7250 : 1310 : prev_standalone_seen = standalone_seen;
7251 : 1310 : standalone_seen = nullptr;
7252 : : }
7253 : : }
7254 : :
7255 : 587 : if (cnt > 1 && construct_seen)
7256 : : {
7257 : 4 : error_at ((*construct_seen->tokens)[0].location,
7258 : : "OpenMP construct among %<omp::directive%> attributes"
7259 : : " requires all %<omp::directive%> attributes on the"
7260 : : " same statement to be in the same %<omp::sequence%>");
7261 : 4 : goto fail;
7262 : : }
7263 : 583 : if (cnt > 1 && standalone_seen && prev_standalone_seen)
7264 : : {
7265 : 2 : error_at ((*standalone_seen->tokens)[0].location,
7266 : : "multiple OpenMP standalone directives among"
7267 : : " %<omp::directive%> attributes must be all within the"
7268 : : " same %<omp::sequence%>");
7269 : 2 : goto fail;
7270 : : }
7271 : :
7272 : 581 : if (prev_standalone_seen)
7273 : : standalone_seen = prev_standalone_seen;
7274 : 514 : if (standalone_seen
7275 : 581 : && !c_parser_next_token_is (parser, CPP_SEMICOLON))
7276 : : {
7277 : 2 : error_at (standalone_seen->tokens->address ()->location,
7278 : : "standalone OpenMP directives in %<omp::directive%> attribute"
7279 : : " can only appear on an empty statement");
7280 : 2 : goto fail;
7281 : : }
7282 : 1150 : if (cnt && c_parser_next_token_is (parser, CPP_PRAGMA))
7283 : : {
7284 : 4 : c_token *token = c_parser_peek_token (parser);
7285 : 4 : enum pragma_kind kind = token->pragma_kind;
7286 : 4 : if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
7287 : : {
7288 : 4 : error_at (token->location,
7289 : : "mixing OpenMP directives with attribute and pragma "
7290 : : "syntax on the same statement");
7291 : 4 : goto fail;
7292 : : }
7293 : : }
7294 : :
7295 : 575 : if (!tokens)
7296 : : return false;
7297 : :
7298 : 559 : unsigned int tokens_avail = parser->tokens_avail;
7299 : :
7300 : 559 : tokens++;
7301 : 559 : vec<c_token, va_gc> *toks = NULL;
7302 : 559 : vec_safe_reserve (toks, tokens, true);
7303 : 1825 : FOR_EACH_VEC_ELT (vd, i, v)
7304 : : {
7305 : 1266 : if (!v->tokens)
7306 : 560 : continue;
7307 : 706 : if (!flag_openmp && !v->dir->simd)
7308 : 0 : continue;
7309 : 706 : c_token *first = v->tokens->address ();
7310 : 706 : c_token *last = first + v->tokens->length ();
7311 : 706 : c_token tok = {};
7312 : 706 : tok.type = CPP_PRAGMA;
7313 : 706 : tok.keyword = RID_MAX;
7314 : 706 : tok.pragma_kind = pragma_kind (v->dir->id);
7315 : 706 : tok.location = first->location;
7316 : 706 : toks->quick_push (tok);
7317 : 17418 : while (++first < last)
7318 : 16006 : toks->quick_push (*first);
7319 : 706 : tok = {};
7320 : 706 : tok.type = CPP_PRAGMA_EOL;
7321 : 706 : tok.keyword = RID_MAX;
7322 : 706 : tok.location = last[-1].location;
7323 : 706 : toks->quick_push (tok);
7324 : : }
7325 : :
7326 : 559 : c_token tok = {};
7327 : 559 : tok.type = CPP_EOF;
7328 : 559 : tok.keyword = RID_MAX;
7329 : 559 : tok.location = toks->last ().location;
7330 : 559 : toks->quick_push (tok);
7331 : :
7332 : 559 : gcc_assert (!parser->in_omp_attribute_pragma);
7333 : 559 : parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
7334 : 559 : parser->in_omp_attribute_pragma->token_vec = toks;
7335 : 559 : parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
7336 : 559 : parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
7337 : 559 : parser->tokens = toks->address ();
7338 : 559 : parser->tokens_avail = tokens;
7339 : 559 : return true;
7340 : 604 : }
7341 : :
7342 : : /* Handle omp::directive and omp::sequence attributes in ATTRS
7343 : : (if any) at the start or after declaration-id of a declaration. */
7344 : :
7345 : : static void
7346 : 62271472 : c_parser_handle_directive_omp_attributes (tree &attrs,
7347 : : vec<c_token> *&pragma_clauses,
7348 : : vec<c_token> *attr_clauses)
7349 : : {
7350 : 62271472 : if (!flag_openmp && !flag_openmp_simd)
7351 : : return;
7352 : :
7353 : 1579366 : for (tree *pa = &attrs; *pa; )
7354 : 642298 : if (is_attribute_namespace_p ("omp", *pa)
7355 : 642298 : && is_attribute_p ("directive", get_attribute_name (*pa)))
7356 : : {
7357 : 137 : int cnt = 0;
7358 : 273 : for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
7359 : : {
7360 : 138 : tree a = *pa2;
7361 : 138 : tree d = TREE_VALUE (a);
7362 : 138 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7363 : 138 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7364 : 138 : c_token *first = toks->address ();
7365 : 138 : c_token *last = first + toks->length ();
7366 : 138 : const char *directive[3] = {};
7367 : 416 : for (int i = 0; i < 3; i++)
7368 : : {
7369 : 382 : tree id = NULL_TREE;
7370 : 382 : if (first + i == last)
7371 : : break;
7372 : 328 : if (first[i].type == CPP_NAME)
7373 : 278 : id = first[i].value;
7374 : 50 : else if (first[i].type == CPP_KEYWORD)
7375 : 0 : id = ridpointers[(int) first[i].keyword];
7376 : : else
7377 : : break;
7378 : 278 : directive[i] = IDENTIFIER_POINTER (id);
7379 : : }
7380 : 138 : const c_omp_directive *dir = NULL;
7381 : 138 : if (directive[0])
7382 : 138 : dir = c_omp_categorize_directive (directive[0], directive[1],
7383 : : directive[2]);
7384 : 138 : if (dir == NULL)
7385 : : {
7386 : 9 : error_at (first->location,
7387 : : "unknown OpenMP directive name in "
7388 : : "%qs attribute argument",
7389 : 9 : TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7390 : 9 : *pa2 = TREE_CHAIN (a);
7391 : : }
7392 : 129 : else if (dir->id == PRAGMA_OMP_DECLARE
7393 : 105 : && (strcmp (directive[1], "simd") == 0
7394 : 22 : || strcmp (directive[1], "variant") == 0))
7395 : : {
7396 : 92 : if (pragma_clauses)
7397 : : {
7398 : 2 : error_at (first->location,
7399 : : "mixing OpenMP directives with attribute and "
7400 : : "pragma syntax on the same declaration");
7401 : 6 : for (pa = &attrs; *pa; )
7402 : 2 : if (is_attribute_namespace_p ("omp", *pa)
7403 : 4 : && is_attribute_p ("directive",
7404 : 2 : get_attribute_name (*pa)))
7405 : 2 : *pa = TREE_CHAIN (*pa);
7406 : : else
7407 : 0 : pa = &TREE_CHAIN (*pa);
7408 : 2 : return;
7409 : : }
7410 : 90 : ++cnt;
7411 : 110 : attr_clauses->reserve (attr_clauses->length ()
7412 : 90 : + toks->length () + 2);
7413 : 834 : for (++first; first < last; ++first)
7414 : 744 : attr_clauses->quick_push (*first);
7415 : 90 : c_token tok = {};
7416 : 90 : tok.type = CPP_PRAGMA_EOL;
7417 : 90 : tok.keyword = RID_MAX;
7418 : 90 : tok.location = last[-1].location;
7419 : 90 : attr_clauses->quick_push (tok);
7420 : 90 : *pa2 = TREE_CHAIN (a);
7421 : 90 : }
7422 : : else
7423 : 37 : pa2 = &TREE_CHAIN (a);
7424 : : }
7425 : 135 : if (cnt && TREE_VALUE (*pa) == NULL_TREE)
7426 : 86 : *pa = TREE_CHAIN (*pa);
7427 : : else
7428 : 49 : pa = &TREE_CHAIN (*pa);
7429 : : }
7430 : : else
7431 : 642161 : pa = &TREE_CHAIN (*pa);
7432 : 937068 : if (attr_clauses->length ())
7433 : : {
7434 : 70 : c_token tok = {};
7435 : 70 : tok.type = CPP_EOF;
7436 : 70 : tok.keyword = RID_MAX;
7437 : 70 : tok.location = attr_clauses->last ().location;
7438 : 70 : attr_clauses->quick_push (tok);
7439 : 70 : attr_clauses->quick_push (tok);
7440 : 70 : pragma_clauses = attr_clauses;
7441 : : }
7442 : : }
7443 : :
7444 : : /* Check if STD_ATTR contains a musttail attribute and remove if it
7445 : : precedes a return. PARSER is the parser and ATTR is the output
7446 : : attr_state. */
7447 : :
7448 : : static tree
7449 : 892 : c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
7450 : : {
7451 : 892 : if (c_parser_next_token_is_keyword (parser, RID_RETURN))
7452 : : {
7453 : 153 : if (tree a = lookup_attribute ("gnu", "musttail", std_attrs))
7454 : : {
7455 : 274 : for (; a; a = lookup_attribute ("gnu", "musttail", TREE_CHAIN (a)))
7456 : 138 : if (TREE_VALUE (a))
7457 : 2 : error ("%qs attribute does not take any arguments",
7458 : : "musttail");
7459 : 136 : std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
7460 : 136 : attr.musttail_p = true;
7461 : : }
7462 : 153 : if (lookup_attribute ("clang", "musttail", std_attrs))
7463 : : {
7464 : 10 : std_attrs = remove_attribute ("clang", "musttail", std_attrs);
7465 : 10 : attr.musttail_p = true;
7466 : : }
7467 : : }
7468 : 892 : return std_attrs;
7469 : : }
7470 : :
7471 : : /* Return a statement before optional series of LABEL_EXPR/CASE_LABEL_EXPRs.
7472 : : Instead of collecting vectors of labels before each stmt just in case
7473 : : the statement would be iteration or switch statement for named loops,
7474 : : we just remember last emitted statement and let the iteration/switch
7475 : : statement search backwards in cur_stmt_list until that stmt for loop
7476 : : names if any. */
7477 : :
7478 : : static tree
7479 : 86576222 : get_before_labels ()
7480 : : {
7481 : 86576222 : if (!building_stmt_list_p ())
7482 : 0 : return NULL_TREE;
7483 : 86576222 : tree_stmt_iterator tsi = tsi_last (cur_stmt_list);
7484 : 86576222 : if (tsi_end_p (tsi))
7485 : : return NULL_TREE;
7486 : 47969275 : return tsi_stmt (tsi);
7487 : : }
7488 : :
7489 : : /* Parse a compound statement except for the opening brace. This is
7490 : : used for parsing both compound statements and statement expressions
7491 : : (which follow different paths to handling the opening). */
7492 : :
7493 : : static location_t
7494 : 36268634 : c_parser_compound_statement_nostart (c_parser *parser)
7495 : : {
7496 : 36268634 : bool last_stmt = false;
7497 : 36268634 : bool last_label = false;
7498 : 36268634 : bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
7499 : 36268634 : location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
7500 : 36268634 : struct omp_for_parse_data *omp_for_parse_state
7501 : : = parser->omp_for_parse_state;
7502 : 72537268 : bool in_omp_loop_block
7503 : 36268634 : = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
7504 : 36268634 : tree sl = NULL_TREE;
7505 : 36268634 : attr_state a = {};
7506 : :
7507 : 36268634 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
7508 : : {
7509 : 23536 : location_t endloc = c_parser_peek_token (parser)->location;
7510 : 23536 : add_debug_begin_stmt (endloc);
7511 : 23536 : c_parser_consume_token (parser);
7512 : 23536 : return endloc;
7513 : : }
7514 : :
7515 : : /* If we're parsing a {} sequence in an OMP_FOR body, start a
7516 : : statement list for intervening code. */
7517 : 36245098 : if (in_omp_loop_block)
7518 : 172 : sl = push_stmt_list ();
7519 : :
7520 : 36245098 : mark_valid_location_for_stdc_pragma (true);
7521 : 36245098 : if (c_parser_next_token_is_keyword (parser, RID_LABEL))
7522 : : {
7523 : : /* Read zero or more forward-declarations for labels that nested
7524 : : functions can jump to. */
7525 : 723 : mark_valid_location_for_stdc_pragma (false);
7526 : 723 : if (in_omp_loop_block)
7527 : 5 : check_omp_intervening_code (parser);
7528 : 1567 : while (c_parser_next_token_is_keyword (parser, RID_LABEL))
7529 : : {
7530 : 844 : label_loc = c_parser_peek_token (parser)->location;
7531 : 844 : c_parser_consume_token (parser);
7532 : : /* Any identifiers, including those declared as type names,
7533 : : are OK here. */
7534 : 1518 : while (true)
7535 : : {
7536 : 1181 : tree label;
7537 : 1181 : if (c_parser_next_token_is_not (parser, CPP_NAME))
7538 : : {
7539 : 0 : c_parser_error (parser, "expected identifier");
7540 : 0 : break;
7541 : : }
7542 : 1181 : label
7543 : 1181 : = declare_label (c_parser_peek_token (parser)->value);
7544 : 1181 : C_DECLARED_LABEL_FLAG (label) = 1;
7545 : 1181 : add_stmt (build_stmt (label_loc, DECL_EXPR, label));
7546 : 1181 : c_parser_consume_token (parser);
7547 : 1181 : if (c_parser_next_token_is (parser, CPP_COMMA))
7548 : 337 : c_parser_consume_token (parser);
7549 : : else
7550 : : break;
7551 : 337 : }
7552 : 844 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
7553 : : }
7554 : 723 : pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7555 : : }
7556 : : /* We must now have at least one statement, label or declaration. */
7557 : 36245098 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
7558 : : {
7559 : 0 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7560 : 0 : c_parser_error (parser, "expected declaration or statement");
7561 : 0 : location_t endloc = c_parser_peek_token (parser)->location;
7562 : 0 : c_parser_consume_token (parser);
7563 : 0 : return endloc;
7564 : : }
7565 : 36245098 : tree before_labels = get_before_labels ();
7566 : 121854249 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
7567 : : {
7568 : 49364112 : location_t loc = c_parser_peek_token (parser)->location;
7569 : 49364112 : loc = expansion_point_location_if_in_system_header (loc);
7570 : :
7571 : 98728224 : bool want_nested_loop = (omp_for_parse_state
7572 : 49364112 : ? omp_for_parse_state->want_nested_loop
7573 : : : false);
7574 : :
7575 : : /* First take care of special cases for OpenMP "canonical loop
7576 : : nest form", that do not allow standard attributes, labels, or
7577 : : __extension__ before the nested statement. */
7578 : 49364112 : if (in_omp_loop_block && !last_label)
7579 : : {
7580 : 385 : tree_code code = omp_for_parse_state->code;
7581 : 495 : if (want_nested_loop
7582 : 385 : && c_parser_omp_next_tokens_can_be_canon_loop (parser, code,
7583 : : false))
7584 : : {
7585 : : /* Found the next nested loop. If there were intervening
7586 : : code statements collected before now, wrap them in an
7587 : : OMP_STRUCTURED_BLOCK node, and start a new structured
7588 : : block to hold statements that may come after the FOR. */
7589 : 110 : gcc_assert (sl);
7590 : 110 : add_structured_block_stmt (pop_stmt_list (sl));
7591 : 110 : omp_for_parse_state->depth++;
7592 : 110 : add_stmt (c_parser_omp_loop_nest (parser, NULL));
7593 : 110 : omp_for_parse_state->depth--;
7594 : 110 : sl = push_stmt_list ();
7595 : 110 : parser->error = false;
7596 : 110 : before_labels = get_before_labels ();
7597 : 161 : continue;
7598 : : }
7599 : 275 : else if (want_nested_loop
7600 : 458 : && c_parser_next_token_is (parser, CPP_OPEN_BRACE))
7601 : : {
7602 : : /* If this nested compound statement contains the nested loop,
7603 : : we need to separate the other statements in the current
7604 : : statement into separate blocks of intervening code. If
7605 : : there's no nested loop, it's all part of the same
7606 : : chunk of intervening code. */
7607 : 44 : tree pre_sl = pop_stmt_list (sl);
7608 : 44 : tree nested_sl = push_stmt_list ();
7609 : 44 : mark_valid_location_for_stdc_pragma (false);
7610 : 44 : c_parser_statement_after_labels (parser, NULL, NULL_TREE);
7611 : 44 : nested_sl = pop_stmt_list (nested_sl);
7612 : 44 : if (omp_for_parse_state->want_nested_loop)
7613 : : {
7614 : : /* This block didn't contain a loop-nest, so it's
7615 : : all part of the same chunk of intervening code. */
7616 : 13 : check_omp_intervening_code (parser);
7617 : 13 : sl = push_stmt_list ();
7618 : 13 : add_stmt (pre_sl);
7619 : 13 : add_stmt (nested_sl);
7620 : : }
7621 : : else
7622 : : {
7623 : : /* It contains the nested loop. */
7624 : 31 : add_structured_block_stmt (pre_sl);
7625 : 31 : add_stmt (nested_sl);
7626 : 31 : sl = push_stmt_list ();
7627 : : }
7628 : 44 : parser->error = false;
7629 : 44 : before_labels = get_before_labels ();
7630 : 44 : continue;
7631 : 44 : }
7632 : 231 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
7633 : : {
7634 : : /* Prior to implementing the OpenMP 5.1 syntax for canonical
7635 : : loop form, GCC used to accept an empty statements that
7636 : : would now be flagged as intervening code. Continue to
7637 : : do that, as an extension. */
7638 : : /* FIXME: Maybe issue a warning or something here? */
7639 : 4 : c_parser_consume_token (parser);
7640 : 4 : before_labels = get_before_labels ();
7641 : 4 : continue;
7642 : : }
7643 : : }
7644 : :
7645 : : /* Standard attributes may start a label, statement or declaration. */
7646 : 49363954 : bool have_std_attrs
7647 : 49363954 : = c_parser_nth_token_starts_std_attributes (parser, 1);
7648 : 49363954 : tree std_attrs = NULL_TREE;
7649 : 49363954 : if (have_std_attrs)
7650 : : {
7651 : 798 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7652 : 798 : std_attrs = c_parser_handle_musttail (parser, std_attrs, a);
7653 : : }
7654 : 49363954 : if (c_parser_next_token_is_keyword (parser, RID_CASE)
7655 : 48373204 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
7656 : 97704468 : || (c_parser_next_token_is (parser, CPP_NAME)
7657 : 9854289 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7658 : : {
7659 : 1046142 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
7660 : 990750 : label_loc = c_parser_peek_2nd_token (parser)->location;
7661 : : else
7662 : 55392 : label_loc = c_parser_peek_token (parser)->location;
7663 : 1046142 : last_label = true;
7664 : 1046142 : last_stmt = false;
7665 : 1046142 : mark_valid_location_for_stdc_pragma (false);
7666 : 1046142 : if (in_omp_loop_block)
7667 : 26 : check_omp_intervening_code (parser);
7668 : 1046142 : c_parser_label (parser, std_attrs);
7669 : : }
7670 : 48317812 : else if (c_parser_next_tokens_start_declaration (parser)
7671 : 48317812 : || (have_std_attrs
7672 : 663 : && !c_parser_handle_statement_omp_attributes
7673 : 663 : (parser, std_attrs, &have_std_attrs)
7674 : 229 : && c_parser_next_token_is (parser, CPP_SEMICOLON)
7675 : 69 : && (have_std_attrs = true)))
7676 : : {
7677 : 7465865 : if (last_label)
7678 : 56 : pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wfree_labels,
7679 : : "a label can only be part of a statement and "
7680 : : "a declaration is not a statement");
7681 : : /* It's unlikely we'll see a nested loop in a declaration in
7682 : : intervening code in an OMP loop, but disallow it anyway. */
7683 : 7465865 : if (in_omp_loop_block)
7684 : : {
7685 : 19 : check_omp_intervening_code (parser);
7686 : 19 : omp_for_parse_state->want_nested_loop = false;
7687 : : }
7688 : 7465865 : mark_valid_location_for_stdc_pragma (false);
7689 : 7465865 : bool fallthru_attr_p = false;
7690 : 7465865 : c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
7691 : : true, true, true, false, NULL,
7692 : : NULL, have_std_attrs, std_attrs,
7693 : : NULL, &fallthru_attr_p);
7694 : :
7695 : 7465865 : if (in_omp_loop_block)
7696 : 19 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7697 : 7465865 : if (last_stmt && !fallthru_attr_p)
7698 : 300523 : pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7699 : : "ISO C90 forbids mixed declarations and code");
7700 : 7465865 : last_stmt = fallthru_attr_p;
7701 : 7465865 : last_label = false;
7702 : 7465865 : before_labels = get_before_labels ();
7703 : : }
7704 : 40851947 : else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
7705 : : {
7706 : : /* __extension__ can start a declaration, but is also an
7707 : : unary operator that can start an expression. Consume all
7708 : : but the last of a possible series of __extension__ to
7709 : : determine which. If standard attributes have already
7710 : : been seen, it must start a statement, not a declaration,
7711 : : but standard attributes starting a declaration may appear
7712 : : after __extension__. */
7713 : 1560 : while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7714 : 780 : && (c_parser_peek_2nd_token (parser)->keyword
7715 : : == RID_EXTENSION))
7716 : 0 : c_parser_consume_token (parser);
7717 : 780 : if (!have_std_attrs
7718 : 780 : && (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
7719 : 709 : || c_parser_nth_token_starts_std_attributes (parser, 2)))
7720 : : {
7721 : 74 : int ext;
7722 : 74 : ext = disable_extension_diagnostics ();
7723 : 74 : c_parser_consume_token (parser);
7724 : 74 : last_label = false;
7725 : : /* It's unlikely we'll see a nested loop in a declaration in
7726 : : intervening code in an OMP loop, but disallow it anyway. */
7727 : 74 : if (in_omp_loop_block)
7728 : : {
7729 : 0 : check_omp_intervening_code (parser);
7730 : 0 : omp_for_parse_state->want_nested_loop = false;
7731 : : }
7732 : 74 : mark_valid_location_for_stdc_pragma (false);
7733 : 74 : c_parser_declaration_or_fndef (parser, true, true, true, true,
7734 : : true, false);
7735 : 74 : if (in_omp_loop_block)
7736 : 0 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7737 : : /* Following the old parser, __extension__ does not
7738 : : disable this diagnostic. */
7739 : 74 : restore_extension_diagnostics (ext);
7740 : 74 : if (last_stmt)
7741 : 7 : pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7742 : : "ISO C90 forbids mixed declarations and code");
7743 : 74 : last_stmt = false;
7744 : 74 : before_labels = get_before_labels ();
7745 : : }
7746 : : else
7747 : 706 : goto statement;
7748 : : }
7749 : 40851167 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
7750 : : {
7751 : 327815 : if (have_std_attrs && !parser->in_omp_attribute_pragma)
7752 : 0 : c_parser_error (parser, "expected declaration or statement");
7753 : 327815 : else if (std_attrs)
7754 : 0 : c_warn_unused_attributes (std_attrs);
7755 : : /* External pragmas, and some omp pragmas, are not associated
7756 : : with regular c code, and so are not to be considered statements
7757 : : syntactically. This ensures that the user doesn't put them
7758 : : places that would turn into syntax errors if the directive
7759 : : were ignored. */
7760 : 327815 : if (omp_for_parse_state)
7761 : 9 : omp_for_parse_state->want_nested_loop = false;
7762 : 655550 : if (c_parser_pragma (parser,
7763 : : last_label ? pragma_stmt : pragma_compound,
7764 : : NULL, before_labels))
7765 : : {
7766 : 22454 : last_label = false;
7767 : 22454 : last_stmt = true;
7768 : 22454 : if (omp_for_parse_state)
7769 : 2 : check_omp_intervening_code (parser);
7770 : : }
7771 : 305363 : if (omp_for_parse_state)
7772 : 9 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7773 : 327815 : before_labels = get_before_labels ();
7774 : : }
7775 : 40523352 : else if (c_parser_next_token_is (parser, CPP_EOF))
7776 : : {
7777 : 56 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7778 : 56 : c_parser_error (parser, "expected declaration or statement");
7779 : 58 : return c_parser_peek_token (parser)->location;
7780 : : }
7781 : 40523296 : else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
7782 : : {
7783 : 5 : if (parser->in_if_block)
7784 : : {
7785 : 2 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7786 : 2 : error_at (loc, "expected %<}%> before %<else%>");
7787 : 2 : return c_parser_peek_token (parser)->location;
7788 : : }
7789 : : else
7790 : : {
7791 : 3 : error_at (loc, "%<else%> without a previous %<if%>");
7792 : 3 : c_parser_consume_token (parser);
7793 : 3 : before_labels = get_before_labels ();
7794 : 3 : continue;
7795 : : }
7796 : : }
7797 : : else
7798 : : {
7799 : 40523291 : statement:
7800 : 40523997 : c_warn_unused_attributes (std_attrs);
7801 : 40523997 : last_label = false;
7802 : 40523997 : last_stmt = true;
7803 : 40523997 : mark_valid_location_for_stdc_pragma (false);
7804 : 40523997 : if (!omp_for_parse_state)
7805 : 40523768 : c_parser_statement_after_labels (parser, NULL, before_labels,
7806 : : NULL, a);
7807 : : else
7808 : : {
7809 : : /* In canonical loop nest form, nested loops can only appear
7810 : : directly, or in a directly nested compound statement. We
7811 : : already took care of those cases above, so now we have
7812 : : something else. This statement and everything inside
7813 : : it must be intervening code. */
7814 : 229 : omp_for_parse_state->want_nested_loop = false;
7815 : 229 : check_omp_intervening_code (parser);
7816 : 229 : c_parser_statement_after_labels (parser, NULL, before_labels);
7817 : 229 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7818 : : }
7819 : 40523996 : before_labels = get_before_labels ();
7820 : : }
7821 : :
7822 : 49363892 : parser->error = false;
7823 : : }
7824 : 36245039 : if (last_label)
7825 : 44 : pedwarn_c11 (label_loc, OPT_Wfree_labels,
7826 : : "label at end of compound statement");
7827 : 36245039 : location_t endloc = c_parser_peek_token (parser)->location;
7828 : 36245039 : c_parser_consume_token (parser);
7829 : :
7830 : : /* Restore the value we started with. */
7831 : 36245039 : mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7832 : :
7833 : : /* Package leftover intervening code, or the whole contents of the
7834 : : compound statement if we were looking for a nested loop in an OMP_FOR
7835 : : construct and didn't find one. */
7836 : 36245039 : if (sl)
7837 : : {
7838 : 172 : sl = pop_stmt_list (sl);
7839 : 172 : if (omp_for_parse_state->want_nested_loop)
7840 : 31 : add_stmt (sl);
7841 : : else
7842 : 141 : add_structured_block_stmt (sl);
7843 : : }
7844 : : return endloc;
7845 : : }
7846 : :
7847 : : /* Parse all consecutive labels, possibly preceded by standard
7848 : : attributes. In this context, a statement is required, not a
7849 : : declaration, so attributes must be followed by a statement that is
7850 : : not just a semicolon. Returns an attr_state. */
7851 : :
7852 : : static attr_state
7853 : 2013213 : c_parser_all_labels (c_parser *parser)
7854 : : {
7855 : 2013213 : attr_state attr = {};
7856 : 2013213 : bool have_std_attrs;
7857 : 2013213 : tree std_attrs = NULL;
7858 : 2013213 : if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1)))
7859 : : {
7860 : 70 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7861 : 70 : std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
7862 : : }
7863 : :
7864 : 2014159 : while (c_parser_next_token_is_keyword (parser, RID_CASE)
7865 : 2013673 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
7866 : 4027821 : || (c_parser_next_token_is (parser, CPP_NAME)
7867 : 492390 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7868 : : {
7869 : 946 : c_parser_label (parser, std_attrs);
7870 : 946 : std_attrs = NULL;
7871 : 946 : if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
7872 : : 1)))
7873 : : {
7874 : 3 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7875 : 3 : std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
7876 : : }
7877 : : }
7878 : 2013213 : if (std_attrs
7879 : 2013213 : && (!c_parser_handle_statement_omp_attributes (parser, std_attrs, &have_std_attrs)
7880 : 11 : || std_attrs))
7881 : : {
7882 : 22 : if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
7883 : 0 : c_parser_error (parser, "expected statement");
7884 : 18 : c_warn_unused_attributes (std_attrs);
7885 : : }
7886 : 2013248 : else if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
7887 : 1 : c_parser_error (parser, "expected statement");
7888 : 2013213 : return attr;
7889 : : }
7890 : :
7891 : :
7892 : : /* Information used while parsing an OpenMP metadirective. */
7893 : : struct omp_metadirective_parse_data {
7894 : : /* These fields are used to unique-ify labels when reparsing the
7895 : : code in a metadirective alternative. */
7896 : : vec<tree> * GTY((skip)) body_labels;
7897 : : unsigned int region_num;
7898 : : };
7899 : :
7900 : : /* Helper function for c_parser_label: mangle a metadirective region
7901 : : label NAME. */
7902 : : static tree
7903 : 16 : mangle_metadirective_region_label (c_parser *parser, tree name)
7904 : : {
7905 : 16 : if (parser->omp_metadirective_state->body_labels->contains (name))
7906 : : {
7907 : 16 : const char *old_name = IDENTIFIER_POINTER (name);
7908 : 16 : char *new_name = (char *) XALLOCAVEC (char, strlen (old_name) + 32);
7909 : 16 : sprintf (new_name, "%s_MDR%u", old_name,
7910 : : parser->omp_metadirective_state->region_num);
7911 : 16 : return get_identifier (new_name);
7912 : : }
7913 : 0 : return name;
7914 : : }
7915 : :
7916 : : /* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
7917 : :
7918 : : label:
7919 : : identifier : gnu-attributes[opt]
7920 : : case constant-expression :
7921 : : default :
7922 : :
7923 : : GNU extensions:
7924 : :
7925 : : label:
7926 : : case constant-expression ... constant-expression :
7927 : :
7928 : : The use of gnu-attributes on labels is a GNU extension. The syntax in
7929 : : GNU C accepts any expressions without commas, non-constant
7930 : : expressions being rejected later. Any standard
7931 : : attribute-specifier-sequence before the first label has been parsed
7932 : : in the caller, to distinguish statements from declarations. Any
7933 : : attribute-specifier-sequence after the label is parsed in this
7934 : : function. */
7935 : : static void
7936 : 1047088 : c_parser_label (c_parser *parser, tree std_attrs)
7937 : : {
7938 : 1047088 : location_t loc1 = c_parser_peek_token (parser)->location;
7939 : 1047088 : tree label = NULL_TREE;
7940 : :
7941 : : /* Remember whether this case or a user-defined label is allowed to fall
7942 : : through to. */
7943 : 1047088 : bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
7944 : :
7945 : 1047088 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
7946 : : {
7947 : 991236 : tree exp1, exp2;
7948 : 991236 : c_parser_consume_token (parser);
7949 : 991236 : exp1 = convert_lvalue_to_rvalue (loc1,
7950 : : c_parser_expr_no_commas (parser, NULL),
7951 : : true, true).value;
7952 : 991236 : if (c_parser_next_token_is (parser, CPP_COLON))
7953 : : {
7954 : 990914 : c_parser_consume_token (parser);
7955 : 990914 : label = do_case (loc1, exp1, NULL_TREE, std_attrs);
7956 : : }
7957 : 322 : else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
7958 : : {
7959 : 314 : c_parser_consume_token (parser);
7960 : 314 : exp2 = convert_lvalue_to_rvalue (loc1,
7961 : : c_parser_expr_no_commas (parser,
7962 : : NULL),
7963 : : true, true).value;
7964 : 314 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
7965 : 314 : label = do_case (loc1, exp1, exp2, std_attrs);
7966 : : }
7967 : : else
7968 : 8 : c_parser_error (parser, "expected %<:%> or %<...%>");
7969 : : }
7970 : 55852 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
7971 : : {
7972 : 32701 : c_parser_consume_token (parser);
7973 : 32701 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
7974 : 32701 : label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
7975 : : }
7976 : : else
7977 : : {
7978 : 23151 : tree name = c_parser_peek_token (parser)->value;
7979 : 23151 : tree tlab;
7980 : 23151 : tree attrs;
7981 : 23151 : location_t loc2 = c_parser_peek_token (parser)->location;
7982 : 23151 : gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
7983 : 23151 : c_parser_consume_token (parser);
7984 : 23151 : gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
7985 : 23151 : c_parser_consume_token (parser);
7986 : 23151 : attrs = c_parser_gnu_attributes (parser);
7987 : 23151 : if (parser->omp_metadirective_state)
7988 : 8 : name = mangle_metadirective_region_label (parser, name);
7989 : 23151 : tlab = define_label (loc2, name);
7990 : 23151 : if (tlab)
7991 : : {
7992 : 23123 : decl_attributes (&tlab, attrs, 0);
7993 : 23123 : decl_attributes (&tlab, std_attrs, 0);
7994 : 23123 : label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
7995 : : }
7996 : 23151 : if (attrs
7997 : 23151 : && c_parser_next_tokens_start_declaration (parser))
7998 : 1 : warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
7999 : : " label and declaration appertains to the label");
8000 : : }
8001 : 1047088 : if (label)
8002 : : {
8003 : 1046908 : if (TREE_CODE (label) == LABEL_EXPR)
8004 : 23123 : FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
8005 : : else
8006 : 1023785 : FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
8007 : : }
8008 : 1047088 : }
8009 : :
8010 : : /* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
8011 : :
8012 : : statement:
8013 : : labeled-statement
8014 : : attribute-specifier-sequence[opt] compound-statement
8015 : : expression-statement
8016 : : attribute-specifier-sequence[opt] selection-statement
8017 : : attribute-specifier-sequence[opt] iteration-statement
8018 : : attribute-specifier-sequence[opt] jump-statement
8019 : :
8020 : : labeled-statement:
8021 : : attribute-specifier-sequence[opt] label statement
8022 : :
8023 : : expression-statement:
8024 : : expression[opt] ;
8025 : : attribute-specifier-sequence expression ;
8026 : :
8027 : : selection-statement:
8028 : : if-statement
8029 : : switch-statement
8030 : :
8031 : : iteration-statement:
8032 : : while-statement
8033 : : do-statement
8034 : : for-statement
8035 : :
8036 : : jump-statement:
8037 : : goto identifier ;
8038 : : continue ;
8039 : : break ;
8040 : : return expression[opt] ;
8041 : :
8042 : : GNU extensions:
8043 : :
8044 : : statement:
8045 : : attribute-specifier-sequence[opt] asm-statement
8046 : :
8047 : : jump-statement:
8048 : : goto * expression ;
8049 : :
8050 : : expression-statement:
8051 : : gnu-attributes ;
8052 : :
8053 : : Objective-C:
8054 : :
8055 : : statement:
8056 : : attribute-specifier-sequence[opt] objc-throw-statement
8057 : : attribute-specifier-sequence[opt] objc-try-catch-statement
8058 : : attribute-specifier-sequence[opt] objc-synchronized-statement
8059 : :
8060 : : objc-throw-statement:
8061 : : @throw expression ;
8062 : : @throw ;
8063 : :
8064 : : OpenACC:
8065 : :
8066 : : statement:
8067 : : attribute-specifier-sequence[opt] openacc-construct
8068 : :
8069 : : openacc-construct:
8070 : : parallel-construct
8071 : : kernels-construct
8072 : : data-construct
8073 : : loop-construct
8074 : :
8075 : : parallel-construct:
8076 : : parallel-directive structured-block
8077 : :
8078 : : kernels-construct:
8079 : : kernels-directive structured-block
8080 : :
8081 : : data-construct:
8082 : : data-directive structured-block
8083 : :
8084 : : loop-construct:
8085 : : loop-directive structured-block
8086 : :
8087 : : OpenMP:
8088 : :
8089 : : statement:
8090 : : attribute-specifier-sequence[opt] openmp-construct
8091 : :
8092 : : openmp-construct:
8093 : : parallel-construct
8094 : : for-construct
8095 : : simd-construct
8096 : : for-simd-construct
8097 : : sections-construct
8098 : : single-construct
8099 : : parallel-for-construct
8100 : : parallel-for-simd-construct
8101 : : parallel-sections-construct
8102 : : master-construct
8103 : : critical-construct
8104 : : atomic-construct
8105 : : ordered-construct
8106 : :
8107 : : parallel-construct:
8108 : : parallel-directive structured-block
8109 : :
8110 : : for-construct:
8111 : : for-directive iteration-statement
8112 : :
8113 : : simd-construct:
8114 : : simd-directive iteration-statements
8115 : :
8116 : : for-simd-construct:
8117 : : for-simd-directive iteration-statements
8118 : :
8119 : : sections-construct:
8120 : : sections-directive section-scope
8121 : :
8122 : : single-construct:
8123 : : single-directive structured-block
8124 : :
8125 : : parallel-for-construct:
8126 : : parallel-for-directive iteration-statement
8127 : :
8128 : : parallel-for-simd-construct:
8129 : : parallel-for-simd-directive iteration-statement
8130 : :
8131 : : parallel-sections-construct:
8132 : : parallel-sections-directive section-scope
8133 : :
8134 : : master-construct:
8135 : : master-directive structured-block
8136 : :
8137 : : critical-construct:
8138 : : critical-directive structured-block
8139 : :
8140 : : atomic-construct:
8141 : : atomic-directive expression-statement
8142 : :
8143 : : ordered-construct:
8144 : : ordered-directive structured-block
8145 : :
8146 : : Transactional Memory:
8147 : :
8148 : : statement:
8149 : : attribute-specifier-sequence[opt] transaction-statement
8150 : : attribute-specifier-sequence[opt] transaction-cancel-statement
8151 : :
8152 : : IF_P is used to track whether there's a (possibly labeled) if statement
8153 : : which is not enclosed in braces and has an else clause. This is used to
8154 : : implement -Wparentheses. */
8155 : :
8156 : : static void
8157 : 517904 : c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
8158 : : {
8159 : 517904 : tree before_labels = get_before_labels ();
8160 : 517904 : attr_state a = c_parser_all_labels (parser);
8161 : 517904 : if (loc_after_labels)
8162 : 353313 : *loc_after_labels = c_parser_peek_token (parser)->location;
8163 : 517904 : parser->omp_attrs_forbidden_p = false;
8164 : 517904 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8165 : 517904 : }
8166 : :
8167 : : /* Parse and handle optional identifier after break or continue keywords. */
8168 : :
8169 : : static tree
8170 : 183276 : c_parser_bc_name (c_parser *parser, bool is_break)
8171 : : {
8172 : 183276 : if (!c_parser_next_token_is (parser, CPP_NAME))
8173 : : return NULL_TREE;
8174 : :
8175 : 316 : c_token *tok = c_parser_peek_token (parser);
8176 : 316 : tree label = c_finish_bc_name (tok->location, tok->value, is_break);
8177 : 316 : c_parser_consume_token (parser);
8178 : 316 : return label;
8179 : : }
8180 : :
8181 : : /* Parse a statement, other than a labeled statement. CHAIN is a vector
8182 : : of if-else-if conditions. All labels and standard attributes have
8183 : : been parsed in the caller.
8184 : :
8185 : : IF_P is used to track whether there's a (possibly labeled) if statement
8186 : : which is not enclosed in braces and has an else clause. This is used to
8187 : : implement -Wparentheses. ASTATE is an earlier parsed attribute state.
8188 : :
8189 : : BEFORE_LABELS is last statement before possible labels, see
8190 : : get_before_labels description for details. */
8191 : :
8192 : : static void
8193 : 42089850 : c_parser_statement_after_labels (c_parser *parser, bool *if_p,
8194 : : tree before_labels,
8195 : : vec<tree> *chain, attr_state astate)
8196 : : {
8197 : 42089850 : location_t loc = c_parser_peek_token (parser)->location;
8198 : 42089850 : tree stmt = NULL_TREE;
8199 : 42089850 : bool in_if_block = parser->in_if_block;
8200 : 42089850 : parser->in_if_block = false;
8201 : 42089850 : if (if_p != NULL)
8202 : 800162 : *if_p = false;
8203 : :
8204 : 42089850 : if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
8205 : 41646355 : add_debug_begin_stmt (loc);
8206 : :
8207 : 443495 : restart:
8208 : 42089886 : switch (c_parser_peek_token (parser)->type)
8209 : : {
8210 : 443499 : case CPP_OPEN_BRACE:
8211 : 443499 : add_stmt (c_parser_compound_statement (parser));
8212 : 443499 : break;
8213 : 35900641 : case CPP_KEYWORD:
8214 : 35900641 : switch (c_parser_peek_token (parser)->keyword)
8215 : : {
8216 : 1244539 : case RID_IF:
8217 : 1244539 : c_parser_if_statement (parser, if_p, chain);
8218 : 1244539 : break;
8219 : 36575 : case RID_SWITCH:
8220 : 36575 : c_parser_switch_statement (parser, if_p, before_labels);
8221 : 36575 : break;
8222 : 43552 : case RID_WHILE:
8223 : 43552 : c_parser_while_statement (parser, false, 0, false, if_p, before_labels);
8224 : 43552 : break;
8225 : 144439 : case RID_DO:
8226 : 144439 : c_parser_do_statement (parser, false, 0, false, before_labels);
8227 : 144439 : break;
8228 : 270378 : case RID_FOR:
8229 : 270378 : c_parser_for_statement (parser, false, 0, false, if_p, before_labels);
8230 : 270378 : break;
8231 : 83057 : case RID_GOTO:
8232 : 83057 : c_parser_consume_token (parser);
8233 : 83057 : if (c_parser_next_token_is (parser, CPP_NAME))
8234 : : {
8235 : 82127 : tree name = c_parser_peek_token (parser)->value;
8236 : 82127 : if (parser->omp_metadirective_state)
8237 : 8 : name = mangle_metadirective_region_label (parser, name);
8238 : 82127 : stmt = c_finish_goto_label (loc, name);
8239 : 82127 : c_parser_consume_token (parser);
8240 : : }
8241 : 930 : else if (c_parser_next_token_is (parser, CPP_MULT))
8242 : : {
8243 : 930 : struct c_expr val;
8244 : :
8245 : 930 : c_parser_consume_token (parser);
8246 : 930 : val = c_parser_expression (parser);
8247 : 930 : val = convert_lvalue_to_rvalue (loc, val, false, true);
8248 : 930 : stmt = c_finish_goto_ptr (loc, val);
8249 : : }
8250 : : else
8251 : 0 : c_parser_error (parser, "expected identifier or %<*%>");
8252 : 83057 : goto expect_semicolon;
8253 : 12240 : case RID_CONTINUE:
8254 : 12240 : c_parser_consume_token (parser);
8255 : 12240 : stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false,
8256 : : c_parser_bc_name (parser, false));
8257 : 12240 : goto expect_semicolon;
8258 : 171036 : case RID_BREAK:
8259 : 171036 : c_parser_consume_token (parser);
8260 : 171036 : stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true,
8261 : : c_parser_bc_name (parser, true));
8262 : 171036 : goto expect_semicolon;
8263 : 33675969 : case RID_RETURN:
8264 : 33675969 : c_parser_consume_token (parser);
8265 : 33675969 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8266 : : {
8267 : 41728 : stmt = c_finish_return (loc, NULL_TREE, NULL_TREE,
8268 : 20864 : astate.musttail_p);
8269 : 20864 : c_parser_consume_token (parser);
8270 : : }
8271 : : else
8272 : : {
8273 : 33655105 : location_t xloc = c_parser_peek_token (parser)->location;
8274 : 33655105 : struct c_expr expr = c_parser_expression_conv (parser);
8275 : 33655105 : mark_exp_read (expr.value);
8276 : 34417411 : stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
8277 : : expr.value, expr.original_type,
8278 : 33655105 : astate.musttail_p);
8279 : 33655105 : goto expect_semicolon;
8280 : : }
8281 : 20864 : break;
8282 : 200472 : case RID_ASM:
8283 : 200472 : stmt = c_parser_asm_statement (parser);
8284 : 200472 : break;
8285 : 137 : case RID_TRANSACTION_ATOMIC:
8286 : 137 : case RID_TRANSACTION_RELAXED:
8287 : 274 : stmt = c_parser_transaction (parser,
8288 : 137 : c_parser_peek_token (parser)->keyword);
8289 : 137 : break;
8290 : 28 : case RID_TRANSACTION_CANCEL:
8291 : 28 : stmt = c_parser_transaction_cancel (parser);
8292 : 28 : goto expect_semicolon;
8293 : 0 : case RID_AT_THROW:
8294 : 0 : gcc_assert (c_dialect_objc ());
8295 : 0 : c_parser_consume_token (parser);
8296 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8297 : : {
8298 : 0 : stmt = objc_build_throw_stmt (loc, NULL_TREE);
8299 : 0 : c_parser_consume_token (parser);
8300 : : }
8301 : : else
8302 : : {
8303 : 0 : struct c_expr expr = c_parser_expression (parser);
8304 : 0 : expr = convert_lvalue_to_rvalue (loc, expr, false, false);
8305 : 0 : expr.value = c_fully_fold (expr.value, false, NULL);
8306 : 0 : stmt = objc_build_throw_stmt (loc, expr.value);
8307 : 0 : goto expect_semicolon;
8308 : : }
8309 : 0 : break;
8310 : 0 : case RID_AT_TRY:
8311 : 0 : gcc_assert (c_dialect_objc ());
8312 : 0 : c_parser_objc_try_catch_finally_statement (parser);
8313 : 0 : break;
8314 : 0 : case RID_AT_SYNCHRONIZED:
8315 : 0 : gcc_assert (c_dialect_objc ());
8316 : 0 : c_parser_objc_synchronized_statement (parser);
8317 : 0 : break;
8318 : 9 : case RID_ATTRIBUTE:
8319 : 9 : {
8320 : : /* Allow '__attribute__((fallthrough));' or
8321 : : '__attribute__((assume(cond)));' or
8322 : : '__attribute__((musttail))) return'. */
8323 : 9 : tree attrs = c_parser_gnu_attributes (parser);
8324 : 9 : bool has_assume = lookup_attribute ("assume", attrs);
8325 : 9 : if (has_assume)
8326 : : {
8327 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8328 : 0 : attrs = handle_assume_attribute (loc, attrs, true);
8329 : : else
8330 : : {
8331 : 0 : auto_urlify_attributes sentinel;
8332 : 0 : warning_at (loc, OPT_Wattributes,
8333 : : "%<assume%> attribute not followed by %<;%>");
8334 : 0 : has_assume = false;
8335 : 0 : }
8336 : : }
8337 : 9 : gcc_assert (!astate.musttail_p);
8338 : 9 : attrs = c_parser_handle_musttail (parser, attrs, astate);
8339 : 9 : if (astate.musttail_p)
8340 : : {
8341 : 4 : if (attrs)
8342 : : {
8343 : 1 : auto_urlify_attributes sentinel;
8344 : 1 : warning_at (c_parser_peek_token (parser)->location,
8345 : 1 : OPT_Wattributes,
8346 : : "attribute %<musttail%> mixed with other "
8347 : : "attributes on %<return%> statement");
8348 : 1 : }
8349 : 4 : goto restart;
8350 : : }
8351 : 5 : if (attribute_fallthrough_p (attrs))
8352 : : {
8353 : 5 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8354 : : {
8355 : 5 : tree fn = build_call_expr_internal_loc (loc,
8356 : : IFN_FALLTHROUGH,
8357 : : void_type_node, 0);
8358 : 5 : add_stmt (fn);
8359 : : /* Eat the ';'. */
8360 : 5 : c_parser_consume_token (parser);
8361 : : }
8362 : : else
8363 : : {
8364 : 0 : auto_urlify_attributes sentinel;
8365 : 0 : warning_at (loc, OPT_Wattributes,
8366 : : "%<fallthrough%> attribute not followed "
8367 : : "by %<;%>");
8368 : 0 : }
8369 : : }
8370 : 0 : else if (has_assume)
8371 : : /* Eat the ';'. */
8372 : 0 : c_parser_consume_token (parser);
8373 : 0 : else if (attrs != NULL_TREE)
8374 : : {
8375 : 0 : auto_urlify_attributes sentinel;
8376 : 0 : warning_at (loc, OPT_Wattributes,
8377 : : "only attribute %<fallthrough%> or %<assume%> can "
8378 : : "be applied to a null statement");
8379 : 0 : }
8380 : : break;
8381 : : }
8382 : 18210 : default:
8383 : 18210 : goto expr_stmt;
8384 : : }
8385 : : break;
8386 : 199260 : case CPP_SEMICOLON:
8387 : 199260 : c_parser_consume_token (parser);
8388 : 199260 : break;
8389 : 5 : case CPP_CLOSE_PAREN:
8390 : 5 : case CPP_CLOSE_SQUARE:
8391 : : /* Avoid infinite loop in error recovery:
8392 : : c_parser_skip_until_found stops at a closing nesting
8393 : : delimiter without consuming it, but here we need to consume
8394 : : it to proceed further. */
8395 : 5 : c_parser_error (parser, "expected statement");
8396 : 5 : c_parser_consume_token (parser);
8397 : 5 : break;
8398 : 2697 : case CPP_PRAGMA:
8399 : 2697 : if (!c_parser_pragma (parser, pragma_stmt, if_p, before_labels))
8400 : 32 : goto restart;
8401 : : break;
8402 : 5561994 : default:
8403 : 5561994 : expr_stmt:
8404 : 5561994 : stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
8405 : 39483459 : expect_semicolon:
8406 : 39483459 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
8407 : 39483459 : break;
8408 : : }
8409 : : /* Two cases cannot and do not have line numbers associated: If stmt
8410 : : is degenerate, such as "2;", then stmt is an INTEGER_CST, which
8411 : : cannot hold line numbers. But that's OK because the statement
8412 : : will either be changed to a MODIFY_EXPR during gimplification of
8413 : : the statement expr, or discarded. If stmt was compound, but
8414 : : without new variables, we will have skipped the creation of a
8415 : : BIND and will have a bare STATEMENT_LIST. But that's OK because
8416 : : (recursively) all of the component statements should already have
8417 : : line numbers assigned. ??? Can we discard no-op statements
8418 : : earlier? */
8419 : 42089849 : if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
8420 : 2388219 : protected_set_expr_location (stmt, loc);
8421 : :
8422 : 42089849 : parser->in_if_block = in_if_block;
8423 : 42089849 : }
8424 : :
8425 : : /* Parse the condition from an if, do, while or for statements. */
8426 : :
8427 : : static tree
8428 : 458225 : c_parser_condition (c_parser *parser)
8429 : : {
8430 : 458225 : location_t loc = c_parser_peek_token (parser)->location;
8431 : 458225 : tree cond;
8432 : 458225 : cond = c_parser_expression_conv (parser).value;
8433 : 458225 : cond = c_objc_common_truthvalue_conversion (loc, cond);
8434 : 458225 : cond = c_fully_fold (cond, false, NULL);
8435 : 458225 : if (warn_sequence_point)
8436 : 81379 : verify_sequence_points (cond);
8437 : 458225 : return cond;
8438 : : }
8439 : :
8440 : : /* Parse a parenthesized condition from a do or while statement.
8441 : :
8442 : : condition:
8443 : : ( expression )
8444 : : */
8445 : :
8446 : : static tree
8447 : 188065 : c_parser_paren_condition (c_parser *parser)
8448 : : {
8449 : 188065 : tree cond;
8450 : 188065 : matching_parens parens;
8451 : 188065 : if (!parens.require_open (parser))
8452 : 0 : return error_mark_node;
8453 : 188065 : cond = c_parser_condition (parser);
8454 : 188065 : parens.skip_until_found_close (parser);
8455 : 188065 : return cond;
8456 : : }
8457 : :
8458 : : /* Parse a selection-header:
8459 : :
8460 : : selection-header:
8461 : : expression
8462 : : declaration expression
8463 : : simple-declaration
8464 : :
8465 : : simple-declaration:
8466 : : attribute-specifier-sequence[opt] declaration-specifiers declarator
8467 : : = initializer
8468 : :
8469 : : SWITCH_P is true if we are called from c_parser_switch_statement; in
8470 : : that case, don't perform the truthvalue conversion. */
8471 : :
8472 : : static c_expr
8473 : 1281106 : c_parser_selection_header (c_parser *parser, bool switch_p)
8474 : : {
8475 : 1281106 : location_t loc = c_parser_peek_token (parser)->location;
8476 : 1281106 : c_expr expr;
8477 : 1281106 : bool parse_expr = true;
8478 : 1281106 : tree std_attrs;
8479 : 1281106 : bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
8480 : 1281106 : if (have_std_attrs)
8481 : 20 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8482 : : else
8483 : : std_attrs = NULL_TREE;
8484 : 1281106 : if (c_parser_next_tokens_start_declaration (parser))
8485 : : {
8486 : 239 : pedwarn_c23 (loc, OPT_Wpedantic,
8487 : : "ISO C does not support if declarations before C2Y");
8488 : 239 : expr.value
8489 : 239 : = c_parser_declaration_or_fndef (parser,
8490 : : /*fndef_ok=*/false,
8491 : : /*static_assert_ok=*/false,
8492 : : /*empty_ok=*/false,
8493 : : /*nested=*/true,
8494 : : /*start_attr_ok=*/true,
8495 : : /*simple_ok=*/true,
8496 : : /*objc_foreach_object_decl=*/nullptr,
8497 : : /*omp_declare_simd_clauses=*/nullptr,
8498 : : have_std_attrs,
8499 : : std_attrs);
8500 : 239 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8501 : 99 : c_parser_consume_token (parser);
8502 : : else
8503 : : {
8504 : : /* A simple-declaration is a declaration that can appear in
8505 : : place of the controlling expression of a selection statement.
8506 : : In that case, there shall be an initializer. */
8507 : 140 : if (!expr.value)
8508 : : {
8509 : 48 : error_at (loc, "declaration in the controlling expression must "
8510 : : "have an initializer");
8511 : 48 : expr.original_type = error_mark_node;
8512 : 48 : expr.set_error ();
8513 : 48 : return expr;
8514 : : }
8515 : : parse_expr = false;
8516 : : }
8517 : 191 : if (expr.value)
8518 : : {
8519 : 175 : expr.original_type = TREE_TYPE (expr.value);
8520 : 175 : expr = convert_lvalue_to_rvalue (loc, expr, /*convert_p=*/true,
8521 : : /*read_p=*/true);
8522 : : }
8523 : : }
8524 : 1280867 : else if (have_std_attrs)
8525 : : {
8526 : 8 : c_parser_error (parser, "expected declaration");
8527 : 8 : expr.original_type = error_mark_node;
8528 : 8 : expr.set_error ();
8529 : 8 : return expr;
8530 : : }
8531 : :
8532 : 191 : if (parse_expr)
8533 : 1280958 : expr = c_parser_expression_conv (parser);
8534 : 1281050 : if (!switch_p)
8535 : : {
8536 : 1244510 : expr.value = c_objc_common_truthvalue_conversion (loc, expr.value);
8537 : 1244510 : expr.value = c_fully_fold (expr.value, false, NULL);
8538 : 1244510 : if (warn_sequence_point)
8539 : 244173 : verify_sequence_points (expr.value);
8540 : : }
8541 : : return expr;
8542 : : }
8543 : :
8544 : : /* Parse a selection-header enclosed in parentheses:
8545 : :
8546 : : ( selection-header )
8547 : : */
8548 : :
8549 : : static tree
8550 : 1244539 : c_parser_paren_selection_header (c_parser *parser)
8551 : : {
8552 : 1244539 : matching_parens parens;
8553 : 1244539 : if (!parens.require_open (parser))
8554 : 1 : return error_mark_node;
8555 : 1244538 : tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value;
8556 : 1244538 : parens.skip_until_found_close (parser);
8557 : 1244538 : return cond;
8558 : : }
8559 : :
8560 : : /* Parse a statement which is a block in C99.
8561 : :
8562 : : IF_P is used to track whether there's a (possibly labeled) if statement
8563 : : which is not enclosed in braces and has an else clause. This is used to
8564 : : implement -Wparentheses. */
8565 : :
8566 : : static tree
8567 : 508477 : c_parser_c99_block_statement (c_parser *parser, bool *if_p,
8568 : : location_t *loc_after_labels)
8569 : : {
8570 : 508477 : tree block = c_begin_compound_stmt (flag_isoc99);
8571 : 508477 : location_t loc = c_parser_peek_token (parser)->location;
8572 : 508477 : c_parser_statement (parser, if_p, loc_after_labels);
8573 : 508477 : return c_end_compound_stmt (loc, block, flag_isoc99);
8574 : : }
8575 : :
8576 : : /* Parse the body of an if statement. This is just parsing a
8577 : : statement but (a) it is a block in C99, (b) we track whether the
8578 : : body is an if statement for the sake of -Wparentheses warnings, (c)
8579 : : we handle an empty body specially for the sake of -Wempty-body
8580 : : warnings, and (d) we call parser_compound_statement directly
8581 : : because c_parser_statement_after_labels resets
8582 : : parser->in_if_block.
8583 : :
8584 : : IF_P is used to track whether there's a (possibly labeled) if statement
8585 : : which is not enclosed in braces and has an else clause. This is used to
8586 : : implement -Wparentheses. */
8587 : :
8588 : : static tree
8589 : 1244539 : c_parser_if_body (c_parser *parser, bool *if_p,
8590 : : const token_indent_info &if_tinfo)
8591 : : {
8592 : 1244539 : tree block = c_begin_compound_stmt (flag_isoc99);
8593 : 1244539 : location_t body_loc = c_parser_peek_token (parser)->location;
8594 : 1244539 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8595 : 1244539 : token_indent_info body_tinfo
8596 : 1244539 : = get_token_indent_info (c_parser_peek_token (parser));
8597 : 1244539 : tree before_labels = get_before_labels ();
8598 : 1244539 : attr_state a = c_parser_all_labels (parser);
8599 : :
8600 : 1244539 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8601 : : {
8602 : 5380 : location_t loc = c_parser_peek_token (parser)->location;
8603 : 5380 : add_stmt (build_empty_stmt (loc));
8604 : 5380 : c_parser_consume_token (parser);
8605 : 5380 : if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
8606 : 459 : warning_at (loc, OPT_Wempty_body,
8607 : : "suggest braces around empty body in an %<if%> statement");
8608 : : }
8609 : 1239159 : else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8610 : 442007 : add_stmt (c_parser_compound_statement (parser));
8611 : : else
8612 : : {
8613 : 797152 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8614 : 797152 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8615 : : }
8616 : :
8617 : 1244539 : token_indent_info next_tinfo
8618 : 1244539 : = get_token_indent_info (c_parser_peek_token (parser));
8619 : 1244539 : warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
8620 : 1244539 : if (body_loc_after_labels != UNKNOWN_LOCATION
8621 : 797152 : && next_tinfo.type != CPP_SEMICOLON)
8622 : 792576 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8623 : 792576 : if_tinfo.location, RID_IF);
8624 : :
8625 : 1244539 : return c_end_compound_stmt (body_loc, block, flag_isoc99);
8626 : : }
8627 : :
8628 : : /* Parse the else body of an if statement. This is just parsing a
8629 : : statement but (a) it is a block in C99, (b) we handle an empty body
8630 : : specially for the sake of -Wempty-body warnings. CHAIN is a vector
8631 : : of if-else-if conditions. */
8632 : :
8633 : : static tree
8634 : 250770 : c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
8635 : : vec<tree> *chain)
8636 : : {
8637 : 250770 : location_t body_loc = c_parser_peek_token (parser)->location;
8638 : 250770 : tree block = c_begin_compound_stmt (flag_isoc99);
8639 : 250770 : token_indent_info body_tinfo
8640 : 250770 : = get_token_indent_info (c_parser_peek_token (parser));
8641 : 250770 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8642 : 250770 : tree before_labels = get_before_labels ();
8643 : 250770 : attr_state a = c_parser_all_labels (parser);
8644 : :
8645 : 250770 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8646 : : {
8647 : 29 : location_t loc = c_parser_peek_token (parser)->location;
8648 : 29 : warning_at (loc,
8649 : 29 : OPT_Wempty_body,
8650 : : "suggest braces around empty body in an %<else%> statement");
8651 : 29 : add_stmt (build_empty_stmt (loc));
8652 : 29 : c_parser_consume_token (parser);
8653 : : }
8654 : : else
8655 : : {
8656 : 250741 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8657 : 215202 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8658 : 250741 : c_parser_statement_after_labels (parser, NULL, before_labels, chain, a);
8659 : : }
8660 : :
8661 : 250770 : token_indent_info next_tinfo
8662 : 250770 : = get_token_indent_info (c_parser_peek_token (parser));
8663 : 250770 : warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
8664 : 250770 : if (body_loc_after_labels != UNKNOWN_LOCATION
8665 : 215202 : && next_tinfo.type != CPP_SEMICOLON)
8666 : 215188 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8667 : 215188 : else_tinfo.location, RID_ELSE);
8668 : :
8669 : 250770 : return c_end_compound_stmt (body_loc, block, flag_isoc99);
8670 : : }
8671 : :
8672 : : /* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8673 : :
8674 : : if-statement:
8675 : : if ( selection-header ) statement
8676 : : if ( selection-header ) statement else statement
8677 : :
8678 : : CHAIN is a vector of if-else-if conditions.
8679 : : IF_P is used to track whether there's a (possibly labeled) if statement
8680 : : which is not enclosed in braces and has an else clause. This is used to
8681 : : implement -Wparentheses. */
8682 : :
8683 : : static void
8684 : 1244539 : c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
8685 : : {
8686 : 1244539 : tree block;
8687 : 1244539 : location_t loc;
8688 : 1244539 : tree cond;
8689 : 1244539 : bool nested_if = false;
8690 : 1244539 : tree first_body, second_body;
8691 : 1244539 : bool in_if_block;
8692 : :
8693 : 1244539 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
8694 : 1244539 : token_indent_info if_tinfo
8695 : 1244539 : = get_token_indent_info (c_parser_peek_token (parser));
8696 : 1244539 : c_parser_consume_token (parser);
8697 : 1244539 : block = c_begin_compound_stmt (flag_isoc99);
8698 : 1244539 : loc = c_parser_peek_token (parser)->location;
8699 : 1244539 : cond = c_parser_paren_selection_header (parser);
8700 : 1244539 : in_if_block = parser->in_if_block;
8701 : 1244539 : parser->in_if_block = true;
8702 : 1244539 : first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
8703 : 1244539 : parser->in_if_block = in_if_block;
8704 : :
8705 : 1244539 : if (warn_duplicated_cond)
8706 : 62 : warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
8707 : :
8708 : 1244539 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
8709 : : {
8710 : 250770 : token_indent_info else_tinfo
8711 : 250770 : = get_token_indent_info (c_parser_peek_token (parser));
8712 : 250770 : c_parser_consume_token (parser);
8713 : 250770 : if (warn_duplicated_cond)
8714 : : {
8715 : 43 : if (c_parser_next_token_is_keyword (parser, RID_IF)
8716 : 43 : && chain == NULL)
8717 : : {
8718 : : /* We've got "if (COND) else if (COND2)". Start the
8719 : : condition chain and add COND as the first element. */
8720 : 18 : chain = new vec<tree> ();
8721 : 18 : if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8722 : 12 : chain->safe_push (cond);
8723 : : }
8724 : 25 : else if (!c_parser_next_token_is_keyword (parser, RID_IF))
8725 : : /* This is if-else without subsequent if. Zap the condition
8726 : : chain; we would have already warned at this point. */
8727 : 4 : vec_free (chain);
8728 : : }
8729 : 250770 : second_body = c_parser_else_body (parser, else_tinfo, chain);
8730 : : /* Set IF_P to true to indicate that this if statement has an
8731 : : else clause. This may trigger the Wparentheses warning
8732 : : below when we get back up to the parent if statement. */
8733 : 250770 : if (if_p != NULL)
8734 : 188 : *if_p = true;
8735 : : }
8736 : : else
8737 : : {
8738 : 993769 : second_body = NULL_TREE;
8739 : :
8740 : : /* Diagnose an ambiguous else if if-then-else is nested inside
8741 : : if-then. */
8742 : 993769 : if (nested_if)
8743 : 142 : warning_at (loc, OPT_Wdangling_else,
8744 : : "suggest explicit braces to avoid ambiguous %<else%>");
8745 : :
8746 : 993769 : if (warn_duplicated_cond)
8747 : : /* This if statement does not have an else clause. We don't
8748 : : need the condition chain anymore. */
8749 : 19 : vec_free (chain);
8750 : : }
8751 : 1244539 : c_finish_if_stmt (loc, cond, first_body, second_body);
8752 : 1244539 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8753 : :
8754 : 1244539 : c_parser_maybe_reclassify_token (parser);
8755 : 1244539 : }
8756 : :
8757 : : /* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8758 : :
8759 : : switch-statement:
8760 : : switch (expression) statement
8761 : :
8762 : : BEFORE_LABELS is last statement before possible labels, see
8763 : : get_before_labels description for details. */
8764 : :
8765 : : static void
8766 : 36575 : c_parser_switch_statement (c_parser *parser, bool *if_p, tree before_labels)
8767 : : {
8768 : 36575 : struct c_expr ce;
8769 : 36575 : tree block, expr, body;
8770 : 36575 : unsigned char save_in_statement;
8771 : 36575 : location_t switch_loc = c_parser_peek_token (parser)->location;
8772 : 36575 : location_t switch_cond_loc;
8773 : 36575 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8774 : 36575 : c_parser_consume_token (parser);
8775 : 36575 : tree switch_name;
8776 : 36575 : int num_names = c_get_loop_names (before_labels, true, &switch_name);
8777 : 36575 : block = c_begin_compound_stmt (flag_isoc99);
8778 : 36575 : bool explicit_cast_p = false;
8779 : 36575 : matching_parens parens;
8780 : 36575 : if (parens.require_open (parser))
8781 : : {
8782 : 36568 : switch_cond_loc = c_parser_peek_token (parser)->location;
8783 : 36568 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
8784 : 36568 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
8785 : : explicit_cast_p = true;
8786 : 36568 : ce = c_parser_selection_header (parser, /*switch_p=*/true);
8787 : : /* The call above already performed convert_lvalue_to_rvalue, but
8788 : : if it parsed an expression, read_p was false. Make sure we mark
8789 : : the expression as read. */
8790 : 36568 : ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8791 : 36568 : expr = ce.value;
8792 : : /* ??? expr has no valid location? */
8793 : 36568 : parens.skip_until_found_close (parser);
8794 : : }
8795 : : else
8796 : : {
8797 : 7 : switch_cond_loc = UNKNOWN_LOCATION;
8798 : 7 : expr = error_mark_node;
8799 : 7 : ce.original_type = error_mark_node;
8800 : : }
8801 : 36575 : tree stmt
8802 : 36575 : = c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p,
8803 : : switch_name);
8804 : 36575 : save_in_statement = in_statement;
8805 : 36575 : in_statement |= IN_SWITCH_STMT;
8806 : 36575 : if (switch_name)
8807 : : {
8808 : 124 : C_DECL_LOOP_SWITCH_NAME_VALID (switch_name) = 1;
8809 : 124 : in_statement |= IN_NAMED_STMT;
8810 : : }
8811 : : else
8812 : 36451 : in_statement &= ~IN_NAMED_STMT;
8813 : 36575 : location_t loc_after_labels;
8814 : 36575 : bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8815 : 36575 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
8816 : 36575 : location_t next_loc = c_parser_peek_token (parser)->location;
8817 : 36575 : if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8818 : 367 : warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8819 : : RID_SWITCH);
8820 : 36575 : c_finish_switch (body, ce.original_type);
8821 : 36575 : in_statement = save_in_statement;
8822 : 36575 : if (num_names)
8823 : : {
8824 : 124 : if (!C_DECL_LOOP_SWITCH_NAME_USED (switch_name))
8825 : 112 : SWITCH_STMT_NAME (stmt) = NULL_TREE;
8826 : : else
8827 : 12 : SWITCH_STMT_NO_BREAK_P (stmt) = 0;
8828 : 124 : c_release_loop_names (num_names);
8829 : : }
8830 : 36575 : add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8831 : 36575 : c_parser_maybe_reclassify_token (parser);
8832 : 36575 : }
8833 : :
8834 : : /* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8835 : :
8836 : : while-statement:
8837 : : while (expression) statement
8838 : :
8839 : : IF_P is used to track whether there's a (possibly labeled) if statement
8840 : : which is not enclosed in braces and has an else clause. This is used to
8841 : : implement -Wparentheses.
8842 : :
8843 : : BEFORE_LABELS is last statement before possible labels, see
8844 : : get_before_labels description for details. */
8845 : :
8846 : : static void
8847 : 43567 : c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8848 : : bool novector, bool *if_p, tree before_labels)
8849 : : {
8850 : 43567 : tree block, cond, body;
8851 : 43567 : unsigned char save_in_statement;
8852 : 43567 : location_t loc;
8853 : 43567 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8854 : 43567 : token_indent_info while_tinfo
8855 : 43567 : = get_token_indent_info (c_parser_peek_token (parser));
8856 : 43567 : tree loop_name;
8857 : 43567 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
8858 : :
8859 : 43567 : if (parser->omp_for_parse_state)
8860 : : {
8861 : 1 : error_at (c_parser_peek_token (parser)->location,
8862 : : "loop not permitted in intervening code in OpenMP loop body");
8863 : 1 : parser->omp_for_parse_state->fail = true;
8864 : : }
8865 : :
8866 : 43567 : c_parser_consume_token (parser);
8867 : 43567 : block = c_begin_compound_stmt (flag_isoc99);
8868 : 43567 : loc = c_parser_peek_token (parser)->location;
8869 : 43567 : cond = c_parser_paren_condition (parser);
8870 : 43567 : if (ivdep && cond != error_mark_node)
8871 : 3 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8872 : : build_int_cst (integer_type_node,
8873 : : annot_expr_ivdep_kind),
8874 : : integer_zero_node);
8875 : 43567 : if (unroll && cond != error_mark_node)
8876 : 6 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8877 : : build_int_cst (integer_type_node,
8878 : : annot_expr_unroll_kind),
8879 : 6 : build_int_cst (integer_type_node, unroll));
8880 : 43567 : if (novector && cond != error_mark_node)
8881 : 6 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8882 : : build_int_cst (integer_type_node,
8883 : : annot_expr_no_vector_kind),
8884 : : integer_zero_node);
8885 : 43567 : save_in_statement = in_statement;
8886 : 43567 : in_statement = IN_ITERATION_STMT;
8887 : 43567 : if (loop_name)
8888 : : {
8889 : 135 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
8890 : 135 : in_statement |= IN_NAMED_STMT;
8891 : : }
8892 : :
8893 : 43567 : token_indent_info body_tinfo
8894 : 43567 : = get_token_indent_info (c_parser_peek_token (parser));
8895 : :
8896 : 43567 : location_t loc_after_labels;
8897 : 43567 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
8898 : 43567 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
8899 : 43567 : if (loop_name && !C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8900 : 133 : loop_name = NULL_TREE;
8901 : 43567 : add_stmt (build_stmt (loc, WHILE_STMT, cond, body, loop_name, NULL_TREE,
8902 : : NULL_TREE));
8903 : 43567 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8904 : 43567 : c_parser_maybe_reclassify_token (parser);
8905 : 43567 : if (num_names)
8906 : 135 : c_release_loop_names (num_names);
8907 : :
8908 : 43567 : token_indent_info next_tinfo
8909 : 43567 : = get_token_indent_info (c_parser_peek_token (parser));
8910 : 43567 : warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
8911 : :
8912 : 43567 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8913 : 10442 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8914 : : while_tinfo.location, RID_WHILE);
8915 : :
8916 : 43567 : in_statement = save_in_statement;
8917 : 43567 : }
8918 : :
8919 : : /* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8920 : :
8921 : : do-statement:
8922 : : do statement while ( expression ) ;
8923 : :
8924 : : BEFORE_LABELS is last statement before possible labels, see
8925 : : get_before_labels description for details. */
8926 : :
8927 : : static void
8928 : 144498 : c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8929 : : bool novector, tree before_labels)
8930 : : {
8931 : 144498 : tree block, cond, body;
8932 : 144498 : unsigned char save_in_statement;
8933 : 144498 : location_t loc;
8934 : 144498 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
8935 : 144498 : tree loop_name;
8936 : 144498 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
8937 : :
8938 : 144498 : if (parser->omp_for_parse_state)
8939 : : {
8940 : 1 : error_at (c_parser_peek_token (parser)->location,
8941 : : "loop not permitted in intervening code in OpenMP loop body");
8942 : 1 : parser->omp_for_parse_state->fail = true;
8943 : : }
8944 : :
8945 : 144498 : c_parser_consume_token (parser);
8946 : 144498 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8947 : 50 : warning_at (c_parser_peek_token (parser)->location,
8948 : 50 : OPT_Wempty_body,
8949 : : "suggest braces around empty body in %<do%> statement");
8950 : 144498 : block = c_begin_compound_stmt (flag_isoc99);
8951 : 144498 : loc = c_parser_peek_token (parser)->location;
8952 : 144498 : save_in_statement = in_statement;
8953 : 144498 : in_statement = IN_ITERATION_STMT;
8954 : 144498 : if (loop_name)
8955 : : {
8956 : 178 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
8957 : 178 : in_statement |= IN_NAMED_STMT;
8958 : : }
8959 : 144498 : body = c_parser_c99_block_statement (parser, NULL);
8960 : 144498 : c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
8961 : 144498 : in_statement = save_in_statement;
8962 : 144498 : if (num_names)
8963 : : {
8964 : 178 : if (!C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8965 : 176 : loop_name = NULL_TREE;
8966 : 178 : c_release_loop_names (num_names);
8967 : : }
8968 : 144498 : cond = c_parser_paren_condition (parser);
8969 : 144498 : if (ivdep && cond != error_mark_node)
8970 : 2 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8971 : : build_int_cst (integer_type_node,
8972 : : annot_expr_ivdep_kind),
8973 : : integer_zero_node);
8974 : 144498 : if (unroll && cond != error_mark_node)
8975 : 3 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8976 : : build_int_cst (integer_type_node,
8977 : : annot_expr_unroll_kind),
8978 : 3 : build_int_cst (integer_type_node, unroll));
8979 : 144498 : if (novector && cond != error_mark_node)
8980 : 54 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8981 : : build_int_cst (integer_type_node,
8982 : : annot_expr_no_vector_kind),
8983 : : integer_zero_node);
8984 : 144498 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
8985 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
8986 : :
8987 : 144498 : add_stmt (build_stmt (loc, DO_STMT, cond, body, loop_name));
8988 : 144498 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8989 : 144498 : }
8990 : :
8991 : : /* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8992 : :
8993 : : for-statement:
8994 : : for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
8995 : : for ( nested-declaration expression[opt] ; expression[opt] ) statement
8996 : :
8997 : : The form with a declaration is new in C99.
8998 : :
8999 : : ??? In accordance with the old parser, the declaration may be a
9000 : : nested function, which is then rejected in check_for_loop_decls,
9001 : : but does it make any sense for this to be included in the grammar?
9002 : : Note in particular that the nested function does not include a
9003 : : trailing ';', whereas the "declaration" production includes one.
9004 : : Also, can we reject bad declarations earlier and cheaper than
9005 : : check_for_loop_decls?
9006 : :
9007 : : In Objective-C, there are two additional variants:
9008 : :
9009 : : foreach-statement:
9010 : : for ( expression in expresssion ) statement
9011 : : for ( declaration in expression ) statement
9012 : :
9013 : : This is inconsistent with C, because the second variant is allowed
9014 : : even if c99 is not enabled.
9015 : :
9016 : : The rest of the comment documents these Objective-C foreach-statement.
9017 : :
9018 : : Here is the canonical example of the first variant:
9019 : : for (object in array) { do something with object }
9020 : : we call the first expression ("object") the "object_expression" and
9021 : : the second expression ("array") the "collection_expression".
9022 : : object_expression must be an lvalue of type "id" (a generic Objective-C
9023 : : object) because the loop works by assigning to object_expression the
9024 : : various objects from the collection_expression. collection_expression
9025 : : must evaluate to something of type "id" which responds to the method
9026 : : countByEnumeratingWithState:objects:count:.
9027 : :
9028 : : The canonical example of the second variant is:
9029 : : for (id object in array) { do something with object }
9030 : : which is completely equivalent to
9031 : : {
9032 : : id object;
9033 : : for (object in array) { do something with object }
9034 : : }
9035 : : Note that initizializing 'object' in some way (eg, "for ((object =
9036 : : xxx) in array) { do something with object }") is possibly
9037 : : technically valid, but completely pointless as 'object' will be
9038 : : assigned to something else as soon as the loop starts. We should
9039 : : most likely reject it (TODO).
9040 : :
9041 : : The beginning of the Objective-C foreach-statement looks exactly
9042 : : like the beginning of the for-statement, and we can tell it is a
9043 : : foreach-statement only because the initial declaration or
9044 : : expression is terminated by 'in' instead of ';'.
9045 : :
9046 : : IF_P is used to track whether there's a (possibly labeled) if statement
9047 : : which is not enclosed in braces and has an else clause. This is used to
9048 : : implement -Wparentheses.
9049 : :
9050 : : BEFORE_LABELS is last statement before possible labels, see
9051 : : get_before_labels description for details. */
9052 : :
9053 : : static void
9054 : 273171 : c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9055 : : bool novector, bool *if_p, tree before_labels)
9056 : : {
9057 : 273171 : tree block, cond, incr, body;
9058 : 273171 : unsigned char save_in_statement;
9059 : 273171 : tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
9060 : : /* The following are only used when parsing an ObjC foreach statement. */
9061 : 273171 : tree object_expression;
9062 : : /* Silence the bogus uninitialized warning. */
9063 : 273171 : tree collection_expression = NULL;
9064 : 273171 : location_t loc = c_parser_peek_token (parser)->location;
9065 : 273171 : location_t for_loc = loc;
9066 : 273171 : bool is_foreach_statement = false;
9067 : 273171 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
9068 : 273171 : token_indent_info for_tinfo
9069 : 273171 : = get_token_indent_info (c_parser_peek_token (parser));
9070 : 273171 : tree loop_name;
9071 : 273171 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
9072 : :
9073 : 273171 : if (parser->omp_for_parse_state)
9074 : : {
9075 : 13 : error_at (for_loc,
9076 : : "loop not permitted in intervening code in OpenMP loop body");
9077 : 13 : parser->omp_for_parse_state->fail = true;
9078 : : }
9079 : :
9080 : 273171 : c_parser_consume_token (parser);
9081 : : /* Open a compound statement in Objective-C as well, just in case this is
9082 : : as foreach expression. */
9083 : 545456 : block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
9084 : 273171 : cond = error_mark_node;
9085 : 273171 : incr = error_mark_node;
9086 : 273171 : matching_parens parens;
9087 : 273171 : if (parens.require_open (parser))
9088 : : {
9089 : : /* Parse the initialization declaration or expression. */
9090 : 273170 : object_expression = error_mark_node;
9091 : 273170 : parser->objc_could_be_foreach_context = c_dialect_objc ();
9092 : 273170 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9093 : : {
9094 : 12158 : parser->objc_could_be_foreach_context = false;
9095 : 12158 : c_parser_consume_token (parser);
9096 : 12158 : c_finish_expr_stmt (loc, NULL_TREE);
9097 : : }
9098 : 261012 : else if (c_parser_next_tokens_start_declaration (parser)
9099 : 261012 : || c_parser_nth_token_starts_std_attributes (parser, 1))
9100 : : {
9101 : 19728 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
9102 : : false, &object_expression);
9103 : 19728 : parser->objc_could_be_foreach_context = false;
9104 : :
9105 : 19728 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9106 : : {
9107 : 0 : c_parser_consume_token (parser);
9108 : 0 : is_foreach_statement = true;
9109 : 0 : if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9110 : 0 : c_parser_error (parser, "multiple iterating variables in "
9111 : : "fast enumeration");
9112 : : }
9113 : : else
9114 : 19728 : check_for_loop_decls (for_loc, flag_isoc99);
9115 : : }
9116 : 241284 : else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
9117 : : {
9118 : : /* __extension__ can start a declaration, but is also an
9119 : : unary operator that can start an expression. Consume all
9120 : : but the last of a possible series of __extension__ to
9121 : : determine which. */
9122 : 0 : while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
9123 : 0 : && (c_parser_peek_2nd_token (parser)->keyword
9124 : : == RID_EXTENSION))
9125 : 0 : c_parser_consume_token (parser);
9126 : 0 : if (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
9127 : 0 : || c_parser_nth_token_starts_std_attributes (parser, 2))
9128 : : {
9129 : 0 : int ext;
9130 : 0 : ext = disable_extension_diagnostics ();
9131 : 0 : c_parser_consume_token (parser);
9132 : 0 : c_parser_declaration_or_fndef (parser, true, true, true, true,
9133 : : true, false, &object_expression);
9134 : 0 : parser->objc_could_be_foreach_context = false;
9135 : :
9136 : 0 : restore_extension_diagnostics (ext);
9137 : 0 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9138 : : {
9139 : 0 : c_parser_consume_token (parser);
9140 : 0 : is_foreach_statement = true;
9141 : 0 : if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9142 : 0 : c_parser_error (parser, "multiple iterating variables in "
9143 : : "fast enumeration");
9144 : : }
9145 : : else
9146 : 0 : check_for_loop_decls (for_loc, flag_isoc99);
9147 : : }
9148 : : else
9149 : 0 : goto init_expr;
9150 : : }
9151 : : else
9152 : : {
9153 : 241284 : init_expr:
9154 : 241284 : {
9155 : 241284 : struct c_expr ce;
9156 : 241284 : tree init_expression;
9157 : 241284 : ce = c_parser_expression (parser);
9158 : 241284 : init_expression = ce.value;
9159 : 241284 : parser->objc_could_be_foreach_context = false;
9160 : 241284 : if (c_parser_next_token_is_keyword (parser, RID_IN))
9161 : : {
9162 : 0 : c_parser_consume_token (parser);
9163 : 0 : is_foreach_statement = true;
9164 : 0 : if (! lvalue_p (init_expression))
9165 : 0 : c_parser_error (parser, "invalid iterating variable in "
9166 : : "fast enumeration");
9167 : 0 : object_expression
9168 : 0 : = c_fully_fold (init_expression, false, NULL);
9169 : : }
9170 : : else
9171 : : {
9172 : 241284 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9173 : 241284 : init_expression = ce.value;
9174 : 241284 : c_finish_expr_stmt (loc, init_expression);
9175 : 241284 : c_parser_skip_until_found (parser, CPP_SEMICOLON,
9176 : : "expected %<;%>");
9177 : : }
9178 : : }
9179 : : }
9180 : : /* Parse the loop condition. In the case of a foreach
9181 : : statement, there is no loop condition. */
9182 : 273170 : gcc_assert (!parser->objc_could_be_foreach_context);
9183 : 273170 : if (!is_foreach_statement)
9184 : : {
9185 : 273170 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9186 : : {
9187 : 3010 : if (ivdep)
9188 : : {
9189 : 1 : c_parser_error (parser, "missing loop condition in loop "
9190 : : "with %<GCC ivdep%> pragma");
9191 : 1 : cond = error_mark_node;
9192 : : }
9193 : 3009 : else if (unroll)
9194 : : {
9195 : 0 : c_parser_error (parser, "missing loop condition in loop "
9196 : : "with %<GCC unroll%> pragma");
9197 : 0 : cond = error_mark_node;
9198 : : }
9199 : : else
9200 : : {
9201 : 3009 : c_parser_consume_token (parser);
9202 : 3009 : cond = NULL_TREE;
9203 : : }
9204 : : }
9205 : : else
9206 : : {
9207 : 270160 : cond = c_parser_condition (parser);
9208 : 270160 : c_parser_skip_until_found (parser, CPP_SEMICOLON,
9209 : : "expected %<;%>");
9210 : : }
9211 : 273170 : if (ivdep && cond != error_mark_node)
9212 : 122 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9213 : : build_int_cst (integer_type_node,
9214 : : annot_expr_ivdep_kind),
9215 : : integer_zero_node);
9216 : 273170 : if (unroll && cond != error_mark_node)
9217 : 264 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9218 : : build_int_cst (integer_type_node,
9219 : : annot_expr_unroll_kind),
9220 : 264 : build_int_cst (integer_type_node, unroll));
9221 : 273170 : if (novector && cond && cond != error_mark_node)
9222 : 2417 : cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9223 : : build_int_cst (integer_type_node,
9224 : : annot_expr_no_vector_kind),
9225 : : integer_zero_node);
9226 : : }
9227 : : /* Parse the increment expression (the third expression in a
9228 : : for-statement). In the case of a foreach-statement, this is
9229 : : the expression that follows the 'in'. */
9230 : 273170 : loc = c_parser_peek_token (parser)->location;
9231 : 273170 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9232 : : {
9233 : 4172 : if (is_foreach_statement)
9234 : : {
9235 : 0 : c_parser_error (parser,
9236 : : "missing collection in fast enumeration");
9237 : 0 : collection_expression = error_mark_node;
9238 : : }
9239 : : else
9240 : 4172 : incr = c_process_expr_stmt (loc, NULL_TREE);
9241 : : }
9242 : : else
9243 : : {
9244 : 268998 : if (is_foreach_statement)
9245 : 0 : collection_expression
9246 : 0 : = c_fully_fold (c_parser_expression (parser).value, false, NULL);
9247 : : else
9248 : : {
9249 : 268998 : struct c_expr ce = c_parser_expression (parser);
9250 : 268998 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9251 : 268998 : incr = c_process_expr_stmt (loc, ce.value);
9252 : : }
9253 : : }
9254 : 273170 : parens.skip_until_found_close (parser);
9255 : : }
9256 : 273171 : save_in_statement = in_statement;
9257 : 273171 : if (is_foreach_statement)
9258 : : {
9259 : 0 : in_statement = IN_OBJC_FOREACH;
9260 : 0 : save_objc_foreach_break_label = objc_foreach_break_label;
9261 : 0 : save_objc_foreach_continue_label = objc_foreach_continue_label;
9262 : 0 : objc_foreach_break_label = create_artificial_label (loc);
9263 : 0 : objc_foreach_continue_label = create_artificial_label (loc);
9264 : 0 : if (loop_name)
9265 : : {
9266 : 0 : gcc_checking_assert (!DECL_CHAIN (loop_name)
9267 : : && !DECL_CHAIN (objc_foreach_break_label));
9268 : 0 : C_DECL_SWITCH_NAME (loop_name) = 1;
9269 : 0 : DECL_CHAIN (loop_name) = objc_foreach_break_label;
9270 : 0 : DECL_CHAIN (objc_foreach_break_label) = objc_foreach_continue_label;
9271 : : }
9272 : : }
9273 : : else
9274 : 273171 : in_statement = IN_ITERATION_STMT;
9275 : 273171 : if (loop_name)
9276 : : {
9277 : 452 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9278 : 452 : in_statement |= IN_NAMED_STMT;
9279 : : }
9280 : :
9281 : 273171 : token_indent_info body_tinfo
9282 : 273171 : = get_token_indent_info (c_parser_peek_token (parser));
9283 : :
9284 : 273171 : location_t loc_after_labels;
9285 : 273171 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
9286 : 273171 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
9287 : :
9288 : 273171 : if (loop_name && is_foreach_statement)
9289 : : {
9290 : 0 : gcc_checking_assert (DECL_CHAIN (loop_name) == objc_foreach_break_label
9291 : : && (DECL_CHAIN (objc_foreach_break_label)
9292 : : == objc_foreach_continue_label));
9293 : 0 : C_DECL_SWITCH_NAME (loop_name) = 0;
9294 : 0 : DECL_CHAIN (loop_name) = NULL_TREE;
9295 : 0 : DECL_CHAIN (objc_foreach_break_label) = NULL_TREE;
9296 : : }
9297 : :
9298 : 272719 : if (is_foreach_statement)
9299 : 0 : objc_finish_foreach_loop (for_loc, object_expression,
9300 : : collection_expression, body,
9301 : : objc_foreach_break_label,
9302 : : objc_foreach_continue_label);
9303 : : else
9304 : 546342 : add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
9305 : : body, NULL_TREE,
9306 : 452 : loop_name && C_DECL_LOOP_SWITCH_NAME_USED (loop_name)
9307 : : ? loop_name : NULL_TREE, NULL_TREE, NULL_TREE));
9308 : 273171 : add_stmt (c_end_compound_stmt (for_loc, block,
9309 : 273171 : flag_isoc99 || c_dialect_objc ()));
9310 : 273171 : c_parser_maybe_reclassify_token (parser);
9311 : :
9312 : 273171 : token_indent_info next_tinfo
9313 : 273171 : = get_token_indent_info (c_parser_peek_token (parser));
9314 : 273171 : warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
9315 : :
9316 : 273171 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9317 : 160827 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9318 : : for_tinfo.location, RID_FOR);
9319 : :
9320 : 273171 : in_statement = save_in_statement;
9321 : 273171 : if (num_names)
9322 : 452 : c_release_loop_names (num_names);
9323 : 273171 : if (is_foreach_statement)
9324 : : {
9325 : 0 : objc_foreach_break_label = save_objc_foreach_break_label;
9326 : 0 : objc_foreach_continue_label = save_objc_foreach_continue_label;
9327 : : }
9328 : 273171 : }
9329 : :
9330 : : /* Parse an asm statement, a GNU extension. This is a full-blown asm
9331 : : statement with inputs, outputs, clobbers, and volatile, inline, and goto
9332 : : tags allowed.
9333 : :
9334 : : asm-qualifier:
9335 : : volatile
9336 : : inline
9337 : : goto
9338 : :
9339 : : asm-qualifier-list:
9340 : : asm-qualifier-list asm-qualifier
9341 : : asm-qualifier
9342 : :
9343 : : asm-statement:
9344 : : asm asm-qualifier-list[opt] ( asm-argument ) ;
9345 : :
9346 : : asm-argument:
9347 : : asm-string-literal
9348 : : asm-string-literal : asm-operands[opt]
9349 : : asm-string-literal : asm-operands[opt] : asm-operands[opt]
9350 : : asm-string-literal : asm-operands[opt] : asm-operands[opt] \
9351 : : : asm-clobbers[opt]
9352 : : asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
9353 : : : asm-goto-operands
9354 : :
9355 : : The form with asm-goto-operands is valid if and only if the
9356 : : asm-qualifier-list contains goto, and is the only allowed form in that case.
9357 : : Duplicate asm-qualifiers are not allowed.
9358 : :
9359 : : The :: token is considered equivalent to two consecutive : tokens. */
9360 : :
9361 : : static tree
9362 : 200472 : c_parser_asm_statement (c_parser *parser)
9363 : : {
9364 : 200472 : tree str, outputs, inputs, clobbers, labels, ret;
9365 : 200472 : bool simple;
9366 : 200472 : location_t asm_loc = c_parser_peek_token (parser)->location;
9367 : 200472 : int section, nsections;
9368 : :
9369 : 200472 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
9370 : 200472 : c_parser_consume_token (parser);
9371 : :
9372 : : /* Handle the asm-qualifier-list. */
9373 : 200472 : location_t volatile_loc = UNKNOWN_LOCATION;
9374 : 200472 : location_t inline_loc = UNKNOWN_LOCATION;
9375 : 200472 : location_t goto_loc = UNKNOWN_LOCATION;
9376 : 361819 : for (;;)
9377 : : {
9378 : 361819 : c_token *token = c_parser_peek_token (parser);
9379 : 361819 : location_t loc = token->location;
9380 : 361819 : switch (token->keyword)
9381 : : {
9382 : 160906 : case RID_VOLATILE:
9383 : 160906 : if (volatile_loc)
9384 : : {
9385 : 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9386 : 6 : inform (volatile_loc, "first seen here");
9387 : : }
9388 : : else
9389 : : volatile_loc = loc;
9390 : 160906 : c_parser_consume_token (parser);
9391 : 160906 : continue;
9392 : :
9393 : 38 : case RID_INLINE:
9394 : 38 : if (inline_loc)
9395 : : {
9396 : 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9397 : 6 : inform (inline_loc, "first seen here");
9398 : : }
9399 : : else
9400 : : inline_loc = loc;
9401 : 38 : c_parser_consume_token (parser);
9402 : 38 : continue;
9403 : :
9404 : 401 : case RID_GOTO:
9405 : 401 : if (goto_loc)
9406 : : {
9407 : 6 : error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9408 : 6 : inform (goto_loc, "first seen here");
9409 : : }
9410 : : else
9411 : : goto_loc = loc;
9412 : 401 : c_parser_consume_token (parser);
9413 : 401 : continue;
9414 : :
9415 : 2 : case RID_CONST:
9416 : 2 : case RID_RESTRICT:
9417 : 2 : error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
9418 : 2 : c_parser_consume_token (parser);
9419 : 2 : continue;
9420 : :
9421 : 200472 : default:
9422 : 200472 : break;
9423 : : }
9424 : 200472 : break;
9425 : : }
9426 : :
9427 : 200472 : bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
9428 : 200472 : bool is_inline = (inline_loc != UNKNOWN_LOCATION);
9429 : 200472 : bool is_goto = (goto_loc != UNKNOWN_LOCATION);
9430 : :
9431 : 200472 : ret = NULL;
9432 : :
9433 : 200472 : matching_parens parens;
9434 : 200472 : if (!parens.require_open (parser))
9435 : 0 : goto error;
9436 : :
9437 : 200472 : str = c_parser_asm_string_literal (parser);
9438 : 200472 : if (str == NULL_TREE)
9439 : 12 : goto error_close_paren;
9440 : :
9441 : 200460 : simple = true;
9442 : 200460 : outputs = NULL_TREE;
9443 : 200460 : inputs = NULL_TREE;
9444 : 200460 : clobbers = NULL_TREE;
9445 : 200460 : labels = NULL_TREE;
9446 : :
9447 : 200460 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9448 : 1955 : goto done_asm;
9449 : :
9450 : : /* Parse each colon-delimited section of operands. */
9451 : 198505 : nsections = 3 + is_goto;
9452 : 507926 : for (section = 0; section < nsections; ++section)
9453 : : {
9454 : 507541 : if (c_parser_next_token_is (parser, CPP_SCOPE))
9455 : : {
9456 : 35079 : ++section;
9457 : 35079 : if (section == nsections)
9458 : : {
9459 : 5 : c_parser_error (parser, "expected %<)%>");
9460 : 5 : goto error_close_paren;
9461 : : }
9462 : 35074 : c_parser_consume_token (parser);
9463 : : }
9464 : 943568 : else if (!c_parser_require (parser, CPP_COLON,
9465 : : is_goto
9466 : : ? G_("expected %<:%>")
9467 : : : G_("expected %<:%> or %<)%>"),
9468 : : UNKNOWN_LOCATION, is_goto))
9469 : 7 : goto error_close_paren;
9470 : :
9471 : : /* Once past any colon, we're no longer a simple asm. */
9472 : 507529 : simple = false;
9473 : :
9474 : 507529 : if ((!c_parser_next_token_is (parser, CPP_COLON)
9475 : 411324 : && !c_parser_next_token_is (parser, CPP_SCOPE)
9476 : 411275 : && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9477 : 512399 : || section == 3)
9478 : 406455 : switch (section)
9479 : : {
9480 : 128523 : case 0:
9481 : 128523 : outputs = c_parser_asm_operands (parser);
9482 : 128523 : break;
9483 : 127987 : case 1:
9484 : 127987 : inputs = c_parser_asm_operands (parser);
9485 : 127987 : break;
9486 : 149560 : case 2:
9487 : 149560 : clobbers = c_parser_asm_clobbers (parser);
9488 : 149560 : break;
9489 : 385 : case 3:
9490 : 385 : labels = c_parser_asm_goto_operands (parser);
9491 : 385 : break;
9492 : 0 : default:
9493 : 0 : gcc_unreachable ();
9494 : : }
9495 : :
9496 : 507529 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9497 : 198108 : goto done_asm;
9498 : : }
9499 : :
9500 : 385 : done_asm:
9501 : 200448 : if (!parens.require_close (parser))
9502 : : {
9503 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9504 : 0 : goto error;
9505 : : }
9506 : :
9507 : 200448 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
9508 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
9509 : :
9510 : 200448 : ret = build_asm_stmt (is_volatile,
9511 : : build_asm_expr (asm_loc, str, outputs, inputs,
9512 : : clobbers, labels, simple, is_inline));
9513 : :
9514 : 200472 : error:
9515 : 200472 : return ret;
9516 : :
9517 : 24 : error_close_paren:
9518 : 24 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9519 : 24 : goto error;
9520 : : }
9521 : :
9522 : : /* Parse asm operands, a GNU extension.
9523 : :
9524 : : asm-operands:
9525 : : asm-operand
9526 : : asm-operands , asm-operand
9527 : :
9528 : : asm-operand:
9529 : : asm-string-literal ( expression )
9530 : : [ identifier ] asm-string-literal ( expression )
9531 : : */
9532 : :
9533 : : static tree
9534 : 256543 : c_parser_asm_operands (c_parser *parser)
9535 : : {
9536 : 256543 : tree list = NULL_TREE;
9537 : 1129091 : while (true)
9538 : : {
9539 : 692817 : tree name, str;
9540 : 692817 : struct c_expr expr;
9541 : 692817 : if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
9542 : : {
9543 : 472 : c_parser_consume_token (parser);
9544 : 472 : if (c_parser_next_token_is (parser, CPP_NAME))
9545 : : {
9546 : 472 : tree id = c_parser_peek_token (parser)->value;
9547 : 472 : c_parser_consume_token (parser);
9548 : 472 : name = build_string (IDENTIFIER_LENGTH (id),
9549 : 472 : IDENTIFIER_POINTER (id));
9550 : : }
9551 : : else
9552 : : {
9553 : 0 : c_parser_error (parser, "expected identifier");
9554 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
9555 : 0 : return NULL_TREE;
9556 : : }
9557 : 472 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
9558 : : "expected %<]%>");
9559 : : }
9560 : : else
9561 : : name = NULL_TREE;
9562 : 692817 : str = c_parser_asm_string_literal (parser);
9563 : 692817 : if (str == NULL_TREE)
9564 : : return NULL_TREE;
9565 : 692817 : matching_parens parens;
9566 : 692817 : if (!parens.require_open (parser))
9567 : : return NULL_TREE;
9568 : 692817 : expr = c_parser_expression (parser);
9569 : 692817 : mark_exp_read (expr.value);
9570 : 692817 : if (!parens.require_close (parser))
9571 : : {
9572 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
9573 : 0 : return NULL_TREE;
9574 : : }
9575 : 692817 : list = chainon (list, build_tree_list (build_tree_list (name, str),
9576 : : expr.value));
9577 : 692817 : if (c_parser_next_token_is (parser, CPP_COMMA))
9578 : 436274 : c_parser_consume_token (parser);
9579 : : else
9580 : : break;
9581 : 436274 : }
9582 : 256543 : return list;
9583 : : }
9584 : :
9585 : : /* Parse asm clobbers, a GNU extension.
9586 : :
9587 : : asm-clobbers:
9588 : : asm-string-literal
9589 : : asm-clobbers , asm-string-literal
9590 : : */
9591 : :
9592 : : static tree
9593 : 149560 : c_parser_asm_clobbers (c_parser *parser)
9594 : : {
9595 : 149560 : tree list = NULL_TREE;
9596 : 203498 : while (true)
9597 : : {
9598 : 176529 : tree str = c_parser_asm_string_literal (parser);
9599 : 176529 : if (str)
9600 : 176529 : list = tree_cons (NULL_TREE, str, list);
9601 : : else
9602 : : return NULL_TREE;
9603 : 176529 : if (c_parser_next_token_is (parser, CPP_COMMA))
9604 : 26969 : c_parser_consume_token (parser);
9605 : : else
9606 : : break;
9607 : 26969 : }
9608 : : return list;
9609 : : }
9610 : :
9611 : : /* Parse asm goto labels, a GNU extension.
9612 : :
9613 : : asm-goto-operands:
9614 : : identifier
9615 : : asm-goto-operands , identifier
9616 : : */
9617 : :
9618 : : static tree
9619 : 385 : c_parser_asm_goto_operands (c_parser *parser)
9620 : : {
9621 : 385 : tree list = NULL_TREE;
9622 : 969 : while (true)
9623 : : {
9624 : 677 : tree name, label;
9625 : :
9626 : 677 : if (c_parser_next_token_is (parser, CPP_NAME))
9627 : : {
9628 : 676 : c_token *tok = c_parser_peek_token (parser);
9629 : 676 : name = tok->value;
9630 : 676 : label = lookup_label_for_goto (tok->location, name);
9631 : 676 : c_parser_consume_token (parser);
9632 : 676 : TREE_USED (label) = 1;
9633 : : }
9634 : : else
9635 : : {
9636 : 1 : c_parser_error (parser, "expected identifier");
9637 : 1 : return NULL_TREE;
9638 : : }
9639 : :
9640 : 676 : name = build_string (IDENTIFIER_LENGTH (name),
9641 : 676 : IDENTIFIER_POINTER (name));
9642 : 676 : list = tree_cons (name, label, list);
9643 : 676 : if (c_parser_next_token_is (parser, CPP_COMMA))
9644 : 292 : c_parser_consume_token (parser);
9645 : : else
9646 : 384 : return nreverse (list);
9647 : 292 : }
9648 : : }
9649 : :
9650 : : /* Parse a possibly concatenated sequence of string literals.
9651 : : TRANSLATE says whether to translate them to the execution character
9652 : : set; WIDE_OK says whether any kind of prefixed string literal is
9653 : : permitted in this context. This code is based on that in
9654 : : lex_string. */
9655 : :
9656 : : struct c_expr
9657 : 3719015 : c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
9658 : : {
9659 : 3719015 : struct c_expr ret;
9660 : 3719015 : size_t count;
9661 : 3719015 : struct obstack str_ob;
9662 : 3719015 : struct obstack loc_ob;
9663 : 3719015 : cpp_string str, istr, *strs;
9664 : 3719015 : c_token *tok;
9665 : 3719015 : location_t loc, last_tok_loc;
9666 : 3719015 : enum cpp_ttype type;
9667 : 3719015 : tree value, string_tree;
9668 : :
9669 : 3719015 : tok = c_parser_peek_token (parser);
9670 : 3719015 : loc = tok->location;
9671 : 3719015 : last_tok_loc = linemap_resolve_location (line_table, loc,
9672 : : LRK_MACRO_DEFINITION_LOCATION,
9673 : : NULL);
9674 : 3719015 : type = tok->type;
9675 : 3719015 : switch (type)
9676 : : {
9677 : 3718998 : case CPP_STRING:
9678 : 3718998 : case CPP_WSTRING:
9679 : 3718998 : case CPP_STRING16:
9680 : 3718998 : case CPP_STRING32:
9681 : 3718998 : case CPP_UTF8STRING:
9682 : 3718998 : string_tree = tok->value;
9683 : 3718998 : break;
9684 : :
9685 : 17 : default:
9686 : 17 : c_parser_error (parser, "expected string literal");
9687 : 17 : ret.set_error ();
9688 : 17 : ret.value = NULL_TREE;
9689 : 17 : ret.original_code = ERROR_MARK;
9690 : 17 : ret.original_type = NULL_TREE;
9691 : 17 : return ret;
9692 : : }
9693 : :
9694 : : /* Try to avoid the overhead of creating and destroying an obstack
9695 : : for the common case of just one string. */
9696 : 3718998 : switch (c_parser_peek_2nd_token (parser)->type)
9697 : : {
9698 : 2853506 : default:
9699 : 2853506 : c_parser_consume_token (parser);
9700 : 2853506 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9701 : 2853506 : str.len = TREE_STRING_LENGTH (string_tree);
9702 : 2853506 : count = 1;
9703 : 2853506 : strs = &str;
9704 : 2853506 : break;
9705 : :
9706 : 865492 : case CPP_STRING:
9707 : 865492 : case CPP_WSTRING:
9708 : 865492 : case CPP_STRING16:
9709 : 865492 : case CPP_STRING32:
9710 : 865492 : case CPP_UTF8STRING:
9711 : 865492 : gcc_obstack_init (&str_ob);
9712 : 865492 : gcc_obstack_init (&loc_ob);
9713 : 865492 : count = 0;
9714 : 27841816 : do
9715 : : {
9716 : 27841816 : c_parser_consume_token (parser);
9717 : 27841816 : count++;
9718 : 27841816 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9719 : 27841816 : str.len = TREE_STRING_LENGTH (string_tree);
9720 : 27841816 : if (type != tok->type)
9721 : : {
9722 : 669 : if (type == CPP_STRING)
9723 : 29 : type = tok->type;
9724 : 640 : else if (tok->type != CPP_STRING)
9725 : 66 : error ("unsupported non-standard concatenation "
9726 : : "of string literals");
9727 : : }
9728 : 27841816 : obstack_grow (&str_ob, &str, sizeof (cpp_string));
9729 : 27841816 : obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
9730 : 27841816 : tok = c_parser_peek_token (parser);
9731 : 27841816 : string_tree = tok->value;
9732 : 27841816 : last_tok_loc
9733 : 27841816 : = linemap_resolve_location (line_table, tok->location,
9734 : : LRK_MACRO_DEFINITION_LOCATION, NULL);
9735 : : }
9736 : 27841816 : while (tok->type == CPP_STRING
9737 : : || tok->type == CPP_WSTRING
9738 : : || tok->type == CPP_STRING16
9739 : : || tok->type == CPP_STRING32
9740 : 27841816 : || tok->type == CPP_UTF8STRING);
9741 : 865492 : strs = (cpp_string *) obstack_finish (&str_ob);
9742 : : }
9743 : :
9744 : 3718998 : if (count > 1 && !in_system_header_at (input_location))
9745 : 646536 : warning (OPT_Wtraditional,
9746 : : "traditional C rejects string constant concatenation");
9747 : :
9748 : 3718998 : if ((type == CPP_STRING || wide_ok)
9749 : 7437986 : && ((translate
9750 : 3718988 : ? cpp_interpret_string : cpp_interpret_string_notranslate)
9751 : 3718988 : (parse_in, strs, count, &istr, type)))
9752 : : {
9753 : 3718988 : value = build_string (istr.len, (const char *) istr.text);
9754 : 3718988 : free (CONST_CAST (unsigned char *, istr.text));
9755 : 3718988 : if (count > 1)
9756 : : {
9757 : 865492 : location_t *locs = (location_t *) obstack_finish (&loc_ob);
9758 : 865492 : gcc_assert (g_string_concat_db);
9759 : 865492 : g_string_concat_db->record_string_concatenation (count, locs);
9760 : : }
9761 : : }
9762 : : else
9763 : : {
9764 : 10 : if (type != CPP_STRING && !wide_ok)
9765 : : {
9766 : 10 : error_at (loc, "a wide string is invalid in this context");
9767 : 10 : type = CPP_STRING;
9768 : : }
9769 : : /* Callers cannot generally handle error_mark_node in this
9770 : : context, so return the empty string instead. An error has
9771 : : been issued, either above or from cpp_interpret_string. */
9772 : 10 : switch (type)
9773 : : {
9774 : 10 : default:
9775 : 10 : case CPP_STRING:
9776 : 10 : case CPP_UTF8STRING:
9777 : 10 : if (type == CPP_UTF8STRING && flag_char8_t)
9778 : : {
9779 : 0 : value = build_string (TYPE_PRECISION (char8_type_node)
9780 : 0 : / TYPE_PRECISION (char_type_node),
9781 : : ""); /* char8_t is 8 bits */
9782 : : }
9783 : : else
9784 : 10 : value = build_string (1, "");
9785 : : break;
9786 : 0 : case CPP_STRING16:
9787 : 0 : value = build_string (TYPE_PRECISION (char16_type_node)
9788 : 0 : / TYPE_PRECISION (char_type_node),
9789 : : "\0"); /* char16_t is 16 bits */
9790 : 0 : break;
9791 : 0 : case CPP_STRING32:
9792 : 0 : value = build_string (TYPE_PRECISION (char32_type_node)
9793 : 0 : / TYPE_PRECISION (char_type_node),
9794 : : "\0\0\0"); /* char32_t is 32 bits */
9795 : 0 : break;
9796 : 0 : case CPP_WSTRING:
9797 : 0 : value = build_string (TYPE_PRECISION (wchar_type_node)
9798 : 0 : / TYPE_PRECISION (char_type_node),
9799 : : "\0\0\0"); /* widest supported wchar_t
9800 : : is 32 bits */
9801 : 0 : break;
9802 : : }
9803 : : }
9804 : :
9805 : 3718998 : switch (type)
9806 : : {
9807 : 3715741 : default:
9808 : 3715741 : case CPP_STRING:
9809 : 3715741 : TREE_TYPE (value) = char_array_type_node;
9810 : 3715741 : break;
9811 : 243 : case CPP_UTF8STRING:
9812 : 243 : if (flag_char8_t)
9813 : 63 : TREE_TYPE (value) = char8_array_type_node;
9814 : : else
9815 : 180 : TREE_TYPE (value) = char_array_type_node;
9816 : : break;
9817 : 219 : case CPP_STRING16:
9818 : 219 : TREE_TYPE (value) = char16_array_type_node;
9819 : 219 : break;
9820 : 2282 : case CPP_STRING32:
9821 : 2282 : TREE_TYPE (value) = char32_array_type_node;
9822 : 2282 : break;
9823 : 513 : case CPP_WSTRING:
9824 : 513 : TREE_TYPE (value) = wchar_array_type_node;
9825 : : }
9826 : 3718998 : value = fix_string_type (value);
9827 : :
9828 : 3718998 : if (count > 1)
9829 : : {
9830 : 865492 : obstack_free (&str_ob, 0);
9831 : 865492 : obstack_free (&loc_ob, 0);
9832 : : }
9833 : :
9834 : 3718998 : ret.value = value;
9835 : 3718998 : ret.original_code = STRING_CST;
9836 : 3718998 : ret.original_type = NULL_TREE;
9837 : 3718998 : set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc));
9838 : 3718998 : ret.m_decimal = 0;
9839 : 3718998 : parser->seen_string_literal = true;
9840 : 3718998 : return ret;
9841 : : }
9842 : :
9843 : : /* Parse an expression other than a compound expression; that is, an
9844 : : assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9845 : : AFTER is not NULL then it is an Objective-C message expression which
9846 : : is the primary-expression starting the expression as an initializer.
9847 : :
9848 : : assignment-expression:
9849 : : conditional-expression
9850 : : unary-expression assignment-operator assignment-expression
9851 : :
9852 : : assignment-operator: one of
9853 : : = *= /= %= += -= <<= >>= &= ^= |=
9854 : :
9855 : : In GNU C we accept any conditional expression on the LHS and
9856 : : diagnose the invalid lvalue rather than producing a syntax
9857 : : error. */
9858 : :
9859 : : static struct c_expr
9860 : 222113903 : c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
9861 : : tree omp_atomic_lhs)
9862 : : {
9863 : 222113903 : struct c_expr lhs, rhs, ret;
9864 : 222113903 : enum tree_code code;
9865 : 222113903 : location_t op_location, exp_location;
9866 : 222113903 : bool save_in_omp_for = c_in_omp_for;
9867 : 222113903 : c_in_omp_for = false;
9868 : 222113903 : gcc_assert (!after || c_dialect_objc ());
9869 : 222113903 : lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
9870 : 222113901 : op_location = c_parser_peek_token (parser)->location;
9871 : 222113901 : switch (c_parser_peek_token (parser)->type)
9872 : : {
9873 : : case CPP_EQ:
9874 : : code = NOP_EXPR;
9875 : : break;
9876 : 12042 : case CPP_MULT_EQ:
9877 : 12042 : code = MULT_EXPR;
9878 : 12042 : break;
9879 : 8640 : case CPP_DIV_EQ:
9880 : 8640 : code = TRUNC_DIV_EXPR;
9881 : 8640 : break;
9882 : 2229 : case CPP_MOD_EQ:
9883 : 2229 : code = TRUNC_MOD_EXPR;
9884 : 2229 : break;
9885 : 89307 : case CPP_PLUS_EQ:
9886 : 89307 : code = PLUS_EXPR;
9887 : 89307 : break;
9888 : 28561 : case CPP_MINUS_EQ:
9889 : 28561 : code = MINUS_EXPR;
9890 : 28561 : break;
9891 : 3983 : case CPP_LSHIFT_EQ:
9892 : 3983 : code = LSHIFT_EXPR;
9893 : 3983 : break;
9894 : 16539 : case CPP_RSHIFT_EQ:
9895 : 16539 : code = RSHIFT_EXPR;
9896 : 16539 : break;
9897 : 24470 : case CPP_AND_EQ:
9898 : 24470 : code = BIT_AND_EXPR;
9899 : 24470 : break;
9900 : 3094 : case CPP_XOR_EQ:
9901 : 3094 : code = BIT_XOR_EXPR;
9902 : 3094 : break;
9903 : 19796 : case CPP_OR_EQ:
9904 : 19796 : code = BIT_IOR_EXPR;
9905 : 19796 : break;
9906 : 219293635 : default:
9907 : 219293635 : c_in_omp_for = save_in_omp_for;
9908 : 219293635 : return lhs;
9909 : : }
9910 : 2820266 : c_parser_consume_token (parser);
9911 : 2820266 : exp_location = c_parser_peek_token (parser)->location;
9912 : 2820266 : rhs = c_parser_expr_no_commas (parser, NULL);
9913 : 2820266 : rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
9914 : :
9915 : 2820266 : ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
9916 : : code, exp_location, rhs.value,
9917 : : rhs.original_type);
9918 : 2820266 : ret.m_decimal = 0;
9919 : 2820266 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
9920 : 2820266 : if (code == NOP_EXPR)
9921 : 2611605 : ret.original_code = MODIFY_EXPR;
9922 : : else
9923 : : {
9924 : 208661 : suppress_warning (ret.value, OPT_Wparentheses);
9925 : 208661 : ret.original_code = ERROR_MARK;
9926 : : }
9927 : 2820266 : ret.original_type = NULL;
9928 : 2820266 : c_in_omp_for = save_in_omp_for;
9929 : 2820266 : return ret;
9930 : : }
9931 : :
9932 : : /* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
9933 : : AFTER is not NULL then it is an Objective-C message expression which is
9934 : : the primary-expression starting the expression as an initializer.
9935 : :
9936 : : conditional-expression:
9937 : : logical-OR-expression
9938 : : logical-OR-expression ? expression : conditional-expression
9939 : :
9940 : : GNU extensions:
9941 : :
9942 : : conditional-expression:
9943 : : logical-OR-expression ? : conditional-expression
9944 : : */
9945 : :
9946 : : static struct c_expr
9947 : 222515744 : c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
9948 : : tree omp_atomic_lhs)
9949 : : {
9950 : 222515744 : struct c_expr cond, exp1, exp2, ret;
9951 : 222515744 : location_t start, cond_loc, colon_loc;
9952 : 222515744 : bool save_c_omp_array_section_p = c_omp_array_section_p;
9953 : :
9954 : 222515744 : gcc_assert (!after || c_dialect_objc ());
9955 : :
9956 : 222515744 : cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
9957 : :
9958 : 222515742 : if (c_parser_next_token_is_not (parser, CPP_QUERY))
9959 : 222114088 : return cond;
9960 : 401654 : c_omp_array_section_p = false;
9961 : 401654 : if (cond.value != error_mark_node)
9962 : 401643 : start = cond.get_start ();
9963 : : else
9964 : : start = UNKNOWN_LOCATION;
9965 : 401654 : cond_loc = c_parser_peek_token (parser)->location;
9966 : 401654 : cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
9967 : 401654 : c_parser_consume_token (parser);
9968 : 401654 : if (c_parser_next_token_is (parser, CPP_COLON))
9969 : : {
9970 : 741 : tree eptype = NULL_TREE;
9971 : :
9972 : 741 : location_t middle_loc = c_parser_peek_token (parser)->location;
9973 : 741 : pedwarn (middle_loc, OPT_Wpedantic,
9974 : : "ISO C forbids omitting the middle term of a %<?:%> expression");
9975 : 741 : if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
9976 : : {
9977 : 1 : eptype = TREE_TYPE (cond.value);
9978 : 1 : cond.value = TREE_OPERAND (cond.value, 0);
9979 : : }
9980 : 741 : tree e = cond.value;
9981 : 744 : while (TREE_CODE (e) == COMPOUND_EXPR)
9982 : 3 : e = TREE_OPERAND (e, 1);
9983 : 741 : warn_for_omitted_condop (middle_loc, e);
9984 : : /* Make sure first operand is calculated only once. */
9985 : 741 : exp1.value = save_expr (default_conversion (cond.value));
9986 : 741 : if (eptype)
9987 : 1 : exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
9988 : 741 : exp1.original_type = NULL;
9989 : 741 : exp1.src_range = cond.src_range;
9990 : 741 : cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
9991 : 741 : c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
9992 : : }
9993 : : else
9994 : : {
9995 : 400913 : cond.value
9996 : 400913 : = c_objc_common_truthvalue_conversion
9997 : 400913 : (cond_loc, default_conversion (cond.value));
9998 : 400913 : c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
9999 : 400913 : exp1 = c_parser_expression_conv (parser);
10000 : 400913 : mark_exp_read (exp1.value);
10001 : 400913 : c_inhibit_evaluation_warnings +=
10002 : 400913 : ((cond.value == truthvalue_true_node)
10003 : 400913 : - (cond.value == truthvalue_false_node));
10004 : : }
10005 : :
10006 : 401654 : colon_loc = c_parser_peek_token (parser)->location;
10007 : 401654 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
10008 : : {
10009 : 9 : c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10010 : 9 : ret.set_error ();
10011 : 9 : ret.original_code = ERROR_MARK;
10012 : 9 : ret.original_type = NULL;
10013 : 9 : c_omp_array_section_p = save_c_omp_array_section_p;
10014 : 9 : return ret;
10015 : : }
10016 : 401645 : {
10017 : 401645 : location_t exp2_loc = c_parser_peek_token (parser)->location;
10018 : 401645 : exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
10019 : 401645 : exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
10020 : : }
10021 : 401645 : c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10022 : 401645 : location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
10023 : 401645 : location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
10024 : 401645 : if (UNLIKELY (omp_atomic_lhs != NULL)
10025 : 69 : && (TREE_CODE (cond.value) == GT_EXPR
10026 : : || TREE_CODE (cond.value) == LT_EXPR
10027 : : || TREE_CODE (cond.value) == EQ_EXPR)
10028 : 63 : && c_tree_equal (exp2.value, omp_atomic_lhs)
10029 : 401703 : && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
10030 : 19 : || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
10031 : 55 : ret.value = build3_loc (colon_loc, COND_EXPR, TREE_TYPE (omp_atomic_lhs),
10032 : : cond.value, exp1.value, exp2.value);
10033 : : else
10034 : 401590 : ret.value
10035 : 401590 : = build_conditional_expr (colon_loc, cond.value,
10036 : 401590 : cond.original_code == C_MAYBE_CONST_EXPR,
10037 : : exp1.value, exp1.original_type, loc1,
10038 : : exp2.value, exp2.original_type, loc2);
10039 : 401645 : ret.original_code = ERROR_MARK;
10040 : 401645 : if (exp1.value == error_mark_node || exp2.value == error_mark_node)
10041 : 15 : ret.original_type = NULL;
10042 : : else
10043 : : {
10044 : 401630 : tree t1, t2;
10045 : :
10046 : : /* If both sides are enum type, the default conversion will have
10047 : : made the type of the result be an integer type. We want to
10048 : : remember the enum types we started with. */
10049 : 401630 : t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
10050 : 401630 : t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
10051 : 401630 : ret.original_type = ((t1 != error_mark_node
10052 : 401630 : && t2 != error_mark_node
10053 : 401630 : && (TYPE_MAIN_VARIANT (t1)
10054 : 401630 : == TYPE_MAIN_VARIANT (t2)))
10055 : 401630 : ? t1
10056 : : : NULL);
10057 : : }
10058 : 401645 : set_c_expr_source_range (&ret, start, exp2.get_finish ());
10059 : 401645 : ret.m_decimal = 0;
10060 : 401645 : c_omp_array_section_p = save_c_omp_array_section_p;
10061 : 401645 : return ret;
10062 : : }
10063 : :
10064 : : /* Parse a binary expression; that is, a logical-OR-expression (C90
10065 : : 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
10066 : : NULL then it is an Objective-C message expression which is the
10067 : : primary-expression starting the expression as an initializer.
10068 : :
10069 : : OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
10070 : : when it should be the unfolded lhs. In a valid OpenMP source,
10071 : : one of the operands of the toplevel binary expression must be equal
10072 : : to it. In that case, just return a build2 created binary operation
10073 : : rather than result of parser_build_binary_op.
10074 : :
10075 : : multiplicative-expression:
10076 : : cast-expression
10077 : : multiplicative-expression * cast-expression
10078 : : multiplicative-expression / cast-expression
10079 : : multiplicative-expression % cast-expression
10080 : :
10081 : : additive-expression:
10082 : : multiplicative-expression
10083 : : additive-expression + multiplicative-expression
10084 : : additive-expression - multiplicative-expression
10085 : :
10086 : : shift-expression:
10087 : : additive-expression
10088 : : shift-expression << additive-expression
10089 : : shift-expression >> additive-expression
10090 : :
10091 : : relational-expression:
10092 : : shift-expression
10093 : : relational-expression < shift-expression
10094 : : relational-expression > shift-expression
10095 : : relational-expression <= shift-expression
10096 : : relational-expression >= shift-expression
10097 : :
10098 : : equality-expression:
10099 : : relational-expression
10100 : : equality-expression == relational-expression
10101 : : equality-expression != relational-expression
10102 : :
10103 : : AND-expression:
10104 : : equality-expression
10105 : : AND-expression & equality-expression
10106 : :
10107 : : exclusive-OR-expression:
10108 : : AND-expression
10109 : : exclusive-OR-expression ^ AND-expression
10110 : :
10111 : : inclusive-OR-expression:
10112 : : exclusive-OR-expression
10113 : : inclusive-OR-expression | exclusive-OR-expression
10114 : :
10115 : : logical-AND-expression:
10116 : : inclusive-OR-expression
10117 : : logical-AND-expression && inclusive-OR-expression
10118 : :
10119 : : logical-OR-expression:
10120 : : logical-AND-expression
10121 : : logical-OR-expression || logical-AND-expression
10122 : : */
10123 : :
10124 : : static struct c_expr
10125 : 222532181 : c_parser_binary_expression (c_parser *parser, struct c_expr *after,
10126 : : tree omp_atomic_lhs)
10127 : : {
10128 : : /* A binary expression is parsed using operator-precedence parsing,
10129 : : with the operands being cast expressions. All the binary
10130 : : operators are left-associative. Thus a binary expression is of
10131 : : form:
10132 : :
10133 : : E0 op1 E1 op2 E2 ...
10134 : :
10135 : : which we represent on a stack. On the stack, the precedence
10136 : : levels are strictly increasing. When a new operator is
10137 : : encountered of higher precedence than that at the top of the
10138 : : stack, it is pushed; its LHS is the top expression, and its RHS
10139 : : is everything parsed until it is popped. When a new operator is
10140 : : encountered with precedence less than or equal to that at the top
10141 : : of the stack, triples E[i-1] op[i] E[i] are popped and replaced
10142 : : by the result of the operation until the operator at the top of
10143 : : the stack has lower precedence than the new operator or there is
10144 : : only one element on the stack; then the top expression is the LHS
10145 : : of the new operator. In the case of logical AND and OR
10146 : : expressions, we also need to adjust c_inhibit_evaluation_warnings
10147 : : as appropriate when the operators are pushed and popped. */
10148 : :
10149 : 222532181 : struct {
10150 : : /* The expression at this stack level. */
10151 : : struct c_expr expr;
10152 : : /* The precedence of the operator on its left, PREC_NONE at the
10153 : : bottom of the stack. */
10154 : : enum c_parser_prec prec;
10155 : : /* The operation on its left. */
10156 : : enum tree_code op;
10157 : : /* The source location of this operation. */
10158 : : location_t loc;
10159 : : /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
10160 : : tree sizeof_arg;
10161 : : } stack[NUM_PRECS];
10162 : 222532181 : int sp;
10163 : : /* Location of the binary operator. */
10164 : 222532181 : location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
10165 : : #define POP \
10166 : : do { \
10167 : : switch (stack[sp].op) \
10168 : : { \
10169 : : case TRUTH_ANDIF_EXPR: \
10170 : : c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10171 : : == truthvalue_false_node); \
10172 : : break; \
10173 : : case TRUTH_ORIF_EXPR: \
10174 : : c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10175 : : == truthvalue_true_node); \
10176 : : break; \
10177 : : case TRUNC_DIV_EXPR: \
10178 : : if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
10179 : : || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
10180 : : && (stack[sp].expr.original_code == SIZEOF_EXPR \
10181 : : || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
10182 : : { \
10183 : : tree type0 = stack[sp - 1].sizeof_arg; \
10184 : : tree type1 = stack[sp].sizeof_arg; \
10185 : : tree first_arg = type0; \
10186 : : if (!TYPE_P (type0)) \
10187 : : type0 = TREE_TYPE (type0); \
10188 : : if (!TYPE_P (type1)) \
10189 : : type1 = TREE_TYPE (type1); \
10190 : : if (POINTER_TYPE_P (type0) \
10191 : : && comptypes (TREE_TYPE (type0), type1) \
10192 : : && !(TREE_CODE (first_arg) == PARM_DECL \
10193 : : && C_ARRAY_PARAMETER (first_arg) \
10194 : : && warn_sizeof_array_argument)) \
10195 : : { \
10196 : : auto_diagnostic_group d; \
10197 : : if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
10198 : : "division %<sizeof (%T) / sizeof (%T)%> " \
10199 : : "does not compute the number of array " \
10200 : : "elements", \
10201 : : type0, type1)) \
10202 : : if (DECL_P (first_arg)) \
10203 : : inform (DECL_SOURCE_LOCATION (first_arg), \
10204 : : "first %<sizeof%> operand was declared here"); \
10205 : : } \
10206 : : else if (TREE_CODE (type0) == ARRAY_TYPE \
10207 : : && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
10208 : : && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
10209 : : maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
10210 : : stack[sp].sizeof_arg, type1); \
10211 : : } \
10212 : : break; \
10213 : : default: \
10214 : : break; \
10215 : : } \
10216 : : stack[sp - 1].expr \
10217 : : = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
10218 : : stack[sp - 1].expr, true, true); \
10219 : : stack[sp].expr \
10220 : : = convert_lvalue_to_rvalue (stack[sp].loc, \
10221 : : stack[sp].expr, true, true); \
10222 : : if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
10223 : : && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
10224 : : && ((1 << stack[sp].prec) \
10225 : : & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
10226 : : | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
10227 : : | (1 << PREC_ADD) | (1 << PREC_MULT) \
10228 : : | (1 << PREC_EQ)))) \
10229 : : || ((c_parser_next_token_is (parser, CPP_QUERY) \
10230 : : || (omp_atomic_lhs == void_list_node \
10231 : : && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
10232 : : && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
10233 : : && stack[sp].op != TRUNC_MOD_EXPR \
10234 : : && stack[sp].op != GE_EXPR \
10235 : : && stack[sp].op != LE_EXPR \
10236 : : && stack[sp].op != NE_EXPR \
10237 : : && stack[0].expr.value != error_mark_node \
10238 : : && stack[1].expr.value != error_mark_node \
10239 : : && (omp_atomic_lhs == void_list_node \
10240 : : || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
10241 : : || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
10242 : : || (stack[sp].op == EQ_EXPR \
10243 : : && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
10244 : : { \
10245 : : tree t = make_node (stack[1].op); \
10246 : : TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
10247 : : TREE_OPERAND (t, 0) = stack[0].expr.value; \
10248 : : TREE_OPERAND (t, 1) = stack[1].expr.value; \
10249 : : stack[0].expr.value = t; \
10250 : : stack[0].expr.m_decimal = 0; \
10251 : : } \
10252 : : else \
10253 : : stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
10254 : : stack[sp].op, \
10255 : : stack[sp - 1].expr, \
10256 : : stack[sp].expr); \
10257 : : sp--; \
10258 : : } while (0)
10259 : 222532181 : gcc_assert (!after || c_dialect_objc ());
10260 : 222532181 : stack[0].loc = c_parser_peek_token (parser)->location;
10261 : 222532181 : stack[0].expr = c_parser_cast_expression (parser, after);
10262 : 222532181 : stack[0].prec = PREC_NONE;
10263 : 222532181 : stack[0].sizeof_arg = c_last_sizeof_arg;
10264 : 222532181 : sp = 0;
10265 : 240807599 : while (true)
10266 : : {
10267 : 231669890 : enum c_parser_prec oprec;
10268 : 231669890 : enum tree_code ocode;
10269 : 231669890 : source_range src_range;
10270 : 231669890 : if (parser->error)
10271 : 1070 : goto out;
10272 : 231668820 : switch (c_parser_peek_token (parser)->type)
10273 : : {
10274 : : case CPP_MULT:
10275 : : oprec = PREC_MULT;
10276 : : ocode = MULT_EXPR;
10277 : : break;
10278 : 254033 : case CPP_DIV:
10279 : 254033 : oprec = PREC_MULT;
10280 : 254033 : ocode = TRUNC_DIV_EXPR;
10281 : 254033 : break;
10282 : 54187 : case CPP_MOD:
10283 : 54187 : oprec = PREC_MULT;
10284 : 54187 : ocode = TRUNC_MOD_EXPR;
10285 : 54187 : break;
10286 : 1810088 : case CPP_PLUS:
10287 : 1810088 : oprec = PREC_ADD;
10288 : 1810088 : ocode = PLUS_EXPR;
10289 : 1810088 : break;
10290 : 739958 : case CPP_MINUS:
10291 : 739958 : oprec = PREC_ADD;
10292 : 739958 : ocode = MINUS_EXPR;
10293 : 739958 : break;
10294 : 778647 : case CPP_LSHIFT:
10295 : 778647 : oprec = PREC_SHIFT;
10296 : 778647 : ocode = LSHIFT_EXPR;
10297 : 778647 : break;
10298 : 209607 : case CPP_RSHIFT:
10299 : 209607 : oprec = PREC_SHIFT;
10300 : 209607 : ocode = RSHIFT_EXPR;
10301 : 209607 : break;
10302 : 453989 : case CPP_LESS:
10303 : 453989 : oprec = PREC_REL;
10304 : 453989 : ocode = LT_EXPR;
10305 : 453989 : break;
10306 : 189643 : case CPP_GREATER:
10307 : 189643 : oprec = PREC_REL;
10308 : 189643 : ocode = GT_EXPR;
10309 : 189643 : break;
10310 : 162621 : case CPP_LESS_EQ:
10311 : 162621 : oprec = PREC_REL;
10312 : 162621 : ocode = LE_EXPR;
10313 : 162621 : break;
10314 : 165455 : case CPP_GREATER_EQ:
10315 : 165455 : oprec = PREC_REL;
10316 : 165455 : ocode = GE_EXPR;
10317 : 165455 : break;
10318 : 385483 : case CPP_EQ_EQ:
10319 : 385483 : oprec = PREC_EQ;
10320 : 385483 : ocode = EQ_EXPR;
10321 : 385483 : break;
10322 : 760668 : case CPP_NOT_EQ:
10323 : 760668 : oprec = PREC_EQ;
10324 : 760668 : ocode = NE_EXPR;
10325 : 760668 : break;
10326 : 576548 : case CPP_AND:
10327 : 576548 : oprec = PREC_BITAND;
10328 : 576548 : ocode = BIT_AND_EXPR;
10329 : 576548 : break;
10330 : 74994 : case CPP_XOR:
10331 : 74994 : oprec = PREC_BITXOR;
10332 : 74994 : ocode = BIT_XOR_EXPR;
10333 : 74994 : break;
10334 : 840264 : case CPP_OR:
10335 : 840264 : oprec = PREC_BITOR;
10336 : 840264 : ocode = BIT_IOR_EXPR;
10337 : 840264 : break;
10338 : 181127 : case CPP_AND_AND:
10339 : 181127 : oprec = PREC_LOGAND;
10340 : 181127 : ocode = TRUTH_ANDIF_EXPR;
10341 : 181127 : break;
10342 : 320080 : case CPP_OR_OR:
10343 : 320080 : oprec = PREC_LOGOR;
10344 : 320080 : ocode = TRUTH_ORIF_EXPR;
10345 : 320080 : break;
10346 : 222531111 : default:
10347 : : /* Not a binary operator, so end of the binary
10348 : : expression. */
10349 : 222531111 : goto out;
10350 : : }
10351 : 9137709 : binary_loc = c_parser_peek_token (parser)->location;
10352 : 9137709 : while (oprec <= stack[sp].prec)
10353 : 10571768 : POP;
10354 : 9137709 : c_parser_consume_token (parser);
10355 : 9137709 : switch (ocode)
10356 : : {
10357 : 181127 : case TRUTH_ANDIF_EXPR:
10358 : 181127 : src_range = stack[sp].expr.src_range;
10359 : 181127 : stack[sp].expr
10360 : 181127 : = convert_lvalue_to_rvalue (stack[sp].loc,
10361 : : stack[sp].expr, true, true);
10362 : 362254 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10363 : 181127 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10364 : 181127 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10365 : 181127 : == truthvalue_false_node);
10366 : 181127 : set_c_expr_source_range (&stack[sp].expr, src_range);
10367 : 181127 : break;
10368 : 320080 : case TRUTH_ORIF_EXPR:
10369 : 320080 : src_range = stack[sp].expr.src_range;
10370 : 320080 : stack[sp].expr
10371 : 320080 : = convert_lvalue_to_rvalue (stack[sp].loc,
10372 : : stack[sp].expr, true, true);
10373 : 640160 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10374 : 320080 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10375 : 320080 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10376 : 320080 : == truthvalue_true_node);
10377 : 320080 : set_c_expr_source_range (&stack[sp].expr, src_range);
10378 : 320080 : break;
10379 : : default:
10380 : : break;
10381 : : }
10382 : 9137709 : sp++;
10383 : 9137709 : stack[sp].loc = binary_loc;
10384 : 9137709 : stack[sp].expr = c_parser_cast_expression (parser, NULL);
10385 : 9137709 : stack[sp].prec = oprec;
10386 : 9137709 : stack[sp].op = ocode;
10387 : 9137709 : stack[sp].sizeof_arg = c_last_sizeof_arg;
10388 : 9137709 : }
10389 : 222532181 : out:
10390 : 222532181 : while (sp > 0)
10391 : 230236552 : POP;
10392 : 222532179 : return stack[0].expr;
10393 : : #undef POP
10394 : : }
10395 : :
10396 : : /* Parse any storage class specifiers after an open parenthesis in a
10397 : : context where a compound literal is permitted. */
10398 : :
10399 : : static struct c_declspecs *
10400 : 118232796 : c_parser_compound_literal_scspecs (c_parser *parser)
10401 : : {
10402 : 118232796 : bool seen_scspec = false;
10403 : 118232796 : struct c_declspecs *specs = build_null_declspecs ();
10404 : 236465914 : while (c_parser_next_token_is (parser, CPP_KEYWORD))
10405 : : {
10406 : 4143468 : switch (c_parser_peek_token (parser)->keyword)
10407 : : {
10408 : 322 : case RID_CONSTEXPR:
10409 : 322 : case RID_REGISTER:
10410 : 322 : case RID_STATIC:
10411 : 322 : case RID_THREAD:
10412 : 322 : seen_scspec = true;
10413 : 322 : declspecs_add_scspec (c_parser_peek_token (parser)->location,
10414 : 322 : specs, c_parser_peek_token (parser)->value);
10415 : 322 : c_parser_consume_token (parser);
10416 : 322 : break;
10417 : 4143146 : default:
10418 : 4143146 : goto out;
10419 : : }
10420 : : }
10421 : 114089650 : out:
10422 : 118232796 : return seen_scspec ? specs : NULL;
10423 : : }
10424 : :
10425 : : /* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
10426 : : is not NULL then it is an Objective-C message expression which is the
10427 : : primary-expression starting the expression as an initializer.
10428 : :
10429 : : cast-expression:
10430 : : unary-expression
10431 : : ( type-name ) unary-expression
10432 : : */
10433 : :
10434 : : static struct c_expr
10435 : 358235874 : c_parser_cast_expression (c_parser *parser, struct c_expr *after)
10436 : : {
10437 : 358235874 : location_t cast_loc = c_parser_peek_token (parser)->location;
10438 : 358235874 : gcc_assert (!after || c_dialect_objc ());
10439 : 0 : if (after)
10440 : 0 : return c_parser_postfix_expression_after_primary (parser,
10441 : 0 : cast_loc, *after);
10442 : : /* If the expression begins with a parenthesized type name, it may
10443 : : be either a cast or a compound literal; we need to see whether
10444 : : the next character is '{' to tell the difference. If not, it is
10445 : : an unary expression. Full detection of unknown typenames here
10446 : : would require a 3-token lookahead. */
10447 : 358235874 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10448 : 358235874 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10449 : : {
10450 : 117871825 : struct c_declspecs *scspecs;
10451 : 117871825 : struct c_type_name *type_name;
10452 : 117871825 : struct c_expr ret;
10453 : 117871825 : struct c_expr expr;
10454 : 117871825 : matching_parens parens;
10455 : 117871825 : parens.consume_open (parser);
10456 : 117871825 : scspecs = c_parser_compound_literal_scspecs (parser);
10457 : 117871825 : type_name = c_parser_type_name (parser, true);
10458 : 117871825 : parens.skip_until_found_close (parser);
10459 : 117871825 : if (type_name == NULL)
10460 : : {
10461 : 1 : ret.set_error ();
10462 : 1 : ret.original_code = ERROR_MARK;
10463 : 1 : ret.original_type = NULL;
10464 : 1 : return ret;
10465 : : }
10466 : :
10467 : : /* Save casted types in the function's used types hash table. */
10468 : 117871824 : used_types_insert (type_name->specs->type);
10469 : :
10470 : 117871824 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10471 : 897259 : return c_parser_postfix_expression_after_paren_type (parser, scspecs,
10472 : : type_name,
10473 : 897259 : cast_loc);
10474 : 116974565 : if (scspecs)
10475 : 1 : error_at (cast_loc, "storage class specifier in cast");
10476 : 116974565 : if (type_name->specs->alignas_p)
10477 : 1 : error_at (type_name->specs->locations[cdw_alignas],
10478 : : "alignment specified for type name in cast");
10479 : 116974565 : {
10480 : 116974565 : location_t expr_loc = c_parser_peek_token (parser)->location;
10481 : 116974565 : expr = c_parser_cast_expression (parser, NULL);
10482 : 116974565 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
10483 : : }
10484 : 116974565 : ret.value = c_cast_expr (cast_loc, type_name, expr.value);
10485 : 116974565 : if (ret.value && expr.value)
10486 : 116974565 : set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
10487 : 116974565 : ret.original_code = ERROR_MARK;
10488 : 116974565 : ret.original_type = NULL;
10489 : 116974565 : ret.m_decimal = 0;
10490 : 116974565 : return ret;
10491 : : }
10492 : : else
10493 : 240364049 : return c_parser_unary_expression (parser);
10494 : : }
10495 : :
10496 : : /* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
10497 : :
10498 : : unary-expression:
10499 : : postfix-expression
10500 : : ++ unary-expression
10501 : : -- unary-expression
10502 : : unary-operator cast-expression
10503 : : _Countof unary-expression
10504 : : _Countof ( type-name )
10505 : : sizeof unary-expression
10506 : : sizeof ( type-name )
10507 : :
10508 : : (_Countof is new in C2y.)
10509 : :
10510 : : unary-operator: one of
10511 : : & * + - ~ !
10512 : :
10513 : : GNU extensions:
10514 : :
10515 : : unary-expression:
10516 : : __alignof__ unary-expression
10517 : : __alignof__ ( type-name )
10518 : : && identifier
10519 : :
10520 : : (C11 permits _Alignof with type names only.)
10521 : :
10522 : : unary-operator: one of
10523 : : __extension__ __real__ __imag__
10524 : :
10525 : : Transactional Memory:
10526 : :
10527 : : unary-expression:
10528 : : transaction-expression
10529 : :
10530 : : In addition, the GNU syntax treats ++ and -- as unary operators, so
10531 : : they may be applied to cast expressions with errors for non-lvalues
10532 : : given later. */
10533 : :
10534 : : static struct c_expr
10535 : 240705907 : c_parser_unary_expression (c_parser *parser)
10536 : : {
10537 : 240705907 : int ext;
10538 : 240705907 : struct c_expr ret, op;
10539 : 240705907 : location_t op_loc = c_parser_peek_token (parser)->location;
10540 : 240705907 : location_t exp_loc;
10541 : 240705907 : location_t finish;
10542 : 240705907 : ret.original_code = ERROR_MARK;
10543 : 240705907 : ret.original_type = NULL;
10544 : 240705907 : switch (c_parser_peek_token (parser)->type)
10545 : : {
10546 : 219836 : case CPP_PLUS_PLUS:
10547 : 219836 : c_parser_consume_token (parser);
10548 : 219836 : exp_loc = c_parser_peek_token (parser)->location;
10549 : 219836 : op = c_parser_cast_expression (parser, NULL);
10550 : :
10551 : 219836 : op = default_function_array_read_conversion (exp_loc, op);
10552 : 219836 : return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
10553 : 19692 : case CPP_MINUS_MINUS:
10554 : 19692 : c_parser_consume_token (parser);
10555 : 19692 : exp_loc = c_parser_peek_token (parser)->location;
10556 : 19692 : op = c_parser_cast_expression (parser, NULL);
10557 : :
10558 : 19692 : op = default_function_array_read_conversion (exp_loc, op);
10559 : 19692 : return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
10560 : 439865 : case CPP_AND:
10561 : 439865 : c_parser_consume_token (parser);
10562 : 439865 : op = c_parser_cast_expression (parser, NULL);
10563 : 439865 : mark_exp_read (op.value);
10564 : 439865 : return parser_build_unary_op (op_loc, ADDR_EXPR, op);
10565 : 1181355 : case CPP_MULT:
10566 : 1181355 : {
10567 : 1181355 : c_parser_consume_token (parser);
10568 : 1181355 : exp_loc = c_parser_peek_token (parser)->location;
10569 : 1181355 : op = c_parser_cast_expression (parser, NULL);
10570 : 1181355 : finish = op.get_finish ();
10571 : 1181355 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10572 : 1181355 : location_t combined_loc = make_location (op_loc, op_loc, finish);
10573 : 1181355 : ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
10574 : 1181355 : ret.src_range.m_start = op_loc;
10575 : 1181355 : ret.src_range.m_finish = finish;
10576 : 1181355 : ret.m_decimal = 0;
10577 : 1181355 : return ret;
10578 : : }
10579 : 28536 : case CPP_PLUS:
10580 : 28536 : if (!c_dialect_objc () && !in_system_header_at (input_location))
10581 : 28534 : warning_at (op_loc,
10582 : 28534 : OPT_Wtraditional,
10583 : : "traditional C rejects the unary plus operator");
10584 : 28536 : c_parser_consume_token (parser);
10585 : 28536 : exp_loc = c_parser_peek_token (parser)->location;
10586 : 28536 : op = c_parser_cast_expression (parser, NULL);
10587 : 28536 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10588 : 28536 : return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
10589 : 6512840 : case CPP_MINUS:
10590 : 6512840 : c_parser_consume_token (parser);
10591 : 6512840 : exp_loc = c_parser_peek_token (parser)->location;
10592 : 6512840 : op = c_parser_cast_expression (parser, NULL);
10593 : 6512840 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10594 : 6512840 : return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
10595 : 288410 : case CPP_COMPL:
10596 : 288410 : c_parser_consume_token (parser);
10597 : 288410 : exp_loc = c_parser_peek_token (parser)->location;
10598 : 288410 : op = c_parser_cast_expression (parser, NULL);
10599 : 288410 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10600 : 288410 : return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
10601 : 373275 : case CPP_NOT:
10602 : 373275 : c_parser_consume_token (parser);
10603 : 373275 : exp_loc = c_parser_peek_token (parser)->location;
10604 : 373275 : op = c_parser_cast_expression (parser, NULL);
10605 : 373275 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10606 : 373275 : return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
10607 : 1834 : case CPP_AND_AND:
10608 : : /* Refer to the address of a label as a pointer. */
10609 : 1834 : c_parser_consume_token (parser);
10610 : 1834 : if (c_parser_next_token_is (parser, CPP_NAME))
10611 : : {
10612 : 3654 : ret.value = finish_label_address_expr
10613 : 1827 : (c_parser_peek_token (parser)->value, op_loc);
10614 : 1827 : set_c_expr_source_range (&ret, op_loc,
10615 : : c_parser_peek_token (parser)->get_finish ());
10616 : 1827 : c_parser_consume_token (parser);
10617 : : }
10618 : : else
10619 : : {
10620 : 7 : c_parser_error (parser, "expected identifier");
10621 : 7 : ret.set_error ();
10622 : : }
10623 : 1834 : return ret;
10624 : 2824615 : case CPP_KEYWORD:
10625 : 2824615 : switch (c_parser_peek_token (parser)->keyword)
10626 : : {
10627 : 71 : case RID_COUNTOF:
10628 : 71 : return c_parser_countof_expression (parser);
10629 : 630515 : case RID_SIZEOF:
10630 : 630515 : return c_parser_sizeof_expression (parser);
10631 : 72243 : case RID_ALIGNOF:
10632 : 72243 : return c_parser_alignof_expression (parser);
10633 : 764 : case RID_BUILTIN_HAS_ATTRIBUTE:
10634 : 764 : return c_parser_has_attribute_expression (parser);
10635 : 448365 : case RID_EXTENSION:
10636 : 448365 : c_parser_consume_token (parser);
10637 : 448365 : ext = disable_extension_diagnostics ();
10638 : 448365 : ret = c_parser_cast_expression (parser, NULL);
10639 : 448365 : restore_extension_diagnostics (ext);
10640 : 448365 : return ret;
10641 : 38361 : case RID_REALPART:
10642 : 38361 : c_parser_consume_token (parser);
10643 : 38361 : exp_loc = c_parser_peek_token (parser)->location;
10644 : 38361 : op = c_parser_cast_expression (parser, NULL);
10645 : 38361 : op = default_function_array_conversion (exp_loc, op);
10646 : 38361 : return parser_build_unary_op (op_loc, REALPART_EXPR, op);
10647 : 38304 : case RID_IMAGPART:
10648 : 38304 : c_parser_consume_token (parser);
10649 : 38304 : exp_loc = c_parser_peek_token (parser)->location;
10650 : 38304 : op = c_parser_cast_expression (parser, NULL);
10651 : 38304 : op = default_function_array_conversion (exp_loc, op);
10652 : 38304 : return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
10653 : 7 : case RID_TRANSACTION_ATOMIC:
10654 : 7 : case RID_TRANSACTION_RELAXED:
10655 : 14 : return c_parser_transaction_expression (parser,
10656 : 7 : c_parser_peek_token (parser)->keyword);
10657 : 1595985 : default:
10658 : 1595985 : return c_parser_postfix_expression (parser);
10659 : : }
10660 : 228815649 : default:
10661 : 228815649 : return c_parser_postfix_expression (parser);
10662 : : }
10663 : : }
10664 : :
10665 : : /* Parse a sizeof expression. */
10666 : :
10667 : : static inline struct c_expr
10668 : 630515 : c_parser_sizeof_expression (c_parser *parser)
10669 : : {
10670 : 630515 : return c_parser_sizeof_or_countof_expression (parser, RID_SIZEOF);
10671 : : }
10672 : :
10673 : : /* Parse a _Countof expression. */
10674 : :
10675 : : static inline struct c_expr
10676 : 71 : c_parser_countof_expression (c_parser *parser)
10677 : : {
10678 : 71 : return c_parser_sizeof_or_countof_expression (parser, RID_COUNTOF);
10679 : : }
10680 : :
10681 : : /* Parse a sizeof or _Countof expression. */
10682 : :
10683 : : static struct c_expr
10684 : 630586 : c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
10685 : : {
10686 : 630586 : const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
10687 : 630586 : struct c_expr expr;
10688 : 630586 : struct c_expr result;
10689 : 630586 : location_t expr_loc;
10690 : 630586 : gcc_assert (c_parser_next_token_is_keyword (parser, rid));
10691 : :
10692 : 630586 : location_t start;
10693 : 630586 : location_t finish = UNKNOWN_LOCATION;
10694 : :
10695 : 630586 : start = c_parser_peek_token (parser)->location;
10696 : :
10697 : 630586 : if (rid == RID_COUNTOF)
10698 : 71 : pedwarn_c23 (start, OPT_Wpedantic,
10699 : : "ISO C does not support %qs before C2Y", op_name);
10700 : :
10701 : 630586 : c_parser_consume_token (parser);
10702 : 630586 : c_inhibit_evaluation_warnings++;
10703 : 630586 : if (rid == RID_COUNTOF)
10704 : 71 : in_countof++;
10705 : : else
10706 : 630515 : in_sizeof++;
10707 : 630586 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10708 : 630586 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10709 : : {
10710 : : /* Either sizeof ( type-name ) or sizeof unary-expression
10711 : : starting with a compound literal. */
10712 : 329517 : struct c_declspecs *scspecs;
10713 : 329517 : struct c_type_name *type_name;
10714 : 329517 : matching_parens parens;
10715 : 329517 : parens.consume_open (parser);
10716 : 329517 : expr_loc = c_parser_peek_token (parser)->location;
10717 : 329517 : scspecs = c_parser_compound_literal_scspecs (parser);
10718 : 329517 : type_name = c_parser_type_name (parser, true);
10719 : 329517 : parens.skip_until_found_close (parser);
10720 : 329517 : finish = parser->tokens_buf[0].location;
10721 : 329517 : if (type_name == NULL)
10722 : : {
10723 : : /* Let c_expr_sizeof_expr call pop_maybe_used and fill in c_expr
10724 : : for parsing error; the parsing of the expression could have
10725 : : called record_maybe_used_decl. */
10726 : 1 : expr.set_error ();
10727 : 27 : goto Xof_expr;
10728 : : }
10729 : 329516 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10730 : : {
10731 : 26 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10732 : : type_name,
10733 : : expr_loc);
10734 : 26 : finish = expr.get_finish ();
10735 : 26 : goto Xof_expr;
10736 : : }
10737 : : /* sizeof ( type-name ). */
10738 : 329490 : if (scspecs)
10739 : 1 : error_at (expr_loc, "storage class specifier in %qs", op_name);
10740 : 329490 : if (type_name->specs->alignas_p)
10741 : 2 : error_at (type_name->specs->locations[cdw_alignas],
10742 : : "alignment specified for type name in %qs", op_name);
10743 : 329490 : c_inhibit_evaluation_warnings--;
10744 : 329490 : if (rid == RID_COUNTOF)
10745 : : {
10746 : 18 : in_countof--;
10747 : 18 : result = c_expr_countof_type (expr_loc, type_name);
10748 : : }
10749 : : else
10750 : : {
10751 : 329472 : in_sizeof--;
10752 : 329472 : result = c_expr_sizeof_type (expr_loc, type_name);
10753 : : }
10754 : : }
10755 : : else
10756 : : {
10757 : 301069 : expr_loc = c_parser_peek_token (parser)->location;
10758 : 301069 : expr = c_parser_unary_expression (parser);
10759 : 301069 : finish = expr.get_finish ();
10760 : 301096 : Xof_expr:
10761 : 301096 : c_inhibit_evaluation_warnings--;
10762 : 301096 : if (rid == RID_COUNTOF)
10763 : 53 : in_countof--;
10764 : : else
10765 : 301043 : in_sizeof--;
10766 : 301096 : mark_exp_read (expr.value);
10767 : 301096 : if (TREE_CODE (expr.value) == COMPONENT_REF
10768 : 301096 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
10769 : 1 : error_at (expr_loc, "%qs applied to a bit-field", op_name);
10770 : 301096 : if (rid == RID_COUNTOF)
10771 : 53 : result = c_expr_countof_expr (expr_loc, expr);
10772 : : else
10773 : 301043 : result = c_expr_sizeof_expr (expr_loc, expr);
10774 : : }
10775 : 630586 : if (finish == UNKNOWN_LOCATION)
10776 : 1 : finish = start;
10777 : 630586 : set_c_expr_source_range (&result, start, finish);
10778 : 630586 : return result;
10779 : : }
10780 : :
10781 : : /* Parse an alignof expression. */
10782 : :
10783 : : static struct c_expr
10784 : 72243 : c_parser_alignof_expression (c_parser *parser)
10785 : : {
10786 : 72243 : struct c_expr expr;
10787 : 72243 : location_t start_loc = c_parser_peek_token (parser)->location;
10788 : 72243 : location_t end_loc;
10789 : 72243 : tree alignof_spelling = c_parser_peek_token (parser)->value;
10790 : 72243 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
10791 : 72243 : bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
10792 : : "_Alignof") == 0
10793 : 72243 : || strcmp (IDENTIFIER_POINTER (alignof_spelling),
10794 : 72472 : "alignof") == 0);
10795 : : /* A diagnostic is not required for the use of this identifier in
10796 : : the implementation namespace; only diagnose it for the C11 or C23
10797 : : spelling because of existing code using the other spellings. */
10798 : 229 : if (is_c11_alignof)
10799 : : {
10800 : 229 : if (flag_isoc99)
10801 : 225 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
10802 : : alignof_spelling);
10803 : : else
10804 : 4 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
10805 : : alignof_spelling);
10806 : : }
10807 : 72243 : c_parser_consume_token (parser);
10808 : 72243 : c_inhibit_evaluation_warnings++;
10809 : 72243 : in_alignof++;
10810 : 72243 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10811 : 72243 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10812 : : {
10813 : : /* Either __alignof__ ( type-name ) or __alignof__
10814 : : unary-expression starting with a compound literal. */
10815 : 31454 : location_t loc;
10816 : 31454 : struct c_declspecs *scspecs;
10817 : 31454 : struct c_type_name *type_name;
10818 : 31454 : struct c_expr ret;
10819 : 31454 : matching_parens parens;
10820 : 31454 : parens.consume_open (parser);
10821 : 31454 : loc = c_parser_peek_token (parser)->location;
10822 : 31454 : scspecs = c_parser_compound_literal_scspecs (parser);
10823 : 31454 : type_name = c_parser_type_name (parser, true);
10824 : 31454 : end_loc = c_parser_peek_token (parser)->location;
10825 : 31454 : parens.skip_until_found_close (parser);
10826 : 31454 : if (type_name == NULL)
10827 : : {
10828 : 0 : struct c_expr ret;
10829 : 0 : c_inhibit_evaluation_warnings--;
10830 : 0 : in_alignof--;
10831 : 0 : ret.set_error ();
10832 : 0 : ret.original_code = ERROR_MARK;
10833 : 0 : ret.original_type = NULL;
10834 : 31452 : return ret;
10835 : : }
10836 : 31454 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10837 : : {
10838 : 2 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10839 : : type_name,
10840 : : loc);
10841 : 2 : goto alignof_expr;
10842 : : }
10843 : : /* alignof ( type-name ). */
10844 : 31452 : if (scspecs)
10845 : 1 : error_at (loc, "storage class specifier in %qE", alignof_spelling);
10846 : 31452 : if (type_name->specs->alignas_p)
10847 : 1 : error_at (type_name->specs->locations[cdw_alignas],
10848 : : "alignment specified for type name in %qE",
10849 : : alignof_spelling);
10850 : 31452 : c_inhibit_evaluation_warnings--;
10851 : 31452 : in_alignof--;
10852 : 31452 : ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
10853 : : NULL, NULL),
10854 : : false, is_c11_alignof, 1);
10855 : 31452 : ret.original_code = ERROR_MARK;
10856 : 31452 : ret.original_type = NULL;
10857 : 31452 : set_c_expr_source_range (&ret, start_loc, end_loc);
10858 : 31452 : ret.m_decimal = 0;
10859 : 31452 : return ret;
10860 : : }
10861 : : else
10862 : : {
10863 : 40789 : struct c_expr ret;
10864 : 40789 : expr = c_parser_unary_expression (parser);
10865 : 40789 : end_loc = expr.src_range.m_finish;
10866 : 40791 : alignof_expr:
10867 : 40791 : mark_exp_read (expr.value);
10868 : 40791 : c_inhibit_evaluation_warnings--;
10869 : 40791 : in_alignof--;
10870 : 40791 : if (is_c11_alignof)
10871 : 36 : pedwarn (start_loc,
10872 : 36 : OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
10873 : : alignof_spelling);
10874 : 40791 : ret.value = c_alignof_expr (start_loc, expr.value);
10875 : 40791 : ret.original_code = ERROR_MARK;
10876 : 40791 : ret.original_type = NULL;
10877 : 40791 : set_c_expr_source_range (&ret, start_loc, end_loc);
10878 : 40791 : ret.m_decimal = 0;
10879 : 40791 : return ret;
10880 : : }
10881 : : }
10882 : :
10883 : : /* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
10884 : : expression. */
10885 : :
10886 : : static struct c_expr
10887 : 764 : c_parser_has_attribute_expression (c_parser *parser)
10888 : : {
10889 : 764 : gcc_assert (c_parser_next_token_is_keyword (parser,
10890 : : RID_BUILTIN_HAS_ATTRIBUTE));
10891 : 764 : location_t start = c_parser_peek_token (parser)->location;
10892 : 764 : c_parser_consume_token (parser);
10893 : :
10894 : 764 : c_inhibit_evaluation_warnings++;
10895 : :
10896 : 764 : matching_parens parens;
10897 : 764 : if (!parens.require_open (parser))
10898 : : {
10899 : 0 : c_inhibit_evaluation_warnings--;
10900 : 0 : in_typeof--;
10901 : :
10902 : 0 : struct c_expr result;
10903 : 0 : result.set_error ();
10904 : 0 : result.original_code = ERROR_MARK;
10905 : 0 : result.original_type = NULL;
10906 : 0 : return result;
10907 : : }
10908 : :
10909 : : /* Treat the type argument the same way as in typeof for the purposes
10910 : : of warnings. FIXME: Generalize this so the warning refers to
10911 : : __builtin_has_attribute rather than typeof. */
10912 : 764 : in_typeof++;
10913 : :
10914 : : /* The first operand: one of DECL, EXPR, or TYPE. */
10915 : 764 : tree oper = NULL_TREE;
10916 : 764 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
10917 : : {
10918 : 148 : struct c_type_name *tname = c_parser_type_name (parser);
10919 : 148 : in_typeof--;
10920 : 148 : if (tname)
10921 : : {
10922 : 148 : oper = groktypename (tname, NULL, NULL);
10923 : 148 : pop_maybe_used (c_type_variably_modified_p (oper));
10924 : : }
10925 : : }
10926 : : else
10927 : : {
10928 : 616 : struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
10929 : 616 : c_inhibit_evaluation_warnings--;
10930 : 616 : in_typeof--;
10931 : 616 : if (cexpr.value != error_mark_node)
10932 : : {
10933 : 613 : mark_exp_read (cexpr.value);
10934 : 613 : oper = cexpr.value;
10935 : 613 : tree etype = TREE_TYPE (oper);
10936 : 613 : bool was_vm = c_type_variably_modified_p (etype);
10937 : : /* This is returned with the type so that when the type is
10938 : : evaluated, this can be evaluated. */
10939 : 613 : if (was_vm)
10940 : 0 : oper = c_fully_fold (oper, false, NULL);
10941 : 613 : pop_maybe_used (was_vm);
10942 : : }
10943 : : }
10944 : :
10945 : 764 : struct c_expr result;
10946 : 764 : result.original_code = ERROR_MARK;
10947 : 764 : result.original_type = NULL;
10948 : :
10949 : 764 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
10950 : : {
10951 : : /* Consume the closing parenthesis if that's the next token
10952 : : in the likely case the built-in was invoked with fewer
10953 : : than two arguments. */
10954 : 4 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
10955 : 4 : c_parser_consume_token (parser);
10956 : 4 : c_inhibit_evaluation_warnings--;
10957 : 4 : result.set_error ();
10958 : 4 : return result;
10959 : : }
10960 : :
10961 : 760 : bool save_translate_strings_p = parser->translate_strings_p;
10962 : :
10963 : 760 : location_t atloc = c_parser_peek_token (parser)->location;
10964 : : /* Parse a single attribute. Require no leading comma and do not
10965 : : allow empty attributes. */
10966 : 760 : tree attr = c_parser_gnu_attribute (parser, NULL_TREE, false, false);
10967 : :
10968 : 760 : parser->translate_strings_p = save_translate_strings_p;
10969 : :
10970 : 760 : location_t finish = c_parser_peek_token (parser)->location;
10971 : 760 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
10972 : 757 : c_parser_consume_token (parser);
10973 : : else
10974 : : {
10975 : 3 : c_parser_error (parser, "expected identifier");
10976 : 3 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
10977 : :
10978 : 3 : result.set_error ();
10979 : 3 : return result;
10980 : : }
10981 : :
10982 : 757 : if (!attr)
10983 : : {
10984 : 0 : error_at (atloc, "expected identifier");
10985 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
10986 : : "expected %<)%>");
10987 : 0 : result.set_error ();
10988 : 0 : return result;
10989 : : }
10990 : :
10991 : 757 : result.original_code = INTEGER_CST;
10992 : 757 : result.original_type = boolean_type_node;
10993 : :
10994 : 757 : if (has_attribute (atloc, oper, attr, default_conversion))
10995 : 296 : result.value = boolean_true_node;
10996 : : else
10997 : 461 : result.value = boolean_false_node;
10998 : :
10999 : 757 : set_c_expr_source_range (&result, start, finish);
11000 : 757 : result.m_decimal = 0;
11001 : 757 : return result;
11002 : : }
11003 : :
11004 : : /* Helper function to read arguments of builtins which are interfaces
11005 : : for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
11006 : : others. The name of the builtin is passed using BNAME parameter.
11007 : : Function returns true if there were no errors while parsing and
11008 : : stores the arguments in CEXPR_LIST. If it returns true,
11009 : : *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
11010 : : parenthesis. */
11011 : : static bool
11012 : 1526455 : c_parser_get_builtin_args (c_parser *parser, const char *bname,
11013 : : vec<c_expr_t, va_gc> **ret_cexpr_list,
11014 : : bool choose_expr_p,
11015 : : location_t *out_close_paren_loc)
11016 : : {
11017 : 1526455 : location_t loc = c_parser_peek_token (parser)->location;
11018 : 1526455 : vec<c_expr_t, va_gc> *cexpr_list;
11019 : 1526455 : c_expr_t expr;
11020 : 1526455 : bool saved_force_folding_builtin_constant_p;
11021 : :
11022 : 1526455 : *ret_cexpr_list = NULL;
11023 : 1526455 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
11024 : : {
11025 : 1 : error_at (loc, "cannot take address of %qs", bname);
11026 : 1 : return false;
11027 : : }
11028 : :
11029 : 1526454 : c_parser_consume_token (parser);
11030 : :
11031 : 1526454 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11032 : : {
11033 : 18 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11034 : 18 : c_parser_consume_token (parser);
11035 : 18 : return true;
11036 : : }
11037 : :
11038 : 1526436 : saved_force_folding_builtin_constant_p
11039 : 1526436 : = force_folding_builtin_constant_p;
11040 : 1526436 : force_folding_builtin_constant_p |= choose_expr_p;
11041 : 1526436 : expr = c_parser_expr_no_commas (parser, NULL);
11042 : 1526436 : force_folding_builtin_constant_p
11043 : 1526436 : = saved_force_folding_builtin_constant_p;
11044 : 1526436 : vec_alloc (cexpr_list, 1);
11045 : 1526436 : vec_safe_push (cexpr_list, expr);
11046 : 17846216 : while (c_parser_next_token_is (parser, CPP_COMMA))
11047 : : {
11048 : 14793344 : c_parser_consume_token (parser);
11049 : 14793344 : if (c_parser_next_token_is (parser, CPP_EMBED))
11050 : : {
11051 : 2 : c_token *embed = c_parser_peek_token (parser);
11052 : 2 : tree value = embed->value;
11053 : 2 : expr.original_code = INTEGER_CST;
11054 : 2 : expr.original_type = integer_type_node;
11055 : 2 : expr.value = NULL_TREE;
11056 : 2 : set_c_expr_source_range (&expr, embed->get_range ());
11057 : 2 : expr.m_decimal = 0;
11058 : 510 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
11059 : : {
11060 : 1016 : expr.value = build_int_cst (integer_type_node,
11061 : 508 : RAW_DATA_UCHAR_ELT (value, i));
11062 : 508 : vec_safe_push (cexpr_list, expr);
11063 : : }
11064 : 2 : c_parser_consume_token (parser);
11065 : 2 : continue;
11066 : 2 : }
11067 : 14793342 : expr = c_parser_expr_no_commas (parser, NULL);
11068 : 14793342 : vec_safe_push (cexpr_list, expr);
11069 : : }
11070 : :
11071 : 1526436 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11072 : 1526436 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
11073 : : return false;
11074 : :
11075 : 1526436 : *ret_cexpr_list = cexpr_list;
11076 : 1526436 : return true;
11077 : : }
11078 : :
11079 : : /* This represents a single generic-association. */
11080 : :
11081 : : struct c_generic_association
11082 : : {
11083 : : /* The location of the starting token of the type. */
11084 : : location_t type_location;
11085 : : /* The association's type, or NULL_TREE for 'default'. */
11086 : : tree type;
11087 : : /* The association's expression. */
11088 : : struct c_expr expression;
11089 : : };
11090 : :
11091 : : /* Parse a generic-selection. (C11 6.5.1.1).
11092 : :
11093 : : generic-selection:
11094 : : _Generic ( generic-controlling-operand , generic-assoc-list )
11095 : :
11096 : : generic-controlling-operand:
11097 : : assignment-expression
11098 : : type-name
11099 : :
11100 : : (The use of a type-name is new in C2Y.)
11101 : :
11102 : : generic-assoc-list:
11103 : : generic-association
11104 : : generic-assoc-list , generic-association
11105 : :
11106 : : generic-association:
11107 : : type-name : assignment-expression
11108 : : default : assignment-expression
11109 : : */
11110 : :
11111 : : static struct c_expr
11112 : 621 : c_parser_generic_selection (c_parser *parser)
11113 : : {
11114 : 621 : struct c_expr selector, error_expr;
11115 : 621 : tree selector_type;
11116 : 621 : struct c_generic_association matched_assoc;
11117 : 621 : int match_found = -1;
11118 : 621 : location_t generic_loc, selector_loc;
11119 : :
11120 : 621 : error_expr.original_code = ERROR_MARK;
11121 : 621 : error_expr.original_type = NULL;
11122 : 621 : error_expr.set_error ();
11123 : 621 : matched_assoc.type_location = UNKNOWN_LOCATION;
11124 : 621 : matched_assoc.type = NULL_TREE;
11125 : 621 : matched_assoc.expression = error_expr;
11126 : :
11127 : 621 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
11128 : 621 : generic_loc = c_parser_peek_token (parser)->location;
11129 : 621 : c_parser_consume_token (parser);
11130 : 621 : if (flag_isoc99)
11131 : 619 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11132 : : "ISO C99 does not support %<_Generic%>");
11133 : : else
11134 : 2 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11135 : : "ISO C90 does not support %<_Generic%>");
11136 : :
11137 : 621 : matching_parens parens;
11138 : 621 : if (!parens.require_open (parser))
11139 : 0 : return error_expr;
11140 : :
11141 : 621 : selector_loc = c_parser_peek_token (parser)->location;
11142 : 621 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
11143 : : {
11144 : 31 : c_inhibit_evaluation_warnings++;
11145 : 31 : pedwarn_c23 (selector_loc, OPT_Wpedantic,
11146 : : "ISO C does not support use of type name as %<_Generic%> "
11147 : : "controlling operand before C2Y");
11148 : 31 : struct c_type_name *type = c_parser_type_name (parser);
11149 : 31 : if (type)
11150 : 30 : selector_type = groktypename (type, NULL, NULL);
11151 : 31 : c_inhibit_evaluation_warnings--;
11152 : 31 : if (!type)
11153 : : {
11154 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11155 : 1 : return error_expr;
11156 : : }
11157 : : }
11158 : : else
11159 : : {
11160 : 590 : c_inhibit_evaluation_warnings++;
11161 : 590 : selector = c_parser_expr_no_commas (parser, NULL);
11162 : 590 : selector = default_function_array_conversion (selector_loc, selector);
11163 : 590 : c_inhibit_evaluation_warnings--;
11164 : :
11165 : 590 : if (selector.value == error_mark_node)
11166 : : {
11167 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11168 : 0 : return selector;
11169 : : }
11170 : 590 : mark_exp_read (selector.value);
11171 : 590 : selector_type = TREE_TYPE (selector.value);
11172 : : /* In ISO C terms, rvalues (including the controlling expression
11173 : : of _Generic) do not have qualified types. */
11174 : 590 : if (TREE_CODE (selector_type) != ARRAY_TYPE)
11175 : 590 : selector_type = TYPE_MAIN_VARIANT (selector_type);
11176 : : /* In ISO C terms, _Noreturn is not part of the type of expressions
11177 : : such as &abort, but in GCC it is represented internally as a type
11178 : : qualifier. */
11179 : 58 : if (FUNCTION_POINTER_TYPE_P (selector_type)
11180 : 594 : && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
11181 : 1 : selector_type
11182 : 1 : = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
11183 : : }
11184 : :
11185 : 620 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11186 : : {
11187 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11188 : 0 : return error_expr;
11189 : : }
11190 : :
11191 : 620 : auto_vec<c_generic_association> associations;
11192 : 1768 : while (1)
11193 : : {
11194 : 1194 : struct c_generic_association assoc, *iter;
11195 : 1194 : unsigned int ix;
11196 : 1194 : c_token *token = c_parser_peek_token (parser);
11197 : :
11198 : 1194 : assoc.type_location = token->location;
11199 : 1194 : if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
11200 : : {
11201 : 475 : c_parser_consume_token (parser);
11202 : 475 : assoc.type = NULL_TREE;
11203 : : }
11204 : : else
11205 : : {
11206 : 719 : struct c_type_name *type_name;
11207 : :
11208 : 719 : type_name = c_parser_type_name (parser);
11209 : 719 : if (type_name == NULL)
11210 : : {
11211 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11212 : 1 : return error_expr;
11213 : : }
11214 : 718 : assoc.type = groktypename (type_name, NULL, NULL);
11215 : 718 : if (assoc.type == error_mark_node)
11216 : : {
11217 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11218 : 0 : return error_expr;
11219 : : }
11220 : :
11221 : 718 : if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
11222 : 9 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11223 : : "ISO C does not support %<_Generic%> association with "
11224 : : "function type before C2Y");
11225 : 709 : else if (!COMPLETE_TYPE_P (assoc.type))
11226 : 13 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11227 : : "ISO C does not support %<_Generic%> association with "
11228 : : "incomplete type before C2Y");
11229 : :
11230 : 718 : if (c_type_variably_modified_p (assoc.type))
11231 : 2 : error_at (assoc.type_location,
11232 : : "%<_Generic%> association has "
11233 : : "variable length type");
11234 : : }
11235 : :
11236 : 1193 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
11237 : : {
11238 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11239 : 0 : return error_expr;
11240 : : }
11241 : :
11242 : 1193 : bool match = assoc.type == NULL_TREE
11243 : 1193 : || comptypes (assoc.type, selector_type);
11244 : :
11245 : 142 : if (!match)
11246 : 142 : c_inhibit_evaluation_warnings++;
11247 : :
11248 : 1193 : assoc.expression = c_parser_expr_no_commas (parser, NULL);
11249 : :
11250 : 1193 : if (!match)
11251 : 142 : c_inhibit_evaluation_warnings--;
11252 : :
11253 : 1193 : if (assoc.expression.value == error_mark_node)
11254 : : {
11255 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11256 : 0 : return error_expr;
11257 : : }
11258 : :
11259 : 1871 : for (ix = 0; associations.iterate (ix, &iter); ++ix)
11260 : : {
11261 : 678 : if (assoc.type == NULL_TREE)
11262 : : {
11263 : 188 : if (iter->type == NULL_TREE)
11264 : : {
11265 : 1 : error_at (assoc.type_location,
11266 : : "duplicate %<default%> case in %<_Generic%>");
11267 : 1 : inform (iter->type_location, "original %<default%> is here");
11268 : : }
11269 : : }
11270 : 490 : else if (iter->type != NULL_TREE)
11271 : : {
11272 : 159 : if (comptypes (assoc.type, iter->type))
11273 : : {
11274 : 1 : error_at (assoc.type_location,
11275 : : "%<_Generic%> specifies two compatible types");
11276 : 1 : inform (iter->type_location, "compatible type is here");
11277 : : }
11278 : : }
11279 : : }
11280 : :
11281 : 1193 : if (assoc.type == NULL_TREE)
11282 : : {
11283 : 475 : if (match_found < 0)
11284 : : {
11285 : 332 : matched_assoc = assoc;
11286 : 362 : match_found = associations.length ();
11287 : : }
11288 : : }
11289 : 718 : else if (match)
11290 : : {
11291 : 576 : if (match_found < 0 || matched_assoc.type == NULL_TREE)
11292 : : {
11293 : 576 : matched_assoc = assoc;
11294 : 906 : match_found = associations.length ();
11295 : : }
11296 : : else
11297 : : {
11298 : 0 : error_at (assoc.type_location,
11299 : : "%<_Generic%> selector matches multiple associations");
11300 : 0 : inform (matched_assoc.type_location,
11301 : : "other match is here");
11302 : : }
11303 : : }
11304 : :
11305 : 1193 : associations.safe_push (assoc);
11306 : :
11307 : 1193 : if (c_parser_peek_token (parser)->type != CPP_COMMA)
11308 : : break;
11309 : 574 : c_parser_consume_token (parser);
11310 : 574 : }
11311 : :
11312 : 619 : unsigned int ix;
11313 : 619 : struct c_generic_association *iter;
11314 : 1811 : FOR_EACH_VEC_ELT (associations, ix, iter)
11315 : 1192 : if (ix != (unsigned) match_found)
11316 : 577 : mark_exp_read (iter->expression.value);
11317 : :
11318 : 619 : if (!parens.require_close (parser))
11319 : : {
11320 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11321 : 0 : return error_expr;
11322 : : }
11323 : :
11324 : 619 : if (match_found < 0)
11325 : : {
11326 : 4 : error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
11327 : : "compatible with any association",
11328 : : selector_type);
11329 : 4 : return error_expr;
11330 : : }
11331 : :
11332 : 615 : return matched_assoc.expression;
11333 : 620 : }
11334 : :
11335 : : /* Check the validity of a function pointer argument *EXPR (argument
11336 : : position POS) to __builtin_tgmath. Return the number of function
11337 : : arguments if possibly valid; return 0 having reported an error if
11338 : : not valid. */
11339 : :
11340 : : static unsigned int
11341 : 1755 : check_tgmath_function (c_expr *expr, unsigned int pos)
11342 : : {
11343 : 1755 : tree type = TREE_TYPE (expr->value);
11344 : 1755 : if (!FUNCTION_POINTER_TYPE_P (type))
11345 : : {
11346 : 2 : error_at (expr->get_location (),
11347 : : "argument %u of %<__builtin_tgmath%> is not a function pointer",
11348 : : pos);
11349 : 2 : return 0;
11350 : : }
11351 : 1753 : type = TREE_TYPE (type);
11352 : 1753 : if (!prototype_p (type))
11353 : : {
11354 : 2 : error_at (expr->get_location (),
11355 : : "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
11356 : 2 : return 0;
11357 : : }
11358 : 1751 : if (stdarg_p (type))
11359 : : {
11360 : 2 : error_at (expr->get_location (),
11361 : : "argument %u of %<__builtin_tgmath%> has variable arguments",
11362 : : pos);
11363 : 2 : return 0;
11364 : : }
11365 : 1749 : unsigned int nargs = 0;
11366 : 1749 : function_args_iterator iter;
11367 : 1749 : tree t;
11368 : 4176 : FOREACH_FUNCTION_ARGS (type, t, iter)
11369 : : {
11370 : 4176 : if (t == void_type_node)
11371 : : break;
11372 : 2427 : nargs++;
11373 : : }
11374 : 1749 : if (nargs == 0)
11375 : : {
11376 : 2 : error_at (expr->get_location (),
11377 : : "argument %u of %<__builtin_tgmath%> has no arguments", pos);
11378 : 2 : return 0;
11379 : : }
11380 : : return nargs;
11381 : : }
11382 : :
11383 : : /* Ways in which a parameter or return value of a type-generic macro
11384 : : may vary between the different functions the macro may call. */
11385 : : enum tgmath_parm_kind
11386 : : {
11387 : : tgmath_fixed, tgmath_real, tgmath_complex
11388 : : };
11389 : :
11390 : : /* Helper function for c_parser_postfix_expression. Parse predefined
11391 : : identifiers. */
11392 : :
11393 : : static struct c_expr
11394 : 11827 : c_parser_predefined_identifier (c_parser *parser)
11395 : : {
11396 : 11827 : location_t loc = c_parser_peek_token (parser)->location;
11397 : 11827 : switch (c_parser_peek_token (parser)->keyword)
11398 : : {
11399 : 709 : case RID_FUNCTION_NAME:
11400 : 709 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11401 : : "identifier", "__FUNCTION__");
11402 : 709 : break;
11403 : 4851 : case RID_PRETTY_FUNCTION_NAME:
11404 : 4851 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11405 : : "identifier", "__PRETTY_FUNCTION__");
11406 : 4851 : break;
11407 : 6267 : case RID_C99_FUNCTION_NAME:
11408 : 6267 : pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
11409 : : "%<__func__%> predefined identifier");
11410 : 6267 : break;
11411 : 0 : default:
11412 : 0 : gcc_unreachable ();
11413 : : }
11414 : :
11415 : 11827 : struct c_expr expr;
11416 : 11827 : expr.original_code = ERROR_MARK;
11417 : 11827 : expr.original_type = NULL;
11418 : 11827 : expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
11419 : 11827 : c_parser_peek_token (parser)->value);
11420 : 11827 : set_c_expr_source_range (&expr, loc, loc);
11421 : 11827 : expr.m_decimal = 0;
11422 : 11827 : c_parser_consume_token (parser);
11423 : 11827 : return expr;
11424 : : }
11425 : :
11426 : : /* Check whether the ARRAY_REF has an counted-by object associated with it
11427 : : through the "counted_by" attribute. */
11428 : :
11429 : : static bool
11430 : 40 : has_counted_by_object (tree array_ref)
11431 : : {
11432 : : /* Currently, only when the array_ref is an indirect_ref to a call to the
11433 : : .ACCESS_WITH_SIZE, return true.
11434 : : More cases can be included later when the counted_by attribute is
11435 : : extended to other situations. */
11436 : 40 : if (TREE_CODE (array_ref) == INDIRECT_REF
11437 : 40 : && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11438 : : return true;
11439 : : return false;
11440 : : }
11441 : :
11442 : : /* Get the reference to the counted-by object associated with the ARRAY_REF. */
11443 : :
11444 : : static tree
11445 : 25 : get_counted_by_ref (tree array_ref)
11446 : : {
11447 : : /* Currently, only when the array_ref is an indirect_ref to a call to the
11448 : : .ACCESS_WITH_SIZE, get the corresponding counted_by ref.
11449 : : More cases can be included later when the counted_by attribute is
11450 : : extended to other situations. */
11451 : 25 : if (TREE_CODE (array_ref) == INDIRECT_REF
11452 : 25 : && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11453 : 25 : return CALL_EXPR_ARG (TREE_OPERAND (array_ref, 0), 1);
11454 : : return NULL_TREE;
11455 : : }
11456 : :
11457 : : /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
11458 : : C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
11459 : : call c_parser_postfix_expression_after_paren_type on encountering them.
11460 : :
11461 : : postfix-expression:
11462 : : primary-expression
11463 : : postfix-expression [ expression ]
11464 : : postfix-expression ( argument-expression-list[opt] )
11465 : : postfix-expression . identifier
11466 : : postfix-expression -> identifier
11467 : : postfix-expression ++
11468 : : postfix-expression --
11469 : : ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
11470 : : ( storage-class-specifiers[opt] type-name ) { initializer-list , }
11471 : :
11472 : : argument-expression-list:
11473 : : argument-expression
11474 : : argument-expression-list , argument-expression
11475 : :
11476 : : primary-expression:
11477 : : identifier
11478 : : constant
11479 : : string-literal
11480 : : ( expression )
11481 : : generic-selection
11482 : :
11483 : : GNU extensions:
11484 : :
11485 : : primary-expression:
11486 : : __func__
11487 : : (treated as a keyword in GNU C)
11488 : : __FUNCTION__
11489 : : __PRETTY_FUNCTION__
11490 : : ( compound-statement )
11491 : : __builtin_va_arg ( assignment-expression , type-name )
11492 : : __builtin_offsetof ( type-name , offsetof-member-designator )
11493 : : __builtin_choose_expr ( assignment-expression ,
11494 : : assignment-expression ,
11495 : : assignment-expression )
11496 : : __builtin_types_compatible_p ( type-name , type-name )
11497 : : __builtin_tgmath ( expr-list )
11498 : : __builtin_complex ( assignment-expression , assignment-expression )
11499 : : __builtin_shuffle ( assignment-expression , assignment-expression )
11500 : : __builtin_shuffle ( assignment-expression ,
11501 : : assignment-expression ,
11502 : : assignment-expression, )
11503 : : __builtin_convertvector ( assignment-expression , type-name )
11504 : : __builtin_assoc_barrier ( assignment-expression )
11505 : :
11506 : : offsetof-member-designator:
11507 : : identifier
11508 : : offsetof-member-designator . identifier
11509 : : offsetof-member-designator [ expression ]
11510 : :
11511 : : Objective-C:
11512 : :
11513 : : primary-expression:
11514 : : [ objc-receiver objc-message-args ]
11515 : : @selector ( objc-selector-arg )
11516 : : @protocol ( identifier )
11517 : : @encode ( type-name )
11518 : : objc-string-literal
11519 : : Classname . identifier
11520 : : */
11521 : :
11522 : : static struct c_expr
11523 : 230423289 : c_parser_postfix_expression (c_parser *parser)
11524 : : {
11525 : 230423289 : struct c_expr expr, e1;
11526 : 230423289 : struct c_type_name *t1, *t2;
11527 : 230423289 : location_t loc = c_parser_peek_token (parser)->location;
11528 : 230423289 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
11529 : 230423289 : expr.original_code = ERROR_MARK;
11530 : 230423289 : expr.original_type = NULL;
11531 : 230423289 : expr.m_decimal = 0;
11532 : 230423289 : switch (c_parser_peek_token (parser)->type)
11533 : : {
11534 : 49797532 : case CPP_NUMBER:
11535 : 49797532 : expr.value = c_parser_peek_token (parser)->value;
11536 : 49797532 : set_c_expr_source_range (&expr, tok_range);
11537 : 49797532 : loc = c_parser_peek_token (parser)->location;
11538 : 49797532 : expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
11539 : 49797532 : c_parser_consume_token (parser);
11540 : 49797532 : if (TREE_CODE (expr.value) == FIXED_CST
11541 : 49797532 : && !targetm.fixed_point_supported_p ())
11542 : : {
11543 : 6 : error_at (loc, "fixed-point types not supported for this target");
11544 : 6 : expr.set_error ();
11545 : : }
11546 : : break;
11547 : 112978 : case CPP_CHAR:
11548 : 112978 : case CPP_CHAR16:
11549 : 112978 : case CPP_CHAR32:
11550 : 112978 : case CPP_UTF8CHAR:
11551 : 112978 : case CPP_WCHAR:
11552 : 112978 : expr.value = c_parser_peek_token (parser)->value;
11553 : : /* For the purpose of warning when a pointer is compared with
11554 : : a zero character constant. */
11555 : 112978 : expr.original_type = char_type_node;
11556 : 112978 : set_c_expr_source_range (&expr, tok_range);
11557 : 112978 : c_parser_consume_token (parser);
11558 : 112978 : break;
11559 : 1150075 : case CPP_STRING:
11560 : 1150075 : case CPP_STRING16:
11561 : 1150075 : case CPP_STRING32:
11562 : 1150075 : case CPP_WSTRING:
11563 : 1150075 : case CPP_UTF8STRING:
11564 : 1150075 : expr = c_parser_string_literal (parser, parser->translate_strings_p,
11565 : : true);
11566 : 1150075 : break;
11567 : 0 : case CPP_OBJC_STRING:
11568 : 0 : gcc_assert (c_dialect_objc ());
11569 : 0 : expr.value
11570 : 0 : = objc_build_string_object (c_parser_peek_token (parser)->value);
11571 : 0 : set_c_expr_source_range (&expr, tok_range);
11572 : 0 : c_parser_consume_token (parser);
11573 : 0 : break;
11574 : 170374331 : case CPP_NAME:
11575 : 170374331 : switch (c_parser_peek_token (parser)->id_kind)
11576 : : {
11577 : 170374329 : case C_ID_ID:
11578 : 170374329 : {
11579 : 170374329 : tree id = c_parser_peek_token (parser)->value;
11580 : 170374329 : c_parser_consume_token (parser);
11581 : 511122987 : expr.value = build_external_ref (loc, id,
11582 : 170374329 : (c_parser_peek_token (parser)->type
11583 : : == CPP_OPEN_PAREN),
11584 : : &expr.original_type);
11585 : 170374329 : set_c_expr_source_range (&expr, tok_range);
11586 : 170374329 : break;
11587 : : }
11588 : 0 : case C_ID_CLASSNAME:
11589 : 0 : {
11590 : : /* Here we parse the Objective-C 2.0 Class.name dot
11591 : : syntax. */
11592 : 0 : tree class_name = c_parser_peek_token (parser)->value;
11593 : 0 : tree component;
11594 : 0 : c_parser_consume_token (parser);
11595 : 0 : gcc_assert (c_dialect_objc ());
11596 : 0 : if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
11597 : : {
11598 : 0 : expr.set_error ();
11599 : 0 : break;
11600 : : }
11601 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
11602 : : {
11603 : 0 : c_parser_error (parser, "expected identifier");
11604 : 0 : expr.set_error ();
11605 : 0 : break;
11606 : : }
11607 : 0 : c_token *component_tok = c_parser_peek_token (parser);
11608 : 0 : component = component_tok->value;
11609 : 0 : location_t end_loc = component_tok->get_finish ();
11610 : 0 : c_parser_consume_token (parser);
11611 : 0 : expr.value = objc_build_class_component_ref (class_name,
11612 : : component);
11613 : 0 : set_c_expr_source_range (&expr, loc, end_loc);
11614 : 0 : break;
11615 : : }
11616 : 2 : default:
11617 : 2 : c_parser_error (parser, "expected expression");
11618 : 2 : expr.set_error ();
11619 : 2 : break;
11620 : : }
11621 : : break;
11622 : 7391595 : case CPP_OPEN_PAREN:
11623 : : /* A parenthesized expression, statement expression or compound
11624 : : literal. */
11625 : 7391595 : if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
11626 : : {
11627 : : /* A statement expression. */
11628 : 33489 : tree stmt;
11629 : 33489 : location_t brace_loc;
11630 : 33489 : bool save_c_omp_array_section_p = c_omp_array_section_p;
11631 : 33489 : c_parser_consume_token (parser);
11632 : 33489 : brace_loc = c_parser_peek_token (parser)->location;
11633 : 33489 : c_parser_consume_token (parser);
11634 : : /* If we've not yet started the current function's statement list,
11635 : : or we're in the parameter scope of an old-style function
11636 : : declaration, statement expressions are not allowed. */
11637 : 33489 : if (!building_stmt_list_p () || old_style_parameter_scope ())
11638 : : {
11639 : 24 : error_at (loc, "braced-group within expression allowed "
11640 : : "only inside a function");
11641 : 24 : parser->error = true;
11642 : 24 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
11643 : 24 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11644 : 24 : expr.set_error ();
11645 : 24 : break;
11646 : : }
11647 : 33465 : c_omp_array_section_p = false;
11648 : 33465 : stmt = c_begin_stmt_expr ();
11649 : 33465 : c_parser_compound_statement_nostart (parser);
11650 : 33465 : location_t close_loc = c_parser_peek_token (parser)->location;
11651 : 33465 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11652 : : "expected %<)%>");
11653 : 33465 : pedwarn (loc, OPT_Wpedantic,
11654 : : "ISO C forbids braced-groups within expressions");
11655 : 33465 : expr.value = c_finish_stmt_expr (brace_loc, stmt);
11656 : 33465 : set_c_expr_source_range (&expr, loc, close_loc);
11657 : 33465 : mark_exp_read (expr.value);
11658 : 33465 : c_omp_array_section_p = save_c_omp_array_section_p;
11659 : : }
11660 : : else
11661 : : {
11662 : : /* A parenthesized expression. */
11663 : 7358106 : location_t loc_open_paren = c_parser_peek_token (parser)->location;
11664 : 7358106 : c_parser_consume_token (parser);
11665 : 7358106 : expr = c_parser_expression (parser);
11666 : 7358106 : if (TREE_CODE (expr.value) == MODIFY_EXPR)
11667 : 37680 : suppress_warning (expr.value, OPT_Wparentheses);
11668 : 7358106 : if (expr.original_code != C_MAYBE_CONST_EXPR
11669 : 7358094 : && expr.original_code != SIZEOF_EXPR)
11670 : 7353230 : expr.original_code = ERROR_MARK;
11671 : : /* Remember that we saw ( ) around the sizeof. */
11672 : 7358106 : if (expr.original_code == SIZEOF_EXPR)
11673 : 4864 : expr.original_code = PAREN_SIZEOF_EXPR;
11674 : : /* Don't change EXPR.ORIGINAL_TYPE. */
11675 : 7358106 : location_t loc_close_paren = c_parser_peek_token (parser)->location;
11676 : 7358106 : set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
11677 : 7358106 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11678 : : "expected %<)%>", loc_open_paren);
11679 : : }
11680 : : break;
11681 : 1595985 : case CPP_KEYWORD:
11682 : 1595985 : switch (c_parser_peek_token (parser)->keyword)
11683 : : {
11684 : 11807 : case RID_FUNCTION_NAME:
11685 : 11807 : case RID_PRETTY_FUNCTION_NAME:
11686 : 11807 : case RID_C99_FUNCTION_NAME:
11687 : 11807 : expr = c_parser_predefined_identifier (parser);
11688 : 11807 : break;
11689 : 19882 : case RID_VA_ARG:
11690 : 19882 : {
11691 : 19882 : location_t start_loc = loc;
11692 : 19882 : c_parser_consume_token (parser);
11693 : 19882 : matching_parens parens;
11694 : 19882 : if (!parens.require_open (parser))
11695 : : {
11696 : 0 : expr.set_error ();
11697 : 0 : break;
11698 : : }
11699 : 19882 : e1 = c_parser_expr_no_commas (parser, NULL);
11700 : 19882 : mark_exp_read (e1.value);
11701 : 19882 : e1.value = c_fully_fold (e1.value, false, NULL);
11702 : 19882 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11703 : : {
11704 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11705 : 0 : expr.set_error ();
11706 : 0 : break;
11707 : : }
11708 : 19882 : loc = c_parser_peek_token (parser)->location;
11709 : 19882 : t1 = c_parser_type_name (parser);
11710 : 19882 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11711 : 19882 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11712 : : "expected %<)%>");
11713 : 19882 : if (t1 == NULL)
11714 : : {
11715 : 0 : expr.set_error ();
11716 : : }
11717 : : else
11718 : : {
11719 : 19882 : tree type_expr = NULL_TREE;
11720 : 19882 : expr.value = c_build_va_arg (start_loc, e1.value, loc,
11721 : : groktypename (t1, &type_expr, NULL));
11722 : 19882 : if (type_expr)
11723 : : {
11724 : 24 : expr.value = build2 (C_MAYBE_CONST_EXPR,
11725 : 24 : TREE_TYPE (expr.value), type_expr,
11726 : : expr.value);
11727 : 24 : C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
11728 : : }
11729 : 19882 : set_c_expr_source_range (&expr, start_loc, end_loc);
11730 : : }
11731 : : }
11732 : 19882 : break;
11733 : 13578 : case RID_C23_VA_START:
11734 : 13578 : {
11735 : 13578 : c_parser_consume_token (parser);
11736 : 13578 : matching_parens parens;
11737 : 13578 : if (!parens.require_open (parser))
11738 : : {
11739 : 0 : expr.set_error ();
11740 : 0 : break;
11741 : : }
11742 : 13578 : e1 = c_parser_expr_no_commas (parser, NULL);
11743 : 13578 : e1 = convert_lvalue_to_rvalue (e1.get_location (), e1, true, true);
11744 : 13578 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11745 : : {
11746 : 13400 : location_t cloc = c_parser_peek_token (parser)->location;
11747 : 13400 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11748 : : {
11749 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11750 : 0 : expr.set_error ();
11751 : 0 : break;
11752 : : }
11753 : 13400 : if (c_parser_next_token_is (parser, CPP_NAME)
11754 : 13395 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
11755 : 26795 : && (c_parser_peek_2nd_token (parser)->type
11756 : : == CPP_CLOSE_PAREN))
11757 : : {
11758 : 13374 : tree name = c_parser_peek_token (parser)->value;
11759 : 13374 : location_t nloc = c_parser_peek_token (parser)->location;
11760 : 13374 : tree decl = lookup_name (name);
11761 : 13374 : tree last_parm
11762 : 13374 : = tree_last (DECL_ARGUMENTS (current_function_decl));
11763 : 13374 : if (!last_parm || decl != last_parm)
11764 : 4 : warning_at (nloc, OPT_Wvarargs,
11765 : : "optional second parameter of %<va_start%> "
11766 : : "not last named argument");
11767 : 13370 : else if (DECL_REGISTER (decl))
11768 : 2 : warning_at (nloc, OPT_Wvarargs,
11769 : : "undefined behavior when second parameter "
11770 : : "of %<va_start%> is declared with "
11771 : : "%<register%> storage");
11772 : 13374 : c_parser_consume_token (parser);
11773 : : }
11774 : : else
11775 : : {
11776 : 26 : unsigned nesting_depth = 0;
11777 : 26 : location_t sloc = c_parser_peek_token (parser)->location;
11778 : 26 : location_t eloc = sloc;
11779 : :
11780 : : /* For va_start (ap,) the ) comes from stdarg.h.
11781 : : Use location of , in that case, otherwise without
11782 : : -Wsystem-headers nothing is reported. After all,
11783 : : the problematic token is the comma in that case. */
11784 : 26 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11785 : 1 : sloc = eloc = cloc;
11786 : 492 : while (true)
11787 : : {
11788 : 259 : c_token *token = c_parser_peek_token (parser);
11789 : 259 : if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
11790 : : break;
11791 : :
11792 : 233 : if (token->type == CPP_EOF)
11793 : : break;
11794 : 233 : if (token->type == CPP_OPEN_PAREN)
11795 : 8 : ++nesting_depth;
11796 : 225 : else if (token->type == CPP_CLOSE_PAREN)
11797 : 8 : --nesting_depth;
11798 : 233 : eloc = token->location;
11799 : 233 : c_parser_consume_token (parser);
11800 : 233 : }
11801 : 26 : if (sloc != eloc)
11802 : 25 : sloc = make_location (sloc, sloc, eloc);
11803 : 26 : warning_at (sloc, OPT_Wvarargs,
11804 : : "%<va_start%> macro used with additional "
11805 : : "arguments other than identifier of the "
11806 : : "last named argument");
11807 : : }
11808 : : }
11809 : 13578 : parens.skip_until_found_close (parser);
11810 : 13578 : tree fndecl = builtin_decl_explicit (BUILT_IN_VA_START);
11811 : 13578 : vec<tree, va_gc> *params;
11812 : 13578 : vec_alloc (params, 2);
11813 : 13578 : params->quick_push (e1.value);
11814 : 13578 : params->quick_push (integer_zero_node);
11815 : 13578 : auto_vec<location_t> arg_loc (2);
11816 : 13578 : arg_loc.quick_push (e1.get_location ());
11817 : 13578 : arg_loc.quick_push (UNKNOWN_LOCATION);
11818 : 13578 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
11819 : : params, NULL);
11820 : 13578 : set_c_expr_source_range (&expr, loc,
11821 : : parser->tokens_buf[0].get_finish ());
11822 : 13578 : expr.m_decimal = 0;
11823 : 13578 : expr.original_code = ERROR_MARK;
11824 : 13578 : expr.original_type = NULL;
11825 : 13578 : release_tree_vector (params);
11826 : 13578 : break;
11827 : 13578 : }
11828 : 3603 : case RID_OFFSETOF:
11829 : 3603 : {
11830 : 3603 : c_parser_consume_token (parser);
11831 : 3603 : matching_parens parens;
11832 : 3603 : if (!parens.require_open (parser))
11833 : : {
11834 : 0 : expr.set_error ();
11835 : 1 : break;
11836 : : }
11837 : 3603 : t1 = c_parser_type_name (parser);
11838 : 3603 : if (t1 == NULL)
11839 : 0 : parser->error = true;
11840 : 3603 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11841 : 1 : gcc_assert (parser->error);
11842 : 3603 : if (parser->error)
11843 : : {
11844 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11845 : 1 : expr.set_error ();
11846 : 1 : break;
11847 : : }
11848 : 3602 : tree type = groktypename (t1, NULL, NULL);
11849 : 3602 : tree offsetof_ref;
11850 : 3602 : if (type == error_mark_node)
11851 : : offsetof_ref = error_mark_node;
11852 : : else
11853 : : {
11854 : 3601 : offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
11855 : 3601 : SET_EXPR_LOCATION (offsetof_ref, loc);
11856 : : }
11857 : : /* Parse the second argument to __builtin_offsetof. We
11858 : : must have one identifier, and beyond that we want to
11859 : : accept sub structure and sub array references. */
11860 : 3602 : if (c_parser_next_token_is (parser, CPP_NAME))
11861 : : {
11862 : 3602 : c_token *comp_tok = c_parser_peek_token (parser);
11863 : : /* Ignore the counted_by attribute for reference inside
11864 : : offsetof since the information is not useful at all. */
11865 : 3602 : offsetof_ref
11866 : 3602 : = build_component_ref (loc, offsetof_ref, comp_tok->value,
11867 : : comp_tok->location, UNKNOWN_LOCATION,
11868 : : false);
11869 : 3602 : c_parser_consume_token (parser);
11870 : 3602 : while (c_parser_next_token_is (parser, CPP_DOT)
11871 : 4060 : || c_parser_next_token_is (parser,
11872 : : CPP_OPEN_SQUARE)
11873 : 7898 : || c_parser_next_token_is (parser,
11874 : : CPP_DEREF))
11875 : : {
11876 : 693 : if (c_parser_next_token_is (parser, CPP_DEREF))
11877 : : {
11878 : 1 : loc = c_parser_peek_token (parser)->location;
11879 : 1 : offsetof_ref = build_array_ref (loc,
11880 : : offsetof_ref,
11881 : : integer_zero_node);
11882 : 1 : goto do_dot;
11883 : : }
11884 : 692 : else if (c_parser_next_token_is (parser, CPP_DOT))
11885 : : {
11886 : 235 : do_dot:
11887 : 236 : c_parser_consume_token (parser);
11888 : 236 : if (c_parser_next_token_is_not (parser,
11889 : : CPP_NAME))
11890 : : {
11891 : 0 : c_parser_error (parser, "expected identifier");
11892 : 0 : break;
11893 : : }
11894 : 236 : c_token *comp_tok = c_parser_peek_token (parser);
11895 : : /* Ignore the counted_by attribute for reference inside
11896 : : offsetof since the information is not useful. */
11897 : 236 : offsetof_ref
11898 : 236 : = build_component_ref (loc, offsetof_ref,
11899 : : comp_tok->value,
11900 : : comp_tok->location,
11901 : : UNKNOWN_LOCATION,
11902 : : false);
11903 : 236 : c_parser_consume_token (parser);
11904 : : }
11905 : : else
11906 : : {
11907 : 457 : struct c_expr ce;
11908 : 457 : tree idx;
11909 : 457 : loc = c_parser_peek_token (parser)->location;
11910 : 457 : c_parser_consume_token (parser);
11911 : 457 : ce = c_parser_expression (parser);
11912 : 457 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
11913 : 457 : idx = ce.value;
11914 : 457 : idx = c_fully_fold (idx, false, NULL);
11915 : 457 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
11916 : : "expected %<]%>");
11917 : 457 : offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
11918 : : }
11919 : : }
11920 : : }
11921 : : else
11922 : 0 : c_parser_error (parser, "expected identifier");
11923 : 3602 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11924 : 3602 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11925 : : "expected %<)%>");
11926 : 3602 : expr.value = fold_offsetof (offsetof_ref);
11927 : 3602 : set_c_expr_source_range (&expr, loc, end_loc);
11928 : : }
11929 : 3602 : break;
11930 : 1229 : case RID_CHOOSE_EXPR:
11931 : 1229 : {
11932 : 1229 : vec<c_expr_t, va_gc> *cexpr_list;
11933 : 1229 : c_expr_t *e1_p, *e2_p, *e3_p;
11934 : 1229 : tree c;
11935 : 1229 : location_t close_paren_loc;
11936 : :
11937 : 1229 : c_parser_consume_token (parser);
11938 : 1229 : if (!c_parser_get_builtin_args (parser,
11939 : : "__builtin_choose_expr",
11940 : : &cexpr_list, true,
11941 : : &close_paren_loc))
11942 : : {
11943 : 0 : expr.set_error ();
11944 : 0 : break;
11945 : : }
11946 : :
11947 : 1229 : if (vec_safe_length (cexpr_list) != 3)
11948 : : {
11949 : 0 : error_at (loc, "wrong number of arguments to "
11950 : : "%<__builtin_choose_expr%>");
11951 : 0 : expr.set_error ();
11952 : 0 : break;
11953 : : }
11954 : :
11955 : 1229 : e1_p = &(*cexpr_list)[0];
11956 : 1229 : e2_p = &(*cexpr_list)[1];
11957 : 1229 : e3_p = &(*cexpr_list)[2];
11958 : :
11959 : 1229 : c = e1_p->value;
11960 : 1229 : mark_exp_read (e2_p->value);
11961 : 1229 : mark_exp_read (e3_p->value);
11962 : 1229 : if (TREE_CODE (c) != INTEGER_CST
11963 : 1229 : || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
11964 : 7 : error_at (loc,
11965 : : "first argument to %<__builtin_choose_expr%> not"
11966 : : " a constant");
11967 : 1229 : constant_expression_warning (c);
11968 : 1229 : expr = integer_zerop (c) ? *e3_p : *e2_p;
11969 : 1229 : set_c_expr_source_range (&expr, loc, close_paren_loc);
11970 : 1229 : break;
11971 : : }
11972 : 698 : case RID_TYPES_COMPATIBLE_P:
11973 : 698 : {
11974 : 698 : c_parser_consume_token (parser);
11975 : 698 : matching_parens parens;
11976 : 698 : if (!parens.require_open (parser))
11977 : : {
11978 : 0 : expr.set_error ();
11979 : 2 : break;
11980 : : }
11981 : 698 : t1 = c_parser_type_name (parser);
11982 : 698 : if (t1 == NULL)
11983 : : {
11984 : 0 : expr.set_error ();
11985 : 0 : break;
11986 : : }
11987 : 698 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11988 : : {
11989 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11990 : 1 : expr.set_error ();
11991 : 1 : break;
11992 : : }
11993 : 697 : t2 = c_parser_type_name (parser);
11994 : 697 : if (t2 == NULL)
11995 : : {
11996 : 0 : expr.set_error ();
11997 : 0 : break;
11998 : : }
11999 : 697 : location_t close_paren_loc = c_parser_peek_token (parser)->location;
12000 : 697 : parens.skip_until_found_close (parser);
12001 : 697 : tree e1, e2;
12002 : 697 : e1 = groktypename (t1, NULL, NULL);
12003 : 697 : e2 = groktypename (t2, NULL, NULL);
12004 : 697 : if (e1 == error_mark_node || e2 == error_mark_node)
12005 : : {
12006 : 1 : expr.set_error ();
12007 : 1 : break;
12008 : : }
12009 : :
12010 : 696 : e1 = TYPE_MAIN_VARIANT (e1);
12011 : 696 : e2 = TYPE_MAIN_VARIANT (e2);
12012 : :
12013 : 696 : expr.value
12014 : 696 : = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
12015 : 696 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12016 : : }
12017 : 696 : break;
12018 : 356 : case RID_BUILTIN_TGMATH:
12019 : 356 : {
12020 : 356 : vec<c_expr_t, va_gc> *cexpr_list;
12021 : 356 : location_t close_paren_loc;
12022 : :
12023 : 356 : c_parser_consume_token (parser);
12024 : 356 : if (!c_parser_get_builtin_args (parser,
12025 : : "__builtin_tgmath",
12026 : : &cexpr_list, false,
12027 : : &close_paren_loc))
12028 : : {
12029 : 0 : expr.set_error ();
12030 : 327 : break;
12031 : : }
12032 : :
12033 : 356 : if (vec_safe_length (cexpr_list) < 3)
12034 : : {
12035 : 3 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12036 : 3 : expr.set_error ();
12037 : 3 : break;
12038 : : }
12039 : :
12040 : : unsigned int i;
12041 : : c_expr_t *p;
12042 : 2587 : FOR_EACH_VEC_ELT (*cexpr_list, i, p)
12043 : 2234 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12044 : 353 : unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1);
12045 : 353 : if (nargs == 0)
12046 : : {
12047 : 4 : expr.set_error ();
12048 : 4 : break;
12049 : : }
12050 : 698 : if (vec_safe_length (cexpr_list) < nargs)
12051 : : {
12052 : 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12053 : 1 : expr.set_error ();
12054 : 1 : break;
12055 : : }
12056 : 348 : unsigned int num_functions = vec_safe_length (cexpr_list) - nargs;
12057 : 348 : if (num_functions < 2)
12058 : : {
12059 : 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12060 : 1 : expr.set_error ();
12061 : 1 : break;
12062 : : }
12063 : :
12064 : : /* The first NUM_FUNCTIONS expressions are the function
12065 : : pointers. The remaining NARGS expressions are the
12066 : : arguments that are to be passed to one of those
12067 : : functions, chosen following <tgmath.h> rules. */
12068 : 1744 : for (unsigned int j = 1; j < num_functions; j++)
12069 : : {
12070 : 1402 : unsigned int this_nargs
12071 : 1402 : = check_tgmath_function (&(*cexpr_list)[j], j + 1);
12072 : 1402 : if (this_nargs == 0)
12073 : : {
12074 : 4 : expr.set_error ();
12075 : 29 : goto out;
12076 : : }
12077 : 1398 : if (this_nargs != nargs)
12078 : : {
12079 : 1 : error_at ((*cexpr_list)[j].get_location (),
12080 : : "argument %u of %<__builtin_tgmath%> has "
12081 : : "wrong number of arguments", j + 1);
12082 : 1 : expr.set_error ();
12083 : 1 : goto out;
12084 : : }
12085 : : }
12086 : :
12087 : : /* The functions all have the same number of arguments.
12088 : : Determine whether arguments and return types vary in
12089 : : ways permitted for <tgmath.h> functions. */
12090 : : /* The first entry in each of these vectors is for the
12091 : : return type, subsequent entries for parameter
12092 : : types. */
12093 : 342 : auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
12094 : 342 : auto_vec<tree> parm_first (nargs + 1);
12095 : 342 : auto_vec<bool> parm_complex (nargs + 1);
12096 : 342 : auto_vec<bool> parm_varies (nargs + 1);
12097 : 342 : tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
12098 : 342 : tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
12099 : 342 : parm_first.quick_push (first_ret);
12100 : 342 : parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
12101 : 342 : parm_varies.quick_push (false);
12102 : 342 : function_args_iterator iter;
12103 : 342 : tree t;
12104 : 342 : unsigned int argpos;
12105 : 802 : FOREACH_FUNCTION_ARGS (first_type, t, iter)
12106 : : {
12107 : 802 : if (t == void_type_node)
12108 : : break;
12109 : 460 : parm_first.quick_push (TYPE_MAIN_VARIANT (t));
12110 : 460 : parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
12111 : 460 : parm_varies.quick_push (false);
12112 : : }
12113 : 1727 : for (unsigned int j = 1; j < num_functions; j++)
12114 : : {
12115 : 1397 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12116 : 1397 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12117 : 1397 : if (ret != parm_first[0])
12118 : : {
12119 : 1294 : parm_varies[0] = true;
12120 : 1294 : if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
12121 : 1294 : && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
12122 : : {
12123 : 3 : error_at ((*cexpr_list)[0].get_location (),
12124 : : "invalid type-generic return type for "
12125 : : "argument %u of %<__builtin_tgmath%>",
12126 : : 1);
12127 : 3 : expr.set_error ();
12128 : 3 : goto out;
12129 : : }
12130 : 1291 : if (!SCALAR_FLOAT_TYPE_P (ret)
12131 : 1291 : && !COMPLEX_FLOAT_TYPE_P (ret))
12132 : : {
12133 : 3 : error_at ((*cexpr_list)[j].get_location (),
12134 : : "invalid type-generic return type for "
12135 : : "argument %u of %<__builtin_tgmath%>",
12136 : : j + 1);
12137 : 3 : expr.set_error ();
12138 : 3 : goto out;
12139 : : }
12140 : : }
12141 : 1391 : if (TREE_CODE (ret) == COMPLEX_TYPE)
12142 : 342 : parm_complex[0] = true;
12143 : 1391 : argpos = 1;
12144 : 3329 : FOREACH_FUNCTION_ARGS (type, t, iter)
12145 : : {
12146 : 3329 : if (t == void_type_node)
12147 : : break;
12148 : 1944 : t = TYPE_MAIN_VARIANT (t);
12149 : 1944 : if (t != parm_first[argpos])
12150 : : {
12151 : 1919 : parm_varies[argpos] = true;
12152 : 1919 : if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
12153 : 1919 : && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
12154 : : {
12155 : 3 : error_at ((*cexpr_list)[0].get_location (),
12156 : : "invalid type-generic type for "
12157 : : "argument %u of argument %u of "
12158 : : "%<__builtin_tgmath%>", argpos, 1);
12159 : 3 : expr.set_error ();
12160 : 3 : goto out;
12161 : : }
12162 : 1916 : if (!SCALAR_FLOAT_TYPE_P (t)
12163 : 1916 : && !COMPLEX_FLOAT_TYPE_P (t))
12164 : : {
12165 : 3 : error_at ((*cexpr_list)[j].get_location (),
12166 : : "invalid type-generic type for "
12167 : : "argument %u of argument %u of "
12168 : : "%<__builtin_tgmath%>", argpos, j + 1);
12169 : 3 : expr.set_error ();
12170 : 3 : goto out;
12171 : : }
12172 : : }
12173 : 1938 : if (TREE_CODE (t) == COMPLEX_TYPE)
12174 : 674 : parm_complex[argpos] = true;
12175 : 1938 : argpos++;
12176 : : }
12177 : : }
12178 : : enum tgmath_parm_kind max_variation = tgmath_fixed;
12179 : 1108 : for (unsigned int j = 0; j <= nargs; j++)
12180 : : {
12181 : 778 : enum tgmath_parm_kind this_kind;
12182 : 778 : if (parm_varies[j])
12183 : : {
12184 : 731 : if (parm_complex[j])
12185 : 394 : max_variation = this_kind = tgmath_complex;
12186 : : else
12187 : : {
12188 : 337 : this_kind = tgmath_real;
12189 : 337 : if (max_variation != tgmath_complex)
12190 : 778 : max_variation = tgmath_real;
12191 : : }
12192 : : }
12193 : : else
12194 : 47 : this_kind = tgmath_fixed;
12195 : 778 : parm_kind.quick_push (this_kind);
12196 : : }
12197 : 330 : if (max_variation == tgmath_fixed)
12198 : : {
12199 : 1 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12200 : : "all have the same type");
12201 : 1 : expr.set_error ();
12202 : 1 : break;
12203 : : }
12204 : :
12205 : : /* Identify a parameter (not the return type) that varies,
12206 : : including with complex types if any variation includes
12207 : : complex types; there must be at least one such
12208 : : parameter. */
12209 : 341 : unsigned int tgarg = 0;
12210 : 341 : for (unsigned int j = 1; j <= nargs; j++)
12211 : 339 : if (parm_kind[j] == max_variation)
12212 : : {
12213 : : tgarg = j;
12214 : : break;
12215 : : }
12216 : 329 : if (tgarg == 0)
12217 : : {
12218 : 2 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12219 : : "lack type-generic parameter");
12220 : 2 : expr.set_error ();
12221 : 2 : break;
12222 : : }
12223 : :
12224 : : /* Determine the type of the relevant parameter for each
12225 : : function. */
12226 : 327 : auto_vec<tree> tg_type (num_functions);
12227 : 2035 : for (unsigned int j = 0; j < num_functions; j++)
12228 : : {
12229 : 1708 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12230 : 1708 : argpos = 1;
12231 : 1738 : FOREACH_FUNCTION_ARGS (type, t, iter)
12232 : : {
12233 : 1738 : if (argpos == tgarg)
12234 : : {
12235 : 1708 : tg_type.quick_push (TYPE_MAIN_VARIANT (t));
12236 : 1708 : break;
12237 : : }
12238 : 30 : argpos++;
12239 : : }
12240 : : }
12241 : :
12242 : : /* Verify that the corresponding types are different for
12243 : : all the listed functions. Also determine whether all
12244 : : the types are complex, whether all the types are
12245 : : standard or binary, and whether all the types are
12246 : : decimal. */
12247 : 327 : bool all_complex = true;
12248 : 327 : bool all_binary = true;
12249 : 327 : bool all_decimal = true;
12250 : 327 : hash_set<tree> tg_types;
12251 : 2687 : FOR_EACH_VEC_ELT (tg_type, i, t)
12252 : : {
12253 : 1708 : if (TREE_CODE (t) == COMPLEX_TYPE)
12254 : : all_decimal = false;
12255 : : else
12256 : : {
12257 : 1186 : all_complex = false;
12258 : 1186 : if (DECIMAL_FLOAT_TYPE_P (t))
12259 : : all_binary = false;
12260 : : else
12261 : : all_decimal = false;
12262 : : }
12263 : 1708 : if (tg_types.add (t))
12264 : : {
12265 : 1 : error_at ((*cexpr_list)[i].get_location (),
12266 : : "duplicate type-generic parameter type for "
12267 : : "function argument %u of %<__builtin_tgmath%>",
12268 : : i + 1);
12269 : 1 : expr.set_error ();
12270 : 1 : goto out;
12271 : : }
12272 : : }
12273 : :
12274 : : /* Verify that other parameters and the return type whose
12275 : : types vary have their types varying in the correct
12276 : : way. */
12277 : 2029 : for (unsigned int j = 0; j < num_functions; j++)
12278 : : {
12279 : 1705 : tree exp_type = tg_type[j];
12280 : 1705 : tree exp_real_type = exp_type;
12281 : 1705 : if (TREE_CODE (exp_type) == COMPLEX_TYPE)
12282 : 522 : exp_real_type = TREE_TYPE (exp_type);
12283 : 1705 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12284 : 1705 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12285 : 2606 : if ((parm_kind[0] == tgmath_complex && ret != exp_type)
12286 : 2606 : || (parm_kind[0] == tgmath_real && ret != exp_real_type))
12287 : : {
12288 : 1 : error_at ((*cexpr_list)[j].get_location (),
12289 : : "bad return type for function argument %u "
12290 : : "of %<__builtin_tgmath%>", j + 1);
12291 : 1 : expr.set_error ();
12292 : 1 : goto out;
12293 : : }
12294 : 1704 : argpos = 1;
12295 : 4078 : FOREACH_FUNCTION_ARGS (type, t, iter)
12296 : : {
12297 : 4078 : if (t == void_type_node)
12298 : : break;
12299 : 2375 : t = TYPE_MAIN_VARIANT (t);
12300 : 2375 : if ((parm_kind[argpos] == tgmath_complex
12301 : 1787 : && t != exp_type)
12302 : 4162 : || (parm_kind[argpos] == tgmath_real
12303 : 558 : && t != exp_real_type))
12304 : : {
12305 : 1 : error_at ((*cexpr_list)[j].get_location (),
12306 : : "bad type for argument %u of "
12307 : : "function argument %u of "
12308 : : "%<__builtin_tgmath%>", argpos, j + 1);
12309 : 1 : expr.set_error ();
12310 : 1 : goto out;
12311 : : }
12312 : 2374 : argpos++;
12313 : : }
12314 : : }
12315 : :
12316 : : /* The functions listed are a valid set of functions for a
12317 : : <tgmath.h> macro to select between. Identify the
12318 : : matching function, if any. First, the argument types
12319 : : must be combined following <tgmath.h> rules. Integer
12320 : : types are treated as _Decimal64 if any type-generic
12321 : : argument is decimal, or if the only alternatives for
12322 : : type-generic arguments are of decimal types, and are
12323 : : otherwise treated as _Float32x (or _Complex _Float32x
12324 : : for complex integer types) if any type-generic argument
12325 : : has _FloatNx type, otherwise as double (or _Complex
12326 : : double for complex integer types). After that
12327 : : adjustment, types are combined following the usual
12328 : : arithmetic conversions. If the function only accepts
12329 : : complex arguments, a complex type is produced. */
12330 : : bool arg_complex = all_complex;
12331 : : bool arg_binary = all_binary;
12332 : : bool arg_int_decimal = all_decimal;
12333 : : bool arg_int_floatnx = false;
12334 : : bool arg_int_decimalx = false;
12335 : 756 : for (unsigned int j = 1; j <= nargs; j++)
12336 : : {
12337 : 441 : if (parm_kind[j] == tgmath_fixed)
12338 : 10 : continue;
12339 : 431 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12340 : 431 : tree type = TREE_TYPE (ce->value);
12341 : 431 : if (!INTEGRAL_TYPE_P (type)
12342 : 431 : && !SCALAR_FLOAT_TYPE_P (type)
12343 : 89 : && TREE_CODE (type) != COMPLEX_TYPE)
12344 : : {
12345 : 1 : error_at (ce->get_location (),
12346 : : "invalid type of argument %u of type-generic "
12347 : : "function", j);
12348 : 1 : expr.set_error ();
12349 : 1 : goto out;
12350 : : }
12351 : 430 : if (DECIMAL_FLOAT_TYPE_P (type))
12352 : : {
12353 : 68 : arg_int_decimal = true;
12354 : 68 : if (all_complex)
12355 : : {
12356 : 1 : error_at (ce->get_location (),
12357 : : "decimal floating-point argument %u to "
12358 : : "complex-only type-generic function", j);
12359 : 1 : expr.set_error ();
12360 : 1 : goto out;
12361 : : }
12362 : 67 : else if (all_binary)
12363 : : {
12364 : 1 : error_at (ce->get_location (),
12365 : : "decimal floating-point argument %u to "
12366 : : "binary-only type-generic function", j);
12367 : 1 : expr.set_error ();
12368 : 1 : goto out;
12369 : : }
12370 : 66 : else if (arg_complex)
12371 : : {
12372 : 1 : error_at (ce->get_location (),
12373 : : "both complex and decimal floating-point "
12374 : : "arguments to type-generic function");
12375 : 1 : expr.set_error ();
12376 : 1 : goto out;
12377 : : }
12378 : 65 : else if (arg_binary)
12379 : : {
12380 : 1 : error_at (ce->get_location (),
12381 : : "both binary and decimal floating-point "
12382 : : "arguments to type-generic function");
12383 : 1 : expr.set_error ();
12384 : 1 : goto out;
12385 : : }
12386 : : }
12387 : 362 : else if (TREE_CODE (type) == COMPLEX_TYPE)
12388 : : {
12389 : 88 : arg_complex = true;
12390 : 88 : if (COMPLEX_FLOAT_TYPE_P (type))
12391 : : arg_binary = true;
12392 : 88 : if (all_decimal)
12393 : : {
12394 : 1 : error_at (ce->get_location (),
12395 : : "complex argument %u to "
12396 : : "decimal-only type-generic function", j);
12397 : 1 : expr.set_error ();
12398 : 1 : goto out;
12399 : : }
12400 : 87 : else if (arg_int_decimal)
12401 : : {
12402 : 1 : error_at (ce->get_location (),
12403 : : "both complex and decimal floating-point "
12404 : : "arguments to type-generic function");
12405 : 1 : expr.set_error ();
12406 : 1 : goto out;
12407 : : }
12408 : : }
12409 : 274 : else if (SCALAR_FLOAT_TYPE_P (type))
12410 : : {
12411 : 180 : arg_binary = true;
12412 : 180 : if (all_decimal)
12413 : : {
12414 : 1 : error_at (ce->get_location (),
12415 : : "binary argument %u to "
12416 : : "decimal-only type-generic function", j);
12417 : 1 : expr.set_error ();
12418 : 1 : goto out;
12419 : : }
12420 : 179 : else if (arg_int_decimal)
12421 : : {
12422 : 1 : error_at (ce->get_location (),
12423 : : "both binary and decimal floating-point "
12424 : : "arguments to type-generic function");
12425 : 1 : expr.set_error ();
12426 : 1 : goto out;
12427 : : }
12428 : : }
12429 : 422 : tree rtype = TYPE_MAIN_VARIANT (type);
12430 : 422 : if (TREE_CODE (rtype) == COMPLEX_TYPE)
12431 : 86 : rtype = TREE_TYPE (rtype);
12432 : 422 : if (SCALAR_FLOAT_TYPE_P (rtype))
12433 : 1208 : for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
12434 : 908 : if (rtype == FLOATNX_TYPE_NODE (j))
12435 : : {
12436 : : arg_int_floatnx = true;
12437 : : break;
12438 : : }
12439 : 422 : if (rtype == dfloat64x_type_node)
12440 : 0 : arg_int_decimalx = true;
12441 : : }
12442 : : tree arg_real = NULL_TREE;
12443 : 743 : for (unsigned int j = 1; j <= nargs; j++)
12444 : : {
12445 : 428 : if (parm_kind[j] == tgmath_fixed)
12446 : 10 : continue;
12447 : 418 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12448 : 418 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
12449 : 418 : if (TREE_CODE (type) == COMPLEX_TYPE)
12450 : 85 : type = TREE_TYPE (type);
12451 : 418 : if (INTEGRAL_TYPE_P (type))
12452 : 114 : type = (arg_int_decimalx
12453 : 114 : ? dfloat64x_type_node
12454 : : : arg_int_floatnx
12455 : 114 : ? float32x_type_node
12456 : : : arg_int_decimal
12457 : 106 : ? dfloat64_type_node
12458 : : : double_type_node);
12459 : 418 : if (arg_real == NULL_TREE)
12460 : : arg_real = type;
12461 : : else
12462 : 103 : arg_real = common_type (arg_real, type);
12463 : 418 : if (arg_real == error_mark_node)
12464 : : {
12465 : 0 : expr.set_error ();
12466 : 0 : goto out;
12467 : : }
12468 : : }
12469 : 315 : tree arg_type = (arg_complex
12470 : 315 : ? build_complex_type (arg_real)
12471 : : : arg_real);
12472 : :
12473 : : /* Look for a function to call with type-generic parameter
12474 : : type ARG_TYPE. */
12475 : 315 : c_expr_t *fn = NULL;
12476 : 976 : for (unsigned int j = 0; j < num_functions; j++)
12477 : : {
12478 : 970 : if (tg_type[j] == arg_type)
12479 : : {
12480 : 309 : fn = &(*cexpr_list)[j];
12481 : 309 : break;
12482 : : }
12483 : : }
12484 : 315 : if (fn == NULL
12485 : 6 : && parm_kind[0] == tgmath_fixed
12486 : 4 : && SCALAR_FLOAT_TYPE_P (parm_first[0]))
12487 : : {
12488 : : /* Presume this is a macro that rounds its result to a
12489 : : narrower type, and look for the first function with
12490 : : at least the range and precision of the argument
12491 : : type. */
12492 : 4 : for (unsigned int j = 0; j < num_functions; j++)
12493 : : {
12494 : 8 : if (arg_complex
12495 : 4 : != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
12496 : 0 : continue;
12497 : 4 : tree real_tg_type = (arg_complex
12498 : 4 : ? TREE_TYPE (tg_type[j])
12499 : 0 : : tg_type[j]);
12500 : 8 : if (DECIMAL_FLOAT_TYPE_P (arg_real)
12501 : 4 : != DECIMAL_FLOAT_TYPE_P (real_tg_type))
12502 : 0 : continue;
12503 : 4 : scalar_float_mode arg_mode
12504 : 4 : = SCALAR_FLOAT_TYPE_MODE (arg_real);
12505 : 4 : scalar_float_mode tg_mode
12506 : 4 : = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
12507 : 4 : const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
12508 : 4 : const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
12509 : 4 : if (arg_fmt->b == tg_fmt->b
12510 : 4 : && arg_fmt->p <= tg_fmt->p
12511 : 4 : && arg_fmt->emax <= tg_fmt->emax
12512 : 4 : && (arg_fmt->emin - arg_fmt->p
12513 : 4 : >= tg_fmt->emin - tg_fmt->p))
12514 : : {
12515 : 4 : fn = &(*cexpr_list)[j];
12516 : 4 : break;
12517 : : }
12518 : : }
12519 : : }
12520 : 315 : if (fn == NULL)
12521 : : {
12522 : 2 : error_at (loc, "no matching function for type-generic call");
12523 : 2 : expr.set_error ();
12524 : 2 : break;
12525 : : }
12526 : :
12527 : : /* Construct a call to FN. */
12528 : 313 : vec<tree, va_gc> *args;
12529 : 313 : vec_alloc (args, nargs);
12530 : 313 : vec<tree, va_gc> *origtypes;
12531 : 313 : vec_alloc (origtypes, nargs);
12532 : 313 : auto_vec<location_t> arg_loc (nargs);
12533 : 739 : for (unsigned int j = 0; j < nargs; j++)
12534 : : {
12535 : 426 : c_expr_t *ce = &(*cexpr_list)[num_functions + j];
12536 : 426 : args->quick_push (ce->value);
12537 : 426 : arg_loc.quick_push (ce->get_location ());
12538 : 426 : origtypes->quick_push (ce->original_type);
12539 : : }
12540 : 313 : expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
12541 : : args, origtypes);
12542 : 313 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12543 : 313 : break;
12544 : 982 : }
12545 : 22 : case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
12546 : 22 : {
12547 : 22 : vec<c_expr_t, va_gc> *cexpr_list;
12548 : 22 : c_expr_t *e2_p;
12549 : 22 : tree chain_value;
12550 : 22 : location_t close_paren_loc;
12551 : :
12552 : 22 : c_parser_consume_token (parser);
12553 : 22 : if (!c_parser_get_builtin_args (parser,
12554 : : "__builtin_call_with_static_chain",
12555 : : &cexpr_list, false,
12556 : : &close_paren_loc))
12557 : : {
12558 : 0 : expr.set_error ();
12559 : 0 : break;
12560 : : }
12561 : 22 : if (vec_safe_length (cexpr_list) != 2)
12562 : : {
12563 : 0 : error_at (loc, "wrong number of arguments to "
12564 : : "%<__builtin_call_with_static_chain%>");
12565 : 0 : expr.set_error ();
12566 : 0 : break;
12567 : : }
12568 : :
12569 : 22 : expr = (*cexpr_list)[0];
12570 : 22 : e2_p = &(*cexpr_list)[1];
12571 : 22 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12572 : 22 : chain_value = e2_p->value;
12573 : 22 : mark_exp_read (chain_value);
12574 : :
12575 : 22 : if (TREE_CODE (expr.value) != CALL_EXPR)
12576 : 3 : error_at (loc, "first argument to "
12577 : : "%<__builtin_call_with_static_chain%> "
12578 : : "must be a call expression");
12579 : 19 : else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
12580 : 1 : error_at (loc, "second argument to "
12581 : : "%<__builtin_call_with_static_chain%> "
12582 : : "must be a pointer type");
12583 : : else
12584 : 18 : CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
12585 : 22 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12586 : 22 : break;
12587 : : }
12588 : 12078 : case RID_BUILTIN_COMPLEX:
12589 : 12078 : {
12590 : 12078 : vec<c_expr_t, va_gc> *cexpr_list;
12591 : 12078 : c_expr_t *e1_p, *e2_p;
12592 : 12078 : location_t close_paren_loc;
12593 : :
12594 : 12078 : c_parser_consume_token (parser);
12595 : 12078 : if (!c_parser_get_builtin_args (parser,
12596 : : "__builtin_complex",
12597 : : &cexpr_list, false,
12598 : : &close_paren_loc))
12599 : : {
12600 : 1 : expr.set_error ();
12601 : 1 : break;
12602 : : }
12603 : :
12604 : 12077 : if (vec_safe_length (cexpr_list) != 2)
12605 : : {
12606 : 2 : error_at (loc, "wrong number of arguments to "
12607 : : "%<__builtin_complex%>");
12608 : 2 : expr.set_error ();
12609 : 2 : break;
12610 : : }
12611 : :
12612 : 12075 : e1_p = &(*cexpr_list)[0];
12613 : 12075 : e2_p = &(*cexpr_list)[1];
12614 : :
12615 : 12075 : *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
12616 : 12075 : if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
12617 : 56 : e1_p->value = convert (TREE_TYPE (e1_p->value),
12618 : 56 : TREE_OPERAND (e1_p->value, 0));
12619 : 12075 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12620 : 12075 : if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
12621 : 56 : e2_p->value = convert (TREE_TYPE (e2_p->value),
12622 : 56 : TREE_OPERAND (e2_p->value, 0));
12623 : 12075 : if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12624 : 12074 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12625 : 12073 : || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
12626 : 24147 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
12627 : : {
12628 : 3 : error_at (loc, "%<__builtin_complex%> operand "
12629 : : "not of real binary floating-point type");
12630 : 3 : expr.set_error ();
12631 : 3 : break;
12632 : : }
12633 : 12072 : if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
12634 : 12072 : != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
12635 : : {
12636 : 1 : error_at (loc,
12637 : : "%<__builtin_complex%> operands of different types");
12638 : 1 : expr.set_error ();
12639 : 1 : break;
12640 : : }
12641 : 12071 : pedwarn_c90 (loc, OPT_Wpedantic,
12642 : : "ISO C90 does not support complex types");
12643 : 12071 : expr.value = build2_loc (loc, COMPLEX_EXPR,
12644 : : build_complex_type
12645 : 12071 : (TYPE_MAIN_VARIANT
12646 : : (TREE_TYPE (e1_p->value))),
12647 : : e1_p->value, e2_p->value);
12648 : 12071 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12649 : 12071 : break;
12650 : : }
12651 : 44 : case RID_BUILTIN_COUNTED_BY_REF:
12652 : 44 : {
12653 : 44 : vec<c_expr_t, va_gc> *cexpr_list;
12654 : 44 : c_expr_t *e_p;
12655 : 44 : location_t close_paren_loc;
12656 : :
12657 : 44 : c_parser_consume_token (parser);
12658 : 44 : if (!c_parser_get_builtin_args (parser,
12659 : : "__builtin_counted_by_ref",
12660 : : &cexpr_list, false,
12661 : : &close_paren_loc))
12662 : : {
12663 : 0 : expr.set_error ();
12664 : 0 : break;
12665 : : }
12666 : 44 : if (vec_safe_length (cexpr_list) != 1)
12667 : : {
12668 : 2 : error_at (loc, "wrong number of arguments to "
12669 : : "%<__builtin_counted_by_ref%>");
12670 : 2 : expr.set_error ();
12671 : 2 : break;
12672 : : }
12673 : :
12674 : 42 : e_p = &(*cexpr_list)[0];
12675 : 42 : tree ref = e_p->value;
12676 : :
12677 : 42 : if (TREE_CODE (TREE_TYPE (ref)) != ARRAY_TYPE)
12678 : : {
12679 : 2 : error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12680 : : " must be an array");
12681 : 2 : expr.set_error ();
12682 : 2 : break;
12683 : : }
12684 : :
12685 : : /* If the array ref is inside TYPEOF or ALIGNOF, the call to
12686 : : .ACCESS_WITH_SIZE was not generated by the routine
12687 : : build_component_ref by default, we should generate it here. */
12688 : 40 : if ((in_typeof || in_alignof) && TREE_CODE (ref) == COMPONENT_REF)
12689 : 10 : ref = handle_counted_by_for_component_ref (loc, ref);
12690 : :
12691 : 40 : if (has_counted_by_object (ref))
12692 : 25 : expr.value = get_counted_by_ref (ref);
12693 : : else
12694 : 15 : expr.value = null_pointer_node;
12695 : :
12696 : 40 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12697 : 40 : break;
12698 : : }
12699 : 459654 : case RID_BUILTIN_SHUFFLE:
12700 : 459654 : {
12701 : 459654 : vec<c_expr_t, va_gc> *cexpr_list;
12702 : 459654 : unsigned int i;
12703 : 459654 : c_expr_t *p;
12704 : 459654 : location_t close_paren_loc;
12705 : :
12706 : 459654 : c_parser_consume_token (parser);
12707 : 459654 : if (!c_parser_get_builtin_args (parser,
12708 : : "__builtin_shuffle",
12709 : : &cexpr_list, false,
12710 : : &close_paren_loc))
12711 : : {
12712 : 0 : expr.set_error ();
12713 : 0 : break;
12714 : : }
12715 : :
12716 : 1420216 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12717 : 960562 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12718 : :
12719 : 459654 : if (vec_safe_length (cexpr_list) == 2)
12720 : 418400 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12721 : : NULL_TREE,
12722 : 418400 : (*cexpr_list)[1].value);
12723 : :
12724 : 41254 : else if (vec_safe_length (cexpr_list) == 3)
12725 : 41254 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12726 : 41254 : (*cexpr_list)[1].value,
12727 : 41254 : (*cexpr_list)[2].value);
12728 : : else
12729 : : {
12730 : 0 : error_at (loc, "wrong number of arguments to "
12731 : : "%<__builtin_shuffle%>");
12732 : 0 : expr.set_error ();
12733 : : }
12734 : 459654 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12735 : 459654 : break;
12736 : : }
12737 : 1052000 : case RID_BUILTIN_SHUFFLEVECTOR:
12738 : 1052000 : {
12739 : 1052000 : vec<c_expr_t, va_gc> *cexpr_list;
12740 : 1052000 : unsigned int i;
12741 : 1052000 : c_expr_t *p;
12742 : 1052000 : location_t close_paren_loc;
12743 : :
12744 : 1052000 : c_parser_consume_token (parser);
12745 : 1052000 : if (!c_parser_get_builtin_args (parser,
12746 : : "__builtin_shufflevector",
12747 : : &cexpr_list, false,
12748 : : &close_paren_loc))
12749 : : {
12750 : 0 : expr.set_error ();
12751 : 0 : break;
12752 : : }
12753 : :
12754 : 16380206 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12755 : 15328206 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12756 : :
12757 : 1052000 : if (vec_safe_length (cexpr_list) < 3)
12758 : : {
12759 : 0 : error_at (loc, "wrong number of arguments to "
12760 : : "%<__builtin_shuffle%>");
12761 : 0 : expr.set_error ();
12762 : : }
12763 : : else
12764 : : {
12765 : 1052000 : auto_vec<tree, 16> mask;
12766 : 14276206 : for (i = 2; i < cexpr_list->length (); ++i)
12767 : 13224206 : mask.safe_push ((*cexpr_list)[i].value);
12768 : 1052000 : expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
12769 : 1052000 : (*cexpr_list)[1].value,
12770 : : mask);
12771 : 1052000 : }
12772 : 1052000 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12773 : 1052000 : break;
12774 : : }
12775 : 329 : case RID_BUILTIN_CONVERTVECTOR:
12776 : 329 : {
12777 : 329 : location_t start_loc = loc;
12778 : 329 : c_parser_consume_token (parser);
12779 : 329 : matching_parens parens;
12780 : 329 : if (!parens.require_open (parser))
12781 : : {
12782 : 0 : expr.set_error ();
12783 : 2 : break;
12784 : : }
12785 : 329 : e1 = c_parser_expr_no_commas (parser, NULL);
12786 : 329 : mark_exp_read (e1.value);
12787 : 329 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
12788 : : {
12789 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
12790 : 2 : expr.set_error ();
12791 : 2 : break;
12792 : : }
12793 : 327 : loc = c_parser_peek_token (parser)->location;
12794 : 327 : t1 = c_parser_type_name (parser);
12795 : 327 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12796 : 327 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
12797 : : "expected %<)%>");
12798 : 327 : if (t1 == NULL)
12799 : 1 : expr.set_error ();
12800 : : else
12801 : : {
12802 : 326 : tree type_expr = NULL_TREE;
12803 : 326 : expr.value = c_build_vec_convert (start_loc, e1.value, loc,
12804 : : groktypename (t1, &type_expr,
12805 : : NULL));
12806 : 326 : set_c_expr_source_range (&expr, start_loc, end_loc);
12807 : : }
12808 : : }
12809 : 327 : break;
12810 : 10 : case RID_BUILTIN_ASSOC_BARRIER:
12811 : 10 : {
12812 : 10 : location_t start_loc = loc;
12813 : 10 : c_parser_consume_token (parser);
12814 : 10 : matching_parens parens;
12815 : 10 : if (!parens.require_open (parser))
12816 : : {
12817 : 0 : expr.set_error ();
12818 : 0 : break;
12819 : : }
12820 : 10 : e1 = c_parser_expr_no_commas (parser, NULL);
12821 : 10 : mark_exp_read (e1.value);
12822 : 10 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12823 : 10 : parens.skip_until_found_close (parser);
12824 : 10 : expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
12825 : 10 : set_c_expr_source_range (&expr, start_loc, end_loc);
12826 : : }
12827 : 10 : break;
12828 : 1072 : case RID_BUILTIN_STDC:
12829 : 1072 : {
12830 : 1072 : vec<c_expr_t, va_gc> *cexpr_list;
12831 : 1072 : c_expr_t *arg_p;
12832 : 1072 : location_t close_paren_loc;
12833 : 1072 : enum c_builtin_stdc {
12834 : : C_BUILTIN_STDC_BIT_CEIL,
12835 : : C_BUILTIN_STDC_BIT_FLOOR,
12836 : : C_BUILTIN_STDC_BIT_WIDTH,
12837 : : C_BUILTIN_STDC_COUNT_ONES,
12838 : : C_BUILTIN_STDC_COUNT_ZEROS,
12839 : : C_BUILTIN_STDC_FIRST_LEADING_ONE,
12840 : : C_BUILTIN_STDC_FIRST_LEADING_ZERO,
12841 : : C_BUILTIN_STDC_FIRST_TRAILING_ONE,
12842 : : C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
12843 : : C_BUILTIN_STDC_HAS_SINGLE_BIT,
12844 : : C_BUILTIN_STDC_LEADING_ONES,
12845 : : C_BUILTIN_STDC_LEADING_ZEROS,
12846 : : C_BUILTIN_STDC_ROTATE_LEFT,
12847 : : C_BUILTIN_STDC_ROTATE_RIGHT,
12848 : : C_BUILTIN_STDC_TRAILING_ONES,
12849 : : C_BUILTIN_STDC_TRAILING_ZEROS,
12850 : : C_BUILTIN_STDC_MAX
12851 : 1072 : } stdc_rid = C_BUILTIN_STDC_MAX;
12852 : 1072 : const char *name
12853 : 1072 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
12854 : 1072 : unsigned num_args = 1;
12855 : 1072 : switch (name[sizeof ("__builtin_stdc_") - 1])
12856 : : {
12857 : 202 : case 'b':
12858 : 202 : switch (name[sizeof ("__builtin_stdc_bit_") - 1])
12859 : : {
12860 : : case 'c':
12861 : : stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
12862 : : break;
12863 : 64 : case 'f':
12864 : 64 : stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
12865 : 64 : break;
12866 : 58 : default:
12867 : 58 : stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
12868 : 58 : break;
12869 : : }
12870 : : break;
12871 : 106 : case 'c':
12872 : 106 : if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
12873 : : stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
12874 : : else
12875 : 53 : stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
12876 : : break;
12877 : 215 : case 'f':
12878 : 215 : switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
12879 : : {
12880 : : case 'n':
12881 : : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
12882 : : break;
12883 : : case 'e':
12884 : : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
12885 : : break;
12886 : : case 'o':
12887 : : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
12888 : : break;
12889 : : default:
12890 : : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
12891 : : break;
12892 : : }
12893 : : break;
12894 : : case 'h':
12895 : : stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
12896 : : break;
12897 : 106 : case 'l':
12898 : 106 : if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
12899 : : stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
12900 : : else
12901 : 53 : stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
12902 : : break;
12903 : 284 : case 'r':
12904 : 284 : if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l')
12905 : : stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT;
12906 : : else
12907 : 137 : stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT;
12908 : : num_args = 2;
12909 : : break;
12910 : 106 : case 't':
12911 : 106 : if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
12912 : : stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
12913 : : else
12914 : 53 : stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
12915 : : break;
12916 : : }
12917 : 281 : gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
12918 : :
12919 : 1072 : c_parser_consume_token (parser);
12920 : 1072 : if (!c_parser_get_builtin_args (parser, name,
12921 : : &cexpr_list, false,
12922 : : &close_paren_loc))
12923 : : {
12924 : 0 : expr.set_error ();
12925 : 0 : break;
12926 : : }
12927 : :
12928 : 2128 : if (vec_safe_length (cexpr_list) != num_args)
12929 : : {
12930 : 34 : error_at (loc, "wrong number of arguments to %qs", name);
12931 : 34 : expr.set_error ();
12932 : 34 : break;
12933 : : }
12934 : :
12935 : 1038 : arg_p = &(*cexpr_list)[0];
12936 : 1038 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
12937 : 1038 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
12938 : : {
12939 : 80 : error_at (loc, "%qs operand not an integral type", name);
12940 : 80 : expr.set_error ();
12941 : 80 : break;
12942 : : }
12943 : 958 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
12944 : : {
12945 : 16 : error_at (loc, "argument %u in call to function "
12946 : : "%qs has enumerated type", 1, name);
12947 : 16 : expr.set_error ();
12948 : 16 : break;
12949 : : }
12950 : 942 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
12951 : : {
12952 : 16 : error_at (loc, "argument %u in call to function "
12953 : : "%qs has boolean type", 1, name);
12954 : 16 : expr.set_error ();
12955 : 16 : break;
12956 : : }
12957 : 926 : if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
12958 : : {
12959 : 16 : error_at (loc, "argument 1 in call to function "
12960 : : "%qs has signed type", name);
12961 : 16 : expr.set_error ();
12962 : 16 : break;
12963 : : }
12964 : 910 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
12965 : 910 : == char_type_node)
12966 : : {
12967 : 16 : error_at (loc, "argument 1 in call to function "
12968 : : "%qs has %<char%> type", name);
12969 : 16 : expr.set_error ();
12970 : 16 : break;
12971 : : }
12972 : 894 : tree arg = arg_p->value;
12973 : 894 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
12974 : : /* Expand:
12975 : : __builtin_stdc_leading_zeros (arg) as
12976 : : (unsigned int) __builtin_clzg (arg, prec)
12977 : : __builtin_stdc_leading_ones (arg) as
12978 : : (unsigned int) __builtin_clzg ((type) ~arg, prec)
12979 : : __builtin_stdc_trailing_zeros (arg) as
12980 : : (unsigned int) __builtin_ctzg (arg, prec)
12981 : : __builtin_stdc_trailing_ones (arg) as
12982 : : (unsigned int) __builtin_ctzg ((type) ~arg, prec)
12983 : : __builtin_stdc_first_leading_zero (arg) as
12984 : : __builtin_clzg ((type) ~arg, -1) + 1U
12985 : : __builtin_stdc_first_leading_one (arg) as
12986 : : __builtin_clzg (arg, -1) + 1U
12987 : : __builtin_stdc_first_trailing_zero (arg) as
12988 : : __builtin_ctzg ((type) ~arg, -1) + 1U
12989 : : __builtin_stdc_first_trailing_one (arg) as
12990 : : __builtin_ctzg (arg, -1) + 1U
12991 : : __builtin_stdc_count_zeros (arg) as
12992 : : (unsigned int) __builtin_popcountg ((type) ~arg)
12993 : : __builtin_stdc_count_ones (arg) as
12994 : : (unsigned int) __builtin_popcountg (arg)
12995 : : __builtin_stdc_has_single_bit (arg) as
12996 : : (_Bool) (__builtin_popcountg (arg) == 1)
12997 : : __builtin_stdc_bit_width (arg) as
12998 : : (unsigned int) (prec - __builtin_clzg (arg, prec))
12999 : : __builtin_stdc_bit_floor (arg) as
13000 : : arg == 0 ? (type) 0
13001 : : : (type) 1 << (prec - 1 - __builtin_clzg (arg))
13002 : : __builtin_stdc_bit_ceil (arg) as
13003 : : arg <= 1 ? (type) 1
13004 : : : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
13005 : : without evaluating arg multiple times, type being
13006 : : __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
13007 : 894 : int prec = TYPE_PRECISION (type);
13008 : 894 : if (num_args == 2)
13009 : : {
13010 : : /* Expand:
13011 : : __builtin_stdc_rotate_left (arg1, arg2) as
13012 : : arg1 r<< (arg2 % prec)
13013 : : __builtin_stdc_rotate_right (arg1, arg2) as
13014 : : arg1 r>> (arg2 % prec). */
13015 : 260 : arg_p = &(*cexpr_list)[1];
13016 : 260 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13017 : 260 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13018 : : {
13019 : 10 : error_at (loc, "%qs operand not an integral type", name);
13020 : 10 : expr.set_error ();
13021 : 10 : break;
13022 : : }
13023 : 250 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13024 : : {
13025 : 2 : error_at (loc, "argument %u in call to function "
13026 : : "%qs has enumerated type", 2, name);
13027 : 2 : expr.set_error ();
13028 : 2 : break;
13029 : : }
13030 : 248 : tree arg1 = save_expr (arg);
13031 : 248 : tree arg2 = save_expr (arg_p->value);
13032 : 248 : tree_code code;
13033 : 248 : if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT)
13034 : : code = LROTATE_EXPR;
13035 : : else
13036 : 119 : code = RROTATE_EXPR;
13037 : :
13038 : 248 : if (TREE_CODE (arg2) == INTEGER_CST
13039 : 248 : && tree_int_cst_sgn (arg2) < 0)
13040 : 20 : warning_at (loc, OPT_Wshift_count_negative,
13041 : : "rotate count is negative");
13042 : :
13043 : 248 : tree instrument_expr = NULL_TREE;
13044 : 248 : if (sanitize_flags_p (SANITIZE_SHIFT))
13045 : 28 : instrument_expr = ubsan_instrument_shift (loc, code,
13046 : : arg1, arg2);
13047 : :
13048 : : /* Promote arg2 to unsigned just so that we don't
13049 : : need to deal with arg2 type not being able to represent
13050 : : prec. In the end gimplification uses unsigned int
13051 : : for all shifts/rotates anyway. */
13052 : 248 : if (TYPE_PRECISION (TREE_TYPE (arg2))
13053 : 248 : < TYPE_PRECISION (integer_type_node))
13054 : 13 : arg2 = fold_convert (unsigned_type_node, arg2);
13055 : :
13056 : 248 : if (TYPE_UNSIGNED (TREE_TYPE (arg2)))
13057 : 25 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg2),
13058 : 25 : arg2, build_int_cst (TREE_TYPE (arg2),
13059 : 25 : prec));
13060 : : else
13061 : : {
13062 : : /* When second argument is signed, just do the modulo in
13063 : : unsigned type, that results in better generated code
13064 : : (for power of 2 precisions bitwise AND). */
13065 : 223 : tree utype = c_common_unsigned_type (TREE_TYPE (arg2));
13066 : 223 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, utype,
13067 : : fold_convert (utype, arg2),
13068 : 223 : build_int_cst (utype, prec));
13069 : : }
13070 : :
13071 : : /* The middle-end isn't prepared to handle {L,R}ROTATE_EXPR
13072 : : on types without mode precision, except for large/huge
13073 : : _BitInt types. */
13074 : 248 : if (type_has_mode_precision_p (TREE_TYPE (arg1))
13075 : 248 : || (TREE_CODE (TREE_TYPE (arg1)) == BITINT_TYPE
13076 : 148 : && prec > MAX_FIXED_MODE_SIZE))
13077 : 192 : expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg1,
13078 : : arg2);
13079 : : else
13080 : : {
13081 : 56 : arg2 = save_expr (arg2);
13082 : 80 : tree t1 = build2_loc (loc, (code == LROTATE_EXPR
13083 : : ? LSHIFT_EXPR : RSHIFT_EXPR),
13084 : 56 : TREE_TYPE (arg1), arg1, arg2);
13085 : 112 : tree t2 = build2_loc (loc, MINUS_EXPR,
13086 : 56 : TREE_TYPE (arg2),
13087 : 56 : build_int_cst (TREE_TYPE (arg2),
13088 : 56 : prec), arg2);
13089 : 80 : t2 = build2_loc (loc, (code == LROTATE_EXPR
13090 : : ? RSHIFT_EXPR : LSHIFT_EXPR),
13091 : 56 : TREE_TYPE (arg1), arg1, t2);
13092 : 56 : suppress_warning (t2, OPT_Wshift_count_overflow);
13093 : 56 : tree t3 = build2_loc (loc, BIT_IOR_EXPR,
13094 : 56 : TREE_TYPE (arg1), t1, t2);
13095 : 56 : tree t4 = build2_loc (loc, NE_EXPR, boolean_type_node,
13096 : : arg2,
13097 : 56 : build_zero_cst (TREE_TYPE (arg2)));
13098 : 56 : t4 = build2_loc (loc, COMPOUND_EXPR, boolean_type_node,
13099 : : arg1, t4);
13100 : 56 : expr.value = build3_loc (loc, COND_EXPR,
13101 : 56 : TREE_TYPE (arg1), t4, t3, arg1);
13102 : : }
13103 : 248 : if (instrument_expr)
13104 : 28 : expr.value = build2_loc (loc, COMPOUND_EXPR,
13105 : 28 : TREE_TYPE (expr.value),
13106 : : instrument_expr, expr.value);
13107 : 248 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13108 : 248 : break;
13109 : : }
13110 : 634 : tree barg1 = arg;
13111 : 634 : switch (stdc_rid)
13112 : : {
13113 : 69 : case C_BUILTIN_STDC_BIT_CEIL:
13114 : 69 : arg = save_expr (arg);
13115 : 69 : barg1 = build2_loc (loc, PLUS_EXPR, type, arg,
13116 : : build_int_cst (type, -1));
13117 : 69 : break;
13118 : 53 : case C_BUILTIN_STDC_BIT_FLOOR:
13119 : 53 : barg1 = arg = save_expr (arg);
13120 : 53 : break;
13121 : 211 : case C_BUILTIN_STDC_COUNT_ZEROS:
13122 : 211 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13123 : 211 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13124 : 211 : case C_BUILTIN_STDC_LEADING_ONES:
13125 : 211 : case C_BUILTIN_STDC_TRAILING_ONES:
13126 : 211 : barg1 = build1_loc (loc, BIT_NOT_EXPR, type, arg);
13127 : 211 : break;
13128 : : default:
13129 : : break;
13130 : : }
13131 : 634 : tree barg2 = NULL_TREE;
13132 : 634 : switch (stdc_rid)
13133 : : {
13134 : 215 : case C_BUILTIN_STDC_BIT_WIDTH:
13135 : 215 : case C_BUILTIN_STDC_LEADING_ONES:
13136 : 215 : case C_BUILTIN_STDC_LEADING_ZEROS:
13137 : 215 : case C_BUILTIN_STDC_TRAILING_ONES:
13138 : 215 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13139 : 215 : barg2 = build_int_cst (integer_type_node, prec);
13140 : 215 : break;
13141 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13142 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13143 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13144 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13145 : 171 : barg2 = integer_minus_one_node;
13146 : 171 : break;
13147 : : default:
13148 : : break;
13149 : : }
13150 : 634 : tree fndecl = NULL_TREE;
13151 : 634 : switch (stdc_rid)
13152 : : {
13153 : 340 : case C_BUILTIN_STDC_BIT_CEIL:
13154 : 340 : case C_BUILTIN_STDC_BIT_FLOOR:
13155 : 340 : case C_BUILTIN_STDC_BIT_WIDTH:
13156 : 340 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13157 : 340 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13158 : 340 : case C_BUILTIN_STDC_LEADING_ONES:
13159 : 340 : case C_BUILTIN_STDC_LEADING_ZEROS:
13160 : 340 : fndecl = builtin_decl_explicit (BUILT_IN_CLZG);
13161 : 340 : break;
13162 : 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13163 : 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13164 : 168 : case C_BUILTIN_STDC_TRAILING_ONES:
13165 : 168 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13166 : 168 : fndecl = builtin_decl_explicit (BUILT_IN_CTZG);
13167 : 168 : break;
13168 : 126 : case C_BUILTIN_STDC_COUNT_ONES:
13169 : 126 : case C_BUILTIN_STDC_COUNT_ZEROS:
13170 : 126 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13171 : 126 : fndecl = builtin_decl_explicit (BUILT_IN_POPCOUNTG);
13172 : 126 : break;
13173 : 0 : default:
13174 : 0 : gcc_unreachable ();
13175 : : }
13176 : : /* Construct a call to __builtin_{clz,ctz,popcount}g. */
13177 : 634 : int nargs = barg2 != NULL_TREE ? 2 : 1;
13178 : 634 : vec<tree, va_gc> *args;
13179 : 634 : vec_alloc (args, nargs);
13180 : 634 : vec<tree, va_gc> *origtypes;
13181 : 634 : vec_alloc (origtypes, nargs);
13182 : 1268 : auto_vec<location_t> arg_loc (nargs);
13183 : 634 : args->quick_push (barg1);
13184 : 634 : arg_loc.quick_push (arg_p->get_location ());
13185 : 634 : origtypes->quick_push (arg_p->original_type);
13186 : 634 : if (nargs == 2)
13187 : : {
13188 : 386 : args->quick_push (barg2);
13189 : 386 : arg_loc.quick_push (loc);
13190 : 386 : origtypes->quick_push (integer_type_node);
13191 : : }
13192 : 634 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
13193 : : args, origtypes);
13194 : 634 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13195 : 634 : if (expr.value == error_mark_node)
13196 : : break;
13197 : 634 : switch (stdc_rid)
13198 : : {
13199 : 122 : case C_BUILTIN_STDC_BIT_CEIL:
13200 : 122 : case C_BUILTIN_STDC_BIT_FLOOR:
13201 : 122 : --prec;
13202 : : /* FALLTHRU */
13203 : 169 : case C_BUILTIN_STDC_BIT_WIDTH:
13204 : 169 : expr.value = build2_loc (loc, MINUS_EXPR, integer_type_node,
13205 : : build_int_cst (integer_type_node,
13206 : 169 : prec), expr.value);
13207 : 169 : break;
13208 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13209 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13210 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13211 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13212 : 171 : expr.value = build2_loc (loc, PLUS_EXPR, integer_type_node,
13213 : : expr.value, integer_one_node);
13214 : 171 : break;
13215 : 42 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13216 : 42 : expr.value = build2_loc (loc, EQ_EXPR, boolean_type_node,
13217 : : expr.value, integer_one_node);
13218 : 42 : break;
13219 : : default:
13220 : : break;
13221 : : }
13222 : :
13223 : 382 : if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
13224 : : && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
13225 : : {
13226 : 512 : if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
13227 : 470 : expr.value = fold_convert_loc (loc, unsigned_type_node,
13228 : : expr.value);
13229 : : break;
13230 : : }
13231 : : /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
13232 : : or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
13233 : : warnings. The LSHIFT_EXPR is in dead code in that case. */
13234 : 122 : if (integer_zerop (arg)
13235 : 122 : || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
13236 : 42 : expr.value = build_int_cst (type, 0);
13237 : : else
13238 : 80 : expr.value
13239 : 80 : = build2_loc (loc, LSHIFT_EXPR, type,
13240 : : build_int_cst (type,
13241 : : (stdc_rid
13242 : : == C_BUILTIN_STDC_BIT_CEIL
13243 : 114 : ? 2 : 1)), expr.value);
13244 : 122 : if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
13245 : 69 : expr.value = build3_loc (loc, COND_EXPR, type,
13246 : : build2_loc (loc, LE_EXPR,
13247 : : boolean_type_node, arg,
13248 : : build_int_cst (type, 1)),
13249 : : build_int_cst (type, 1),
13250 : : expr.value);
13251 : : else
13252 : 53 : expr.value = build3_loc (loc, COND_EXPR, type,
13253 : : build2_loc (loc, EQ_EXPR,
13254 : : boolean_type_node, arg,
13255 : : build_int_cst (type, 0)),
13256 : : build_int_cst (type, 0),
13257 : : expr.value);
13258 : : break;
13259 : : }
13260 : 0 : case RID_AT_SELECTOR:
13261 : 0 : {
13262 : 0 : gcc_assert (c_dialect_objc ());
13263 : 0 : c_parser_consume_token (parser);
13264 : 0 : matching_parens parens;
13265 : 0 : if (!parens.require_open (parser))
13266 : : {
13267 : 0 : expr.set_error ();
13268 : 0 : break;
13269 : : }
13270 : 0 : tree sel = c_parser_objc_selector_arg (parser);
13271 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13272 : 0 : parens.skip_until_found_close (parser);
13273 : 0 : expr.value = objc_build_selector_expr (loc, sel);
13274 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13275 : : }
13276 : 0 : break;
13277 : 0 : case RID_AT_PROTOCOL:
13278 : 0 : {
13279 : 0 : gcc_assert (c_dialect_objc ());
13280 : 0 : c_parser_consume_token (parser);
13281 : 0 : matching_parens parens;
13282 : 0 : if (!parens.require_open (parser))
13283 : : {
13284 : 0 : expr.set_error ();
13285 : 0 : break;
13286 : : }
13287 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
13288 : : {
13289 : 0 : c_parser_error (parser, "expected identifier");
13290 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13291 : 0 : expr.set_error ();
13292 : 0 : break;
13293 : : }
13294 : 0 : tree id = c_parser_peek_token (parser)->value;
13295 : 0 : c_parser_consume_token (parser);
13296 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13297 : 0 : parens.skip_until_found_close (parser);
13298 : 0 : expr.value = objc_build_protocol_expr (id);
13299 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13300 : : }
13301 : 0 : break;
13302 : 0 : case RID_AT_ENCODE:
13303 : 0 : {
13304 : : /* Extension to support C-structures in the archiver. */
13305 : 0 : gcc_assert (c_dialect_objc ());
13306 : 0 : c_parser_consume_token (parser);
13307 : 0 : matching_parens parens;
13308 : 0 : if (!parens.require_open (parser))
13309 : : {
13310 : 0 : expr.set_error ();
13311 : 0 : break;
13312 : : }
13313 : 0 : t1 = c_parser_type_name (parser);
13314 : 0 : if (t1 == NULL)
13315 : : {
13316 : 0 : expr.set_error ();
13317 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13318 : 0 : break;
13319 : : }
13320 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13321 : 0 : parens.skip_until_found_close (parser);
13322 : 0 : tree type = groktypename (t1, NULL, NULL);
13323 : 0 : expr.value = objc_build_encode_expr (type);
13324 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13325 : : }
13326 : 0 : break;
13327 : 621 : case RID_GENERIC:
13328 : 621 : expr = c_parser_generic_selection (parser);
13329 : 621 : break;
13330 : 3 : case RID_OMP_ALL_MEMORY:
13331 : 3 : gcc_assert (flag_openmp);
13332 : 3 : c_parser_consume_token (parser);
13333 : 3 : error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
13334 : : "%<depend%> clause");
13335 : 3 : expr.set_error ();
13336 : 3 : break;
13337 : : /* C23 'nullptr' literal. */
13338 : 11183 : case RID_NULLPTR:
13339 : 11183 : c_parser_consume_token (parser);
13340 : 11183 : expr.value = nullptr_node;
13341 : 11183 : set_c_expr_source_range (&expr, tok_range);
13342 : 11183 : pedwarn_c11 (loc, OPT_Wpedantic,
13343 : : "ISO C does not support %qs before C23", "nullptr");
13344 : 11183 : break;
13345 : 3712 : case RID_TRUE:
13346 : 3712 : c_parser_consume_token (parser);
13347 : 3712 : expr.value = boolean_true_node;
13348 : 3712 : set_c_expr_source_range (&expr, tok_range);
13349 : 3712 : break;
13350 : 4067 : case RID_FALSE:
13351 : 4067 : c_parser_consume_token (parser);
13352 : 4067 : expr.value = boolean_false_node;
13353 : 4067 : set_c_expr_source_range (&expr, tok_range);
13354 : 4067 : break;
13355 : 37 : default:
13356 : 37 : c_parser_error (parser, "expected expression");
13357 : 37 : expr.set_error ();
13358 : 37 : break;
13359 : : }
13360 : : break;
13361 : 2 : case CPP_OPEN_SQUARE:
13362 : 2 : if (c_dialect_objc ())
13363 : : {
13364 : 0 : tree receiver, args;
13365 : 0 : c_parser_consume_token (parser);
13366 : 0 : receiver = c_parser_objc_receiver (parser);
13367 : 0 : args = c_parser_objc_message_args (parser);
13368 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13369 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13370 : : "expected %<]%>");
13371 : 0 : expr.value = objc_build_message_expr (receiver, args);
13372 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13373 : 0 : break;
13374 : : }
13375 : : /* Else fall through to report error. */
13376 : : /* FALLTHRU */
13377 : 793 : default:
13378 : 793 : c_parser_error (parser, "expected expression");
13379 : 793 : expr.set_error ();
13380 : 793 : break;
13381 : : }
13382 : 230423289 : out:
13383 : 230423289 : return c_parser_postfix_expression_after_primary
13384 : 230423289 : (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
13385 : : }
13386 : :
13387 : : /* Parse a postfix expression after a parenthesized type name: the
13388 : : brace-enclosed initializer of a compound literal, possibly followed
13389 : : by some postfix operators. This is separate because it is not
13390 : : possible to tell until after the type name whether a cast
13391 : : expression has a cast or a compound literal, or whether the operand
13392 : : of sizeof is a parenthesized type name or starts with a compound
13393 : : literal. TYPE_LOC is the location where TYPE_NAME starts--the
13394 : : location of the first token after the parentheses around the type
13395 : : name. */
13396 : :
13397 : : static struct c_expr
13398 : 897287 : c_parser_postfix_expression_after_paren_type (c_parser *parser,
13399 : : struct c_declspecs *scspecs,
13400 : : struct c_type_name *type_name,
13401 : : location_t type_loc)
13402 : : {
13403 : 897287 : tree type;
13404 : 897287 : struct c_expr init;
13405 : 897287 : bool non_const;
13406 : 897287 : struct c_expr expr;
13407 : 897287 : location_t start_loc;
13408 : 897287 : tree type_expr = NULL_TREE;
13409 : 897287 : bool type_expr_const = true;
13410 : 897287 : bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
13411 : 897287 : unsigned int underspec_state = 0;
13412 : 897287 : check_compound_literal_type (type_loc, type_name);
13413 : 897287 : rich_location richloc (line_table, type_loc);
13414 : 897287 : start_loc = c_parser_peek_token (parser)->location;
13415 : 897287 : if (constexpr_p)
13416 : : {
13417 : 232 : underspec_state = start_underspecified_init (start_loc, NULL_TREE);
13418 : : /* A constexpr compound literal is subject to the constraints on
13419 : : underspecified declarations, which may not declare tags or
13420 : : members or structures or unions; it is undefined behavior to
13421 : : declare the members of an enumeration. Where the structure,
13422 : : union or enumeration type is declared within the compound
13423 : : literal initializer, this is diagnosed elsewhere as a result
13424 : : of the above call to start_underspecified_init. Diagnose
13425 : : here the case of declaring such a type in the type specifiers
13426 : : of the compound literal. */
13427 : 232 : switch (type_name->specs->typespec_kind)
13428 : : {
13429 : 2 : case ctsk_tagfirstref:
13430 : 2 : case ctsk_tagfirstref_attrs:
13431 : 2 : error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
13432 : : type_name->specs->type);
13433 : 2 : break;
13434 : :
13435 : 4 : case ctsk_tagdef:
13436 : 4 : error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
13437 : : type_name->specs->type);
13438 : 4 : break;
13439 : :
13440 : : default:
13441 : : break;
13442 : : }
13443 : : }
13444 : 897287 : start_init (NULL_TREE, NULL,
13445 : 897287 : (global_bindings_p ()
13446 : 897037 : || (scspecs && scspecs->storage_class == csc_static)
13447 : 1794296 : || constexpr_p), constexpr_p, &richloc);
13448 : 897287 : type = groktypename (type_name, &type_expr, &type_expr_const);
13449 : 897287 : if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
13450 : : {
13451 : 9 : error_at (type_loc, "compound literal has variable size");
13452 : 9 : type = error_mark_node;
13453 : : }
13454 : 897278 : else if (TREE_CODE (type) == FUNCTION_TYPE)
13455 : : {
13456 : 3 : error_at (type_loc, "compound literal has function type");
13457 : 3 : type = error_mark_node;
13458 : : }
13459 : 897287 : if (constexpr_p && type != error_mark_node)
13460 : : {
13461 : 232 : tree type_no_array = strip_array_types (type);
13462 : : /* The type of a constexpr object must not be variably modified
13463 : : (which applies to all compound literals), volatile, atomic or
13464 : : restrict qualified or have a member with such a qualifier.
13465 : : const qualification is implicitly added. */
13466 : 232 : if (TYPE_QUALS (type_no_array)
13467 : 232 : & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
13468 : 9 : error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
13469 : 223 : else if (RECORD_OR_UNION_TYPE_P (type_no_array)
13470 : 223 : && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
13471 : 8 : error_at (type_loc, "invalid qualifiers for field of "
13472 : : "%<constexpr%> object");
13473 : 464 : type = c_build_qualified_type (type,
13474 : 232 : (TYPE_QUALS (type_no_array)
13475 : : | TYPE_QUAL_CONST));
13476 : : }
13477 : 897287 : init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE);
13478 : 897287 : if (constexpr_p)
13479 : 232 : finish_underspecified_init (NULL_TREE, underspec_state);
13480 : 897287 : finish_init ();
13481 : 897287 : maybe_warn_string_init (type_loc, type, init);
13482 : :
13483 : 897287 : if (type != error_mark_node
13484 : 897271 : && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
13485 : 897287 : && current_function_decl)
13486 : : {
13487 : 0 : error ("compound literal qualified by address-space qualifier");
13488 : 0 : type = error_mark_node;
13489 : : }
13490 : :
13491 : 1794290 : if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
13492 : 897287 : "ISO C90 forbids compound literals") && scspecs)
13493 : 284 : pedwarn_c11 (start_loc, OPT_Wpedantic,
13494 : : "ISO C forbids storage class specifiers in compound literals "
13495 : : "before C23");
13496 : 897287 : non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
13497 : 1794123 : ? CONSTRUCTOR_NON_CONST (init.value)
13498 : 451 : : init.original_code == C_MAYBE_CONST_EXPR);
13499 : 897287 : non_const |= !type_expr_const;
13500 : 897287 : unsigned int alignas_align = 0;
13501 : 897287 : if (type != error_mark_node
13502 : 897271 : && type_name->specs->align_log != -1)
13503 : : {
13504 : 4 : alignas_align = 1U << type_name->specs->align_log;
13505 : 4 : if (alignas_align < min_align_of_type (type))
13506 : : {
13507 : 1 : error_at (type_name->specs->locations[cdw_alignas],
13508 : : "%<_Alignas%> specifiers cannot reduce "
13509 : : "alignment of compound literal");
13510 : 1 : alignas_align = 0;
13511 : : }
13512 : : }
13513 : 897287 : expr.value = build_compound_literal (start_loc, type, init.value, non_const,
13514 : : alignas_align, scspecs);
13515 : 897287 : set_c_expr_source_range (&expr, init.src_range);
13516 : 897287 : expr.m_decimal = 0;
13517 : 897287 : expr.original_code = ERROR_MARK;
13518 : 897287 : expr.original_type = NULL;
13519 : 897287 : if (type != error_mark_node
13520 : 897271 : && expr.value != error_mark_node
13521 : 897199 : && type_expr)
13522 : : {
13523 : 30 : if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
13524 : : {
13525 : 18 : gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
13526 : 18 : C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
13527 : : }
13528 : : else
13529 : : {
13530 : 12 : gcc_assert (!non_const);
13531 : 12 : expr.value = build2 (C_MAYBE_CONST_EXPR, type,
13532 : : type_expr, expr.value);
13533 : : }
13534 : : }
13535 : 897287 : return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
13536 : 897287 : }
13537 : :
13538 : : /* Callback function for sizeof_pointer_memaccess_warning to compare
13539 : : types. */
13540 : :
13541 : : static bool
13542 : 3456 : sizeof_ptr_memacc_comptypes (tree type1, tree type2)
13543 : : {
13544 : 3456 : return comptypes (type1, type2) == 1;
13545 : : }
13546 : :
13547 : : /* Warn for patterns where abs-like function appears to be used incorrectly,
13548 : : gracefully ignore any non-abs-like function. The warning location should
13549 : : be LOC. FNDECL is the declaration of called function, it must be a
13550 : : BUILT_IN_NORMAL function. ARG is the first and only argument of the
13551 : : call. */
13552 : :
13553 : : static void
13554 : 57387 : warn_for_abs (location_t loc, tree fndecl, tree arg)
13555 : : {
13556 : : /* Avoid warning in unreachable subexpressions. */
13557 : 57387 : if (c_inhibit_evaluation_warnings)
13558 : : return;
13559 : :
13560 : 31049 : tree atype = TREE_TYPE (arg);
13561 : :
13562 : : /* Casts from pointers (and thus arrays and fndecls) will generate
13563 : : -Wint-conversion warnings. Most other wrong types hopefully lead to type
13564 : : mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
13565 : : types and possibly other exotic types. */
13566 : 31049 : if (!INTEGRAL_TYPE_P (atype)
13567 : 31049 : && !SCALAR_FLOAT_TYPE_P (atype)
13568 : 5123 : && TREE_CODE (atype) != COMPLEX_TYPE)
13569 : : return;
13570 : :
13571 : 26404 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13572 : :
13573 : 26404 : switch (fcode)
13574 : : {
13575 : 35 : case BUILT_IN_ABS:
13576 : 35 : case BUILT_IN_LABS:
13577 : 35 : case BUILT_IN_LLABS:
13578 : 35 : case BUILT_IN_IMAXABS:
13579 : 35 : if (!INTEGRAL_TYPE_P (atype))
13580 : : {
13581 : 4 : if (SCALAR_FLOAT_TYPE_P (atype))
13582 : 3 : warning_at (loc, OPT_Wabsolute_value,
13583 : : "using integer absolute value function %qD when "
13584 : : "argument is of floating-point type %qT",
13585 : : fndecl, atype);
13586 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13587 : 1 : warning_at (loc, OPT_Wabsolute_value,
13588 : : "using integer absolute value function %qD when "
13589 : : "argument is of complex type %qT", fndecl, atype);
13590 : : else
13591 : : gcc_unreachable ();
13592 : 4 : return;
13593 : : }
13594 : 31 : if (TYPE_UNSIGNED (atype))
13595 : 9 : warning_at (loc, OPT_Wabsolute_value,
13596 : : "taking the absolute value of unsigned type %qT "
13597 : : "has no effect", atype);
13598 : : break;
13599 : :
13600 : 334 : CASE_FLT_FN (BUILT_IN_FABS):
13601 : 334 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
13602 : 334 : if (!SCALAR_FLOAT_TYPE_P (atype)
13603 : 334 : || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
13604 : : {
13605 : 4 : if (INTEGRAL_TYPE_P (atype))
13606 : 2 : warning_at (loc, OPT_Wabsolute_value,
13607 : : "using floating-point absolute value function %qD "
13608 : : "when argument is of integer type %qT", fndecl, atype);
13609 : 2 : else if (DECIMAL_FLOAT_TYPE_P (atype))
13610 : 1 : warning_at (loc, OPT_Wabsolute_value,
13611 : : "using floating-point absolute value function %qD "
13612 : : "when argument is of decimal floating-point type %qT",
13613 : : fndecl, atype);
13614 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13615 : 1 : warning_at (loc, OPT_Wabsolute_value,
13616 : : "using floating-point absolute value function %qD when "
13617 : : "argument is of complex type %qT", fndecl, atype);
13618 : : else
13619 : 0 : gcc_unreachable ();
13620 : 4 : return;
13621 : : }
13622 : : break;
13623 : :
13624 : 7 : CASE_FLT_FN (BUILT_IN_CABS):
13625 : 7 : if (TREE_CODE (atype) != COMPLEX_TYPE)
13626 : : {
13627 : 4 : if (INTEGRAL_TYPE_P (atype))
13628 : 2 : warning_at (loc, OPT_Wabsolute_value,
13629 : : "using complex absolute value function %qD when "
13630 : : "argument is of integer type %qT", fndecl, atype);
13631 : 2 : else if (SCALAR_FLOAT_TYPE_P (atype))
13632 : 2 : warning_at (loc, OPT_Wabsolute_value,
13633 : : "using complex absolute value function %qD when "
13634 : : "argument is of floating-point type %qT",
13635 : : fndecl, atype);
13636 : : else
13637 : : gcc_unreachable ();
13638 : :
13639 : 4 : return;
13640 : : }
13641 : : break;
13642 : :
13643 : 6 : case BUILT_IN_FABSD32:
13644 : 6 : case BUILT_IN_FABSD64:
13645 : 6 : case BUILT_IN_FABSD128:
13646 : 6 : case BUILT_IN_FABSD64X:
13647 : 6 : if (!DECIMAL_FLOAT_TYPE_P (atype))
13648 : : {
13649 : 4 : if (INTEGRAL_TYPE_P (atype))
13650 : 1 : warning_at (loc, OPT_Wabsolute_value,
13651 : : "using decimal floating-point absolute value "
13652 : : "function %qD when argument is of integer type %qT",
13653 : : fndecl, atype);
13654 : 3 : else if (SCALAR_FLOAT_TYPE_P (atype))
13655 : 2 : warning_at (loc, OPT_Wabsolute_value,
13656 : : "using decimal floating-point absolute value "
13657 : : "function %qD when argument is of floating-point "
13658 : : "type %qT", fndecl, atype);
13659 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13660 : 1 : warning_at (loc, OPT_Wabsolute_value,
13661 : : "using decimal floating-point absolute value "
13662 : : "function %qD when argument is of complex type %qT",
13663 : : fndecl, atype);
13664 : : else
13665 : 0 : gcc_unreachable ();
13666 : 4 : return;
13667 : : }
13668 : : break;
13669 : :
13670 : : default:
13671 : : return;
13672 : : }
13673 : :
13674 : 366 : if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13675 : : return;
13676 : :
13677 : 365 : tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13678 : 365 : if (TREE_CODE (atype) == COMPLEX_TYPE)
13679 : : {
13680 : 3 : gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
13681 : 3 : atype = TREE_TYPE (atype);
13682 : 3 : ftype = TREE_TYPE (ftype);
13683 : : }
13684 : :
13685 : 365 : if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
13686 : 9 : warning_at (loc, OPT_Wabsolute_value,
13687 : : "absolute value function %qD given an argument of type %qT "
13688 : : "but has parameter of type %qT which may cause truncation "
13689 : : "of value", fndecl, atype, ftype);
13690 : : }
13691 : :
13692 : :
13693 : : /* Parse a postfix expression after the initial primary or compound
13694 : : literal; that is, parse a series of postfix operators.
13695 : :
13696 : : EXPR_LOC is the location of the primary expression. */
13697 : :
13698 : : static struct c_expr
13699 : 231320623 : c_parser_postfix_expression_after_primary (c_parser *parser,
13700 : : location_t expr_loc,
13701 : : struct c_expr expr)
13702 : : {
13703 : 231320623 : struct c_expr orig_expr;
13704 : 231320623 : tree ident, idx, len;
13705 : 231320623 : location_t sizeof_arg_loc[6], comp_loc;
13706 : 231320623 : tree sizeof_arg[6];
13707 : 231320623 : unsigned int literal_zero_mask;
13708 : 231320623 : unsigned int i;
13709 : 231320623 : vec<tree, va_gc> *exprlist;
13710 : 231320623 : vec<tree, va_gc> *origtypes = NULL;
13711 : 231320623 : vec<location_t> arg_loc = vNULL;
13712 : 286092776 : location_t start;
13713 : 286092776 : location_t finish;
13714 : :
13715 : 286092776 : while (true)
13716 : : {
13717 : 286092776 : location_t op_loc = c_parser_peek_token (parser)->location;
13718 : 286092776 : switch (c_parser_peek_token (parser)->type)
13719 : : {
13720 : 3389210 : case CPP_OPEN_SQUARE:
13721 : : /* Array reference. */
13722 : 3389210 : c_parser_consume_token (parser);
13723 : 3389210 : idx = len = NULL_TREE;
13724 : 3389210 : if (!c_omp_array_section_p
13725 : 3389897 : || c_parser_next_token_is_not (parser, CPP_COLON))
13726 : 3389027 : idx = c_parser_expression (parser).value;
13727 : :
13728 : 3389210 : if (c_omp_array_section_p
13729 : 3389897 : && c_parser_next_token_is (parser, CPP_COLON))
13730 : : {
13731 : 560 : c_parser_consume_token (parser);
13732 : 560 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
13733 : 525 : len = c_parser_expression (parser).value;
13734 : :
13735 : 560 : expr.value = build_omp_array_section (op_loc, expr.value, idx,
13736 : : len);
13737 : : }
13738 : : else
13739 : 3388650 : expr.value = build_array_ref (op_loc, expr.value, idx);
13740 : :
13741 : 3389210 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13742 : : "expected %<]%>");
13743 : :
13744 : 3389210 : start = expr.get_start ();
13745 : 3389210 : finish = parser->tokens_buf[0].location;
13746 : 3389210 : set_c_expr_source_range (&expr, start, finish);
13747 : 3389210 : expr.original_code = ERROR_MARK;
13748 : 3389210 : expr.original_type = NULL;
13749 : 3389210 : expr.m_decimal = 0;
13750 : 3389210 : break;
13751 : 48489495 : case CPP_OPEN_PAREN:
13752 : : /* Function call. */
13753 : 48489495 : {
13754 : 48489495 : matching_parens parens;
13755 : 48489495 : parens.consume_open (parser);
13756 : 387915960 : for (i = 0; i < 6; i++)
13757 : : {
13758 : 290936970 : sizeof_arg[i] = NULL_TREE;
13759 : 290936970 : sizeof_arg_loc[i] = UNKNOWN_LOCATION;
13760 : : }
13761 : 48489495 : literal_zero_mask = 0;
13762 : 48489495 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
13763 : : exprlist = NULL;
13764 : 37092560 : else if (TREE_CODE (expr.value) == FUNCTION_DECL
13765 : 37025626 : && fndecl_built_in_p (expr.value, BUILT_IN_CLASSIFY_TYPE)
13766 : 37094402 : && c_parser_next_tokens_start_typename (parser,
13767 : : cla_prefer_id))
13768 : : {
13769 : : /* __builtin_classify_type (type) */
13770 : 29 : c_inhibit_evaluation_warnings++;
13771 : 29 : in_alignof++;
13772 : 29 : struct c_type_name *type = c_parser_type_name (parser);
13773 : 29 : c_inhibit_evaluation_warnings--;
13774 : 29 : in_alignof--;
13775 : 29 : struct c_typespec ret;
13776 : 29 : ret.expr = NULL_TREE;
13777 : 29 : ret.spec = error_mark_node;
13778 : 29 : ret.expr_const_operands = false;
13779 : 29 : if (type != NULL)
13780 : 29 : ret.spec = groktypename (type, &ret.expr,
13781 : : &ret.expr_const_operands);
13782 : 29 : parens.skip_until_found_close (parser);
13783 : 29 : expr.value = build_int_cst (integer_type_node,
13784 : 29 : type_to_class (ret.spec));
13785 : 29 : break;
13786 : : }
13787 : : else
13788 : 37092531 : exprlist = c_parser_expr_list (parser, true, false, &origtypes,
13789 : : sizeof_arg_loc, sizeof_arg,
13790 : : &arg_loc, &literal_zero_mask);
13791 : 48489466 : parens.skip_until_found_close (parser);
13792 : : }
13793 : 48489466 : orig_expr = expr;
13794 : 48489466 : mark_exp_read (expr.value);
13795 : 48489466 : if (warn_sizeof_pointer_memaccess)
13796 : 4536101 : sizeof_pointer_memaccess_warning (sizeof_arg_loc,
13797 : : expr.value, exprlist,
13798 : : sizeof_arg,
13799 : : sizeof_ptr_memacc_comptypes);
13800 : 48489466 : if (TREE_CODE (expr.value) == FUNCTION_DECL)
13801 : : {
13802 : 48412808 : if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET)
13803 : 48443704 : && vec_safe_length (exprlist) == 3)
13804 : : {
13805 : 30896 : tree arg0 = (*exprlist)[0];
13806 : 30896 : tree arg2 = (*exprlist)[2];
13807 : 30896 : warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
13808 : : }
13809 : 48412808 : if (warn_absolute_value
13810 : 4264955 : && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL)
13811 : 48551837 : && vec_safe_length (exprlist) == 1)
13812 : 57387 : warn_for_abs (expr_loc, expr.value, (*exprlist)[0]);
13813 : 48412808 : if (parser->omp_for_parse_state
13814 : 177 : && parser->omp_for_parse_state->in_intervening_code
13815 : 48412946 : && omp_runtime_api_call (expr.value))
13816 : : {
13817 : 2 : error_at (expr_loc, "calls to the OpenMP runtime API are "
13818 : : "not permitted in intervening code");
13819 : 2 : parser->omp_for_parse_state->fail = true;
13820 : : }
13821 : 48412808 : if (warn_calloc_transposed_args)
13822 : 4264930 : if (tree attr = lookup_attribute ("alloc_size",
13823 : 4264930 : TYPE_ATTRIBUTES
13824 : : (TREE_TYPE (expr.value))))
13825 : 1259 : if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
13826 : 146 : warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
13827 : : sizeof_arg, attr);
13828 : : }
13829 : :
13830 : 48489466 : start = expr.get_start ();
13831 : 48489466 : finish = parser->tokens_buf[0].get_finish ();
13832 : 48489466 : expr.value
13833 : 48489466 : = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
13834 : : exprlist, origtypes);
13835 : 48489466 : set_c_expr_source_range (&expr, start, finish);
13836 : 48489466 : expr.m_decimal = 0;
13837 : :
13838 : 48489466 : expr.original_code = ERROR_MARK;
13839 : 48489466 : if (TREE_CODE (expr.value) == INTEGER_CST
13840 : 12675 : && TREE_CODE (orig_expr.value) == FUNCTION_DECL
13841 : 48502141 : && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P))
13842 : 1530 : expr.original_code = C_MAYBE_CONST_EXPR;
13843 : 48489466 : expr.original_type = NULL;
13844 : 48489466 : if (exprlist)
13845 : : {
13846 : 37092531 : release_tree_vector (exprlist);
13847 : 37092531 : release_tree_vector (origtypes);
13848 : : }
13849 : 48489466 : arg_loc.release ();
13850 : 48489466 : break;
13851 : 1729630 : case CPP_DOT:
13852 : : /* Structure element reference. */
13853 : 1729630 : c_parser_consume_token (parser);
13854 : 1729630 : expr = default_function_array_conversion (expr_loc, expr);
13855 : 1729630 : if (c_parser_next_token_is (parser, CPP_NAME))
13856 : : {
13857 : 1729630 : c_token *comp_tok = c_parser_peek_token (parser);
13858 : 1729630 : ident = comp_tok->value;
13859 : 1729630 : comp_loc = comp_tok->location;
13860 : : }
13861 : : else
13862 : : {
13863 : 0 : c_parser_error (parser, "expected identifier");
13864 : 0 : expr.set_error ();
13865 : 0 : expr.original_code = ERROR_MARK;
13866 : 0 : expr.original_type = NULL;
13867 : 0 : return expr;
13868 : : }
13869 : 1729630 : start = expr.get_start ();
13870 : 1729630 : finish = c_parser_peek_token (parser)->get_finish ();
13871 : 1729630 : c_parser_consume_token (parser);
13872 : 1729630 : expr.value = build_component_ref (op_loc, expr.value, ident,
13873 : : comp_loc, UNKNOWN_LOCATION);
13874 : 1729630 : set_c_expr_source_range (&expr, start, finish);
13875 : 1729630 : expr.original_code = ERROR_MARK;
13876 : 1729630 : if (TREE_CODE (expr.value) != COMPONENT_REF)
13877 : 32 : expr.original_type = NULL;
13878 : : else
13879 : : {
13880 : : /* Remember the original type of a bitfield. */
13881 : 1729598 : tree field = TREE_OPERAND (expr.value, 1);
13882 : 1729598 : if (TREE_CODE (field) != FIELD_DECL)
13883 : 0 : expr.original_type = NULL;
13884 : : else
13885 : 1729598 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
13886 : : }
13887 : 1729630 : expr.m_decimal = 0;
13888 : 1729630 : break;
13889 : 490764 : case CPP_DEREF:
13890 : : /* Structure element reference. */
13891 : 490764 : c_parser_consume_token (parser);
13892 : 490764 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
13893 : 490764 : if (c_parser_next_token_is (parser, CPP_NAME))
13894 : : {
13895 : 490732 : c_token *comp_tok = c_parser_peek_token (parser);
13896 : 490732 : ident = comp_tok->value;
13897 : 490732 : comp_loc = comp_tok->location;
13898 : : }
13899 : : else
13900 : : {
13901 : 32 : c_parser_error (parser, "expected identifier");
13902 : 32 : expr.set_error ();
13903 : 32 : expr.original_code = ERROR_MARK;
13904 : 32 : expr.original_type = NULL;
13905 : 32 : return expr;
13906 : : }
13907 : 490732 : start = expr.get_start ();
13908 : 490732 : finish = c_parser_peek_token (parser)->get_finish ();
13909 : 490732 : c_parser_consume_token (parser);
13910 : 490732 : expr.value = build_component_ref (op_loc,
13911 : : build_indirect_ref (op_loc,
13912 : : expr.value,
13913 : : RO_ARROW),
13914 : : ident, comp_loc,
13915 : : expr.get_location ());
13916 : 490732 : set_c_expr_source_range (&expr, start, finish);
13917 : 490732 : expr.original_code = ERROR_MARK;
13918 : 490732 : if (TREE_CODE (expr.value) != COMPONENT_REF)
13919 : 260 : expr.original_type = NULL;
13920 : : else
13921 : : {
13922 : : /* Remember the original type of a bitfield. */
13923 : 490472 : tree field = TREE_OPERAND (expr.value, 1);
13924 : 490472 : if (TREE_CODE (field) != FIELD_DECL)
13925 : 0 : expr.original_type = NULL;
13926 : : else
13927 : 490472 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
13928 : : }
13929 : 490732 : expr.m_decimal = 0;
13930 : 490732 : break;
13931 : 655739 : case CPP_PLUS_PLUS:
13932 : : /* Postincrement. */
13933 : 655739 : start = expr.get_start ();
13934 : 655739 : finish = c_parser_peek_token (parser)->get_finish ();
13935 : 655739 : c_parser_consume_token (parser);
13936 : 655739 : expr = default_function_array_read_conversion (expr_loc, expr);
13937 : 655739 : expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
13938 : : expr.value, false);
13939 : 655739 : set_c_expr_source_range (&expr, start, finish);
13940 : 655739 : expr.original_code = ERROR_MARK;
13941 : 655739 : expr.original_type = NULL;
13942 : 655739 : break;
13943 : 17347 : case CPP_MINUS_MINUS:
13944 : : /* Postdecrement. */
13945 : 17347 : start = expr.get_start ();
13946 : 17347 : finish = c_parser_peek_token (parser)->get_finish ();
13947 : 17347 : c_parser_consume_token (parser);
13948 : 17347 : expr = default_function_array_read_conversion (expr_loc, expr);
13949 : 17347 : expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
13950 : : expr.value, false);
13951 : 17347 : set_c_expr_source_range (&expr, start, finish);
13952 : 17347 : expr.original_code = ERROR_MARK;
13953 : 17347 : expr.original_type = NULL;
13954 : 17347 : break;
13955 : 231320591 : default:
13956 : 231320591 : return expr;
13957 : : }
13958 : : }
13959 : : }
13960 : :
13961 : : /* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
13962 : :
13963 : : expression:
13964 : : assignment-expression
13965 : : expression , assignment-expression
13966 : : */
13967 : :
13968 : : static struct c_expr
13969 : 54137266 : c_parser_expression (c_parser *parser)
13970 : : {
13971 : 54137266 : location_t tloc = c_parser_peek_token (parser)->location;
13972 : 54137266 : struct c_expr expr;
13973 : 54137266 : expr = c_parser_expr_no_commas (parser, NULL);
13974 : 54137266 : if (c_parser_next_token_is (parser, CPP_COMMA))
13975 : 86937 : expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
13976 : 54237364 : while (c_parser_next_token_is (parser, CPP_COMMA))
13977 : : {
13978 : 100098 : struct c_expr next;
13979 : 100098 : tree lhsval;
13980 : 100098 : location_t loc = c_parser_peek_token (parser)->location;
13981 : 100098 : location_t expr_loc;
13982 : 100098 : c_parser_consume_token (parser);
13983 : 100098 : expr_loc = c_parser_peek_token (parser)->location;
13984 : 100098 : lhsval = expr.value;
13985 : 100098 : while (TREE_CODE (lhsval) == COMPOUND_EXPR
13986 : 114113 : || TREE_CODE (lhsval) == NOP_EXPR)
13987 : : {
13988 : 14015 : if (TREE_CODE (lhsval) == COMPOUND_EXPR)
13989 : 13917 : lhsval = TREE_OPERAND (lhsval, 1);
13990 : : else
13991 : 98 : lhsval = TREE_OPERAND (lhsval, 0);
13992 : : }
13993 : 100098 : if (DECL_P (lhsval) || handled_component_p (lhsval))
13994 : 88 : mark_exp_read (lhsval);
13995 : 100098 : if (c_parser_next_token_is (parser, CPP_EMBED))
13996 : : {
13997 : : /* Users aren't interested in milions of -Wunused-value
13998 : : warnings when using #embed inside of a comma expression,
13999 : : and one CPP_NUMBER plus CPP_COMMA before it and one
14000 : : CPP_COMMA plus CPP_NUMBER after it is guaranteed by
14001 : : the preprocessor. Thus, parse the whole CPP_EMBED just
14002 : : as a single INTEGER_CST, the last byte in it. */
14003 : 1 : c_token *embed = c_parser_peek_token (parser);
14004 : 1 : tree val = embed->value;
14005 : 1 : unsigned last = RAW_DATA_LENGTH (val) - 1;
14006 : 1 : next.value = build_int_cst (TREE_TYPE (val),
14007 : 1 : RAW_DATA_UCHAR_ELT (val, last));
14008 : 1 : next.original_type = integer_type_node;
14009 : 1 : c_parser_consume_token (parser);
14010 : : }
14011 : : else
14012 : : {
14013 : 100097 : next = c_parser_expr_no_commas (parser, NULL);
14014 : 100097 : next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
14015 : : }
14016 : 100098 : expr.value = build_compound_expr (loc, expr.value, next.value);
14017 : 100098 : expr.original_code = COMPOUND_EXPR;
14018 : 100098 : expr.original_type = next.original_type;
14019 : 100098 : expr.m_decimal = 0;
14020 : : }
14021 : 54137266 : return expr;
14022 : : }
14023 : :
14024 : : /* Parse an expression and convert functions or arrays to pointers and
14025 : : lvalues to rvalues. */
14026 : :
14027 : : static struct c_expr
14028 : 41357195 : c_parser_expression_conv (c_parser *parser)
14029 : : {
14030 : 41357195 : struct c_expr expr;
14031 : 41357195 : location_t loc = c_parser_peek_token (parser)->location;
14032 : 41357195 : expr = c_parser_expression (parser);
14033 : 41357195 : expr = convert_lvalue_to_rvalue (loc, expr, true, false);
14034 : 41357195 : return expr;
14035 : : }
14036 : :
14037 : : /* Helper function of c_parser_expr_list. Check if IDXth (0 based)
14038 : : argument is a literal zero alone and if so, set it in literal_zero_mask. */
14039 : :
14040 : : static inline void
14041 : 122977108 : c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
14042 : : unsigned int idx)
14043 : : {
14044 : 122977108 : if (idx >= HOST_BITS_PER_INT)
14045 : : return;
14046 : :
14047 : 122955083 : c_token *tok = c_parser_peek_token (parser);
14048 : 122955083 : switch (tok->type)
14049 : : {
14050 : 6736854 : case CPP_NUMBER:
14051 : 6736854 : case CPP_CHAR:
14052 : 6736854 : case CPP_WCHAR:
14053 : 6736854 : case CPP_CHAR16:
14054 : 6736854 : case CPP_CHAR32:
14055 : 6736854 : case CPP_UTF8CHAR:
14056 : : /* If a parameter is literal zero alone, remember it
14057 : : for -Wmemset-transposed-args warning. */
14058 : 6736854 : if (integer_zerop (tok->value)
14059 : 1233716 : && !TREE_OVERFLOW (tok->value)
14060 : 7970570 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14061 : 854112 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
14062 : 1232882 : *literal_zero_mask |= 1U << idx;
14063 : : default:
14064 : : break;
14065 : : }
14066 : : }
14067 : :
14068 : : /* Parse a non-empty list of expressions. If CONVERT_P, convert
14069 : : functions and arrays to pointers and lvalues to rvalues. If
14070 : : FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
14071 : : locations of function arguments into this vector.
14072 : :
14073 : : nonempty-expr-list:
14074 : : assignment-expression
14075 : : nonempty-expr-list , assignment-expression
14076 : : */
14077 : :
14078 : : static vec<tree, va_gc> *
14079 : 41507925 : c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
14080 : : vec<tree, va_gc> **p_orig_types,
14081 : : location_t *sizeof_arg_loc, tree *sizeof_arg,
14082 : : vec<location_t> *locations,
14083 : : unsigned int *literal_zero_mask)
14084 : : {
14085 : 41507925 : vec<tree, va_gc> *ret;
14086 : 41507925 : vec<tree, va_gc> *orig_types;
14087 : 41507925 : struct c_expr expr;
14088 : 41507925 : unsigned int idx = 0;
14089 : 41507925 : bool save_c_omp_array_section_p = c_omp_array_section_p;
14090 : 41507925 : c_omp_array_section_p = false;
14091 : :
14092 : 41507925 : ret = make_tree_vector ();
14093 : 41507925 : if (p_orig_types == NULL)
14094 : 4415394 : orig_types = NULL;
14095 : : else
14096 : 37092531 : orig_types = make_tree_vector ();
14097 : :
14098 : 41507925 : if (literal_zero_mask)
14099 : 37092531 : c_parser_check_literal_zero (parser, literal_zero_mask, 0);
14100 : 41507925 : expr = c_parser_expr_no_commas (parser, NULL);
14101 : 41507925 : if (convert_p)
14102 : 37093002 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
14103 : 41507925 : if (fold_p)
14104 : 4415394 : expr.value = c_fully_fold (expr.value, false, NULL);
14105 : 41507925 : ret->quick_push (expr.value);
14106 : 41507925 : if (orig_types)
14107 : 37092531 : orig_types->quick_push (expr.original_type);
14108 : 41507925 : if (locations)
14109 : 37092531 : locations->safe_push (expr.get_location ());
14110 : 41507925 : if (sizeof_arg != NULL
14111 : 37092531 : && (expr.original_code == SIZEOF_EXPR
14112 : 37092531 : || expr.original_code == PAREN_SIZEOF_EXPR))
14113 : : {
14114 : 1970 : sizeof_arg[0] = c_last_sizeof_arg;
14115 : 1970 : sizeof_arg_loc[0] = c_last_sizeof_loc;
14116 : : }
14117 : 128711688 : while (c_parser_next_token_is (parser, CPP_COMMA))
14118 : : {
14119 : 87203763 : c_parser_consume_token (parser);
14120 : 87203763 : if (c_parser_next_token_is (parser, CPP_EMBED))
14121 : : {
14122 : 3 : c_token *embed = c_parser_peek_token (parser);
14123 : 3 : tree value = embed->value;
14124 : 3 : expr.original_code = INTEGER_CST;
14125 : 3 : expr.original_type = integer_type_node;
14126 : 3 : expr.value = NULL_TREE;
14127 : 3 : set_c_expr_source_range (&expr, embed->get_range ());
14128 : 3 : expr.m_decimal = 0;
14129 : 381 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
14130 : : {
14131 : 378 : if (literal_zero_mask
14132 : 126 : && idx + 1 < HOST_BITS_PER_INT
14133 : 409 : && RAW_DATA_POINTER (value)[i] == 0)
14134 : 0 : *literal_zero_mask |= 1U << (idx + 1);
14135 : 378 : expr.value = build_int_cst (integer_type_node,
14136 : 378 : RAW_DATA_UCHAR_ELT (value, i));
14137 : 378 : vec_safe_push (ret, expr.value);
14138 : 378 : if (orig_types)
14139 : 126 : vec_safe_push (orig_types, expr.original_type);
14140 : 378 : if (locations)
14141 : 126 : locations->safe_push (expr.get_location ());
14142 : 378 : ++idx;
14143 : : }
14144 : 3 : c_parser_consume_token (parser);
14145 : 3 : continue;
14146 : 3 : }
14147 : 87203760 : if (literal_zero_mask)
14148 : 85884577 : c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
14149 : 87203760 : expr = c_parser_expr_no_commas (parser, NULL);
14150 : 87203760 : if (convert_p)
14151 : 85884843 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
14152 : : true);
14153 : 87203760 : if (fold_p)
14154 : 1319183 : expr.value = c_fully_fold (expr.value, false, NULL);
14155 : 87203760 : vec_safe_push (ret, expr.value);
14156 : 87203760 : if (orig_types)
14157 : 85884577 : vec_safe_push (orig_types, expr.original_type);
14158 : 87203760 : if (locations)
14159 : 85884577 : locations->safe_push (expr.get_location ());
14160 : 87203760 : if (++idx < 6
14161 : 85682788 : && sizeof_arg != NULL
14162 : 87203760 : && (expr.original_code == SIZEOF_EXPR
14163 : 84363619 : || expr.original_code == PAREN_SIZEOF_EXPR))
14164 : : {
14165 : 78898 : sizeof_arg[idx] = c_last_sizeof_arg;
14166 : 78898 : sizeof_arg_loc[idx] = c_last_sizeof_loc;
14167 : : }
14168 : : }
14169 : 41507925 : if (orig_types)
14170 : 37092531 : *p_orig_types = orig_types;
14171 : 41507925 : c_omp_array_section_p = save_c_omp_array_section_p;
14172 : 41507925 : return ret;
14173 : : }
14174 : :
14175 : : /* Parse Objective-C-specific constructs. */
14176 : :
14177 : : /* Parse an objc-class-definition.
14178 : :
14179 : : objc-class-definition:
14180 : : @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
14181 : : objc-class-instance-variables[opt] objc-methodprotolist @end
14182 : : @implementation identifier objc-superclass[opt]
14183 : : objc-class-instance-variables[opt]
14184 : : @interface identifier ( identifier ) objc-protocol-refs[opt]
14185 : : objc-methodprotolist @end
14186 : : @interface identifier ( ) objc-protocol-refs[opt]
14187 : : objc-methodprotolist @end
14188 : : @implementation identifier ( identifier )
14189 : :
14190 : : objc-superclass:
14191 : : : identifier
14192 : :
14193 : : "@interface identifier (" must start "@interface identifier (
14194 : : identifier ) ...": objc-methodprotolist in the first production may
14195 : : not start with a parenthesized identifier as a declarator of a data
14196 : : definition with no declaration specifiers if the objc-superclass,
14197 : : objc-protocol-refs and objc-class-instance-variables are omitted. */
14198 : :
14199 : : static void
14200 : 0 : c_parser_objc_class_definition (c_parser *parser, tree attributes)
14201 : : {
14202 : 0 : bool iface_p;
14203 : 0 : tree id1;
14204 : 0 : tree superclass;
14205 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
14206 : : iface_p = true;
14207 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
14208 : : iface_p = false;
14209 : : else
14210 : 0 : gcc_unreachable ();
14211 : :
14212 : 0 : c_parser_consume_token (parser);
14213 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14214 : : {
14215 : 0 : c_parser_error (parser, "expected identifier");
14216 : 0 : return;
14217 : : }
14218 : 0 : id1 = c_parser_peek_token (parser)->value;
14219 : 0 : location_t loc1 = c_parser_peek_token (parser)->location;
14220 : 0 : c_parser_consume_token (parser);
14221 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14222 : : {
14223 : : /* We have a category or class extension. */
14224 : 0 : tree id2;
14225 : 0 : tree proto = NULL_TREE;
14226 : 0 : matching_parens parens;
14227 : 0 : parens.consume_open (parser);
14228 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14229 : : {
14230 : 0 : if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
14231 : : {
14232 : : /* We have a class extension. */
14233 : : id2 = NULL_TREE;
14234 : : }
14235 : : else
14236 : : {
14237 : 0 : c_parser_error (parser, "expected identifier or %<)%>");
14238 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
14239 : 0 : return;
14240 : : }
14241 : : }
14242 : : else
14243 : : {
14244 : 0 : id2 = c_parser_peek_token (parser)->value;
14245 : 0 : c_parser_consume_token (parser);
14246 : : }
14247 : 0 : parens.skip_until_found_close (parser);
14248 : 0 : if (!iface_p)
14249 : : {
14250 : 0 : objc_start_category_implementation (id1, id2);
14251 : 0 : return;
14252 : : }
14253 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14254 : 0 : proto = c_parser_objc_protocol_refs (parser);
14255 : 0 : objc_start_category_interface (id1, id2, proto, attributes);
14256 : 0 : c_parser_objc_methodprotolist (parser);
14257 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14258 : 0 : objc_finish_interface ();
14259 : 0 : return;
14260 : : }
14261 : 0 : if (c_parser_next_token_is (parser, CPP_COLON))
14262 : : {
14263 : 0 : c_parser_consume_token (parser);
14264 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14265 : : {
14266 : 0 : c_parser_error (parser, "expected identifier");
14267 : 0 : return;
14268 : : }
14269 : 0 : superclass = c_parser_peek_token (parser)->value;
14270 : 0 : c_parser_consume_token (parser);
14271 : : }
14272 : : else
14273 : : superclass = NULL_TREE;
14274 : 0 : if (iface_p)
14275 : : {
14276 : 0 : tree proto = NULL_TREE;
14277 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14278 : 0 : proto = c_parser_objc_protocol_refs (parser);
14279 : 0 : objc_start_class_interface (id1, loc1, superclass, proto, attributes);
14280 : : }
14281 : : else
14282 : 0 : objc_start_class_implementation (id1, superclass);
14283 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14284 : 0 : c_parser_objc_class_instance_variables (parser);
14285 : 0 : if (iface_p)
14286 : : {
14287 : 0 : objc_continue_interface ();
14288 : 0 : c_parser_objc_methodprotolist (parser);
14289 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14290 : 0 : objc_finish_interface ();
14291 : : }
14292 : : else
14293 : : {
14294 : 0 : objc_continue_implementation ();
14295 : 0 : return;
14296 : : }
14297 : : }
14298 : :
14299 : : /* Parse objc-class-instance-variables.
14300 : :
14301 : : objc-class-instance-variables:
14302 : : { objc-instance-variable-decl-list[opt] }
14303 : :
14304 : : objc-instance-variable-decl-list:
14305 : : objc-visibility-spec
14306 : : objc-instance-variable-decl ;
14307 : : ;
14308 : : objc-instance-variable-decl-list objc-visibility-spec
14309 : : objc-instance-variable-decl-list objc-instance-variable-decl ;
14310 : : objc-instance-variable-decl-list ;
14311 : :
14312 : : objc-visibility-spec:
14313 : : @private
14314 : : @protected
14315 : : @public
14316 : :
14317 : : objc-instance-variable-decl:
14318 : : struct-declaration
14319 : : */
14320 : :
14321 : : static void
14322 : 0 : c_parser_objc_class_instance_variables (c_parser *parser)
14323 : : {
14324 : 0 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
14325 : 0 : c_parser_consume_token (parser);
14326 : 0 : while (c_parser_next_token_is_not (parser, CPP_EOF))
14327 : : {
14328 : 0 : tree decls;
14329 : : /* Parse any stray semicolon. */
14330 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14331 : : {
14332 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14333 : : "extra semicolon");
14334 : 0 : c_parser_consume_token (parser);
14335 : 0 : continue;
14336 : : }
14337 : : /* Stop if at the end of the instance variables. */
14338 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
14339 : : {
14340 : 0 : c_parser_consume_token (parser);
14341 : 0 : break;
14342 : : }
14343 : : /* Parse any objc-visibility-spec. */
14344 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
14345 : : {
14346 : 0 : c_parser_consume_token (parser);
14347 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
14348 : 0 : continue;
14349 : : }
14350 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
14351 : : {
14352 : 0 : c_parser_consume_token (parser);
14353 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
14354 : 0 : continue;
14355 : : }
14356 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
14357 : : {
14358 : 0 : c_parser_consume_token (parser);
14359 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
14360 : 0 : continue;
14361 : : }
14362 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
14363 : : {
14364 : 0 : c_parser_consume_token (parser);
14365 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
14366 : 0 : continue;
14367 : : }
14368 : 0 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
14369 : : {
14370 : 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14371 : 0 : continue;
14372 : : }
14373 : :
14374 : : /* Parse some comma-separated declarations. */
14375 : 0 : decls = c_parser_struct_declaration (parser, NULL);
14376 : 0 : if (decls == NULL)
14377 : : {
14378 : : /* There is a syntax error. We want to skip the offending
14379 : : tokens up to the next ';' (included) or '}'
14380 : : (excluded). */
14381 : :
14382 : : /* First, skip manually a ')' or ']'. This is because they
14383 : : reduce the nesting level, so c_parser_skip_until_found()
14384 : : wouldn't be able to skip past them. */
14385 : 0 : c_token *token = c_parser_peek_token (parser);
14386 : 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
14387 : 0 : c_parser_consume_token (parser);
14388 : :
14389 : : /* Then, do the standard skipping. */
14390 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14391 : :
14392 : : /* We hopefully recovered. Start normal parsing again. */
14393 : 0 : parser->error = false;
14394 : 0 : continue;
14395 : 0 : }
14396 : : else
14397 : : {
14398 : : /* Comma-separated instance variables are chained together
14399 : : in reverse order; add them one by one. */
14400 : 0 : tree ivar = nreverse (decls);
14401 : 0 : for (; ivar; ivar = DECL_CHAIN (ivar))
14402 : 0 : objc_add_instance_variable (copy_node (ivar));
14403 : : }
14404 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14405 : : }
14406 : 0 : }
14407 : :
14408 : : /* Parse an objc-class-declaration.
14409 : :
14410 : : objc-class-declaration:
14411 : : @class identifier-list ;
14412 : : */
14413 : :
14414 : : static void
14415 : 0 : c_parser_objc_class_declaration (c_parser *parser)
14416 : : {
14417 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
14418 : 0 : c_parser_consume_token (parser);
14419 : : /* Any identifiers, including those declared as type names, are OK
14420 : : here. */
14421 : 0 : while (true)
14422 : : {
14423 : 0 : tree id;
14424 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14425 : : {
14426 : 0 : c_parser_error (parser, "expected identifier");
14427 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14428 : 0 : parser->error = false;
14429 : 0 : return;
14430 : : }
14431 : 0 : id = c_parser_peek_token (parser)->value;
14432 : 0 : objc_declare_class (id);
14433 : 0 : c_parser_consume_token (parser);
14434 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14435 : 0 : c_parser_consume_token (parser);
14436 : : else
14437 : : break;
14438 : 0 : }
14439 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14440 : : }
14441 : :
14442 : : /* Parse an objc-alias-declaration.
14443 : :
14444 : : objc-alias-declaration:
14445 : : @compatibility_alias identifier identifier ;
14446 : : */
14447 : :
14448 : : static void
14449 : 0 : c_parser_objc_alias_declaration (c_parser *parser)
14450 : : {
14451 : 0 : tree id1, id2;
14452 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
14453 : 0 : c_parser_consume_token (parser);
14454 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14455 : : {
14456 : 0 : c_parser_error (parser, "expected identifier");
14457 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14458 : 0 : return;
14459 : : }
14460 : 0 : id1 = c_parser_peek_token (parser)->value;
14461 : 0 : c_parser_consume_token (parser);
14462 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14463 : : {
14464 : 0 : c_parser_error (parser, "expected identifier");
14465 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14466 : 0 : return;
14467 : : }
14468 : 0 : id2 = c_parser_peek_token (parser)->value;
14469 : 0 : c_parser_consume_token (parser);
14470 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14471 : 0 : objc_declare_alias (id1, id2);
14472 : : }
14473 : :
14474 : : /* Parse an objc-protocol-definition.
14475 : :
14476 : : objc-protocol-definition:
14477 : : @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
14478 : : @protocol identifier-list ;
14479 : :
14480 : : "@protocol identifier ;" should be resolved as "@protocol
14481 : : identifier-list ;": objc-methodprotolist may not start with a
14482 : : semicolon in the first alternative if objc-protocol-refs are
14483 : : omitted. */
14484 : :
14485 : : static void
14486 : 0 : c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
14487 : : {
14488 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
14489 : :
14490 : 0 : c_parser_consume_token (parser);
14491 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14492 : : {
14493 : 0 : c_parser_error (parser, "expected identifier");
14494 : 0 : return;
14495 : : }
14496 : 0 : if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14497 : 0 : || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
14498 : : {
14499 : : /* Any identifiers, including those declared as type names, are
14500 : : OK here. */
14501 : 0 : while (true)
14502 : : {
14503 : 0 : tree id;
14504 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14505 : : {
14506 : 0 : c_parser_error (parser, "expected identifier");
14507 : 0 : break;
14508 : : }
14509 : 0 : id = c_parser_peek_token (parser)->value;
14510 : 0 : objc_declare_protocol (id, attributes);
14511 : 0 : c_parser_consume_token (parser);
14512 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14513 : 0 : c_parser_consume_token (parser);
14514 : : else
14515 : : break;
14516 : 0 : }
14517 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14518 : : }
14519 : : else
14520 : : {
14521 : 0 : tree id = c_parser_peek_token (parser)->value;
14522 : 0 : tree proto = NULL_TREE;
14523 : 0 : c_parser_consume_token (parser);
14524 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14525 : 0 : proto = c_parser_objc_protocol_refs (parser);
14526 : 0 : parser->objc_pq_context = true;
14527 : 0 : objc_start_protocol (id, proto, attributes);
14528 : 0 : c_parser_objc_methodprotolist (parser);
14529 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14530 : 0 : parser->objc_pq_context = false;
14531 : 0 : objc_finish_interface ();
14532 : : }
14533 : : }
14534 : :
14535 : : /* Parse an objc-method-type.
14536 : :
14537 : : objc-method-type:
14538 : : +
14539 : : -
14540 : :
14541 : : Return true if it is a class method (+) and false if it is
14542 : : an instance method (-).
14543 : : */
14544 : : static inline bool
14545 : 0 : c_parser_objc_method_type (c_parser *parser)
14546 : : {
14547 : 0 : switch (c_parser_peek_token (parser)->type)
14548 : : {
14549 : 0 : case CPP_PLUS:
14550 : 0 : c_parser_consume_token (parser);
14551 : 0 : return true;
14552 : 0 : case CPP_MINUS:
14553 : 0 : c_parser_consume_token (parser);
14554 : 0 : return false;
14555 : 0 : default:
14556 : 0 : gcc_unreachable ();
14557 : : }
14558 : : }
14559 : :
14560 : : /* Parse an objc-method-definition.
14561 : :
14562 : : objc-method-definition:
14563 : : objc-method-type objc-method-decl ;[opt] compound-statement
14564 : : */
14565 : :
14566 : : static void
14567 : 0 : c_parser_objc_method_definition (c_parser *parser)
14568 : : {
14569 : 0 : bool is_class_method = c_parser_objc_method_type (parser);
14570 : 0 : tree decl, attributes = NULL_TREE, expr = NULL_TREE;
14571 : 0 : parser->objc_pq_context = true;
14572 : 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14573 : : &expr);
14574 : 0 : if (decl == error_mark_node)
14575 : 0 : return; /* Bail here. */
14576 : :
14577 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14578 : : {
14579 : 0 : c_parser_consume_token (parser);
14580 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14581 : : "extra semicolon in method definition specified");
14582 : : }
14583 : :
14584 : 0 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14585 : : {
14586 : 0 : c_parser_error (parser, "expected %<{%>");
14587 : 0 : return;
14588 : : }
14589 : :
14590 : 0 : parser->objc_pq_context = false;
14591 : 0 : if (objc_start_method_definition (is_class_method, decl, attributes, expr))
14592 : : {
14593 : 0 : add_stmt (c_parser_compound_statement (parser));
14594 : 0 : objc_finish_method_definition (current_function_decl);
14595 : : }
14596 : : else
14597 : : {
14598 : : /* This code is executed when we find a method definition
14599 : : outside of an @implementation context (or invalid for other
14600 : : reasons). Parse the method (to keep going) but do not emit
14601 : : any code.
14602 : : */
14603 : 0 : c_parser_compound_statement (parser);
14604 : : }
14605 : : }
14606 : :
14607 : : /* Parse an objc-methodprotolist.
14608 : :
14609 : : objc-methodprotolist:
14610 : : empty
14611 : : objc-methodprotolist objc-methodproto
14612 : : objc-methodprotolist declaration
14613 : : objc-methodprotolist ;
14614 : : @optional
14615 : : @required
14616 : :
14617 : : The declaration is a data definition, which may be missing
14618 : : declaration specifiers under the same rules and diagnostics as
14619 : : other data definitions outside functions, and the stray semicolon
14620 : : is diagnosed the same way as a stray semicolon outside a
14621 : : function. */
14622 : :
14623 : : static void
14624 : 0 : c_parser_objc_methodprotolist (c_parser *parser)
14625 : : {
14626 : 0 : while (true)
14627 : : {
14628 : : /* The list is terminated by @end. */
14629 : 0 : switch (c_parser_peek_token (parser)->type)
14630 : : {
14631 : 0 : case CPP_SEMICOLON:
14632 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14633 : : "ISO C does not allow extra %<;%> outside of a function");
14634 : 0 : c_parser_consume_token (parser);
14635 : 0 : break;
14636 : 0 : case CPP_PLUS:
14637 : 0 : case CPP_MINUS:
14638 : 0 : c_parser_objc_methodproto (parser);
14639 : 0 : break;
14640 : 0 : case CPP_PRAGMA:
14641 : 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14642 : 0 : break;
14643 : : case CPP_EOF:
14644 : : return;
14645 : 0 : default:
14646 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_END))
14647 : : return;
14648 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
14649 : 0 : c_parser_objc_at_property_declaration (parser);
14650 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
14651 : : {
14652 : 0 : objc_set_method_opt (true);
14653 : 0 : c_parser_consume_token (parser);
14654 : : }
14655 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
14656 : : {
14657 : 0 : objc_set_method_opt (false);
14658 : 0 : c_parser_consume_token (parser);
14659 : : }
14660 : : else
14661 : 0 : c_parser_declaration_or_fndef (parser, false, false, true,
14662 : : false, true, false);
14663 : : break;
14664 : : }
14665 : : }
14666 : : }
14667 : :
14668 : : /* Parse an objc-methodproto.
14669 : :
14670 : : objc-methodproto:
14671 : : objc-method-type objc-method-decl ;
14672 : : */
14673 : :
14674 : : static void
14675 : 0 : c_parser_objc_methodproto (c_parser *parser)
14676 : : {
14677 : 0 : bool is_class_method = c_parser_objc_method_type (parser);
14678 : 0 : tree decl, attributes = NULL_TREE;
14679 : :
14680 : : /* Remember protocol qualifiers in prototypes. */
14681 : 0 : parser->objc_pq_context = true;
14682 : 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14683 : : NULL);
14684 : : /* Forget protocol qualifiers now. */
14685 : 0 : parser->objc_pq_context = false;
14686 : :
14687 : : /* Do not allow the presence of attributes to hide an erroneous
14688 : : method implementation in the interface section. */
14689 : 0 : if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
14690 : : {
14691 : 0 : c_parser_error (parser, "expected %<;%>");
14692 : 0 : return;
14693 : : }
14694 : :
14695 : 0 : if (decl != error_mark_node)
14696 : 0 : objc_add_method_declaration (is_class_method, decl, attributes);
14697 : :
14698 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14699 : : }
14700 : :
14701 : : /* If we are at a position that method attributes may be present, check that
14702 : : there are not any parsed already (a syntax error) and then collect any
14703 : : specified at the current location. Finally, if new attributes were present,
14704 : : check that the next token is legal ( ';' for decls and '{' for defs). */
14705 : :
14706 : : static bool
14707 : 0 : c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
14708 : : {
14709 : 0 : bool bad = false;
14710 : 0 : if (*attributes)
14711 : : {
14712 : 0 : c_parser_error (parser,
14713 : : "method attributes must be specified at the end only");
14714 : 0 : *attributes = NULL_TREE;
14715 : 0 : bad = true;
14716 : : }
14717 : :
14718 : 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
14719 : 0 : *attributes = c_parser_gnu_attributes (parser);
14720 : :
14721 : : /* If there were no attributes here, just report any earlier error. */
14722 : 0 : if (*attributes == NULL_TREE || bad)
14723 : : return bad;
14724 : :
14725 : : /* If the attributes are followed by a ; or {, then just report any earlier
14726 : : error. */
14727 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
14728 : 0 : || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14729 : 0 : return bad;
14730 : :
14731 : : /* We've got attributes, but not at the end. */
14732 : 0 : c_parser_error (parser,
14733 : : "expected %<;%> or %<{%> after method attribute definition");
14734 : 0 : return true;
14735 : : }
14736 : :
14737 : : /* Parse an objc-method-decl.
14738 : :
14739 : : objc-method-decl:
14740 : : ( objc-type-name ) objc-selector
14741 : : objc-selector
14742 : : ( objc-type-name ) objc-keyword-selector objc-optparmlist
14743 : : objc-keyword-selector objc-optparmlist
14744 : : gnu-attributes
14745 : :
14746 : : objc-keyword-selector:
14747 : : objc-keyword-decl
14748 : : objc-keyword-selector objc-keyword-decl
14749 : :
14750 : : objc-keyword-decl:
14751 : : objc-selector : ( objc-type-name ) identifier
14752 : : objc-selector : identifier
14753 : : : ( objc-type-name ) identifier
14754 : : : identifier
14755 : :
14756 : : objc-optparmlist:
14757 : : objc-optparms objc-optellipsis
14758 : :
14759 : : objc-optparms:
14760 : : empty
14761 : : objc-opt-parms , parameter-declaration
14762 : :
14763 : : objc-optellipsis:
14764 : : empty
14765 : : , ...
14766 : : */
14767 : :
14768 : : static tree
14769 : 0 : c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
14770 : : tree *attributes, tree *expr)
14771 : : {
14772 : 0 : tree type = NULL_TREE;
14773 : 0 : tree sel;
14774 : 0 : tree parms = NULL_TREE;
14775 : 0 : bool ellipsis = false;
14776 : 0 : bool attr_err = false;
14777 : :
14778 : 0 : *attributes = NULL_TREE;
14779 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14780 : : {
14781 : 0 : matching_parens parens;
14782 : 0 : parens.consume_open (parser);
14783 : 0 : type = c_parser_objc_type_name (parser);
14784 : 0 : parens.skip_until_found_close (parser);
14785 : : }
14786 : 0 : sel = c_parser_objc_selector (parser);
14787 : : /* If there is no selector, or a colon follows, we have an
14788 : : objc-keyword-selector. If there is a selector, and a colon does
14789 : : not follow, that selector ends the objc-method-decl. */
14790 : 0 : if (!sel || c_parser_next_token_is (parser, CPP_COLON))
14791 : : {
14792 : : tree tsel = sel;
14793 : : tree list = NULL_TREE;
14794 : 0 : while (true)
14795 : : {
14796 : 0 : tree atype = NULL_TREE, id, keyworddecl;
14797 : 0 : tree param_attr = NULL_TREE;
14798 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
14799 : : break;
14800 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14801 : : {
14802 : 0 : c_parser_consume_token (parser);
14803 : 0 : atype = c_parser_objc_type_name (parser);
14804 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
14805 : : "expected %<)%>");
14806 : : }
14807 : : /* New ObjC allows attributes on method parameters. */
14808 : 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
14809 : 0 : param_attr = c_parser_gnu_attributes (parser);
14810 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14811 : : {
14812 : 0 : c_parser_error (parser, "expected identifier");
14813 : 0 : return error_mark_node;
14814 : : }
14815 : 0 : id = c_parser_peek_token (parser)->value;
14816 : 0 : c_parser_consume_token (parser);
14817 : 0 : keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
14818 : 0 : list = chainon (list, keyworddecl);
14819 : 0 : tsel = c_parser_objc_selector (parser);
14820 : 0 : if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
14821 : : break;
14822 : : }
14823 : :
14824 : 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14825 : :
14826 : : /* Parse the optional parameter list. Optional Objective-C
14827 : : method parameters follow the C syntax, and may include '...'
14828 : : to denote a variable number of arguments. */
14829 : 0 : parms = make_node (TREE_LIST);
14830 : 0 : while (c_parser_next_token_is (parser, CPP_COMMA))
14831 : : {
14832 : 0 : struct c_parm *parm;
14833 : 0 : c_parser_consume_token (parser);
14834 : 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
14835 : : {
14836 : 0 : ellipsis = true;
14837 : 0 : c_parser_consume_token (parser);
14838 : 0 : attr_err |= c_parser_objc_maybe_method_attributes
14839 : 0 : (parser, attributes) ;
14840 : 0 : break;
14841 : : }
14842 : 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
14843 : 0 : if (parm == NULL)
14844 : : break;
14845 : 0 : parms = chainon (parms,
14846 : : build_tree_list (NULL_TREE, grokparm (parm, expr)));
14847 : : }
14848 : : sel = list;
14849 : : }
14850 : : else
14851 : 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14852 : :
14853 : 0 : if (sel == NULL)
14854 : : {
14855 : 0 : c_parser_error (parser, "objective-c method declaration is expected");
14856 : 0 : return error_mark_node;
14857 : : }
14858 : :
14859 : 0 : if (attr_err)
14860 : 0 : return error_mark_node;
14861 : :
14862 : 0 : return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
14863 : : }
14864 : :
14865 : : /* Parse an objc-type-name.
14866 : :
14867 : : objc-type-name:
14868 : : objc-type-qualifiers[opt] type-name
14869 : : objc-type-qualifiers[opt]
14870 : :
14871 : : objc-type-qualifiers:
14872 : : objc-type-qualifier
14873 : : objc-type-qualifiers objc-type-qualifier
14874 : :
14875 : : objc-type-qualifier: one of
14876 : : in out inout bycopy byref oneway
14877 : : */
14878 : :
14879 : : static tree
14880 : 0 : c_parser_objc_type_name (c_parser *parser)
14881 : : {
14882 : 0 : tree quals = NULL_TREE;
14883 : 0 : struct c_type_name *type_name = NULL;
14884 : 0 : tree type = NULL_TREE;
14885 : 0 : while (true)
14886 : : {
14887 : 0 : c_token *token = c_parser_peek_token (parser);
14888 : 0 : if (token->type == CPP_KEYWORD
14889 : 0 : && (token->keyword == RID_IN
14890 : : || token->keyword == RID_OUT
14891 : : || token->keyword == RID_INOUT
14892 : : || token->keyword == RID_BYCOPY
14893 : : || token->keyword == RID_BYREF
14894 : 0 : || token->keyword == RID_ONEWAY))
14895 : : {
14896 : 0 : quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
14897 : 0 : c_parser_consume_token (parser);
14898 : : }
14899 : : else
14900 : : break;
14901 : 0 : }
14902 : 0 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
14903 : 0 : type_name = c_parser_type_name (parser);
14904 : 0 : if (type_name)
14905 : 0 : type = groktypename (type_name, NULL, NULL);
14906 : :
14907 : : /* If the type is unknown, and error has already been produced and
14908 : : we need to recover from the error. In that case, use NULL_TREE
14909 : : for the type, as if no type had been specified; this will use the
14910 : : default type ('id') which is good for error recovery. */
14911 : 0 : if (type == error_mark_node)
14912 : 0 : type = NULL_TREE;
14913 : :
14914 : 0 : return build_tree_list (quals, type);
14915 : : }
14916 : :
14917 : : /* Parse objc-protocol-refs.
14918 : :
14919 : : objc-protocol-refs:
14920 : : < identifier-list >
14921 : : */
14922 : :
14923 : : static tree
14924 : 0 : c_parser_objc_protocol_refs (c_parser *parser)
14925 : : {
14926 : 0 : tree list = NULL_TREE;
14927 : 0 : gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
14928 : 0 : c_parser_consume_token (parser);
14929 : : /* Any identifiers, including those declared as type names, are OK
14930 : : here. */
14931 : 0 : while (true)
14932 : : {
14933 : 0 : tree id;
14934 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14935 : : {
14936 : 0 : c_parser_error (parser, "expected identifier");
14937 : 0 : break;
14938 : : }
14939 : 0 : id = c_parser_peek_token (parser)->value;
14940 : 0 : list = chainon (list, build_tree_list (NULL_TREE, id));
14941 : 0 : c_parser_consume_token (parser);
14942 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14943 : 0 : c_parser_consume_token (parser);
14944 : : else
14945 : : break;
14946 : 0 : }
14947 : 0 : c_parser_require (parser, CPP_GREATER, "expected %<>%>");
14948 : 0 : return list;
14949 : : }
14950 : :
14951 : : /* Parse an objc-try-catch-finally-statement.
14952 : :
14953 : : objc-try-catch-finally-statement:
14954 : : @try compound-statement objc-catch-list[opt]
14955 : : @try compound-statement objc-catch-list[opt] @finally compound-statement
14956 : :
14957 : : objc-catch-list:
14958 : : @catch ( objc-catch-parameter-declaration ) compound-statement
14959 : : objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
14960 : :
14961 : : objc-catch-parameter-declaration:
14962 : : parameter-declaration
14963 : : '...'
14964 : :
14965 : : where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
14966 : :
14967 : : PS: This function is identical to cp_parser_objc_try_catch_finally_statement
14968 : : for C++. Keep them in sync. */
14969 : :
14970 : : static void
14971 : 0 : c_parser_objc_try_catch_finally_statement (c_parser *parser)
14972 : : {
14973 : 0 : location_t location;
14974 : 0 : tree stmt;
14975 : :
14976 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
14977 : 0 : c_parser_consume_token (parser);
14978 : 0 : location = c_parser_peek_token (parser)->location;
14979 : 0 : objc_maybe_warn_exceptions (location);
14980 : 0 : stmt = c_parser_compound_statement (parser);
14981 : 0 : objc_begin_try_stmt (location, stmt);
14982 : :
14983 : 0 : while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
14984 : : {
14985 : 0 : struct c_parm *parm;
14986 : 0 : tree parameter_declaration = error_mark_node;
14987 : 0 : bool seen_open_paren = false;
14988 : :
14989 : 0 : c_parser_consume_token (parser);
14990 : 0 : matching_parens parens;
14991 : 0 : if (!parens.require_open (parser))
14992 : 0 : seen_open_paren = true;
14993 : 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
14994 : : {
14995 : : /* We have "@catch (...)" (where the '...' are literally
14996 : : what is in the code). Skip the '...'.
14997 : : parameter_declaration is set to NULL_TREE, and
14998 : : objc_being_catch_clauses() knows that that means
14999 : : '...'. */
15000 : 0 : c_parser_consume_token (parser);
15001 : 0 : parameter_declaration = NULL_TREE;
15002 : : }
15003 : : else
15004 : : {
15005 : : /* We have "@catch (NSException *exception)" or something
15006 : : like that. Parse the parameter declaration. */
15007 : 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
15008 : 0 : if (parm == NULL)
15009 : 0 : parameter_declaration = error_mark_node;
15010 : : else
15011 : 0 : parameter_declaration = grokparm (parm, NULL);
15012 : : }
15013 : 0 : if (seen_open_paren)
15014 : 0 : parens.require_close (parser);
15015 : : else
15016 : : {
15017 : : /* If there was no open parenthesis, we are recovering from
15018 : : an error, and we are trying to figure out what mistake
15019 : : the user has made. */
15020 : :
15021 : : /* If there is an immediate closing parenthesis, the user
15022 : : probably forgot the opening one (ie, they typed "@catch
15023 : : NSException *e)". Parse the closing parenthesis and keep
15024 : : going. */
15025 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15026 : 0 : c_parser_consume_token (parser);
15027 : :
15028 : : /* If these is no immediate closing parenthesis, the user
15029 : : probably doesn't know that parenthesis are required at
15030 : : all (ie, they typed "@catch NSException *e"). So, just
15031 : : forget about the closing parenthesis and keep going. */
15032 : : }
15033 : 0 : objc_begin_catch_clause (parameter_declaration);
15034 : 0 : if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
15035 : 0 : c_parser_compound_statement_nostart (parser);
15036 : 0 : objc_finish_catch_clause ();
15037 : : }
15038 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
15039 : : {
15040 : 0 : c_parser_consume_token (parser);
15041 : 0 : location = c_parser_peek_token (parser)->location;
15042 : 0 : stmt = c_parser_compound_statement (parser);
15043 : 0 : objc_build_finally_clause (location, stmt);
15044 : : }
15045 : 0 : objc_finish_try_stmt ();
15046 : 0 : }
15047 : :
15048 : : /* Parse an objc-synchronized-statement.
15049 : :
15050 : : objc-synchronized-statement:
15051 : : @synchronized ( expression ) compound-statement
15052 : : */
15053 : :
15054 : : static void
15055 : 0 : c_parser_objc_synchronized_statement (c_parser *parser)
15056 : : {
15057 : 0 : location_t loc;
15058 : 0 : tree expr, stmt;
15059 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
15060 : 0 : c_parser_consume_token (parser);
15061 : 0 : loc = c_parser_peek_token (parser)->location;
15062 : 0 : objc_maybe_warn_exceptions (loc);
15063 : 0 : matching_parens parens;
15064 : 0 : if (parens.require_open (parser))
15065 : : {
15066 : 0 : struct c_expr ce = c_parser_expression (parser);
15067 : 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15068 : 0 : expr = ce.value;
15069 : 0 : expr = c_fully_fold (expr, false, NULL);
15070 : 0 : parens.skip_until_found_close (parser);
15071 : : }
15072 : : else
15073 : 0 : expr = error_mark_node;
15074 : 0 : stmt = c_parser_compound_statement (parser);
15075 : 0 : objc_build_synchronized (loc, expr, stmt);
15076 : 0 : }
15077 : :
15078 : : /* Parse an objc-selector; return NULL_TREE without an error if the
15079 : : next token is not an objc-selector.
15080 : :
15081 : : objc-selector:
15082 : : identifier
15083 : : one of
15084 : : enum struct union if else while do for switch case default
15085 : : break continue return goto asm sizeof typeof typeof_unqual __alignof
15086 : : unsigned long const short volatile signed restrict _Complex
15087 : : in out inout bycopy byref oneway int char float double void _Bool
15088 : : _Atomic
15089 : :
15090 : : ??? Why this selection of keywords but not, for example, storage
15091 : : class specifiers? */
15092 : :
15093 : : static tree
15094 : 0 : c_parser_objc_selector (c_parser *parser)
15095 : : {
15096 : 0 : c_token *token = c_parser_peek_token (parser);
15097 : 0 : tree value = token->value;
15098 : 0 : if (token->type == CPP_NAME)
15099 : : {
15100 : 0 : c_parser_consume_token (parser);
15101 : 0 : return value;
15102 : : }
15103 : 0 : if (token->type != CPP_KEYWORD)
15104 : : return NULL_TREE;
15105 : 0 : switch (token->keyword)
15106 : : {
15107 : 0 : case RID_ENUM:
15108 : 0 : case RID_STRUCT:
15109 : 0 : case RID_UNION:
15110 : 0 : case RID_IF:
15111 : 0 : case RID_ELSE:
15112 : 0 : case RID_WHILE:
15113 : 0 : case RID_DO:
15114 : 0 : case RID_FOR:
15115 : 0 : case RID_SWITCH:
15116 : 0 : case RID_CASE:
15117 : 0 : case RID_DEFAULT:
15118 : 0 : case RID_BREAK:
15119 : 0 : case RID_CONTINUE:
15120 : 0 : case RID_RETURN:
15121 : 0 : case RID_GOTO:
15122 : 0 : case RID_ASM:
15123 : 0 : case RID_SIZEOF:
15124 : 0 : case RID_TYPEOF:
15125 : 0 : case RID_TYPEOF_UNQUAL:
15126 : 0 : case RID_ALIGNOF:
15127 : 0 : case RID_UNSIGNED:
15128 : 0 : case RID_LONG:
15129 : 0 : case RID_CONST:
15130 : 0 : case RID_SHORT:
15131 : 0 : case RID_VOLATILE:
15132 : 0 : case RID_SIGNED:
15133 : 0 : case RID_RESTRICT:
15134 : 0 : case RID_COMPLEX:
15135 : 0 : case RID_IN:
15136 : 0 : case RID_OUT:
15137 : 0 : case RID_INOUT:
15138 : 0 : case RID_BYCOPY:
15139 : 0 : case RID_BYREF:
15140 : 0 : case RID_ONEWAY:
15141 : 0 : case RID_INT:
15142 : 0 : case RID_CHAR:
15143 : 0 : case RID_FLOAT:
15144 : 0 : case RID_DOUBLE:
15145 : 0 : CASE_RID_FLOATN_NX:
15146 : 0 : case RID_VOID:
15147 : 0 : case RID_BOOL:
15148 : 0 : case RID_ATOMIC:
15149 : 0 : case RID_AUTO_TYPE:
15150 : 0 : case RID_INT_N_0:
15151 : 0 : case RID_INT_N_1:
15152 : 0 : case RID_INT_N_2:
15153 : 0 : case RID_INT_N_3:
15154 : 0 : c_parser_consume_token (parser);
15155 : 0 : return value;
15156 : : default:
15157 : : return NULL_TREE;
15158 : : }
15159 : : }
15160 : :
15161 : : /* Parse an objc-selector-arg.
15162 : :
15163 : : objc-selector-arg:
15164 : : objc-selector
15165 : : objc-keywordname-list
15166 : :
15167 : : objc-keywordname-list:
15168 : : objc-keywordname
15169 : : objc-keywordname-list objc-keywordname
15170 : :
15171 : : objc-keywordname:
15172 : : objc-selector :
15173 : : :
15174 : : */
15175 : :
15176 : : static tree
15177 : 0 : c_parser_objc_selector_arg (c_parser *parser)
15178 : : {
15179 : 0 : tree sel = c_parser_objc_selector (parser);
15180 : 0 : tree list = NULL_TREE;
15181 : 0 : if (sel
15182 : 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15183 : 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15184 : : return sel;
15185 : 0 : while (true)
15186 : : {
15187 : 0 : if (c_parser_next_token_is (parser, CPP_SCOPE))
15188 : : {
15189 : 0 : c_parser_consume_token (parser);
15190 : 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15191 : 0 : list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
15192 : : }
15193 : : else
15194 : : {
15195 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15196 : : return list;
15197 : 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15198 : : }
15199 : 0 : sel = c_parser_objc_selector (parser);
15200 : 0 : if (!sel
15201 : 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15202 : 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15203 : : break;
15204 : : }
15205 : : return list;
15206 : : }
15207 : :
15208 : : /* Parse an objc-receiver.
15209 : :
15210 : : objc-receiver:
15211 : : expression
15212 : : class-name
15213 : : type-name
15214 : : */
15215 : :
15216 : : static tree
15217 : 0 : c_parser_objc_receiver (c_parser *parser)
15218 : : {
15219 : 0 : location_t loc = c_parser_peek_token (parser)->location;
15220 : :
15221 : 0 : if (c_parser_peek_token (parser)->type == CPP_NAME
15222 : 0 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
15223 : 0 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
15224 : : {
15225 : 0 : tree id = c_parser_peek_token (parser)->value;
15226 : 0 : c_parser_consume_token (parser);
15227 : 0 : return objc_get_class_reference (id);
15228 : : }
15229 : 0 : struct c_expr ce = c_parser_expression (parser);
15230 : 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15231 : 0 : return c_fully_fold (ce.value, false, NULL);
15232 : : }
15233 : :
15234 : : /* Parse objc-message-args.
15235 : :
15236 : : objc-message-args:
15237 : : objc-selector
15238 : : objc-keywordarg-list
15239 : :
15240 : : objc-keywordarg-list:
15241 : : objc-keywordarg
15242 : : objc-keywordarg-list objc-keywordarg
15243 : :
15244 : : objc-keywordarg:
15245 : : objc-selector : objc-keywordexpr
15246 : : : objc-keywordexpr
15247 : : */
15248 : :
15249 : : static tree
15250 : 0 : c_parser_objc_message_args (c_parser *parser)
15251 : : {
15252 : 0 : tree sel = c_parser_objc_selector (parser);
15253 : 0 : tree list = NULL_TREE;
15254 : 0 : if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
15255 : : return sel;
15256 : 0 : while (true)
15257 : : {
15258 : 0 : tree keywordexpr;
15259 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15260 : 0 : return error_mark_node;
15261 : 0 : keywordexpr = c_parser_objc_keywordexpr (parser);
15262 : 0 : list = chainon (list, build_tree_list (sel, keywordexpr));
15263 : 0 : sel = c_parser_objc_selector (parser);
15264 : 0 : if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
15265 : : break;
15266 : : }
15267 : : return list;
15268 : : }
15269 : :
15270 : : /* Parse an objc-keywordexpr.
15271 : :
15272 : : objc-keywordexpr:
15273 : : nonempty-expr-list
15274 : : */
15275 : :
15276 : : static tree
15277 : 0 : c_parser_objc_keywordexpr (c_parser *parser)
15278 : : {
15279 : 0 : tree ret;
15280 : 0 : vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true,
15281 : : NULL, NULL, NULL, NULL);
15282 : 0 : if (vec_safe_length (expr_list) == 1)
15283 : : {
15284 : : /* Just return the expression, remove a level of
15285 : : indirection. */
15286 : 0 : ret = (*expr_list)[0];
15287 : : }
15288 : : else
15289 : : {
15290 : : /* We have a comma expression, we will collapse later. */
15291 : 0 : ret = build_tree_list_vec (expr_list);
15292 : : }
15293 : 0 : release_tree_vector (expr_list);
15294 : 0 : return ret;
15295 : : }
15296 : :
15297 : : /* A check, needed in several places, that ObjC interface, implementation or
15298 : : method definitions are not prefixed by incorrect items. */
15299 : : static bool
15300 : 0 : c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
15301 : : struct c_declspecs *specs)
15302 : : {
15303 : 0 : if (!specs->declspecs_seen_p || specs->non_sc_seen_p
15304 : 0 : || specs->typespec_kind != ctsk_none)
15305 : : {
15306 : 0 : c_parser_error (parser,
15307 : : "no type or storage class may be specified here,");
15308 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
15309 : 0 : return true;
15310 : : }
15311 : : return false;
15312 : : }
15313 : :
15314 : : /* Parse an Objective-C @property declaration. The syntax is:
15315 : :
15316 : : objc-property-declaration:
15317 : : '@property' objc-property-attributes[opt] struct-declaration ;
15318 : :
15319 : : objc-property-attributes:
15320 : : '(' objc-property-attribute-list ')'
15321 : :
15322 : : objc-property-attribute-list:
15323 : : objc-property-attribute
15324 : : objc-property-attribute-list, objc-property-attribute
15325 : :
15326 : : objc-property-attribute
15327 : : 'getter' = identifier
15328 : : 'setter' = identifier
15329 : : 'readonly'
15330 : : 'readwrite'
15331 : : 'assign'
15332 : : 'retain'
15333 : : 'copy'
15334 : : 'nonatomic'
15335 : :
15336 : : For example:
15337 : : @property NSString *name;
15338 : : @property (readonly) id object;
15339 : : @property (retain, nonatomic, getter=getTheName) id name;
15340 : : @property int a, b, c;
15341 : :
15342 : : PS: This function is identical to cp_parser_objc_at_propery_declaration
15343 : : for C++. Keep them in sync. */
15344 : : static void
15345 : 0 : c_parser_objc_at_property_declaration (c_parser *parser)
15346 : : {
15347 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
15348 : 0 : location_t loc = c_parser_peek_token (parser)->location;
15349 : 0 : c_parser_consume_token (parser); /* Eat '@property'. */
15350 : :
15351 : : /* Parse the optional attribute list.
15352 : :
15353 : : A list of parsed, but not verified, attributes. */
15354 : 0 : vec<property_attribute_info *> prop_attr_list = vNULL;
15355 : :
15356 : 0 : bool syntax_error = false;
15357 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
15358 : : {
15359 : 0 : matching_parens parens;
15360 : :
15361 : 0 : location_t attr_start = c_parser_peek_token (parser)->location;
15362 : : /* Eat the '(' */
15363 : 0 : parens.consume_open (parser);
15364 : :
15365 : : /* Property attribute keywords are valid now. */
15366 : 0 : parser->objc_property_attr_context = true;
15367 : :
15368 : : /* Allow @property (), with a warning. */
15369 : 0 : location_t attr_end = c_parser_peek_token (parser)->location;
15370 : :
15371 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15372 : : {
15373 : 0 : location_t attr_comb = make_location (attr_end, attr_start, attr_end);
15374 : 0 : warning_at (attr_comb, OPT_Wattributes,
15375 : : "empty property attribute list");
15376 : : }
15377 : : else
15378 : 0 : while (true)
15379 : : {
15380 : 0 : c_token *token = c_parser_peek_token (parser);
15381 : 0 : attr_start = token->location;
15382 : 0 : attr_end = get_finish (token->location);
15383 : 0 : location_t attr_comb = make_location (attr_start, attr_start,
15384 : : attr_end);
15385 : :
15386 : 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
15387 : : {
15388 : 0 : warning_at (attr_comb, OPT_Wattributes,
15389 : : "missing property attribute");
15390 : 0 : if (token->type == CPP_CLOSE_PAREN)
15391 : : break;
15392 : 0 : c_parser_consume_token (parser);
15393 : 0 : continue;
15394 : : }
15395 : :
15396 : 0 : tree attr_name = NULL_TREE;
15397 : 0 : enum rid keyword = RID_MAX; /* Not a valid property attribute. */
15398 : 0 : bool add_at = false;
15399 : 0 : if (token->type == CPP_KEYWORD)
15400 : : {
15401 : 0 : keyword = token->keyword;
15402 : 0 : if (OBJC_IS_AT_KEYWORD (keyword))
15403 : : {
15404 : : /* For '@' keywords the token value has the keyword,
15405 : : prepend the '@' for diagnostics. */
15406 : 0 : attr_name = token->value;
15407 : 0 : add_at = true;
15408 : : }
15409 : : else
15410 : 0 : attr_name = ridpointers[(int)keyword];
15411 : : }
15412 : 0 : else if (token->type == CPP_NAME)
15413 : 0 : attr_name = token->value;
15414 : 0 : c_parser_consume_token (parser);
15415 : :
15416 : 0 : enum objc_property_attribute_kind prop_kind
15417 : 0 : = objc_prop_attr_kind_for_rid (keyword);
15418 : 0 : property_attribute_info *prop
15419 : 0 : = new property_attribute_info (attr_name, attr_comb, prop_kind);
15420 : 0 : prop_attr_list.safe_push (prop);
15421 : :
15422 : 0 : tree meth_name;
15423 : 0 : switch (prop->prop_kind)
15424 : : {
15425 : : default: break;
15426 : 0 : case OBJC_PROPERTY_ATTR_UNKNOWN:
15427 : 0 : if (attr_name)
15428 : 0 : error_at (attr_comb, "unknown property attribute %<%s%s%>",
15429 : 0 : add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
15430 : : else
15431 : 0 : error_at (attr_comb, "unknown property attribute");
15432 : 0 : prop->parse_error = syntax_error = true;
15433 : 0 : break;
15434 : :
15435 : 0 : case OBJC_PROPERTY_ATTR_GETTER:
15436 : 0 : case OBJC_PROPERTY_ATTR_SETTER:
15437 : 0 : if (c_parser_next_token_is_not (parser, CPP_EQ))
15438 : : {
15439 : 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15440 : 0 : error_at (attr_comb, "expected %<=%> after Objective-C %qE",
15441 : : attr_name);
15442 : 0 : prop->parse_error = syntax_error = true;
15443 : 0 : break;
15444 : : }
15445 : 0 : token = c_parser_peek_token (parser);
15446 : 0 : attr_end = token->location;
15447 : 0 : c_parser_consume_token (parser); /* eat the = */
15448 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15449 : : {
15450 : 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15451 : 0 : error_at (attr_comb, "expected %qE selector name",
15452 : : attr_name);
15453 : 0 : prop->parse_error = syntax_error = true;
15454 : 0 : break;
15455 : : }
15456 : : /* Get the end of the method name, and consume the name. */
15457 : 0 : token = c_parser_peek_token (parser);
15458 : 0 : attr_end = get_finish (token->location);
15459 : 0 : meth_name = token->value;
15460 : 0 : c_parser_consume_token (parser);
15461 : 0 : if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
15462 : : {
15463 : 0 : if (c_parser_next_token_is_not (parser, CPP_COLON))
15464 : : {
15465 : 0 : attr_comb = make_location (attr_end, attr_start,
15466 : : attr_end);
15467 : 0 : error_at (attr_comb, "setter method names must"
15468 : : " terminate with %<:%>");
15469 : 0 : prop->parse_error = syntax_error = true;
15470 : : }
15471 : : else
15472 : : {
15473 : 0 : attr_end = get_finish (c_parser_peek_token
15474 : 0 : (parser)->location);
15475 : 0 : c_parser_consume_token (parser);
15476 : : }
15477 : 0 : attr_comb = make_location (attr_start, attr_start,
15478 : : attr_end);
15479 : : }
15480 : : else
15481 : 0 : attr_comb = make_location (attr_start, attr_start,
15482 : : attr_end);
15483 : 0 : prop->ident = meth_name;
15484 : : /* Updated location including all that was successfully
15485 : : parsed. */
15486 : 0 : prop->prop_loc = attr_comb;
15487 : 0 : break;
15488 : : }
15489 : :
15490 : : /* If we see a comma here, then keep going - even if we already
15491 : : saw a syntax error. For simple mistakes e.g. (asign, getter=x)
15492 : : this makes a more useful output and avoid spurious warnings about
15493 : : missing attributes that are, in fact, specified after the one with
15494 : : the syntax error. */
15495 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15496 : 0 : c_parser_consume_token (parser);
15497 : : else
15498 : : break;
15499 : : }
15500 : 0 : parser->objc_property_attr_context = false;
15501 : :
15502 : 0 : if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
15503 : : /* We don't really want to chew the whole of the file looking for a
15504 : : matching closing parenthesis, so we will try to read the decl and
15505 : : let the error handling for that close out the statement. */
15506 : : ;
15507 : : else
15508 : 0 : syntax_error = false, parens.skip_until_found_close (parser);
15509 : : }
15510 : :
15511 : : /* 'properties' is the list of properties that we read. Usually a
15512 : : single one, but maybe more (eg, in "@property int a, b, c;" there
15513 : : are three). */
15514 : 0 : tree properties = c_parser_struct_declaration (parser, NULL);
15515 : :
15516 : 0 : if (properties == error_mark_node)
15517 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15518 : : else
15519 : : {
15520 : 0 : if (properties == NULL_TREE)
15521 : 0 : c_parser_error (parser, "expected identifier");
15522 : : else
15523 : : {
15524 : : /* Comma-separated properties are chained together in reverse order;
15525 : : add them one by one. */
15526 : 0 : properties = nreverse (properties);
15527 : 0 : for (; properties; properties = TREE_CHAIN (properties))
15528 : 0 : objc_add_property_declaration (loc, copy_node (properties),
15529 : : prop_attr_list);
15530 : : }
15531 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15532 : : }
15533 : :
15534 : 0 : while (!prop_attr_list.is_empty())
15535 : 0 : delete prop_attr_list.pop ();
15536 : 0 : prop_attr_list.release ();
15537 : 0 : parser->error = false;
15538 : 0 : }
15539 : :
15540 : : /* Parse an Objective-C @synthesize declaration. The syntax is:
15541 : :
15542 : : objc-synthesize-declaration:
15543 : : @synthesize objc-synthesize-identifier-list ;
15544 : :
15545 : : objc-synthesize-identifier-list:
15546 : : objc-synthesize-identifier
15547 : : objc-synthesize-identifier-list, objc-synthesize-identifier
15548 : :
15549 : : objc-synthesize-identifier
15550 : : identifier
15551 : : identifier = identifier
15552 : :
15553 : : For example:
15554 : : @synthesize MyProperty;
15555 : : @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
15556 : :
15557 : : PS: This function is identical to cp_parser_objc_at_synthesize_declaration
15558 : : for C++. Keep them in sync.
15559 : : */
15560 : : static void
15561 : 0 : c_parser_objc_at_synthesize_declaration (c_parser *parser)
15562 : : {
15563 : 0 : tree list = NULL_TREE;
15564 : 0 : location_t loc;
15565 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
15566 : 0 : loc = c_parser_peek_token (parser)->location;
15567 : :
15568 : 0 : c_parser_consume_token (parser);
15569 : 0 : while (true)
15570 : : {
15571 : 0 : tree property, ivar;
15572 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15573 : : {
15574 : 0 : c_parser_error (parser, "expected identifier");
15575 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15576 : : /* Once we find the semicolon, we can resume normal parsing.
15577 : : We have to reset parser->error manually because
15578 : : c_parser_skip_until_found() won't reset it for us if the
15579 : : next token is precisely a semicolon. */
15580 : 0 : parser->error = false;
15581 : 0 : return;
15582 : : }
15583 : 0 : property = c_parser_peek_token (parser)->value;
15584 : 0 : c_parser_consume_token (parser);
15585 : 0 : if (c_parser_next_token_is (parser, CPP_EQ))
15586 : : {
15587 : 0 : c_parser_consume_token (parser);
15588 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15589 : : {
15590 : 0 : c_parser_error (parser, "expected identifier");
15591 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15592 : 0 : parser->error = false;
15593 : 0 : return;
15594 : : }
15595 : 0 : ivar = c_parser_peek_token (parser)->value;
15596 : 0 : c_parser_consume_token (parser);
15597 : : }
15598 : : else
15599 : : ivar = NULL_TREE;
15600 : 0 : list = chainon (list, build_tree_list (ivar, property));
15601 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15602 : 0 : c_parser_consume_token (parser);
15603 : : else
15604 : : break;
15605 : 0 : }
15606 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15607 : 0 : objc_add_synthesize_declaration (loc, list);
15608 : : }
15609 : :
15610 : : /* Parse an Objective-C @dynamic declaration. The syntax is:
15611 : :
15612 : : objc-dynamic-declaration:
15613 : : @dynamic identifier-list ;
15614 : :
15615 : : For example:
15616 : : @dynamic MyProperty;
15617 : : @dynamic MyProperty, AnotherProperty;
15618 : :
15619 : : PS: This function is identical to cp_parser_objc_at_dynamic_declaration
15620 : : for C++. Keep them in sync.
15621 : : */
15622 : : static void
15623 : 0 : c_parser_objc_at_dynamic_declaration (c_parser *parser)
15624 : : {
15625 : 0 : tree list = NULL_TREE;
15626 : 0 : location_t loc;
15627 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
15628 : 0 : loc = c_parser_peek_token (parser)->location;
15629 : :
15630 : 0 : c_parser_consume_token (parser);
15631 : 0 : while (true)
15632 : : {
15633 : 0 : tree property;
15634 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15635 : : {
15636 : 0 : c_parser_error (parser, "expected identifier");
15637 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15638 : 0 : parser->error = false;
15639 : 0 : return;
15640 : : }
15641 : 0 : property = c_parser_peek_token (parser)->value;
15642 : 0 : list = chainon (list, build_tree_list (NULL_TREE, property));
15643 : 0 : c_parser_consume_token (parser);
15644 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15645 : 0 : c_parser_consume_token (parser);
15646 : : else
15647 : : break;
15648 : 0 : }
15649 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15650 : 0 : objc_add_dynamic_declaration (loc, list);
15651 : : }
15652 : :
15653 : :
15654 : : /* Parse a pragma GCC ivdep. */
15655 : :
15656 : : static bool
15657 : 128 : c_parse_pragma_ivdep (c_parser *parser)
15658 : : {
15659 : 0 : c_parser_consume_pragma (parser);
15660 : 0 : c_parser_skip_to_pragma_eol (parser);
15661 : 128 : return true;
15662 : : }
15663 : :
15664 : : /* Parse a pragma GCC novector. */
15665 : :
15666 : : static bool
15667 : 2478 : c_parse_pragma_novector (c_parser *parser)
15668 : : {
15669 : 0 : c_parser_consume_pragma (parser);
15670 : 0 : c_parser_skip_to_pragma_eol (parser);
15671 : 2478 : return true;
15672 : : }
15673 : :
15674 : : /* Parse a pragma GCC unroll. */
15675 : :
15676 : : static unsigned short
15677 : 277 : c_parser_pragma_unroll (c_parser *parser)
15678 : : {
15679 : 277 : unsigned short unroll;
15680 : 277 : c_parser_consume_pragma (parser);
15681 : 277 : location_t location = c_parser_peek_token (parser)->location;
15682 : 277 : tree expr = c_parser_expr_no_commas (parser, NULL).value;
15683 : 277 : mark_exp_read (expr);
15684 : 277 : expr = c_fully_fold (expr, false, NULL);
15685 : 277 : HOST_WIDE_INT lunroll = 0;
15686 : 554 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
15687 : 276 : || TREE_CODE (expr) != INTEGER_CST
15688 : 275 : || (lunroll = tree_to_shwi (expr)) < 0
15689 : 551 : || lunroll >= USHRT_MAX)
15690 : : {
15691 : 4 : error_at (location, "%<#pragma GCC unroll%> requires an"
15692 : : " assignment-expression that evaluates to a non-negative"
15693 : : " integral constant less than %u", USHRT_MAX);
15694 : 4 : unroll = 0;
15695 : : }
15696 : : else
15697 : : {
15698 : 273 : unroll = (unsigned short)lunroll;
15699 : 273 : if (unroll == 0)
15700 : : unroll = 1;
15701 : : }
15702 : :
15703 : 277 : c_parser_skip_to_pragma_eol (parser);
15704 : 277 : return unroll;
15705 : : }
15706 : :
15707 : : /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
15708 : : should be considered, statements. ALLOW_STMT is true if we're within
15709 : : the context of a function and such pragmas are to be allowed. Returns
15710 : : true if we actually parsed such a pragma. BEFORE_LABELS is last statement
15711 : : before possible labels, see get_before_labels description for details. */
15712 : :
15713 : : static bool
15714 : 1946464 : c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
15715 : : tree before_labels)
15716 : : {
15717 : 1946464 : unsigned int id;
15718 : 1946464 : const char *construct = NULL;
15719 : :
15720 : 1946464 : input_location = c_parser_peek_token (parser)->location;
15721 : 1946464 : id = c_parser_peek_token (parser)->pragma_kind;
15722 : 1946464 : gcc_assert (id != PRAGMA_NONE);
15723 : 1946464 : if (parser->omp_for_parse_state
15724 : 12 : && parser->omp_for_parse_state->in_intervening_code
15725 : : && id >= PRAGMA_OMP__START_
15726 : 9 : && id <= PRAGMA_OMP__LAST_)
15727 : : {
15728 : 3 : error_at (input_location,
15729 : : "intervening code must not contain OpenMP directives");
15730 : 3 : parser->omp_for_parse_state->fail = true;
15731 : 3 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15732 : 3 : return false;
15733 : : }
15734 : :
15735 : 1946461 : switch (id)
15736 : : {
15737 : 144 : case PRAGMA_OACC_DECLARE:
15738 : 144 : c_parser_oacc_declare (parser);
15739 : 144 : return false;
15740 : :
15741 : 136 : case PRAGMA_OACC_ENTER_DATA:
15742 : 136 : if (context != pragma_compound)
15743 : : {
15744 : : construct = "acc enter data";
15745 : 62 : in_compound:
15746 : 62 : if (context == pragma_stmt)
15747 : : {
15748 : 59 : error_at (c_parser_peek_token (parser)->location,
15749 : : "%<#pragma %s%> may only be used in compound "
15750 : : "statements", construct);
15751 : 59 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15752 : 59 : return true;
15753 : : }
15754 : 3 : goto bad_stmt;
15755 : : }
15756 : 133 : c_parser_oacc_enter_exit_data (parser, true);
15757 : 133 : return false;
15758 : :
15759 : 131 : case PRAGMA_OACC_EXIT_DATA:
15760 : 131 : if (context != pragma_compound)
15761 : : {
15762 : 3 : construct = "acc exit data";
15763 : 3 : goto in_compound;
15764 : : }
15765 : 128 : c_parser_oacc_enter_exit_data (parser, false);
15766 : 128 : return false;
15767 : :
15768 : 350 : case PRAGMA_OACC_ROUTINE:
15769 : 350 : if (context != pragma_external)
15770 : : {
15771 : 5 : error_at (c_parser_peek_token (parser)->location,
15772 : : "%<#pragma acc routine%> must be at file scope");
15773 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15774 : 5 : return false;
15775 : : }
15776 : 345 : c_parser_oacc_routine (parser, context);
15777 : 345 : return false;
15778 : :
15779 : 100 : case PRAGMA_OACC_UPDATE:
15780 : 100 : if (context != pragma_compound)
15781 : : {
15782 : 8 : construct = "acc update";
15783 : 8 : goto in_compound;
15784 : : }
15785 : 92 : c_parser_oacc_update (parser);
15786 : 92 : return false;
15787 : :
15788 : 359 : case PRAGMA_OMP_BARRIER:
15789 : 359 : if (context != pragma_compound)
15790 : : {
15791 : 11 : construct = "omp barrier";
15792 : 11 : goto in_compound;
15793 : : }
15794 : 348 : c_parser_omp_barrier (parser);
15795 : 348 : return false;
15796 : :
15797 : 76 : case PRAGMA_OMP_DEPOBJ:
15798 : 76 : if (context != pragma_compound)
15799 : : {
15800 : 1 : construct = "omp depobj";
15801 : 1 : goto in_compound;
15802 : : }
15803 : 75 : c_parser_omp_depobj (parser);
15804 : 75 : return false;
15805 : :
15806 : 70 : case PRAGMA_OMP_FLUSH:
15807 : 70 : if (context != pragma_compound)
15808 : : {
15809 : 9 : construct = "omp flush";
15810 : 9 : goto in_compound;
15811 : : }
15812 : 61 : c_parser_omp_flush (parser);
15813 : 61 : return false;
15814 : :
15815 : 183 : case PRAGMA_OMP_INTEROP:
15816 : 183 : if (context != pragma_compound)
15817 : : {
15818 : 0 : construct = "omp interop";
15819 : 0 : goto in_compound;
15820 : : }
15821 : 183 : c_parser_omp_interop (parser);
15822 : 183 : return false;
15823 : :
15824 : 101 : case PRAGMA_OMP_TASKWAIT:
15825 : 101 : if (context != pragma_compound)
15826 : : {
15827 : 8 : construct = "omp taskwait";
15828 : 8 : goto in_compound;
15829 : : }
15830 : 93 : c_parser_omp_taskwait (parser);
15831 : 93 : return false;
15832 : :
15833 : 14 : case PRAGMA_OMP_TASKYIELD:
15834 : 14 : if (context != pragma_compound)
15835 : : {
15836 : 8 : construct = "omp taskyield";
15837 : 8 : goto in_compound;
15838 : : }
15839 : 6 : c_parser_omp_taskyield (parser);
15840 : 6 : return false;
15841 : :
15842 : 221 : case PRAGMA_OMP_CANCEL:
15843 : 221 : if (context != pragma_compound)
15844 : : {
15845 : 8 : construct = "omp cancel";
15846 : 8 : goto in_compound;
15847 : : }
15848 : 213 : c_parser_omp_cancel (parser);
15849 : 213 : return false;
15850 : :
15851 : 179 : case PRAGMA_OMP_CANCELLATION_POINT:
15852 : 179 : return c_parser_omp_cancellation_point (parser, context);
15853 : :
15854 : 78 : case PRAGMA_OMP_THREADPRIVATE:
15855 : 78 : c_parser_omp_threadprivate (parser);
15856 : 78 : return false;
15857 : :
15858 : 7362 : case PRAGMA_OMP_TARGET:
15859 : 7362 : return c_parser_omp_target (parser, context, if_p);
15860 : :
15861 : 91 : case PRAGMA_OMP_BEGIN:
15862 : 91 : c_parser_omp_begin (parser);
15863 : 91 : return false;
15864 : :
15865 : 199 : case PRAGMA_OMP_END:
15866 : 199 : c_parser_omp_end (parser);
15867 : 199 : return false;
15868 : :
15869 : 22 : case PRAGMA_OMP_SCAN:
15870 : 22 : error_at (c_parser_peek_token (parser)->location,
15871 : : "%<#pragma omp scan%> may only be used in "
15872 : : "a loop construct with %<inscan%> %<reduction%> clause");
15873 : 22 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15874 : 22 : return false;
15875 : :
15876 : 5 : case PRAGMA_OMP_SECTION:
15877 : 5 : error_at (c_parser_peek_token (parser)->location,
15878 : : "%<#pragma omp section%> may only be used in "
15879 : : "%<#pragma omp sections%> construct");
15880 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15881 : 5 : return false;
15882 : :
15883 : 1201 : case PRAGMA_OMP_DECLARE:
15884 : 1201 : return c_parser_omp_declare (parser, context);
15885 : :
15886 : 70 : case PRAGMA_OMP_REQUIRES:
15887 : 70 : if (context != pragma_external)
15888 : : {
15889 : 8 : error_at (c_parser_peek_token (parser)->location,
15890 : : "%<#pragma %s%> may only be used at file scope",
15891 : : "omp requires");
15892 : 8 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15893 : 8 : return false;
15894 : : }
15895 : 62 : c_parser_omp_requires (parser);
15896 : 62 : return false;
15897 : :
15898 : 69 : case PRAGMA_OMP_ALLOCATE:
15899 : 69 : c_parser_omp_allocate (parser);
15900 : 69 : return false;
15901 : :
15902 : 38 : case PRAGMA_OMP_ASSUMES:
15903 : 38 : if (context != pragma_external)
15904 : : {
15905 : 1 : error_at (c_parser_peek_token (parser)->location,
15906 : : "%<#pragma %s%> may only be used at file scope",
15907 : : "omp assumes");
15908 : 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15909 : 1 : return false;
15910 : : }
15911 : 37 : c_parser_omp_assumes (parser);
15912 : 37 : return false;
15913 : :
15914 : 79 : case PRAGMA_OMP_NOTHING:
15915 : 79 : c_parser_omp_nothing (parser);
15916 : 79 : return false;
15917 : :
15918 : 108 : case PRAGMA_OMP_METADIRECTIVE:
15919 : 108 : c_parser_omp_metadirective (parser, if_p);
15920 : 108 : return true;
15921 : :
15922 : 124 : case PRAGMA_OMP_ERROR:
15923 : 124 : return c_parser_omp_error (parser, context);
15924 : :
15925 : 543 : case PRAGMA_OMP_ORDERED:
15926 : 543 : return c_parser_omp_ordered (parser, context, if_p);
15927 : :
15928 : 2867 : case PRAGMA_NOVECTOR:
15929 : 2867 : case PRAGMA_UNROLL:
15930 : 2867 : case PRAGMA_IVDEP:
15931 : 2867 : {
15932 : 2867 : bool novector = false;
15933 : 2867 : unsigned short unroll = 0;
15934 : 2867 : bool ivdep = false;
15935 : :
15936 : 2867 : switch (id)
15937 : : {
15938 : 2474 : case PRAGMA_NOVECTOR:
15939 : 2474 : novector = c_parse_pragma_novector (parser);
15940 : 2474 : break;
15941 : 268 : case PRAGMA_UNROLL:
15942 : 268 : unroll = c_parser_pragma_unroll (parser);
15943 : 268 : break;
15944 : 125 : case PRAGMA_IVDEP:
15945 : 125 : ivdep = c_parse_pragma_ivdep (parser);
15946 : 125 : break;
15947 : : default:
15948 : : gcc_unreachable ();
15949 : : }
15950 : :
15951 : 2867 : c_token *tok = c_parser_peek_token (parser);
15952 : 2867 : bool has_more = tok->type == CPP_PRAGMA;
15953 : 2883 : while (has_more)
15954 : : {
15955 : 16 : switch (tok->pragma_kind)
15956 : : {
15957 : 3 : case PRAGMA_IVDEP:
15958 : 3 : ivdep = c_parse_pragma_ivdep (parser);
15959 : 3 : break;
15960 : 9 : case PRAGMA_UNROLL:
15961 : 9 : unroll = c_parser_pragma_unroll (parser);
15962 : 9 : break;
15963 : 4 : case PRAGMA_NOVECTOR:
15964 : 4 : novector = c_parse_pragma_novector (parser);
15965 : 4 : break;
15966 : : default:
15967 : : has_more = false;
15968 : : break;
15969 : : }
15970 : 16 : tok = c_parser_peek_token (parser);
15971 : 16 : has_more = has_more && tok->type == CPP_PRAGMA;
15972 : : }
15973 : 2867 : if (!c_parser_next_token_is_keyword (parser, RID_FOR)
15974 : 74 : && !c_parser_next_token_is_keyword (parser, RID_WHILE)
15975 : 2926 : && !c_parser_next_token_is_keyword (parser, RID_DO))
15976 : : {
15977 : 0 : c_parser_error (parser, "for, while or do statement expected");
15978 : 0 : return false;
15979 : : }
15980 : 2867 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
15981 : 2793 : c_parser_for_statement (parser, ivdep, unroll, novector, if_p,
15982 : : before_labels);
15983 : 74 : else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
15984 : 15 : c_parser_while_statement (parser, ivdep, unroll, novector, if_p,
15985 : : before_labels);
15986 : : else
15987 : 59 : c_parser_do_statement (parser, ivdep, unroll, novector,
15988 : : before_labels);
15989 : : }
15990 : : return true;
15991 : :
15992 : 1 : case PRAGMA_GCC_PCH_PREPROCESS:
15993 : 1 : c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
15994 : 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15995 : 1 : return false;
15996 : :
15997 : 83 : case PRAGMA_OACC_WAIT:
15998 : 83 : if (context != pragma_compound)
15999 : : {
16000 : 3 : construct = "acc wait";
16001 : 3 : goto in_compound;
16002 : : }
16003 : : /* FALL THROUGH. */
16004 : :
16005 : 1931537 : default:
16006 : 1931537 : if (id < PRAGMA_FIRST_EXTERNAL)
16007 : : {
16008 : 17224 : if (context != pragma_stmt && context != pragma_compound)
16009 : : {
16010 : 2 : bad_stmt:
16011 : 5 : c_parser_error (parser, "expected declaration specifiers");
16012 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16013 : 5 : return false;
16014 : : }
16015 : 17222 : c_parser_omp_construct (parser, if_p);
16016 : 17222 : return true;
16017 : : }
16018 : 1914313 : break;
16019 : : }
16020 : :
16021 : 1914313 : c_parser_consume_pragma (parser);
16022 : 1914313 : c_invoke_pragma_handler (id);
16023 : :
16024 : : /* Skip to EOL, but suppress any error message. Those will have been
16025 : : generated by the handler routine through calling error, as opposed
16026 : : to calling c_parser_error. */
16027 : 1914313 : parser->error = true;
16028 : 1914313 : c_parser_skip_to_pragma_eol (parser);
16029 : :
16030 : 1914313 : return false;
16031 : : }
16032 : :
16033 : : /* The interface the pragma parsers have to the lexer. */
16034 : :
16035 : : enum cpp_ttype
16036 : 3625099 : pragma_lex (tree *value, location_t *loc)
16037 : : {
16038 : 3625099 : c_token *tok = c_parser_peek_token (the_parser);
16039 : 3625099 : enum cpp_ttype ret = tok->type;
16040 : :
16041 : 3625099 : *value = tok->value;
16042 : 3625099 : if (loc)
16043 : 1506457 : *loc = tok->location;
16044 : :
16045 : 3625099 : if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
16046 : : ret = CPP_EOF;
16047 : 2039344 : else if (ret == CPP_STRING)
16048 : 640961 : *value = c_parser_string_literal (the_parser, false, false).value;
16049 : : else
16050 : : {
16051 : 1398383 : if (ret == CPP_KEYWORD)
16052 : 344 : ret = CPP_NAME;
16053 : 1398383 : c_parser_consume_token (the_parser);
16054 : : }
16055 : :
16056 : 3625099 : return ret;
16057 : : }
16058 : :
16059 : : void
16060 : 9496 : pragma_lex_discard_to_eol ()
16061 : : {
16062 : 9496 : cpp_ttype type;
16063 : 9496 : do
16064 : : {
16065 : 9496 : type = c_parser_peek_token (the_parser)->type;
16066 : 9496 : gcc_assert (type != CPP_EOF);
16067 : 9496 : c_parser_consume_token (the_parser);
16068 : 9496 : } while (type != CPP_PRAGMA_EOL);
16069 : 9496 : }
16070 : :
16071 : : static void
16072 : 12 : c_parser_pragma_pch_preprocess (c_parser *parser)
16073 : : {
16074 : 12 : tree name = NULL;
16075 : :
16076 : 12 : parser->lex_joined_string = true;
16077 : 12 : c_parser_consume_pragma (parser);
16078 : 12 : if (c_parser_next_token_is (parser, CPP_STRING))
16079 : : {
16080 : 12 : name = c_parser_peek_token (parser)->value;
16081 : 12 : c_parser_consume_token (parser);
16082 : : }
16083 : : else
16084 : 0 : c_parser_error (parser, "expected string literal");
16085 : 12 : c_parser_skip_to_pragma_eol (parser);
16086 : 12 : parser->lex_joined_string = false;
16087 : :
16088 : 12 : if (name)
16089 : 12 : c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
16090 : 12 : }
16091 : :
16092 : : /* OpenACC and OpenMP parsing routines. */
16093 : :
16094 : : /* Returns name of the next clause.
16095 : : If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
16096 : : the token is not consumed. Otherwise appropriate pragma_omp_clause is
16097 : : returned and the token is consumed. */
16098 : :
16099 : : static pragma_omp_clause
16100 : 34036 : c_parser_omp_clause_name (c_parser *parser)
16101 : : {
16102 : 34036 : pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
16103 : :
16104 : 34036 : if (c_parser_next_token_is_keyword (parser, RID_AUTO))
16105 : : result = PRAGMA_OACC_CLAUSE_AUTO;
16106 : 33911 : else if (c_parser_next_token_is_keyword (parser, RID_IF))
16107 : : result = PRAGMA_OMP_CLAUSE_IF;
16108 : 33034 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
16109 : : result = PRAGMA_OMP_CLAUSE_DEFAULT;
16110 : 32306 : else if (c_parser_next_token_is_keyword (parser, RID_FOR))
16111 : : result = PRAGMA_OMP_CLAUSE_FOR;
16112 : 32222 : else if (c_parser_next_token_is (parser, CPP_NAME))
16113 : : {
16114 : 32139 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16115 : :
16116 : 32139 : switch (p[0])
16117 : : {
16118 : 1108 : case 'a':
16119 : 1108 : if (!strcmp ("affinity", p))
16120 : : result = PRAGMA_OMP_CLAUSE_AFFINITY;
16121 : 962 : else if (!strcmp ("aligned", p))
16122 : : result = PRAGMA_OMP_CLAUSE_ALIGNED;
16123 : 734 : else if (!strcmp ("allocate", p))
16124 : : result = PRAGMA_OMP_CLAUSE_ALLOCATE;
16125 : 267 : else if (!strcmp ("async", p))
16126 : : result = PRAGMA_OACC_CLAUSE_ASYNC;
16127 : 30 : else if (!strcmp ("attach", p))
16128 : 34036 : result = PRAGMA_OACC_CLAUSE_ATTACH;
16129 : : break;
16130 : 116 : case 'b':
16131 : 116 : if (!strcmp ("bind", p))
16132 : 34036 : result = PRAGMA_OMP_CLAUSE_BIND;
16133 : : break;
16134 : 4583 : case 'c':
16135 : 4583 : if (!strcmp ("collapse", p))
16136 : : result = PRAGMA_OMP_CLAUSE_COLLAPSE;
16137 : 1638 : else if (!strcmp ("copy", p))
16138 : : result = PRAGMA_OACC_CLAUSE_COPY;
16139 : 854 : else if (!strcmp ("copyin", p))
16140 : : result = PRAGMA_OMP_CLAUSE_COPYIN;
16141 : 419 : else if (!strcmp ("copyout", p))
16142 : : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16143 : 96 : else if (!strcmp ("copyprivate", p))
16144 : : result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
16145 : 75 : else if (!strcmp ("create", p))
16146 : 34036 : result = PRAGMA_OACC_CLAUSE_CREATE;
16147 : : break;
16148 : 3503 : case 'd':
16149 : 3503 : if (!strcmp ("defaultmap", p))
16150 : : result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
16151 : 3264 : else if (!strcmp ("delete", p))
16152 : : result = PRAGMA_OACC_CLAUSE_DELETE;
16153 : 3196 : else if (!strcmp ("depend", p))
16154 : : result = PRAGMA_OMP_CLAUSE_DEPEND;
16155 : 2341 : else if (!strcmp ("destroy", p))
16156 : : result = PRAGMA_OMP_CLAUSE_DESTROY;
16157 : 2300 : else if (!strcmp ("detach", p))
16158 : : result = PRAGMA_OACC_CLAUSE_DETACH;
16159 : 2246 : else if (!strcmp ("device", p))
16160 : : result = PRAGMA_OMP_CLAUSE_DEVICE;
16161 : 1843 : else if (!strcmp ("deviceptr", p))
16162 : : result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
16163 : 1786 : else if (!strcmp ("device_resident", p))
16164 : : result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
16165 : 1770 : else if (!strcmp ("device_type", p))
16166 : : result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
16167 : 1728 : else if (!strcmp ("dist_schedule", p))
16168 : : result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
16169 : 146 : else if (!strcmp ("doacross", p))
16170 : 34036 : result = PRAGMA_OMP_CLAUSE_DOACROSS;
16171 : : break;
16172 : 41 : case 'e':
16173 : 41 : if (!strcmp ("enter", p))
16174 : 34036 : result = PRAGMA_OMP_CLAUSE_ENTER;
16175 : : break;
16176 : 3468 : case 'f':
16177 : 3468 : if (!strcmp ("filter", p))
16178 : : result = PRAGMA_OMP_CLAUSE_FILTER;
16179 : 3406 : else if (!strcmp ("final", p))
16180 : : result = PRAGMA_OMP_CLAUSE_FINAL;
16181 : 3308 : else if (!strcmp ("finalize", p))
16182 : : result = PRAGMA_OACC_CLAUSE_FINALIZE;
16183 : 3296 : else if (!strcmp ("firstprivate", p))
16184 : : result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
16185 : 2518 : else if (!strcmp ("from", p))
16186 : : result = PRAGMA_OMP_CLAUSE_FROM;
16187 : 71 : else if (!strcmp ("full", p))
16188 : 34036 : result = PRAGMA_OMP_CLAUSE_FULL;
16189 : : break;
16190 : 651 : case 'g':
16191 : 651 : if (!strcmp ("gang", p))
16192 : : result = PRAGMA_OACC_CLAUSE_GANG;
16193 : 62 : else if (!strcmp ("grainsize", p))
16194 : 34036 : result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
16195 : : break;
16196 : 157 : case 'h':
16197 : 157 : if (!strcmp ("has_device_addr", p))
16198 : : result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
16199 : 70 : else if (!strcmp ("hint", p))
16200 : : result = PRAGMA_OMP_CLAUSE_HINT;
16201 : 41 : else if (!strcmp ("host", p))
16202 : 34036 : result = PRAGMA_OACC_CLAUSE_HOST;
16203 : : break;
16204 : 796 : case 'i':
16205 : 796 : if (!strcmp ("if_present", p))
16206 : : result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
16207 : 777 : else if (!strcmp ("in_reduction", p))
16208 : : result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
16209 : 457 : else if (!strcmp ("inbranch", p))
16210 : : result = PRAGMA_OMP_CLAUSE_INBRANCH;
16211 : 394 : else if (!strcmp ("independent", p))
16212 : : result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
16213 : 349 : else if (!strcmp ("indirect", p))
16214 : : result = PRAGMA_OMP_CLAUSE_INDIRECT;
16215 : 323 : else if (!strcmp ("init", p))
16216 : : result = PRAGMA_OMP_CLAUSE_INIT;
16217 : 156 : else if (!strcmp ("is_device_ptr", p))
16218 : : result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
16219 : 42 : else if (!strcmp ("interop", p))
16220 : 34036 : result = PRAGMA_OMP_CLAUSE_INTEROP;
16221 : : break;
16222 : 1250 : case 'l':
16223 : 1250 : if (!strcmp ("lastprivate", p))
16224 : : result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
16225 : 519 : else if (!strcmp ("linear", p))
16226 : : result = PRAGMA_OMP_CLAUSE_LINEAR;
16227 : 45 : else if (!strcmp ("link", p))
16228 : 34036 : result = PRAGMA_OMP_CLAUSE_LINK;
16229 : : break;
16230 : 1784 : case 'm':
16231 : 1784 : if (!strcmp ("map", p))
16232 : : result = PRAGMA_OMP_CLAUSE_MAP;
16233 : 78 : else if (!strcmp ("mergeable", p))
16234 : 34036 : result = PRAGMA_OMP_CLAUSE_MERGEABLE;
16235 : : break;
16236 : 1922 : case 'n':
16237 : 1922 : if (!strcmp ("no_create", p))
16238 : : result = PRAGMA_OACC_CLAUSE_NO_CREATE;
16239 : 1912 : else if (!strcmp ("nocontext", p))
16240 : : result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
16241 : 1889 : else if (!strcmp ("nogroup", p))
16242 : : result = PRAGMA_OMP_CLAUSE_NOGROUP;
16243 : 1871 : else if (!strcmp ("nohost", p))
16244 : : result = PRAGMA_OACC_CLAUSE_NOHOST;
16245 : 1846 : else if (!strcmp ("nontemporal", p))
16246 : : result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
16247 : 1725 : else if (!strcmp ("notinbranch", p))
16248 : : result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
16249 : 1589 : else if (!strcmp ("novariants", p))
16250 : : result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
16251 : 1568 : else if (!strcmp ("nowait", p))
16252 : : result = PRAGMA_OMP_CLAUSE_NOWAIT;
16253 : 1177 : else if (!strcmp ("num_gangs", p))
16254 : : result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
16255 : 875 : else if (!strcmp ("num_tasks", p))
16256 : : result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
16257 : 826 : else if (!strcmp ("num_teams", p))
16258 : : result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
16259 : 631 : else if (!strcmp ("num_threads", p))
16260 : : result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
16261 : 207 : else if (!strcmp ("num_workers", p))
16262 : 34036 : result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
16263 : : break;
16264 : 689 : case 'o':
16265 : 689 : if (!strcmp ("ordered", p))
16266 : : result = PRAGMA_OMP_CLAUSE_ORDERED;
16267 : 380 : else if (!strcmp ("order", p))
16268 : 34036 : result = PRAGMA_OMP_CLAUSE_ORDER;
16269 : : break;
16270 : 1634 : case 'p':
16271 : 1634 : if (!strcmp ("parallel", p))
16272 : : result = PRAGMA_OMP_CLAUSE_PARALLEL;
16273 : 1527 : else if (!strcmp ("partial", p))
16274 : : result = PRAGMA_OMP_CLAUSE_PARTIAL;
16275 : 1297 : else if (!strcmp ("present", p))
16276 : : result = PRAGMA_OACC_CLAUSE_PRESENT;
16277 : : /* As of OpenACC 2.5, these are now aliases of the non-present_or
16278 : : clauses. */
16279 : 1169 : else if (!strcmp ("present_or_copy", p)
16280 : 1156 : || !strcmp ("pcopy", p))
16281 : : result = PRAGMA_OACC_CLAUSE_COPY;
16282 : 1147 : else if (!strcmp ("present_or_copyin", p)
16283 : 1131 : || !strcmp ("pcopyin", p))
16284 : : result = PRAGMA_OACC_CLAUSE_COPYIN;
16285 : 1122 : else if (!strcmp ("present_or_copyout", p)
16286 : 1069 : || !strcmp ("pcopyout", p))
16287 : : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16288 : 1055 : else if (!strcmp ("present_or_create", p)
16289 : 1041 : || !strcmp ("pcreate", p))
16290 : : result = PRAGMA_OACC_CLAUSE_CREATE;
16291 : 1036 : else if (!strcmp ("priority", p))
16292 : : result = PRAGMA_OMP_CLAUSE_PRIORITY;
16293 : 939 : else if (!strcmp ("private", p))
16294 : : result = PRAGMA_OMP_CLAUSE_PRIVATE;
16295 : 204 : else if (!strcmp ("proc_bind", p))
16296 : 34036 : result = PRAGMA_OMP_CLAUSE_PROC_BIND;
16297 : : break;
16298 : 2683 : case 'r':
16299 : 2683 : if (!strcmp ("reduction", p))
16300 : 34036 : result = PRAGMA_OMP_CLAUSE_REDUCTION;
16301 : : break;
16302 : 5162 : case 's':
16303 : 5162 : if (!strcmp ("safelen", p))
16304 : : result = PRAGMA_OMP_CLAUSE_SAFELEN;
16305 : 4935 : else if (!strcmp ("schedule", p))
16306 : : result = PRAGMA_OMP_CLAUSE_SCHEDULE;
16307 : 1468 : else if (!strcmp ("sections", p))
16308 : : result = PRAGMA_OMP_CLAUSE_SECTIONS;
16309 : 1390 : else if (!strcmp ("self", p))
16310 : : result = PRAGMA_OACC_CLAUSE_SELF;
16311 : 1324 : else if (!strcmp ("seq", p))
16312 : : result = PRAGMA_OACC_CLAUSE_SEQ;
16313 : 1063 : else if (!strcmp ("shared", p))
16314 : : result = PRAGMA_OMP_CLAUSE_SHARED;
16315 : 374 : else if (!strcmp ("simd", p))
16316 : : result = PRAGMA_OMP_CLAUSE_SIMD;
16317 : 317 : else if (!strcmp ("simdlen", p))
16318 : 34036 : result = PRAGMA_OMP_CLAUSE_SIMDLEN;
16319 : : break;
16320 : 988 : case 't':
16321 : 988 : if (!strcmp ("task_reduction", p))
16322 : : result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
16323 : 902 : else if (!strcmp ("taskgroup", p))
16324 : : result = PRAGMA_OMP_CLAUSE_TASKGROUP;
16325 : 792 : else if (!strcmp ("thread_limit", p))
16326 : : result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
16327 : 638 : else if (!strcmp ("threads", p))
16328 : : result = PRAGMA_OMP_CLAUSE_THREADS;
16329 : 592 : else if (!strcmp ("tile", p))
16330 : : result = PRAGMA_OACC_CLAUSE_TILE;
16331 : 469 : else if (!strcmp ("to", p))
16332 : 34036 : result = PRAGMA_OMP_CLAUSE_TO;
16333 : : break;
16334 : 320 : case 'u':
16335 : 320 : if (!strcmp ("uniform", p))
16336 : : result = PRAGMA_OMP_CLAUSE_UNIFORM;
16337 : 205 : else if (!strcmp ("untied", p))
16338 : : result = PRAGMA_OMP_CLAUSE_UNTIED;
16339 : 109 : else if (!strcmp ("use", p))
16340 : : result = PRAGMA_OMP_CLAUSE_USE;
16341 : 66 : else if (!strcmp ("use_device", p))
16342 : : result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
16343 : 45 : else if (!strcmp ("use_device_addr", p))
16344 : : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
16345 : 10 : else if (!strcmp ("use_device_ptr", p))
16346 : 34036 : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
16347 : : break;
16348 : 741 : case 'v':
16349 : 741 : if (!strcmp ("vector", p))
16350 : : result = PRAGMA_OACC_CLAUSE_VECTOR;
16351 : 223 : else if (!strcmp ("vector_length", p))
16352 : 34036 : result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
16353 : : break;
16354 : 542 : case 'w':
16355 : 542 : if (!strcmp ("wait", p))
16356 : : result = PRAGMA_OACC_CLAUSE_WAIT;
16357 : 453 : else if (!strcmp ("worker", p))
16358 : 34036 : result = PRAGMA_OACC_CLAUSE_WORKER;
16359 : : break;
16360 : : }
16361 : : }
16362 : :
16363 : 34036 : if (result != PRAGMA_OMP_CLAUSE_NONE)
16364 : 33927 : c_parser_consume_token (parser);
16365 : :
16366 : 34036 : return result;
16367 : : }
16368 : :
16369 : : /* Validate that a clause of the given type does not already exist. */
16370 : :
16371 : : static void
16372 : 17522 : check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
16373 : : const char *name)
16374 : : {
16375 : 17522 : if (tree c = omp_find_clause (clauses, code))
16376 : 347 : error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
16377 : 17522 : }
16378 : :
16379 : : /* OpenACC 2.0
16380 : : Parse wait clause or wait directive parameters. */
16381 : :
16382 : : static tree
16383 : 117 : c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
16384 : : {
16385 : 117 : vec<tree, va_gc> *args;
16386 : 117 : tree t, args_tree;
16387 : :
16388 : 117 : matching_parens parens;
16389 : 117 : if (!parens.require_open (parser))
16390 : : return list;
16391 : :
16392 : 117 : args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL);
16393 : 117 : args_tree = build_tree_list_vec (args);
16394 : :
16395 : 277 : for (t = args_tree; t; t = TREE_CHAIN (t))
16396 : : {
16397 : 160 : tree targ = TREE_VALUE (t);
16398 : :
16399 : 160 : if (targ != error_mark_node)
16400 : : {
16401 : 146 : if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
16402 : : {
16403 : 6 : c_parser_error (parser, "expression must be integral");
16404 : 6 : targ = error_mark_node;
16405 : : }
16406 : : else
16407 : : {
16408 : 140 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16409 : :
16410 : 140 : OMP_CLAUSE_DECL (c) = targ;
16411 : 140 : OMP_CLAUSE_CHAIN (c) = list;
16412 : 140 : list = c;
16413 : : }
16414 : : }
16415 : : }
16416 : :
16417 : 117 : release_tree_vector (args);
16418 : 117 : parens.require_close (parser);
16419 : 117 : return list;
16420 : : }
16421 : :
16422 : : /* OpenACC 2.0, OpenMP 2.5:
16423 : : variable-list:
16424 : : identifier
16425 : : variable-list , identifier
16426 : :
16427 : : If KIND is nonzero, create the appropriate node and install the
16428 : : decl in OMP_CLAUSE_DECL and add the node to the head of the list.
16429 : : If KIND is nonzero, CLAUSE_LOC is the location of the clause.
16430 : :
16431 : : If KIND is zero (= OMP_CLAUSE_ERROR), create a TREE_LIST with the decl
16432 : : in TREE_PURPOSE and the location in TREE_VALUE (accessible using
16433 : : EXPR_LOCATION); return the list created.
16434 : :
16435 : : The optional ALLOW_DEREF argument is true if list items can use the deref
16436 : : (->) operator. */
16437 : :
16438 : : struct omp_dim
16439 : : {
16440 : : tree low_bound, length;
16441 : : location_t loc;
16442 : : bool no_colon;
16443 : 3269 : omp_dim (tree lb, tree len, location_t lo, bool nc)
16444 : 3269 : : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
16445 : : };
16446 : :
16447 : : static tree
16448 : 16226 : c_parser_omp_variable_list (c_parser *parser,
16449 : : location_t clause_loc,
16450 : : enum omp_clause_code kind, tree list,
16451 : : bool map_lvalue = false)
16452 : : {
16453 : 16226 : auto_vec<omp_dim> dims;
16454 : 16226 : bool array_section_p;
16455 : 16226 : auto_vec<c_token> tokens;
16456 : 16226 : unsigned int tokens_avail = 0;
16457 : 16226 : c_token *saved_tokens = NULL;
16458 : :
16459 : 19403 : while (1)
16460 : : {
16461 : 19403 : tree t = NULL_TREE;
16462 : 19403 : location_t tloc = c_parser_peek_token (parser)->location;
16463 : :
16464 : 19403 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16465 : : {
16466 : 888 : if (c_parser_next_token_is_not (parser, CPP_NAME)
16467 : 888 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
16468 : : {
16469 : 29 : struct c_expr expr;
16470 : 29 : if (kind == OMP_CLAUSE_DEPEND
16471 : 27 : && c_parser_next_token_is_keyword (parser,
16472 : : RID_OMP_ALL_MEMORY)
16473 : 45 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16474 : 13 : || (c_parser_peek_2nd_token (parser)->type
16475 : : == CPP_CLOSE_PAREN)))
16476 : : {
16477 : 15 : expr.value = ridpointers[RID_OMP_ALL_MEMORY];
16478 : 15 : c_parser_consume_token (parser);
16479 : : }
16480 : : else
16481 : 14 : expr = c_parser_expr_no_commas (parser, NULL);
16482 : 29 : if (expr.value != error_mark_node)
16483 : : {
16484 : 27 : tree u = build_omp_clause (clause_loc, kind);
16485 : 27 : OMP_CLAUSE_DECL (u) = expr.value;
16486 : 27 : OMP_CLAUSE_CHAIN (u) = list;
16487 : 27 : list = u;
16488 : : }
16489 : :
16490 : 29 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
16491 : : break;
16492 : :
16493 : 4 : c_parser_consume_token (parser);
16494 : 4 : continue;
16495 : 4 : }
16496 : :
16497 : 859 : tokens.truncate (0);
16498 : 859 : unsigned int nesting_depth = 0;
16499 : 11227 : while (1)
16500 : : {
16501 : 6043 : c_token *token = c_parser_peek_token (parser);
16502 : 6043 : switch (token->type)
16503 : : {
16504 : : case CPP_EOF:
16505 : : case CPP_PRAGMA_EOL:
16506 : : break;
16507 : 930 : case CPP_OPEN_BRACE:
16508 : 930 : case CPP_OPEN_PAREN:
16509 : 930 : case CPP_OPEN_SQUARE:
16510 : 930 : ++nesting_depth;
16511 : 930 : goto add;
16512 : 1723 : case CPP_CLOSE_BRACE:
16513 : 1723 : case CPP_CLOSE_PAREN:
16514 : 1723 : case CPP_CLOSE_SQUARE:
16515 : 1723 : if (nesting_depth-- == 0)
16516 : : break;
16517 : 930 : goto add;
16518 : 138 : case CPP_COMMA:
16519 : 138 : if (nesting_depth == 0)
16520 : : break;
16521 : 72 : goto add;
16522 : 5184 : default:
16523 : 5184 : add:
16524 : 5184 : tokens.safe_push (*token);
16525 : 5184 : c_parser_consume_token (parser);
16526 : 5184 : continue;
16527 : : }
16528 : 859 : break;
16529 : 5184 : }
16530 : :
16531 : : /* Make sure nothing tries to read past the end of the tokens. */
16532 : 859 : c_token eof_token;
16533 : 859 : memset (&eof_token, 0, sizeof (eof_token));
16534 : 859 : eof_token.type = CPP_EOF;
16535 : 859 : tokens.safe_push (eof_token);
16536 : 859 : tokens.safe_push (eof_token);
16537 : :
16538 : 859 : saved_tokens = parser->tokens;
16539 : 859 : tokens_avail = parser->tokens_avail;
16540 : 859 : parser->tokens = tokens.address ();
16541 : 1718 : parser->tokens_avail = tokens.length ();
16542 : : }
16543 : 18515 : else if (map_lvalue
16544 : 2090 : && (kind == OMP_CLAUSE_MAP
16545 : : || kind == OMP_CLAUSE_TO
16546 : 2090 : || kind == OMP_CLAUSE_FROM))
16547 : : {
16548 : 2090 : location_t loc = c_parser_peek_token (parser)->location;
16549 : 2090 : bool save_c_omp_array_section_p = c_omp_array_section_p;
16550 : 2090 : c_omp_array_section_p = true;
16551 : 2090 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
16552 : 2090 : if (expr.value != error_mark_node)
16553 : 2082 : mark_exp_read (expr.value);
16554 : 2090 : c_omp_array_section_p = save_c_omp_array_section_p;
16555 : 2090 : tree decl = expr.value;
16556 : :
16557 : : /* This code rewrites a parsed expression containing various tree
16558 : : codes used to represent array accesses into a more uniform nest of
16559 : : OMP_ARRAY_SECTION nodes before it is processed by
16560 : : c-typeck.cc:handle_omp_array_sections_1. It might be more
16561 : : efficient to move this logic to that function instead, analysing
16562 : : the parsed expression directly rather than this preprocessed
16563 : : form. (See also equivalent code in cp/parser.cc,
16564 : : cp/semantics.cc). */
16565 : 2090 : dims.truncate (0);
16566 : 2090 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16567 : : {
16568 : 1034 : while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16569 : : {
16570 : 547 : tree low_bound = TREE_OPERAND (decl, 1);
16571 : 547 : tree length = TREE_OPERAND (decl, 2);
16572 : 547 : dims.safe_push (omp_dim (low_bound, length, loc, false));
16573 : 547 : decl = TREE_OPERAND (decl, 0);
16574 : : }
16575 : :
16576 : 513 : while (TREE_CODE (decl) == ARRAY_REF
16577 : : || TREE_CODE (decl) == INDIRECT_REF
16578 : 513 : || TREE_CODE (decl) == COMPOUND_EXPR)
16579 : : {
16580 : 26 : if (TREE_CODE (decl) == COMPOUND_EXPR)
16581 : : {
16582 : 2 : decl = TREE_OPERAND (decl, 1);
16583 : 2 : STRIP_NOPS (decl);
16584 : : }
16585 : 24 : else if (TREE_CODE (decl) == INDIRECT_REF)
16586 : : {
16587 : 34 : dims.safe_push (omp_dim (integer_zero_node,
16588 : 17 : integer_one_node, loc, true));
16589 : 17 : decl = TREE_OPERAND (decl, 0);
16590 : : }
16591 : : else /* ARRAY_REF. */
16592 : : {
16593 : 7 : tree index = TREE_OPERAND (decl, 1);
16594 : 14 : dims.safe_push (omp_dim (index, integer_one_node, loc,
16595 : 7 : true));
16596 : 7 : decl = TREE_OPERAND (decl, 0);
16597 : : }
16598 : : }
16599 : :
16600 : 1545 : for (int i = dims.length () - 1; i >= 0; i--)
16601 : 571 : decl = build_omp_array_section (loc, decl, dims[i].low_bound,
16602 : 571 : dims[i].length);
16603 : : }
16604 : 1603 : else if (TREE_CODE (decl) == INDIRECT_REF)
16605 : : {
16606 : : /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
16607 : 42 : decl = TREE_OPERAND (decl, 0);
16608 : 42 : STRIP_NOPS (decl);
16609 : :
16610 : 42 : decl = build_omp_array_section (loc, decl, integer_zero_node,
16611 : : integer_one_node);
16612 : : }
16613 : 1561 : else if (TREE_CODE (decl) == ARRAY_REF)
16614 : : {
16615 : 12 : tree idx = TREE_OPERAND (decl, 1);
16616 : :
16617 : 12 : decl = TREE_OPERAND (decl, 0);
16618 : 12 : STRIP_NOPS (decl);
16619 : :
16620 : 12 : decl = build_omp_array_section (loc, decl, idx, integer_one_node);
16621 : : }
16622 : 1549 : else if (TREE_CODE (decl) == NON_LVALUE_EXPR
16623 : 1549 : || CONVERT_EXPR_P (decl))
16624 : 0 : decl = TREE_OPERAND (decl, 0);
16625 : :
16626 : 2090 : tree u = build_omp_clause (clause_loc, kind);
16627 : 2090 : OMP_CLAUSE_DECL (u) = decl;
16628 : 2090 : OMP_CLAUSE_CHAIN (u) = list;
16629 : 2090 : list = u;
16630 : :
16631 : 2090 : goto next_item;
16632 : : }
16633 : :
16634 : 17284 : if (c_parser_next_token_is (parser, CPP_NAME)
16635 : 17284 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
16636 : : {
16637 : 17247 : t = lookup_name (c_parser_peek_token (parser)->value);
16638 : :
16639 : 17247 : if (t == NULL_TREE)
16640 : : {
16641 : 14 : undeclared_variable (c_parser_peek_token (parser)->location,
16642 : 14 : c_parser_peek_token (parser)->value);
16643 : 14 : t = error_mark_node;
16644 : : }
16645 : :
16646 : 17247 : c_parser_consume_token (parser);
16647 : : }
16648 : 37 : else if (c_parser_next_token_is (parser, CPP_KEYWORD)
16649 : 37 : && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
16650 : 15 : || (c_parser_peek_token (parser)->keyword
16651 : : == RID_PRETTY_FUNCTION_NAME)
16652 : 9 : || (c_parser_peek_token (parser)->keyword
16653 : : == RID_C99_FUNCTION_NAME)))
16654 : 20 : t = c_parser_predefined_identifier (parser).value;
16655 : : else
16656 : : {
16657 : 17 : c_parser_error (parser, "expected identifier");
16658 : 17 : break;
16659 : : }
16660 : :
16661 : 17267 : if (t == error_mark_node)
16662 : : ;
16663 : 17249 : else if (kind != 0) /* kind != OMP_CLAUSE_ERROR */
16664 : : {
16665 : 17022 : switch (kind)
16666 : : {
16667 : 139 : case OMP_CLAUSE__CACHE_:
16668 : : /* The OpenACC cache directive explicitly only allows "array
16669 : : elements or subarrays". */
16670 : 139 : if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
16671 : : {
16672 : 3 : c_parser_error (parser, "expected %<[%>");
16673 : 3 : t = error_mark_node;
16674 : 3 : break;
16675 : : }
16676 : : /* FALLTHROUGH */
16677 : : case OMP_CLAUSE_MAP:
16678 : : case OMP_CLAUSE_FROM:
16679 : : case OMP_CLAUSE_TO:
16680 : 136 : start_component_ref:
16681 : 5950 : while (c_parser_next_token_is (parser, CPP_DOT)
16682 : 11693 : || c_parser_next_token_is (parser, CPP_DEREF))
16683 : : {
16684 : 316 : location_t op_loc = c_parser_peek_token (parser)->location;
16685 : 316 : location_t arrow_loc = UNKNOWN_LOCATION;
16686 : 316 : if (c_parser_next_token_is (parser, CPP_DEREF))
16687 : : {
16688 : 109 : c_expr t_expr;
16689 : 109 : t_expr.value = t;
16690 : 109 : t_expr.original_code = ERROR_MARK;
16691 : 109 : t_expr.original_type = NULL;
16692 : 109 : set_c_expr_source_range (&t_expr, op_loc, op_loc);
16693 : 109 : t_expr.m_decimal = 0;
16694 : 109 : t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
16695 : : true, false);
16696 : 109 : t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
16697 : 109 : arrow_loc = t_expr.get_location ();
16698 : : }
16699 : 316 : c_parser_consume_token (parser);
16700 : 316 : if (!c_parser_next_token_is (parser, CPP_NAME))
16701 : : {
16702 : 0 : c_parser_error (parser, "expected identifier");
16703 : 0 : t = error_mark_node;
16704 : 0 : break;
16705 : : }
16706 : :
16707 : 316 : c_token *comp_tok = c_parser_peek_token (parser);
16708 : 316 : tree ident = comp_tok->value;
16709 : 316 : location_t comp_loc = comp_tok->location;
16710 : 316 : c_parser_consume_token (parser);
16711 : 316 : t = build_component_ref (op_loc, t, ident, comp_loc,
16712 : : arrow_loc);
16713 : : }
16714 : : /* FALLTHROUGH */
16715 : 10279 : case OMP_CLAUSE_AFFINITY:
16716 : 10279 : case OMP_CLAUSE_DEPEND:
16717 : 10279 : case OMP_CLAUSE_REDUCTION:
16718 : 10279 : case OMP_CLAUSE_IN_REDUCTION:
16719 : 10279 : case OMP_CLAUSE_TASK_REDUCTION:
16720 : 10279 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
16721 : 10279 : array_section_p = false;
16722 : 10279 : dims.truncate (0);
16723 : 23256 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
16724 : : {
16725 : 2698 : location_t loc = UNKNOWN_LOCATION;
16726 : 2698 : tree low_bound = NULL_TREE, length = NULL_TREE;
16727 : 2698 : bool no_colon = false;
16728 : :
16729 : 2698 : c_parser_consume_token (parser);
16730 : 2698 : if (!c_parser_next_token_is (parser, CPP_COLON))
16731 : : {
16732 : 2286 : location_t expr_loc
16733 : 2286 : = c_parser_peek_token (parser)->location;
16734 : 2286 : c_expr expr = c_parser_expression (parser);
16735 : 2286 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
16736 : : false, true);
16737 : 2286 : low_bound = expr.value;
16738 : 2286 : loc = expr_loc;
16739 : : }
16740 : 2698 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
16741 : : {
16742 : 418 : length = integer_one_node;
16743 : 418 : no_colon = true;
16744 : : }
16745 : : else
16746 : : {
16747 : : /* Look for `:'. */
16748 : 2280 : if (!c_parser_require (parser, CPP_COLON,
16749 : : "expected %<:%>"))
16750 : : {
16751 : 0 : t = error_mark_node;
16752 : 0 : break;
16753 : : }
16754 : 2280 : array_section_p = true;
16755 : 2280 : if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
16756 : : {
16757 : 2095 : location_t expr_loc
16758 : 2095 : = c_parser_peek_token (parser)->location;
16759 : 2095 : c_expr expr = c_parser_expression (parser);
16760 : 2095 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
16761 : : false, true);
16762 : 2095 : length = expr.value;
16763 : : }
16764 : : }
16765 : : /* Look for the closing `]'. */
16766 : 2698 : if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
16767 : : "expected %<]%>"))
16768 : : {
16769 : 0 : t = error_mark_node;
16770 : 0 : break;
16771 : : }
16772 : :
16773 : 2698 : dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
16774 : : }
16775 : :
16776 : 10279 : if (t != error_mark_node)
16777 : : {
16778 : 10279 : if ((kind == OMP_CLAUSE_MAP
16779 : 10279 : || kind == OMP_CLAUSE_FROM
16780 : 5177 : || kind == OMP_CLAUSE_TO)
16781 : 5498 : && !array_section_p
16782 : 14530 : && (c_parser_next_token_is (parser, CPP_DOT)
16783 : 4247 : || c_parser_next_token_is (parser, CPP_DEREF)))
16784 : : {
16785 : 8 : for (unsigned i = 0; i < dims.length (); i++)
16786 : : {
16787 : 4 : gcc_assert (dims[i].length == integer_one_node);
16788 : 4 : t = build_array_ref (dims[i].loc,
16789 : 4 : t, dims[i].low_bound);
16790 : : }
16791 : 4 : goto start_component_ref;
16792 : : }
16793 : : else
16794 : 12969 : for (unsigned i = 0; i < dims.length (); i++)
16795 : 5388 : t = build_omp_array_section (clause_loc, t,
16796 : 2694 : dims[i].low_bound,
16797 : 2694 : dims[i].length);
16798 : : }
16799 : :
16800 : 10275 : if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16801 : 855 : && t != error_mark_node
16802 : 855 : && parser->tokens_avail != 2)
16803 : : {
16804 : 44 : if (array_section_p)
16805 : : {
16806 : 12 : error_at (c_parser_peek_token (parser)->location,
16807 : : "expected %<)%> or %<,%>");
16808 : 12 : t = error_mark_node;
16809 : : }
16810 : : else
16811 : : {
16812 : 32 : parser->tokens = tokens.address ();
16813 : 32 : parser->tokens_avail = tokens.length ();
16814 : :
16815 : 32 : t = c_parser_expr_no_commas (parser, NULL).value;
16816 : 32 : if (t != error_mark_node && parser->tokens_avail != 2)
16817 : : {
16818 : 0 : error_at (c_parser_peek_token (parser)->location,
16819 : : "expected %<)%> or %<,%>");
16820 : 0 : t = error_mark_node;
16821 : : }
16822 : : }
16823 : : }
16824 : : break;
16825 : : default:
16826 : : break;
16827 : : }
16828 : :
16829 : 17022 : if (t != error_mark_node)
16830 : : {
16831 : 17007 : tree u = build_omp_clause (clause_loc, kind);
16832 : 17007 : OMP_CLAUSE_DECL (u) = t;
16833 : 17007 : OMP_CLAUSE_CHAIN (u) = list;
16834 : 17007 : list = u;
16835 : : }
16836 : : }
16837 : : else /* kind == OMP_CLAUSE_ERROR */
16838 : 227 : list = tree_cons (t, build_empty_stmt (tloc), list);
16839 : :
16840 : 17267 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16841 : : {
16842 : 859 : parser->tokens = saved_tokens;
16843 : 859 : parser->tokens_avail = tokens_avail;
16844 : : }
16845 : :
16846 : 16408 : next_item:
16847 : 19357 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
16848 : : break;
16849 : :
16850 : 3173 : c_parser_consume_token (parser);
16851 : : }
16852 : :
16853 : 16226 : return list;
16854 : 16226 : }
16855 : :
16856 : : /* Similarly, but expect leading and trailing parenthesis. This is a very
16857 : : common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
16858 : : argument is true if list items can use the deref (->) operator. */
16859 : :
16860 : : static tree
16861 : 3490 : c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
16862 : : tree list, bool map_lvalue = false)
16863 : : {
16864 : : /* The clauses location. */
16865 : 3490 : location_t loc = c_parser_peek_token (parser)->location;
16866 : :
16867 : 3490 : if (parser->in_omp_decl_attribute)
16868 : : {
16869 : 37 : if (kind)
16870 : : {
16871 : 22 : tree u = build_omp_clause (loc, kind);
16872 : 22 : OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
16873 : 22 : OMP_CLAUSE_CHAIN (u) = list;
16874 : 22 : return u;
16875 : : }
16876 : : else
16877 : 15 : return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
16878 : : }
16879 : :
16880 : 3453 : matching_parens parens;
16881 : 3453 : if (parens.require_open (parser))
16882 : : {
16883 : 3449 : list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue);
16884 : 3449 : parens.skip_until_found_close (parser);
16885 : : }
16886 : : return list;
16887 : : }
16888 : :
16889 : : /* OpenACC 2.0:
16890 : : copy ( variable-list )
16891 : : copyin ( variable-list )
16892 : : copyout ( variable-list )
16893 : : create ( variable-list )
16894 : : delete ( variable-list )
16895 : : present ( variable-list )
16896 : :
16897 : : OpenACC 2.6:
16898 : : no_create ( variable-list )
16899 : : attach ( variable-list )
16900 : : detach ( variable-list )
16901 : :
16902 : : OpenACC 2.7:
16903 : : copyin (readonly : variable-list )
16904 : : */
16905 : :
16906 : : static tree
16907 : 2026 : c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
16908 : : tree list)
16909 : : {
16910 : 2026 : enum gomp_map_kind kind;
16911 : 2026 : switch (c_kind)
16912 : : {
16913 : : case PRAGMA_OACC_CLAUSE_ATTACH:
16914 : : kind = GOMP_MAP_ATTACH;
16915 : : break;
16916 : 806 : case PRAGMA_OACC_CLAUSE_COPY:
16917 : 806 : kind = GOMP_MAP_TOFROM;
16918 : 806 : break;
16919 : 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
16920 : 359 : kind = GOMP_MAP_TO;
16921 : 359 : break;
16922 : 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
16923 : 390 : kind = GOMP_MAP_FROM;
16924 : 390 : break;
16925 : 94 : case PRAGMA_OACC_CLAUSE_CREATE:
16926 : 94 : kind = GOMP_MAP_ALLOC;
16927 : 94 : break;
16928 : 68 : case PRAGMA_OACC_CLAUSE_DELETE:
16929 : 68 : kind = GOMP_MAP_RELEASE;
16930 : 68 : break;
16931 : 20 : case PRAGMA_OACC_CLAUSE_DETACH:
16932 : 20 : kind = GOMP_MAP_DETACH;
16933 : 20 : break;
16934 : 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
16935 : 36 : kind = GOMP_MAP_FORCE_TO;
16936 : 36 : break;
16937 : 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
16938 : 16 : kind = GOMP_MAP_DEVICE_RESIDENT;
16939 : 16 : break;
16940 : 13 : case PRAGMA_OACC_CLAUSE_LINK:
16941 : 13 : kind = GOMP_MAP_LINK;
16942 : 13 : break;
16943 : 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
16944 : 10 : kind = GOMP_MAP_IF_PRESENT;
16945 : 10 : break;
16946 : 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
16947 : 128 : kind = GOMP_MAP_FORCE_PRESENT;
16948 : 128 : break;
16949 : 59 : case PRAGMA_OACC_CLAUSE_SELF:
16950 : : /* "The 'host' clause is a synonym for the 'self' clause." */
16951 : 59 : case PRAGMA_OACC_CLAUSE_HOST:
16952 : 59 : kind = GOMP_MAP_FORCE_FROM;
16953 : 59 : break;
16954 : 0 : default:
16955 : 0 : gcc_unreachable ();
16956 : : }
16957 : :
16958 : 2026 : tree nl = list;
16959 : 2026 : bool readonly = false;
16960 : 2026 : location_t open_loc = c_parser_peek_token (parser)->location;
16961 : 2026 : matching_parens parens;
16962 : 2026 : if (parens.require_open (parser))
16963 : : {
16964 : : /* Turn on readonly modifier parsing for copyin clause. */
16965 : 2026 : if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
16966 : : {
16967 : 359 : c_token *token = c_parser_peek_token (parser);
16968 : 359 : if (token->type == CPP_NAME
16969 : 359 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
16970 : 366 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16971 : : {
16972 : 7 : c_parser_consume_token (parser);
16973 : 7 : c_parser_consume_token (parser);
16974 : 7 : readonly = true;
16975 : : }
16976 : : }
16977 : 2026 : nl = c_parser_omp_variable_list (parser, open_loc, OMP_CLAUSE_MAP, list,
16978 : : false);
16979 : 2026 : parens.skip_until_found_close (parser);
16980 : : }
16981 : :
16982 : 4671 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
16983 : : {
16984 : 2645 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
16985 : 2645 : if (readonly)
16986 : 13 : OMP_CLAUSE_MAP_READONLY (c) = 1;
16987 : : }
16988 : :
16989 : 2026 : return nl;
16990 : : }
16991 : :
16992 : : /* OpenACC 2.0:
16993 : : deviceptr ( variable-list ) */
16994 : :
16995 : : static tree
16996 : 57 : c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
16997 : : {
16998 : 57 : tree vars, t;
16999 : :
17000 : : /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
17001 : : c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
17002 : : variable-list must only allow for pointer variables. */
17003 : 57 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
17004 : 118 : for (t = vars; t && t; t = TREE_CHAIN (t))
17005 : : {
17006 : 61 : tree v = TREE_PURPOSE (t);
17007 : 61 : location_t loc = EXPR_LOCATION (TREE_VALUE (t));
17008 : :
17009 : 61 : if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
17010 : 3 : error_at (loc, "%qD is not a variable", v);
17011 : 58 : else if (TREE_TYPE (v) == error_mark_node)
17012 : : ;
17013 : 57 : else if (!POINTER_TYPE_P (TREE_TYPE (v)))
17014 : 7 : error_at (loc, "%qD is not a pointer variable", v);
17015 : :
17016 : 61 : tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
17017 : 61 : OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
17018 : 61 : OMP_CLAUSE_DECL (u) = v;
17019 : 61 : OMP_CLAUSE_CHAIN (u) = list;
17020 : 61 : list = u;
17021 : : }
17022 : :
17023 : 57 : return list;
17024 : : }
17025 : :
17026 : : /* OpenACC 2.0, OpenMP 3.0:
17027 : : collapse ( constant-expression ) */
17028 : :
17029 : : static tree
17030 : 2945 : c_parser_omp_clause_collapse (c_parser *parser, tree list)
17031 : : {
17032 : 2945 : tree c, num = error_mark_node;
17033 : 2945 : HOST_WIDE_INT n;
17034 : 2945 : location_t loc;
17035 : :
17036 : 2945 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
17037 : 2945 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
17038 : :
17039 : 2945 : loc = c_parser_peek_token (parser)->location;
17040 : 2945 : matching_parens parens;
17041 : 2945 : if (parens.require_open (parser))
17042 : : {
17043 : 2945 : num = c_parser_expr_no_commas (parser, NULL).value;
17044 : 2945 : parens.skip_until_found_close (parser);
17045 : : }
17046 : 2945 : if (num == error_mark_node)
17047 : : return list;
17048 : 2945 : mark_exp_read (num);
17049 : 2945 : num = c_fully_fold (num, false, NULL);
17050 : 5890 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17051 : 2945 : || !tree_fits_shwi_p (num)
17052 : 2945 : || (n = tree_to_shwi (num)) <= 0
17053 : 5890 : || (int) n != n)
17054 : : {
17055 : 0 : error_at (loc,
17056 : : "collapse argument needs positive constant integer expression");
17057 : 0 : return list;
17058 : : }
17059 : 2945 : c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
17060 : 2945 : OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
17061 : 2945 : OMP_CLAUSE_CHAIN (c) = list;
17062 : 2945 : return c;
17063 : : }
17064 : :
17065 : : /* OpenMP 2.5:
17066 : : copyin ( variable-list ) */
17067 : :
17068 : : static tree
17069 : 101 : c_parser_omp_clause_copyin (c_parser *parser, tree list)
17070 : : {
17071 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
17072 : : }
17073 : :
17074 : : /* OpenMP 2.5:
17075 : : copyprivate ( variable-list ) */
17076 : :
17077 : : static tree
17078 : 21 : c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
17079 : : {
17080 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
17081 : : }
17082 : :
17083 : : /* OpenMP 2.5:
17084 : : default ( none | shared )
17085 : :
17086 : : OpenMP 5.1:
17087 : : default ( private | firstprivate )
17088 : :
17089 : : OpenACC:
17090 : : default ( none | present ) */
17091 : :
17092 : : static tree
17093 : 728 : c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
17094 : : {
17095 : 728 : enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
17096 : 728 : location_t loc = c_parser_peek_token (parser)->location;
17097 : 728 : tree c;
17098 : :
17099 : 728 : matching_parens parens;
17100 : 728 : if (!parens.require_open (parser))
17101 : : return list;
17102 : 725 : if (c_parser_next_token_is (parser, CPP_NAME))
17103 : : {
17104 : 713 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17105 : :
17106 : 713 : switch (p[0])
17107 : : {
17108 : 391 : case 'n':
17109 : 391 : if (strcmp ("none", p) != 0)
17110 : 0 : goto invalid_kind;
17111 : : kind = OMP_CLAUSE_DEFAULT_NONE;
17112 : : break;
17113 : :
17114 : 23 : case 'p':
17115 : 23 : if (is_oacc)
17116 : : {
17117 : 18 : if (strcmp ("present", p) != 0)
17118 : 3 : goto invalid_kind;
17119 : : kind = OMP_CLAUSE_DEFAULT_PRESENT;
17120 : : }
17121 : : else
17122 : : {
17123 : 5 : if (strcmp ("private", p) != 0)
17124 : 0 : goto invalid_kind;
17125 : : kind = OMP_CLAUSE_DEFAULT_PRIVATE;
17126 : : }
17127 : : break;
17128 : :
17129 : 9 : case 'f':
17130 : 9 : if (strcmp ("firstprivate", p) != 0 || is_oacc)
17131 : 0 : goto invalid_kind;
17132 : : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
17133 : : break;
17134 : :
17135 : 286 : case 's':
17136 : 286 : if (strcmp ("shared", p) != 0 || is_oacc)
17137 : 0 : goto invalid_kind;
17138 : : kind = OMP_CLAUSE_DEFAULT_SHARED;
17139 : : break;
17140 : :
17141 : 4 : default:
17142 : 4 : goto invalid_kind;
17143 : : }
17144 : :
17145 : 700 : c_parser_consume_token (parser);
17146 : : }
17147 : : else
17148 : : {
17149 : 25 : invalid_kind:
17150 : 25 : if (is_oacc)
17151 : 21 : c_parser_error (parser, "expected %<none%> or %<present%>");
17152 : : else
17153 : 4 : c_parser_error (parser, "expected %<none%>, %<shared%>, "
17154 : : "%<private%> or %<firstprivate%>");
17155 : : }
17156 : 725 : parens.skip_until_found_close (parser);
17157 : :
17158 : 725 : if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
17159 : : return list;
17160 : :
17161 : 700 : check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
17162 : 700 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
17163 : 700 : OMP_CLAUSE_CHAIN (c) = list;
17164 : 700 : OMP_CLAUSE_DEFAULT_KIND (c) = kind;
17165 : :
17166 : 700 : return c;
17167 : : }
17168 : :
17169 : : /* OpenMP 2.5:
17170 : : firstprivate ( variable-list ) */
17171 : :
17172 : : static tree
17173 : 777 : c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
17174 : : {
17175 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
17176 : : }
17177 : :
17178 : : /* OpenMP 3.1:
17179 : : final ( expression ) */
17180 : :
17181 : : static tree
17182 : 98 : c_parser_omp_clause_final (c_parser *parser, tree list)
17183 : : {
17184 : 98 : location_t loc = c_parser_peek_token (parser)->location;
17185 : 98 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
17186 : : {
17187 : 98 : matching_parens parens;
17188 : 98 : tree t, c;
17189 : 98 : if (!parens.require_open (parser))
17190 : 0 : t = error_mark_node;
17191 : : else
17192 : : {
17193 : 98 : location_t eloc = c_parser_peek_token (parser)->location;
17194 : 98 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17195 : 98 : t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
17196 : 98 : t = c_objc_common_truthvalue_conversion (eloc, t);
17197 : 98 : t = c_fully_fold (t, false, NULL);
17198 : 98 : parens.skip_until_found_close (parser);
17199 : : }
17200 : :
17201 : 98 : check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
17202 : :
17203 : 98 : c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
17204 : 98 : OMP_CLAUSE_FINAL_EXPR (c) = t;
17205 : 98 : OMP_CLAUSE_CHAIN (c) = list;
17206 : 98 : list = c;
17207 : : }
17208 : : else
17209 : 0 : c_parser_error (parser, "expected %<(%>");
17210 : :
17211 : 98 : return list;
17212 : : }
17213 : :
17214 : : /* OpenMP 5.1:
17215 : : indirect [( expression )]
17216 : : */
17217 : :
17218 : : static tree
17219 : 26 : c_parser_omp_clause_indirect (c_parser *parser, tree list)
17220 : : {
17221 : 26 : location_t location = c_parser_peek_token (parser)->location;
17222 : 26 : tree t;
17223 : :
17224 : 26 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17225 : : {
17226 : 17 : matching_parens parens;
17227 : 17 : if (!parens.require_open (parser))
17228 : 1 : return list;
17229 : :
17230 : 17 : location_t loc = c_parser_peek_token (parser)->location;
17231 : 17 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17232 : 17 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17233 : 17 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
17234 : 17 : t = c_fully_fold (t, false, NULL);
17235 : 34 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17236 : 34 : || TREE_CODE (t) != INTEGER_CST)
17237 : : {
17238 : 1 : c_parser_error (parser, "expected constant logical expression");
17239 : 1 : return list;
17240 : : }
17241 : 16 : parens.skip_until_found_close (parser);
17242 : : }
17243 : : else
17244 : 9 : t = integer_one_node;
17245 : :
17246 : 25 : check_no_duplicate_clause (list, OMP_CLAUSE_INDIRECT, "indirect");
17247 : :
17248 : 25 : tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
17249 : 25 : OMP_CLAUSE_INDIRECT_EXPR (c) = t;
17250 : 25 : OMP_CLAUSE_CHAIN (c) = list;
17251 : :
17252 : 25 : return c;
17253 : : }
17254 : :
17255 : : /* OpenACC, OpenMP 2.5:
17256 : : if ( expression )
17257 : :
17258 : : OpenMP 4.5:
17259 : : if ( directive-name-modifier : expression )
17260 : :
17261 : : directive-name-modifier:
17262 : : parallel | task | taskloop | target data | target | target update
17263 : : | target enter data | target exit data
17264 : :
17265 : : OpenMP 5.0:
17266 : : directive-name-modifier:
17267 : : ... | simd | cancel */
17268 : :
17269 : : static tree
17270 : 877 : c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
17271 : : {
17272 : 877 : location_t location = c_parser_peek_token (parser)->location;
17273 : 877 : enum tree_code if_modifier = ERROR_MARK;
17274 : :
17275 : 877 : matching_parens parens;
17276 : 877 : if (!parens.require_open (parser))
17277 : : return list;
17278 : :
17279 : 1655 : if (is_omp && c_parser_next_token_is (parser, CPP_NAME))
17280 : : {
17281 : 637 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17282 : 637 : int n = 2;
17283 : 637 : if (strcmp (p, "cancel") == 0)
17284 : : if_modifier = VOID_CST;
17285 : 622 : else if (strcmp (p, "parallel") == 0)
17286 : : if_modifier = OMP_PARALLEL;
17287 : 483 : else if (strcmp (p, "simd") == 0)
17288 : : if_modifier = OMP_SIMD;
17289 : 377 : else if (strcmp (p, "task") == 0)
17290 : : if_modifier = OMP_TASK;
17291 : 366 : else if (strcmp (p, "taskloop") == 0)
17292 : : if_modifier = OMP_TASKLOOP;
17293 : 315 : else if (strcmp (p, "target") == 0)
17294 : : {
17295 : 102 : if_modifier = OMP_TARGET;
17296 : 102 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17297 : : {
17298 : 37 : p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
17299 : 37 : if (strcmp ("data", p) == 0)
17300 : : if_modifier = OMP_TARGET_DATA;
17301 : 29 : else if (strcmp ("update", p) == 0)
17302 : : if_modifier = OMP_TARGET_UPDATE;
17303 : 18 : else if (strcmp ("enter", p) == 0)
17304 : : if_modifier = OMP_TARGET_ENTER_DATA;
17305 : 10 : else if (strcmp ("exit", p) == 0)
17306 : : if_modifier = OMP_TARGET_EXIT_DATA;
17307 : 0 : if (if_modifier != OMP_TARGET)
17308 : : {
17309 : 37 : n = 3;
17310 : 37 : c_parser_consume_token (parser);
17311 : : }
17312 : : else
17313 : : {
17314 : 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17315 : 0 : error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
17316 : : "or %<exit%>");
17317 : 0 : if_modifier = ERROR_MARK;
17318 : : }
17319 : 0 : if (if_modifier == OMP_TARGET_ENTER_DATA
17320 : 37 : || if_modifier == OMP_TARGET_EXIT_DATA)
17321 : : {
17322 : 18 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17323 : : {
17324 : 18 : p = IDENTIFIER_POINTER
17325 : : (c_parser_peek_2nd_token (parser)->value);
17326 : 18 : if (strcmp ("data", p) == 0)
17327 : 18 : n = 4;
17328 : : }
17329 : 18 : if (n == 4)
17330 : 18 : c_parser_consume_token (parser);
17331 : : else
17332 : : {
17333 : 0 : location_t loc
17334 : 0 : = c_parser_peek_2nd_token (parser)->location;
17335 : 0 : error_at (loc, "expected %<data%>");
17336 : 0 : if_modifier = ERROR_MARK;
17337 : : }
17338 : : }
17339 : : }
17340 : : }
17341 : 37 : if (if_modifier != ERROR_MARK)
17342 : : {
17343 : 424 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17344 : : {
17345 : 423 : c_parser_consume_token (parser);
17346 : 423 : c_parser_consume_token (parser);
17347 : : }
17348 : : else
17349 : : {
17350 : 1 : if (n > 2)
17351 : : {
17352 : 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17353 : 0 : error_at (loc, "expected %<:%>");
17354 : : }
17355 : : if_modifier = ERROR_MARK;
17356 : : }
17357 : : }
17358 : : }
17359 : :
17360 : 877 : location_t loc = c_parser_peek_token (parser)->location;
17361 : 877 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17362 : 877 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17363 : 877 : tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
17364 : 877 : t = c_fully_fold (t, false, NULL);
17365 : 877 : parens.skip_until_found_close (parser);
17366 : :
17367 : 3973 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17368 : 3136 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
17369 : : {
17370 : 174 : if (if_modifier != ERROR_MARK
17371 : 174 : && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17372 : : {
17373 : 9 : const char *p = NULL;
17374 : 9 : switch (if_modifier)
17375 : : {
17376 : : case VOID_CST: p = "cancel"; break;
17377 : 1 : case OMP_PARALLEL: p = "parallel"; break;
17378 : 0 : case OMP_SIMD: p = "simd"; break;
17379 : 1 : case OMP_TASK: p = "task"; break;
17380 : 1 : case OMP_TASKLOOP: p = "taskloop"; break;
17381 : 1 : case OMP_TARGET_DATA: p = "target data"; break;
17382 : 1 : case OMP_TARGET: p = "target"; break;
17383 : 1 : case OMP_TARGET_UPDATE: p = "target update"; break;
17384 : 1 : case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
17385 : 1 : case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
17386 : 0 : default: gcc_unreachable ();
17387 : : }
17388 : 9 : error_at (location, "too many %<if%> clauses with %qs modifier",
17389 : : p);
17390 : 9 : return list;
17391 : : }
17392 : 165 : else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17393 : : {
17394 : 13 : if (!is_omp)
17395 : 1 : error_at (location, "too many %<if%> clauses");
17396 : : else
17397 : 12 : error_at (location, "too many %<if%> clauses without modifier");
17398 : 13 : return list;
17399 : : }
17400 : 152 : else if (if_modifier == ERROR_MARK
17401 : 152 : || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
17402 : : {
17403 : 18 : error_at (location, "if any %<if%> clause has modifier, then all "
17404 : : "%<if%> clauses have to use modifier");
17405 : 18 : return list;
17406 : : }
17407 : : }
17408 : :
17409 : 837 : c = build_omp_clause (location, OMP_CLAUSE_IF);
17410 : 837 : OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
17411 : 837 : OMP_CLAUSE_IF_EXPR (c) = t;
17412 : 837 : OMP_CLAUSE_CHAIN (c) = list;
17413 : 837 : return c;
17414 : : }
17415 : :
17416 : : /* OpenMP 2.5:
17417 : : lastprivate ( variable-list )
17418 : :
17419 : : OpenMP 5.0:
17420 : : lastprivate ( [ lastprivate-modifier : ] variable-list ) */
17421 : :
17422 : : static tree
17423 : 731 : c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
17424 : : {
17425 : : /* The clauses location. */
17426 : 731 : location_t loc = c_parser_peek_token (parser)->location;
17427 : :
17428 : 731 : if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
17429 : : {
17430 : 731 : bool conditional = false;
17431 : 731 : if (c_parser_next_token_is (parser, CPP_NAME)
17432 : 731 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17433 : : {
17434 : 107 : const char *p
17435 : 107 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17436 : 107 : if (strcmp (p, "conditional") == 0)
17437 : : {
17438 : 107 : conditional = true;
17439 : 107 : c_parser_consume_token (parser);
17440 : 107 : c_parser_consume_token (parser);
17441 : : }
17442 : : }
17443 : 731 : tree nlist = c_parser_omp_variable_list (parser, loc,
17444 : : OMP_CLAUSE_LASTPRIVATE, list);
17445 : 731 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
17446 : 731 : if (conditional)
17447 : 246 : for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
17448 : 139 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
17449 : 731 : return nlist;
17450 : : }
17451 : : return list;
17452 : : }
17453 : :
17454 : : /* OpenMP 3.1:
17455 : : mergeable */
17456 : :
17457 : : static tree
17458 : 78 : c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17459 : : {
17460 : 78 : tree c;
17461 : :
17462 : : /* FIXME: Should we allow duplicates? */
17463 : 78 : check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
17464 : :
17465 : 78 : c = build_omp_clause (c_parser_peek_token (parser)->location,
17466 : : OMP_CLAUSE_MERGEABLE);
17467 : 78 : OMP_CLAUSE_CHAIN (c) = list;
17468 : :
17469 : 78 : return c;
17470 : : }
17471 : :
17472 : : /* OpenMP 2.5:
17473 : : nowait */
17474 : :
17475 : : static tree
17476 : 391 : c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17477 : : {
17478 : 391 : tree c;
17479 : 391 : location_t loc = c_parser_peek_token (parser)->location;
17480 : :
17481 : 391 : check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
17482 : :
17483 : 391 : c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
17484 : 391 : OMP_CLAUSE_CHAIN (c) = list;
17485 : 391 : return c;
17486 : : }
17487 : :
17488 : : /* OpenMP 2.5:
17489 : : num_threads ( expression ) */
17490 : :
17491 : : static tree
17492 : 424 : c_parser_omp_clause_num_threads (c_parser *parser, tree list)
17493 : : {
17494 : 424 : location_t num_threads_loc = c_parser_peek_token (parser)->location;
17495 : 424 : matching_parens parens;
17496 : 424 : if (parens.require_open (parser))
17497 : : {
17498 : 424 : location_t expr_loc = c_parser_peek_token (parser)->location;
17499 : 424 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17500 : 424 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17501 : 424 : tree c, t = expr.value;
17502 : 424 : t = c_fully_fold (t, false, NULL);
17503 : :
17504 : 424 : parens.skip_until_found_close (parser);
17505 : :
17506 : 424 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17507 : : {
17508 : 0 : c_parser_error (parser, "expected integer expression");
17509 : 0 : return list;
17510 : : }
17511 : :
17512 : : /* Attempt to statically determine when the number isn't positive. */
17513 : 424 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17514 : 424 : build_int_cst (TREE_TYPE (t), 0));
17515 : 424 : protected_set_expr_location (c, expr_loc);
17516 : 424 : if (c == boolean_true_node)
17517 : : {
17518 : 1 : warning_at (expr_loc, OPT_Wopenmp,
17519 : : "%<num_threads%> value must be positive");
17520 : 1 : t = integer_one_node;
17521 : : }
17522 : :
17523 : 424 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
17524 : :
17525 : 424 : c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
17526 : 424 : OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
17527 : 424 : OMP_CLAUSE_CHAIN (c) = list;
17528 : 424 : list = c;
17529 : : }
17530 : :
17531 : : return list;
17532 : : }
17533 : :
17534 : : /* OpenMP 4.5:
17535 : : num_tasks ( expression )
17536 : :
17537 : : OpenMP 5.1:
17538 : : num_tasks ( strict : expression ) */
17539 : :
17540 : : static tree
17541 : 49 : c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
17542 : : {
17543 : 49 : location_t num_tasks_loc = c_parser_peek_token (parser)->location;
17544 : 49 : matching_parens parens;
17545 : 49 : if (parens.require_open (parser))
17546 : : {
17547 : 49 : bool strict = false;
17548 : 49 : if (c_parser_next_token_is (parser, CPP_NAME)
17549 : 39 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17550 : 50 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17551 : : "strict") == 0)
17552 : : {
17553 : 1 : strict = true;
17554 : 1 : c_parser_consume_token (parser);
17555 : 1 : c_parser_consume_token (parser);
17556 : : }
17557 : :
17558 : 49 : location_t expr_loc = c_parser_peek_token (parser)->location;
17559 : 49 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17560 : 49 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17561 : 49 : tree c, t = expr.value;
17562 : 49 : t = c_fully_fold (t, false, NULL);
17563 : :
17564 : 49 : parens.skip_until_found_close (parser);
17565 : :
17566 : 49 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17567 : : {
17568 : 0 : c_parser_error (parser, "expected integer expression");
17569 : 0 : return list;
17570 : : }
17571 : :
17572 : : /* Attempt to statically determine when the number isn't positive. */
17573 : 49 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17574 : 49 : build_int_cst (TREE_TYPE (t), 0));
17575 : 49 : if (CAN_HAVE_LOCATION_P (c))
17576 : 39 : SET_EXPR_LOCATION (c, expr_loc);
17577 : 49 : if (c == boolean_true_node)
17578 : : {
17579 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17580 : : "%<num_tasks%> value must be positive");
17581 : 0 : t = integer_one_node;
17582 : : }
17583 : :
17584 : 49 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks");
17585 : :
17586 : 49 : c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
17587 : 49 : OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
17588 : 49 : OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
17589 : 49 : OMP_CLAUSE_CHAIN (c) = list;
17590 : 49 : list = c;
17591 : : }
17592 : :
17593 : : return list;
17594 : : }
17595 : :
17596 : : /* OpenMP 4.5:
17597 : : grainsize ( expression )
17598 : :
17599 : : OpenMP 5.1:
17600 : : grainsize ( strict : expression ) */
17601 : :
17602 : : static tree
17603 : 62 : c_parser_omp_clause_grainsize (c_parser *parser, tree list)
17604 : : {
17605 : 62 : location_t grainsize_loc = c_parser_peek_token (parser)->location;
17606 : 62 : matching_parens parens;
17607 : 62 : if (parens.require_open (parser))
17608 : : {
17609 : 62 : bool strict = false;
17610 : 62 : if (c_parser_next_token_is (parser, CPP_NAME)
17611 : 47 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17612 : 63 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17613 : : "strict") == 0)
17614 : : {
17615 : 1 : strict = true;
17616 : 1 : c_parser_consume_token (parser);
17617 : 1 : c_parser_consume_token (parser);
17618 : : }
17619 : :
17620 : 62 : location_t expr_loc = c_parser_peek_token (parser)->location;
17621 : 62 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17622 : 62 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17623 : 62 : tree c, t = expr.value;
17624 : 62 : t = c_fully_fold (t, false, NULL);
17625 : :
17626 : 62 : parens.skip_until_found_close (parser);
17627 : :
17628 : 62 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17629 : : {
17630 : 0 : c_parser_error (parser, "expected integer expression");
17631 : 0 : return list;
17632 : : }
17633 : :
17634 : : /* Attempt to statically determine when the number isn't positive. */
17635 : 62 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17636 : 62 : build_int_cst (TREE_TYPE (t), 0));
17637 : 62 : if (CAN_HAVE_LOCATION_P (c))
17638 : 47 : SET_EXPR_LOCATION (c, expr_loc);
17639 : 62 : if (c == boolean_true_node)
17640 : : {
17641 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17642 : : "%<grainsize%> value must be positive");
17643 : 0 : t = integer_one_node;
17644 : : }
17645 : :
17646 : 62 : check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize");
17647 : :
17648 : 62 : c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
17649 : 62 : OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
17650 : 62 : OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
17651 : 62 : OMP_CLAUSE_CHAIN (c) = list;
17652 : 62 : list = c;
17653 : : }
17654 : :
17655 : : return list;
17656 : : }
17657 : :
17658 : : /* OpenMP 4.5:
17659 : : priority ( expression ) */
17660 : :
17661 : : static tree
17662 : 97 : c_parser_omp_clause_priority (c_parser *parser, tree list)
17663 : : {
17664 : 97 : location_t priority_loc = c_parser_peek_token (parser)->location;
17665 : 97 : matching_parens parens;
17666 : 97 : if (parens.require_open (parser))
17667 : : {
17668 : 97 : location_t expr_loc = c_parser_peek_token (parser)->location;
17669 : 97 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17670 : 97 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17671 : 97 : tree c, t = expr.value;
17672 : 97 : t = c_fully_fold (t, false, NULL);
17673 : :
17674 : 97 : parens.skip_until_found_close (parser);
17675 : :
17676 : 97 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17677 : : {
17678 : 0 : c_parser_error (parser, "expected integer expression");
17679 : 0 : return list;
17680 : : }
17681 : :
17682 : : /* Attempt to statically determine when the number isn't
17683 : : non-negative. */
17684 : 97 : c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
17685 : 97 : build_int_cst (TREE_TYPE (t), 0));
17686 : 97 : if (CAN_HAVE_LOCATION_P (c))
17687 : 86 : SET_EXPR_LOCATION (c, expr_loc);
17688 : 97 : if (c == boolean_true_node)
17689 : : {
17690 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17691 : : "%<priority%> value must be non-negative");
17692 : 0 : t = integer_one_node;
17693 : : }
17694 : :
17695 : 97 : check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority");
17696 : :
17697 : 97 : c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
17698 : 97 : OMP_CLAUSE_PRIORITY_EXPR (c) = t;
17699 : 97 : OMP_CLAUSE_CHAIN (c) = list;
17700 : 97 : list = c;
17701 : : }
17702 : :
17703 : : return list;
17704 : : }
17705 : :
17706 : : /* OpenMP 4.5:
17707 : : hint ( expression ) */
17708 : :
17709 : : static tree
17710 : 58 : c_parser_omp_clause_hint (c_parser *parser, tree list)
17711 : : {
17712 : 58 : location_t hint_loc = c_parser_peek_token (parser)->location;
17713 : 58 : matching_parens parens;
17714 : 58 : if (parens.require_open (parser))
17715 : : {
17716 : 58 : location_t expr_loc = c_parser_peek_token (parser)->location;
17717 : 58 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17718 : 58 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17719 : 58 : tree c, t = expr.value;
17720 : 58 : t = c_fully_fold (t, false, NULL);
17721 : 116 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17722 : 57 : || TREE_CODE (t) != INTEGER_CST
17723 : 111 : || tree_int_cst_sgn (t) == -1)
17724 : : {
17725 : 6 : c_parser_error (parser, "expected constant integer expression "
17726 : : "with valid sync-hint value");
17727 : 6 : return list;
17728 : : }
17729 : 52 : parens.skip_until_found_close (parser);
17730 : 52 : check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
17731 : :
17732 : 52 : c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
17733 : 52 : OMP_CLAUSE_HINT_EXPR (c) = t;
17734 : 52 : OMP_CLAUSE_CHAIN (c) = list;
17735 : 52 : list = c;
17736 : : }
17737 : :
17738 : : return list;
17739 : : }
17740 : :
17741 : : /* OpenMP 5.1:
17742 : : filter ( integer-expression ) */
17743 : :
17744 : : static tree
17745 : 62 : c_parser_omp_clause_filter (c_parser *parser, tree list)
17746 : : {
17747 : 62 : location_t hint_loc = c_parser_peek_token (parser)->location;
17748 : 62 : matching_parens parens;
17749 : 62 : if (parens.require_open (parser))
17750 : : {
17751 : 62 : location_t expr_loc = c_parser_peek_token (parser)->location;
17752 : 62 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17753 : 62 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17754 : 62 : tree c, t = expr.value;
17755 : 62 : t = c_fully_fold (t, false, NULL);
17756 : 62 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17757 : : {
17758 : 2 : c_parser_error (parser, "expected integer expression");
17759 : 2 : return list;
17760 : : }
17761 : 60 : parens.skip_until_found_close (parser);
17762 : 60 : check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
17763 : :
17764 : 60 : c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
17765 : 60 : OMP_CLAUSE_FILTER_EXPR (c) = t;
17766 : 60 : OMP_CLAUSE_CHAIN (c) = list;
17767 : 60 : list = c;
17768 : : }
17769 : :
17770 : : return list;
17771 : : }
17772 : :
17773 : : /* OpenMP 4.5:
17774 : : defaultmap ( tofrom : scalar )
17775 : :
17776 : : OpenMP 5.0:
17777 : : defaultmap ( implicit-behavior [ : variable-category ] ) */
17778 : :
17779 : : static tree
17780 : 239 : c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
17781 : : {
17782 : 239 : location_t loc = c_parser_peek_token (parser)->location;
17783 : 239 : tree c;
17784 : 239 : const char *p;
17785 : 239 : enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17786 : 239 : enum omp_clause_defaultmap_kind category
17787 : : = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
17788 : :
17789 : 239 : matching_parens parens;
17790 : 239 : if (!parens.require_open (parser))
17791 : : return list;
17792 : 239 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
17793 : : p = "default";
17794 : 231 : else if (!c_parser_next_token_is (parser, CPP_NAME))
17795 : : {
17796 : 2 : invalid_behavior:
17797 : 3 : c_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
17798 : : "%<tofrom%>, %<firstprivate%>, %<none%> "
17799 : : "or %<default%>");
17800 : 3 : goto out_err;
17801 : : }
17802 : : else
17803 : 229 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17804 : :
17805 : 237 : switch (p[0])
17806 : : {
17807 : 7 : case 'a':
17808 : 7 : if (strcmp ("alloc", p) == 0)
17809 : : behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
17810 : : else
17811 : 0 : goto invalid_behavior;
17812 : : break;
17813 : :
17814 : 8 : case 'd':
17815 : 8 : if (strcmp ("default", p) == 0)
17816 : : behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17817 : : else
17818 : 0 : goto invalid_behavior;
17819 : : break;
17820 : :
17821 : 27 : case 'f':
17822 : 27 : if (strcmp ("firstprivate", p) == 0)
17823 : : behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
17824 : 3 : else if (strcmp ("from", p) == 0)
17825 : : behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
17826 : : else
17827 : 0 : goto invalid_behavior;
17828 : : break;
17829 : :
17830 : 101 : case 'n':
17831 : 101 : if (strcmp ("none", p) == 0)
17832 : : behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
17833 : : else
17834 : 0 : goto invalid_behavior;
17835 : : break;
17836 : :
17837 : 4 : case 'p':
17838 : 4 : if (strcmp ("present", p) == 0)
17839 : : behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
17840 : : else
17841 : 0 : goto invalid_behavior;
17842 : : break;
17843 : :
17844 : 89 : case 't':
17845 : 89 : if (strcmp ("tofrom", p) == 0)
17846 : : behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
17847 : 4 : else if (strcmp ("to", p) == 0)
17848 : : behavior = OMP_CLAUSE_DEFAULTMAP_TO;
17849 : : else
17850 : 0 : goto invalid_behavior;
17851 : : break;
17852 : :
17853 : 1 : default:
17854 : 1 : goto invalid_behavior;
17855 : : }
17856 : 236 : c_parser_consume_token (parser);
17857 : :
17858 : 236 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
17859 : : {
17860 : 132 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
17861 : 3 : goto out_err;
17862 : 129 : if (!c_parser_next_token_is (parser, CPP_NAME))
17863 : : {
17864 : 1 : invalid_category:
17865 : 2 : c_parser_error (parser, "expected %<scalar%>, %<aggregate%>, "
17866 : : "%<pointer%> or %<all%>");
17867 : 2 : goto out_err;
17868 : : }
17869 : 128 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17870 : 128 : switch (p[0])
17871 : : {
17872 : 22 : case 'a':
17873 : 22 : if (strcmp ("aggregate", p) == 0)
17874 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
17875 : 8 : else if (strcmp ("all", p) == 0)
17876 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
17877 : : else
17878 : 0 : goto invalid_category;
17879 : : break;
17880 : :
17881 : 15 : case 'p':
17882 : 15 : if (strcmp ("pointer", p) == 0)
17883 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
17884 : : else
17885 : 0 : goto invalid_category;
17886 : : break;
17887 : :
17888 : 90 : case 's':
17889 : 90 : if (strcmp ("scalar", p) == 0)
17890 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
17891 : : else
17892 : 0 : goto invalid_category;
17893 : : break;
17894 : :
17895 : 1 : default:
17896 : 1 : goto invalid_category;
17897 : : }
17898 : :
17899 : 127 : c_parser_consume_token (parser);
17900 : : }
17901 : 231 : parens.skip_until_found_close (parser);
17902 : :
17903 : 961 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17904 : 512 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
17905 : 512 : && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17906 : : || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17907 : 32 : || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
17908 : 31 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17909 : : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
17910 : 29 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17911 : : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
17912 : : {
17913 : 13 : enum omp_clause_defaultmap_kind cat = category;
17914 : 13 : location_t loc = OMP_CLAUSE_LOCATION (c);
17915 : 13 : if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17916 : 13 : || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17917 : 3 : && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17918 : : != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
17919 : 8 : cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
17920 : 13 : p = NULL;
17921 : 13 : switch (cat)
17922 : : {
17923 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
17924 : : p = NULL;
17925 : : break;
17926 : 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
17927 : 3 : p = "all";
17928 : 3 : break;
17929 : 2 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
17930 : 2 : p = "aggregate";
17931 : 2 : break;
17932 : 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
17933 : 3 : p = "pointer";
17934 : 3 : break;
17935 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
17936 : : p = "scalar";
17937 : : break;
17938 : 0 : default:
17939 : 0 : gcc_unreachable ();
17940 : : }
17941 : 8 : if (p)
17942 : 10 : error_at (loc, "too many %<defaultmap%> clauses with %qs category",
17943 : : p);
17944 : : else
17945 : 3 : error_at (loc, "too many %<defaultmap%> clauses with unspecified "
17946 : : "category");
17947 : : break;
17948 : : }
17949 : :
17950 : 231 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
17951 : 231 : OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
17952 : 231 : OMP_CLAUSE_CHAIN (c) = list;
17953 : 231 : return c;
17954 : :
17955 : 8 : out_err:
17956 : 8 : parens.skip_until_found_close (parser);
17957 : 8 : return list;
17958 : : }
17959 : :
17960 : : /* OpenACC 2.0:
17961 : : use_device ( variable-list )
17962 : :
17963 : : OpenMP 4.5:
17964 : : use_device_ptr ( variable-list ) */
17965 : :
17966 : : static tree
17967 : 31 : c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
17968 : : {
17969 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_PTR,
17970 : 0 : list);
17971 : : }
17972 : :
17973 : : /* OpenMP 5.0:
17974 : : use_device_addr ( variable-list ) */
17975 : :
17976 : : static tree
17977 : 35 : c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
17978 : : {
17979 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_ADDR,
17980 : 0 : list);
17981 : : }
17982 : :
17983 : : /* OpenMP 5.1:
17984 : : has_device_addr ( variable-list ) */
17985 : :
17986 : : static tree
17987 : 87 : c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
17988 : : {
17989 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_HAS_DEVICE_ADDR,
17990 : 0 : list);
17991 : : }
17992 : :
17993 : : /* OpenMP 4.5:
17994 : : is_device_ptr ( variable-list ) */
17995 : :
17996 : : static tree
17997 : 114 : c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
17998 : : {
17999 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_IS_DEVICE_PTR, list);
18000 : : }
18001 : :
18002 : : /* OpenACC:
18003 : : num_gangs ( expression )
18004 : : num_workers ( expression )
18005 : : vector_length ( expression ) */
18006 : :
18007 : : static tree
18008 : 732 : c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
18009 : : tree list)
18010 : : {
18011 : 732 : location_t loc = c_parser_peek_token (parser)->location;
18012 : :
18013 : 732 : matching_parens parens;
18014 : 732 : if (!parens.require_open (parser))
18015 : : return list;
18016 : :
18017 : 726 : location_t expr_loc = c_parser_peek_token (parser)->location;
18018 : 726 : c_expr expr = c_parser_expression (parser);
18019 : 726 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18020 : 726 : tree c, t = expr.value;
18021 : 726 : t = c_fully_fold (t, false, NULL);
18022 : :
18023 : 726 : parens.skip_until_found_close (parser);
18024 : :
18025 : 726 : if (t == error_mark_node)
18026 : : return list;
18027 : 702 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18028 : : {
18029 : 16 : error_at (expr_loc, "%qs expression must be integral",
18030 : 16 : omp_clause_code_name[code]);
18031 : 16 : return list;
18032 : : }
18033 : :
18034 : : /* Attempt to statically determine when the number isn't positive. */
18035 : 686 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
18036 : 686 : build_int_cst (TREE_TYPE (t), 0));
18037 : 686 : protected_set_expr_location (c, expr_loc);
18038 : 686 : if (c == boolean_true_node)
18039 : : {
18040 : 36 : warning_at (expr_loc, 0,
18041 : : "%qs value must be positive",
18042 : 18 : omp_clause_code_name[code]);
18043 : 18 : t = integer_one_node;
18044 : : }
18045 : :
18046 : 686 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18047 : :
18048 : 686 : c = build_omp_clause (loc, code);
18049 : 686 : OMP_CLAUSE_OPERAND (c, 0) = t;
18050 : 686 : OMP_CLAUSE_CHAIN (c) = list;
18051 : 686 : return c;
18052 : : }
18053 : :
18054 : : /* OpenACC:
18055 : :
18056 : : gang [( gang-arg-list )]
18057 : : worker [( [num:] int-expr )]
18058 : : vector [( [length:] int-expr )]
18059 : :
18060 : : where gang-arg is one of:
18061 : :
18062 : : [num:] int-expr
18063 : : static: size-expr
18064 : :
18065 : : and size-expr may be:
18066 : :
18067 : : *
18068 : : int-expr
18069 : : */
18070 : :
18071 : : static tree
18072 : 1560 : c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
18073 : : omp_clause_code kind,
18074 : : const char *str, tree list)
18075 : : {
18076 : 1560 : const char *id = "num";
18077 : 1560 : tree ops[2] = { NULL_TREE, NULL_TREE }, c;
18078 : :
18079 : 1560 : if (kind == OMP_CLAUSE_VECTOR)
18080 : 518 : id = "length";
18081 : :
18082 : 1560 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18083 : : {
18084 : 246 : c_parser_consume_token (parser);
18085 : :
18086 : 276 : do
18087 : : {
18088 : 261 : c_token *next = c_parser_peek_token (parser);
18089 : 261 : int idx = 0;
18090 : :
18091 : : /* Gang static argument. */
18092 : 261 : if (kind == OMP_CLAUSE_GANG
18093 : 403 : && c_parser_next_token_is_keyword (parser, RID_STATIC))
18094 : : {
18095 : 70 : c_parser_consume_token (parser);
18096 : :
18097 : 70 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18098 : 12 : goto cleanup_error;
18099 : :
18100 : 70 : idx = 1;
18101 : 70 : if (ops[idx] != NULL_TREE)
18102 : : {
18103 : 0 : c_parser_error (parser, "too many %<static%> arguments");
18104 : 0 : goto cleanup_error;
18105 : : }
18106 : :
18107 : : /* Check for the '*' argument. */
18108 : 70 : if (c_parser_next_token_is (parser, CPP_MULT)
18109 : 70 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18110 : 30 : || c_parser_peek_2nd_token (parser)->type
18111 : : == CPP_CLOSE_PAREN))
18112 : : {
18113 : 29 : c_parser_consume_token (parser);
18114 : 29 : ops[idx] = integer_minus_one_node;
18115 : :
18116 : 29 : if (c_parser_next_token_is (parser, CPP_COMMA))
18117 : : {
18118 : 1 : c_parser_consume_token (parser);
18119 : 1 : continue;
18120 : : }
18121 : : else
18122 : : break;
18123 : : }
18124 : : }
18125 : : /* Worker num: argument and vector length: arguments. */
18126 : 191 : else if (c_parser_next_token_is (parser, CPP_NAME)
18127 : 149 : && strcmp (id, IDENTIFIER_POINTER (next->value)) == 0
18128 : 324 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18129 : : {
18130 : 127 : c_parser_consume_token (parser); /* id */
18131 : 127 : c_parser_consume_token (parser); /* ':' */
18132 : : }
18133 : :
18134 : : /* Now collect the actual argument. */
18135 : 232 : if (ops[idx] != NULL_TREE)
18136 : : {
18137 : 5 : c_parser_error (parser, "unexpected argument");
18138 : 5 : goto cleanup_error;
18139 : : }
18140 : :
18141 : 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
18142 : 227 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18143 : 227 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18144 : 227 : tree expr = cexpr.value;
18145 : 227 : if (expr == error_mark_node)
18146 : 7 : goto cleanup_error;
18147 : :
18148 : 220 : expr = c_fully_fold (expr, false, NULL);
18149 : :
18150 : : /* Attempt to statically determine when the number isn't a
18151 : : positive integer. */
18152 : :
18153 : 220 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
18154 : : {
18155 : 14 : c_parser_error (parser, "expected integer expression");
18156 : 14 : return list;
18157 : : }
18158 : :
18159 : 206 : tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
18160 : 206 : build_int_cst (TREE_TYPE (expr), 0));
18161 : 206 : if (c == boolean_true_node)
18162 : : {
18163 : 1 : warning_at (loc, 0,
18164 : : "%qs value must be positive", str);
18165 : 1 : expr = integer_one_node;
18166 : : }
18167 : :
18168 : 206 : ops[idx] = expr;
18169 : :
18170 : 220 : if (kind == OMP_CLAUSE_GANG
18171 : 305 : && c_parser_next_token_is (parser, CPP_COMMA))
18172 : : {
18173 : 14 : c_parser_consume_token (parser);
18174 : 14 : continue;
18175 : : }
18176 : : break;
18177 : 15 : }
18178 : : while (1);
18179 : :
18180 : 220 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18181 : 7 : goto cleanup_error;
18182 : : }
18183 : :
18184 : 1527 : check_no_duplicate_clause (list, kind, str);
18185 : :
18186 : 1527 : c = build_omp_clause (loc, kind);
18187 : :
18188 : 1527 : if (ops[1])
18189 : 67 : OMP_CLAUSE_OPERAND (c, 1) = ops[1];
18190 : :
18191 : 1527 : OMP_CLAUSE_OPERAND (c, 0) = ops[0];
18192 : 1527 : OMP_CLAUSE_CHAIN (c) = list;
18193 : :
18194 : 1527 : return c;
18195 : :
18196 : 19 : cleanup_error:
18197 : 19 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18198 : 19 : return list;
18199 : : }
18200 : :
18201 : : /* OpenACC 2.5:
18202 : : auto
18203 : : finalize
18204 : : independent
18205 : : nohost
18206 : : seq */
18207 : :
18208 : : static tree
18209 : 487 : c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
18210 : : tree list)
18211 : : {
18212 : 487 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18213 : :
18214 : 487 : tree c = build_omp_clause (loc, code);
18215 : 487 : OMP_CLAUSE_CHAIN (c) = list;
18216 : :
18217 : 487 : return c;
18218 : : }
18219 : :
18220 : : /* OpenACC:
18221 : : async [( int-expr )] */
18222 : :
18223 : : static tree
18224 : 237 : c_parser_oacc_clause_async (c_parser *parser, tree list)
18225 : : {
18226 : 237 : tree c, t;
18227 : 237 : location_t loc = c_parser_peek_token (parser)->location;
18228 : :
18229 : 237 : t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18230 : :
18231 : 237 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18232 : : {
18233 : 185 : c_parser_consume_token (parser);
18234 : :
18235 : 185 : t = c_parser_expr_no_commas (parser, NULL).value;
18236 : 185 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18237 : 9 : c_parser_error (parser, "expected integer expression");
18238 : 176 : else if (t == error_mark_node
18239 : 176 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18240 : 14 : return list;
18241 : : }
18242 : : else
18243 : 52 : t = c_fully_fold (t, false, NULL);
18244 : :
18245 : 223 : check_no_duplicate_clause (list, OMP_CLAUSE_ASYNC, "async");
18246 : :
18247 : 223 : c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
18248 : 223 : OMP_CLAUSE_ASYNC_EXPR (c) = t;
18249 : 223 : OMP_CLAUSE_CHAIN (c) = list;
18250 : 223 : list = c;
18251 : :
18252 : 223 : return list;
18253 : : }
18254 : :
18255 : : /* OpenACC 2.0:
18256 : : tile ( size-expr-list ) */
18257 : :
18258 : : static tree
18259 : 123 : c_parser_oacc_clause_tile (c_parser *parser, tree list)
18260 : : {
18261 : 123 : tree c, expr = error_mark_node;
18262 : 123 : location_t loc;
18263 : 123 : tree tile = NULL_TREE;
18264 : :
18265 : 123 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
18266 : 123 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
18267 : :
18268 : 123 : loc = c_parser_peek_token (parser)->location;
18269 : 123 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
18270 : : return list;
18271 : :
18272 : 163 : do
18273 : : {
18274 : 163 : if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
18275 : : return list;
18276 : :
18277 : 163 : if (c_parser_next_token_is (parser, CPP_MULT)
18278 : 163 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18279 : 53 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
18280 : : {
18281 : 60 : c_parser_consume_token (parser);
18282 : 60 : expr = integer_zero_node;
18283 : : }
18284 : : else
18285 : : {
18286 : 103 : location_t expr_loc = c_parser_peek_token (parser)->location;
18287 : 103 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18288 : 103 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18289 : 103 : expr = cexpr.value;
18290 : :
18291 : 103 : if (expr == error_mark_node)
18292 : : {
18293 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
18294 : : "expected %<)%>");
18295 : 7 : return list;
18296 : : }
18297 : :
18298 : 96 : expr = c_fully_fold (expr, false, NULL);
18299 : :
18300 : 192 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
18301 : 95 : || !tree_fits_shwi_p (expr)
18302 : 183 : || tree_to_shwi (expr) <= 0)
18303 : : {
18304 : 16 : error_at (expr_loc, "%<tile%> argument needs positive"
18305 : : " integral constant");
18306 : 16 : expr = integer_zero_node;
18307 : : }
18308 : : }
18309 : :
18310 : 156 : tile = tree_cons (NULL_TREE, expr, tile);
18311 : : }
18312 : 156 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
18313 : :
18314 : : /* Consume the trailing ')'. */
18315 : 111 : c_parser_consume_token (parser);
18316 : :
18317 : 111 : c = build_omp_clause (loc, OMP_CLAUSE_TILE);
18318 : 111 : tile = nreverse (tile);
18319 : 111 : OMP_CLAUSE_TILE_LIST (c) = tile;
18320 : 111 : OMP_CLAUSE_CHAIN (c) = list;
18321 : 111 : return c;
18322 : : }
18323 : :
18324 : : /* OpenACC:
18325 : : wait [( int-expr-list )] */
18326 : :
18327 : : static tree
18328 : 89 : c_parser_oacc_clause_wait (c_parser *parser, tree list)
18329 : : {
18330 : 89 : location_t clause_loc = c_parser_peek_token (parser)->location;
18331 : :
18332 : 89 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18333 : 74 : list = c_parser_oacc_wait_list (parser, clause_loc, list);
18334 : : else
18335 : : {
18336 : 15 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
18337 : :
18338 : 15 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18339 : 15 : OMP_CLAUSE_CHAIN (c) = list;
18340 : 15 : list = c;
18341 : : }
18342 : :
18343 : 89 : return list;
18344 : : }
18345 : :
18346 : : /* OpenACC 2.7:
18347 : : self [( expression )] */
18348 : :
18349 : : static tree
18350 : 48 : c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
18351 : : {
18352 : 48 : tree t;
18353 : 48 : location_t location = c_parser_peek_token (parser)->location;
18354 : 48 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18355 : : {
18356 : 42 : matching_parens parens;
18357 : 42 : parens.consume_open (parser);
18358 : :
18359 : 42 : location_t loc = c_parser_peek_token (parser)->location;
18360 : 42 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18361 : 42 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
18362 : 42 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
18363 : 42 : t = c_fully_fold (t, false, NULL);
18364 : 42 : parens.skip_until_found_close (parser);
18365 : : }
18366 : : else
18367 : 6 : t = truthvalue_true_node;
18368 : :
18369 : 78 : for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
18370 : 36 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
18371 : : {
18372 : 6 : error_at (location, "too many %<self%> clauses");
18373 : 6 : return list;
18374 : : }
18375 : :
18376 : 42 : tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
18377 : 42 : OMP_CLAUSE_SELF_EXPR (c) = t;
18378 : 42 : OMP_CLAUSE_CHAIN (c) = list;
18379 : 42 : return c;
18380 : : }
18381 : :
18382 : : /* OpenMP 5.0:
18383 : : order ( concurrent )
18384 : :
18385 : : OpenMP 5.1:
18386 : : order ( order-modifier : concurrent )
18387 : :
18388 : : order-modifier:
18389 : : reproducible
18390 : : unconstrained */
18391 : :
18392 : : static tree
18393 : 375 : c_parser_omp_clause_order (c_parser *parser, tree list)
18394 : : {
18395 : 375 : location_t loc = c_parser_peek_token (parser)->location;
18396 : 375 : tree c;
18397 : 375 : const char *p;
18398 : 375 : bool unconstrained = false;
18399 : 375 : bool reproducible = false;
18400 : :
18401 : 375 : matching_parens parens;
18402 : 375 : if (!parens.require_open (parser))
18403 : : return list;
18404 : 373 : if (c_parser_next_token_is (parser, CPP_NAME)
18405 : 373 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18406 : : {
18407 : 107 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18408 : 107 : if (strcmp (p, "unconstrained") == 0)
18409 : : unconstrained = true;
18410 : 56 : else if (strcmp (p, "reproducible") == 0)
18411 : : reproducible = true;
18412 : : else
18413 : : {
18414 : 1 : c_parser_error (parser, "expected %<reproducible%> or "
18415 : : "%<unconstrained%>");
18416 : 1 : goto out_err;
18417 : : }
18418 : 106 : c_parser_consume_token (parser);
18419 : 106 : c_parser_consume_token (parser);
18420 : : }
18421 : 372 : if (!c_parser_next_token_is (parser, CPP_NAME))
18422 : : {
18423 : 0 : c_parser_error (parser, "expected %<concurrent%>");
18424 : 0 : goto out_err;
18425 : : }
18426 : 372 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18427 : 372 : if (strcmp (p, "concurrent") != 0)
18428 : : {
18429 : 1 : c_parser_error (parser, "expected %<concurrent%>");
18430 : 1 : goto out_err;
18431 : : }
18432 : 371 : c_parser_consume_token (parser);
18433 : 371 : parens.skip_until_found_close (parser);
18434 : 371 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
18435 : 371 : c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
18436 : 371 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
18437 : 371 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
18438 : 371 : OMP_CLAUSE_CHAIN (c) = list;
18439 : 371 : return c;
18440 : :
18441 : 2 : out_err:
18442 : 2 : parens.skip_until_found_close (parser);
18443 : 2 : return list;
18444 : : }
18445 : :
18446 : :
18447 : : /* OpenMP 5.0:
18448 : : bind ( teams | parallel | thread ) */
18449 : :
18450 : : static tree
18451 : 115 : c_parser_omp_clause_bind (c_parser *parser, tree list)
18452 : : {
18453 : 115 : location_t loc = c_parser_peek_token (parser)->location;
18454 : 115 : tree c;
18455 : 115 : const char *p;
18456 : 115 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18457 : :
18458 : 115 : matching_parens parens;
18459 : 115 : if (!parens.require_open (parser))
18460 : : return list;
18461 : 113 : if (!c_parser_next_token_is (parser, CPP_NAME))
18462 : : {
18463 : 3 : invalid:
18464 : 4 : c_parser_error (parser,
18465 : : "expected %<teams%>, %<parallel%> or %<thread%>");
18466 : 4 : parens.skip_until_found_close (parser);
18467 : 4 : return list;
18468 : : }
18469 : 110 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18470 : 110 : if (strcmp (p, "teams") == 0)
18471 : : kind = OMP_CLAUSE_BIND_TEAMS;
18472 : 72 : else if (strcmp (p, "parallel") == 0)
18473 : : kind = OMP_CLAUSE_BIND_PARALLEL;
18474 : 35 : else if (strcmp (p, "thread") != 0)
18475 : 1 : goto invalid;
18476 : 109 : c_parser_consume_token (parser);
18477 : 109 : parens.skip_until_found_close (parser);
18478 : : /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
18479 : 109 : c = build_omp_clause (loc, OMP_CLAUSE_BIND);
18480 : 109 : OMP_CLAUSE_BIND_KIND (c) = kind;
18481 : 109 : OMP_CLAUSE_CHAIN (c) = list;
18482 : 109 : return c;
18483 : : }
18484 : :
18485 : :
18486 : : /* OpenMP 2.5:
18487 : : ordered
18488 : :
18489 : : OpenMP 4.5:
18490 : : ordered ( constant-expression ) */
18491 : :
18492 : : static tree
18493 : 309 : c_parser_omp_clause_ordered (c_parser *parser, tree list)
18494 : : {
18495 : 309 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
18496 : :
18497 : 309 : tree c, num = NULL_TREE;
18498 : 309 : HOST_WIDE_INT n;
18499 : 309 : location_t loc = c_parser_peek_token (parser)->location;
18500 : 309 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18501 : : {
18502 : 168 : matching_parens parens;
18503 : 168 : parens.consume_open (parser);
18504 : 168 : num = c_parser_expr_no_commas (parser, NULL).value;
18505 : 168 : parens.skip_until_found_close (parser);
18506 : : }
18507 : 309 : if (num == error_mark_node)
18508 : : return list;
18509 : 309 : if (num)
18510 : : {
18511 : 168 : mark_exp_read (num);
18512 : 168 : num = c_fully_fold (num, false, NULL);
18513 : 336 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
18514 : 168 : || !tree_fits_shwi_p (num)
18515 : 168 : || (n = tree_to_shwi (num)) <= 0
18516 : 336 : || (int) n != n)
18517 : : {
18518 : 0 : error_at (loc, "ordered argument needs positive "
18519 : : "constant integer expression");
18520 : 0 : return list;
18521 : : }
18522 : : }
18523 : 309 : c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
18524 : 309 : OMP_CLAUSE_ORDERED_EXPR (c) = num;
18525 : 309 : OMP_CLAUSE_CHAIN (c) = list;
18526 : 309 : return c;
18527 : : }
18528 : :
18529 : : /* OpenMP 2.5:
18530 : : private ( variable-list ) */
18531 : :
18532 : : static tree
18533 : 735 : c_parser_omp_clause_private (c_parser *parser, tree list)
18534 : : {
18535 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
18536 : : }
18537 : :
18538 : : /* OpenMP 2.5:
18539 : : reduction ( reduction-operator : variable-list )
18540 : :
18541 : : reduction-operator:
18542 : : One of: + * - & ^ | && ||
18543 : :
18544 : : OpenMP 3.1:
18545 : :
18546 : : reduction-operator:
18547 : : One of: + * - & ^ | && || max min
18548 : :
18549 : : OpenMP 4.0:
18550 : :
18551 : : reduction-operator:
18552 : : One of: + * - & ^ | && ||
18553 : : identifier
18554 : :
18555 : : OpenMP 5.0:
18556 : : reduction ( reduction-modifier, reduction-operator : variable-list )
18557 : : in_reduction ( reduction-operator : variable-list )
18558 : : task_reduction ( reduction-operator : variable-list ) */
18559 : :
18560 : : static tree
18561 : 3089 : c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
18562 : : bool is_omp, tree list)
18563 : : {
18564 : 3089 : location_t clause_loc = c_parser_peek_token (parser)->location;
18565 : 3089 : matching_parens parens;
18566 : 3089 : if (parens.require_open (parser))
18567 : : {
18568 : 3089 : bool task = false;
18569 : 3089 : bool inscan = false;
18570 : 3089 : enum tree_code code = ERROR_MARK;
18571 : 3089 : tree reduc_id = NULL_TREE;
18572 : :
18573 : 3089 : if (kind == OMP_CLAUSE_REDUCTION && is_omp)
18574 : : {
18575 : 1778 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
18576 : 1778 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18577 : : {
18578 : 86 : c_parser_consume_token (parser);
18579 : 86 : c_parser_consume_token (parser);
18580 : : }
18581 : 1692 : else if (c_parser_next_token_is (parser, CPP_NAME)
18582 : 1692 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18583 : : {
18584 : 465 : const char *p
18585 : 465 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18586 : 465 : if (strcmp (p, "task") == 0)
18587 : : task = true;
18588 : 285 : else if (strcmp (p, "inscan") == 0)
18589 : : inscan = true;
18590 : : if (task || inscan)
18591 : : {
18592 : 465 : c_parser_consume_token (parser);
18593 : 465 : c_parser_consume_token (parser);
18594 : : }
18595 : : }
18596 : : }
18597 : :
18598 : 3089 : switch (c_parser_peek_token (parser)->type)
18599 : : {
18600 : : case CPP_PLUS:
18601 : : code = PLUS_EXPR;
18602 : : break;
18603 : 253 : case CPP_MULT:
18604 : 253 : code = MULT_EXPR;
18605 : 253 : break;
18606 : 155 : case CPP_MINUS:
18607 : 155 : code = MINUS_EXPR;
18608 : 155 : break;
18609 : 27 : case CPP_AND:
18610 : 27 : code = BIT_AND_EXPR;
18611 : 27 : break;
18612 : 14 : case CPP_XOR:
18613 : 14 : code = BIT_XOR_EXPR;
18614 : 14 : break;
18615 : 82 : case CPP_OR:
18616 : 82 : code = BIT_IOR_EXPR;
18617 : 82 : break;
18618 : 67 : case CPP_AND_AND:
18619 : 67 : code = TRUTH_ANDIF_EXPR;
18620 : 67 : break;
18621 : 78 : case CPP_OR_OR:
18622 : 78 : code = TRUTH_ORIF_EXPR;
18623 : 78 : break;
18624 : 253 : case CPP_NAME:
18625 : 253 : {
18626 : 253 : const char *p
18627 : 253 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18628 : 253 : if (strcmp (p, "min") == 0)
18629 : : {
18630 : : code = MIN_EXPR;
18631 : : break;
18632 : : }
18633 : 213 : if (strcmp (p, "max") == 0)
18634 : : {
18635 : : code = MAX_EXPR;
18636 : : break;
18637 : : }
18638 : 130 : reduc_id = c_parser_peek_token (parser)->value;
18639 : 130 : break;
18640 : : }
18641 : 0 : default:
18642 : 0 : c_parser_error (parser,
18643 : : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
18644 : : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
18645 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18646 : 0 : return list;
18647 : : }
18648 : 3089 : c_parser_consume_token (parser);
18649 : 3089 : reduc_id = c_omp_reduction_id (code, reduc_id);
18650 : 3089 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18651 : : {
18652 : 3089 : tree nl, c;
18653 : :
18654 : 3089 : nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
18655 : 6791 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18656 : : {
18657 : 3702 : tree d = OMP_CLAUSE_DECL (c), type;
18658 : 3702 : if (TREE_CODE (d) != OMP_ARRAY_SECTION)
18659 : 3183 : type = TREE_TYPE (d);
18660 : : else
18661 : : {
18662 : : int cnt = 0;
18663 : : tree t;
18664 : 636 : for (t = d;
18665 : 1155 : TREE_CODE (t) == OMP_ARRAY_SECTION;
18666 : 636 : t = TREE_OPERAND (t, 0))
18667 : 636 : cnt++;
18668 : 519 : type = TREE_TYPE (t);
18669 : 1153 : while (cnt > 0)
18670 : : {
18671 : 636 : if (TREE_CODE (type) != POINTER_TYPE
18672 : 399 : && TREE_CODE (type) != ARRAY_TYPE)
18673 : : break;
18674 : 634 : type = TREE_TYPE (type);
18675 : 634 : cnt--;
18676 : : }
18677 : : }
18678 : 3795 : while (TREE_CODE (type) == ARRAY_TYPE)
18679 : 93 : type = TREE_TYPE (type);
18680 : 3702 : OMP_CLAUSE_REDUCTION_CODE (c) = code;
18681 : 3702 : if (task)
18682 : 212 : OMP_CLAUSE_REDUCTION_TASK (c) = 1;
18683 : 3490 : else if (inscan)
18684 : 400 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
18685 : 3702 : if (code == ERROR_MARK
18686 : 219 : || !(INTEGRAL_TYPE_P (type)
18687 : 3562 : || SCALAR_FLOAT_TYPE_P (type)
18688 : : || TREE_CODE (type) == COMPLEX_TYPE))
18689 : 273 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
18690 : 546 : = c_omp_reduction_lookup (reduc_id,
18691 : 273 : TYPE_MAIN_VARIANT (type));
18692 : : }
18693 : :
18694 : : list = nl;
18695 : : }
18696 : 3089 : parens.skip_until_found_close (parser);
18697 : : }
18698 : : return list;
18699 : : }
18700 : :
18701 : : /* OpenMP 2.5:
18702 : : schedule ( schedule-kind )
18703 : : schedule ( schedule-kind , expression )
18704 : :
18705 : : schedule-kind:
18706 : : static | dynamic | guided | runtime | auto
18707 : :
18708 : : OpenMP 4.5:
18709 : : schedule ( schedule-modifier : schedule-kind )
18710 : : schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
18711 : :
18712 : : schedule-modifier:
18713 : : simd
18714 : : monotonic
18715 : : nonmonotonic */
18716 : :
18717 : : static tree
18718 : 3467 : c_parser_omp_clause_schedule (c_parser *parser, tree list)
18719 : : {
18720 : 3467 : tree c, t;
18721 : 3467 : location_t loc = c_parser_peek_token (parser)->location;
18722 : 3467 : int modifiers = 0, nmodifiers = 0;
18723 : :
18724 : 3467 : matching_parens parens;
18725 : 3467 : if (!parens.require_open (parser))
18726 : : return list;
18727 : :
18728 : 3465 : c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
18729 : :
18730 : 3465 : location_t comma = UNKNOWN_LOCATION;
18731 : 6944 : while (c_parser_next_token_is (parser, CPP_NAME))
18732 : : {
18733 : 1780 : tree kind = c_parser_peek_token (parser)->value;
18734 : 1780 : const char *p = IDENTIFIER_POINTER (kind);
18735 : 1780 : if (strcmp ("simd", p) == 0)
18736 : 31 : OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
18737 : 1749 : else if (strcmp ("monotonic", p) == 0)
18738 : 74 : modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
18739 : 1675 : else if (strcmp ("nonmonotonic", p) == 0)
18740 : 84 : modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
18741 : : else
18742 : : break;
18743 : 189 : comma = UNKNOWN_LOCATION;
18744 : 189 : c_parser_consume_token (parser);
18745 : 189 : if (nmodifiers++ == 0
18746 : 367 : && c_parser_next_token_is (parser, CPP_COMMA))
18747 : : {
18748 : 14 : comma = c_parser_peek_token (parser)->location;
18749 : 14 : c_parser_consume_token (parser);
18750 : : }
18751 : : else
18752 : : {
18753 : 175 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
18754 : 175 : break;
18755 : : }
18756 : : }
18757 : 3465 : if (comma != UNKNOWN_LOCATION)
18758 : 3 : error_at (comma, "expected %<:%>");
18759 : :
18760 : 3465 : if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
18761 : : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18762 : : == (OMP_CLAUSE_SCHEDULE_MONOTONIC
18763 : : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18764 : : {
18765 : 2 : error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
18766 : : "specified");
18767 : 2 : modifiers = 0;
18768 : : }
18769 : :
18770 : 3465 : if (c_parser_next_token_is (parser, CPP_NAME))
18771 : : {
18772 : 1708 : tree kind = c_parser_peek_token (parser)->value;
18773 : 1708 : const char *p = IDENTIFIER_POINTER (kind);
18774 : :
18775 : 1708 : switch (p[0])
18776 : : {
18777 : 169 : case 'd':
18778 : 169 : if (strcmp ("dynamic", p) != 0)
18779 : 0 : goto invalid_kind;
18780 : 169 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
18781 : 169 : break;
18782 : :
18783 : 761 : case 'g':
18784 : 761 : if (strcmp ("guided", p) != 0)
18785 : 0 : goto invalid_kind;
18786 : 761 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
18787 : 761 : break;
18788 : :
18789 : 777 : case 'r':
18790 : 777 : if (strcmp ("runtime", p) != 0)
18791 : 0 : goto invalid_kind;
18792 : 777 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
18793 : 777 : break;
18794 : :
18795 : 1 : default:
18796 : 1 : goto invalid_kind;
18797 : : }
18798 : : }
18799 : 1757 : else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
18800 : 1076 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
18801 : 681 : else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
18802 : 680 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
18803 : : else
18804 : 1 : goto invalid_kind;
18805 : :
18806 : 3463 : c_parser_consume_token (parser);
18807 : 3463 : if (c_parser_next_token_is (parser, CPP_COMMA))
18808 : : {
18809 : 1795 : location_t here;
18810 : 1795 : c_parser_consume_token (parser);
18811 : :
18812 : 1795 : here = c_parser_peek_token (parser)->location;
18813 : 1795 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18814 : 1795 : expr = convert_lvalue_to_rvalue (here, expr, false, true);
18815 : 1795 : t = expr.value;
18816 : 1795 : t = c_fully_fold (t, false, NULL);
18817 : :
18818 : 1795 : if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
18819 : 1 : error_at (here, "schedule %<runtime%> does not take "
18820 : : "a %<chunk_size%> parameter");
18821 : 1794 : else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
18822 : 0 : error_at (here,
18823 : : "schedule %<auto%> does not take "
18824 : : "a %<chunk_size%> parameter");
18825 : 1794 : else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
18826 : 1794 : || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
18827 : : {
18828 : : /* Attempt to statically determine when the number isn't
18829 : : positive. */
18830 : 1793 : tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
18831 : 1793 : build_int_cst (TREE_TYPE (t), 0));
18832 : 1793 : protected_set_expr_location (s, loc);
18833 : 1793 : if (s == boolean_true_node)
18834 : : {
18835 : 2 : warning_at (loc, OPT_Wopenmp,
18836 : : "chunk size value must be positive");
18837 : 2 : t = integer_one_node;
18838 : : }
18839 : 1793 : OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
18840 : : }
18841 : : else
18842 : 1 : c_parser_error (parser, "expected integer expression");
18843 : :
18844 : 1795 : parens.skip_until_found_close (parser);
18845 : : }
18846 : : else
18847 : 1668 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
18848 : : "expected %<,%> or %<)%>");
18849 : :
18850 : 6926 : OMP_CLAUSE_SCHEDULE_KIND (c)
18851 : 6926 : = (enum omp_clause_schedule_kind)
18852 : 3463 : (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
18853 : :
18854 : 3463 : check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
18855 : 3463 : OMP_CLAUSE_CHAIN (c) = list;
18856 : 3463 : return c;
18857 : :
18858 : 2 : invalid_kind:
18859 : 2 : c_parser_error (parser, "invalid schedule kind");
18860 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18861 : 2 : return list;
18862 : : }
18863 : :
18864 : : /* OpenMP 2.5:
18865 : : shared ( variable-list ) */
18866 : :
18867 : : static tree
18868 : 689 : c_parser_omp_clause_shared (c_parser *parser, tree list)
18869 : : {
18870 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
18871 : : }
18872 : :
18873 : : /* OpenMP 3.0:
18874 : : untied */
18875 : :
18876 : : static tree
18877 : 96 : c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18878 : : {
18879 : 96 : tree c;
18880 : :
18881 : : /* FIXME: Should we allow duplicates? */
18882 : 96 : check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
18883 : :
18884 : 96 : c = build_omp_clause (c_parser_peek_token (parser)->location,
18885 : : OMP_CLAUSE_UNTIED);
18886 : 96 : OMP_CLAUSE_CHAIN (c) = list;
18887 : :
18888 : 96 : return c;
18889 : : }
18890 : :
18891 : : /* OpenMP 4.0:
18892 : : inbranch
18893 : : notinbranch */
18894 : :
18895 : : static tree
18896 : 199 : c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
18897 : : enum omp_clause_code code, tree list)
18898 : : {
18899 : 199 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18900 : :
18901 : 199 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18902 : 199 : OMP_CLAUSE_CHAIN (c) = list;
18903 : :
18904 : 199 : return c;
18905 : : }
18906 : :
18907 : : /* OpenMP 4.0:
18908 : : parallel
18909 : : for
18910 : : sections
18911 : : taskgroup */
18912 : :
18913 : : static tree
18914 : 379 : c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
18915 : : enum omp_clause_code code, tree list)
18916 : : {
18917 : 379 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18918 : 379 : OMP_CLAUSE_CHAIN (c) = list;
18919 : :
18920 : 379 : return c;
18921 : : }
18922 : :
18923 : : /* OpenMP 4.5:
18924 : : nogroup */
18925 : :
18926 : : static tree
18927 : 18 : c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18928 : : {
18929 : 18 : check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup");
18930 : 18 : tree c = build_omp_clause (c_parser_peek_token (parser)->location,
18931 : : OMP_CLAUSE_NOGROUP);
18932 : 18 : OMP_CLAUSE_CHAIN (c) = list;
18933 : 18 : return c;
18934 : : }
18935 : :
18936 : : /* OpenMP 4.5:
18937 : : simd
18938 : : threads */
18939 : :
18940 : : static tree
18941 : 103 : c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
18942 : : enum omp_clause_code code, tree list)
18943 : : {
18944 : 103 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18945 : 103 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18946 : 103 : OMP_CLAUSE_CHAIN (c) = list;
18947 : 103 : return c;
18948 : : }
18949 : :
18950 : : /* OpenMP 4.0:
18951 : : num_teams ( expression )
18952 : :
18953 : : OpenMP 5.1:
18954 : : num_teams ( expression : expression ) */
18955 : :
18956 : : static tree
18957 : 195 : c_parser_omp_clause_num_teams (c_parser *parser, tree list)
18958 : : {
18959 : 195 : location_t num_teams_loc = c_parser_peek_token (parser)->location;
18960 : 195 : matching_parens parens;
18961 : 195 : if (parens.require_open (parser))
18962 : : {
18963 : 195 : location_t upper_loc = c_parser_peek_token (parser)->location;
18964 : 195 : location_t lower_loc = UNKNOWN_LOCATION;
18965 : 195 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18966 : 195 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
18967 : 195 : tree c, upper = expr.value, lower = NULL_TREE;
18968 : 195 : upper = c_fully_fold (upper, false, NULL);
18969 : :
18970 : 195 : if (c_parser_next_token_is (parser, CPP_COLON))
18971 : : {
18972 : 51 : c_parser_consume_token (parser);
18973 : 51 : lower_loc = upper_loc;
18974 : 51 : lower = upper;
18975 : 51 : upper_loc = c_parser_peek_token (parser)->location;
18976 : 51 : expr = c_parser_expr_no_commas (parser, NULL);
18977 : 51 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
18978 : 51 : upper = expr.value;
18979 : 51 : upper = c_fully_fold (upper, false, NULL);
18980 : : }
18981 : :
18982 : 195 : parens.skip_until_found_close (parser);
18983 : :
18984 : 390 : if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
18985 : 390 : || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
18986 : : {
18987 : 0 : c_parser_error (parser, "expected integer expression");
18988 : 0 : return list;
18989 : : }
18990 : :
18991 : : /* Attempt to statically determine when the number isn't positive. */
18992 : 195 : c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
18993 : 195 : build_int_cst (TREE_TYPE (upper), 0));
18994 : 195 : protected_set_expr_location (c, upper_loc);
18995 : 195 : if (c == boolean_true_node)
18996 : : {
18997 : 4 : warning_at (upper_loc, OPT_Wopenmp,
18998 : : "%<num_teams%> value must be positive");
18999 : 4 : upper = integer_one_node;
19000 : : }
19001 : 195 : if (lower)
19002 : : {
19003 : 51 : c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
19004 : 51 : build_int_cst (TREE_TYPE (lower), 0));
19005 : 51 : protected_set_expr_location (c, lower_loc);
19006 : 51 : if (c == boolean_true_node)
19007 : : {
19008 : 2 : warning_at (lower_loc, OPT_Wopenmp,
19009 : : "%<num_teams%> value must be positive");
19010 : 2 : lower = NULL_TREE;
19011 : : }
19012 : 49 : else if (TREE_CODE (lower) == INTEGER_CST
19013 : 7 : && TREE_CODE (upper) == INTEGER_CST
19014 : 54 : && tree_int_cst_lt (upper, lower))
19015 : : {
19016 : 2 : warning_at (lower_loc, OPT_Wopenmp,
19017 : : "%<num_teams%> lower bound %qE bigger than upper "
19018 : : "bound %qE", lower, upper);
19019 : 2 : lower = NULL_TREE;
19020 : : }
19021 : : }
19022 : :
19023 : 195 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
19024 : :
19025 : 195 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
19026 : 195 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
19027 : 195 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
19028 : 195 : OMP_CLAUSE_CHAIN (c) = list;
19029 : 195 : list = c;
19030 : : }
19031 : :
19032 : : return list;
19033 : : }
19034 : :
19035 : : /* OpenMP 4.0:
19036 : : thread_limit ( expression ) */
19037 : :
19038 : : static tree
19039 : 154 : c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
19040 : : {
19041 : 154 : location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
19042 : 154 : matching_parens parens;
19043 : 154 : if (parens.require_open (parser))
19044 : : {
19045 : 154 : location_t expr_loc = c_parser_peek_token (parser)->location;
19046 : 154 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19047 : 154 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19048 : 154 : tree c, t = expr.value;
19049 : 154 : t = c_fully_fold (t, false, NULL);
19050 : :
19051 : 154 : parens.skip_until_found_close (parser);
19052 : :
19053 : 154 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
19054 : : {
19055 : 0 : c_parser_error (parser, "expected integer expression");
19056 : 0 : return list;
19057 : : }
19058 : :
19059 : : /* Attempt to statically determine when the number isn't positive. */
19060 : 154 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
19061 : 154 : build_int_cst (TREE_TYPE (t), 0));
19062 : 154 : protected_set_expr_location (c, expr_loc);
19063 : 154 : if (c == boolean_true_node)
19064 : : {
19065 : 0 : warning_at (expr_loc, OPT_Wopenmp,
19066 : : "%<thread_limit%> value must be positive");
19067 : 0 : t = integer_one_node;
19068 : : }
19069 : :
19070 : 154 : check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
19071 : : "thread_limit");
19072 : :
19073 : 154 : c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
19074 : 154 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
19075 : 154 : OMP_CLAUSE_CHAIN (c) = list;
19076 : 154 : list = c;
19077 : : }
19078 : :
19079 : : return list;
19080 : : }
19081 : :
19082 : : /* OpenMP 4.0:
19083 : : aligned ( variable-list )
19084 : : aligned ( variable-list : constant-expression ) */
19085 : :
19086 : : static tree
19087 : 228 : c_parser_omp_clause_aligned (c_parser *parser, tree list)
19088 : : {
19089 : 228 : location_t clause_loc = c_parser_peek_token (parser)->location;
19090 : 228 : tree nl, c;
19091 : :
19092 : 228 : matching_parens parens;
19093 : 228 : if (!parens.require_open (parser))
19094 : : return list;
19095 : :
19096 : 228 : nl = c_parser_omp_variable_list (parser, clause_loc,
19097 : : OMP_CLAUSE_ALIGNED, list);
19098 : :
19099 : 228 : if (c_parser_next_token_is (parser, CPP_COLON))
19100 : : {
19101 : 212 : c_parser_consume_token (parser);
19102 : 212 : location_t expr_loc = c_parser_peek_token (parser)->location;
19103 : 212 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19104 : 212 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19105 : 212 : tree alignment = expr.value;
19106 : 212 : alignment = c_fully_fold (alignment, false, NULL);
19107 : 212 : if (TREE_CODE (alignment) != INTEGER_CST
19108 : 210 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
19109 : 422 : || tree_int_cst_sgn (alignment) != 1)
19110 : : {
19111 : 4 : error_at (clause_loc, "%<aligned%> clause alignment expression must "
19112 : : "be positive constant integer expression");
19113 : 4 : alignment = NULL_TREE;
19114 : : }
19115 : :
19116 : 444 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19117 : 232 : OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
19118 : : }
19119 : :
19120 : 228 : parens.skip_until_found_close (parser);
19121 : 228 : return nl;
19122 : : }
19123 : :
19124 : : /* OpenMP 5.0:
19125 : : allocate ( variable-list )
19126 : : allocate ( expression : variable-list )
19127 : :
19128 : : OpenMP 5.1:
19129 : : allocate ( allocator-modifier : variable-list )
19130 : : allocate ( allocator-modifier , allocator-modifier : variable-list )
19131 : :
19132 : : allocator-modifier:
19133 : : allocator ( expression )
19134 : : align ( expression ) */
19135 : :
19136 : : static tree
19137 : 467 : c_parser_omp_clause_allocate (c_parser *parser, tree list)
19138 : : {
19139 : 467 : location_t clause_loc = c_parser_peek_token (parser)->location;
19140 : 467 : tree nl, c;
19141 : 467 : tree allocator = NULL_TREE;
19142 : 467 : tree align = NULL_TREE;
19143 : :
19144 : 467 : matching_parens parens;
19145 : 467 : if (!parens.require_open (parser))
19146 : : return list;
19147 : :
19148 : 467 : if ((c_parser_next_token_is_not (parser, CPP_NAME)
19149 : 5 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
19150 : 467 : || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
19151 : 448 : && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
19152 : : {
19153 : 202 : bool has_modifiers = false;
19154 : 202 : tree orig_type = NULL_TREE;
19155 : 202 : if (c_parser_next_token_is (parser, CPP_NAME)
19156 : 202 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19157 : : {
19158 : 61 : unsigned int n = 3;
19159 : 61 : const char *p
19160 : 61 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19161 : 29 : if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
19162 : 59 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
19163 : 120 : && (c_parser_peek_nth_token_raw (parser, n)->type
19164 : : == CPP_CLOSE_PAREN))
19165 : : {
19166 : 59 : if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19167 : : == CPP_COLON)
19168 : : has_modifiers = true;
19169 : 27 : else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19170 : : == CPP_COMMA
19171 : 27 : && (c_parser_peek_nth_token_raw (parser, n + 2)->type
19172 : : == CPP_NAME)
19173 : 54 : && (c_parser_peek_nth_token_raw (parser, n + 3)->type
19174 : : == CPP_OPEN_PAREN))
19175 : : {
19176 : 27 : c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
19177 : 27 : const char *q = IDENTIFIER_POINTER (tok->value);
19178 : 27 : n += 4;
19179 : 27 : if ((strcmp (q, "allocator") == 0
19180 : 14 : || strcmp (q, "align") == 0)
19181 : 27 : && c_parser_check_balanced_raw_token_sequence (parser,
19182 : : &n)
19183 : 27 : && (c_parser_peek_nth_token_raw (parser, n)->type
19184 : : == CPP_CLOSE_PAREN)
19185 : 54 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
19186 : : == CPP_COLON))
19187 : : has_modifiers = true;
19188 : : }
19189 : : }
19190 : : if (has_modifiers)
19191 : : {
19192 : 59 : c_parser_consume_token (parser);
19193 : 59 : matching_parens parens2;
19194 : 59 : parens2.require_open (parser);
19195 : 59 : location_t expr_loc = c_parser_peek_token (parser)->location;
19196 : 59 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19197 : 59 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19198 : 59 : if (expr.value == error_mark_node)
19199 : : ;
19200 : 58 : else if (strcmp (p, "allocator") == 0)
19201 : : {
19202 : 31 : allocator = expr.value;
19203 : 31 : allocator = c_fully_fold (allocator, false, NULL);
19204 : 3 : orig_type = expr.original_type
19205 : 31 : ? expr.original_type : TREE_TYPE (allocator);
19206 : 31 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19207 : : }
19208 : : else
19209 : : {
19210 : 27 : align = expr.value;
19211 : 27 : align = c_fully_fold (align, false, NULL);
19212 : : }
19213 : 59 : parens2.skip_until_found_close (parser);
19214 : 59 : if (c_parser_next_token_is (parser, CPP_COMMA))
19215 : : {
19216 : 27 : c_parser_consume_token (parser);
19217 : 27 : c_token *tok = c_parser_peek_token (parser);
19218 : 27 : const char *q = "";
19219 : 27 : if (c_parser_next_token_is (parser, CPP_NAME))
19220 : 27 : q = IDENTIFIER_POINTER (tok->value);
19221 : 27 : if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
19222 : : {
19223 : 0 : c_parser_error (parser, "expected %<allocator%> or "
19224 : : "%<align%>");
19225 : 0 : parens.skip_until_found_close (parser);
19226 : 2 : return list;
19227 : : }
19228 : 27 : else if (strcmp (p, q) == 0)
19229 : : {
19230 : 2 : error_at (tok->location, "duplicate %qs modifier", p);
19231 : 2 : parens.skip_until_found_close (parser);
19232 : 2 : return list;
19233 : : }
19234 : 25 : c_parser_consume_token (parser);
19235 : 25 : if (!parens2.require_open (parser))
19236 : : {
19237 : 0 : parens.skip_until_found_close (parser);
19238 : 0 : return list;
19239 : : }
19240 : 25 : expr_loc = c_parser_peek_token (parser)->location;
19241 : 25 : expr = c_parser_expr_no_commas (parser, NULL);
19242 : 25 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19243 : : true);
19244 : 25 : if (strcmp (q, "allocator") == 0)
19245 : : {
19246 : 12 : allocator = expr.value;
19247 : 12 : allocator = c_fully_fold (allocator, false, NULL);
19248 : 2 : orig_type = expr.original_type
19249 : 12 : ? expr.original_type : TREE_TYPE (allocator);
19250 : 12 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19251 : : }
19252 : : else
19253 : : {
19254 : 13 : align = expr.value;
19255 : 13 : align = c_fully_fold (align, false, NULL);
19256 : : }
19257 : 25 : parens2.skip_until_found_close (parser);
19258 : : }
19259 : : }
19260 : : }
19261 : 59 : if (!has_modifiers)
19262 : : {
19263 : 143 : location_t expr_loc = c_parser_peek_token (parser)->location;
19264 : 143 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19265 : 143 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19266 : 143 : allocator = expr.value;
19267 : 143 : allocator = c_fully_fold (allocator, false, NULL);
19268 : 7 : orig_type = expr.original_type
19269 : 143 : ? expr.original_type : TREE_TYPE (allocator);
19270 : 143 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19271 : : }
19272 : 200 : if (allocator
19273 : 200 : && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
19274 : 183 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
19275 : 362 : || (TYPE_NAME (orig_type)
19276 : 181 : != get_identifier ("omp_allocator_handle_t"))))
19277 : : {
19278 : 8 : error_at (clause_loc, "%<allocate%> clause allocator expression "
19279 : : "has type %qT rather than "
19280 : : "%<omp_allocator_handle_t%>",
19281 : 4 : TREE_TYPE (allocator));
19282 : 4 : allocator = NULL_TREE;
19283 : : }
19284 : 200 : if (align
19285 : 200 : && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
19286 : 38 : || !tree_fits_uhwi_p (align)
19287 : 37 : || !integer_pow2p (align)))
19288 : : {
19289 : 4 : error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
19290 : : "argument needs to be positive constant "
19291 : : "power of two integer expression");
19292 : 4 : align = NULL_TREE;
19293 : : }
19294 : 200 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19295 : : {
19296 : 0 : parens.skip_until_found_close (parser);
19297 : 0 : return list;
19298 : : }
19299 : : }
19300 : :
19301 : 465 : nl = c_parser_omp_variable_list (parser, clause_loc,
19302 : : OMP_CLAUSE_ALLOCATE, list);
19303 : :
19304 : 465 : if (allocator || align)
19305 : 465 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19306 : : {
19307 : 274 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
19308 : 274 : OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
19309 : : }
19310 : :
19311 : 465 : parens.skip_until_found_close (parser);
19312 : 465 : return nl;
19313 : : }
19314 : :
19315 : : /* OpenMP 4.0:
19316 : : linear ( variable-list )
19317 : : linear ( variable-list : expression )
19318 : :
19319 : : OpenMP 4.5:
19320 : : linear ( modifier ( variable-list ) )
19321 : : linear ( modifier ( variable-list ) : expression )
19322 : :
19323 : : modifier:
19324 : : val
19325 : :
19326 : : OpenMP 5.2:
19327 : : linear ( variable-list : modifiers-list )
19328 : :
19329 : : modifiers:
19330 : : val
19331 : : step ( expression ) */
19332 : :
19333 : : static tree
19334 : 474 : c_parser_omp_clause_linear (c_parser *parser, tree list)
19335 : : {
19336 : 474 : location_t clause_loc = c_parser_peek_token (parser)->location;
19337 : 474 : tree nl, c, step;
19338 : 474 : enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
19339 : 474 : bool old_linear_modifier = false;
19340 : :
19341 : 474 : matching_parens parens;
19342 : 474 : if (!parens.require_open (parser))
19343 : : return list;
19344 : :
19345 : 474 : if (c_parser_next_token_is (parser, CPP_NAME))
19346 : : {
19347 : 474 : c_token *tok = c_parser_peek_token (parser);
19348 : 474 : const char *p = IDENTIFIER_POINTER (tok->value);
19349 : 474 : if (strcmp ("val", p) == 0)
19350 : 12 : kind = OMP_CLAUSE_LINEAR_VAL;
19351 : 474 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
19352 : : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19353 : 12 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19354 : : {
19355 : 12 : old_linear_modifier = true;
19356 : 12 : c_parser_consume_token (parser);
19357 : 12 : c_parser_consume_token (parser);
19358 : : }
19359 : : }
19360 : :
19361 : 474 : nl = c_parser_omp_variable_list (parser, clause_loc,
19362 : : OMP_CLAUSE_LINEAR, list);
19363 : :
19364 : 474 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19365 : 12 : parens.skip_until_found_close (parser);
19366 : :
19367 : 474 : if (c_parser_next_token_is (parser, CPP_COLON))
19368 : : {
19369 : 348 : c_parser_consume_token (parser);
19370 : 348 : location_t expr_loc = c_parser_peek_token (parser)->location;
19371 : 348 : bool has_modifiers = false;
19372 : 348 : if (kind == OMP_CLAUSE_LINEAR_DEFAULT
19373 : 684 : && c_parser_next_token_is (parser, CPP_NAME))
19374 : : {
19375 : 72 : c_token *tok = c_parser_peek_token (parser);
19376 : 72 : const char *p = IDENTIFIER_POINTER (tok->value);
19377 : 72 : unsigned int pos = 0;
19378 : 72 : if (strcmp ("val", p) == 0)
19379 : 7 : pos = 2;
19380 : 65 : else if (strcmp ("step", p) == 0
19381 : 65 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19382 : : {
19383 : 13 : pos = 3;
19384 : 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &pos)
19385 : 13 : && (c_parser_peek_nth_token_raw (parser, pos)->type
19386 : : == CPP_CLOSE_PAREN))
19387 : 13 : ++pos;
19388 : : else
19389 : 0 : pos = 0;
19390 : : }
19391 : 72 : if (pos)
19392 : : {
19393 : 20 : tok = c_parser_peek_nth_token_raw (parser, pos);
19394 : 20 : if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
19395 : 17 : has_modifiers = true;
19396 : : }
19397 : : }
19398 : 72 : if (has_modifiers)
19399 : : {
19400 : : step = NULL_TREE;
19401 : 25 : while (c_parser_next_token_is (parser, CPP_NAME))
19402 : : {
19403 : 25 : c_token *tok = c_parser_peek_token (parser);
19404 : 25 : const char *p = IDENTIFIER_POINTER (tok->value);
19405 : 25 : if (strcmp ("val", p) == 0)
19406 : : {
19407 : 9 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19408 : : error_at (tok->location, "multiple linear modifiers");
19409 : 9 : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19410 : 9 : c_parser_consume_token (parser);
19411 : : }
19412 : 16 : else if (strcmp ("step", p) == 0)
19413 : : {
19414 : 16 : c_parser_consume_token (parser);
19415 : 16 : matching_parens parens2;
19416 : 16 : if (parens2.require_open (parser))
19417 : : {
19418 : 16 : if (step)
19419 : 0 : error_at (tok->location,
19420 : : "multiple %<step%> modifiers");
19421 : 16 : expr_loc = c_parser_peek_token (parser)->location;
19422 : 16 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19423 : 16 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19424 : : true);
19425 : 16 : step = c_fully_fold (expr.value, false, NULL);
19426 : 16 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19427 : : {
19428 : 0 : error_at (clause_loc, "%<linear%> clause step "
19429 : : "expression must be integral");
19430 : 0 : step = integer_one_node;
19431 : : }
19432 : 16 : parens2.skip_until_found_close (parser);
19433 : : }
19434 : : else
19435 : : break;
19436 : : }
19437 : : else
19438 : : break;
19439 : 25 : if (c_parser_next_token_is (parser, CPP_COMMA))
19440 : : {
19441 : 8 : c_parser_consume_token (parser);
19442 : 8 : continue;
19443 : : }
19444 : : break;
19445 : : }
19446 : 17 : if (!step)
19447 : 1 : step = integer_one_node;
19448 : : }
19449 : : else
19450 : : {
19451 : 331 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19452 : 331 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19453 : 331 : step = c_fully_fold (expr.value, false, NULL);
19454 : 331 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19455 : : {
19456 : 2 : error_at (clause_loc, "%<linear%> clause step expression must "
19457 : : "be integral");
19458 : 2 : step = integer_one_node;
19459 : : }
19460 : : }
19461 : :
19462 : : }
19463 : : else
19464 : 126 : step = integer_one_node;
19465 : :
19466 : 957 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19467 : : {
19468 : 483 : OMP_CLAUSE_LINEAR_STEP (c) = step;
19469 : 483 : OMP_CLAUSE_LINEAR_KIND (c) = kind;
19470 : 483 : OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
19471 : : }
19472 : :
19473 : 474 : parens.skip_until_found_close (parser);
19474 : 474 : return nl;
19475 : : }
19476 : :
19477 : : /* OpenMP 5.0:
19478 : : nontemporal ( variable-list ) */
19479 : :
19480 : : static tree
19481 : 121 : c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
19482 : : {
19483 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_NONTEMPORAL, list);
19484 : : }
19485 : :
19486 : : /* OpenMP 4.0:
19487 : : safelen ( constant-expression ) */
19488 : :
19489 : : static tree
19490 : 227 : c_parser_omp_clause_safelen (c_parser *parser, tree list)
19491 : : {
19492 : 227 : location_t clause_loc = c_parser_peek_token (parser)->location;
19493 : 227 : tree c, t;
19494 : :
19495 : 227 : matching_parens parens;
19496 : 227 : if (!parens.require_open (parser))
19497 : : return list;
19498 : :
19499 : 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
19500 : 227 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19501 : 227 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19502 : 227 : t = expr.value;
19503 : 227 : t = c_fully_fold (t, false, NULL);
19504 : 227 : if (TREE_CODE (t) != INTEGER_CST
19505 : 225 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19506 : 452 : || tree_int_cst_sgn (t) != 1)
19507 : : {
19508 : 4 : error_at (clause_loc, "%<safelen%> clause expression must "
19509 : : "be positive constant integer expression");
19510 : 4 : t = NULL_TREE;
19511 : : }
19512 : :
19513 : 227 : parens.skip_until_found_close (parser);
19514 : 227 : if (t == NULL_TREE || t == error_mark_node)
19515 : : return list;
19516 : :
19517 : 223 : check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen");
19518 : :
19519 : 223 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
19520 : 223 : OMP_CLAUSE_SAFELEN_EXPR (c) = t;
19521 : 223 : OMP_CLAUSE_CHAIN (c) = list;
19522 : 223 : return c;
19523 : : }
19524 : :
19525 : : /* OpenMP 4.0:
19526 : : simdlen ( constant-expression ) */
19527 : :
19528 : : static tree
19529 : 317 : c_parser_omp_clause_simdlen (c_parser *parser, tree list)
19530 : : {
19531 : 317 : location_t clause_loc = c_parser_peek_token (parser)->location;
19532 : 317 : tree c, t;
19533 : :
19534 : 317 : matching_parens parens;
19535 : 317 : if (!parens.require_open (parser))
19536 : : return list;
19537 : :
19538 : 317 : location_t expr_loc = c_parser_peek_token (parser)->location;
19539 : 317 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19540 : 317 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19541 : 317 : t = expr.value;
19542 : 317 : t = c_fully_fold (t, false, NULL);
19543 : 317 : if (TREE_CODE (t) != INTEGER_CST
19544 : 315 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19545 : 632 : || tree_int_cst_sgn (t) != 1)
19546 : : {
19547 : 4 : error_at (clause_loc, "%<simdlen%> clause expression must "
19548 : : "be positive constant integer expression");
19549 : 4 : t = NULL_TREE;
19550 : : }
19551 : :
19552 : 317 : parens.skip_until_found_close (parser);
19553 : 317 : if (t == NULL_TREE || t == error_mark_node)
19554 : : return list;
19555 : :
19556 : 313 : check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen");
19557 : :
19558 : 313 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
19559 : 313 : OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
19560 : 313 : OMP_CLAUSE_CHAIN (c) = list;
19561 : 313 : return c;
19562 : : }
19563 : :
19564 : : /* OpenMP 4.5:
19565 : : vec:
19566 : : identifier [+/- integer]
19567 : : vec , identifier [+/- integer]
19568 : : */
19569 : :
19570 : : static tree
19571 : 206 : c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
19572 : : tree list, bool depend_p)
19573 : : {
19574 : 206 : tree vec = NULL;
19575 : 206 : if (c_parser_next_token_is_not (parser, CPP_NAME)
19576 : 206 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
19577 : : {
19578 : 0 : c_parser_error (parser, "expected identifier");
19579 : 0 : return list;
19580 : : }
19581 : :
19582 : 206 : if (!depend_p)
19583 : : {
19584 : 83 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19585 : 83 : if (strcmp (p, "omp_cur_iteration") == 0
19586 : 36 : && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
19587 : 34 : && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
19588 : 116 : && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
19589 : : {
19590 : 33 : tree val = c_parser_peek_nth_token (parser, 3)->value;
19591 : 33 : if (integer_onep (val))
19592 : : {
19593 : 33 : c_parser_consume_token (parser);
19594 : 33 : c_parser_consume_token (parser);
19595 : 33 : c_parser_consume_token (parser);
19596 : 33 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19597 : 33 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19598 : 33 : OMP_CLAUSE_CHAIN (u) = list;
19599 : 33 : return u;
19600 : : }
19601 : : }
19602 : : }
19603 : :
19604 : :
19605 : :
19606 : 1151 : while (c_parser_next_token_is (parser, CPP_NAME)
19607 : 1151 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
19608 : : {
19609 : 1151 : tree t = lookup_name (c_parser_peek_token (parser)->value);
19610 : 1151 : tree addend = NULL;
19611 : :
19612 : 1151 : if (t == NULL_TREE)
19613 : : {
19614 : 6 : undeclared_variable (c_parser_peek_token (parser)->location,
19615 : 6 : c_parser_peek_token (parser)->value);
19616 : 6 : t = error_mark_node;
19617 : : }
19618 : :
19619 : 1151 : c_parser_consume_token (parser);
19620 : :
19621 : 1151 : bool neg = false;
19622 : 1151 : if (c_parser_next_token_is (parser, CPP_MINUS))
19623 : : neg = true;
19624 : 920 : else if (!c_parser_next_token_is (parser, CPP_PLUS))
19625 : : {
19626 : 857 : addend = integer_zero_node;
19627 : 857 : neg = false;
19628 : 857 : goto add_to_vector;
19629 : : }
19630 : 294 : c_parser_consume_token (parser);
19631 : :
19632 : 294 : if (c_parser_next_token_is_not (parser, CPP_NUMBER))
19633 : : {
19634 : 1 : c_parser_error (parser, "expected integer");
19635 : 1 : return list;
19636 : : }
19637 : :
19638 : 293 : addend = c_parser_peek_token (parser)->value;
19639 : 293 : if (TREE_CODE (addend) != INTEGER_CST)
19640 : : {
19641 : 0 : c_parser_error (parser, "expected integer");
19642 : 0 : return list;
19643 : : }
19644 : 293 : c_parser_consume_token (parser);
19645 : :
19646 : 1150 : add_to_vector:
19647 : 1150 : if (t != error_mark_node)
19648 : : {
19649 : 1145 : vec = tree_cons (addend, t, vec);
19650 : 1145 : if (neg)
19651 : 228 : OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
19652 : : }
19653 : :
19654 : 1150 : if (c_parser_next_token_is_not (parser, CPP_COMMA)
19655 : 979 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
19656 : 2128 : || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
19657 : : break;
19658 : :
19659 : 978 : c_parser_consume_token (parser);
19660 : : }
19661 : :
19662 : 172 : if (vec == NULL_TREE)
19663 : : return list;
19664 : :
19665 : 168 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19666 : 168 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19667 : 168 : OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
19668 : 168 : OMP_CLAUSE_DECL (u) = nreverse (vec);
19669 : 168 : OMP_CLAUSE_CHAIN (u) = list;
19670 : 168 : return u;
19671 : : }
19672 : :
19673 : : /* OpenMP 5.0:
19674 : : iterators ( iterators-definition )
19675 : :
19676 : : iterators-definition:
19677 : : iterator-specifier
19678 : : iterator-specifier , iterators-definition
19679 : :
19680 : : iterator-specifier:
19681 : : identifier = range-specification
19682 : : iterator-type identifier = range-specification
19683 : :
19684 : : range-specification:
19685 : : begin : end
19686 : : begin : end : step */
19687 : :
19688 : : static tree
19689 : 124 : c_parser_omp_iterators (c_parser *parser)
19690 : : {
19691 : 124 : tree ret = NULL_TREE, *last = &ret;
19692 : 124 : c_parser_consume_token (parser);
19693 : :
19694 : 124 : push_scope ();
19695 : :
19696 : 124 : matching_parens parens;
19697 : 124 : if (!parens.require_open (parser))
19698 : 1 : return error_mark_node;
19699 : :
19700 : 173 : do
19701 : : {
19702 : 148 : tree iter_type = NULL_TREE, type_expr = NULL_TREE;
19703 : 148 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
19704 : : {
19705 : 50 : struct c_type_name *type = c_parser_type_name (parser);
19706 : 50 : if (type != NULL)
19707 : 50 : iter_type = groktypename (type, &type_expr, NULL);
19708 : : }
19709 : 50 : if (iter_type == NULL_TREE)
19710 : 98 : iter_type = integer_type_node;
19711 : :
19712 : 148 : location_t loc = c_parser_peek_token (parser)->location;
19713 : 148 : if (!c_parser_next_token_is (parser, CPP_NAME))
19714 : : {
19715 : 8 : c_parser_error (parser, "expected identifier");
19716 : 8 : break;
19717 : : }
19718 : :
19719 : 140 : tree id = c_parser_peek_token (parser)->value;
19720 : 140 : c_parser_consume_token (parser);
19721 : :
19722 : 140 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
19723 : : break;
19724 : :
19725 : 138 : location_t eloc = c_parser_peek_token (parser)->location;
19726 : 138 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19727 : 138 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19728 : 138 : tree begin = expr.value;
19729 : :
19730 : 138 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19731 : : break;
19732 : :
19733 : 136 : eloc = c_parser_peek_token (parser)->location;
19734 : 136 : expr = c_parser_expr_no_commas (parser, NULL);
19735 : 136 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19736 : 136 : tree end = expr.value;
19737 : :
19738 : 136 : tree step = integer_one_node;
19739 : 136 : if (c_parser_next_token_is (parser, CPP_COLON))
19740 : : {
19741 : 57 : c_parser_consume_token (parser);
19742 : 57 : eloc = c_parser_peek_token (parser)->location;
19743 : 57 : expr = c_parser_expr_no_commas (parser, NULL);
19744 : 57 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19745 : 57 : step = expr.value;
19746 : : }
19747 : :
19748 : 136 : tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
19749 : 136 : DECL_ARTIFICIAL (iter_var) = 1;
19750 : 136 : DECL_CONTEXT (iter_var) = current_function_decl;
19751 : 136 : pushdecl (iter_var);
19752 : :
19753 : 136 : *last = make_tree_vec (6);
19754 : 136 : TREE_VEC_ELT (*last, 0) = iter_var;
19755 : 136 : TREE_VEC_ELT (*last, 1) = begin;
19756 : 136 : TREE_VEC_ELT (*last, 2) = end;
19757 : 136 : TREE_VEC_ELT (*last, 3) = step;
19758 : 136 : last = &TREE_CHAIN (*last);
19759 : :
19760 : 136 : if (c_parser_next_token_is (parser, CPP_COMMA))
19761 : : {
19762 : 25 : c_parser_consume_token (parser);
19763 : 25 : continue;
19764 : : }
19765 : : break;
19766 : : }
19767 : : while (1);
19768 : :
19769 : 123 : parens.skip_until_found_close (parser);
19770 : 123 : return ret ? ret : error_mark_node;
19771 : : }
19772 : :
19773 : : /* OpenMP 5.0:
19774 : : affinity ( [aff-modifier :] variable-list )
19775 : : aff-modifier:
19776 : : iterator ( iterators-definition ) */
19777 : :
19778 : : static tree
19779 : 146 : c_parser_omp_clause_affinity (c_parser *parser, tree list)
19780 : : {
19781 : 146 : location_t clause_loc = c_parser_peek_token (parser)->location;
19782 : 146 : tree nl, iterators = NULL_TREE;
19783 : :
19784 : 146 : matching_parens parens;
19785 : 146 : if (!parens.require_open (parser))
19786 : : return list;
19787 : :
19788 : 146 : if (c_parser_next_token_is (parser, CPP_NAME))
19789 : : {
19790 : 144 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19791 : 144 : bool parse_iter = ((strcmp ("iterator", p) == 0)
19792 : 144 : && (c_parser_peek_2nd_token (parser)->type
19793 : 50 : == CPP_OPEN_PAREN));
19794 : 50 : if (parse_iter)
19795 : : {
19796 : 50 : unsigned n = 3;
19797 : 50 : parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, &n)
19798 : 50 : && (c_parser_peek_nth_token_raw (parser, n)->type
19799 : : == CPP_CLOSE_PAREN)
19800 : 100 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
19801 : : == CPP_COLON));
19802 : : }
19803 : 3 : if (parse_iter)
19804 : : {
19805 : 47 : iterators = c_parser_omp_iterators (parser);
19806 : 47 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19807 : : {
19808 : 0 : if (iterators)
19809 : 0 : pop_scope ();
19810 : 0 : parens.skip_until_found_close (parser);
19811 : 0 : return list;
19812 : : }
19813 : : }
19814 : : }
19815 : 146 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_AFFINITY,
19816 : : list);
19817 : 146 : if (iterators)
19818 : : {
19819 : 47 : tree block = pop_scope ();
19820 : 47 : if (iterators != error_mark_node)
19821 : : {
19822 : 43 : TREE_VEC_ELT (iterators, 5) = block;
19823 : 99 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19824 : 112 : OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
19825 : 56 : OMP_CLAUSE_DECL (c));
19826 : : }
19827 : : }
19828 : :
19829 : 146 : parens.skip_until_found_close (parser);
19830 : 146 : return nl;
19831 : : }
19832 : :
19833 : :
19834 : : /* OpenMP 4.0:
19835 : : depend ( depend-kind: variable-list )
19836 : :
19837 : : depend-kind:
19838 : : in | out | inout
19839 : :
19840 : : OpenMP 4.5:
19841 : : depend ( source )
19842 : :
19843 : : depend ( sink : vec )
19844 : :
19845 : : OpenMP 5.0:
19846 : : depend ( depend-modifier , depend-kind: variable-list )
19847 : :
19848 : : depend-kind:
19849 : : in | out | inout | mutexinoutset | depobj | inoutset
19850 : :
19851 : : depend-modifier:
19852 : : iterator ( iterators-definition ) */
19853 : :
19854 : : static tree
19855 : 893 : c_parser_omp_clause_depend (c_parser *parser, tree list)
19856 : : {
19857 : 893 : location_t clause_loc = c_parser_peek_token (parser)->location;
19858 : 893 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
19859 : 893 : enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
19860 : 893 : tree nl, c, iterators = NULL_TREE;
19861 : :
19862 : 893 : matching_parens parens;
19863 : 893 : if (!parens.require_open (parser))
19864 : : return list;
19865 : :
19866 : 1047 : do
19867 : : {
19868 : 970 : if (c_parser_next_token_is_not (parser, CPP_NAME))
19869 : 0 : goto invalid_kind;
19870 : :
19871 : 970 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19872 : 970 : if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
19873 : : {
19874 : 77 : iterators = c_parser_omp_iterators (parser);
19875 : 77 : c_parser_require (parser, CPP_COMMA, "expected %<,%>");
19876 : 77 : continue;
19877 : : }
19878 : 893 : if (strcmp ("in", p) == 0)
19879 : : kind = OMP_CLAUSE_DEPEND_IN;
19880 : 642 : else if (strcmp ("inout", p) == 0)
19881 : : kind = OMP_CLAUSE_DEPEND_INOUT;
19882 : 423 : else if (strcmp ("inoutset", p) == 0)
19883 : : kind = OMP_CLAUSE_DEPEND_INOUTSET;
19884 : 408 : else if (strcmp ("mutexinoutset", p) == 0)
19885 : : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
19886 : 387 : else if (strcmp ("out", p) == 0)
19887 : : kind = OMP_CLAUSE_DEPEND_OUT;
19888 : 242 : else if (strcmp ("depobj", p) == 0)
19889 : : kind = OMP_CLAUSE_DEPEND_DEPOBJ;
19890 : 221 : else if (strcmp ("sink", p) == 0)
19891 : : dkind = OMP_CLAUSE_DOACROSS_SINK;
19892 : 98 : else if (strcmp ("source", p) == 0)
19893 : : dkind = OMP_CLAUSE_DOACROSS_SOURCE;
19894 : : else
19895 : 2 : goto invalid_kind;
19896 : 891 : break;
19897 : 77 : }
19898 : : while (1);
19899 : :
19900 : 891 : c_parser_consume_token (parser);
19901 : :
19902 : 891 : if (iterators
19903 : 891 : && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
19904 : 891 : || dkind == OMP_CLAUSE_DOACROSS_SINK))
19905 : : {
19906 : 2 : pop_scope ();
19907 : 2 : error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
19908 : : dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
19909 : 2 : iterators = NULL_TREE;
19910 : : }
19911 : :
19912 : 891 : if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
19913 : : {
19914 : 96 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19915 : 96 : OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
19916 : 96 : OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
19917 : 96 : OMP_CLAUSE_DECL (c) = NULL_TREE;
19918 : 96 : OMP_CLAUSE_CHAIN (c) = list;
19919 : 96 : parens.skip_until_found_close (parser);
19920 : 96 : return c;
19921 : : }
19922 : :
19923 : 795 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19924 : 0 : goto resync_fail;
19925 : :
19926 : 795 : if (dkind == OMP_CLAUSE_DOACROSS_SINK)
19927 : 123 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
19928 : : else
19929 : : {
19930 : 672 : nl = c_parser_omp_variable_list (parser, clause_loc,
19931 : : OMP_CLAUSE_DEPEND, list);
19932 : :
19933 : 672 : if (iterators)
19934 : : {
19935 : 73 : tree block = pop_scope ();
19936 : 73 : if (iterators == error_mark_node)
19937 : : iterators = NULL_TREE;
19938 : : else
19939 : 68 : TREE_VEC_ELT (iterators, 5) = block;
19940 : : }
19941 : :
19942 : 1385 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19943 : : {
19944 : 713 : OMP_CLAUSE_DEPEND_KIND (c) = kind;
19945 : 713 : if (iterators)
19946 : 150 : OMP_CLAUSE_DECL (c)
19947 : 150 : = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
19948 : : }
19949 : : }
19950 : :
19951 : 795 : parens.skip_until_found_close (parser);
19952 : 795 : return nl;
19953 : :
19954 : 2 : invalid_kind:
19955 : 2 : c_parser_error (parser, "invalid depend kind");
19956 : 2 : resync_fail:
19957 : 2 : parens.skip_until_found_close (parser);
19958 : 2 : if (iterators)
19959 : 2 : pop_scope ();
19960 : : return list;
19961 : : }
19962 : :
19963 : : /* OpenMP 5.2:
19964 : : doacross ( source : )
19965 : : doacross ( source : omp_cur_iteration )
19966 : :
19967 : : doacross ( sink : vec )
19968 : : doacross ( sink : omp_cur_iteration - logical_iteration ) */
19969 : :
19970 : : static tree
19971 : 145 : c_parser_omp_clause_doacross (c_parser *parser, tree list)
19972 : : {
19973 : 145 : location_t clause_loc = c_parser_peek_token (parser)->location;
19974 : 145 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
19975 : 145 : tree nl;
19976 : 145 : const char *p;
19977 : :
19978 : 145 : matching_parens parens;
19979 : 145 : if (!parens.require_open (parser))
19980 : : return list;
19981 : :
19982 : 145 : if (c_parser_next_token_is_not (parser, CPP_NAME))
19983 : 0 : goto invalid_kind;
19984 : :
19985 : 145 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19986 : 145 : if (strcmp ("sink", p) == 0)
19987 : : kind = OMP_CLAUSE_DOACROSS_SINK;
19988 : 60 : else if (strcmp ("source", p) == 0)
19989 : : kind = OMP_CLAUSE_DOACROSS_SOURCE;
19990 : : else
19991 : 0 : goto invalid_kind;
19992 : :
19993 : 145 : c_parser_consume_token (parser);
19994 : :
19995 : 145 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19996 : 4 : goto resync_fail;
19997 : :
19998 : 141 : if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
19999 : : {
20000 : 58 : if (c_parser_next_token_is (parser, CPP_NAME)
20001 : 58 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
20002 : : "omp_cur_iteration") == 0)
20003 : 28 : c_parser_consume_token (parser);
20004 : 58 : nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20005 : 58 : OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
20006 : 58 : OMP_CLAUSE_DECL (nl) = NULL_TREE;
20007 : 58 : OMP_CLAUSE_CHAIN (nl) = list;
20008 : : }
20009 : : else
20010 : 83 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
20011 : :
20012 : 141 : parens.skip_until_found_close (parser);
20013 : 141 : return nl;
20014 : :
20015 : 0 : invalid_kind:
20016 : 0 : c_parser_error (parser, "invalid doacross kind");
20017 : 4 : resync_fail:
20018 : 4 : parens.skip_until_found_close (parser);
20019 : 4 : return list;
20020 : : }
20021 : :
20022 : : /* OpenMP 4.0:
20023 : : map ( map-kind: variable-list )
20024 : : map ( variable-list )
20025 : :
20026 : : map-kind:
20027 : : alloc | to | from | tofrom
20028 : :
20029 : : OpenMP 4.5:
20030 : : map-kind:
20031 : : alloc | to | from | tofrom | release | delete
20032 : :
20033 : : map ( always [,] map-kind: variable-list )
20034 : :
20035 : : OpenMP 5.0:
20036 : : map ( [map-type-modifier[,] ...] map-kind: variable-list )
20037 : :
20038 : : map-type-modifier:
20039 : : always | close */
20040 : :
20041 : : static tree
20042 : 1706 : c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
20043 : : {
20044 : 1706 : location_t clause_loc = c_parser_peek_token (parser)->location;
20045 : 1706 : tree nl, c;
20046 : 1706 : enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
20047 : :
20048 : 1706 : matching_parens parens;
20049 : 1706 : if (!parens.require_open (parser))
20050 : : return list;
20051 : :
20052 : : int pos = 1;
20053 : 2259 : int map_kind_pos = 0;
20054 : 2259 : while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
20055 : : {
20056 : 1943 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
20057 : : {
20058 : : map_kind_pos = pos;
20059 : : break;
20060 : : }
20061 : :
20062 : 553 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
20063 : : pos++;
20064 : 378 : else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
20065 : : == CPP_OPEN_PAREN)
20066 : : {
20067 : 13 : unsigned int npos = pos + 2;
20068 : 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
20069 : 13 : && (c_parser_peek_nth_token_raw (parser, npos)->type
20070 : : == CPP_CLOSE_PAREN)
20071 : 26 : && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
20072 : : == CPP_COMMA))
20073 : 12 : pos = npos + 1;
20074 : : }
20075 : :
20076 : 553 : pos++;
20077 : : }
20078 : :
20079 : 1706 : int always_modifier = 0;
20080 : 1706 : int close_modifier = 0;
20081 : 1706 : int present_modifier = 0;
20082 : 1706 : int mapper_modifier = 0;
20083 : 1706 : tree mapper_name = NULL_TREE;
20084 : 2042 : for (int pos = 1; pos < map_kind_pos; ++pos)
20085 : : {
20086 : 353 : c_token *tok = c_parser_peek_token (parser);
20087 : :
20088 : 353 : if (tok->type == CPP_COMMA)
20089 : : {
20090 : 147 : c_parser_consume_token (parser);
20091 : 147 : continue;
20092 : : }
20093 : :
20094 : 206 : const char *p = IDENTIFIER_POINTER (tok->value);
20095 : 206 : if (strcmp ("always", p) == 0)
20096 : : {
20097 : 75 : if (always_modifier)
20098 : : {
20099 : 4 : c_parser_error (parser, "too many %<always%> modifiers");
20100 : 4 : parens.skip_until_found_close (parser);
20101 : 4 : return list;
20102 : : }
20103 : 71 : always_modifier++;
20104 : 71 : c_parser_consume_token (parser);
20105 : : }
20106 : 131 : else if (strcmp ("close", p) == 0)
20107 : : {
20108 : 62 : if (close_modifier)
20109 : : {
20110 : 4 : c_parser_error (parser, "too many %<close%> modifiers");
20111 : 4 : parens.skip_until_found_close (parser);
20112 : 4 : return list;
20113 : : }
20114 : 58 : close_modifier++;
20115 : 58 : c_parser_consume_token (parser);
20116 : : }
20117 : 69 : else if (strcmp ("mapper", p) == 0)
20118 : : {
20119 : 12 : c_parser_consume_token (parser);
20120 : :
20121 : 12 : matching_parens mparens;
20122 : 12 : if (mparens.require_open (parser))
20123 : : {
20124 : 12 : if (mapper_modifier)
20125 : : {
20126 : 0 : c_parser_error (parser, "too many %<mapper%> modifiers");
20127 : : /* Assume it's a well-formed mapper modifier, even if it
20128 : : seems to be in the wrong place. */
20129 : 0 : c_parser_consume_token (parser);
20130 : 0 : mparens.require_close (parser);
20131 : 0 : parens.skip_until_found_close (parser);
20132 : 0 : return list;
20133 : : }
20134 : :
20135 : 12 : tok = c_parser_peek_token (parser);
20136 : :
20137 : 12 : switch (tok->type)
20138 : : {
20139 : 5 : case CPP_NAME:
20140 : 5 : {
20141 : 5 : mapper_name = tok->value;
20142 : 5 : c_parser_consume_token (parser);
20143 : 5 : if (declare_mapper_p)
20144 : : {
20145 : 1 : error_at (tok->location,
20146 : : "in %<declare mapper%> directives, parameter "
20147 : : "to %<mapper%> modifier must be %<default%>");
20148 : : }
20149 : : }
20150 : : break;
20151 : :
20152 : 7 : case CPP_KEYWORD:
20153 : 7 : if (tok->keyword == RID_DEFAULT)
20154 : : {
20155 : 7 : c_parser_consume_token (parser);
20156 : 7 : break;
20157 : : }
20158 : : /* Fallthrough. */
20159 : :
20160 : 0 : default:
20161 : 0 : error_at (tok->location,
20162 : : "expected identifier or %<default%>");
20163 : 0 : return list;
20164 : : }
20165 : :
20166 : 12 : if (!mparens.require_close (parser))
20167 : : {
20168 : 0 : parens.skip_until_found_close (parser);
20169 : 0 : return list;
20170 : : }
20171 : :
20172 : 12 : mapper_modifier++;
20173 : 12 : pos += 3;
20174 : : }
20175 : : }
20176 : 57 : else if (strcmp ("present", p) == 0)
20177 : : {
20178 : 52 : if (present_modifier)
20179 : : {
20180 : 4 : c_parser_error (parser, "too many %<present%> modifiers");
20181 : 4 : parens.skip_until_found_close (parser);
20182 : 4 : return list;
20183 : : }
20184 : 48 : present_modifier++;
20185 : 48 : c_parser_consume_token (parser);
20186 : : }
20187 : : else
20188 : : {
20189 : 5 : c_parser_error (parser, "%<map%> clause with map-type modifier other "
20190 : : "than %<always%>, %<close%>, %<mapper%> or "
20191 : : "%<present%>");
20192 : 5 : parens.skip_until_found_close (parser);
20193 : 5 : return list;
20194 : : }
20195 : : }
20196 : :
20197 : 1689 : if (c_parser_next_token_is (parser, CPP_NAME)
20198 : 1689 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20199 : : {
20200 : 1373 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20201 : 1373 : int always_present_modifier = always_modifier && present_modifier;
20202 : :
20203 : 1373 : if (strcmp ("alloc", p) == 0)
20204 : 128 : kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
20205 : 1245 : else if (strcmp ("to", p) == 0)
20206 : 831 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
20207 : 428 : : present_modifier ? GOMP_MAP_PRESENT_TO
20208 : 420 : : always_modifier ? GOMP_MAP_ALWAYS_TO
20209 : : : GOMP_MAP_TO);
20210 : 814 : else if (strcmp ("from", p) == 0)
20211 : 944 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
20212 : 474 : : present_modifier ? GOMP_MAP_PRESENT_FROM
20213 : 471 : : always_modifier ? GOMP_MAP_ALWAYS_FROM
20214 : : : GOMP_MAP_FROM);
20215 : 335 : else if (strcmp ("tofrom", p) == 0)
20216 : 544 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
20217 : 280 : : present_modifier ? GOMP_MAP_PRESENT_TOFROM
20218 : 274 : : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
20219 : : : GOMP_MAP_TOFROM);
20220 : 50 : else if (strcmp ("release", p) == 0)
20221 : : kind = GOMP_MAP_RELEASE;
20222 : 15 : else if (strcmp ("delete", p) == 0)
20223 : : kind = GOMP_MAP_DELETE;
20224 : : else
20225 : : {
20226 : 0 : c_parser_error (parser, "invalid map kind");
20227 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20228 : : "expected %<)%>");
20229 : 0 : return list;
20230 : : }
20231 : 1373 : c_parser_consume_token (parser);
20232 : 1373 : c_parser_consume_token (parser);
20233 : : }
20234 : :
20235 : 1689 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
20236 : : true);
20237 : :
20238 : 1689 : tree last_new = NULL_TREE;
20239 : :
20240 : 5468 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20241 : : {
20242 : 2090 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
20243 : 2090 : last_new = c;
20244 : : }
20245 : :
20246 : 1689 : if (mapper_name)
20247 : : {
20248 : 5 : tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20249 : 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
20250 : 5 : OMP_CLAUSE_DECL (name) = mapper_name;
20251 : 5 : OMP_CLAUSE_CHAIN (name) = nl;
20252 : 5 : nl = name;
20253 : :
20254 : 5 : gcc_assert (last_new);
20255 : :
20256 : 5 : name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20257 : 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
20258 : 5 : OMP_CLAUSE_DECL (name) = null_pointer_node;
20259 : 5 : OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
20260 : 5 : OMP_CLAUSE_CHAIN (last_new) = name;
20261 : : }
20262 : :
20263 : 1689 : parens.skip_until_found_close (parser);
20264 : 1689 : return nl;
20265 : : }
20266 : :
20267 : : /* OpenMP 4.0:
20268 : : device ( expression )
20269 : :
20270 : : OpenMP 5.0:
20271 : : device ( [device-modifier :] integer-expression )
20272 : :
20273 : : device-modifier:
20274 : : ancestor | device_num */
20275 : :
20276 : : static tree
20277 : 367 : c_parser_omp_clause_device (c_parser *parser, tree list)
20278 : : {
20279 : 367 : location_t clause_loc = c_parser_peek_token (parser)->location;
20280 : 367 : location_t expr_loc;
20281 : 367 : c_expr expr;
20282 : 367 : tree c, t;
20283 : 367 : bool ancestor = false;
20284 : :
20285 : 367 : matching_parens parens;
20286 : 367 : if (!parens.require_open (parser))
20287 : : return list;
20288 : :
20289 : 367 : if (c_parser_next_token_is (parser, CPP_NAME)
20290 : 367 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20291 : : {
20292 : 50 : c_token *tok = c_parser_peek_token (parser);
20293 : 50 : const char *p = IDENTIFIER_POINTER (tok->value);
20294 : 50 : if (strcmp ("ancestor", p) == 0)
20295 : : {
20296 : : /* A requires directive with the reverse_offload clause must be
20297 : : specified. */
20298 : 25 : if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
20299 : : {
20300 : 1 : error_at (tok->location, "%<ancestor%> device modifier not "
20301 : : "preceded by %<requires%> directive "
20302 : : "with %<reverse_offload%> clause");
20303 : 1 : parens.skip_until_found_close (parser);
20304 : 1 : return list;
20305 : : }
20306 : : ancestor = true;
20307 : : }
20308 : 25 : else if (strcmp ("device_num", p) == 0)
20309 : : ;
20310 : : else
20311 : : {
20312 : 1 : error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
20313 : 1 : parens.skip_until_found_close (parser);
20314 : 1 : return list;
20315 : : }
20316 : 48 : c_parser_consume_token (parser);
20317 : 48 : c_parser_consume_token (parser);
20318 : : }
20319 : :
20320 : 365 : expr_loc = c_parser_peek_token (parser)->location;
20321 : 365 : expr = c_parser_expr_no_commas (parser, NULL);
20322 : 365 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20323 : 365 : t = expr.value;
20324 : 365 : t = c_fully_fold (t, false, NULL);
20325 : :
20326 : 365 : parens.skip_until_found_close (parser);
20327 : :
20328 : 365 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
20329 : : {
20330 : 2 : c_parser_error (parser, "expected integer expression");
20331 : 2 : return list;
20332 : : }
20333 : 363 : if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
20334 : : {
20335 : 1 : error_at (expr_loc, "the %<device%> clause expression must evaluate to "
20336 : : "%<1%>");
20337 : 1 : return list;
20338 : : }
20339 : :
20340 : 362 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
20341 : :
20342 : 362 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
20343 : :
20344 : 362 : OMP_CLAUSE_DEVICE_ID (c) = t;
20345 : 362 : OMP_CLAUSE_CHAIN (c) = list;
20346 : 362 : OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
20347 : :
20348 : 362 : list = c;
20349 : 362 : return list;
20350 : : }
20351 : :
20352 : : /* OpenMP 4.0:
20353 : : dist_schedule ( static )
20354 : : dist_schedule ( static , expression ) */
20355 : :
20356 : : static tree
20357 : 1582 : c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
20358 : : {
20359 : 1582 : tree c, t = NULL_TREE;
20360 : 1582 : location_t loc = c_parser_peek_token (parser)->location;
20361 : :
20362 : 1582 : matching_parens parens;
20363 : 1582 : if (!parens.require_open (parser))
20364 : : return list;
20365 : :
20366 : 1582 : if (!c_parser_next_token_is_keyword (parser, RID_STATIC))
20367 : : {
20368 : 0 : c_parser_error (parser, "invalid dist_schedule kind");
20369 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20370 : : "expected %<)%>");
20371 : 0 : return list;
20372 : : }
20373 : :
20374 : 1582 : c_parser_consume_token (parser);
20375 : 1582 : if (c_parser_next_token_is (parser, CPP_COMMA))
20376 : : {
20377 : 1575 : c_parser_consume_token (parser);
20378 : :
20379 : 1575 : location_t expr_loc = c_parser_peek_token (parser)->location;
20380 : 1575 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20381 : 1575 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20382 : 1575 : t = expr.value;
20383 : 1575 : t = c_fully_fold (t, false, NULL);
20384 : 1575 : parens.skip_until_found_close (parser);
20385 : : }
20386 : : else
20387 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20388 : : "expected %<,%> or %<)%>");
20389 : :
20390 : : /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
20391 : : "dist_schedule"); */
20392 : 1582 : if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE))
20393 : 2 : warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
20394 : 1582 : if (t == error_mark_node)
20395 : : return list;
20396 : :
20397 : 1582 : c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
20398 : 1582 : OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
20399 : 1582 : OMP_CLAUSE_CHAIN (c) = list;
20400 : 1582 : return c;
20401 : : }
20402 : :
20403 : : /* OpenMP 4.0:
20404 : : proc_bind ( proc-bind-kind )
20405 : :
20406 : : proc-bind-kind:
20407 : : primary | master | close | spread
20408 : : where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
20409 : :
20410 : : static tree
20411 : 194 : c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
20412 : : {
20413 : 194 : location_t clause_loc = c_parser_peek_token (parser)->location;
20414 : 194 : enum omp_clause_proc_bind_kind kind;
20415 : 194 : tree c;
20416 : :
20417 : 194 : matching_parens parens;
20418 : 194 : if (!parens.require_open (parser))
20419 : : return list;
20420 : :
20421 : 194 : if (c_parser_next_token_is (parser, CPP_NAME))
20422 : : {
20423 : 194 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20424 : 194 : if (strcmp ("primary", p) == 0)
20425 : : kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
20426 : 193 : else if (strcmp ("master", p) == 0)
20427 : : kind = OMP_CLAUSE_PROC_BIND_MASTER;
20428 : 177 : else if (strcmp ("close", p) == 0)
20429 : : kind = OMP_CLAUSE_PROC_BIND_CLOSE;
20430 : 165 : else if (strcmp ("spread", p) == 0)
20431 : : kind = OMP_CLAUSE_PROC_BIND_SPREAD;
20432 : : else
20433 : 0 : goto invalid_kind;
20434 : : }
20435 : : else
20436 : 0 : goto invalid_kind;
20437 : :
20438 : 194 : check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind");
20439 : 194 : c_parser_consume_token (parser);
20440 : 194 : parens.skip_until_found_close (parser);
20441 : 194 : c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
20442 : 194 : OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
20443 : 194 : OMP_CLAUSE_CHAIN (c) = list;
20444 : 194 : return c;
20445 : :
20446 : 0 : invalid_kind:
20447 : 0 : c_parser_error (parser, "invalid proc_bind kind");
20448 : 0 : parens.skip_until_found_close (parser);
20449 : 0 : return list;
20450 : : }
20451 : :
20452 : : /* OpenMP 5.0:
20453 : : device_type ( host | nohost | any ) */
20454 : :
20455 : : static tree
20456 : 42 : c_parser_omp_clause_device_type (c_parser *parser, tree list)
20457 : : {
20458 : 42 : location_t clause_loc = c_parser_peek_token (parser)->location;
20459 : 42 : enum omp_clause_device_type_kind kind;
20460 : 42 : tree c;
20461 : :
20462 : 42 : matching_parens parens;
20463 : 42 : if (!parens.require_open (parser))
20464 : : return list;
20465 : :
20466 : 42 : if (c_parser_next_token_is (parser, CPP_NAME))
20467 : : {
20468 : 42 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20469 : 42 : if (strcmp ("host", p) == 0)
20470 : : kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
20471 : 26 : else if (strcmp ("nohost", p) == 0)
20472 : : kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
20473 : 17 : else if (strcmp ("any", p) == 0)
20474 : : kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
20475 : : else
20476 : 0 : goto invalid_kind;
20477 : : }
20478 : : else
20479 : 0 : goto invalid_kind;
20480 : :
20481 : 42 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
20482 : : "device_type");
20483 : 42 : c_parser_consume_token (parser);
20484 : 42 : parens.skip_until_found_close (parser);
20485 : 42 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
20486 : 42 : OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
20487 : 42 : OMP_CLAUSE_CHAIN (c) = list;
20488 : 42 : return c;
20489 : :
20490 : 0 : invalid_kind:
20491 : 0 : c_parser_error (parser, "expected %<host%>, %<nohost%> or %<any%>");
20492 : 0 : parens.skip_until_found_close (parser);
20493 : 0 : return list;
20494 : : }
20495 : :
20496 : : /* OpenMP 4.0:
20497 : : from ( variable-list )
20498 : : to ( variable-list )
20499 : :
20500 : : OpenMP 5.1:
20501 : : from ( [present :] variable-list )
20502 : : to ( [present :] variable-list ) */
20503 : :
20504 : : static tree
20505 : 2831 : c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
20506 : : tree list)
20507 : : {
20508 : 2831 : location_t loc = c_parser_peek_token (parser)->location;
20509 : 2831 : matching_parens parens;
20510 : 2831 : if (!parens.require_open (parser))
20511 : : return list;
20512 : :
20513 : 2831 : bool present = false;
20514 : 2831 : c_token *token = c_parser_peek_token (parser);
20515 : :
20516 : 2831 : if (token->type == CPP_NAME
20517 : 2831 : && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
20518 : 2836 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20519 : : {
20520 : 5 : present = true;
20521 : 5 : c_parser_consume_token (parser);
20522 : 5 : c_parser_consume_token (parser);
20523 : : }
20524 : :
20525 : 2831 : tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
20526 : 2831 : parens.skip_until_found_close (parser);
20527 : :
20528 : 2831 : if (present)
20529 : 10 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20530 : 5 : OMP_CLAUSE_MOTION_PRESENT (c) = 1;
20531 : :
20532 : : return nl;
20533 : : }
20534 : :
20535 : : /* OpenMP 4.0:
20536 : : uniform ( variable-list ) */
20537 : :
20538 : : static tree
20539 : 115 : c_parser_omp_clause_uniform (c_parser *parser, tree list)
20540 : : {
20541 : : /* The clauses location. */
20542 : 115 : location_t loc = c_parser_peek_token (parser)->location;
20543 : :
20544 : 115 : matching_parens parens;
20545 : 115 : if (parens.require_open (parser))
20546 : : {
20547 : 115 : list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
20548 : : list);
20549 : 115 : parens.skip_until_found_close (parser);
20550 : : }
20551 : 115 : return list;
20552 : : }
20553 : :
20554 : : /* OpenMP 5.1
20555 : : full */
20556 : :
20557 : : static tree
20558 : 69 : c_parser_omp_clause_full (c_parser *parser, tree list)
20559 : : {
20560 : 69 : check_no_duplicate_clause (list, OMP_CLAUSE_FULL, "full");
20561 : :
20562 : 69 : location_t loc = c_parser_peek_token (parser)->location;
20563 : 69 : tree c = build_omp_clause (loc, OMP_CLAUSE_FULL);
20564 : 69 : OMP_CLAUSE_CHAIN (c) = list;
20565 : 69 : return c;
20566 : : }
20567 : :
20568 : : /* OpenMP 5.1
20569 : : partial ( constant-expression ) */
20570 : :
20571 : : static tree
20572 : 230 : c_parser_omp_clause_partial (c_parser *parser, tree list)
20573 : : {
20574 : 230 : tree num = NULL_TREE;
20575 : 230 : location_t loc = c_parser_peek_token (parser)->location;
20576 : :
20577 : 230 : check_no_duplicate_clause (list, OMP_CLAUSE_PARTIAL, "partial");
20578 : :
20579 : 230 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
20580 : : {
20581 : 173 : matching_parens parens;
20582 : 173 : parens.consume_open (parser);
20583 : 173 : num = c_parser_expr_no_commas (parser, NULL).value;
20584 : 173 : parens.skip_until_found_close (parser);
20585 : :
20586 : 173 : if (num == error_mark_node)
20587 : 7 : return list;
20588 : :
20589 : 171 : mark_exp_read (num);
20590 : 171 : num = c_fully_fold (num, false, NULL);
20591 : 171 : HOST_WIDE_INT n;
20592 : 342 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
20593 : 170 : || !tree_fits_shwi_p (num)
20594 : 168 : || (n = tree_to_shwi (num)) <= 0
20595 : 337 : || (int) n != n)
20596 : : {
20597 : 5 : error_at (loc, "%<partial%> argument needs positive constant "
20598 : : "integer expression");
20599 : 5 : return list;
20600 : : }
20601 : : }
20602 : :
20603 : 223 : tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL);
20604 : 223 : OMP_CLAUSE_PARTIAL_EXPR (c) = num;
20605 : 223 : OMP_CLAUSE_CHAIN (c) = list;
20606 : 223 : return c;
20607 : : }
20608 : :
20609 : : /* OpenMP 5.1
20610 : : novariants ( scalar-expression ) */
20611 : :
20612 : : static tree
20613 : 21 : c_parser_omp_clause_novariants (c_parser *parser, tree list)
20614 : : {
20615 : 21 : matching_parens parens;
20616 : 21 : if (!parens.require_open (parser))
20617 : : return list;
20618 : :
20619 : 21 : location_t loc = c_parser_peek_token (parser)->location;
20620 : 21 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20621 : 21 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20622 : 21 : t = c_objc_common_truthvalue_conversion (loc, t);
20623 : 21 : t = c_fully_fold (t, false, NULL);
20624 : 21 : parens.skip_until_found_close (parser);
20625 : :
20626 : 21 : check_no_duplicate_clause (list, OMP_CLAUSE_NOVARIANTS, "novariants");
20627 : :
20628 : 21 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
20629 : 21 : OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
20630 : 21 : OMP_CLAUSE_CHAIN (c) = list;
20631 : 21 : list = c;
20632 : :
20633 : 21 : return list;
20634 : : }
20635 : :
20636 : : /* OpenMP 5.1
20637 : : nocontext ( scalar-expression ) */
20638 : :
20639 : : static tree
20640 : 23 : c_parser_omp_clause_nocontext (c_parser *parser, tree list)
20641 : : {
20642 : 23 : matching_parens parens;
20643 : 23 : if (!parens.require_open (parser))
20644 : : return list;
20645 : :
20646 : 23 : location_t loc = c_parser_peek_token (parser)->location;
20647 : 23 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20648 : 23 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20649 : 23 : t = c_objc_common_truthvalue_conversion (loc, t);
20650 : 23 : t = c_fully_fold (t, false, NULL);
20651 : 23 : parens.skip_until_found_close (parser);
20652 : :
20653 : 23 : check_no_duplicate_clause (list, OMP_CLAUSE_NOCONTEXT, "nocontext");
20654 : :
20655 : 23 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
20656 : 23 : OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
20657 : 23 : OMP_CLAUSE_CHAIN (c) = list;
20658 : 23 : list = c;
20659 : :
20660 : 23 : return list;
20661 : : }
20662 : :
20663 : : /* OpenMP 5.0:
20664 : : detach ( event-handle ) */
20665 : :
20666 : : static tree
20667 : 34 : c_parser_omp_clause_detach (c_parser *parser, tree list)
20668 : : {
20669 : 34 : matching_parens parens;
20670 : 34 : location_t clause_loc = c_parser_peek_token (parser)->location;
20671 : :
20672 : 34 : if (!parens.require_open (parser))
20673 : : return list;
20674 : :
20675 : 34 : if (c_parser_next_token_is_not (parser, CPP_NAME)
20676 : 34 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
20677 : : {
20678 : 1 : c_parser_error (parser, "expected identifier");
20679 : 1 : parens.skip_until_found_close (parser);
20680 : 1 : return list;
20681 : : }
20682 : :
20683 : 33 : tree t = lookup_name (c_parser_peek_token (parser)->value);
20684 : 33 : if (t == NULL_TREE)
20685 : : {
20686 : 0 : undeclared_variable (c_parser_peek_token (parser)->location,
20687 : 0 : c_parser_peek_token (parser)->value);
20688 : 0 : parens.skip_until_found_close (parser);
20689 : 0 : return list;
20690 : : }
20691 : 33 : c_parser_consume_token (parser);
20692 : :
20693 : 33 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
20694 : 33 : if (!INTEGRAL_TYPE_P (type)
20695 : : || TREE_CODE (type) != ENUMERAL_TYPE
20696 : 33 : || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
20697 : : {
20698 : 1 : error_at (clause_loc, "%<detach%> clause event handle "
20699 : : "has type %qT rather than "
20700 : : "%<omp_event_handle_t%>",
20701 : : type);
20702 : 1 : parens.skip_until_found_close (parser);
20703 : 1 : return list;
20704 : : }
20705 : :
20706 : 32 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
20707 : 32 : OMP_CLAUSE_DECL (u) = t;
20708 : 32 : OMP_CLAUSE_CHAIN (u) = list;
20709 : 32 : parens.skip_until_found_close (parser);
20710 : 32 : return u;
20711 : : }
20712 : :
20713 : : /* OpenMP 5.0:
20714 : : destroy ( variable-list ) */
20715 : :
20716 : : static tree
20717 : 41 : c_parser_omp_clause_destroy (c_parser *parser, tree list)
20718 : : {
20719 : 41 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_DESTROY, list);
20720 : 86 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20721 : 45 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
20722 : 41 : return nl;
20723 : : }
20724 : :
20725 : : /* OpenMP 5.1:
20726 : : prefer_type ( const-int-expr-or-string-literal-list )
20727 : :
20728 : : OpenMP 6.0:
20729 : : prefer_type ( { preference-selector-list }, { ... } )
20730 : :
20731 : : with preference-selector being:
20732 : : fr ( identifier-or-string-literal-list )
20733 : : attr ( string-list )
20734 : :
20735 : : Data format:
20736 : : For the foreign runtime identifiers, string values are converted to
20737 : : their integer value; unknown string or integer values are set to
20738 : : GOMP_INTEROP_IFR_KNOWN.
20739 : :
20740 : : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
20741 : : (b) for any 'fr', its integer value.
20742 : : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
20743 : : (c) GOMP_INTEROP_IFR_SEPARATOR
20744 : : (d) list of \0-terminated non-empty strings for 'attr'
20745 : : (e) '\0'
20746 : : Tailing '\0'. */
20747 : :
20748 : : static tree
20749 : 125 : c_parser_omp_modifier_prefer_type (c_parser *parser)
20750 : : {
20751 : 125 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
20752 : 2 : return error_mark_node;
20753 : :
20754 : 123 : std::string str;
20755 : :
20756 : : /* Old Format: const-int-expr-or-string-literal-list */
20757 : 123 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
20758 : 240 : while (true)
20759 : : {
20760 : 150 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20761 : 150 : if (c_parser_next_token_is (parser, CPP_STRING))
20762 : : {
20763 : 117 : c_expr cval = c_parser_string_literal (parser, false, false);
20764 : 117 : if (cval.value == error_mark_node)
20765 : 1 : return error_mark_node;
20766 : 117 : if ((size_t) TREE_STRING_LENGTH (cval.value)
20767 : 117 : != strlen (TREE_STRING_POINTER (cval.value)) + 1)
20768 : : {
20769 : 1 : error_at (cval.get_location (), "string literal must "
20770 : : "not contain %<\\0%>");
20771 : 1 : parser->error = true;
20772 : 1 : return error_mark_node;
20773 : : }
20774 : :
20775 : 116 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (cval.value));
20776 : 116 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
20777 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
20778 : : "unknown foreign runtime identifier %qs",
20779 : 3 : TREE_STRING_POINTER (cval.value));
20780 : 116 : str += c;
20781 : : }
20782 : : else
20783 : : {
20784 : 33 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
20785 : 33 : tree value = c_fully_fold (cval.value, false, NULL);
20786 : 64 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
20787 : 61 : && TREE_CODE (value) != INTEGER_CST)
20788 : 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
20789 : : false, true).value;
20790 : 33 : if (TREE_CODE (value) != INTEGER_CST
20791 : 28 : || !tree_fits_shwi_p (value))
20792 : : {
20793 : 5 : c_parser_error (parser, "expected string literal or constant "
20794 : : "integer expression");
20795 : 5 : return error_mark_node;
20796 : : }
20797 : 28 : HOST_WIDE_INT n = tree_to_shwi (value);
20798 : 28 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
20799 : : {
20800 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
20801 : : "unknown foreign runtime identifier %qwd", n);
20802 : 3 : n = GOMP_INTEROP_IFR_UNKNOWN;
20803 : : }
20804 : 28 : str += (char) n;
20805 : : }
20806 : 144 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20807 : 144 : str += '\0';
20808 : 144 : if (c_parser_next_token_is (parser, CPP_COMMA))
20809 : : {
20810 : 90 : c_parser_consume_token (parser);
20811 : 90 : continue;
20812 : : }
20813 : 54 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
20814 : : "expected %<,%> or %<)%>"))
20815 : 0 : return error_mark_node;
20816 : 54 : str += '\0';
20817 : 54 : tree res = build_string (str.length (), str.data ());
20818 : 54 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
20819 : 54 : str.length ());
20820 : 54 : return res;
20821 : 90 : }
20822 : :
20823 : : /* New format. */
20824 : 63 : std::string str2;
20825 : 128 : while (true)
20826 : : {
20827 : 128 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
20828 : 1 : return error_mark_node;
20829 : 127 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20830 : 127 : str2.clear ();
20831 : 127 : bool has_fr = false;
20832 : 205 : while (true)
20833 : : {
20834 : 166 : c_token *tok = c_parser_peek_token (parser);
20835 : 166 : if (tok->type != CPP_NAME
20836 : 166 : || (strcmp("fr", IDENTIFIER_POINTER (tok->value)) != 0
20837 : 63 : && strcmp("attr", IDENTIFIER_POINTER (tok->value)) != 0))
20838 : : {
20839 : 0 : c_parser_error (parser, "expected %<fr%> or %<attr%> preference "
20840 : : "selector");
20841 : 0 : return error_mark_node;
20842 : : }
20843 : 166 : c_parser_consume_token (parser);
20844 : 166 : bool is_fr = IDENTIFIER_POINTER (tok->value)[0] == 'f';
20845 : 166 : if (is_fr && has_fr)
20846 : : {
20847 : 1 : c_parser_error (parser, "duplicated %<fr%> preference selector");
20848 : 1 : return error_mark_node;
20849 : : }
20850 : 165 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
20851 : 0 : return error_mark_node;
20852 : 175 : while (true)
20853 : : {
20854 : 170 : if (c_parser_next_token_is (parser, CPP_STRING))
20855 : : {
20856 : 133 : c_expr cval = c_parser_string_literal (parser, false, false);
20857 : 133 : tree value = cval.value;
20858 : 133 : if (value == error_mark_node)
20859 : 6 : return error_mark_node;
20860 : 133 : if ((size_t) TREE_STRING_LENGTH (value)
20861 : 133 : != strlen (TREE_STRING_POINTER (value)) + 1)
20862 : : {
20863 : 2 : error_at (cval.get_location (), "string literal must "
20864 : : "not contain %<\\0%>");
20865 : 2 : parser->error = true;
20866 : 2 : return error_mark_node;
20867 : : }
20868 : 131 : if (!is_fr)
20869 : : {
20870 : 67 : if (!startswith (TREE_STRING_POINTER (value), "ompx_"))
20871 : : {
20872 : 1 : error_at (cval.get_location (),
20873 : : "%<attr%> string literal must start with "
20874 : : "%<ompx_%>");
20875 : 1 : parser->error = true;
20876 : 1 : return error_mark_node;
20877 : : }
20878 : 66 : if (strchr (TREE_STRING_POINTER (value), ','))
20879 : : {
20880 : 2 : error_at (cval.get_location (),
20881 : : "%<attr%> string literal must not contain "
20882 : : "a comma");
20883 : 2 : parser->error = true;
20884 : 2 : return error_mark_node;
20885 : : }
20886 : 64 : str2 += TREE_STRING_POINTER (value);
20887 : 64 : str2 += '\0';
20888 : : }
20889 : : else
20890 : : {
20891 : 64 : if (*TREE_STRING_POINTER (value) == '\0')
20892 : : {
20893 : 1 : c_parser_error (parser, "non-empty string literal expected");
20894 : 1 : return error_mark_node;
20895 : : }
20896 : 63 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (value));
20897 : 63 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
20898 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
20899 : : "unknown foreign runtime identifier %qs",
20900 : 3 : TREE_STRING_POINTER (value));
20901 : 63 : str += c;
20902 : 63 : has_fr = true;
20903 : : }
20904 : : }
20905 : 37 : else if (!is_fr)
20906 : : {
20907 : 1 : c_parser_error (parser, "expected string literal");
20908 : 1 : return error_mark_node;
20909 : : }
20910 : : else
20911 : : {
20912 : 36 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
20913 : 36 : tree value = c_fully_fold (cval.value, false, NULL);
20914 : 70 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
20915 : 68 : && TREE_CODE (value) != INTEGER_CST)
20916 : 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
20917 : : false, true).value;
20918 : :
20919 : 36 : if (TREE_CODE (value) != INTEGER_CST
20920 : 32 : || !tree_fits_shwi_p (value))
20921 : : {
20922 : 4 : c_parser_error (parser, "expected string literal or "
20923 : : "constant integer expression");
20924 : 4 : return error_mark_node;
20925 : : }
20926 : 32 : HOST_WIDE_INT n = tree_to_shwi (value);
20927 : 32 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
20928 : : {
20929 : 0 : warning_at (cval.get_location (), OPT_Wopenmp,
20930 : : "unknown foreign runtime identifier %qwd", n);
20931 : 0 : n = GOMP_INTEROP_IFR_UNKNOWN;
20932 : : }
20933 : 32 : str += (char) n;
20934 : 32 : has_fr = true;
20935 : : }
20936 : 164 : if (!is_fr
20937 : 223 : && c_parser_next_token_is (parser, CPP_COMMA))
20938 : : {
20939 : 5 : c_parser_consume_token (parser);
20940 : 5 : continue;
20941 : : }
20942 : 213 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
20943 : : is_fr ? G_("expected %<)%>")
20944 : : : G_("expected %<)%> or %<,%>")))
20945 : 4 : return error_mark_node;
20946 : 150 : break;
20947 : 5 : }
20948 : 150 : if (c_parser_next_token_is (parser, CPP_COMMA))
20949 : : {
20950 : 39 : c_parser_consume_token (parser);
20951 : 39 : continue;
20952 : : }
20953 : 111 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
20954 : : break;
20955 : 2 : c_parser_error (parser, "expected %<,%> or %<}%>");
20956 : 2 : return error_mark_node;
20957 : 39 : }
20958 : 109 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20959 : 109 : str += str2;
20960 : 109 : str += '\0';
20961 : 109 : c_parser_consume_token (parser);
20962 : 109 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
20963 : : break;
20964 : 66 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
20965 : 1 : return error_mark_node;
20966 : : }
20967 : 43 : c_parser_consume_token (parser);
20968 : 43 : str += '\0';
20969 : 43 : tree res = build_string (str.length (), str.data ());
20970 : 43 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
20971 : 43 : str.length ());
20972 : 43 : return res;
20973 : 186 : }
20974 : :
20975 : : /* OpenMP 5.1
20976 : : modifiers of the 'init' clause, used by the 'init' and the
20977 : : 'append_args' clauses.
20978 : :
20979 : : Modifiers:
20980 : : target
20981 : : targetsync
20982 : : prefer_type (preference-specification)
20983 : :
20984 : : Returns 'false' if an error has been issued. */
20985 : :
20986 : : static bool
20987 : 233 : c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target,
20988 : : bool *targetsync, tree *prefer_type_tree)
20989 : : {
20990 : 233 : *target = false;
20991 : 233 : *targetsync = false;
20992 : 233 : *prefer_type_tree = NULL_TREE;
20993 : :
20994 : 537 : do
20995 : : {
20996 : 385 : c_token *tok = c_parser_peek_token (parser);
20997 : 385 : if (tok->type != CPP_NAME)
20998 : 1 : goto fail;
20999 : 384 : const char *p = IDENTIFIER_POINTER (tok->value);
21000 : 384 : if (strcmp ("targetsync", p) == 0)
21001 : : {
21002 : 104 : if (*targetsync)
21003 : 1 : error_at (tok->location, "duplicate %<targetsync%> modifier");
21004 : 104 : *targetsync = true;
21005 : 104 : c_parser_consume_token (parser);
21006 : : }
21007 : 280 : else if (strcmp ("target", p) == 0)
21008 : : {
21009 : 147 : if (*target)
21010 : 3 : error_at (tok->location, "duplicate %<target%> modifier");
21011 : 147 : *target = true;
21012 : 147 : c_parser_consume_token (parser);
21013 : : }
21014 : 133 : else if (strcmp ("prefer_type", p) == 0)
21015 : : {
21016 : 125 : if (*prefer_type_tree != NULL_TREE)
21017 : 1 : error_at (tok->location, "duplicate %<prefer_type%> modifier");
21018 : 125 : c_parser_consume_token (parser);
21019 : 125 : *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser);
21020 : 125 : if (*prefer_type_tree == error_mark_node)
21021 : : return false;
21022 : : }
21023 : : else
21024 : 8 : goto fail;
21025 : 348 : tok = c_parser_peek_token (parser);
21026 : 348 : if (tok->type == CPP_COMMA)
21027 : : {
21028 : 152 : c_parser_consume_token (parser);
21029 : 152 : continue;
21030 : : }
21031 : : /* Unknown token - either done or an error; handle it in the caller. */
21032 : : return true;
21033 : 152 : }
21034 : : while (true);
21035 : :
21036 : 9 : fail:
21037 : 9 : c_parser_error (parser,
21038 : : "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
21039 : 9 : return false;
21040 : : }
21041 : :
21042 : : /* OpenMP 5.1:
21043 : : init ( [init-modifier-list : ] variable-list )
21044 : :
21045 : : Modifiers:
21046 : : target
21047 : : targetsync
21048 : : prefer_type (preference-specification) */
21049 : :
21050 : : static tree
21051 : 167 : c_parser_omp_clause_init (c_parser *parser, tree list)
21052 : : {
21053 : 167 : location_t loc = c_parser_peek_token (parser)->location;
21054 : :
21055 : 167 : matching_parens parens;
21056 : 167 : if (!parens.require_open (parser))
21057 : : return list;
21058 : :
21059 : 167 : bool target = false;
21060 : 167 : bool targetsync = false;
21061 : 167 : tree prefer_type_tree = NULL_TREE;
21062 : :
21063 : 167 : if (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
21064 : : &prefer_type_tree)
21065 : 167 : || !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
21066 : : {
21067 : 39 : if (prefer_type_tree != error_mark_node)
21068 : 11 : parens.skip_until_found_close (parser);
21069 : 39 : return list;
21070 : : }
21071 : :
21072 : 128 : if (!target && !targetsync)
21073 : 2 : error_at (loc,
21074 : : "missing required %<target%> and/or %<targetsync%> modifier");
21075 : :
21076 : 128 : tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list,
21077 : : false);
21078 : 128 : parens.skip_until_found_close (parser);
21079 : :
21080 : 280 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21081 : : {
21082 : 152 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21083 : 152 : if (target)
21084 : 90 : OMP_CLAUSE_INIT_TARGET (c) = 1;
21085 : 152 : if (targetsync)
21086 : 81 : OMP_CLAUSE_INIT_TARGETSYNC (c) = 1;
21087 : 152 : if (prefer_type_tree)
21088 : 73 : OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree;
21089 : : }
21090 : : return nl;
21091 : : }
21092 : :
21093 : : /* OpenMP 5.0:
21094 : : use ( variable-list ) */
21095 : :
21096 : : static tree
21097 : 43 : c_parser_omp_clause_use (c_parser *parser, tree list)
21098 : : {
21099 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE, list);
21100 : : }
21101 : :
21102 : : /* OpenMP 6.0:
21103 : : interop ( variable-list ) */
21104 : :
21105 : : static tree
21106 : 42 : c_parser_omp_clause_interop (c_parser *parser, tree list)
21107 : : {
21108 : 42 : check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop");
21109 : 42 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list);
21110 : 100 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21111 : : {
21112 : 58 : TREE_USED (OMP_CLAUSE_DECL (c)) = 1;
21113 : 58 : DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1;
21114 : : }
21115 : 42 : return nl;
21116 : : }
21117 : :
21118 : : /* Parse all OpenACC clauses. The set clauses allowed by the directive
21119 : : is a bitmask in MASK. Return the list of clauses found. */
21120 : :
21121 : : static tree
21122 : 5346 : c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
21123 : : const char *where, bool finish_p = true,
21124 : : bool target_p = false)
21125 : : {
21126 : 5346 : tree clauses = NULL;
21127 : 5346 : bool first = true;
21128 : :
21129 : 12056 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
21130 : : {
21131 : 6756 : location_t here;
21132 : 6756 : pragma_omp_clause c_kind;
21133 : 6756 : const char *c_name;
21134 : 6756 : tree prev = clauses;
21135 : :
21136 : 9363 : if (!first && c_parser_next_token_is (parser, CPP_COMMA))
21137 : 11 : c_parser_consume_token (parser);
21138 : :
21139 : 6756 : here = c_parser_peek_token (parser)->location;
21140 : 6756 : c_kind = c_parser_omp_clause_name (parser);
21141 : :
21142 : 6756 : switch (c_kind)
21143 : : {
21144 : 237 : case PRAGMA_OACC_CLAUSE_ASYNC:
21145 : 237 : clauses = c_parser_oacc_clause_async (parser, clauses);
21146 : 237 : c_name = "async";
21147 : 237 : break;
21148 : 125 : case PRAGMA_OACC_CLAUSE_AUTO:
21149 : 125 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
21150 : : clauses);
21151 : 125 : c_name = "auto";
21152 : 125 : break;
21153 : 27 : case PRAGMA_OACC_CLAUSE_ATTACH:
21154 : 27 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21155 : 27 : c_name = "attach";
21156 : 27 : break;
21157 : 59 : case PRAGMA_OACC_CLAUSE_COLLAPSE:
21158 : 59 : clauses = c_parser_omp_clause_collapse (parser, clauses);
21159 : 59 : c_name = "collapse";
21160 : 59 : break;
21161 : 806 : case PRAGMA_OACC_CLAUSE_COPY:
21162 : 806 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21163 : 806 : c_name = "copy";
21164 : 806 : break;
21165 : 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
21166 : 359 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21167 : 359 : c_name = "copyin";
21168 : 359 : break;
21169 : 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
21170 : 390 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21171 : 390 : c_name = "copyout";
21172 : 390 : break;
21173 : 94 : case PRAGMA_OACC_CLAUSE_CREATE:
21174 : 94 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21175 : 94 : c_name = "create";
21176 : 94 : break;
21177 : 68 : case PRAGMA_OACC_CLAUSE_DELETE:
21178 : 68 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21179 : 68 : c_name = "delete";
21180 : 68 : break;
21181 : 88 : case PRAGMA_OMP_CLAUSE_DEFAULT:
21182 : 88 : clauses = c_parser_omp_clause_default (parser, clauses, true);
21183 : 88 : c_name = "default";
21184 : 88 : break;
21185 : 20 : case PRAGMA_OACC_CLAUSE_DETACH:
21186 : 20 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21187 : 20 : c_name = "detach";
21188 : 20 : break;
21189 : 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
21190 : 36 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21191 : 36 : c_name = "device";
21192 : 36 : break;
21193 : 57 : case PRAGMA_OACC_CLAUSE_DEVICEPTR:
21194 : 57 : clauses = c_parser_oacc_data_clause_deviceptr (parser, clauses);
21195 : 57 : c_name = "deviceptr";
21196 : 57 : break;
21197 : 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
21198 : 16 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21199 : 16 : c_name = "device_resident";
21200 : 16 : break;
21201 : 12 : case PRAGMA_OACC_CLAUSE_FINALIZE:
21202 : 12 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
21203 : : clauses);
21204 : 12 : c_name = "finalize";
21205 : 12 : break;
21206 : 113 : case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
21207 : 113 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
21208 : 113 : c_name = "firstprivate";
21209 : 113 : break;
21210 : 589 : case PRAGMA_OACC_CLAUSE_GANG:
21211 : 589 : c_name = "gang";
21212 : 589 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
21213 : : c_name, clauses);
21214 : 589 : break;
21215 : 41 : case PRAGMA_OACC_CLAUSE_HOST:
21216 : 41 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21217 : 41 : c_name = "host";
21218 : 41 : break;
21219 : 99 : case PRAGMA_OACC_CLAUSE_IF:
21220 : 99 : clauses = c_parser_omp_clause_if (parser, clauses, false);
21221 : 99 : c_name = "if";
21222 : 99 : break;
21223 : 19 : case PRAGMA_OACC_CLAUSE_IF_PRESENT:
21224 : 19 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
21225 : : clauses);
21226 : 19 : c_name = "if_present";
21227 : 19 : break;
21228 : 45 : case PRAGMA_OACC_CLAUSE_INDEPENDENT:
21229 : 45 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
21230 : : clauses);
21231 : 45 : c_name = "independent";
21232 : 45 : break;
21233 : 13 : case PRAGMA_OACC_CLAUSE_LINK:
21234 : 13 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21235 : 13 : c_name = "link";
21236 : 13 : break;
21237 : 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
21238 : 10 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21239 : 10 : c_name = "no_create";
21240 : 10 : break;
21241 : 25 : case PRAGMA_OACC_CLAUSE_NOHOST:
21242 : 25 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST,
21243 : : clauses);
21244 : 25 : c_name = "nohost";
21245 : 25 : break;
21246 : 302 : case PRAGMA_OACC_CLAUSE_NUM_GANGS:
21247 : 302 : clauses = c_parser_oacc_single_int_clause (parser,
21248 : : OMP_CLAUSE_NUM_GANGS,
21249 : : clauses);
21250 : 302 : c_name = "num_gangs";
21251 : 302 : break;
21252 : 207 : case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
21253 : 207 : clauses = c_parser_oacc_single_int_clause (parser,
21254 : : OMP_CLAUSE_NUM_WORKERS,
21255 : : clauses);
21256 : 207 : c_name = "num_workers";
21257 : 207 : break;
21258 : 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
21259 : 128 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21260 : 128 : c_name = "present";
21261 : 128 : break;
21262 : 66 : case PRAGMA_OACC_CLAUSE_PRIVATE:
21263 : 66 : clauses = c_parser_omp_clause_private (parser, clauses);
21264 : 66 : c_name = "private";
21265 : 66 : break;
21266 : 905 : case PRAGMA_OACC_CLAUSE_REDUCTION:
21267 : 905 : clauses
21268 : 905 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
21269 : : false, clauses);
21270 : 905 : c_name = "reduction";
21271 : 905 : break;
21272 : 66 : case PRAGMA_OACC_CLAUSE_SELF:
21273 : 66 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
21274 : : /* OpenACC compute construct */
21275 : 48 : clauses = c_parser_oacc_compute_clause_self (parser, clauses);
21276 : : else
21277 : : /* OpenACC 'update' directive */
21278 : 18 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21279 : : c_name = "self";
21280 : : break;
21281 : 261 : case PRAGMA_OACC_CLAUSE_SEQ:
21282 : 261 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
21283 : : clauses);
21284 : 261 : c_name = "seq";
21285 : 261 : break;
21286 : 123 : case PRAGMA_OACC_CLAUSE_TILE:
21287 : 123 : clauses = c_parser_oacc_clause_tile (parser, clauses);
21288 : 123 : c_name = "tile";
21289 : 123 : break;
21290 : 21 : case PRAGMA_OACC_CLAUSE_USE_DEVICE:
21291 : 21 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
21292 : 21 : c_name = "use_device";
21293 : 21 : break;
21294 : 518 : case PRAGMA_OACC_CLAUSE_VECTOR:
21295 : 518 : c_name = "vector";
21296 : 518 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_VECTOR,
21297 : : c_name, clauses);
21298 : 518 : break;
21299 : 223 : case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
21300 : 223 : clauses = c_parser_oacc_single_int_clause (parser,
21301 : : OMP_CLAUSE_VECTOR_LENGTH,
21302 : : clauses);
21303 : 223 : c_name = "vector_length";
21304 : 223 : break;
21305 : 89 : case PRAGMA_OACC_CLAUSE_WAIT:
21306 : 89 : clauses = c_parser_oacc_clause_wait (parser, clauses);
21307 : 89 : c_name = "wait";
21308 : 89 : break;
21309 : 453 : case PRAGMA_OACC_CLAUSE_WORKER:
21310 : 453 : c_name = "worker";
21311 : 453 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_WORKER,
21312 : : c_name, clauses);
21313 : 453 : break;
21314 : 46 : default:
21315 : 46 : c_parser_error (parser, "expected an OpenACC clause");
21316 : 46 : goto saw_error;
21317 : : }
21318 : :
21319 : 6710 : first = false;
21320 : :
21321 : 6710 : if (((mask >> c_kind) & 1) == 0)
21322 : : {
21323 : : /* Remove the invalid clause(s) from the list to avoid
21324 : : confusing the rest of the compiler. */
21325 : 18 : clauses = prev;
21326 : 18 : error_at (here, "%qs is not valid for %qs", c_name, where);
21327 : : }
21328 : : }
21329 : :
21330 : 5300 : saw_error:
21331 : 5346 : c_parser_skip_to_pragma_eol (parser);
21332 : :
21333 : 5346 : if (finish_p)
21334 : 7819 : return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
21335 : 4650 : : C_ORT_ACC);
21336 : :
21337 : : return clauses;
21338 : : }
21339 : :
21340 : : /* Parse all OpenMP clauses. The set clauses allowed by the directive
21341 : : is a bitmask in MASK. Return the list of clauses found.
21342 : : FINISH_P set if c_finish_omp_clauses should be called.
21343 : : NESTED non-zero if clauses should be terminated by closing paren instead
21344 : : of end of pragma. If it is 2, additionally commas are required in between
21345 : : the clauses. */
21346 : :
21347 : : static tree
21348 : 19874 : c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
21349 : : const char *where, bool finish_p = true,
21350 : : int nested = 0)
21351 : : {
21352 : 19874 : tree clauses = NULL;
21353 : 19874 : bool first = true;
21354 : :
21355 : 47021 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
21356 : : {
21357 : 27232 : location_t here;
21358 : 27232 : pragma_omp_clause c_kind;
21359 : 27232 : const char *c_name;
21360 : 27232 : tree prev = clauses;
21361 : :
21362 : 27329 : if (nested && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
21363 : : break;
21364 : :
21365 : 27210 : if (!first || nested != 2)
21366 : : {
21367 : 27187 : if (c_parser_next_token_is (parser, CPP_COMMA))
21368 : 2693 : c_parser_consume_token (parser);
21369 : 24494 : else if (nested == 2)
21370 : 3 : error_at (c_parser_peek_token (parser)->location,
21371 : : "clauses in %<simd%> trait should be separated "
21372 : : "by %<,%>");
21373 : : }
21374 : :
21375 : 27210 : here = c_parser_peek_token (parser)->location;
21376 : 27210 : c_kind = c_parser_omp_clause_name (parser);
21377 : :
21378 : 27210 : switch (c_kind)
21379 : : {
21380 : 115 : case PRAGMA_OMP_CLAUSE_BIND:
21381 : 115 : clauses = c_parser_omp_clause_bind (parser, clauses);
21382 : 115 : c_name = "bind";
21383 : 115 : break;
21384 : 2886 : case PRAGMA_OMP_CLAUSE_COLLAPSE:
21385 : 2886 : clauses = c_parser_omp_clause_collapse (parser, clauses);
21386 : 2886 : c_name = "collapse";
21387 : 2886 : break;
21388 : 101 : case PRAGMA_OMP_CLAUSE_COPYIN:
21389 : 101 : clauses = c_parser_omp_clause_copyin (parser, clauses);
21390 : 101 : c_name = "copyin";
21391 : 101 : break;
21392 : 21 : case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
21393 : 21 : clauses = c_parser_omp_clause_copyprivate (parser, clauses);
21394 : 21 : c_name = "copyprivate";
21395 : 21 : break;
21396 : 640 : case PRAGMA_OMP_CLAUSE_DEFAULT:
21397 : 640 : clauses = c_parser_omp_clause_default (parser, clauses, false);
21398 : 640 : c_name = "default";
21399 : 640 : break;
21400 : 34 : case PRAGMA_OMP_CLAUSE_DETACH:
21401 : 34 : clauses = c_parser_omp_clause_detach (parser, clauses);
21402 : 34 : c_name = "detach";
21403 : 34 : break;
21404 : 62 : case PRAGMA_OMP_CLAUSE_FILTER:
21405 : 62 : clauses = c_parser_omp_clause_filter (parser, clauses);
21406 : 62 : c_name = "filter";
21407 : 62 : break;
21408 : 664 : case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
21409 : 664 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
21410 : 664 : c_name = "firstprivate";
21411 : 664 : break;
21412 : 98 : case PRAGMA_OMP_CLAUSE_FINAL:
21413 : 98 : clauses = c_parser_omp_clause_final (parser, clauses);
21414 : 98 : c_name = "final";
21415 : 98 : break;
21416 : 62 : case PRAGMA_OMP_CLAUSE_GRAINSIZE:
21417 : 62 : clauses = c_parser_omp_clause_grainsize (parser, clauses);
21418 : 62 : c_name = "grainsize";
21419 : 62 : break;
21420 : 29 : case PRAGMA_OMP_CLAUSE_HINT:
21421 : 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
21422 : 29 : c_name = "hint";
21423 : 29 : break;
21424 : 239 : case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
21425 : 239 : clauses = c_parser_omp_clause_defaultmap (parser, clauses);
21426 : 239 : c_name = "defaultmap";
21427 : 239 : break;
21428 : 778 : case PRAGMA_OMP_CLAUSE_IF:
21429 : 778 : clauses = c_parser_omp_clause_if (parser, clauses, true);
21430 : 778 : c_name = "if";
21431 : 778 : break;
21432 : 320 : case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
21433 : 320 : clauses
21434 : 320 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
21435 : : true, clauses);
21436 : 320 : c_name = "in_reduction";
21437 : 320 : break;
21438 : 26 : case PRAGMA_OMP_CLAUSE_INDIRECT:
21439 : 26 : clauses = c_parser_omp_clause_indirect (parser, clauses);
21440 : 26 : c_name = "indirect";
21441 : 26 : break;
21442 : 731 : case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
21443 : 731 : clauses = c_parser_omp_clause_lastprivate (parser, clauses);
21444 : 731 : c_name = "lastprivate";
21445 : 731 : break;
21446 : 78 : case PRAGMA_OMP_CLAUSE_MERGEABLE:
21447 : 78 : clauses = c_parser_omp_clause_mergeable (parser, clauses);
21448 : 78 : c_name = "mergeable";
21449 : 78 : break;
21450 : 391 : case PRAGMA_OMP_CLAUSE_NOWAIT:
21451 : 391 : clauses = c_parser_omp_clause_nowait (parser, clauses);
21452 : 391 : c_name = "nowait";
21453 : 391 : break;
21454 : 49 : case PRAGMA_OMP_CLAUSE_NUM_TASKS:
21455 : 49 : clauses = c_parser_omp_clause_num_tasks (parser, clauses);
21456 : 49 : c_name = "num_tasks";
21457 : 49 : break;
21458 : 424 : case PRAGMA_OMP_CLAUSE_NUM_THREADS:
21459 : 424 : clauses = c_parser_omp_clause_num_threads (parser, clauses);
21460 : 424 : c_name = "num_threads";
21461 : 424 : break;
21462 : 375 : case PRAGMA_OMP_CLAUSE_ORDER:
21463 : 375 : clauses = c_parser_omp_clause_order (parser, clauses);
21464 : 375 : c_name = "order";
21465 : 375 : break;
21466 : 309 : case PRAGMA_OMP_CLAUSE_ORDERED:
21467 : 309 : clauses = c_parser_omp_clause_ordered (parser, clauses);
21468 : 309 : c_name = "ordered";
21469 : 309 : break;
21470 : 97 : case PRAGMA_OMP_CLAUSE_PRIORITY:
21471 : 97 : clauses = c_parser_omp_clause_priority (parser, clauses);
21472 : 97 : c_name = "priority";
21473 : 97 : break;
21474 : 669 : case PRAGMA_OMP_CLAUSE_PRIVATE:
21475 : 669 : clauses = c_parser_omp_clause_private (parser, clauses);
21476 : 669 : c_name = "private";
21477 : 669 : break;
21478 : 1778 : case PRAGMA_OMP_CLAUSE_REDUCTION:
21479 : 1778 : clauses
21480 : 1778 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
21481 : : true, clauses);
21482 : 1778 : c_name = "reduction";
21483 : 1778 : break;
21484 : 3467 : case PRAGMA_OMP_CLAUSE_SCHEDULE:
21485 : 3467 : clauses = c_parser_omp_clause_schedule (parser, clauses);
21486 : 3467 : c_name = "schedule";
21487 : 3467 : break;
21488 : 689 : case PRAGMA_OMP_CLAUSE_SHARED:
21489 : 689 : clauses = c_parser_omp_clause_shared (parser, clauses);
21490 : 689 : c_name = "shared";
21491 : 689 : break;
21492 : 86 : case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
21493 : 86 : clauses
21494 : 86 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
21495 : : true, clauses);
21496 : 86 : c_name = "task_reduction";
21497 : 86 : break;
21498 : 96 : case PRAGMA_OMP_CLAUSE_UNTIED:
21499 : 96 : clauses = c_parser_omp_clause_untied (parser, clauses);
21500 : 96 : c_name = "untied";
21501 : 96 : break;
21502 : 63 : case PRAGMA_OMP_CLAUSE_INBRANCH:
21503 : 63 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
21504 : : clauses);
21505 : 63 : c_name = "inbranch";
21506 : 63 : break;
21507 : 121 : case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
21508 : 121 : clauses = c_parser_omp_clause_nontemporal (parser, clauses);
21509 : 121 : c_name = "nontemporal";
21510 : 121 : break;
21511 : 136 : case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
21512 : 136 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH,
21513 : : clauses);
21514 : 136 : c_name = "notinbranch";
21515 : 136 : break;
21516 : 107 : case PRAGMA_OMP_CLAUSE_PARALLEL:
21517 : 107 : clauses
21518 : 107 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
21519 : : clauses);
21520 : 107 : c_name = "parallel";
21521 : 107 : if (!first)
21522 : : {
21523 : 0 : clause_not_first:
21524 : 0 : error_at (here, "%qs must be the first clause of %qs",
21525 : : c_name, where);
21526 : 0 : clauses = prev;
21527 : : }
21528 : : break;
21529 : 84 : case PRAGMA_OMP_CLAUSE_FOR:
21530 : 84 : clauses
21531 : 84 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
21532 : : clauses);
21533 : 84 : c_name = "for";
21534 : 84 : if (!first)
21535 : 0 : goto clause_not_first;
21536 : : break;
21537 : 78 : case PRAGMA_OMP_CLAUSE_SECTIONS:
21538 : 78 : clauses
21539 : 78 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
21540 : : clauses);
21541 : 78 : c_name = "sections";
21542 : 78 : if (!first)
21543 : 0 : goto clause_not_first;
21544 : : break;
21545 : 110 : case PRAGMA_OMP_CLAUSE_TASKGROUP:
21546 : 110 : clauses
21547 : 110 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
21548 : : clauses);
21549 : 110 : c_name = "taskgroup";
21550 : 110 : if (!first)
21551 : 0 : goto clause_not_first;
21552 : : break;
21553 : 32 : case PRAGMA_OMP_CLAUSE_LINK:
21554 : 32 : clauses
21555 : 32 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LINK, clauses);
21556 : 32 : c_name = "link";
21557 : 32 : break;
21558 : 467 : case PRAGMA_OMP_CLAUSE_TO:
21559 : 467 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
21560 : : {
21561 : 83 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
21562 : : clauses);
21563 : 185 : for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
21564 : 102 : OMP_CLAUSE_ENTER_TO (c) = 1;
21565 : : clauses = nl;
21566 : : }
21567 : : else
21568 : 384 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_TO,
21569 : : clauses);
21570 : : c_name = "to";
21571 : : break;
21572 : 2447 : case PRAGMA_OMP_CLAUSE_FROM:
21573 : 2447 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_FROM,
21574 : : clauses);
21575 : 2447 : c_name = "from";
21576 : 2447 : break;
21577 : 115 : case PRAGMA_OMP_CLAUSE_UNIFORM:
21578 : 115 : clauses = c_parser_omp_clause_uniform (parser, clauses);
21579 : 115 : c_name = "uniform";
21580 : 115 : break;
21581 : 195 : case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
21582 : 195 : clauses = c_parser_omp_clause_num_teams (parser, clauses);
21583 : 195 : c_name = "num_teams";
21584 : 195 : break;
21585 : 154 : case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
21586 : 154 : clauses = c_parser_omp_clause_thread_limit (parser, clauses);
21587 : 154 : c_name = "thread_limit";
21588 : 154 : break;
21589 : 228 : case PRAGMA_OMP_CLAUSE_ALIGNED:
21590 : 228 : clauses = c_parser_omp_clause_aligned (parser, clauses);
21591 : 228 : c_name = "aligned";
21592 : 228 : break;
21593 : 467 : case PRAGMA_OMP_CLAUSE_ALLOCATE:
21594 : 467 : clauses = c_parser_omp_clause_allocate (parser, clauses);
21595 : 467 : c_name = "allocate";
21596 : 467 : break;
21597 : 474 : case PRAGMA_OMP_CLAUSE_LINEAR:
21598 : 474 : clauses = c_parser_omp_clause_linear (parser, clauses);
21599 : 474 : c_name = "linear";
21600 : 474 : break;
21601 : 146 : case PRAGMA_OMP_CLAUSE_AFFINITY:
21602 : 146 : clauses = c_parser_omp_clause_affinity (parser, clauses);
21603 : 146 : c_name = "affinity";
21604 : 146 : break;
21605 : 855 : case PRAGMA_OMP_CLAUSE_DEPEND:
21606 : 855 : clauses = c_parser_omp_clause_depend (parser, clauses);
21607 : 855 : c_name = "depend";
21608 : 855 : break;
21609 : 145 : case PRAGMA_OMP_CLAUSE_DOACROSS:
21610 : 145 : clauses = c_parser_omp_clause_doacross (parser, clauses);
21611 : 145 : c_name = "doacross";
21612 : 145 : break;
21613 : 41 : case PRAGMA_OMP_CLAUSE_DESTROY:
21614 : 41 : clauses = c_parser_omp_clause_destroy (parser, clauses);
21615 : 41 : c_name = "destroy";
21616 : 41 : break;
21617 : 167 : case PRAGMA_OMP_CLAUSE_INIT:
21618 : 167 : clauses = c_parser_omp_clause_init (parser, clauses);
21619 : 167 : c_name = "init";
21620 : 167 : break;
21621 : 43 : case PRAGMA_OMP_CLAUSE_USE:
21622 : 43 : clauses = c_parser_omp_clause_use (parser, clauses);
21623 : 43 : c_name = "use";
21624 : 43 : break;
21625 : 42 : case PRAGMA_OMP_CLAUSE_INTEROP:
21626 : 42 : clauses = c_parser_omp_clause_interop (parser, clauses);
21627 : 42 : c_name = "interop";
21628 : 42 : break;
21629 : 1637 : case PRAGMA_OMP_CLAUSE_MAP:
21630 : 1637 : clauses = c_parser_omp_clause_map (parser, clauses, false);
21631 : 1637 : c_name = "map";
21632 : 1637 : break;
21633 : 10 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
21634 : 10 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
21635 : 10 : c_name = "use_device_ptr";
21636 : 10 : break;
21637 : 35 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
21638 : 35 : clauses = c_parser_omp_clause_use_device_addr (parser, clauses);
21639 : 35 : c_name = "use_device_addr";
21640 : 35 : break;
21641 : 87 : case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
21642 : 87 : clauses = c_parser_omp_clause_has_device_addr (parser, clauses);
21643 : 87 : c_name = "has_device_addr";
21644 : 87 : break;
21645 : 114 : case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
21646 : 114 : clauses = c_parser_omp_clause_is_device_ptr (parser, clauses);
21647 : 114 : c_name = "is_device_ptr";
21648 : 114 : break;
21649 : 367 : case PRAGMA_OMP_CLAUSE_DEVICE:
21650 : 367 : clauses = c_parser_omp_clause_device (parser, clauses);
21651 : 367 : c_name = "device";
21652 : 367 : break;
21653 : 1582 : case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
21654 : 1582 : clauses = c_parser_omp_clause_dist_schedule (parser, clauses);
21655 : 1582 : c_name = "dist_schedule";
21656 : 1582 : break;
21657 : 194 : case PRAGMA_OMP_CLAUSE_PROC_BIND:
21658 : 194 : clauses = c_parser_omp_clause_proc_bind (parser, clauses);
21659 : 194 : c_name = "proc_bind";
21660 : 194 : break;
21661 : 42 : case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
21662 : 42 : clauses = c_parser_omp_clause_device_type (parser, clauses);
21663 : 42 : c_name = "device_type";
21664 : 42 : break;
21665 : 227 : case PRAGMA_OMP_CLAUSE_SAFELEN:
21666 : 227 : clauses = c_parser_omp_clause_safelen (parser, clauses);
21667 : 227 : c_name = "safelen";
21668 : 227 : break;
21669 : 317 : case PRAGMA_OMP_CLAUSE_SIMDLEN:
21670 : 317 : clauses = c_parser_omp_clause_simdlen (parser, clauses);
21671 : 317 : c_name = "simdlen";
21672 : 317 : break;
21673 : 18 : case PRAGMA_OMP_CLAUSE_NOGROUP:
21674 : 18 : clauses = c_parser_omp_clause_nogroup (parser, clauses);
21675 : 18 : c_name = "nogroup";
21676 : 18 : break;
21677 : 46 : case PRAGMA_OMP_CLAUSE_THREADS:
21678 : 46 : clauses
21679 : 46 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS,
21680 : : clauses);
21681 : 46 : c_name = "threads";
21682 : 46 : break;
21683 : 57 : case PRAGMA_OMP_CLAUSE_SIMD:
21684 : 57 : clauses
21685 : 57 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD,
21686 : : clauses);
21687 : 57 : c_name = "simd";
21688 : 57 : break;
21689 : 40 : case PRAGMA_OMP_CLAUSE_ENTER:
21690 : 40 : clauses
21691 : 40 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
21692 : : clauses);
21693 : 40 : c_name = "enter";
21694 : 40 : break;
21695 : 69 : case PRAGMA_OMP_CLAUSE_FULL:
21696 : 69 : c_name = "full";
21697 : 69 : clauses = c_parser_omp_clause_full (parser, clauses);
21698 : 69 : break;
21699 : 230 : case PRAGMA_OMP_CLAUSE_PARTIAL:
21700 : 230 : c_name = "partial";
21701 : 230 : clauses = c_parser_omp_clause_partial (parser, clauses);
21702 : 230 : break;
21703 : 21 : case PRAGMA_OMP_CLAUSE_NOVARIANTS:
21704 : 21 : c_name = "novariants";
21705 : 21 : clauses = c_parser_omp_clause_novariants (parser, clauses);
21706 : 21 : break;
21707 : 23 : case PRAGMA_OMP_CLAUSE_NOCONTEXT:
21708 : 23 : c_name = "nocontext";
21709 : 23 : clauses = c_parser_omp_clause_nocontext (parser, clauses);
21710 : 23 : break;
21711 : 63 : default:
21712 : 63 : c_parser_error (parser, "expected an OpenMP clause");
21713 : 63 : goto saw_error;
21714 : : }
21715 : :
21716 : 27147 : first = false;
21717 : :
21718 : 27147 : if (((mask >> c_kind) & 1) == 0)
21719 : : {
21720 : : /* Remove the invalid clause(s) from the list to avoid
21721 : : confusing the rest of the compiler. */
21722 : 24 : clauses = prev;
21723 : 24 : error_at (here, "%qs is not valid for %qs", c_name, where);
21724 : : }
21725 : : }
21726 : :
21727 : 19789 : saw_error:
21728 : 19874 : if (!nested)
21729 : 19851 : c_parser_skip_to_pragma_eol (parser);
21730 : :
21731 : 19874 : if (finish_p)
21732 : : {
21733 : 11342 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
21734 : 386 : return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
21735 : 10956 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE)) != 0)
21736 : 183 : return c_finish_omp_clauses (clauses, C_ORT_OMP_INTEROP);
21737 : 10773 : return c_finish_omp_clauses (clauses, C_ORT_OMP);
21738 : : }
21739 : :
21740 : : return clauses;
21741 : : }
21742 : :
21743 : : /* OpenACC 2.0, OpenMP 2.5:
21744 : : structured-block:
21745 : : statement
21746 : :
21747 : : In practice, we're also interested in adding the statement to an
21748 : : outer node. So it is convenient if we work around the fact that
21749 : : c_parser_statement calls add_stmt. */
21750 : :
21751 : : static tree
21752 : 6525 : c_parser_omp_structured_block (c_parser *parser, bool *if_p)
21753 : : {
21754 : 6525 : tree stmt = push_stmt_list ();
21755 : 6525 : parser->omp_attrs_forbidden_p = true;
21756 : 6525 : c_parser_statement (parser, if_p);
21757 : 6525 : return pop_stmt_list (stmt);
21758 : : }
21759 : :
21760 : : /* OpenACC 2.0:
21761 : : # pragma acc cache (variable-list) new-line
21762 : :
21763 : : OpenACC 2.7:
21764 : : # pragma acc cache (readonly: variable-list) new-line
21765 : :
21766 : : LOC is the location of the #pragma token.
21767 : : */
21768 : :
21769 : : static tree
21770 : 137 : c_parser_oacc_cache (location_t loc, c_parser *parser)
21771 : : {
21772 : 137 : tree stmt, clauses = NULL_TREE;
21773 : 137 : bool readonly = false;
21774 : 137 : location_t open_loc = c_parser_peek_token (parser)->location;
21775 : 137 : matching_parens parens;
21776 : 137 : if (parens.require_open (parser))
21777 : : {
21778 : 135 : c_token *token = c_parser_peek_token (parser);
21779 : 135 : if (token->type == CPP_NAME
21780 : 131 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
21781 : 139 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
21782 : : {
21783 : 4 : c_parser_consume_token (parser);
21784 : 4 : c_parser_consume_token (parser);
21785 : 4 : readonly = true;
21786 : : }
21787 : 135 : clauses = c_parser_omp_variable_list (parser, open_loc,
21788 : : OMP_CLAUSE__CACHE_, NULL_TREE);
21789 : 135 : parens.skip_until_found_close (parser);
21790 : : }
21791 : :
21792 : 135 : if (readonly)
21793 : 8 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
21794 : 4 : OMP_CLAUSE__CACHE__READONLY (c) = 1;
21795 : :
21796 : 137 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
21797 : :
21798 : 137 : c_parser_skip_to_pragma_eol (parser);
21799 : :
21800 : 137 : stmt = make_node (OACC_CACHE);
21801 : 137 : TREE_TYPE (stmt) = void_type_node;
21802 : 137 : OACC_CACHE_CLAUSES (stmt) = clauses;
21803 : 137 : SET_EXPR_LOCATION (stmt, loc);
21804 : 137 : add_stmt (stmt);
21805 : :
21806 : 137 : return stmt;
21807 : : }
21808 : :
21809 : : /* OpenACC 2.0:
21810 : : # pragma acc data oacc-data-clause[optseq] new-line
21811 : : structured-block
21812 : :
21813 : : LOC is the location of the #pragma token.
21814 : : */
21815 : :
21816 : : #define OACC_DATA_CLAUSE_MASK \
21817 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
21818 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
21819 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
21820 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
21821 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
21822 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
21823 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
21824 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
21825 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
21826 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
21827 : :
21828 : : static tree
21829 : 497 : c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
21830 : : {
21831 : 497 : tree stmt, clauses, block;
21832 : :
21833 : 497 : clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
21834 : : "#pragma acc data");
21835 : :
21836 : 497 : block = c_begin_omp_parallel ();
21837 : 497 : add_stmt (c_parser_omp_structured_block (parser, if_p));
21838 : :
21839 : 497 : stmt = c_finish_oacc_data (loc, clauses, block);
21840 : :
21841 : 497 : return stmt;
21842 : : }
21843 : :
21844 : : /* OpenACC 2.0:
21845 : : # pragma acc declare oacc-data-clause[optseq] new-line
21846 : : */
21847 : :
21848 : : #define OACC_DECLARE_CLAUSE_MASK \
21849 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
21850 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
21851 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
21852 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
21853 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
21854 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
21855 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
21856 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
21857 : :
21858 : : static void
21859 : 144 : c_parser_oacc_declare (c_parser *parser)
21860 : : {
21861 : 144 : location_t pragma_loc = c_parser_peek_token (parser)->location;
21862 : 144 : tree clauses, stmt, t, decl;
21863 : :
21864 : 144 : bool error = false;
21865 : :
21866 : 144 : c_parser_consume_pragma (parser);
21867 : :
21868 : 144 : clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
21869 : : "#pragma acc declare");
21870 : 144 : if (!clauses)
21871 : : {
21872 : 2 : error_at (pragma_loc,
21873 : : "no valid clauses specified in %<#pragma acc declare%>");
21874 : 2 : return;
21875 : : }
21876 : :
21877 : 296 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
21878 : : {
21879 : 154 : location_t loc = OMP_CLAUSE_LOCATION (t);
21880 : 154 : decl = OMP_CLAUSE_DECL (t);
21881 : 154 : if (!DECL_P (decl))
21882 : : {
21883 : 1 : error_at (loc, "array section in %<#pragma acc declare%>");
21884 : 1 : error = true;
21885 : 1 : continue;
21886 : : }
21887 : :
21888 : 153 : switch (OMP_CLAUSE_MAP_KIND (t))
21889 : : {
21890 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
21891 : : case GOMP_MAP_ALLOC:
21892 : : case GOMP_MAP_TO:
21893 : : case GOMP_MAP_FORCE_DEVICEPTR:
21894 : : case GOMP_MAP_DEVICE_RESIDENT:
21895 : : break;
21896 : :
21897 : 13 : case GOMP_MAP_LINK:
21898 : 13 : if (!global_bindings_p ()
21899 : 13 : && (TREE_STATIC (decl)
21900 : 6 : || !DECL_EXTERNAL (decl)))
21901 : : {
21902 : 2 : error_at (loc,
21903 : : "%qD must be a global variable in "
21904 : : "%<#pragma acc declare link%>",
21905 : : decl);
21906 : 2 : error = true;
21907 : 2 : continue;
21908 : : }
21909 : : break;
21910 : :
21911 : 42 : default:
21912 : 42 : if (global_bindings_p ())
21913 : : {
21914 : 5 : error_at (loc, "invalid OpenACC clause at file scope");
21915 : 5 : error = true;
21916 : 5 : continue;
21917 : : }
21918 : 37 : if (DECL_EXTERNAL (decl))
21919 : : {
21920 : 10 : error_at (loc,
21921 : : "invalid use of %<extern%> variable %qD "
21922 : : "in %<#pragma acc declare%>", decl);
21923 : 10 : error = true;
21924 : 10 : continue;
21925 : : }
21926 : 27 : else if (TREE_PUBLIC (decl))
21927 : : {
21928 : 2 : error_at (loc,
21929 : : "invalid use of %<global%> variable %qD "
21930 : : "in %<#pragma acc declare%>", decl);
21931 : 2 : error = true;
21932 : 2 : continue;
21933 : : }
21934 : : break;
21935 : : }
21936 : :
21937 : 134 : if (!c_check_in_current_scope (decl))
21938 : : {
21939 : 2 : error_at (loc,
21940 : : "%qD must be a variable declared in the same scope as "
21941 : : "%<#pragma acc declare%>", decl);
21942 : 2 : error = true;
21943 : 2 : continue;
21944 : : }
21945 : :
21946 : 132 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
21947 : 250 : || lookup_attribute ("omp declare target link",
21948 : 118 : DECL_ATTRIBUTES (decl)))
21949 : : {
21950 : 17 : error_at (loc, "variable %qD used more than once with "
21951 : : "%<#pragma acc declare%>", decl);
21952 : 17 : error = true;
21953 : 17 : continue;
21954 : : }
21955 : :
21956 : 115 : if (!error)
21957 : : {
21958 : 115 : tree id;
21959 : :
21960 : 115 : if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
21961 : 7 : id = get_identifier ("omp declare target link");
21962 : : else
21963 : 108 : id = get_identifier ("omp declare target");
21964 : :
21965 : 115 : DECL_ATTRIBUTES (decl)
21966 : 115 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
21967 : :
21968 : 115 : if (global_bindings_p ())
21969 : : {
21970 : 45 : symtab_node *node = symtab_node::get (decl);
21971 : 45 : if (node != NULL)
21972 : : {
21973 : 33 : node->offloadable = 1;
21974 : 33 : if (ENABLE_OFFLOADING)
21975 : : {
21976 : : g->have_offload = true;
21977 : : if (is_a <varpool_node *> (node))
21978 : : vec_safe_push (offload_vars, decl);
21979 : : }
21980 : : }
21981 : : }
21982 : : }
21983 : : }
21984 : :
21985 : 142 : if (error || global_bindings_p ())
21986 : 74 : return;
21987 : :
21988 : 68 : stmt = make_node (OACC_DECLARE);
21989 : 68 : TREE_TYPE (stmt) = void_type_node;
21990 : 68 : OACC_DECLARE_CLAUSES (stmt) = clauses;
21991 : 68 : SET_EXPR_LOCATION (stmt, pragma_loc);
21992 : :
21993 : 68 : add_stmt (stmt);
21994 : :
21995 : 68 : return;
21996 : : }
21997 : :
21998 : : /* OpenACC 2.0:
21999 : : # pragma acc enter data oacc-enter-data-clause[optseq] new-line
22000 : :
22001 : : or
22002 : :
22003 : : # pragma acc exit data oacc-exit-data-clause[optseq] new-line
22004 : :
22005 : :
22006 : : LOC is the location of the #pragma token.
22007 : : */
22008 : :
22009 : : #define OACC_ENTER_DATA_CLAUSE_MASK \
22010 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22011 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22012 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22013 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22014 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22015 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22016 : :
22017 : : #define OACC_EXIT_DATA_CLAUSE_MASK \
22018 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22019 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22020 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22021 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
22022 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
22023 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
22024 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22025 : :
22026 : : static void
22027 : 261 : c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
22028 : : {
22029 : 261 : location_t loc = c_parser_peek_token (parser)->location;
22030 : 261 : tree clauses, stmt;
22031 : 261 : const char *p = "";
22032 : :
22033 : 261 : c_parser_consume_pragma (parser);
22034 : :
22035 : 261 : if (c_parser_next_token_is (parser, CPP_NAME))
22036 : : {
22037 : 258 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22038 : 258 : c_parser_consume_token (parser);
22039 : : }
22040 : :
22041 : 261 : if (strcmp (p, "data") != 0)
22042 : : {
22043 : 8 : error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
22044 : : enter ? "enter" : "exit");
22045 : 6 : parser->error = true;
22046 : 6 : c_parser_skip_to_pragma_eol (parser);
22047 : 6 : return;
22048 : : }
22049 : :
22050 : 255 : if (enter)
22051 : 129 : clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
22052 : : "#pragma acc enter data");
22053 : : else
22054 : 126 : clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
22055 : : "#pragma acc exit data");
22056 : :
22057 : 255 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
22058 : : {
22059 : 15 : error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
22060 : : enter ? "enter" : "exit");
22061 : 15 : return;
22062 : : }
22063 : :
22064 : 240 : stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
22065 : 240 : TREE_TYPE (stmt) = void_type_node;
22066 : 240 : OMP_STANDALONE_CLAUSES (stmt) = clauses;
22067 : 240 : SET_EXPR_LOCATION (stmt, loc);
22068 : 240 : add_stmt (stmt);
22069 : : }
22070 : :
22071 : :
22072 : : /* OpenACC 2.0:
22073 : : # pragma acc host_data oacc-data-clause[optseq] new-line
22074 : : structured-block
22075 : : */
22076 : :
22077 : : #define OACC_HOST_DATA_CLAUSE_MASK \
22078 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
22079 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22080 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
22081 : :
22082 : : static tree
22083 : 23 : c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
22084 : : {
22085 : 23 : tree stmt, clauses, block;
22086 : :
22087 : 23 : clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
22088 : : "#pragma acc host_data", false);
22089 : 23 : if (!omp_find_clause (clauses, OMP_CLAUSE_USE_DEVICE_PTR))
22090 : : {
22091 : 2 : error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
22092 : 2 : return error_mark_node;
22093 : : }
22094 : 21 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22095 : 21 : block = c_begin_omp_parallel ();
22096 : 21 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22097 : 21 : stmt = c_finish_oacc_host_data (loc, clauses, block);
22098 : 21 : return stmt;
22099 : : }
22100 : :
22101 : :
22102 : : /* OpenACC 2.0:
22103 : :
22104 : : # pragma acc loop oacc-loop-clause[optseq] new-line
22105 : : structured-block
22106 : :
22107 : : LOC is the location of the #pragma token.
22108 : : */
22109 : :
22110 : : #define OACC_LOOP_CLAUSE_MASK \
22111 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
22112 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22113 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22114 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22115 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22116 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22117 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
22118 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
22119 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22120 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
22121 : : static tree
22122 : 2444 : c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
22123 : : omp_clause_mask mask, tree *cclauses, bool *if_p)
22124 : : {
22125 : 2444 : bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
22126 : :
22127 : 2444 : strcat (p_name, " loop");
22128 : 2444 : mask |= OACC_LOOP_CLAUSE_MASK;
22129 : :
22130 : 2444 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
22131 : : /*finish_p=*/cclauses == NULL,
22132 : : /*target=*/is_parallel);
22133 : 2444 : if (cclauses)
22134 : : {
22135 : 673 : clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
22136 : 673 : if (*cclauses)
22137 : 152 : *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
22138 : 673 : if (clauses)
22139 : 271 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22140 : : }
22141 : :
22142 : 2444 : tree block = c_begin_compound_stmt (true);
22143 : 2444 : tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
22144 : : if_p);
22145 : 2444 : block = c_end_compound_stmt (loc, block, true);
22146 : 2444 : add_stmt (block);
22147 : :
22148 : 2444 : return stmt;
22149 : : }
22150 : :
22151 : : /* OpenACC 2.0:
22152 : : # pragma acc kernels oacc-kernels-clause[optseq] new-line
22153 : : structured-block
22154 : :
22155 : : or
22156 : :
22157 : : # pragma acc parallel oacc-parallel-clause[optseq] new-line
22158 : : structured-block
22159 : :
22160 : : OpenACC 2.6:
22161 : :
22162 : : # pragma acc serial oacc-serial-clause[optseq] new-line
22163 : : structured-block
22164 : :
22165 : : LOC is the location of the #pragma token.
22166 : : */
22167 : :
22168 : : #define OACC_KERNELS_CLAUSE_MASK \
22169 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22170 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22171 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22172 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22173 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22174 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22175 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22176 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22177 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22178 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22179 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22180 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22181 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22182 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22183 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22184 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22185 : :
22186 : : #define OACC_PARALLEL_CLAUSE_MASK \
22187 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22188 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22189 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22190 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22191 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22192 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22193 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22194 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22195 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22196 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22197 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22198 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22199 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22200 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22201 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22202 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22203 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22204 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22205 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22206 : :
22207 : : #define OACC_SERIAL_CLAUSE_MASK \
22208 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22209 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22210 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22211 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22212 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22213 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22214 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22215 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22216 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22217 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22218 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22219 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22220 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22221 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22222 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22223 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22224 : :
22225 : : static tree
22226 : 2154 : c_parser_oacc_compute (location_t loc, c_parser *parser,
22227 : : enum pragma_kind p_kind, char *p_name, bool *if_p)
22228 : : {
22229 : 2154 : omp_clause_mask mask;
22230 : 2154 : enum tree_code code;
22231 : 2154 : switch (p_kind)
22232 : : {
22233 : 522 : case PRAGMA_OACC_KERNELS:
22234 : 522 : strcat (p_name, " kernels");
22235 : 522 : mask = OACC_KERNELS_CLAUSE_MASK;
22236 : 522 : code = OACC_KERNELS;
22237 : 522 : break;
22238 : 1457 : case PRAGMA_OACC_PARALLEL:
22239 : 1457 : strcat (p_name, " parallel");
22240 : 1457 : mask = OACC_PARALLEL_CLAUSE_MASK;
22241 : 1457 : code = OACC_PARALLEL;
22242 : 1457 : break;
22243 : 175 : case PRAGMA_OACC_SERIAL:
22244 : 175 : strcat (p_name, " serial");
22245 : 175 : mask = OACC_SERIAL_CLAUSE_MASK;
22246 : 175 : code = OACC_SERIAL;
22247 : 175 : break;
22248 : 0 : default:
22249 : 0 : gcc_unreachable ();
22250 : : }
22251 : :
22252 : 2154 : if (c_parser_next_token_is (parser, CPP_NAME))
22253 : : {
22254 : 1710 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22255 : 1710 : if (strcmp (p, "loop") == 0)
22256 : : {
22257 : 673 : c_parser_consume_token (parser);
22258 : 673 : tree block = c_begin_omp_parallel ();
22259 : 673 : tree clauses;
22260 : 673 : c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
22261 : 673 : return c_finish_omp_construct (loc, code, block, clauses);
22262 : : }
22263 : : }
22264 : :
22265 : 1481 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
22266 : : /*finish_p=*/true,
22267 : : /*target=*/true);
22268 : :
22269 : 1481 : tree block = c_begin_omp_parallel ();
22270 : 1481 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22271 : :
22272 : 1481 : return c_finish_omp_construct (loc, code, block, clauses);
22273 : : }
22274 : :
22275 : : /* OpenACC 2.0:
22276 : : # pragma acc routine oacc-routine-clause[optseq] new-line
22277 : : function-definition
22278 : :
22279 : : # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
22280 : : */
22281 : :
22282 : : #define OACC_ROUTINE_CLAUSE_MASK \
22283 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22284 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22285 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22286 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22287 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
22288 : :
22289 : : /* Parse an OpenACC routine directive. For named directives, we apply
22290 : : immediately to the named function. For unnamed ones we then parse
22291 : : a declaration or definition, which must be for a function. */
22292 : :
22293 : : static void
22294 : 345 : c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
22295 : : {
22296 : 345 : gcc_checking_assert (context == pragma_external);
22297 : :
22298 : 345 : oacc_routine_data data;
22299 : 345 : data.error_seen = false;
22300 : 345 : data.fndecl_seen = false;
22301 : 345 : data.loc = c_parser_peek_token (parser)->location;
22302 : :
22303 : 345 : c_parser_consume_pragma (parser);
22304 : :
22305 : : /* Look for optional '( name )'. */
22306 : 345 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
22307 : : {
22308 : 143 : c_parser_consume_token (parser); /* '(' */
22309 : :
22310 : 143 : tree decl = NULL_TREE;
22311 : 143 : c_token *name_token = c_parser_peek_token (parser);
22312 : 143 : location_t name_loc = name_token->location;
22313 : 143 : if (name_token->type == CPP_NAME
22314 : 135 : && (name_token->id_kind == C_ID_ID
22315 : : || name_token->id_kind == C_ID_TYPENAME))
22316 : : {
22317 : 135 : decl = lookup_name (name_token->value);
22318 : 135 : if (!decl)
22319 : 5 : error_at (name_loc,
22320 : : "%qE has not been declared", name_token->value);
22321 : 135 : c_parser_consume_token (parser);
22322 : : }
22323 : : else
22324 : 8 : c_parser_error (parser, "expected function name");
22325 : :
22326 : 8 : if (!decl
22327 : 135 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
22328 : : {
22329 : 15 : c_parser_skip_to_pragma_eol (parser, false);
22330 : 43 : return;
22331 : : }
22332 : :
22333 : 128 : data.clauses
22334 : 128 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22335 : : "#pragma acc routine");
22336 : : /* The clauses are in reverse order; fix that to make later diagnostic
22337 : : emission easier. */
22338 : 128 : data.clauses = nreverse (data.clauses);
22339 : :
22340 : 128 : if (TREE_CODE (decl) != FUNCTION_DECL)
22341 : : {
22342 : 3 : error_at (name_loc, "%qD does not refer to a function", decl);
22343 : 3 : return;
22344 : : }
22345 : :
22346 : 125 : c_finish_oacc_routine (&data, decl, false);
22347 : : }
22348 : : else /* No optional '( name )'. */
22349 : : {
22350 : 202 : data.clauses
22351 : 202 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22352 : : "#pragma acc routine");
22353 : : /* The clauses are in reverse order; fix that to make later diagnostic
22354 : : emission easier. */
22355 : 202 : data.clauses = nreverse (data.clauses);
22356 : :
22357 : : /* Emit a helpful diagnostic if there's another pragma following this
22358 : : one. Also don't allow a static assertion declaration, as in the
22359 : : following we'll just parse a *single* "declaration or function
22360 : : definition", and the static assertion counts an one. */
22361 : 202 : if (c_parser_next_token_is (parser, CPP_PRAGMA)
22362 : 395 : || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
22363 : : {
22364 : 10 : error_at (data.loc,
22365 : : "%<#pragma acc routine%> not immediately followed by"
22366 : : " function declaration or definition");
22367 : : /* ..., and then just keep going. */
22368 : 10 : return;
22369 : : }
22370 : :
22371 : : /* We only have to consider the pragma_external case here. */
22372 : 192 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
22373 : 192 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
22374 : : {
22375 : 3 : int ext = disable_extension_diagnostics ();
22376 : 7 : do
22377 : 7 : c_parser_consume_token (parser);
22378 : 7 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
22379 : 10 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
22380 : 3 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
22381 : : false, NULL, NULL, false, NULL, &data);
22382 : 3 : restore_extension_diagnostics (ext);
22383 : : }
22384 : : else
22385 : 189 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
22386 : : false, NULL, NULL, false, NULL, &data);
22387 : : }
22388 : : }
22389 : :
22390 : : /* Finalize an OpenACC routine pragma, applying it to FNDECL.
22391 : : IS_DEFN is true if we're applying it to the definition. */
22392 : :
22393 : : static void
22394 : 327 : c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
22395 : : bool is_defn)
22396 : : {
22397 : : /* Keep going if we're in error reporting mode. */
22398 : 327 : if (data->error_seen
22399 : 321 : || fndecl == error_mark_node)
22400 : : return;
22401 : :
22402 : 321 : if (data->fndecl_seen)
22403 : : {
22404 : 4 : error_at (data->loc,
22405 : : "%<#pragma acc routine%> not immediately followed by"
22406 : : " a single function declaration or definition");
22407 : 4 : data->error_seen = true;
22408 : 4 : return;
22409 : : }
22410 : 317 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
22411 : : {
22412 : 10 : error_at (data->loc,
22413 : : "%<#pragma acc routine%> not immediately followed by"
22414 : : " function declaration or definition");
22415 : 10 : data->error_seen = true;
22416 : 10 : return;
22417 : : }
22418 : :
22419 : 307 : int compatible
22420 : 307 : = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
22421 : : "#pragma acc routine");
22422 : 307 : if (compatible < 0)
22423 : : {
22424 : 47 : data->error_seen = true;
22425 : 47 : return;
22426 : : }
22427 : 260 : if (compatible > 0)
22428 : : {
22429 : : }
22430 : : else
22431 : : {
22432 : 269 : if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
22433 : : {
22434 : 3 : error_at (data->loc,
22435 : : TREE_USED (fndecl)
22436 : : ? G_("%<#pragma acc routine%> must be applied before use")
22437 : : : G_("%<#pragma acc routine%> must be applied before"
22438 : : " definition"));
22439 : 2 : data->error_seen = true;
22440 : 2 : return;
22441 : : }
22442 : :
22443 : : /* Set the routine's level of parallelism. */
22444 : 197 : tree dims = oacc_build_routine_dims (data->clauses);
22445 : 197 : oacc_replace_fn_attrib (fndecl, dims);
22446 : :
22447 : : /* Add an "omp declare target" attribute. */
22448 : 197 : DECL_ATTRIBUTES (fndecl)
22449 : 394 : = tree_cons (get_identifier ("omp declare target"),
22450 : 197 : data->clauses, DECL_ATTRIBUTES (fndecl));
22451 : : }
22452 : :
22453 : : /* Remember that we've used this "#pragma acc routine". */
22454 : 258 : data->fndecl_seen = true;
22455 : : }
22456 : :
22457 : : /* OpenACC 2.0:
22458 : : # pragma acc update oacc-update-clause[optseq] new-line
22459 : : */
22460 : :
22461 : : #define OACC_UPDATE_CLAUSE_MASK \
22462 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22463 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
22464 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
22465 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22466 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
22467 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22468 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22469 : :
22470 : : static void
22471 : 92 : c_parser_oacc_update (c_parser *parser)
22472 : : {
22473 : 92 : location_t loc = c_parser_peek_token (parser)->location;
22474 : :
22475 : 92 : c_parser_consume_pragma (parser);
22476 : :
22477 : 92 : tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
22478 : : "#pragma acc update");
22479 : 92 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
22480 : : {
22481 : 1 : error_at (loc,
22482 : : "%<#pragma acc update%> must contain at least one "
22483 : : "%<device%> or %<host%> or %<self%> clause");
22484 : 1 : return;
22485 : : }
22486 : :
22487 : 91 : if (parser->error)
22488 : : return;
22489 : :
22490 : 91 : tree stmt = make_node (OACC_UPDATE);
22491 : 91 : TREE_TYPE (stmt) = void_type_node;
22492 : 91 : OACC_UPDATE_CLAUSES (stmt) = clauses;
22493 : 91 : SET_EXPR_LOCATION (stmt, loc);
22494 : 91 : add_stmt (stmt);
22495 : : }
22496 : :
22497 : : /* OpenACC 2.0:
22498 : : # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
22499 : :
22500 : : LOC is the location of the #pragma token.
22501 : : */
22502 : :
22503 : : #define OACC_WAIT_CLAUSE_MASK \
22504 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
22505 : :
22506 : : static tree
22507 : 80 : c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
22508 : : {
22509 : 80 : tree clauses, list = NULL_TREE, stmt = NULL_TREE;
22510 : :
22511 : 80 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
22512 : 43 : list = c_parser_oacc_wait_list (parser, loc, list);
22513 : :
22514 : 80 : strcpy (p_name, " wait");
22515 : 80 : clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, p_name);
22516 : 80 : stmt = c_finish_oacc_wait (loc, list, clauses);
22517 : 80 : add_stmt (stmt);
22518 : :
22519 : 80 : return stmt;
22520 : : }
22521 : :
22522 : : struct c_omp_loc_tree
22523 : : {
22524 : : location_t loc;
22525 : : tree var;
22526 : : };
22527 : :
22528 : : /* Check whether the expression used in the allocator clause is declared or
22529 : : modified between the variable declaration and its allocate directive. */
22530 : : static tree
22531 : 48 : c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
22532 : : {
22533 : 48 : tree var = ((struct c_omp_loc_tree *) data)->var;
22534 : 48 : location_t loc = ((struct c_omp_loc_tree *) data)->loc;
22535 : 48 : if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
22536 : : {
22537 : 10 : if (linemap_location_before_p (line_table, DECL_SOURCE_LOCATION (var),
22538 : 10 : DECL_SOURCE_LOCATION (*tp)))
22539 : : {
22540 : 2 : error_at (loc, "variable %qD used in the %<allocator%> clause must "
22541 : : "be declared before %qD", *tp, var);
22542 : 2 : inform (DECL_SOURCE_LOCATION (*tp), "declared here");
22543 : 2 : inform (DECL_SOURCE_LOCATION (var),
22544 : : "to be allocated variable declared here");
22545 : 2 : return *tp;
22546 : : }
22547 : : else
22548 : : {
22549 : 8 : gcc_assert (cur_stmt_list
22550 : : && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
22551 : :
22552 : 8 : tree_stmt_iterator l = tsi_last (cur_stmt_list);
22553 : 9 : while (!tsi_end_p (l))
22554 : : {
22555 : 9 : if (linemap_location_before_p (line_table, EXPR_LOCATION (*l),
22556 : 9 : DECL_SOURCE_LOCATION (var)))
22557 : : break;
22558 : 3 : if (TREE_CODE (*l) == MODIFY_EXPR
22559 : 3 : && TREE_OPERAND (*l, 0) == *tp)
22560 : : {
22561 : 2 : error_at (loc,
22562 : : "variable %qD used in the %<allocator%> clause "
22563 : : "must not be modified between declaration of %qD "
22564 : : "and its %<allocate%> directive", *tp, var);
22565 : 2 : inform (EXPR_LOCATION (*l), "modified here");
22566 : 2 : inform (DECL_SOURCE_LOCATION (var),
22567 : : "to be allocated variable declared here");
22568 : 2 : return *tp;
22569 : : }
22570 : 1 : --l;
22571 : : }
22572 : : }
22573 : : }
22574 : : return NULL_TREE;
22575 : : }
22576 : :
22577 : : /* OpenMP 5.x:
22578 : : # pragma omp allocate (list) clauses
22579 : :
22580 : : OpenMP 5.0 clause:
22581 : : allocator (omp_allocator_handle_t expression)
22582 : :
22583 : : OpenMP 5.1 additional clause:
22584 : : align (constant-expression)] */
22585 : :
22586 : : static void
22587 : 69 : c_parser_omp_allocate (c_parser *parser)
22588 : : {
22589 : 69 : tree alignment = NULL_TREE;
22590 : 69 : tree allocator = NULL_TREE;
22591 : 69 : c_parser_consume_pragma (parser);
22592 : 69 : location_t loc = c_parser_peek_token (parser)->location;
22593 : 69 : location_t allocator_loc = UNKNOWN_LOCATION;
22594 : 69 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
22595 : 215 : do
22596 : : {
22597 : 142 : if (c_parser_next_token_is (parser, CPP_COMMA)
22598 : 142 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22599 : 9 : c_parser_consume_token (parser);
22600 : 142 : if (!c_parser_next_token_is (parser, CPP_NAME))
22601 : : break;
22602 : 76 : matching_parens parens;
22603 : 76 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22604 : 76 : c_parser_consume_token (parser);
22605 : 76 : location_t expr_loc = c_parser_peek_token (parser)->location;
22606 : 76 : if (strcmp ("align", p) != 0 && strcmp ("allocator", p) != 0)
22607 : : {
22608 : 1 : error_at (c_parser_peek_token (parser)->location,
22609 : : "expected %<allocator%> or %<align%>");
22610 : 1 : break;
22611 : : }
22612 : 75 : if (!parens.require_open (parser))
22613 : : break;
22614 : :
22615 : 75 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
22616 : 75 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
22617 : 75 : expr_loc = c_parser_peek_token (parser)->location;
22618 : 75 : if (expr.value == error_mark_node)
22619 : : ;
22620 : 74 : else if (p[2] == 'i' && alignment)
22621 : : {
22622 : 1 : error_at (expr_loc, "too many %qs clauses", "align");
22623 : 1 : break;
22624 : : }
22625 : 73 : else if (p[2] == 'i')
22626 : : {
22627 : 32 : alignment = c_fully_fold (expr.value, false, NULL);
22628 : 32 : if (TREE_CODE (alignment) != INTEGER_CST
22629 : 31 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
22630 : 31 : || tree_int_cst_sgn (alignment) != 1
22631 : 62 : || !integer_pow2p (alignment))
22632 : : {
22633 : 4 : error_at (expr_loc, "%<align%> clause argument needs to be "
22634 : : "positive constant power of two integer "
22635 : : "expression");
22636 : 4 : alignment = NULL_TREE;
22637 : : }
22638 : : }
22639 : 41 : else if (allocator)
22640 : : {
22641 : 1 : error_at (expr_loc, "too many %qs clauses", "allocator");
22642 : 1 : break;
22643 : : }
22644 : : else
22645 : : {
22646 : 40 : allocator = c_fully_fold (expr.value, false, NULL);
22647 : 40 : allocator_loc = expr_loc;
22648 : 40 : tree orig_type
22649 : 40 : = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
22650 : 40 : orig_type = TYPE_MAIN_VARIANT (orig_type);
22651 : 41 : if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
22652 : 40 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
22653 : 118 : || TYPE_NAME (orig_type)
22654 : 39 : != get_identifier ("omp_allocator_handle_t"))
22655 : : {
22656 : 1 : error_at (expr_loc,
22657 : : "%<allocator%> clause allocator expression has type "
22658 : : "%qT rather than %<omp_allocator_handle_t%>",
22659 : 1 : TREE_TYPE (allocator));
22660 : 1 : allocator = NULL_TREE;
22661 : : }
22662 : : }
22663 : 73 : parens.skip_until_found_close (parser);
22664 : 73 : } while (true);
22665 : 69 : c_parser_skip_to_pragma_eol (parser);
22666 : :
22667 : 69 : c_mark_decl_jump_unsafe_in_current_scope ();
22668 : 149 : for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
22669 : : {
22670 : 80 : tree var = OMP_CLAUSE_DECL (c);
22671 : 80 : if (TREE_CODE (var) == PARM_DECL)
22672 : : {
22673 : 1 : error_at (OMP_CLAUSE_LOCATION (nl),
22674 : : "function parameter %qD may not appear as list item in an "
22675 : : "%<allocate%> directive", var);
22676 : 1 : continue;
22677 : : }
22678 : 79 : if (!parser->in_omp_decl_attribute && !c_check_in_current_scope (var))
22679 : : {
22680 : 2 : error_at (OMP_CLAUSE_LOCATION (nl),
22681 : : "%<allocate%> directive must be in the same scope as %qD",
22682 : : var);
22683 : 2 : inform (DECL_SOURCE_LOCATION (var), "declared here");
22684 : 2 : continue;
22685 : : }
22686 : 77 : if (lookup_attribute ("omp allocate", DECL_ATTRIBUTES (var)))
22687 : : {
22688 : 1 : error_at (OMP_CLAUSE_LOCATION (nl),
22689 : : "%qD already appeared as list item in an "
22690 : : "%<allocate%> directive", var);
22691 : 1 : continue;
22692 : : }
22693 : 76 : if (TREE_STATIC (var))
22694 : : {
22695 : 19 : if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
22696 : : {
22697 : 3 : error_at (loc,
22698 : : "%<allocator%> clause required for "
22699 : : "static variable %qD", var);
22700 : 3 : continue;
22701 : : }
22702 : 16 : else if (allocator
22703 : 16 : && (wi::to_widest (allocator) < 1
22704 : 15 : || wi::to_widest (allocator) > GOMP_OMP_PREDEF_ALLOC_MAX)
22705 : 23 : && (wi::to_widest (allocator) < GOMP_OMPX_PREDEF_ALLOC_MIN
22706 : 12 : || wi::to_widest (allocator) > GOMP_OMPX_PREDEF_ALLOC_MAX))
22707 : : {
22708 : 6 : error_at (allocator_loc,
22709 : : "%<allocator%> clause requires a predefined allocator as "
22710 : : "%qD is static", var);
22711 : : }
22712 : : }
22713 : 73 : if (allocator)
22714 : : {
22715 : 40 : struct c_omp_loc_tree data
22716 : 78 : = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), var};
22717 : 40 : walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
22718 : : }
22719 : 73 : DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
22720 : : build_tree_list (allocator, alignment),
22721 : 73 : DECL_ATTRIBUTES (var));
22722 : : }
22723 : 69 : }
22724 : :
22725 : : /* OpenMP 2.5:
22726 : : # pragma omp atomic new-line
22727 : : expression-stmt
22728 : :
22729 : : expression-stmt:
22730 : : x binop= expr | x++ | ++x | x-- | --x
22731 : : binop:
22732 : : +, *, -, /, &, ^, |, <<, >>
22733 : :
22734 : : where x is an lvalue expression with scalar type.
22735 : :
22736 : : OpenMP 3.1:
22737 : : # pragma omp atomic new-line
22738 : : update-stmt
22739 : :
22740 : : # pragma omp atomic read new-line
22741 : : read-stmt
22742 : :
22743 : : # pragma omp atomic write new-line
22744 : : write-stmt
22745 : :
22746 : : # pragma omp atomic update new-line
22747 : : update-stmt
22748 : :
22749 : : # pragma omp atomic capture new-line
22750 : : capture-stmt
22751 : :
22752 : : # pragma omp atomic capture new-line
22753 : : capture-block
22754 : :
22755 : : read-stmt:
22756 : : v = x
22757 : : write-stmt:
22758 : : x = expr
22759 : : update-stmt:
22760 : : expression-stmt | x = x binop expr
22761 : : capture-stmt:
22762 : : v = expression-stmt
22763 : : capture-block:
22764 : : { v = x; update-stmt; } | { update-stmt; v = x; }
22765 : :
22766 : : OpenMP 4.0:
22767 : : update-stmt:
22768 : : expression-stmt | x = x binop expr | x = expr binop x
22769 : : capture-stmt:
22770 : : v = update-stmt
22771 : : capture-block:
22772 : : { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
22773 : :
22774 : : OpenMP 5.1:
22775 : : # pragma omp atomic compare new-line
22776 : : conditional-update-atomic
22777 : :
22778 : : # pragma omp atomic compare capture new-line
22779 : : conditional-update-capture-atomic
22780 : :
22781 : : conditional-update-atomic:
22782 : : cond-expr-stmt | cond-update-stmt
22783 : : cond-expr-stmt:
22784 : : x = expr ordop x ? expr : x;
22785 : : x = x ordop expr ? expr : x;
22786 : : x = x == e ? d : x;
22787 : : cond-update-stmt:
22788 : : if (expr ordop x) { x = expr; }
22789 : : if (x ordop expr) { x = expr; }
22790 : : if (x == e) { x = d; }
22791 : : ordop:
22792 : : <, >
22793 : : conditional-update-capture-atomic:
22794 : : v = cond-expr-stmt
22795 : : { v = x; cond-expr-stmt }
22796 : : { cond-expr-stmt v = x; }
22797 : : { v = x; cond-update-stmt }
22798 : : { cond-update-stmt v = x; }
22799 : : if (x == e) { x = d; } else { v = x; }
22800 : : { r = x == e; if (r) { x = d; } }
22801 : : { r = x == e; if (r) { x = d; } else { v = x; } }
22802 : :
22803 : : where x, r and v are lvalue expressions with scalar type,
22804 : : expr, e and d are expressions with scalar type and e might be
22805 : : the same as v.
22806 : :
22807 : : LOC is the location of the #pragma token. */
22808 : :
22809 : : static void
22810 : 1718 : c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
22811 : : {
22812 : 1718 : tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
22813 : 1718 : tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
22814 : 1718 : tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
22815 : 1718 : enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
22816 : 1718 : enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
22817 : 1718 : struct c_expr expr;
22818 : 1718 : location_t eloc;
22819 : 1718 : bool structured_block = false;
22820 : 1718 : bool swapped = false;
22821 : 1718 : bool non_lvalue_p;
22822 : 1718 : tree clauses = NULL_TREE;
22823 : 1718 : bool capture = false;
22824 : 1718 : bool compare = false;
22825 : 1718 : bool weak = false;
22826 : 1718 : enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22827 : 1718 : bool no_semicolon = false;
22828 : 1718 : bool extra_scope = false;
22829 : :
22830 : 3197 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
22831 : : {
22832 : 1489 : if (c_parser_next_token_is (parser, CPP_COMMA)
22833 : 1489 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22834 : 82 : c_parser_consume_token (parser);
22835 : :
22836 : 1489 : if (c_parser_next_token_is (parser, CPP_NAME))
22837 : : {
22838 : 1485 : const char *p
22839 : 1485 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22840 : 1485 : location_t cloc = c_parser_peek_token (parser)->location;
22841 : 1485 : enum tree_code new_code = ERROR_MARK;
22842 : 1485 : enum omp_memory_order new_memory_order
22843 : : = OMP_MEMORY_ORDER_UNSPECIFIED;
22844 : 1485 : bool new_capture = false;
22845 : 1485 : bool new_compare = false;
22846 : 1485 : bool new_weak = false;
22847 : 1485 : enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22848 : :
22849 : 1485 : if (!strcmp (p, "read"))
22850 : : new_code = OMP_ATOMIC_READ;
22851 : 1227 : else if (!strcmp (p, "write"))
22852 : : new_code = NOP_EXPR;
22853 : 1050 : else if (!strcmp (p, "update"))
22854 : : new_code = OMP_ATOMIC;
22855 : 890 : else if (openacc && !strcmp (p, "capture"))
22856 : : new_code = OMP_ATOMIC_CAPTURE_NEW;
22857 : 4 : else if (openacc)
22858 : : {
22859 : 4 : p = NULL;
22860 : 4 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
22861 : : "or %<capture%> clause");
22862 : : }
22863 : 652 : else if (!strcmp (p, "capture"))
22864 : : new_capture = true;
22865 : 408 : else if (!strcmp (p, "compare"))
22866 : : new_compare = true;
22867 : 235 : else if (!strcmp (p, "weak"))
22868 : : new_weak = true;
22869 : 222 : else if (!strcmp (p, "fail"))
22870 : : {
22871 : 33 : matching_parens parens;
22872 : :
22873 : 33 : c_parser_consume_token (parser);
22874 : 33 : if (!parens.require_open (parser))
22875 : 1 : continue;
22876 : :
22877 : 32 : if (c_parser_next_token_is (parser, CPP_NAME))
22878 : : {
22879 : 30 : const char *q
22880 : 30 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22881 : :
22882 : 30 : if (!strcmp (q, "seq_cst"))
22883 : : new_fail = OMP_MEMORY_ORDER_SEQ_CST;
22884 : 24 : else if (!strcmp (q, "acquire"))
22885 : : new_fail = OMP_MEMORY_ORDER_ACQUIRE;
22886 : 17 : else if (!strcmp (q, "relaxed"))
22887 : : new_fail = OMP_MEMORY_ORDER_RELAXED;
22888 : : }
22889 : :
22890 : : if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
22891 : : {
22892 : 27 : c_parser_consume_token (parser);
22893 : 27 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
22894 : 2 : error_at (cloc, "too many %qs clauses", "fail");
22895 : : else
22896 : : fail = new_fail;
22897 : : }
22898 : : else
22899 : 5 : c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
22900 : : "or %<relaxed%>");
22901 : 32 : parens.skip_until_found_close (parser);
22902 : 32 : continue;
22903 : 32 : }
22904 : 189 : else if (!strcmp (p, "seq_cst"))
22905 : : new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
22906 : 112 : else if (!strcmp (p, "acq_rel"))
22907 : : new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
22908 : 100 : else if (!strcmp (p, "release"))
22909 : : new_memory_order = OMP_MEMORY_ORDER_RELEASE;
22910 : 70 : else if (!strcmp (p, "acquire"))
22911 : : new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
22912 : 57 : else if (!strcmp (p, "relaxed"))
22913 : : new_memory_order = OMP_MEMORY_ORDER_RELAXED;
22914 : 31 : else if (!strcmp (p, "hint"))
22915 : : {
22916 : 29 : c_parser_consume_token (parser);
22917 : 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
22918 : 29 : continue;
22919 : : }
22920 : : else
22921 : : {
22922 : 2 : p = NULL;
22923 : 2 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
22924 : : "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
22925 : : "%<seq_cst%>, %<acq_rel%>, %<release%>, "
22926 : : "%<relaxed%> or %<hint%> clause");
22927 : : }
22928 : 6 : if (p)
22929 : : {
22930 : 1417 : if (new_code != ERROR_MARK)
22931 : : {
22932 : : /* OpenACC permits 'update capture'. */
22933 : 829 : if (openacc
22934 : 829 : && code == OMP_ATOMIC
22935 : 4 : && new_code == OMP_ATOMIC_CAPTURE_NEW)
22936 : : code = new_code;
22937 : 826 : else if (code != ERROR_MARK)
22938 : 5 : error_at (cloc, "too many atomic clauses");
22939 : : else
22940 : : code = new_code;
22941 : : }
22942 : 588 : else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
22943 : : {
22944 : 158 : if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
22945 : 35 : error_at (cloc, "too many memory order clauses");
22946 : : else
22947 : : memory_order = new_memory_order;
22948 : : }
22949 : 430 : else if (new_capture)
22950 : : {
22951 : 244 : if (capture)
22952 : 1 : error_at (cloc, "too many %qs clauses", "capture");
22953 : : else
22954 : : capture = true;
22955 : : }
22956 : 186 : else if (new_compare)
22957 : : {
22958 : 173 : if (compare)
22959 : 1 : error_at (cloc, "too many %qs clauses", "compare");
22960 : : else
22961 : : compare = true;
22962 : : }
22963 : 13 : else if (new_weak)
22964 : : {
22965 : 13 : if (weak)
22966 : 1 : error_at (cloc, "too many %qs clauses", "weak");
22967 : : else
22968 : : weak = true;
22969 : : }
22970 : 1417 : c_parser_consume_token (parser);
22971 : 1417 : continue;
22972 : : }
22973 : : }
22974 : : break;
22975 : : }
22976 : 1718 : c_parser_skip_to_pragma_eol (parser);
22977 : :
22978 : 1718 : if (code == ERROR_MARK)
22979 : 897 : code = OMP_ATOMIC;
22980 : 1718 : if (capture)
22981 : : {
22982 : 243 : if (code != OMP_ATOMIC)
22983 : 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
22984 : : "clauses", "capture");
22985 : : else
22986 : : code = OMP_ATOMIC_CAPTURE_NEW;
22987 : : }
22988 : 1718 : if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
22989 : : {
22990 : 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
22991 : : "clauses", "compare");
22992 : 2 : compare = false;
22993 : : }
22994 : 1718 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
22995 : : {
22996 : 5 : error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
22997 : 5 : fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22998 : : }
22999 : 1718 : if (weak && !compare)
23000 : : {
23001 : 5 : error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
23002 : 5 : weak = false;
23003 : : }
23004 : 1718 : if (openacc)
23005 : : memory_order = OMP_MEMORY_ORDER_RELAXED;
23006 : 1409 : else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
23007 : : {
23008 : 1286 : omp_requires_mask
23009 : 1286 : = (enum omp_requires) (omp_requires_mask
23010 : : | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
23011 : 1286 : switch ((enum omp_memory_order)
23012 : : (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
23013 : : {
23014 : : case OMP_MEMORY_ORDER_UNSPECIFIED:
23015 : : case OMP_MEMORY_ORDER_RELAXED:
23016 : : memory_order = OMP_MEMORY_ORDER_RELAXED;
23017 : : break;
23018 : : case OMP_MEMORY_ORDER_SEQ_CST:
23019 : 9 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23020 : : break;
23021 : 4 : case OMP_MEMORY_ORDER_ACQUIRE:
23022 : 4 : if (code == NOP_EXPR) /* atomic write */
23023 : : {
23024 : 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23025 : : "%<acquire%> clause implicitly provided by a "
23026 : : "%<requires%> directive");
23027 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23028 : : }
23029 : : else
23030 : : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23031 : : break;
23032 : 3 : case OMP_MEMORY_ORDER_RELEASE:
23033 : 3 : if (code == OMP_ATOMIC_READ)
23034 : : {
23035 : 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23036 : : "%<release%> clause implicitly provided by a "
23037 : : "%<requires%> directive");
23038 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23039 : : }
23040 : : else
23041 : : memory_order = OMP_MEMORY_ORDER_RELEASE;
23042 : : break;
23043 : 9 : case OMP_MEMORY_ORDER_ACQ_REL:
23044 : 9 : switch (code)
23045 : : {
23046 : : case OMP_ATOMIC_READ:
23047 : : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23048 : : break;
23049 : : case NOP_EXPR: /* atomic write */
23050 : 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23051 : : break;
23052 : : default:
23053 : 1718 : memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23054 : : break;
23055 : : }
23056 : : break;
23057 : 0 : default:
23058 : 0 : gcc_unreachable ();
23059 : : }
23060 : : }
23061 : : else
23062 : 123 : switch (code)
23063 : : {
23064 : 25 : case OMP_ATOMIC_READ:
23065 : 25 : if (memory_order == OMP_MEMORY_ORDER_RELEASE)
23066 : : {
23067 : 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23068 : : "%<release%> clause");
23069 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23070 : : }
23071 : 24 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23072 : 6 : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23073 : : break;
23074 : 16 : case NOP_EXPR: /* atomic write */
23075 : 16 : if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
23076 : : {
23077 : 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23078 : : "%<acquire%> clause");
23079 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23080 : : }
23081 : 15 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23082 : 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23083 : : break;
23084 : : default:
23085 : : break;
23086 : : }
23087 : 1718 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23088 : 20 : memory_order
23089 : 20 : = (enum omp_memory_order) (memory_order
23090 : : | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
23091 : :
23092 : 1718 : switch (code)
23093 : : {
23094 : 434 : case OMP_ATOMIC_READ:
23095 : 434 : case NOP_EXPR: /* atomic write */
23096 : 434 : v = c_parser_cast_expression (parser, NULL).value;
23097 : 434 : non_lvalue_p = !lvalue_p (v);
23098 : 434 : v = c_fully_fold (v, false, NULL, true);
23099 : 434 : if (v == error_mark_node)
23100 : 0 : goto saw_error;
23101 : 434 : if (non_lvalue_p)
23102 : 4 : v = non_lvalue (v);
23103 : 434 : loc = c_parser_peek_token (parser)->location;
23104 : 434 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23105 : 0 : goto saw_error;
23106 : 434 : if (code == NOP_EXPR)
23107 : : {
23108 : 176 : eloc = c_parser_peek_token (parser)->location;
23109 : 176 : expr = c_parser_expression (parser);
23110 : 176 : expr = default_function_array_read_conversion (eloc, expr);
23111 : : /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
23112 : : opcode. */
23113 : 176 : code = OMP_ATOMIC;
23114 : 176 : lhs = v;
23115 : 176 : v = NULL_TREE;
23116 : 176 : rhs = c_fully_fold (expr.value, false, NULL);
23117 : 176 : if (rhs == error_mark_node)
23118 : 0 : goto saw_error;
23119 : : }
23120 : : else
23121 : : {
23122 : 258 : lhs = c_parser_cast_expression (parser, NULL).value;
23123 : 258 : non_lvalue_p = !lvalue_p (lhs);
23124 : 258 : lhs = c_fully_fold (lhs, false, NULL, true);
23125 : 258 : if (lhs == error_mark_node)
23126 : 0 : goto saw_error;
23127 : 258 : if (non_lvalue_p)
23128 : 2 : lhs = non_lvalue (lhs);
23129 : : }
23130 : 434 : goto done;
23131 : 473 : case OMP_ATOMIC_CAPTURE_NEW:
23132 : 473 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
23133 : : {
23134 : 314 : c_parser_consume_token (parser);
23135 : 314 : structured_block = true;
23136 : : }
23137 : 159 : else if (compare
23138 : 188 : && c_parser_next_token_is_keyword (parser, RID_IF))
23139 : : break;
23140 : : else
23141 : : {
23142 : 142 : v = c_parser_cast_expression (parser, NULL).value;
23143 : 142 : non_lvalue_p = !lvalue_p (v);
23144 : 142 : v = c_fully_fold (v, false, NULL, true);
23145 : 142 : if (v == error_mark_node)
23146 : 0 : goto saw_error;
23147 : 142 : if (non_lvalue_p)
23148 : 2 : v = non_lvalue (v);
23149 : 142 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23150 : 0 : goto saw_error;
23151 : 154 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23152 : : {
23153 : 1 : eloc = c_parser_peek_token (parser)->location;
23154 : 1 : error_at (eloc, "expected expression");
23155 : 1 : goto saw_error;
23156 : : }
23157 : : }
23158 : : break;
23159 : : default:
23160 : : break;
23161 : : }
23162 : :
23163 : : /* For structured_block case we don't know yet whether
23164 : : old or new x should be captured. */
23165 : 1283 : restart:
23166 : 1675 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23167 : : {
23168 : 85 : c_parser_consume_token (parser);
23169 : :
23170 : 85 : matching_parens parens;
23171 : 85 : if (!parens.require_open (parser))
23172 : 34 : goto saw_error;
23173 : 84 : eloc = c_parser_peek_token (parser)->location;
23174 : 84 : c_expr cmp_expr;
23175 : 84 : if (r)
23176 : : {
23177 : 17 : cmp_expr = c_parser_cast_expression (parser, NULL);
23178 : 17 : cmp_expr = default_function_array_conversion (eloc, cmp_expr);
23179 : : }
23180 : : else
23181 : 67 : cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
23182 : 84 : parens.skip_until_found_close (parser);
23183 : 84 : if (cmp_expr.value == error_mark_node)
23184 : 0 : goto saw_error;
23185 : 84 : if (r)
23186 : : {
23187 : 17 : if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
23188 : 1 : goto bad_if;
23189 : 16 : cmp_expr.value = rhs1;
23190 : 16 : rhs1 = NULL_TREE;
23191 : 16 : gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
23192 : : }
23193 : 83 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23194 : : ;
23195 : 36 : else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23196 : : {
23197 : 4 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23198 : : "expected %<==%> comparison in %<if%> condition");
23199 : 2 : goto saw_error;
23200 : : }
23201 : 34 : else if (TREE_CODE (cmp_expr.value) != GT_EXPR
23202 : 25 : && TREE_CODE (cmp_expr.value) != LT_EXPR)
23203 : : {
23204 : 16 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23205 : : "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
23206 : : "condition");
23207 : 10 : goto saw_error;
23208 : : }
23209 : 71 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
23210 : 2 : goto saw_error;
23211 : :
23212 : 69 : extra_scope = true;
23213 : 69 : eloc = c_parser_peek_token (parser)->location;
23214 : 69 : expr = c_parser_cast_expression (parser, NULL);
23215 : 69 : lhs = expr.value;
23216 : 69 : expr = default_function_array_conversion (eloc, expr);
23217 : 69 : unfolded_lhs = expr.value;
23218 : 69 : lhs = c_fully_fold (lhs, false, NULL, true);
23219 : 69 : orig_lhs = lhs;
23220 : 69 : if (lhs == error_mark_node)
23221 : 0 : goto saw_error;
23222 : 69 : if (!lvalue_p (unfolded_lhs))
23223 : 0 : lhs = non_lvalue (lhs);
23224 : 69 : if (!c_parser_next_token_is (parser, CPP_EQ))
23225 : : {
23226 : 1 : c_parser_error (parser, "expected %<=%>");
23227 : 1 : goto saw_error;
23228 : : }
23229 : 68 : c_parser_consume_token (parser);
23230 : 68 : eloc = c_parser_peek_token (parser)->location;
23231 : 68 : expr = c_parser_expr_no_commas (parser, NULL);
23232 : 68 : rhs1 = expr.value;
23233 : :
23234 : 68 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23235 : 1 : goto saw_error;
23236 : :
23237 : 67 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
23238 : 1 : goto saw_error;
23239 : :
23240 : 66 : extra_scope = false;
23241 : 66 : no_semicolon = true;
23242 : :
23243 : 66 : if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
23244 : : {
23245 : 59 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23246 : : {
23247 : 44 : opcode = COND_EXPR;
23248 : 44 : rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23249 : : false, NULL, true);
23250 : 44 : rhs1 = c_fully_fold (rhs1, false, NULL, true);
23251 : : }
23252 : 15 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
23253 : : {
23254 : 7 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23255 : 13 : ? MIN_EXPR : MAX_EXPR);
23256 : 13 : rhs = c_fully_fold (rhs1, false, NULL, true);
23257 : 13 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
23258 : : false, NULL, true);
23259 : : }
23260 : : else
23261 : 2 : goto bad_if;
23262 : : }
23263 : 7 : else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23264 : 2 : goto bad_if;
23265 : 5 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
23266 : 5 : && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
23267 : : {
23268 : 2 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23269 : 3 : ? MAX_EXPR : MIN_EXPR);
23270 : 3 : rhs = c_fully_fold (rhs1, false, NULL, true);
23271 : 3 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23272 : : false, NULL, true);
23273 : : }
23274 : : else
23275 : : {
23276 : 8 : bad_if:
23277 : 8 : c_parser_error (parser,
23278 : : "invalid form of %<#pragma omp atomic compare%>");
23279 : 8 : goto saw_error;
23280 : : }
23281 : :
23282 : 60 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
23283 : : {
23284 : 24 : if (code != OMP_ATOMIC_CAPTURE_NEW
23285 : 22 : || (structured_block && r == NULL_TREE)
23286 : 21 : || TREE_CODE (cmp_expr.value) != EQ_EXPR)
23287 : : {
23288 : 3 : eloc = c_parser_peek_token (parser)->location;
23289 : 3 : error_at (eloc, "unexpected %<else%>");
23290 : 3 : goto saw_error;
23291 : : }
23292 : :
23293 : 21 : c_parser_consume_token (parser);
23294 : :
23295 : 21 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
23296 : 1 : goto saw_error;
23297 : :
23298 : 20 : extra_scope = true;
23299 : 20 : v = c_parser_cast_expression (parser, NULL).value;
23300 : 20 : non_lvalue_p = !lvalue_p (v);
23301 : 20 : v = c_fully_fold (v, false, NULL, true);
23302 : 20 : if (v == error_mark_node)
23303 : 0 : goto saw_error;
23304 : 20 : if (non_lvalue_p)
23305 : 0 : v = non_lvalue (v);
23306 : 20 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23307 : 1 : goto saw_error;
23308 : :
23309 : 19 : expr = c_parser_expr_no_commas (parser, NULL);
23310 : :
23311 : 19 : if (!c_tree_equal (expr.value, unfolded_lhs))
23312 : 1 : goto bad_if;
23313 : :
23314 : 18 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23315 : 1 : goto saw_error;
23316 : :
23317 : 17 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
23318 : 0 : goto saw_error;
23319 : :
23320 : 17 : extra_scope = false;
23321 : 17 : code = OMP_ATOMIC_CAPTURE_OLD;
23322 : 17 : if (r == NULL_TREE)
23323 : : /* Signal to c_finish_omp_atomic that in
23324 : : if (x == e) { x = d; } else { v = x; }
23325 : : case the store to v should be conditional. */
23326 : 10 : r = void_list_node;
23327 : : }
23328 : 36 : else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23329 : : {
23330 : 1 : c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
23331 : 1 : goto saw_error;
23332 : : }
23333 : 35 : else if (code == OMP_ATOMIC_CAPTURE_NEW
23334 : 35 : && r != NULL_TREE
23335 : 9 : && v == NULL_TREE)
23336 : 52 : code = OMP_ATOMIC;
23337 : 52 : goto stmt_done;
23338 : : }
23339 : 1382 : eloc = c_parser_peek_token (parser)->location;
23340 : 1382 : expr = c_parser_cast_expression (parser, NULL);
23341 : 1382 : lhs = expr.value;
23342 : 1382 : expr = default_function_array_conversion (eloc, expr);
23343 : 1382 : unfolded_lhs = expr.value;
23344 : 1382 : lhs = c_fully_fold (lhs, false, NULL, true);
23345 : 1382 : orig_lhs = lhs;
23346 : 1382 : switch (TREE_CODE (lhs))
23347 : : {
23348 : 4 : invalid_compare:
23349 : 4 : error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
23350 : : /* FALLTHRU */
23351 : 84 : case ERROR_MARK:
23352 : 84 : saw_error:
23353 : 84 : c_parser_skip_to_end_of_block_or_statement (parser);
23354 : 90 : if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23355 : 4 : c_parser_consume_token (parser);
23356 : 84 : if (structured_block)
23357 : : {
23358 : 10 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23359 : 9 : c_parser_consume_token (parser);
23360 : 1 : else if (code == OMP_ATOMIC_CAPTURE_NEW)
23361 : : {
23362 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
23363 : 1 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23364 : 1 : c_parser_consume_token (parser);
23365 : : }
23366 : : }
23367 : 84 : return;
23368 : :
23369 : 158 : case POSTINCREMENT_EXPR:
23370 : 158 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23371 : 20 : code = OMP_ATOMIC_CAPTURE_OLD;
23372 : : /* FALLTHROUGH */
23373 : 220 : case PREINCREMENT_EXPR:
23374 : 220 : lhs = TREE_OPERAND (lhs, 0);
23375 : 220 : unfolded_lhs = NULL_TREE;
23376 : 220 : opcode = PLUS_EXPR;
23377 : 220 : rhs = integer_one_node;
23378 : 220 : if (compare)
23379 : 2 : goto invalid_compare;
23380 : : break;
23381 : :
23382 : 24 : case POSTDECREMENT_EXPR:
23383 : 24 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23384 : 2 : code = OMP_ATOMIC_CAPTURE_OLD;
23385 : : /* FALLTHROUGH */
23386 : 52 : case PREDECREMENT_EXPR:
23387 : 52 : lhs = TREE_OPERAND (lhs, 0);
23388 : 52 : unfolded_lhs = NULL_TREE;
23389 : 52 : opcode = MINUS_EXPR;
23390 : 52 : rhs = integer_one_node;
23391 : 52 : if (compare)
23392 : 2 : goto invalid_compare;
23393 : : break;
23394 : :
23395 : 12 : case COMPOUND_EXPR:
23396 : 12 : if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
23397 : 12 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
23398 : 12 : && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
23399 : 12 : && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
23400 : 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
23401 : : (TREE_OPERAND (lhs, 1), 0), 0))))
23402 : : /* Undo effects of boolean_increment for post {in,de}crement. */
23403 : 12 : lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
23404 : : /* FALLTHRU */
23405 : 24 : case MODIFY_EXPR:
23406 : 24 : if (TREE_CODE (lhs) == MODIFY_EXPR
23407 : 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
23408 : : {
23409 : : /* Undo effects of boolean_increment. */
23410 : 24 : if (integer_onep (TREE_OPERAND (lhs, 1)))
23411 : : {
23412 : : /* This is pre or post increment. */
23413 : 12 : rhs = TREE_OPERAND (lhs, 1);
23414 : 12 : lhs = TREE_OPERAND (lhs, 0);
23415 : 12 : unfolded_lhs = NULL_TREE;
23416 : 12 : opcode = NOP_EXPR;
23417 : 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
23418 : 12 : && !structured_block
23419 : 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23420 : 1 : code = OMP_ATOMIC_CAPTURE_OLD;
23421 : 12 : if (compare)
23422 : 0 : goto invalid_compare;
23423 : : break;
23424 : : }
23425 : 12 : if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
23426 : 12 : && TREE_OPERAND (lhs, 0)
23427 : 12 : == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
23428 : : {
23429 : : /* This is pre or post decrement. */
23430 : 12 : rhs = TREE_OPERAND (lhs, 1);
23431 : 12 : lhs = TREE_OPERAND (lhs, 0);
23432 : 12 : unfolded_lhs = NULL_TREE;
23433 : 12 : opcode = NOP_EXPR;
23434 : 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
23435 : 12 : && !structured_block
23436 : 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23437 : 1 : code = OMP_ATOMIC_CAPTURE_OLD;
23438 : 12 : if (compare)
23439 : 0 : goto invalid_compare;
23440 : : break;
23441 : : }
23442 : : }
23443 : : /* FALLTHRU */
23444 : 1082 : default:
23445 : 1082 : if (!lvalue_p (unfolded_lhs))
23446 : 5 : lhs = non_lvalue (lhs);
23447 : 1201 : if (compare && !c_parser_next_token_is (parser, CPP_EQ))
23448 : : {
23449 : 7 : c_parser_error (parser, "expected %<=%>");
23450 : 7 : goto saw_error;
23451 : : }
23452 : 1075 : switch (c_parser_peek_token (parser)->type)
23453 : : {
23454 : : case CPP_MULT_EQ:
23455 : : opcode = MULT_EXPR;
23456 : : break;
23457 : : case CPP_DIV_EQ:
23458 : : opcode = TRUNC_DIV_EXPR;
23459 : : break;
23460 : : case CPP_PLUS_EQ:
23461 : : opcode = PLUS_EXPR;
23462 : : break;
23463 : : case CPP_MINUS_EQ:
23464 : : opcode = MINUS_EXPR;
23465 : : break;
23466 : : case CPP_LSHIFT_EQ:
23467 : : opcode = LSHIFT_EXPR;
23468 : : break;
23469 : : case CPP_RSHIFT_EQ:
23470 : : opcode = RSHIFT_EXPR;
23471 : : break;
23472 : : case CPP_AND_EQ:
23473 : : opcode = BIT_AND_EXPR;
23474 : : break;
23475 : : case CPP_OR_EQ:
23476 : : opcode = BIT_IOR_EXPR;
23477 : : break;
23478 : : case CPP_XOR_EQ:
23479 : : opcode = BIT_XOR_EXPR;
23480 : : break;
23481 : 556 : case CPP_EQ:
23482 : 556 : c_parser_consume_token (parser);
23483 : 556 : eloc = c_parser_peek_token (parser)->location;
23484 : 556 : expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
23485 : 556 : rhs1 = expr.value;
23486 : 556 : switch (TREE_CODE (rhs1))
23487 : : {
23488 : 289 : case MULT_EXPR:
23489 : 289 : case TRUNC_DIV_EXPR:
23490 : 289 : case RDIV_EXPR:
23491 : 289 : case PLUS_EXPR:
23492 : 289 : case MINUS_EXPR:
23493 : 289 : case LSHIFT_EXPR:
23494 : 289 : case RSHIFT_EXPR:
23495 : 289 : case BIT_AND_EXPR:
23496 : 289 : case BIT_IOR_EXPR:
23497 : 289 : case BIT_XOR_EXPR:
23498 : 289 : if (compare)
23499 : : break;
23500 : 282 : if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
23501 : : {
23502 : 147 : opcode = TREE_CODE (rhs1);
23503 : 147 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23504 : : true);
23505 : 147 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23506 : : true);
23507 : 147 : goto stmt_done;
23508 : : }
23509 : 135 : if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
23510 : : {
23511 : 117 : opcode = TREE_CODE (rhs1);
23512 : 117 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23513 : : true);
23514 : 117 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23515 : : true);
23516 : 117 : swapped = !commutative_tree_code (opcode);
23517 : 117 : goto stmt_done;
23518 : : }
23519 : : break;
23520 : 69 : case COND_EXPR:
23521 : 69 : if (!compare)
23522 : : break;
23523 : 66 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
23524 : 44 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
23525 : 97 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
23526 : : break;
23527 : 63 : if (!TREE_OPERAND (rhs1, 1))
23528 : : break;
23529 : 63 : if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
23530 : : break;
23531 : 58 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23532 : : unfolded_lhs))
23533 : : {
23534 : 39 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23535 : : {
23536 : 23 : opcode = COND_EXPR;
23537 : 23 : rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23538 : : 0), 1),
23539 : : false, NULL, true);
23540 : 23 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
23541 : : NULL, true);
23542 : 23 : goto stmt_done;
23543 : : }
23544 : 16 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23545 : 16 : TREE_OPERAND (rhs1, 1)))
23546 : : {
23547 : 21 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23548 : 14 : ? MIN_EXPR : MAX_EXPR);
23549 : 14 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23550 : : true);
23551 : 14 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23552 : : 0), 0),
23553 : : false, NULL, true);
23554 : 14 : goto stmt_done;
23555 : : }
23556 : : }
23557 : 19 : else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23558 : : break;
23559 : 17 : else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23560 : : unfolded_lhs))
23561 : : {
23562 : 15 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23563 : 15 : TREE_OPERAND (rhs1, 1)))
23564 : : {
23565 : 18 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23566 : 15 : ? MAX_EXPR : MIN_EXPR);
23567 : 15 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23568 : : true);
23569 : 15 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23570 : : 0), 1),
23571 : : false, NULL, true);
23572 : 15 : goto stmt_done;
23573 : : }
23574 : : }
23575 : : break;
23576 : 17 : case EQ_EXPR:
23577 : 17 : if (!compare
23578 : 17 : || code != OMP_ATOMIC_CAPTURE_NEW
23579 : 17 : || !structured_block
23580 : 17 : || v
23581 : 17 : || r)
23582 : : break;
23583 : 17 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
23584 : 17 : && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
23585 : : {
23586 : 17 : r = lhs;
23587 : 17 : lhs = NULL_TREE;
23588 : 17 : c_parser_consume_token (parser);
23589 : 17 : goto restart;
23590 : : }
23591 : : break;
23592 : 0 : case ERROR_MARK:
23593 : 0 : goto saw_error;
23594 : : default:
23595 : : break;
23596 : : }
23597 : 223 : if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
23598 : : {
23599 : 223 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23600 : : {
23601 : 167 : code = OMP_ATOMIC_CAPTURE_OLD;
23602 : 167 : v = lhs;
23603 : 167 : lhs = NULL_TREE;
23604 : 167 : expr = default_function_array_read_conversion (eloc, expr);
23605 : 167 : unfolded_lhs1 = expr.value;
23606 : 167 : lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
23607 : 167 : rhs1 = NULL_TREE;
23608 : 167 : c_parser_consume_token (parser);
23609 : 167 : goto restart;
23610 : : }
23611 : 56 : if (structured_block && !compare)
23612 : : {
23613 : 26 : opcode = NOP_EXPR;
23614 : 26 : expr = default_function_array_read_conversion (eloc, expr);
23615 : 26 : rhs = c_fully_fold (expr.value, false, NULL, true);
23616 : 26 : rhs1 = NULL_TREE;
23617 : 26 : goto stmt_done;
23618 : : }
23619 : : }
23620 : 30 : c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
23621 : 30 : goto saw_error;
23622 : 5 : default:
23623 : 5 : c_parser_error (parser,
23624 : : "invalid operator for %<#pragma omp atomic%>");
23625 : 5 : goto saw_error;
23626 : : }
23627 : :
23628 : : /* Arrange to pass the location of the assignment operator to
23629 : : c_finish_omp_atomic. */
23630 : 514 : loc = c_parser_peek_token (parser)->location;
23631 : 514 : c_parser_consume_token (parser);
23632 : 514 : eloc = c_parser_peek_token (parser)->location;
23633 : 514 : expr = c_parser_expression (parser);
23634 : 514 : expr = default_function_array_read_conversion (eloc, expr);
23635 : 514 : rhs = expr.value;
23636 : 514 : rhs = c_fully_fold (rhs, false, NULL, true);
23637 : 514 : break;
23638 : : }
23639 : 1200 : stmt_done:
23640 : 1200 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
23641 : : {
23642 : 129 : if (!no_semicolon
23643 : 129 : && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23644 : 0 : goto saw_error;
23645 : 129 : no_semicolon = false;
23646 : 129 : v = c_parser_cast_expression (parser, NULL).value;
23647 : 129 : non_lvalue_p = !lvalue_p (v);
23648 : 129 : v = c_fully_fold (v, false, NULL, true);
23649 : 129 : if (v == error_mark_node)
23650 : 0 : goto saw_error;
23651 : 129 : if (non_lvalue_p)
23652 : 2 : v = non_lvalue (v);
23653 : 129 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23654 : 0 : goto saw_error;
23655 : 129 : eloc = c_parser_peek_token (parser)->location;
23656 : 129 : expr = c_parser_cast_expression (parser, NULL);
23657 : 129 : lhs1 = expr.value;
23658 : 129 : expr = default_function_array_read_conversion (eloc, expr);
23659 : 129 : unfolded_lhs1 = expr.value;
23660 : 129 : lhs1 = c_fully_fold (lhs1, false, NULL, true);
23661 : 129 : if (lhs1 == error_mark_node)
23662 : 0 : goto saw_error;
23663 : 129 : if (!lvalue_p (unfolded_lhs1))
23664 : 2 : lhs1 = non_lvalue (lhs1);
23665 : : }
23666 : 1200 : if (structured_block)
23667 : : {
23668 : 304 : if (!no_semicolon)
23669 : 280 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
23670 : 304 : c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
23671 : : }
23672 : 896 : done:
23673 : 1634 : if (weak && opcode != COND_EXPR)
23674 : : {
23675 : 1 : error_at (loc, "%<weak%> clause requires atomic equality comparison");
23676 : 1 : weak = false;
23677 : : }
23678 : 1634 : if (unfolded_lhs && unfolded_lhs1
23679 : 1634 : && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
23680 : : {
23681 : 5 : error ("%<#pragma omp atomic capture%> uses two different "
23682 : : "expressions for memory");
23683 : 5 : stmt = error_mark_node;
23684 : : }
23685 : : else
23686 : 1629 : stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
23687 : : swapped, memory_order, weak);
23688 : 1634 : if (stmt != error_mark_node)
23689 : 1604 : add_stmt (stmt);
23690 : :
23691 : 1634 : if (!structured_block && !no_semicolon)
23692 : 1311 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
23693 : : }
23694 : :
23695 : :
23696 : : /* OpenMP 2.5:
23697 : : # pragma omp barrier new-line
23698 : : */
23699 : :
23700 : : static void
23701 : 348 : c_parser_omp_barrier (c_parser *parser)
23702 : : {
23703 : 348 : location_t loc = c_parser_peek_token (parser)->location;
23704 : 348 : c_parser_consume_pragma (parser);
23705 : 348 : c_parser_skip_to_pragma_eol (parser);
23706 : :
23707 : 348 : c_finish_omp_barrier (loc);
23708 : 348 : }
23709 : :
23710 : : /* OpenMP 2.5:
23711 : : # pragma omp critical [(name)] new-line
23712 : : structured-block
23713 : :
23714 : : OpenMP 4.5:
23715 : : # pragma omp critical [(name) [hint(expression)]] new-line
23716 : :
23717 : : LOC is the location of the #pragma itself. */
23718 : :
23719 : : #define OMP_CRITICAL_CLAUSE_MASK \
23720 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
23721 : :
23722 : : static tree
23723 : 144 : c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
23724 : : {
23725 : 144 : tree stmt, name = NULL_TREE, clauses = NULL_TREE;
23726 : :
23727 : 144 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
23728 : : {
23729 : 49 : c_parser_consume_token (parser);
23730 : 49 : if (c_parser_next_token_is (parser, CPP_NAME))
23731 : : {
23732 : 48 : name = c_parser_peek_token (parser)->value;
23733 : 48 : c_parser_consume_token (parser);
23734 : 48 : c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
23735 : : }
23736 : : else
23737 : 1 : c_parser_error (parser, "expected identifier");
23738 : :
23739 : 49 : if (c_parser_next_token_is (parser, CPP_COMMA)
23740 : 49 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23741 : 4 : c_parser_consume_token (parser);
23742 : : }
23743 : 144 : clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
23744 : : "#pragma omp critical");
23745 : 144 : stmt = c_parser_omp_structured_block (parser, if_p);
23746 : 144 : return c_finish_omp_critical (loc, stmt, name, clauses);
23747 : : }
23748 : :
23749 : : /* OpenMP 5.0:
23750 : : # pragma omp depobj ( depobj ) depobj-clause new-line
23751 : :
23752 : : depobj-clause:
23753 : : depend (dependence-type : locator)
23754 : : destroy
23755 : : update (dependence-type)
23756 : :
23757 : : OpenMP 5.2 additionally:
23758 : : destroy ( depobj )
23759 : :
23760 : : dependence-type:
23761 : : in
23762 : : out
23763 : : inout
23764 : : mutexinout */
23765 : :
23766 : : static void
23767 : 75 : c_parser_omp_depobj (c_parser *parser)
23768 : : {
23769 : 75 : location_t loc = c_parser_peek_token (parser)->location;
23770 : 75 : c_parser_consume_pragma (parser);
23771 : 75 : matching_parens parens;
23772 : 75 : if (!parens.require_open (parser))
23773 : : {
23774 : 3 : c_parser_skip_to_pragma_eol (parser);
23775 : 3 : return;
23776 : : }
23777 : :
23778 : 72 : tree depobj = c_parser_expr_no_commas (parser, NULL).value;
23779 : 72 : if (depobj != error_mark_node)
23780 : : {
23781 : 71 : if (!lvalue_p (depobj))
23782 : : {
23783 : 1 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
23784 : : "%<depobj%> expression is not lvalue expression");
23785 : 1 : depobj = error_mark_node;
23786 : : }
23787 : : else
23788 : : {
23789 : 123 : tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
23790 : : depobj, false);
23791 : 70 : if (addr == error_mark_node)
23792 : : depobj = error_mark_node;
23793 : : else
23794 : 123 : depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
23795 : : addr, RO_UNARY_STAR);
23796 : : }
23797 : : }
23798 : :
23799 : 72 : parens.skip_until_found_close (parser);
23800 : 72 : tree clause = NULL_TREE;
23801 : 72 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
23802 : 72 : if (c_parser_next_token_is (parser, CPP_COMMA))
23803 : 3 : c_parser_consume_token (parser);
23804 : 72 : location_t c_loc = c_parser_peek_token (parser)->location;
23805 : 72 : if (c_parser_next_token_is (parser, CPP_NAME))
23806 : : {
23807 : 71 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23808 : :
23809 : 71 : c_parser_consume_token (parser);
23810 : 71 : if (!strcmp ("depend", p))
23811 : : {
23812 : 38 : clause = c_parser_omp_clause_depend (parser, NULL_TREE);
23813 : 38 : clause = c_finish_omp_clauses (clause, C_ORT_OMP);
23814 : 38 : if (!clause)
23815 : 2 : clause = error_mark_node;
23816 : : }
23817 : 33 : else if (!strcmp ("destroy", p))
23818 : : {
23819 : 22 : matching_parens c_parens;
23820 : 22 : kind = OMP_CLAUSE_DEPEND_LAST;
23821 : 22 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
23822 : 22 : && c_parens.require_open (parser))
23823 : : {
23824 : 7 : tree destobj = c_parser_expr_no_commas (parser, NULL).value;
23825 : 7 : if (!lvalue_p (destobj))
23826 : 1 : error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
23827 : : "%<destroy%> expression is not lvalue expression");
23828 : 6 : else if (depobj != error_mark_node
23829 : 6 : && !operand_equal_p (destobj, depobj,
23830 : : OEP_MATCH_SIDE_EFFECTS
23831 : : | OEP_LEXICOGRAPHIC))
23832 : 4 : warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
23833 : : "the %<destroy%> expression %qE should be the same "
23834 : : "as the %<depobj%> argument %qE", destobj, depobj);
23835 : 7 : c_parens.skip_until_found_close (parser);
23836 : : }
23837 : : }
23838 : 11 : else if (!strcmp ("update", p))
23839 : : {
23840 : 10 : matching_parens c_parens;
23841 : 10 : if (c_parens.require_open (parser))
23842 : : {
23843 : 10 : location_t c2_loc = c_parser_peek_token (parser)->location;
23844 : 10 : if (c_parser_next_token_is (parser, CPP_NAME))
23845 : : {
23846 : 10 : const char *p2
23847 : 10 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23848 : :
23849 : 10 : c_parser_consume_token (parser);
23850 : 10 : if (!strcmp ("in", p2))
23851 : : kind = OMP_CLAUSE_DEPEND_IN;
23852 : 8 : else if (!strcmp ("out", p2))
23853 : : kind = OMP_CLAUSE_DEPEND_OUT;
23854 : 7 : else if (!strcmp ("inout", p2))
23855 : : kind = OMP_CLAUSE_DEPEND_INOUT;
23856 : 4 : else if (!strcmp ("mutexinoutset", p2))
23857 : : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
23858 : 3 : else if (!strcmp ("inoutset", p2))
23859 : : kind = OMP_CLAUSE_DEPEND_INOUTSET;
23860 : : }
23861 : : if (kind == OMP_CLAUSE_DEPEND_INVALID)
23862 : : {
23863 : 1 : clause = error_mark_node;
23864 : 1 : error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
23865 : : "%<mutexinoutset%> or %<inoutset%>");
23866 : : }
23867 : 10 : c_parens.skip_until_found_close (parser);
23868 : : }
23869 : : else
23870 : 0 : clause = error_mark_node;
23871 : : }
23872 : : }
23873 : 72 : if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
23874 : : {
23875 : 2 : clause = error_mark_node;
23876 : 2 : error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
23877 : : }
23878 : 72 : c_parser_skip_to_pragma_eol (parser);
23879 : :
23880 : 72 : c_finish_omp_depobj (loc, depobj, kind, clause);
23881 : : }
23882 : :
23883 : :
23884 : : /* OpenMP 2.5:
23885 : : # pragma omp flush flush-vars[opt] new-line
23886 : :
23887 : : flush-vars:
23888 : : ( variable-list )
23889 : :
23890 : : OpenMP 5.0:
23891 : : # pragma omp flush memory-order-clause new-line */
23892 : :
23893 : : static void
23894 : 61 : c_parser_omp_flush (c_parser *parser)
23895 : : {
23896 : 61 : location_t loc = c_parser_peek_token (parser)->location;
23897 : 61 : c_parser_consume_pragma (parser);
23898 : 61 : enum memmodel mo = MEMMODEL_LAST;
23899 : 61 : if (c_parser_next_token_is (parser, CPP_COMMA)
23900 : 61 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23901 : 8 : c_parser_consume_token (parser);
23902 : 61 : if (c_parser_next_token_is (parser, CPP_NAME))
23903 : : {
23904 : 27 : const char *p
23905 : 27 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23906 : :
23907 : 27 : if (!strcmp (p, "seq_cst"))
23908 : : mo = MEMMODEL_SEQ_CST;
23909 : 21 : else if (!strcmp (p, "acq_rel"))
23910 : : mo = MEMMODEL_ACQ_REL;
23911 : 15 : else if (!strcmp (p, "release"))
23912 : : mo = MEMMODEL_RELEASE;
23913 : 9 : else if (!strcmp (p, "acquire"))
23914 : : mo = MEMMODEL_ACQUIRE;
23915 : : else
23916 : 3 : error_at (c_parser_peek_token (parser)->location,
23917 : : "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
23918 : : "%<acquire%>");
23919 : 27 : c_parser_consume_token (parser);
23920 : : }
23921 : 61 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
23922 : : {
23923 : 20 : if (mo != MEMMODEL_LAST)
23924 : 4 : error_at (c_parser_peek_token (parser)->location,
23925 : : "%<flush%> list specified together with memory order "
23926 : : "clause");
23927 : 20 : c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
23928 : : }
23929 : 41 : else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
23930 : 1 : c_parser_error (parser, "expected %<(%> or end of line");
23931 : 61 : c_parser_skip_to_pragma_eol (parser);
23932 : :
23933 : 61 : c_finish_omp_flush (loc, mo);
23934 : 61 : }
23935 : :
23936 : : /* Return true if next tokens contain a standard attribute that contains
23937 : : omp::directive (DIRECTIVE). */
23938 : :
23939 : : static bool
23940 : 363 : c_parser_omp_section_scan (c_parser *parser, const char *directive,
23941 : : bool tentative)
23942 : : {
23943 : 363 : if (!c_parser_nth_token_starts_std_attributes (parser, 1))
23944 : : return false;
23945 : 36 : unsigned int n = 3;
23946 : 36 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
23947 : : return false;
23948 : 36 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
23949 : 36 : if (token->type != CPP_CLOSE_SQUARE)
23950 : : return false;
23951 : 36 : token = c_parser_peek_nth_token_raw (parser, n + 1);
23952 : 36 : if (token->type != CPP_CLOSE_SQUARE)
23953 : : return false;
23954 : 36 : if (n < 9)
23955 : : return false;
23956 : 35 : if (c_parser_peek_nth_token_raw (parser, 3)->type == CPP_NAME
23957 : 35 : && c_parser_peek_nth_token_raw (parser, 4)->type == CPP_OPEN_PAREN
23958 : 35 : && c_parser_peek_nth_token_raw (parser, 5)->type == CPP_NAME)
23959 : : {
23960 : 0 : tree first = c_parser_peek_nth_token_raw (parser, 3)->value;
23961 : 0 : tree second = c_parser_peek_nth_token_raw (parser, 5)->value;
23962 : 0 : if (strcmp (IDENTIFIER_POINTER (first), "directive")
23963 : 0 : && strcmp (IDENTIFIER_POINTER (first), "__directive__"))
23964 : : return false;
23965 : 0 : if (strcmp (IDENTIFIER_POINTER (second), directive))
23966 : : return false;
23967 : : }
23968 : 35 : if (tentative)
23969 : : return true;
23970 : 32 : location_t first_loc = c_parser_peek_token (parser)->location;
23971 : 32 : location_t last_loc = c_parser_peek_nth_token_raw (parser, n + 1)->location;
23972 : 32 : location_t middle_loc = UNKNOWN_LOCATION;
23973 : 32 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
23974 : 32 : bool seen = false;
23975 : 32 : int cnt = 0;
23976 : 67 : for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
23977 : 35 : if (is_attribute_namespace_p ("omp", attr)
23978 : 35 : && is_attribute_p ("directive", get_attribute_name (attr)))
23979 : : {
23980 : 68 : for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
23981 : : {
23982 : 36 : tree d = TREE_VALUE (a);
23983 : 36 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
23984 : 36 : c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
23985 : 36 : cnt++;
23986 : 36 : if (first->type == CPP_NAME
23987 : 36 : && strcmp (IDENTIFIER_POINTER (first->value),
23988 : : directive) == 0)
23989 : : {
23990 : 31 : seen = true;
23991 : 31 : if (middle_loc == UNKNOWN_LOCATION)
23992 : 31 : middle_loc = first->location;
23993 : : }
23994 : : }
23995 : : }
23996 : 32 : if (!seen)
23997 : : return false;
23998 : 31 : if (cnt != 1 || TREE_CHAIN (std_attrs))
23999 : : {
24000 : 7 : error_at (make_location (first_loc, last_loc, middle_loc),
24001 : : "%<[[omp::directive(%s)]]%> must be the only specified "
24002 : : "attribute on a statement", directive);
24003 : 7 : return false;
24004 : : }
24005 : 24 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
24006 : 24 : return true;
24007 : : }
24008 : :
24009 : : /* Parse an OpenMP structured block sequence. KIND is the corresponding
24010 : : separating directive. */
24011 : :
24012 : : static tree
24013 : 815 : c_parser_omp_structured_block_sequence (c_parser *parser,
24014 : : enum pragma_kind kind)
24015 : : {
24016 : 815 : tree stmt = push_stmt_list ();
24017 : 815 : c_parser_statement (parser, NULL);
24018 : 909 : do
24019 : : {
24020 : 862 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24021 : : break;
24022 : 461 : if (c_parser_next_token_is (parser, CPP_EOF))
24023 : : break;
24024 : :
24025 : 461 : if (kind != PRAGMA_NONE
24026 : 461 : && c_parser_peek_token (parser)->pragma_kind == kind)
24027 : : break;
24028 : :
24029 : 69 : if (kind != PRAGMA_NONE
24030 : 104 : && c_parser_omp_section_scan (parser,
24031 : : kind == PRAGMA_OMP_SCAN
24032 : : ? "scan" : "section", false))
24033 : : break;
24034 : :
24035 : 47 : c_parser_statement (parser, NULL);
24036 : : }
24037 : : while (1);
24038 : 815 : return pop_stmt_list (stmt);
24039 : : }
24040 : :
24041 : : /* OpenMP 5.0:
24042 : :
24043 : : scan-loop-body:
24044 : : { structured-block scan-directive structured-block } */
24045 : :
24046 : : static void
24047 : 264 : c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
24048 : : {
24049 : 264 : tree substmt;
24050 : 264 : location_t loc;
24051 : 264 : tree clauses = NULL_TREE;
24052 : 264 : bool found_scan = false;
24053 : :
24054 : 264 : loc = c_parser_peek_token (parser)->location;
24055 : 264 : if (!open_brace_parsed
24056 : 264 : && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
24057 : : {
24058 : : /* Avoid skipping until the end of the block. */
24059 : 1 : parser->error = false;
24060 : 1 : return;
24061 : : }
24062 : :
24063 : 263 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
24064 : 261 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
24065 : : else
24066 : : {
24067 : 2 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24068 : : "%<#pragma omp scan%> with zero preceding executable "
24069 : : "statements");
24070 : 2 : substmt = build_empty_stmt (loc);
24071 : : }
24072 : 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
24073 : 263 : SET_EXPR_LOCATION (substmt, loc);
24074 : 263 : add_stmt (substmt);
24075 : :
24076 : 263 : loc = c_parser_peek_token (parser)->location;
24077 : 263 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
24078 : : {
24079 : 256 : enum omp_clause_code clause = OMP_CLAUSE_ERROR;
24080 : 256 : found_scan = true;
24081 : :
24082 : 256 : c_parser_consume_pragma (parser);
24083 : :
24084 : 256 : if (c_parser_next_token_is (parser, CPP_COMMA))
24085 : 4 : c_parser_consume_token (parser);
24086 : :
24087 : 256 : if (c_parser_next_token_is (parser, CPP_NAME))
24088 : : {
24089 : 254 : const char *p
24090 : 254 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24091 : 254 : if (strcmp (p, "inclusive") == 0)
24092 : : clause = OMP_CLAUSE_INCLUSIVE;
24093 : 126 : else if (strcmp (p, "exclusive") == 0)
24094 : : clause = OMP_CLAUSE_EXCLUSIVE;
24095 : : }
24096 : : if (clause != OMP_CLAUSE_ERROR)
24097 : : {
24098 : 254 : c_parser_consume_token (parser);
24099 : 254 : clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
24100 : : }
24101 : : else
24102 : 2 : c_parser_error (parser, "expected %<inclusive%> or "
24103 : : "%<exclusive%> clause");
24104 : 256 : c_parser_skip_to_pragma_eol (parser);
24105 : : }
24106 : : else
24107 : 7 : error ("expected %<#pragma omp scan%>");
24108 : :
24109 : 263 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24110 : 263 : if (!c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24111 : 254 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
24112 : : else
24113 : : {
24114 : 9 : if (found_scan)
24115 : 2 : warning_at (loc, OPT_Wopenmp,
24116 : : "%<#pragma omp scan%> with zero succeeding executable "
24117 : : "statements");
24118 : 9 : substmt = build_empty_stmt (loc);
24119 : : }
24120 : 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
24121 : 263 : SET_EXPR_LOCATION (substmt, loc);
24122 : 263 : add_stmt (substmt);
24123 : :
24124 : 263 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
24125 : : "expected %<}%>");
24126 : : }
24127 : :
24128 : :
24129 : : /* Check if the next tokens can start a canonical loop. Return true if yes,
24130 : : otherwise diagnose an error if ERROR_P is true, and return false. */
24131 : : static bool
24132 : 17284 : c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser,
24133 : : enum tree_code code,
24134 : : bool error_p)
24135 : : {
24136 : 17284 : if (code == OACC_LOOP)
24137 : : {
24138 : 2581 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24139 : : return true;
24140 : 27 : if (error_p)
24141 : 4 : c_parser_error (parser, "for statement expected");
24142 : : }
24143 : : else
24144 : : {
24145 : 14703 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24146 : : return true;
24147 : :
24148 : 887 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
24149 : 578 : switch (c_parser_peek_token (parser)->pragma_kind)
24150 : : {
24151 : : case PRAGMA_OMP_UNROLL:
24152 : : case PRAGMA_OMP_TILE:
24153 : : return true;
24154 : : default:
24155 : : break;
24156 : : }
24157 : :
24158 : : /* Skip standard attributes on next for in case they are
24159 : : [[omp::directive (unroll partial (4))]] or
24160 : : [[omp::directive (tile sizes (1, 2, 3))]] etc. */
24161 : 319 : size_t n = c_parser_skip_std_attribute_spec_seq (parser, 1);
24162 : 319 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
24163 : : /* TOKEN is a raw token that hasn't been converted to a keyword yet,
24164 : : we have to do the lookup explicitly. */
24165 : 319 : if (token->type == CPP_NAME
24166 : 108 : && C_IS_RESERVED_WORD (token->value)
24167 : 331 : && C_RID_CODE (token->value) == RID_FOR)
24168 : : return true;
24169 : 307 : if (error_p)
24170 : 7 : c_parser_error (parser, "loop nest expected");
24171 : : }
24172 : :
24173 : : return false;
24174 : : }
24175 : :
24176 : : static tree c_parser_omp_tile (location_t, c_parser *, bool *);
24177 : : static tree c_parser_omp_unroll (location_t, c_parser *, bool *);
24178 : :
24179 : : /* This function parses a single level of a loop nest, invoking itself
24180 : : recursively if necessary.
24181 : :
24182 : : loop-nest :: for (...) loop-body
24183 : : loop-body :: loop-nest
24184 : : | { [intervening-code] loop-body [intervening-code] }
24185 : : | final-loop-body
24186 : : intervening-code :: structured-block-sequence
24187 : : final-loop-body :: structured-block
24188 : :
24189 : : For a collapsed loop nest, only a single OMP_FOR is built, pulling out
24190 : : all the iterator information from the inner loops into the
24191 : : parser->omp_for_parse_state structure.
24192 : :
24193 : : The iterator decl, init, cond, and incr are stored in vectors.
24194 : :
24195 : : Initialization code for iterator variables is collected into
24196 : : parser->omp_for_parse_state->pre_body and ends up inserted directly
24197 : : into the OMP_FOR structure. */
24198 : :
24199 : : static tree
24200 : 16950 : c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
24201 : : {
24202 : 16950 : tree decl = NULL_TREE, cond = NULL_TREE, incr = NULL_TREE, init = NULL_TREE;
24203 : 16950 : tree body = NULL_TREE;
24204 : 16950 : matching_parens parens;
24205 : 16950 : bool moreloops;
24206 : 16950 : unsigned char save_in_statement;
24207 : 16950 : tree loop_scope;
24208 : 16950 : location_t loc;
24209 : 16950 : struct omp_for_parse_data *omp_for_parse_state
24210 : : = parser->omp_for_parse_state;
24211 : 16950 : gcc_assert (omp_for_parse_state);
24212 : 16950 : int depth = omp_for_parse_state->depth;
24213 : :
24214 : : /* Arrange for C23 standard attribute syntax to be parsed as regular
24215 : : pragmas. */
24216 : 16950 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
24217 : : {
24218 : 12 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24219 : 12 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
24220 : 12 : if (std_attrs)
24221 : 0 : error_at (c_parser_peek_token (parser)->location,
24222 : : "attributes other than OpenMP directives "
24223 : : "are not allowed on %<for%> in loop nest");
24224 : : }
24225 : :
24226 : 16950 : loc = c_parser_peek_token (parser)->location;
24227 : :
24228 : : /* Handle loop transformations first. */
24229 : 16950 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
24230 : : {
24231 : 576 : tree transform = NULL_TREE, sizes, body = NULL_TREE;
24232 : 576 : int count = 0;
24233 : 576 : switch (c_parser_peek_token (parser)->pragma_kind)
24234 : : {
24235 : 208 : case PRAGMA_OMP_UNROLL:
24236 : 208 : c_parser_consume_pragma (parser);
24237 : 208 : body = push_stmt_list ();
24238 : 208 : transform = c_parser_omp_unroll (loc, parser, if_p);
24239 : 208 : body = pop_stmt_list (body);
24240 : 208 : if (transform == NULL_TREE || transform == error_mark_node)
24241 : : {
24242 : 7 : transform = error_mark_node;
24243 : 7 : break;
24244 : : }
24245 : 201 : gcc_assert (TREE_CODE (transform) == OMP_UNROLL);
24246 : 201 : if (omp_find_clause (OMP_FOR_CLAUSES (transform),
24247 : : OMP_CLAUSE_PARTIAL))
24248 : : {
24249 : 172 : if (omp_for_parse_state->count - depth > 1)
24250 : : {
24251 : 10 : error_at (loc, "%<unroll%> construct with %<partial%> "
24252 : : "clause generates just one loop with "
24253 : : "canonical form but %d loops are needed",
24254 : : omp_for_parse_state->count - depth);
24255 : 10 : transform = error_mark_node;
24256 : : }
24257 : : else
24258 : 576 : count = 1;
24259 : : }
24260 : : else
24261 : : {
24262 : 29 : error_at (loc, "generated loop of %<unroll%> construct "
24263 : : "without %<partial%> clause does not have "
24264 : : "canonical form");
24265 : 29 : transform = error_mark_node;
24266 : : }
24267 : : break;
24268 : 366 : case PRAGMA_OMP_TILE:
24269 : 366 : c_parser_consume_pragma (parser);
24270 : 366 : body = push_stmt_list ();
24271 : 366 : transform = c_parser_omp_tile (loc, parser, if_p);
24272 : 366 : body = pop_stmt_list (body);
24273 : 366 : if (transform == NULL_TREE || transform == error_mark_node)
24274 : : {
24275 : 40 : transform = error_mark_node;
24276 : 40 : break;
24277 : : }
24278 : 326 : gcc_assert (TREE_CODE (transform) == OMP_TILE);
24279 : 326 : sizes = omp_find_clause (OMP_FOR_CLAUSES (transform),
24280 : : OMP_CLAUSE_SIZES);
24281 : 326 : gcc_assert (sizes);
24282 : 326 : count = list_length (OMP_CLAUSE_SIZES_LIST (sizes));
24283 : 326 : if (depth + count < omp_for_parse_state->count)
24284 : : {
24285 : 16 : error_at (loc, "%<tile%> construct generates %d loops "
24286 : : "with canonical form but %d loops are needed",
24287 : : count, omp_for_parse_state->count - depth);
24288 : 16 : transform = error_mark_node;
24289 : : }
24290 : : break;
24291 : 2 : default:
24292 : 2 : c_parser_pragma (parser, pragma_stmt, NULL, void_list_node);
24293 : 2 : break;
24294 : : }
24295 : 576 : if (transform == NULL_TREE)
24296 : 2 : error_at (loc, "expected %<for%> loop or OpenMP loop "
24297 : : "transformation construct");
24298 : 576 : if (transform == NULL_TREE || transform == error_mark_node)
24299 : : {
24300 : 104 : omp_for_parse_state->fail = true;
24301 : 104 : return NULL_TREE;
24302 : : }
24303 : 1030 : for (count = omp_for_parse_state->count; depth < count; ++depth)
24304 : : {
24305 : 558 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE;
24306 : 558 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE;
24307 : 558 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE;
24308 : 558 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE;
24309 : : }
24310 : 472 : omp_for_parse_state->want_nested_loop = false;
24311 : 472 : return body;
24312 : : }
24313 : :
24314 : : /* We have already matched the FOR token but not consumed it yet. */
24315 : 16374 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
24316 : 16374 : c_parser_consume_token (parser);
24317 : :
24318 : : /* Forbid break/continue in the loop initializer, condition, and
24319 : : increment expressions. */
24320 : 16374 : save_in_statement = in_statement;
24321 : 16374 : in_statement = IN_OMP_BLOCK;
24322 : :
24323 : : /* We are not in intervening code now. */
24324 : 16374 : omp_for_parse_state->in_intervening_code = false;
24325 : :
24326 : 16374 : if (!parens.require_open (parser))
24327 : : {
24328 : 0 : omp_for_parse_state->fail = true;
24329 : 0 : return NULL_TREE;
24330 : : }
24331 : :
24332 : : /* An implicit scope block surrounds each level of FOR loop, for
24333 : : declarations of iteration variables at this loop depth. */
24334 : 16374 : loop_scope = c_begin_compound_stmt (true);
24335 : :
24336 : : /* Parse the initialization declaration or expression. */
24337 : 16374 : if (c_parser_next_tokens_start_declaration (parser))
24338 : : {
24339 : : /* This is a declaration, which must be added to the pre_body code. */
24340 : 4737 : tree this_pre_body = push_stmt_list ();
24341 : 4737 : c_in_omp_for = true;
24342 : 4737 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
24343 : : false);
24344 : 4737 : c_in_omp_for = false;
24345 : 4737 : this_pre_body = pop_stmt_list (this_pre_body);
24346 : 4737 : append_to_statement_list_force (this_pre_body,
24347 : : &(omp_for_parse_state->pre_body));
24348 : 4737 : decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
24349 : 4737 : if (decl == NULL)
24350 : 0 : goto error_init;
24351 : 4737 : if (DECL_INITIAL (decl) == error_mark_node)
24352 : 1 : decl = error_mark_node;
24353 : : init = decl;
24354 : : }
24355 : 11637 : else if (c_parser_next_token_is (parser, CPP_NAME)
24356 : 11637 : && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
24357 : : {
24358 : 11635 : struct c_expr decl_exp;
24359 : 11635 : struct c_expr init_exp;
24360 : 11635 : location_t init_loc;
24361 : :
24362 : 11635 : decl_exp = c_parser_postfix_expression (parser);
24363 : 11635 : decl = decl_exp.value;
24364 : :
24365 : 11635 : c_parser_require (parser, CPP_EQ, "expected %<=%>");
24366 : :
24367 : 11635 : init_loc = c_parser_peek_token (parser)->location;
24368 : 11635 : init_exp = c_parser_expr_no_commas (parser, NULL);
24369 : 11635 : init_exp = default_function_array_read_conversion (init_loc,
24370 : : init_exp);
24371 : 11635 : c_in_omp_for = true;
24372 : 11635 : init = build_modify_expr (init_loc, decl, decl_exp.original_type,
24373 : : NOP_EXPR, init_loc, init_exp.value,
24374 : : init_exp.original_type);
24375 : 11635 : c_in_omp_for = false;
24376 : 11635 : init = c_process_expr_stmt (init_loc, init);
24377 : :
24378 : 11635 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24379 : : }
24380 : : else
24381 : : {
24382 : 2 : error_init:
24383 : 2 : c_parser_error (parser,
24384 : : "expected iteration declaration or initialization");
24385 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
24386 : : "expected %<)%>");
24387 : 2 : omp_for_parse_state->fail = true;
24388 : 2 : goto parse_next;
24389 : : }
24390 : :
24391 : : /* Parse the loop condition. */
24392 : 16372 : if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
24393 : : {
24394 : 16370 : location_t cond_loc = c_parser_peek_token (parser)->location;
24395 : 16370 : c_in_omp_for = true;
24396 : 16370 : struct c_expr cond_expr
24397 : 16370 : = c_parser_binary_expression (parser, NULL, NULL_TREE);
24398 : 16370 : c_in_omp_for = false;
24399 : :
24400 : 16370 : cond = cond_expr.value;
24401 : 16370 : cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
24402 : 16370 : switch (cond_expr.original_code)
24403 : : {
24404 : : case GT_EXPR:
24405 : : case GE_EXPR:
24406 : : case LT_EXPR:
24407 : : case LE_EXPR:
24408 : : break;
24409 : 2425 : case NE_EXPR:
24410 : 2425 : if (omp_for_parse_state->code != OACC_LOOP)
24411 : : break;
24412 : : /* FALLTHRU. */
24413 : 7 : default:
24414 : : /* Can't be cond = error_mark_node, because we want to preserve
24415 : : the location until c_finish_omp_for. */
24416 : 7 : cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
24417 : 7 : break;
24418 : : }
24419 : 16370 : protected_set_expr_location (cond, cond_loc);
24420 : : }
24421 : 16372 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24422 : :
24423 : : /* Parse the increment expression. */
24424 : 16372 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
24425 : : {
24426 : 16372 : location_t incr_loc = c_parser_peek_token (parser)->location;
24427 : :
24428 : 16372 : incr = c_process_expr_stmt (incr_loc,
24429 : 32744 : c_parser_expression (parser).value);
24430 : : }
24431 : 16372 : parens.skip_until_found_close (parser);
24432 : :
24433 : 16372 : if (decl == NULL || decl == error_mark_node || init == error_mark_node)
24434 : 3 : omp_for_parse_state->fail = true;
24435 : : else
24436 : : {
24437 : 16369 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
24438 : 16369 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
24439 : 16369 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
24440 : 16369 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
24441 : : }
24442 : :
24443 : 16374 : parse_next:
24444 : 16374 : moreloops = depth < omp_for_parse_state->count - 1;
24445 : 16374 : omp_for_parse_state->want_nested_loop = moreloops;
24446 : 16374 : if (moreloops
24447 : 16374 : && c_parser_omp_next_tokens_can_be_canon_loop (parser,
24448 : : omp_for_parse_state->code,
24449 : : false))
24450 : : {
24451 : 5323 : omp_for_parse_state->depth++;
24452 : 5323 : body = c_parser_omp_loop_nest (parser, if_p);
24453 : 5323 : omp_for_parse_state->depth--;
24454 : : }
24455 : 11191 : else if (moreloops && c_parser_next_token_is (parser, CPP_OPEN_BRACE))
24456 : : {
24457 : : /* This is the open brace in the loop-body grammar production. Rather
24458 : : than trying to special-case braces, just parse it as a compound
24459 : : statement and handle the nested loop-body case there. Note that
24460 : : when we see a further open brace inside the compound statement
24461 : : loop-body, we don't know whether it is the start of intervening
24462 : : code that is a compound statement, or a level of braces
24463 : : surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
24464 : : bit to ensure we have only one nested loop at each level. */
24465 : 121 : omp_for_parse_state->in_intervening_code = true;
24466 : 121 : body = c_parser_compound_statement (parser, NULL);
24467 : 121 : omp_for_parse_state->in_intervening_code = false;
24468 : 121 : if (omp_for_parse_state->want_nested_loop)
24469 : : {
24470 : : /* We have already parsed the whole loop body and not found a
24471 : : nested loop. */
24472 : 11 : error_at (omp_for_parse_state->for_loc,
24473 : : "not enough nested loops");
24474 : 11 : omp_for_parse_state->fail = true;
24475 : : }
24476 : 16374 : if_p = NULL;
24477 : : }
24478 : : else
24479 : : {
24480 : : /* This is the final-loop-body case in the grammar: we have
24481 : : something that is not a FOR and not an open brace. */
24482 : 10930 : if (moreloops)
24483 : : {
24484 : : /* If we were expecting a nested loop, give an error and mark
24485 : : that parsing has failed, and try to recover by parsing the
24486 : : body as regular code without further collapsing. */
24487 : 19 : error_at (omp_for_parse_state->for_loc,
24488 : : "not enough nested loops");
24489 : 19 : omp_for_parse_state->fail = true;
24490 : : }
24491 : 10930 : in_statement = IN_OMP_FOR;
24492 : 10930 : parser->omp_for_parse_state = NULL;
24493 : 10930 : body = push_stmt_list ();
24494 : 10930 : if (omp_for_parse_state->inscan)
24495 : 264 : c_parser_omp_scan_loop_body (parser, false);
24496 : : else
24497 : 10666 : add_stmt (c_parser_c99_block_statement (parser, if_p));
24498 : 10930 : body = pop_stmt_list (body);
24499 : 10930 : parser->omp_for_parse_state = omp_for_parse_state;
24500 : : }
24501 : 16374 : in_statement = save_in_statement;
24502 : 16374 : omp_for_parse_state->want_nested_loop = false;
24503 : 16374 : omp_for_parse_state->in_intervening_code = true;
24504 : :
24505 : : /* Pop and return the implicit scope surrounding this level of loop.
24506 : : If the iteration variable at this depth was bound in the for loop,
24507 : : pull out and save the binding. Later in c_parser_omp_for_loop,
24508 : : these bindings will be moved to the scope surrounding the entire
24509 : : OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
24510 : : we have already resolved all references to the iteration variable
24511 : : in its true scope. */
24512 : 16374 : if (body)
24513 : 16368 : add_stmt (body);
24514 : 16374 : body = c_end_compound_stmt (loc, loop_scope, true);
24515 : 16374 : if (decl && TREE_CODE (body) == BIND_EXPR)
24516 : : {
24517 : 5123 : tree t = BIND_EXPR_VARS (body);
24518 : 5123 : tree prev = NULL_TREE, next = NULL_TREE;
24519 : 5559 : while (t)
24520 : : {
24521 : 5172 : next = DECL_CHAIN (t);
24522 : 5172 : if (t == decl)
24523 : : {
24524 : 4736 : if (prev)
24525 : 0 : DECL_CHAIN (prev) = next;
24526 : : else
24527 : : {
24528 : 4736 : BIND_EXPR_VARS (body) = next;
24529 : 4736 : BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
24530 : : }
24531 : 4736 : DECL_CHAIN (t) = omp_for_parse_state->bindings;
24532 : 4736 : omp_for_parse_state->bindings = t;
24533 : 4736 : break;
24534 : : }
24535 : : else
24536 : : {
24537 : : prev = t;
24538 : : t = next;
24539 : : }
24540 : : }
24541 : 5123 : if (BIND_EXPR_VARS (body) == NULL_TREE)
24542 : 4736 : body = BIND_EXPR_BODY (body);
24543 : : }
24544 : :
24545 : : return body;
24546 : : }
24547 : :
24548 : : /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
24549 : : The real trick here is to determine the loop control variable early
24550 : : so that we can push a new decl if necessary to make it private.
24551 : : LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
24552 : : respectively. */
24553 : :
24554 : : static tree
24555 : 11528 : c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
24556 : : tree clauses, tree *cclauses, bool *if_p)
24557 : : {
24558 : 11528 : tree body, stmt, cl;
24559 : 11528 : tree ret = NULL_TREE;
24560 : 11528 : tree ordered_cl = NULL_TREE;
24561 : 11528 : int i, collapse = 1, ordered = 0, count;
24562 : 11528 : bool oacc_tiling = false;
24563 : 11528 : bool inscan = false;
24564 : 11528 : struct omp_for_parse_data data;
24565 : 11528 : struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
24566 : :
24567 : 27442 : for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
24568 : 15914 : if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
24569 : 2945 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
24570 : 12969 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
24571 : : {
24572 : 111 : oacc_tiling = true;
24573 : 111 : collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
24574 : : }
24575 : 12858 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES)
24576 : 464 : collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl));
24577 : 12394 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
24578 : 12394 : && OMP_CLAUSE_ORDERED_EXPR (cl))
24579 : : {
24580 : 160 : ordered_cl = cl;
24581 : 160 : ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
24582 : : }
24583 : 12234 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
24584 : 2106 : && OMP_CLAUSE_REDUCTION_INSCAN (cl)
24585 : 12619 : && (code == OMP_SIMD || code == OMP_FOR))
24586 : : inscan = true;
24587 : :
24588 : 11528 : if (ordered && ordered < collapse)
24589 : : {
24590 : 2 : error_at (OMP_CLAUSE_LOCATION (ordered_cl),
24591 : : "%<ordered%> clause parameter is less than %<collapse%>");
24592 : 2 : OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
24593 : 2 : = build_int_cst (NULL_TREE, collapse);
24594 : 2 : ordered = collapse;
24595 : : }
24596 : :
24597 : 11528 : gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0));
24598 : 11528 : count = ordered ? ordered : collapse;
24599 : :
24600 : 11528 : if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, true))
24601 : : return NULL;
24602 : :
24603 : : /* Initialize parse state for recursive descent. */
24604 : 11517 : data.declv = make_tree_vec (count);
24605 : 11517 : data.initv = make_tree_vec (count);
24606 : 11517 : data.condv = make_tree_vec (count);
24607 : 11517 : data.incrv = make_tree_vec (count);
24608 : 11517 : data.pre_body = NULL_TREE;
24609 : 11517 : data.bindings = NULL_TREE;
24610 : 11517 : data.for_loc = c_parser_peek_token (parser)->location;
24611 : 11517 : data.count = count;
24612 : 11517 : data.depth = 0;
24613 : 11517 : data.want_nested_loop = true;
24614 : 11517 : data.ordered = ordered > 0;
24615 : 11517 : data.in_intervening_code = false;
24616 : 11517 : data.perfect_nesting_fail = false;
24617 : 11517 : data.fail = false;
24618 : 11517 : data.inscan = inscan;
24619 : 11517 : data.saw_intervening_code = false;
24620 : 11517 : data.code = code;
24621 : 11517 : parser->omp_for_parse_state = &data;
24622 : :
24623 : 11517 : body = c_parser_omp_loop_nest (parser, if_p);
24624 : :
24625 : : /* Add saved bindings for iteration variables that were declared in
24626 : : the nested for loop to the scope surrounding the entire loop. */
24627 : 16253 : for (tree t = data.bindings; t; )
24628 : : {
24629 : 4736 : tree n = TREE_CHAIN (t);
24630 : 4736 : TREE_CHAIN (t) = NULL_TREE;
24631 : 4736 : pushdecl (t);
24632 : 4736 : t = n;
24633 : : }
24634 : :
24635 : : /* Only bother calling c_finish_omp_for if we haven't already generated
24636 : : an error from the initialization parsing. */
24637 : 11517 : if (!data.fail)
24638 : : {
24639 : 11354 : c_in_omp_for = true;
24640 : 11354 : stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
24641 : : data.condv, data.incrv,
24642 : : body, data.pre_body, true);
24643 : 11354 : c_in_omp_for = false;
24644 : :
24645 : : /* Check for iterators appearing in lb, b or incr expressions. */
24646 : 11354 : if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
24647 : : stmt = NULL_TREE;
24648 : :
24649 : : /* Check for errors involving lb/ub/incr expressions referencing
24650 : : variables declared in intervening code. */
24651 : 11354 : if (data.saw_intervening_code
24652 : 38 : && stmt
24653 : 11392 : && !c_omp_check_loop_binding_exprs (stmt, NULL))
24654 : : stmt = NULL_TREE;
24655 : :
24656 : 11344 : if (stmt)
24657 : : {
24658 : 11199 : add_stmt (stmt);
24659 : :
24660 : 27271 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
24661 : : {
24662 : 16530 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
24663 : 16530 : if (init == NULL_TREE)
24664 : : break;
24665 : 16072 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
24666 : 16072 : tree decl = TREE_OPERAND (init, 0);
24667 : 16072 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
24668 : 16072 : gcc_assert (COMPARISON_CLASS_P (cond));
24669 : 16072 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
24670 : :
24671 : 16072 : tree op0 = TREE_OPERAND (init, 1);
24672 : 16072 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
24673 : 16072 : || TREE_CODE (op0) != TREE_VEC)
24674 : 15885 : TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
24675 : : else
24676 : : {
24677 : 187 : TREE_VEC_ELT (op0, 1)
24678 : 187 : = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
24679 : 187 : TREE_VEC_ELT (op0, 2)
24680 : 374 : = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
24681 : : }
24682 : :
24683 : 16072 : tree op1 = TREE_OPERAND (cond, 1);
24684 : 16072 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
24685 : 16072 : || TREE_CODE (op1) != TREE_VEC)
24686 : 15866 : TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
24687 : : else
24688 : : {
24689 : 206 : TREE_VEC_ELT (op1, 1)
24690 : 206 : = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
24691 : 206 : TREE_VEC_ELT (op1, 2)
24692 : 412 : = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
24693 : : }
24694 : : }
24695 : :
24696 : 11199 : if (cclauses != NULL
24697 : 5257 : && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
24698 : : {
24699 : 755 : tree *c;
24700 : 3313 : for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
24701 : 2558 : if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
24702 : 2558 : && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
24703 : 1858 : c = &OMP_CLAUSE_CHAIN (*c);
24704 : : else
24705 : : {
24706 : 1441 : for (i = 0; i < count; i++)
24707 : 923 : if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
24708 : : break;
24709 : 700 : if (i == count)
24710 : 518 : c = &OMP_CLAUSE_CHAIN (*c);
24711 : 182 : else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
24712 : : {
24713 : 1 : error_at (loc,
24714 : : "iteration variable %qD should not be firstprivate",
24715 : 1 : OMP_CLAUSE_DECL (*c));
24716 : 1 : *c = OMP_CLAUSE_CHAIN (*c);
24717 : : }
24718 : : else
24719 : : {
24720 : : /* Move lastprivate (decl) clause to
24721 : : OMP_FOR_CLAUSES. */
24722 : 181 : tree l = *c;
24723 : 181 : *c = OMP_CLAUSE_CHAIN (*c);
24724 : 181 : if (code == OMP_SIMD)
24725 : : {
24726 : 46 : OMP_CLAUSE_CHAIN (l)
24727 : 46 : = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24728 : 46 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
24729 : : }
24730 : : else
24731 : : {
24732 : 135 : OMP_CLAUSE_CHAIN (l) = clauses;
24733 : 135 : clauses = l;
24734 : : }
24735 : : }
24736 : : }
24737 : : }
24738 : 11199 : OMP_FOR_CLAUSES (stmt) = clauses;
24739 : : }
24740 : : ret = stmt;
24741 : : }
24742 : :
24743 : 11517 : parser->omp_for_parse_state = save_data;
24744 : 11517 : return ret;
24745 : : }
24746 : :
24747 : : /* Helper function for OpenMP parsing, split clauses and call
24748 : : finish_omp_clauses on each of the set of clauses afterwards. */
24749 : :
24750 : : static void
24751 : 6563 : omp_split_clauses (location_t loc, enum tree_code code,
24752 : : omp_clause_mask mask, tree clauses, tree *cclauses)
24753 : : {
24754 : 6563 : int i;
24755 : 6563 : c_omp_split_clauses (loc, code, mask, clauses, cclauses);
24756 : 52504 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
24757 : 39378 : if (cclauses[i])
24758 : 20226 : cclauses[i] = c_finish_omp_clauses (cclauses[i],
24759 : : i == C_OMP_CLAUSE_SPLIT_TARGET
24760 : : ? C_ORT_OMP_TARGET : C_ORT_OMP);
24761 : 6563 : }
24762 : :
24763 : : /* OpenMP 5.0:
24764 : : #pragma omp loop loop-clause[optseq] new-line
24765 : : for-loop
24766 : :
24767 : : LOC is the location of the #pragma token.
24768 : : */
24769 : :
24770 : : #define OMP_LOOP_CLAUSE_MASK \
24771 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24772 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24773 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24774 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24775 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
24776 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24777 : :
24778 : : static tree
24779 : 237 : c_parser_omp_loop (location_t loc, c_parser *parser,
24780 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24781 : : bool *if_p)
24782 : : {
24783 : 237 : tree block, clauses, ret;
24784 : :
24785 : 237 : strcat (p_name, " loop");
24786 : 237 : mask |= OMP_LOOP_CLAUSE_MASK;
24787 : :
24788 : 237 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
24789 : 237 : if (cclauses)
24790 : : {
24791 : 80 : omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses);
24792 : 80 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
24793 : : }
24794 : :
24795 : 237 : block = c_begin_compound_stmt (true);
24796 : 237 : ret = c_parser_omp_for_loop (loc, parser, OMP_LOOP, clauses, cclauses, if_p);
24797 : 237 : block = c_end_compound_stmt (loc, block, true);
24798 : 237 : add_stmt (block);
24799 : :
24800 : 237 : return ret;
24801 : : }
24802 : :
24803 : : /* OpenMP 4.0:
24804 : : #pragma omp simd simd-clause[optseq] new-line
24805 : : for-loop
24806 : :
24807 : : LOC is the location of the #pragma token.
24808 : : */
24809 : :
24810 : : #define OMP_SIMD_CLAUSE_MASK \
24811 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
24812 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
24813 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24814 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
24815 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24816 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24817 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24818 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24819 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
24820 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
24821 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24822 : :
24823 : : static tree
24824 : 3506 : c_parser_omp_simd (location_t loc, c_parser *parser,
24825 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24826 : : bool *if_p)
24827 : : {
24828 : 3506 : tree block, clauses, ret;
24829 : :
24830 : 3506 : strcat (p_name, " simd");
24831 : 3506 : mask |= OMP_SIMD_CLAUSE_MASK;
24832 : :
24833 : 3506 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
24834 : 3506 : if (cclauses)
24835 : : {
24836 : 2780 : omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
24837 : 2780 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
24838 : : }
24839 : :
24840 : 3506 : block = c_begin_compound_stmt (true);
24841 : 3506 : ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
24842 : 3506 : block = c_end_compound_stmt (loc, block, true);
24843 : 3506 : add_stmt (block);
24844 : :
24845 : 3506 : return ret;
24846 : : }
24847 : :
24848 : : /* OpenMP 2.5:
24849 : : #pragma omp for for-clause[optseq] new-line
24850 : : for-loop
24851 : :
24852 : : OpenMP 4.0:
24853 : : #pragma omp for simd for-simd-clause[optseq] new-line
24854 : : for-loop
24855 : :
24856 : : LOC is the location of the #pragma token.
24857 : : */
24858 : :
24859 : : #define OMP_FOR_CLAUSE_MASK \
24860 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24861 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
24862 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24863 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24864 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24865 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
24866 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
24867 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24868 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
24869 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
24870 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24871 : :
24872 : : static tree
24873 : 6177 : c_parser_omp_for (location_t loc, c_parser *parser,
24874 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24875 : : bool *if_p)
24876 : : {
24877 : 6177 : tree block, clauses, ret;
24878 : :
24879 : 6177 : strcat (p_name, " for");
24880 : 6177 : mask |= OMP_FOR_CLAUSE_MASK;
24881 : : /* parallel for{, simd} disallows nowait clause, but for
24882 : : target {teams distribute ,}parallel for{, simd} it should be accepted. */
24883 : 6177 : if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
24884 : 3246 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
24885 : : /* Composite distribute parallel for{, simd} disallows ordered clause. */
24886 : 6177 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
24887 : 2724 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
24888 : :
24889 : 6177 : if (c_parser_next_token_is (parser, CPP_NAME))
24890 : : {
24891 : 5429 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24892 : :
24893 : 5429 : if (strcmp (p, "simd") == 0)
24894 : : {
24895 : 2202 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
24896 : 2202 : if (cclauses == NULL)
24897 : 300 : cclauses = cclauses_buf;
24898 : :
24899 : 2202 : c_parser_consume_token (parser);
24900 : 2202 : if (!flag_openmp) /* flag_openmp_simd */
24901 : 14 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
24902 : 14 : if_p);
24903 : 2188 : block = c_begin_compound_stmt (true);
24904 : 2188 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
24905 : 2188 : block = c_end_compound_stmt (loc, block, true);
24906 : 2188 : if (ret == NULL_TREE)
24907 : : return ret;
24908 : 2177 : ret = make_node (OMP_FOR);
24909 : 2177 : TREE_TYPE (ret) = void_type_node;
24910 : 2177 : OMP_FOR_BODY (ret) = block;
24911 : 2177 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24912 : 2177 : SET_EXPR_LOCATION (ret, loc);
24913 : 2177 : add_stmt (ret);
24914 : 2177 : return ret;
24915 : : }
24916 : : }
24917 : 3975 : if (!flag_openmp) /* flag_openmp_simd */
24918 : : {
24919 : 9 : c_parser_skip_to_pragma_eol (parser, false);
24920 : 9 : return NULL_TREE;
24921 : : }
24922 : :
24923 : : /* Composite distribute parallel for disallows linear clause. */
24924 : 3966 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
24925 : 1371 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
24926 : :
24927 : 3966 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
24928 : 3966 : if (cclauses)
24929 : : {
24930 : 2461 : omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
24931 : 2461 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24932 : : }
24933 : :
24934 : 3966 : block = c_begin_compound_stmt (true);
24935 : 3966 : ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
24936 : 3966 : block = c_end_compound_stmt (loc, block, true);
24937 : 3966 : add_stmt (block);
24938 : :
24939 : 3966 : return ret;
24940 : : }
24941 : :
24942 : : static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
24943 : : omp_clause_mask, tree *, bool *);
24944 : :
24945 : : /* OpenMP 2.5:
24946 : : # pragma omp master new-line
24947 : : structured-block
24948 : :
24949 : : LOC is the location of the #pragma token.
24950 : : */
24951 : :
24952 : : static tree
24953 : 231 : c_parser_omp_master (location_t loc, c_parser *parser,
24954 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24955 : : bool *if_p)
24956 : : {
24957 : 231 : tree block, clauses, ret;
24958 : :
24959 : 231 : strcat (p_name, " master");
24960 : :
24961 : 231 : if (c_parser_next_token_is (parser, CPP_NAME))
24962 : : {
24963 : 123 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24964 : :
24965 : 123 : if (strcmp (p, "taskloop") == 0)
24966 : : {
24967 : 94 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
24968 : 94 : if (cclauses == NULL)
24969 : 47 : cclauses = cclauses_buf;
24970 : :
24971 : 94 : c_parser_consume_token (parser);
24972 : 94 : if (!flag_openmp) /* flag_openmp_simd */
24973 : 4 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
24974 : 4 : if_p);
24975 : 90 : block = c_begin_compound_stmt (true);
24976 : 90 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
24977 : : if_p);
24978 : 90 : block = c_end_compound_stmt (loc, block, true);
24979 : 90 : if (ret == NULL_TREE)
24980 : : return ret;
24981 : 90 : ret = c_finish_omp_master (loc, block);
24982 : 90 : OMP_MASTER_COMBINED (ret) = 1;
24983 : 90 : return ret;
24984 : : }
24985 : : }
24986 : 137 : if (!flag_openmp) /* flag_openmp_simd */
24987 : : {
24988 : 2 : c_parser_skip_to_pragma_eol (parser, false);
24989 : 2 : return NULL_TREE;
24990 : : }
24991 : :
24992 : 135 : if (cclauses)
24993 : : {
24994 : 41 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
24995 : 41 : omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
24996 : : }
24997 : : else
24998 : 94 : c_parser_skip_to_pragma_eol (parser);
24999 : :
25000 : 135 : return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
25001 : 135 : if_p));
25002 : : }
25003 : :
25004 : : /* OpenMP 5.1:
25005 : : # pragma omp masked masked-clauses new-line
25006 : : structured-block
25007 : :
25008 : : LOC is the location of the #pragma token.
25009 : : */
25010 : :
25011 : : #define OMP_MASKED_CLAUSE_MASK \
25012 : : (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
25013 : :
25014 : : static tree
25015 : 116 : c_parser_omp_masked (location_t loc, c_parser *parser,
25016 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25017 : : bool *if_p)
25018 : : {
25019 : 116 : tree block, clauses, ret;
25020 : :
25021 : 116 : strcat (p_name, " masked");
25022 : 116 : mask |= OMP_MASKED_CLAUSE_MASK;
25023 : :
25024 : 116 : if (c_parser_next_token_is (parser, CPP_NAME))
25025 : : {
25026 : 86 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25027 : :
25028 : 86 : if (strcmp (p, "taskloop") == 0)
25029 : : {
25030 : 67 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25031 : 67 : if (cclauses == NULL)
25032 : 20 : cclauses = cclauses_buf;
25033 : :
25034 : 67 : c_parser_consume_token (parser);
25035 : 67 : if (!flag_openmp) /* flag_openmp_simd */
25036 : 0 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25037 : 0 : if_p);
25038 : 67 : block = c_begin_compound_stmt (true);
25039 : 67 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25040 : : if_p);
25041 : 67 : block = c_end_compound_stmt (loc, block, true);
25042 : 67 : if (ret == NULL_TREE)
25043 : : return ret;
25044 : 67 : ret = c_finish_omp_masked (loc, block,
25045 : : cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
25046 : 67 : OMP_MASKED_COMBINED (ret) = 1;
25047 : 67 : return ret;
25048 : : }
25049 : : }
25050 : 49 : if (!flag_openmp) /* flag_openmp_simd */
25051 : : {
25052 : 0 : c_parser_skip_to_pragma_eol (parser, false);
25053 : 0 : return NULL_TREE;
25054 : : }
25055 : :
25056 : 49 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25057 : 49 : if (cclauses)
25058 : : {
25059 : 9 : omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
25060 : 9 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
25061 : : }
25062 : :
25063 : 49 : return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
25064 : : if_p),
25065 : 49 : clauses);
25066 : : }
25067 : :
25068 : : /* OpenMP 5.1:
25069 : : # pragma omp interop clauses[opt] new-line */
25070 : :
25071 : : #define OMP_INTEROP_CLAUSE_MASK \
25072 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25073 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DESTROY) \
25074 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25075 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INIT) \
25076 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25077 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE))
25078 : :
25079 : : static void
25080 : 183 : c_parser_omp_interop (c_parser *parser)
25081 : : {
25082 : 183 : location_t loc = c_parser_peek_token (parser)->location;
25083 : 183 : c_parser_consume_pragma (parser);
25084 : 366 : tree clauses = c_parser_omp_all_clauses (parser,
25085 : 183 : OMP_INTEROP_CLAUSE_MASK,
25086 : : "#pragma omp interop");
25087 : 183 : tree stmt = make_node (OMP_INTEROP);
25088 : 183 : TREE_TYPE (stmt) = void_type_node;
25089 : 183 : OMP_INTEROP_CLAUSES (stmt) = clauses;
25090 : 183 : SET_EXPR_LOCATION (stmt, loc);
25091 : 183 : add_stmt (stmt);
25092 : 183 : }
25093 : :
25094 : : /* OpenMP 2.5:
25095 : : # pragma omp ordered new-line
25096 : : structured-block
25097 : :
25098 : : OpenMP 4.5:
25099 : : # pragma omp ordered ordered-clauses new-line
25100 : : structured-block
25101 : :
25102 : : # pragma omp ordered depend-clauses new-line
25103 : :
25104 : : OpenMP 5.2
25105 : : # pragma omp ordered doacross-clauses new-line */
25106 : :
25107 : : #define OMP_ORDERED_CLAUSE_MASK \
25108 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
25109 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
25110 : :
25111 : : #define OMP_ORDERED_DEPEND_CLAUSE_MASK \
25112 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25113 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
25114 : :
25115 : : static bool
25116 : 543 : c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
25117 : : bool *if_p)
25118 : : {
25119 : 543 : location_t loc = c_parser_peek_token (parser)->location;
25120 : 543 : c_parser_consume_pragma (parser);
25121 : :
25122 : 543 : if (context != pragma_stmt && context != pragma_compound)
25123 : : {
25124 : 1 : c_parser_error (parser, "expected declaration specifiers");
25125 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25126 : 1 : return false;
25127 : : }
25128 : :
25129 : 542 : int n = 1;
25130 : 542 : if (c_parser_next_token_is (parser, CPP_COMMA))
25131 : 8 : n = 2;
25132 : :
25133 : 542 : if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
25134 : : {
25135 : 431 : const char *p
25136 : 431 : = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
25137 : :
25138 : 431 : if (!strcmp ("depend", p) || !strcmp ("doacross", p))
25139 : : {
25140 : 347 : if (!flag_openmp) /* flag_openmp_simd */
25141 : : {
25142 : 2 : c_parser_skip_to_pragma_eol (parser, false);
25143 : 2 : return false;
25144 : : }
25145 : 345 : if (context == pragma_stmt)
25146 : : {
25147 : 16 : error_at (loc,
25148 : : "%<#pragma omp ordered%> with %qs clause may "
25149 : : "only be used in compound statements", p);
25150 : 16 : c_parser_skip_to_pragma_eol (parser, false);
25151 : 16 : return true;
25152 : : }
25153 : :
25154 : 329 : tree clauses
25155 : 658 : = c_parser_omp_all_clauses (parser,
25156 : 329 : OMP_ORDERED_DEPEND_CLAUSE_MASK,
25157 : : "#pragma omp ordered");
25158 : 329 : c_finish_omp_ordered (loc, clauses, NULL_TREE);
25159 : 329 : return false;
25160 : : }
25161 : : }
25162 : :
25163 : 195 : tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
25164 : : "#pragma omp ordered");
25165 : :
25166 : 195 : if (!flag_openmp /* flag_openmp_simd */
25167 : 195 : && omp_find_clause (clauses, OMP_CLAUSE_SIMD) == NULL_TREE)
25168 : : return false;
25169 : :
25170 : 193 : c_finish_omp_ordered (loc, clauses,
25171 : : c_parser_omp_structured_block (parser, if_p));
25172 : 193 : return true;
25173 : : }
25174 : :
25175 : : /* OpenMP 2.5:
25176 : :
25177 : : section-scope:
25178 : : { section-sequence }
25179 : :
25180 : : section-sequence:
25181 : : section-directive[opt] structured-block
25182 : : section-sequence section-directive structured-block
25183 : :
25184 : : OpenMP 5.1 allows structured-block-sequence instead of structured-block.
25185 : :
25186 : : SECTIONS_LOC is the location of the #pragma omp sections. */
25187 : :
25188 : : static tree
25189 : 142 : c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
25190 : : {
25191 : 142 : tree stmt, substmt;
25192 : 142 : bool error_suppress = false;
25193 : 142 : location_t loc;
25194 : :
25195 : 142 : loc = c_parser_peek_token (parser)->location;
25196 : 142 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
25197 : : {
25198 : : /* Avoid skipping until the end of the block. */
25199 : 2 : parser->error = false;
25200 : 2 : return NULL_TREE;
25201 : : }
25202 : :
25203 : 140 : stmt = push_stmt_list ();
25204 : :
25205 : 140 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
25206 : 140 : && !c_parser_omp_section_scan (parser, "section", true))
25207 : : {
25208 : 81 : substmt = c_parser_omp_structured_block_sequence (parser,
25209 : : PRAGMA_OMP_SECTION);
25210 : 81 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
25211 : 81 : SET_EXPR_LOCATION (substmt, loc);
25212 : 81 : add_stmt (substmt);
25213 : : }
25214 : :
25215 : 578 : while (1)
25216 : : {
25217 : 359 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
25218 : : break;
25219 : 219 : if (c_parser_next_token_is (parser, CPP_EOF))
25220 : : break;
25221 : :
25222 : 219 : loc = c_parser_peek_token (parser)->location;
25223 : 219 : c_parser_omp_section_scan (parser, "section", false);
25224 : 219 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
25225 : : {
25226 : 218 : c_parser_consume_pragma (parser);
25227 : 218 : c_parser_skip_to_pragma_eol (parser);
25228 : 218 : error_suppress = false;
25229 : : }
25230 : 1 : else if (!error_suppress)
25231 : : {
25232 : 1 : error_at (loc, "expected %<#pragma omp section%> or %<}%>");
25233 : 1 : error_suppress = true;
25234 : : }
25235 : :
25236 : 219 : substmt = c_parser_omp_structured_block_sequence (parser,
25237 : : PRAGMA_OMP_SECTION);
25238 : 219 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
25239 : 219 : SET_EXPR_LOCATION (substmt, loc);
25240 : 219 : add_stmt (substmt);
25241 : : }
25242 : 140 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
25243 : : "expected %<#pragma omp section%> or %<}%>");
25244 : :
25245 : 140 : substmt = pop_stmt_list (stmt);
25246 : :
25247 : 140 : stmt = make_node (OMP_SECTIONS);
25248 : 140 : SET_EXPR_LOCATION (stmt, sections_loc);
25249 : 140 : TREE_TYPE (stmt) = void_type_node;
25250 : 140 : OMP_SECTIONS_BODY (stmt) = substmt;
25251 : :
25252 : 140 : return add_stmt (stmt);
25253 : : }
25254 : :
25255 : : /* OpenMP 2.5:
25256 : : # pragma omp sections sections-clause[optseq] newline
25257 : : sections-scope
25258 : :
25259 : : LOC is the location of the #pragma token.
25260 : : */
25261 : :
25262 : : #define OMP_SECTIONS_CLAUSE_MASK \
25263 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25264 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25265 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25266 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25267 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25268 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25269 : :
25270 : : static tree
25271 : 142 : c_parser_omp_sections (location_t loc, c_parser *parser,
25272 : : char *p_name, omp_clause_mask mask, tree *cclauses)
25273 : : {
25274 : 142 : tree block, clauses, ret;
25275 : :
25276 : 142 : strcat (p_name, " sections");
25277 : 142 : mask |= OMP_SECTIONS_CLAUSE_MASK;
25278 : 142 : if (cclauses)
25279 : 36 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25280 : :
25281 : 142 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25282 : 142 : if (cclauses)
25283 : : {
25284 : 36 : omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
25285 : 36 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
25286 : : }
25287 : :
25288 : 142 : block = c_begin_compound_stmt (true);
25289 : 142 : ret = c_parser_omp_sections_scope (loc, parser);
25290 : 142 : if (ret)
25291 : 140 : OMP_SECTIONS_CLAUSES (ret) = clauses;
25292 : 142 : block = c_end_compound_stmt (loc, block, true);
25293 : 142 : add_stmt (block);
25294 : :
25295 : 142 : return ret;
25296 : : }
25297 : :
25298 : : /* OpenMP 2.5:
25299 : : # pragma omp parallel parallel-clause[optseq] new-line
25300 : : structured-block
25301 : : # pragma omp parallel for parallel-for-clause[optseq] new-line
25302 : : structured-block
25303 : : # pragma omp parallel sections parallel-sections-clause[optseq] new-line
25304 : : structured-block
25305 : :
25306 : : OpenMP 4.0:
25307 : : # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
25308 : : structured-block
25309 : :
25310 : : LOC is the location of the #pragma token.
25311 : : */
25312 : :
25313 : : #define OMP_PARALLEL_CLAUSE_MASK \
25314 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25315 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25316 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25317 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25318 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25319 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
25320 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25321 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
25322 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25323 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
25324 : :
25325 : : static tree
25326 : 5690 : c_parser_omp_parallel (location_t loc, c_parser *parser,
25327 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25328 : : bool *if_p)
25329 : : {
25330 : 5690 : tree stmt, clauses, block;
25331 : :
25332 : 5690 : strcat (p_name, " parallel");
25333 : 5690 : mask |= OMP_PARALLEL_CLAUSE_MASK;
25334 : : /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
25335 : 5690 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
25336 : 1165 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
25337 : 489 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
25338 : :
25339 : 5690 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
25340 : : {
25341 : 4371 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25342 : 4371 : if (cclauses == NULL)
25343 : 1198 : cclauses = cclauses_buf;
25344 : :
25345 : 4371 : c_parser_consume_token (parser);
25346 : 4371 : if (!flag_openmp) /* flag_openmp_simd */
25347 : 20 : return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25348 : 4351 : block = c_begin_omp_parallel ();
25349 : 4351 : tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25350 : 4351 : stmt
25351 : 4351 : = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25352 : : block);
25353 : 4351 : if (ret == NULL_TREE)
25354 : : return ret;
25355 : 4290 : OMP_PARALLEL_COMBINED (stmt) = 1;
25356 : 4290 : return stmt;
25357 : : }
25358 : : /* When combined with distribute, parallel has to be followed by for.
25359 : : #pragma omp target parallel is allowed though. */
25360 : 1319 : else if (cclauses
25361 : 1319 : && (mask & (OMP_CLAUSE_MASK_1
25362 : 40 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25363 : : {
25364 : 0 : error_at (loc, "expected %<for%> after %qs", p_name);
25365 : 0 : c_parser_skip_to_pragma_eol (parser);
25366 : 0 : return NULL_TREE;
25367 : : }
25368 : 1319 : else if (c_parser_next_token_is (parser, CPP_NAME))
25369 : : {
25370 : 713 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25371 : 713 : if (cclauses == NULL && strcmp (p, "masked") == 0)
25372 : : {
25373 : 56 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25374 : 56 : cclauses = cclauses_buf;
25375 : :
25376 : 56 : c_parser_consume_token (parser);
25377 : 56 : if (!flag_openmp) /* flag_openmp_simd */
25378 : 0 : return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25379 : 0 : if_p);
25380 : 56 : block = c_begin_omp_parallel ();
25381 : 56 : tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25382 : : if_p);
25383 : 56 : stmt = c_finish_omp_parallel (loc,
25384 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25385 : : block);
25386 : 56 : if (ret == NULL)
25387 : : return ret;
25388 : : /* masked does have just filter clause, but during gimplification
25389 : : isn't represented by a gimplification omp context, so for
25390 : : #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
25391 : : so that
25392 : : #pragma omp parallel masked
25393 : : #pragma omp taskloop simd lastprivate (x)
25394 : : isn't confused with
25395 : : #pragma omp parallel masked taskloop simd lastprivate (x) */
25396 : 56 : if (OMP_MASKED_COMBINED (ret))
25397 : 47 : OMP_PARALLEL_COMBINED (stmt) = 1;
25398 : 56 : return stmt;
25399 : : }
25400 : 622 : else if (cclauses == NULL && strcmp (p, "master") == 0)
25401 : : {
25402 : 89 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25403 : 89 : cclauses = cclauses_buf;
25404 : :
25405 : 89 : c_parser_consume_token (parser);
25406 : 89 : if (!flag_openmp) /* flag_openmp_simd */
25407 : 3 : return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25408 : 3 : if_p);
25409 : 86 : block = c_begin_omp_parallel ();
25410 : 86 : tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25411 : : if_p);
25412 : 86 : stmt = c_finish_omp_parallel (loc,
25413 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25414 : : block);
25415 : 86 : if (ret == NULL)
25416 : : return ret;
25417 : : /* master doesn't have any clauses and during gimplification
25418 : : isn't represented by a gimplification omp context, so for
25419 : : #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
25420 : : so that
25421 : : #pragma omp parallel master
25422 : : #pragma omp taskloop simd lastprivate (x)
25423 : : isn't confused with
25424 : : #pragma omp parallel master taskloop simd lastprivate (x) */
25425 : 86 : if (OMP_MASTER_COMBINED (ret))
25426 : 45 : OMP_PARALLEL_COMBINED (stmt) = 1;
25427 : 86 : return stmt;
25428 : : }
25429 : 568 : else if (strcmp (p, "loop") == 0)
25430 : : {
25431 : 46 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25432 : 46 : if (cclauses == NULL)
25433 : 27 : cclauses = cclauses_buf;
25434 : :
25435 : 46 : c_parser_consume_token (parser);
25436 : 46 : if (!flag_openmp) /* flag_openmp_simd */
25437 : 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25438 : 2 : if_p);
25439 : 44 : block = c_begin_omp_parallel ();
25440 : 44 : tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25441 : : if_p);
25442 : 44 : stmt
25443 : 44 : = c_finish_omp_parallel (loc,
25444 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25445 : : block);
25446 : 44 : if (ret == NULL_TREE)
25447 : : return ret;
25448 : 44 : OMP_PARALLEL_COMBINED (stmt) = 1;
25449 : 44 : return stmt;
25450 : : }
25451 : 522 : else if (!flag_openmp) /* flag_openmp_simd */
25452 : : {
25453 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25454 : 1 : return NULL_TREE;
25455 : : }
25456 : 521 : else if (cclauses == NULL && strcmp (p, "sections") == 0)
25457 : : {
25458 : 36 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25459 : 36 : cclauses = cclauses_buf;
25460 : :
25461 : 36 : c_parser_consume_token (parser);
25462 : 36 : block = c_begin_omp_parallel ();
25463 : 36 : c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
25464 : 36 : stmt = c_finish_omp_parallel (loc,
25465 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25466 : : block);
25467 : 36 : OMP_PARALLEL_COMBINED (stmt) = 1;
25468 : 36 : return stmt;
25469 : : }
25470 : : }
25471 : 606 : else if (!flag_openmp) /* flag_openmp_simd */
25472 : : {
25473 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25474 : 1 : return NULL_TREE;
25475 : : }
25476 : :
25477 : 1090 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25478 : 1090 : if (cclauses)
25479 : : {
25480 : 20 : omp_split_clauses (loc, OMP_PARALLEL, mask, clauses, cclauses);
25481 : 20 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
25482 : : }
25483 : :
25484 : 1090 : block = c_begin_omp_parallel ();
25485 : 1090 : parser->omp_attrs_forbidden_p = true;
25486 : 1090 : c_parser_statement (parser, if_p);
25487 : 1090 : stmt = c_finish_omp_parallel (loc, clauses, block);
25488 : :
25489 : 1090 : return stmt;
25490 : : }
25491 : :
25492 : : /* OpenMP 2.5:
25493 : : # pragma omp single single-clause[optseq] new-line
25494 : : structured-block
25495 : :
25496 : : LOC is the location of the #pragma.
25497 : : */
25498 : :
25499 : : #define OMP_SINGLE_CLAUSE_MASK \
25500 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25501 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25502 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
25503 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25504 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25505 : :
25506 : : static tree
25507 : 222 : c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
25508 : : {
25509 : 222 : tree stmt = make_node (OMP_SINGLE);
25510 : 222 : SET_EXPR_LOCATION (stmt, loc);
25511 : 222 : TREE_TYPE (stmt) = void_type_node;
25512 : :
25513 : 222 : OMP_SINGLE_CLAUSES (stmt)
25514 : 222 : = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
25515 : : "#pragma omp single");
25516 : 222 : OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25517 : :
25518 : 222 : return add_stmt (stmt);
25519 : : }
25520 : :
25521 : : /* OpenMP 5.1:
25522 : : # pragma omp scope scope-clause[optseq] new-line
25523 : : structured-block
25524 : :
25525 : : LOC is the location of the #pragma.
25526 : : */
25527 : :
25528 : : #define OMP_SCOPE_CLAUSE_MASK \
25529 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25530 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25531 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25532 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25533 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25534 : :
25535 : : static tree
25536 : 61 : c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
25537 : : {
25538 : 61 : tree stmt = make_node (OMP_SCOPE);
25539 : 61 : SET_EXPR_LOCATION (stmt, loc);
25540 : 61 : TREE_TYPE (stmt) = void_type_node;
25541 : :
25542 : 61 : OMP_SCOPE_CLAUSES (stmt)
25543 : 61 : = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
25544 : : "#pragma omp scope");
25545 : 61 : OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25546 : :
25547 : 61 : return add_stmt (stmt);
25548 : : }
25549 : :
25550 : : /* Parse a function dispatch structured block:
25551 : :
25552 : : lvalue-expression = target-call ( [expression-list] );
25553 : : or
25554 : : target-call ( [expression-list] );
25555 : :
25556 : : Adapted from c_parser_expr_no_commas and c_parser_postfix_expression
25557 : : (CPP_NAME/C_ID_ID) for the function name.
25558 : : */
25559 : : static tree
25560 : 151 : c_parser_omp_dispatch_body (c_parser *parser)
25561 : : {
25562 : 151 : struct c_expr lhs, rhs, ret;
25563 : 151 : location_t expr_loc = c_parser_peek_token (parser)->location;
25564 : 151 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
25565 : :
25566 : 151 : lhs = c_parser_conditional_expression (parser, NULL, NULL);
25567 : 151 : if (TREE_CODE (lhs.value) == CALL_EXPR)
25568 : : return lhs.value;
25569 : :
25570 : 53 : location_t op_location = c_parser_peek_token (parser)->location;
25571 : 53 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
25572 : 4 : return error_mark_node;
25573 : :
25574 : : /* Parse function name. */
25575 : 49 : if (!c_parser_next_token_is (parser, CPP_NAME))
25576 : : {
25577 : 1 : c_parser_error (parser, "expected a function name");
25578 : 1 : return error_mark_node;
25579 : : }
25580 : 48 : expr_loc = c_parser_peek_token (parser)->location;
25581 : 48 : tree id = c_parser_peek_token (parser)->value;
25582 : 48 : c_parser_consume_token (parser);
25583 : 48 : if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
25584 : : {
25585 : 1 : c_parser_error (parser, "expected a function name");
25586 : 1 : return error_mark_node;
25587 : : }
25588 : :
25589 : 47 : rhs.value = build_external_ref (expr_loc, id, true, &rhs.original_type);
25590 : 47 : set_c_expr_source_range (&rhs, tok_range);
25591 : :
25592 : : /* Parse argument list. */
25593 : 47 : rhs = c_parser_postfix_expression_after_primary (
25594 : 47 : parser, EXPR_LOC_OR_LOC (rhs.value, expr_loc), rhs);
25595 : 47 : if (TREE_CODE (rhs.value) != CALL_EXPR)
25596 : : {
25597 : 0 : error_at (EXPR_LOC_OR_LOC (rhs.value, expr_loc),
25598 : : "expected target-function call");
25599 : 0 : return error_mark_node;
25600 : : }
25601 : :
25602 : : /* Build assignment. */
25603 : 47 : rhs = convert_lvalue_to_rvalue (expr_loc, rhs, true, true);
25604 : 47 : ret.value
25605 : 47 : = build_modify_expr (op_location, lhs.value, lhs.original_type, NOP_EXPR,
25606 : : expr_loc, rhs.value, rhs.original_type);
25607 : 47 : ret.m_decimal = 0;
25608 : 47 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
25609 : 47 : ret.original_code = MODIFY_EXPR;
25610 : 47 : ret.original_type = NULL;
25611 : 47 : return ret.value;
25612 : : }
25613 : :
25614 : : /* OpenMP 5.1:
25615 : : # pragma omp dispatch dispatch-clause[optseq] new-line
25616 : : expression-stmt
25617 : :
25618 : : LOC is the location of the #pragma.
25619 : : */
25620 : :
25621 : : #define OMP_DISPATCH_CLAUSE_MASK \
25622 : : ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25623 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25624 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
25625 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
25626 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
25627 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \
25628 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
25629 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25630 : :
25631 : : static tree
25632 : 151 : c_parser_omp_dispatch (location_t loc, c_parser *parser)
25633 : : {
25634 : 151 : tree stmt = make_node (OMP_DISPATCH);
25635 : 151 : SET_EXPR_LOCATION (stmt, loc);
25636 : 151 : TREE_TYPE (stmt) = void_type_node;
25637 : :
25638 : 151 : OMP_DISPATCH_CLAUSES (stmt)
25639 : 151 : = c_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
25640 : : "#pragma omp dispatch");
25641 : :
25642 : : // Extract depend clauses and create taskwait
25643 : 151 : tree depend_clauses = NULL_TREE;
25644 : 151 : tree *depend_clauses_ptr = &depend_clauses;
25645 : 334 : for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
25646 : : {
25647 : 183 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
25648 : : {
25649 : 5 : *depend_clauses_ptr = c;
25650 : 5 : depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
25651 : : }
25652 : : }
25653 : 151 : if (depend_clauses != NULL_TREE)
25654 : : {
25655 : 5 : tree stmt = make_node (OMP_TASK);
25656 : 5 : TREE_TYPE (stmt) = void_node;
25657 : 5 : OMP_TASK_CLAUSES (stmt) = depend_clauses;
25658 : 5 : OMP_TASK_BODY (stmt) = NULL_TREE;
25659 : 5 : SET_EXPR_LOCATION (stmt, loc);
25660 : 5 : add_stmt (stmt);
25661 : : }
25662 : :
25663 : : // Parse body as expression statement
25664 : 151 : loc = c_parser_peek_token (parser)->location;
25665 : 151 : tree dispatch_body = c_parser_omp_dispatch_body (parser);
25666 : 151 : if (dispatch_body == error_mark_node)
25667 : : {
25668 : 6 : inform (loc, "%<#pragma omp dispatch%> must be followed by a function "
25669 : : "call with optional assignment");
25670 : 6 : c_parser_skip_to_end_of_block_or_statement (parser);
25671 : 6 : return NULL_TREE;
25672 : : }
25673 : :
25674 : : // Walk the tree to find the dispatch function call and wrap it into an IFN
25675 : 145 : gcc_assert (TREE_CODE (dispatch_body) == CALL_EXPR
25676 : : || TREE_CODE (dispatch_body) == MODIFY_EXPR);
25677 : 145 : tree *dispatch_call = TREE_CODE (dispatch_body) == MODIFY_EXPR
25678 : 145 : ? &TREE_OPERAND (dispatch_body, 1)
25679 : : : &dispatch_body;
25680 : 150 : while (TREE_CODE (*dispatch_call) == FLOAT_EXPR
25681 : : || TREE_CODE (*dispatch_call) == CONVERT_EXPR
25682 : 150 : || TREE_CODE (*dispatch_call) == NOP_EXPR)
25683 : 5 : dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
25684 : 145 : *dispatch_call = build_call_expr_internal_loc (
25685 : : loc, IFN_GOMP_DISPATCH,
25686 : 145 : TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*dispatch_call))), 1, *dispatch_call);
25687 : :
25688 : 145 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
25689 : 145 : OMP_DISPATCH_BODY (stmt) = dispatch_body;
25690 : :
25691 : 145 : return add_stmt (stmt);
25692 : : }
25693 : :
25694 : : /* OpenMP 3.0:
25695 : : # pragma omp task task-clause[optseq] new-line
25696 : :
25697 : : LOC is the location of the #pragma.
25698 : : */
25699 : :
25700 : : #define OMP_TASK_CLAUSE_MASK \
25701 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25702 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
25703 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25704 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25705 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25706 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25707 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
25708 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
25709 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25710 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
25711 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25712 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
25713 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
25714 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
25715 : :
25716 : : static tree
25717 : 894 : c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
25718 : : {
25719 : 894 : tree clauses, block;
25720 : :
25721 : 894 : clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
25722 : : "#pragma omp task");
25723 : :
25724 : 894 : block = c_begin_omp_task ();
25725 : 894 : parser->omp_attrs_forbidden_p = true;
25726 : 894 : c_parser_statement (parser, if_p);
25727 : 894 : return c_finish_omp_task (loc, clauses, block);
25728 : : }
25729 : :
25730 : : /* OpenMP 3.0:
25731 : : # pragma omp taskwait new-line
25732 : :
25733 : : OpenMP 5.0:
25734 : : # pragma omp taskwait taskwait-clause[optseq] new-line
25735 : : */
25736 : :
25737 : : #define OMP_TASKWAIT_CLAUSE_MASK \
25738 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25739 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25740 : :
25741 : : static void
25742 : 93 : c_parser_omp_taskwait (c_parser *parser)
25743 : : {
25744 : 93 : location_t loc = c_parser_peek_token (parser)->location;
25745 : 93 : c_parser_consume_pragma (parser);
25746 : :
25747 : 93 : tree clauses
25748 : 93 : = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
25749 : : "#pragma omp taskwait");
25750 : :
25751 : 93 : if (clauses)
25752 : : {
25753 : 21 : tree stmt = make_node (OMP_TASK);
25754 : 21 : TREE_TYPE (stmt) = void_node;
25755 : 21 : OMP_TASK_CLAUSES (stmt) = clauses;
25756 : 21 : OMP_TASK_BODY (stmt) = NULL_TREE;
25757 : 21 : SET_EXPR_LOCATION (stmt, loc);
25758 : 21 : add_stmt (stmt);
25759 : : }
25760 : : else
25761 : 72 : c_finish_omp_taskwait (loc);
25762 : 93 : }
25763 : :
25764 : : /* OpenMP 3.1:
25765 : : # pragma omp taskyield new-line
25766 : : */
25767 : :
25768 : : static void
25769 : 6 : c_parser_omp_taskyield (c_parser *parser)
25770 : : {
25771 : 6 : location_t loc = c_parser_peek_token (parser)->location;
25772 : 6 : c_parser_consume_pragma (parser);
25773 : 6 : c_parser_skip_to_pragma_eol (parser);
25774 : :
25775 : 6 : c_finish_omp_taskyield (loc);
25776 : 6 : }
25777 : :
25778 : : /* OpenMP 4.0:
25779 : : # pragma omp taskgroup new-line
25780 : :
25781 : : OpenMP 5.0:
25782 : : # pragma omp taskgroup taskgroup-clause[optseq] new-line
25783 : : */
25784 : :
25785 : : #define OMP_TASKGROUP_CLAUSE_MASK \
25786 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25787 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
25788 : :
25789 : : static tree
25790 : 138 : c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
25791 : : {
25792 : 138 : tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
25793 : : "#pragma omp taskgroup");
25794 : :
25795 : 138 : tree body = c_parser_omp_structured_block (parser, if_p);
25796 : 138 : return c_finish_omp_taskgroup (loc, body, clauses);
25797 : : }
25798 : :
25799 : : /* OpenMP 4.0:
25800 : : # pragma omp cancel cancel-clause[optseq] new-line
25801 : :
25802 : : LOC is the location of the #pragma.
25803 : : */
25804 : :
25805 : : #define OMP_CANCEL_CLAUSE_MASK \
25806 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25807 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25808 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25809 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
25810 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
25811 : :
25812 : : static void
25813 : 213 : c_parser_omp_cancel (c_parser *parser)
25814 : : {
25815 : 213 : location_t loc = c_parser_peek_token (parser)->location;
25816 : :
25817 : 213 : c_parser_consume_pragma (parser);
25818 : 213 : tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
25819 : : "#pragma omp cancel");
25820 : :
25821 : 213 : c_finish_omp_cancel (loc, clauses);
25822 : 213 : }
25823 : :
25824 : : /* OpenMP 4.0:
25825 : : # pragma omp cancellation point cancelpt-clause[optseq] new-line
25826 : :
25827 : : LOC is the location of the #pragma.
25828 : : */
25829 : :
25830 : : #define OMP_CANCELLATION_POINT_CLAUSE_MASK \
25831 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25832 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25833 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25834 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
25835 : :
25836 : : static bool
25837 : 179 : c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
25838 : : {
25839 : 179 : location_t loc = c_parser_peek_token (parser)->location;
25840 : 179 : tree clauses;
25841 : 179 : bool point_seen = false;
25842 : :
25843 : 179 : c_parser_consume_pragma (parser);
25844 : 179 : if (c_parser_next_token_is (parser, CPP_NAME))
25845 : : {
25846 : 179 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25847 : 179 : if (strcmp (p, "point") == 0)
25848 : : {
25849 : 177 : c_parser_consume_token (parser);
25850 : 177 : point_seen = true;
25851 : : }
25852 : : }
25853 : 177 : if (!point_seen)
25854 : : {
25855 : 2 : c_parser_error (parser, "expected %<point%>");
25856 : 2 : c_parser_skip_to_pragma_eol (parser);
25857 : 2 : return false;
25858 : : }
25859 : :
25860 : 177 : if (context != pragma_compound)
25861 : : {
25862 : 10 : if (context == pragma_stmt)
25863 : 9 : error_at (loc,
25864 : : "%<#pragma %s%> may only be used in compound statements",
25865 : : "omp cancellation point");
25866 : : else
25867 : 1 : c_parser_error (parser, "expected declaration specifiers");
25868 : 10 : c_parser_skip_to_pragma_eol (parser, false);
25869 : 10 : return true;
25870 : : }
25871 : :
25872 : 167 : clauses
25873 : 167 : = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
25874 : : "#pragma omp cancellation point");
25875 : :
25876 : 167 : c_finish_omp_cancellation_point (loc, clauses);
25877 : 167 : return true;
25878 : : }
25879 : :
25880 : : /* OpenMP 4.0:
25881 : : #pragma omp distribute distribute-clause[optseq] new-line
25882 : : for-loop */
25883 : :
25884 : : #define OMP_DISTRIBUTE_CLAUSE_MASK \
25885 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25886 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25887 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25888 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
25889 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25890 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25891 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25892 : :
25893 : : static tree
25894 : 3427 : c_parser_omp_distribute (location_t loc, c_parser *parser,
25895 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25896 : : bool *if_p)
25897 : : {
25898 : 3427 : tree clauses, block, ret;
25899 : :
25900 : 3427 : strcat (p_name, " distribute");
25901 : 3427 : mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
25902 : :
25903 : 3427 : if (c_parser_next_token_is (parser, CPP_NAME))
25904 : : {
25905 : 3331 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25906 : 3331 : bool simd = false;
25907 : 3331 : bool parallel = false;
25908 : :
25909 : 3331 : if (strcmp (p, "simd") == 0)
25910 : : simd = true;
25911 : : else
25912 : 2991 : parallel = strcmp (p, "parallel") == 0;
25913 : 2991 : if (parallel || simd)
25914 : : {
25915 : 3064 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25916 : 3064 : if (cclauses == NULL)
25917 : 1147 : cclauses = cclauses_buf;
25918 : 3064 : c_parser_consume_token (parser);
25919 : 3064 : if (!flag_openmp) /* flag_openmp_simd */
25920 : : {
25921 : 15 : if (simd)
25922 : 6 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25923 : 6 : if_p);
25924 : : else
25925 : 9 : return c_parser_omp_parallel (loc, parser, p_name, mask,
25926 : 9 : cclauses, if_p);
25927 : : }
25928 : 3049 : block = c_begin_compound_stmt (true);
25929 : 3049 : if (simd)
25930 : 334 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25931 : : if_p);
25932 : : else
25933 : 2715 : ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
25934 : : if_p);
25935 : 3049 : block = c_end_compound_stmt (loc, block, true);
25936 : 3049 : if (ret == NULL)
25937 : : return ret;
25938 : 3044 : ret = make_node (OMP_DISTRIBUTE);
25939 : 3044 : TREE_TYPE (ret) = void_type_node;
25940 : 3044 : OMP_FOR_BODY (ret) = block;
25941 : 3044 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
25942 : 3044 : SET_EXPR_LOCATION (ret, loc);
25943 : 3044 : add_stmt (ret);
25944 : 3044 : return ret;
25945 : : }
25946 : : }
25947 : 363 : if (!flag_openmp) /* flag_openmp_simd */
25948 : : {
25949 : 2 : c_parser_skip_to_pragma_eol (parser, false);
25950 : 2 : return NULL_TREE;
25951 : : }
25952 : :
25953 : 361 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25954 : 361 : if (cclauses)
25955 : : {
25956 : 194 : omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
25957 : 194 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
25958 : : }
25959 : :
25960 : 361 : block = c_begin_compound_stmt (true);
25961 : 361 : ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
25962 : : if_p);
25963 : 361 : block = c_end_compound_stmt (loc, block, true);
25964 : 361 : add_stmt (block);
25965 : :
25966 : 361 : return ret;
25967 : : }
25968 : :
25969 : : /* OpenMP 4.0:
25970 : : # pragma omp teams teams-clause[optseq] new-line
25971 : : structured-block */
25972 : :
25973 : : #define OMP_TEAMS_CLAUSE_MASK \
25974 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25975 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25976 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25977 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25978 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
25979 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
25980 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25981 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
25982 : :
25983 : : static tree
25984 : 3669 : c_parser_omp_teams (location_t loc, c_parser *parser,
25985 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25986 : : bool *if_p)
25987 : : {
25988 : 3669 : tree clauses, block, ret;
25989 : :
25990 : 3669 : strcat (p_name, " teams");
25991 : 3669 : mask |= OMP_TEAMS_CLAUSE_MASK;
25992 : :
25993 : 3669 : if (c_parser_next_token_is (parser, CPP_NAME))
25994 : : {
25995 : 2340 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25996 : 2340 : if (strcmp (p, "distribute") == 0)
25997 : : {
25998 : 2113 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25999 : 2113 : if (cclauses == NULL)
26000 : 1271 : cclauses = cclauses_buf;
26001 : :
26002 : 2113 : c_parser_consume_token (parser);
26003 : 2113 : if (!flag_openmp) /* flag_openmp_simd */
26004 : 12 : return c_parser_omp_distribute (loc, parser, p_name, mask,
26005 : 12 : cclauses, if_p);
26006 : 2101 : block = c_begin_omp_parallel ();
26007 : 2101 : ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
26008 : : if_p);
26009 : 2101 : block = c_end_compound_stmt (loc, block, true);
26010 : 2101 : if (ret == NULL)
26011 : : return ret;
26012 : 2101 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26013 : 2101 : ret = make_node (OMP_TEAMS);
26014 : 2101 : TREE_TYPE (ret) = void_type_node;
26015 : 2101 : OMP_TEAMS_CLAUSES (ret) = clauses;
26016 : 2101 : OMP_TEAMS_BODY (ret) = block;
26017 : 2101 : OMP_TEAMS_COMBINED (ret) = 1;
26018 : 2101 : SET_EXPR_LOCATION (ret, loc);
26019 : 2101 : return add_stmt (ret);
26020 : : }
26021 : 227 : else if (strcmp (p, "loop") == 0)
26022 : : {
26023 : 34 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26024 : 34 : if (cclauses == NULL)
26025 : 16 : cclauses = cclauses_buf;
26026 : :
26027 : 34 : c_parser_consume_token (parser);
26028 : 34 : if (!flag_openmp) /* flag_openmp_simd */
26029 : 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26030 : 2 : if_p);
26031 : 32 : block = c_begin_omp_parallel ();
26032 : 32 : ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
26033 : 32 : block = c_end_compound_stmt (loc, block, true);
26034 : 32 : if (ret == NULL)
26035 : : return ret;
26036 : 31 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26037 : 31 : ret = make_node (OMP_TEAMS);
26038 : 31 : TREE_TYPE (ret) = void_type_node;
26039 : 31 : OMP_TEAMS_CLAUSES (ret) = clauses;
26040 : 31 : OMP_TEAMS_BODY (ret) = block;
26041 : 31 : OMP_TEAMS_COMBINED (ret) = 1;
26042 : 31 : SET_EXPR_LOCATION (ret, loc);
26043 : 31 : return add_stmt (ret);
26044 : : }
26045 : : }
26046 : 1522 : if (!flag_openmp) /* flag_openmp_simd */
26047 : : {
26048 : 2 : c_parser_skip_to_pragma_eol (parser, false);
26049 : 2 : return NULL_TREE;
26050 : : }
26051 : :
26052 : 1520 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26053 : 1520 : if (cclauses)
26054 : : {
26055 : 877 : omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
26056 : 877 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26057 : : }
26058 : :
26059 : 1520 : tree stmt = make_node (OMP_TEAMS);
26060 : 1520 : TREE_TYPE (stmt) = void_type_node;
26061 : 1520 : OMP_TEAMS_CLAUSES (stmt) = clauses;
26062 : 1520 : block = c_begin_omp_parallel ();
26063 : 1520 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26064 : 1520 : OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26065 : 1520 : SET_EXPR_LOCATION (stmt, loc);
26066 : :
26067 : 1520 : return add_stmt (stmt);
26068 : : }
26069 : :
26070 : : /* OpenMP 4.0:
26071 : : # pragma omp target data target-data-clause[optseq] new-line
26072 : : structured-block */
26073 : :
26074 : : #define OMP_TARGET_DATA_CLAUSE_MASK \
26075 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26076 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26077 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26078 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
26079 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
26080 : :
26081 : : static tree
26082 : 155 : c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
26083 : : {
26084 : 155 : if (flag_openmp)
26085 : 155 : omp_requires_mask
26086 : 155 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26087 : :
26088 : 155 : tree clauses
26089 : 155 : = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
26090 : 155 : "#pragma omp target data");
26091 : 155 : c_omp_adjust_map_clauses (clauses, false);
26092 : 155 : int map_seen = 0;
26093 : 455 : for (tree *pc = &clauses; *pc;)
26094 : : {
26095 : 300 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26096 : 218 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26097 : : {
26098 : : case GOMP_MAP_TO:
26099 : : case GOMP_MAP_ALWAYS_TO:
26100 : : case GOMP_MAP_PRESENT_TO:
26101 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26102 : : case GOMP_MAP_FROM:
26103 : : case GOMP_MAP_ALWAYS_FROM:
26104 : : case GOMP_MAP_PRESENT_FROM:
26105 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26106 : : case GOMP_MAP_TOFROM:
26107 : : case GOMP_MAP_ALWAYS_TOFROM:
26108 : : case GOMP_MAP_PRESENT_TOFROM:
26109 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26110 : : case GOMP_MAP_ALLOC:
26111 : : case GOMP_MAP_PRESENT_ALLOC:
26112 : 300 : map_seen = 3;
26113 : : break;
26114 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26115 : : case GOMP_MAP_ALWAYS_POINTER:
26116 : : case GOMP_MAP_ATTACH_DETACH:
26117 : : case GOMP_MAP_ATTACH:
26118 : : break;
26119 : 0 : default:
26120 : 0 : map_seen |= 1;
26121 : 0 : error_at (OMP_CLAUSE_LOCATION (*pc),
26122 : : "%<#pragma omp target data%> with map-type other "
26123 : : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26124 : : "on %<map%> clause");
26125 : 0 : *pc = OMP_CLAUSE_CHAIN (*pc);
26126 : 0 : continue;
26127 : : }
26128 : 82 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
26129 : 82 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
26130 : : map_seen = 3;
26131 : 300 : pc = &OMP_CLAUSE_CHAIN (*pc);
26132 : : }
26133 : :
26134 : 155 : if (map_seen != 3)
26135 : : {
26136 : 3 : if (map_seen == 0)
26137 : 3 : error_at (loc,
26138 : : "%<#pragma omp target data%> must contain at least "
26139 : : "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
26140 : : "clause");
26141 : 3 : return NULL_TREE;
26142 : : }
26143 : :
26144 : 152 : tree stmt = make_node (OMP_TARGET_DATA);
26145 : 152 : TREE_TYPE (stmt) = void_type_node;
26146 : 152 : OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
26147 : 152 : keep_next_level ();
26148 : 152 : tree block = c_begin_compound_stmt (true);
26149 : 152 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26150 : 152 : OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26151 : :
26152 : 152 : SET_EXPR_LOCATION (stmt, loc);
26153 : 152 : return add_stmt (stmt);
26154 : : }
26155 : :
26156 : : /* OpenMP 4.0:
26157 : : # pragma omp target update target-update-clause[optseq] new-line */
26158 : :
26159 : : #define OMP_TARGET_UPDATE_CLAUSE_MASK \
26160 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
26161 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
26162 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26163 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26164 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26165 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26166 : :
26167 : : static bool
26168 : 2826 : c_parser_omp_target_update (location_t loc, c_parser *parser,
26169 : : enum pragma_context context)
26170 : : {
26171 : 2826 : if (context == pragma_stmt)
26172 : : {
26173 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26174 : : "omp target update");
26175 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26176 : 8 : return true;
26177 : : }
26178 : :
26179 : 2818 : tree clauses
26180 : 2818 : = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
26181 : : "#pragma omp target update");
26182 : 2818 : if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
26183 : 2818 : && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
26184 : : {
26185 : 3 : error_at (loc,
26186 : : "%<#pragma omp target update%> must contain at least one "
26187 : : "%<from%> or %<to%> clauses");
26188 : 3 : return false;
26189 : : }
26190 : :
26191 : 2815 : if (flag_openmp)
26192 : 2815 : omp_requires_mask
26193 : 2815 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26194 : :
26195 : 2815 : tree stmt = make_node (OMP_TARGET_UPDATE);
26196 : 2815 : TREE_TYPE (stmt) = void_type_node;
26197 : 2815 : OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
26198 : 2815 : SET_EXPR_LOCATION (stmt, loc);
26199 : 2815 : add_stmt (stmt);
26200 : 2815 : return false;
26201 : : }
26202 : :
26203 : : /* OpenMP 4.5:
26204 : : # pragma omp target enter data target-data-clause[optseq] new-line */
26205 : :
26206 : : #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
26207 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26208 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26209 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26210 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26211 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26212 : :
26213 : : static bool
26214 : 114 : c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
26215 : : enum pragma_context context)
26216 : : {
26217 : 114 : bool data_seen = false;
26218 : 114 : if (c_parser_next_token_is (parser, CPP_NAME))
26219 : : {
26220 : 114 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26221 : 114 : if (strcmp (p, "data") == 0)
26222 : : {
26223 : 114 : c_parser_consume_token (parser);
26224 : 114 : data_seen = true;
26225 : : }
26226 : : }
26227 : 114 : if (!data_seen)
26228 : : {
26229 : 0 : c_parser_error (parser, "expected %<data%>");
26230 : 0 : c_parser_skip_to_pragma_eol (parser);
26231 : 0 : return false;
26232 : : }
26233 : :
26234 : 114 : if (context == pragma_stmt)
26235 : : {
26236 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26237 : : "omp target enter data");
26238 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26239 : 8 : return true;
26240 : : }
26241 : :
26242 : 106 : if (flag_openmp)
26243 : 106 : omp_requires_mask
26244 : 106 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26245 : :
26246 : 106 : tree clauses
26247 : 106 : = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
26248 : 106 : "#pragma omp target enter data");
26249 : 106 : c_omp_adjust_map_clauses (clauses, false);
26250 : 106 : int map_seen = 0;
26251 : 383 : for (tree *pc = &clauses; *pc;)
26252 : : {
26253 : 277 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26254 : 234 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26255 : : {
26256 : : case GOMP_MAP_TO:
26257 : : case GOMP_MAP_ALWAYS_TO:
26258 : : case GOMP_MAP_PRESENT_TO:
26259 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26260 : : case GOMP_MAP_ALLOC:
26261 : : case GOMP_MAP_PRESENT_ALLOC:
26262 : 182 : map_seen = 3;
26263 : : break;
26264 : 34 : case GOMP_MAP_TOFROM:
26265 : 34 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
26266 : 34 : map_seen = 3;
26267 : 34 : break;
26268 : 3 : case GOMP_MAP_ALWAYS_TOFROM:
26269 : 3 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
26270 : 3 : map_seen = 3;
26271 : 3 : break;
26272 : 2 : case GOMP_MAP_PRESENT_TOFROM:
26273 : 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
26274 : 2 : map_seen = 3;
26275 : 2 : break;
26276 : 2 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26277 : 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
26278 : 2 : map_seen = 3;
26279 : 2 : break;
26280 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26281 : : case GOMP_MAP_ALWAYS_POINTER:
26282 : : case GOMP_MAP_ATTACH_DETACH:
26283 : : case GOMP_MAP_ATTACH:
26284 : : break;
26285 : 2 : default:
26286 : 2 : map_seen |= 1;
26287 : 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
26288 : : "%<#pragma omp target enter data%> with map-type other "
26289 : : "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
26290 : 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
26291 : 2 : continue;
26292 : : }
26293 : 275 : pc = &OMP_CLAUSE_CHAIN (*pc);
26294 : : }
26295 : :
26296 : 106 : if (map_seen != 3)
26297 : : {
26298 : 4 : if (map_seen == 0)
26299 : 2 : error_at (loc,
26300 : : "%<#pragma omp target enter data%> must contain at least "
26301 : : "one %<map%> clause");
26302 : 4 : return true;
26303 : : }
26304 : :
26305 : 102 : tree stmt = make_node (OMP_TARGET_ENTER_DATA);
26306 : 102 : TREE_TYPE (stmt) = void_type_node;
26307 : 102 : OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
26308 : 102 : SET_EXPR_LOCATION (stmt, loc);
26309 : 102 : add_stmt (stmt);
26310 : 102 : return true;
26311 : : }
26312 : :
26313 : : /* OpenMP 4.5:
26314 : : # pragma omp target exit data target-data-clause[optseq] new-line */
26315 : :
26316 : : #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
26317 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26318 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26319 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26320 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26321 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26322 : :
26323 : : static bool
26324 : 107 : c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
26325 : : enum pragma_context context)
26326 : : {
26327 : 107 : bool data_seen = false;
26328 : 107 : if (c_parser_next_token_is (parser, CPP_NAME))
26329 : : {
26330 : 107 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26331 : 107 : if (strcmp (p, "data") == 0)
26332 : : {
26333 : 107 : c_parser_consume_token (parser);
26334 : 107 : data_seen = true;
26335 : : }
26336 : : }
26337 : 107 : if (!data_seen)
26338 : : {
26339 : 0 : c_parser_error (parser, "expected %<data%>");
26340 : 0 : c_parser_skip_to_pragma_eol (parser);
26341 : 0 : return false;
26342 : : }
26343 : :
26344 : 107 : if (context == pragma_stmt)
26345 : : {
26346 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26347 : : "omp target exit data");
26348 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26349 : 8 : return true;
26350 : : }
26351 : :
26352 : 99 : if (flag_openmp)
26353 : 99 : omp_requires_mask
26354 : 99 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26355 : :
26356 : 99 : tree clauses
26357 : 99 : = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
26358 : : "#pragma omp target exit data", false);
26359 : 99 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
26360 : 99 : c_omp_adjust_map_clauses (clauses, false);
26361 : 99 : int map_seen = 0;
26362 : 349 : for (tree *pc = &clauses; *pc;)
26363 : : {
26364 : 250 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26365 : 207 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26366 : : {
26367 : : case GOMP_MAP_FROM:
26368 : : case GOMP_MAP_ALWAYS_FROM:
26369 : : case GOMP_MAP_PRESENT_FROM:
26370 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26371 : : case GOMP_MAP_RELEASE:
26372 : : case GOMP_MAP_DELETE:
26373 : 158 : map_seen = 3;
26374 : : break;
26375 : 30 : case GOMP_MAP_TOFROM:
26376 : 30 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
26377 : 30 : map_seen = 3;
26378 : 30 : break;
26379 : 1 : case GOMP_MAP_ALWAYS_TOFROM:
26380 : 1 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
26381 : 1 : map_seen = 3;
26382 : 1 : break;
26383 : 0 : case GOMP_MAP_PRESENT_TOFROM:
26384 : 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
26385 : 0 : map_seen = 3;
26386 : 0 : break;
26387 : 0 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26388 : 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
26389 : 0 : map_seen = 3;
26390 : 0 : break;
26391 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26392 : : case GOMP_MAP_ALWAYS_POINTER:
26393 : : case GOMP_MAP_ATTACH_DETACH:
26394 : : case GOMP_MAP_DETACH:
26395 : : break;
26396 : 2 : default:
26397 : 2 : map_seen |= 1;
26398 : 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
26399 : : "%<#pragma omp target exit data%> with map-type other "
26400 : : "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
26401 : : "on %<map%> clause");
26402 : 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
26403 : 2 : continue;
26404 : : }
26405 : 248 : pc = &OMP_CLAUSE_CHAIN (*pc);
26406 : : }
26407 : :
26408 : 99 : if (map_seen != 3)
26409 : : {
26410 : 2 : if (map_seen == 0)
26411 : 0 : error_at (loc,
26412 : : "%<#pragma omp target exit data%> must contain at least one "
26413 : : "%<map%> clause");
26414 : 2 : return true;
26415 : : }
26416 : :
26417 : 97 : tree stmt = make_node (OMP_TARGET_EXIT_DATA);
26418 : 97 : TREE_TYPE (stmt) = void_type_node;
26419 : 97 : OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
26420 : 97 : SET_EXPR_LOCATION (stmt, loc);
26421 : 97 : add_stmt (stmt);
26422 : 97 : return true;
26423 : : }
26424 : :
26425 : : /* OpenMP 4.0:
26426 : : # pragma omp target target-clause[optseq] new-line
26427 : : structured-block */
26428 : :
26429 : : #define OMP_TARGET_CLAUSE_MASK \
26430 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26431 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26432 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26433 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26434 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
26435 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26436 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26437 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26438 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
26439 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
26440 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26441 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
26442 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
26443 : :
26444 : : static bool
26445 : 7362 : c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
26446 : : {
26447 : 7362 : location_t loc = c_parser_peek_token (parser)->location;
26448 : 7362 : c_parser_consume_pragma (parser);
26449 : 7362 : tree *pc = NULL, stmt, block, body, clauses;
26450 : :
26451 : 7362 : if (context != pragma_stmt && context != pragma_compound)
26452 : : {
26453 : 2 : c_parser_error (parser, "expected declaration specifiers");
26454 : 2 : c_parser_skip_to_pragma_eol (parser);
26455 : 2 : return false;
26456 : : }
26457 : :
26458 : 7360 : if (flag_openmp)
26459 : 7346 : omp_requires_mask
26460 : 7346 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26461 : :
26462 : 7360 : if (c_parser_next_token_is (parser, CPP_NAME))
26463 : : {
26464 : 6437 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26465 : 6437 : enum tree_code ccode = ERROR_MARK;
26466 : :
26467 : 6437 : if (strcmp (p, "teams") == 0)
26468 : : ccode = OMP_TEAMS;
26469 : 4699 : else if (strcmp (p, "parallel") == 0)
26470 : : ccode = OMP_PARALLEL;
26471 : 4210 : else if (strcmp (p, "simd") == 0)
26472 : : ccode = OMP_SIMD;
26473 : 4150 : if (ccode != ERROR_MARK)
26474 : : {
26475 : 2287 : tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
26476 : 2287 : char p_name[sizeof ("#pragma omp target teams distribute "
26477 : : "parallel for simd")];
26478 : :
26479 : 2287 : c_parser_consume_token (parser);
26480 : 2287 : strcpy (p_name, "#pragma omp target");
26481 : 2287 : if (!flag_openmp) /* flag_openmp_simd */
26482 : : {
26483 : 13 : tree stmt;
26484 : 13 : switch (ccode)
26485 : : {
26486 : 8 : case OMP_TEAMS:
26487 : 8 : stmt = c_parser_omp_teams (loc, parser, p_name,
26488 : 8 : OMP_TARGET_CLAUSE_MASK,
26489 : : cclauses, if_p);
26490 : 8 : break;
26491 : 4 : case OMP_PARALLEL:
26492 : 4 : stmt = c_parser_omp_parallel (loc, parser, p_name,
26493 : 4 : OMP_TARGET_CLAUSE_MASK,
26494 : : cclauses, if_p);
26495 : 4 : break;
26496 : 1 : case OMP_SIMD:
26497 : 1 : stmt = c_parser_omp_simd (loc, parser, p_name,
26498 : 1 : OMP_TARGET_CLAUSE_MASK,
26499 : : cclauses, if_p);
26500 : 1 : break;
26501 : 0 : default:
26502 : 0 : gcc_unreachable ();
26503 : : }
26504 : 22 : return stmt != NULL_TREE;
26505 : : }
26506 : 2274 : keep_next_level ();
26507 : 2274 : tree block = c_begin_compound_stmt (true), ret;
26508 : 2274 : switch (ccode)
26509 : : {
26510 : 1730 : case OMP_TEAMS:
26511 : 1730 : ret = c_parser_omp_teams (loc, parser, p_name,
26512 : 1730 : OMP_TARGET_CLAUSE_MASK, cclauses,
26513 : : if_p);
26514 : 1730 : break;
26515 : 485 : case OMP_PARALLEL:
26516 : 485 : ret = c_parser_omp_parallel (loc, parser, p_name,
26517 : 485 : OMP_TARGET_CLAUSE_MASK, cclauses,
26518 : : if_p);
26519 : 485 : break;
26520 : 59 : case OMP_SIMD:
26521 : 59 : ret = c_parser_omp_simd (loc, parser, p_name,
26522 : 59 : OMP_TARGET_CLAUSE_MASK, cclauses,
26523 : : if_p);
26524 : 59 : break;
26525 : 0 : default:
26526 : 0 : gcc_unreachable ();
26527 : : }
26528 : 2274 : block = c_end_compound_stmt (loc, block, true);
26529 : 2274 : if (ret == NULL_TREE)
26530 : : return false;
26531 : 2265 : if (ccode == OMP_TEAMS)
26532 : : /* For combined target teams, ensure the num_teams and
26533 : : thread_limit clause expressions are evaluated on the host,
26534 : : before entering the target construct. */
26535 : 2210 : for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26536 : 2210 : c; c = OMP_CLAUSE_CHAIN (c))
26537 : 481 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
26538 : 481 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
26539 : 202 : for (int i = 0;
26540 : 332 : i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
26541 : 202 : if (OMP_CLAUSE_OPERAND (c, i)
26542 : 202 : && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
26543 : : {
26544 : 129 : tree expr = OMP_CLAUSE_OPERAND (c, i);
26545 : 129 : tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
26546 : 129 : expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
26547 : : expr, NULL_TREE, NULL_TREE);
26548 : 129 : add_stmt (expr);
26549 : 129 : OMP_CLAUSE_OPERAND (c, i) = expr;
26550 : 129 : tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
26551 : : OMP_CLAUSE_FIRSTPRIVATE);
26552 : 129 : OMP_CLAUSE_DECL (tc) = tmp;
26553 : 129 : OMP_CLAUSE_CHAIN (tc)
26554 : 129 : = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26555 : 129 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
26556 : : }
26557 : 2265 : tree stmt = make_node (OMP_TARGET);
26558 : 2265 : TREE_TYPE (stmt) = void_type_node;
26559 : 2265 : OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26560 : 2265 : c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
26561 : 2265 : OMP_TARGET_BODY (stmt) = block;
26562 : 2265 : OMP_TARGET_COMBINED (stmt) = 1;
26563 : 2265 : SET_EXPR_LOCATION (stmt, loc);
26564 : 2265 : add_stmt (stmt);
26565 : 2265 : pc = &OMP_TARGET_CLAUSES (stmt);
26566 : 2265 : goto check_clauses;
26567 : : }
26568 : 4150 : else if (!flag_openmp) /* flag_openmp_simd */
26569 : : {
26570 : 0 : c_parser_skip_to_pragma_eol (parser, false);
26571 : 0 : return false;
26572 : : }
26573 : 4150 : else if (strcmp (p, "data") == 0)
26574 : : {
26575 : 155 : c_parser_consume_token (parser);
26576 : 155 : c_parser_omp_target_data (loc, parser, if_p);
26577 : 155 : return true;
26578 : : }
26579 : 3995 : else if (strcmp (p, "enter") == 0)
26580 : : {
26581 : 114 : c_parser_consume_token (parser);
26582 : 114 : return c_parser_omp_target_enter_data (loc, parser, context);
26583 : : }
26584 : 3881 : else if (strcmp (p, "exit") == 0)
26585 : : {
26586 : 107 : c_parser_consume_token (parser);
26587 : 107 : return c_parser_omp_target_exit_data (loc, parser, context);
26588 : : }
26589 : 3774 : else if (strcmp (p, "update") == 0)
26590 : : {
26591 : 2826 : c_parser_consume_token (parser);
26592 : 2826 : return c_parser_omp_target_update (loc, parser, context);
26593 : : }
26594 : : }
26595 : 1871 : if (!flag_openmp) /* flag_openmp_simd */
26596 : : {
26597 : 1 : c_parser_skip_to_pragma_eol (parser, false);
26598 : 1 : return false;
26599 : : }
26600 : :
26601 : 1870 : stmt = make_node (OMP_TARGET);
26602 : 1870 : TREE_TYPE (stmt) = void_type_node;
26603 : :
26604 : 1870 : clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
26605 : : "#pragma omp target", false);
26606 : 3654 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
26607 : 1784 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
26608 : : {
26609 : 50 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
26610 : 50 : OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
26611 : 50 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
26612 : 50 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
26613 : 50 : OMP_CLAUSE_CHAIN (c) = nc;
26614 : : }
26615 : 1870 : clauses = c_omp_instantiate_mappers (clauses);
26616 : 1870 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
26617 : 1870 : c_omp_adjust_map_clauses (clauses, true);
26618 : :
26619 : 1870 : keep_next_level ();
26620 : 1870 : block = c_begin_compound_stmt (true);
26621 : 1870 : body = c_parser_omp_structured_block (parser, if_p);
26622 : :
26623 : 1870 : c_omp_scan_mapper_bindings (loc, &clauses, body);
26624 : :
26625 : 1870 : add_stmt (body);
26626 : 1870 : OMP_TARGET_CLAUSES (stmt) = clauses;
26627 : 1870 : pc = &OMP_TARGET_CLAUSES (stmt);
26628 : 1870 : OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26629 : :
26630 : 1870 : SET_EXPR_LOCATION (stmt, loc);
26631 : 1870 : add_stmt (stmt);
26632 : :
26633 : : check_clauses:
26634 : 7679 : while (*pc)
26635 : : {
26636 : 3544 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26637 : 1944 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26638 : : {
26639 : : case GOMP_MAP_TO:
26640 : : case GOMP_MAP_ALWAYS_TO:
26641 : : case GOMP_MAP_PRESENT_TO:
26642 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26643 : : case GOMP_MAP_FROM:
26644 : : case GOMP_MAP_ALWAYS_FROM:
26645 : : case GOMP_MAP_PRESENT_FROM:
26646 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26647 : : case GOMP_MAP_TOFROM:
26648 : : case GOMP_MAP_ALWAYS_TOFROM:
26649 : : case GOMP_MAP_PRESENT_TOFROM:
26650 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26651 : : case GOMP_MAP_ALLOC:
26652 : : case GOMP_MAP_PRESENT_ALLOC:
26653 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26654 : : case GOMP_MAP_ALWAYS_POINTER:
26655 : : case GOMP_MAP_POINTER:
26656 : : case GOMP_MAP_ATTACH_DETACH:
26657 : : case GOMP_MAP_ATTACH:
26658 : : break;
26659 : 1 : default:
26660 : 1 : error_at (OMP_CLAUSE_LOCATION (*pc),
26661 : : "%<#pragma omp target%> with map-type other "
26662 : : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26663 : : "on %<map%> clause");
26664 : 1 : *pc = OMP_CLAUSE_CHAIN (*pc);
26665 : 1 : continue;
26666 : : }
26667 : 3543 : pc = &OMP_CLAUSE_CHAIN (*pc);
26668 : : }
26669 : 4135 : cfun->has_omp_target = true;
26670 : 4135 : return true;
26671 : : }
26672 : :
26673 : : /* OpenMP 4.0:
26674 : : # pragma omp declare simd declare-simd-clauses[optseq] new-line
26675 : :
26676 : : OpenMP 5.0:
26677 : : # pragma omp declare variant (identifier) match(context-selector) new-line
26678 : :
26679 : : OpenMP 5.1
26680 : : # pragma omp declare variant (identifier) match(context-selector) \
26681 : : adjust_args(adjust-op:argument-list) append_args(interop-list) new-line
26682 : : */
26683 : :
26684 : : #define OMP_DECLARE_SIMD_CLAUSE_MASK \
26685 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
26686 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
26687 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
26688 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
26689 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
26690 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
26691 : :
26692 : : static void
26693 : 700 : c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
26694 : : {
26695 : 700 : c_token *token = c_parser_peek_token (parser);
26696 : 700 : gcc_assert (token->type == CPP_NAME);
26697 : 700 : tree kind = token->value;
26698 : 700 : gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
26699 : : || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
26700 : :
26701 : 700 : auto_vec<c_token> clauses;
26702 : 11099 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
26703 : : {
26704 : 10399 : c_token *token = c_parser_peek_token (parser);
26705 : 10399 : if (token->type == CPP_EOF)
26706 : : {
26707 : 0 : c_parser_skip_to_pragma_eol (parser);
26708 : 0 : return;
26709 : : }
26710 : 10399 : clauses.safe_push (*token);
26711 : 10399 : c_parser_consume_token (parser);
26712 : : }
26713 : 700 : clauses.safe_push (*c_parser_peek_token (parser));
26714 : 700 : c_parser_skip_to_pragma_eol (parser);
26715 : :
26716 : 1604 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
26717 : : {
26718 : 206 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
26719 : 204 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
26720 : 410 : || c_parser_peek_2nd_token (parser)->value != kind)
26721 : : {
26722 : 2 : error ("%<#pragma omp declare %s%> must be followed by "
26723 : : "function declaration or definition or another "
26724 : : "%<#pragma omp declare %s%>",
26725 : 2 : IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
26726 : 2 : return;
26727 : : }
26728 : 204 : c_parser_consume_pragma (parser);
26729 : 4460 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
26730 : : {
26731 : 4052 : c_token *token = c_parser_peek_token (parser);
26732 : 4052 : if (token->type == CPP_EOF)
26733 : : {
26734 : 0 : c_parser_skip_to_pragma_eol (parser);
26735 : 0 : return;
26736 : : }
26737 : 4052 : clauses.safe_push (*token);
26738 : 4052 : c_parser_consume_token (parser);
26739 : : }
26740 : 204 : clauses.safe_push (*c_parser_peek_token (parser));
26741 : 204 : c_parser_skip_to_pragma_eol (parser);
26742 : : }
26743 : :
26744 : : /* Make sure nothing tries to read past the end of the tokens. */
26745 : 698 : c_token eof_token;
26746 : 698 : memset (&eof_token, 0, sizeof (eof_token));
26747 : 698 : eof_token.type = CPP_EOF;
26748 : 698 : clauses.safe_push (eof_token);
26749 : 698 : clauses.safe_push (eof_token);
26750 : :
26751 : 698 : switch (context)
26752 : : {
26753 : 681 : case pragma_external:
26754 : 681 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26755 : 681 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26756 : : {
26757 : 1 : int ext = disable_extension_diagnostics ();
26758 : 1 : do
26759 : 1 : c_parser_consume_token (parser);
26760 : 1 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
26761 : 2 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26762 : 1 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
26763 : : false, NULL, &clauses);
26764 : 1 : restore_extension_diagnostics (ext);
26765 : : }
26766 : : else
26767 : 680 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
26768 : : false, NULL, &clauses);
26769 : : break;
26770 : 6 : case pragma_struct:
26771 : 6 : case pragma_param:
26772 : 6 : case pragma_stmt:
26773 : 6 : error ("%<#pragma omp declare %s%> must be followed by "
26774 : : "function declaration or definition",
26775 : 6 : IDENTIFIER_POINTER (kind));
26776 : 6 : break;
26777 : 11 : case pragma_compound:
26778 : 11 : bool have_std_attrs;
26779 : 11 : tree std_attrs;
26780 : 11 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
26781 : 11 : if (have_std_attrs)
26782 : 1 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
26783 : : else
26784 : : std_attrs = NULL_TREE;
26785 : 11 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26786 : 11 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26787 : : {
26788 : 1 : int ext = disable_extension_diagnostics ();
26789 : 3 : do
26790 : 3 : c_parser_consume_token (parser);
26791 : 3 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
26792 : 4 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26793 : 1 : if (c_parser_next_tokens_start_declaration (parser)
26794 : 1 : || c_parser_nth_token_starts_std_attributes (parser, 1))
26795 : : {
26796 : 1 : c_parser_declaration_or_fndef (parser, true, true, true, true,
26797 : : true, false, NULL, &clauses,
26798 : : have_std_attrs, std_attrs);
26799 : 1 : restore_extension_diagnostics (ext);
26800 : 1 : break;
26801 : : }
26802 : 0 : restore_extension_diagnostics (ext);
26803 : : }
26804 : 10 : else if (c_parser_next_tokens_start_declaration (parser))
26805 : : {
26806 : 10 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
26807 : : false, NULL, &clauses, have_std_attrs,
26808 : : std_attrs);
26809 : 10 : break;
26810 : : }
26811 : 0 : error ("%<#pragma omp declare %s%> must be followed by "
26812 : : "function declaration or definition",
26813 : 0 : IDENTIFIER_POINTER (kind));
26814 : 0 : break;
26815 : 0 : default:
26816 : 0 : gcc_unreachable ();
26817 : : }
26818 : 700 : }
26819 : :
26820 : : /* OpenMP 5.0:
26821 : :
26822 : : trait-selector:
26823 : : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
26824 : :
26825 : : trait-score:
26826 : : score(score-expression)
26827 : :
26828 : : Note that this function returns a list of trait selectors for the
26829 : : trait-selector-set SET. */
26830 : :
26831 : : static tree
26832 : 945 : c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
26833 : : tree parms)
26834 : : {
26835 : 945 : tree ret = NULL_TREE;
26836 : 1123 : do
26837 : : {
26838 : 1123 : tree selector;
26839 : 1123 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26840 : 2188 : || c_parser_next_token_is (parser, CPP_NAME))
26841 : 1121 : selector = c_parser_peek_token (parser)->value;
26842 : : else
26843 : : {
26844 : 2 : c_parser_error (parser, "expected trait selector name");
26845 : 2 : return error_mark_node;
26846 : : }
26847 : 1121 : enum omp_ts_code sel
26848 : 1121 : = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
26849 : :
26850 : 1121 : if (sel == OMP_TRAIT_INVALID)
26851 : : {
26852 : : /* Per the spec, "Implementations can ignore specified selectors
26853 : : that are not those described in this section"; however, we
26854 : : must record such selectors because they cause match failures. */
26855 : 18 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
26856 : : "unknown selector %qs for context selector set %qs",
26857 : 18 : IDENTIFIER_POINTER (selector), omp_tss_map[set]);
26858 : 18 : c_parser_consume_token (parser);
26859 : 18 : ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
26860 : 18 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
26861 : 5 : c_parser_balanced_token_sequence (parser);
26862 : 18 : if (c_parser_next_token_is (parser, CPP_COMMA))
26863 : : {
26864 : 1 : c_parser_consume_token (parser);
26865 : 1 : continue;
26866 : : }
26867 : : else
26868 : : break;
26869 : : }
26870 : :
26871 : 1103 : c_parser_consume_token (parser);
26872 : :
26873 : 1103 : tree properties = NULL_TREE;
26874 : 1103 : tree scoreval = NULL_TREE;
26875 : 1103 : enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
26876 : 1103 : bool allow_score = omp_ts_map[sel].allow_score;
26877 : 1103 : tree t;
26878 : :
26879 : 1103 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
26880 : : {
26881 : 639 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
26882 : : {
26883 : 12 : error_at (c_parser_peek_token (parser)->location,
26884 : : "selector %qs does not accept any properties",
26885 : 6 : IDENTIFIER_POINTER (selector));
26886 : 16 : return error_mark_node;
26887 : : }
26888 : :
26889 : 633 : matching_parens parens;
26890 : 633 : parens.require_open (parser);
26891 : :
26892 : 633 : c_token *token = c_parser_peek_token (parser);
26893 : 633 : if (c_parser_next_token_is (parser, CPP_NAME)
26894 : 472 : && strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
26895 : 721 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
26896 : : {
26897 : 88 : c_parser_consume_token (parser);
26898 : :
26899 : 88 : matching_parens parens2;
26900 : 88 : parens2.require_open (parser);
26901 : 88 : tree score = c_parser_expr_no_commas (parser, NULL).value;
26902 : 88 : parens2.skip_until_found_close (parser);
26903 : 88 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
26904 : 88 : if (!allow_score)
26905 : 13 : error_at (token->location,
26906 : : "%<score%> cannot be specified in traits "
26907 : : "in the %qs trait-selector-set",
26908 : : omp_tss_map[set]);
26909 : 75 : else if (score != error_mark_node)
26910 : : {
26911 : 75 : mark_exp_read (score);
26912 : 75 : score = c_fully_fold (score, false, NULL);
26913 : 150 : if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
26914 : 149 : || TREE_CODE (score) != INTEGER_CST)
26915 : 1 : error_at (token->location, "%<score%> argument must "
26916 : : "be constant integer expression");
26917 : 74 : else if (tree_int_cst_sgn (score) < 0)
26918 : 1 : error_at (token->location, "%<score%> argument must "
26919 : : "be non-negative");
26920 : : else
26921 : : scoreval = score;
26922 : : }
26923 : 88 : token = c_parser_peek_token (parser);
26924 : : }
26925 : :
26926 : 633 : switch (property_kind)
26927 : : {
26928 : 25 : case OMP_TRAIT_PROPERTY_ID:
26929 : 25 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26930 : 50 : || c_parser_next_token_is (parser, CPP_NAME))
26931 : : {
26932 : 24 : tree prop = c_parser_peek_token (parser)->value;
26933 : 24 : c_parser_consume_token (parser);
26934 : 24 : properties = make_trait_property (prop, NULL_TREE,
26935 : : properties);
26936 : : }
26937 : : else
26938 : : {
26939 : 1 : c_parser_error (parser, "expected identifier");
26940 : 1 : return error_mark_node;
26941 : : }
26942 : 24 : break;
26943 : 523 : case OMP_TRAIT_PROPERTY_NAME_LIST:
26944 : 581 : do
26945 : : {
26946 : 523 : tree prop = OMP_TP_NAMELIST_NODE;
26947 : 523 : tree value = NULL_TREE;
26948 : 523 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26949 : 1046 : || c_parser_next_token_is (parser, CPP_NAME))
26950 : : {
26951 : 390 : value = c_parser_peek_token (parser)->value;
26952 : 390 : c_parser_consume_token (parser);
26953 : : }
26954 : 133 : else if (c_parser_next_token_is (parser, CPP_STRING))
26955 : 128 : value = c_parser_string_literal (parser, false,
26956 : : false).value;
26957 : : else
26958 : : {
26959 : 5 : c_parser_error (parser, "expected identifier or "
26960 : : "string literal");
26961 : 5 : return error_mark_node;
26962 : : }
26963 : :
26964 : 518 : properties = make_trait_property (prop, value, properties);
26965 : :
26966 : 518 : if (c_parser_next_token_is (parser, CPP_COMMA))
26967 : 58 : c_parser_consume_token (parser);
26968 : : else
26969 : : break;
26970 : 58 : }
26971 : : while (1);
26972 : : break;
26973 : 120 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
26974 : 120 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
26975 : 120 : {
26976 : 120 : c_expr texpr = c_parser_expr_no_commas (parser, NULL);
26977 : 120 : texpr = convert_lvalue_to_rvalue (token->location, texpr,
26978 : : true, true);
26979 : 120 : t = texpr.value;
26980 : : }
26981 : 120 : if (t == error_mark_node)
26982 : : return error_mark_node;
26983 : 118 : mark_exp_read (t);
26984 : 118 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
26985 : : {
26986 : 95 : t = c_objc_common_truthvalue_conversion (token->location,
26987 : : t,
26988 : : boolean_type_node);
26989 : 95 : if (t == error_mark_node)
26990 : : return error_mark_node;
26991 : : }
26992 : 23 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
26993 : : {
26994 : 0 : error_at (token->location,
26995 : : "property must be integer expression");
26996 : 0 : return error_mark_node;
26997 : : }
26998 : 116 : t = c_fully_fold (t, false, NULL);
26999 : 116 : properties = make_trait_property (NULL_TREE, t, properties);
27000 : 116 : break;
27001 : 23 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
27002 : 23 : if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
27003 : : {
27004 : 23 : if (parms == NULL_TREE)
27005 : : {
27006 : 0 : error_at (token->location, "properties for %<simd%> "
27007 : : "selector may not be specified in "
27008 : : "%<metadirective%>");
27009 : 0 : return error_mark_node;
27010 : : }
27011 : 23 : tree c;
27012 : 46 : c = c_parser_omp_all_clauses (parser,
27013 : 23 : OMP_DECLARE_SIMD_CLAUSE_MASK,
27014 : : "simd", true, 2);
27015 : 46 : c = c_omp_declare_simd_clauses_to_numbers (parms
27016 : 23 : == error_mark_node
27017 : : ? NULL_TREE : parms,
27018 : : c);
27019 : 23 : properties = c;
27020 : : }
27021 : 0 : else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
27022 : : {
27023 : : /* FIXME: The "requires" selector was added in OpenMP 5.1.
27024 : : Currently only the now-deprecated syntax
27025 : : from OpenMP 5.0 is supported. */
27026 : 0 : sorry_at (token->location,
27027 : : "%<requires%> selector is not supported yet");
27028 : 0 : return error_mark_node;
27029 : : }
27030 : : else
27031 : 0 : gcc_unreachable ();
27032 : 23 : break;
27033 : 0 : default:
27034 : 0 : gcc_unreachable ();
27035 : : }
27036 : :
27037 : 623 : parens.skip_until_found_close (parser);
27038 : 623 : properties = nreverse (properties);
27039 : : }
27040 : 464 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
27041 : 464 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
27042 : 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
27043 : : {
27044 : 8 : c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
27045 : 8 : return error_mark_node;
27046 : : }
27047 : :
27048 : 1079 : ret = make_trait_selector (sel, scoreval, properties, ret);
27049 : :
27050 : 1079 : if (c_parser_next_token_is (parser, CPP_COMMA))
27051 : 177 : c_parser_consume_token (parser);
27052 : : else
27053 : : break;
27054 : : }
27055 : : while (1);
27056 : :
27057 : 919 : return nreverse (ret);
27058 : : }
27059 : :
27060 : : /* OpenMP 5.0:
27061 : :
27062 : : trait-set-selector[,trait-set-selector[,...]]
27063 : :
27064 : : trait-set-selector:
27065 : : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
27066 : :
27067 : : trait-set-selector-name:
27068 : : constructor
27069 : : device
27070 : : implementation
27071 : : user */
27072 : :
27073 : : static tree
27074 : 727 : c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
27075 : : {
27076 : 727 : tree ret = NULL_TREE;
27077 : 1179 : do
27078 : : {
27079 : 953 : const char *setp = "";
27080 : 953 : if (c_parser_next_token_is (parser, CPP_NAME))
27081 : 951 : setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27082 : 953 : enum omp_tss_code set = omp_lookup_tss_code (setp);
27083 : :
27084 : 953 : if (set == OMP_TRAIT_SET_INVALID)
27085 : : {
27086 : 5 : c_parser_error (parser, "expected context selector set name");
27087 : 8 : return error_mark_node;
27088 : : }
27089 : :
27090 : 948 : c_parser_consume_token (parser);
27091 : :
27092 : 948 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
27093 : 1 : return error_mark_node;
27094 : :
27095 : 947 : matching_braces braces;
27096 : 947 : if (!braces.require_open (parser))
27097 : 2 : return error_mark_node;
27098 : :
27099 : 945 : tree selectors = c_parser_omp_context_selector (parser, set, parms);
27100 : 945 : if (selectors == error_mark_node)
27101 : : {
27102 : 26 : c_parser_skip_to_closing_brace (parser);
27103 : 26 : ret = error_mark_node;
27104 : : }
27105 : 919 : else if (ret != error_mark_node)
27106 : 919 : ret = make_trait_set_selector (set, selectors, ret);
27107 : :
27108 : 945 : braces.require_close (parser);
27109 : :
27110 : 945 : if (c_parser_next_token_is (parser, CPP_COMMA))
27111 : 226 : c_parser_consume_token (parser);
27112 : : else
27113 : : break;
27114 : 226 : }
27115 : : while (1);
27116 : :
27117 : 719 : if (ret == error_mark_node)
27118 : : return ret;
27119 : 693 : return nreverse (ret);
27120 : : }
27121 : :
27122 : : /* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
27123 : : that into "omp declare variant base" attribute. */
27124 : :
27125 : : static void
27126 : 610 : c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
27127 : : {
27128 : 610 : matching_parens parens;
27129 : 610 : if (!parens.require_open (parser))
27130 : : {
27131 : 3 : fail:
27132 : 50 : c_parser_skip_to_pragma_eol (parser, false);
27133 : 50 : return;
27134 : : }
27135 : :
27136 : 607 : if (c_parser_next_token_is_not (parser, CPP_NAME)
27137 : 607 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
27138 : : {
27139 : 3 : c_parser_error (parser, "expected identifier");
27140 : 3 : goto fail;
27141 : : }
27142 : :
27143 : 604 : c_token *token = c_parser_peek_token (parser);
27144 : 604 : tree variant = lookup_name (token->value);
27145 : :
27146 : 604 : if (variant == NULL_TREE)
27147 : : {
27148 : 3 : undeclared_variable (token->location, token->value);
27149 : 3 : variant = error_mark_node;
27150 : : }
27151 : :
27152 : 604 : c_parser_consume_token (parser);
27153 : :
27154 : 604 : parens.require_close (parser);
27155 : :
27156 : 604 : tree append_args_tree = NULL_TREE;
27157 : 604 : tree append_args_last;
27158 : 604 : vec<tree> adjust_args_list = vNULL;
27159 : 604 : bool has_match = false, has_adjust_args = false;
27160 : 604 : location_t adjust_args_loc = UNKNOWN_LOCATION;
27161 : 604 : location_t append_args_loc = UNKNOWN_LOCATION;
27162 : 604 : location_t match_loc = UNKNOWN_LOCATION;
27163 : 604 : tree need_device_ptr_list = NULL_TREE;
27164 : 604 : tree ctx = error_mark_node;
27165 : :
27166 : 702 : do
27167 : : {
27168 : 702 : if (c_parser_next_token_is (parser, CPP_COMMA)
27169 : 702 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
27170 : 9 : c_parser_consume_token (parser);
27171 : :
27172 : 702 : const char *clause = "";
27173 : 702 : location_t loc = c_parser_peek_token (parser)->location;
27174 : 702 : if (c_parser_next_token_is (parser, CPP_NAME))
27175 : 701 : clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27176 : :
27177 : 702 : enum clause
27178 : : {
27179 : : match,
27180 : : adjust_args,
27181 : : append_args
27182 : : } ccode;
27183 : :
27184 : 702 : if (strcmp (clause, "match") == 0)
27185 : : {
27186 : : ccode = match;
27187 : : match_loc = loc;
27188 : : }
27189 : 101 : else if (strcmp (clause, "adjust_args") == 0)
27190 : : {
27191 : : ccode = adjust_args;
27192 : : adjust_args_loc = loc;
27193 : : }
27194 : 49 : else if (strcmp (clause, "append_args") == 0)
27195 : : {
27196 : : ccode = append_args;
27197 : : append_args_loc = loc;
27198 : : }
27199 : : else
27200 : : {
27201 : 2 : c_parser_error (parser, "expected %<match%>, %<adjust_args%> or "
27202 : : "%<append_args%> clause");
27203 : 2 : goto fail;
27204 : : }
27205 : :
27206 : 700 : c_parser_consume_token (parser);
27207 : :
27208 : 700 : if (!parens.require_open (parser))
27209 : 1 : goto fail;
27210 : :
27211 : 699 : if (parms == NULL_TREE)
27212 : 445 : parms = error_mark_node;
27213 : :
27214 : 699 : if (ccode == match)
27215 : : {
27216 : 600 : if (has_match)
27217 : 1 : error_at (match_loc, "too many %<match%> clauses");
27218 : 600 : has_match = true;
27219 : 600 : ctx = c_parser_omp_context_selector_specification (parser, parms);
27220 : 600 : if (ctx == error_mark_node)
27221 : 32 : goto fail;
27222 : 568 : ctx = omp_check_context_selector (match_loc, ctx,
27223 : : OMP_CTX_DECLARE_VARIANT);
27224 : 568 : if (ctx != error_mark_node && variant != error_mark_node)
27225 : : {
27226 : 543 : if (TREE_CODE (variant) != FUNCTION_DECL)
27227 : : {
27228 : 1 : error_at (token->location, "variant %qD is not a function",
27229 : : variant);
27230 : 1 : variant = error_mark_node;
27231 : : }
27232 : 542 : else if (fndecl_built_in_p (variant)
27233 : 542 : && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27234 : : "__builtin_", strlen ("__builtin_"))
27235 : : == 0
27236 : 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27237 : : "__sync_", strlen ("__sync_"))
27238 : : == 0
27239 : 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27240 : : "__atomic_", strlen ("__atomic_"))
27241 : : == 0))
27242 : : {
27243 : 1 : error_at (token->location, "variant %qD is a built-in",
27244 : : variant);
27245 : 1 : variant = error_mark_node;
27246 : : }
27247 : : }
27248 : : }
27249 : 99 : else if (ccode == adjust_args)
27250 : : {
27251 : 52 : has_adjust_args = true;
27252 : 52 : if (c_parser_next_token_is (parser, CPP_NAME)
27253 : 52 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
27254 : : {
27255 : 50 : const char *p
27256 : 50 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27257 : 50 : if (strcmp (p, "need_device_ptr") == 0
27258 : 15 : || strcmp (p, "nothing") == 0)
27259 : : {
27260 : 48 : c_parser_consume_token (parser); // need_device_ptr
27261 : 48 : c_parser_consume_token (parser); // :
27262 : :
27263 : 48 : loc = c_parser_peek_token (parser)->location;
27264 : 48 : tree list
27265 : 48 : = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_ERROR,
27266 : : NULL_TREE);
27267 : :
27268 : 48 : tree arg;
27269 : 48 : if (variant != error_mark_node)
27270 : 103 : for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
27271 : : {
27272 : 61 : tree decl = TREE_PURPOSE (c);
27273 : 61 : location_t arg_loc = EXPR_LOCATION (TREE_VALUE (c));
27274 : 61 : int idx;
27275 : 111 : for (arg = parms, idx = 0; arg != NULL;
27276 : 50 : arg = TREE_CHAIN (arg), idx++)
27277 : 110 : if (arg == decl)
27278 : : break;
27279 : 61 : if (arg == NULL_TREE)
27280 : : {
27281 : 1 : error_at (arg_loc,
27282 : : "%qD is not a function argument",
27283 : : decl);
27284 : 5 : goto fail;
27285 : : }
27286 : 60 : if (adjust_args_list.contains (arg))
27287 : : {
27288 : 3 : error_at (arg_loc,
27289 : : "%qD is specified more than once",
27290 : : decl);
27291 : 3 : goto fail;
27292 : : }
27293 : 57 : if (strcmp (p, "need_device_ptr") == 0
27294 : 57 : && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
27295 : : {
27296 : 1 : error_at (loc, "%qD is not of pointer type", decl);
27297 : 1 : goto fail;
27298 : : }
27299 : 56 : adjust_args_list.safe_push (arg);
27300 : 56 : if (strcmp (p, "need_device_ptr") == 0)
27301 : : {
27302 : 46 : need_device_ptr_list = chainon (
27303 : : need_device_ptr_list,
27304 : : build_tree_list (
27305 : : NULL_TREE,
27306 : : build_int_cst (
27307 : : integer_type_node,
27308 : 46 : idx))); // Store 0-based argument index,
27309 : : // as in gimplify_call_expr
27310 : : }
27311 : : }
27312 : 43 : }
27313 : : else
27314 : : {
27315 : 2 : error_at (c_parser_peek_token (parser)->location,
27316 : : "expected %<nothing%> or %<need_device_ptr%>");
27317 : 2 : if (strcmp (p, "need_device_addr") == 0)
27318 : 1 : inform (c_parser_peek_token (parser)->location,
27319 : : "%<need_device_addr%> is not valid for C");
27320 : 2 : goto fail;
27321 : : }
27322 : : }
27323 : : else
27324 : : {
27325 : 2 : error_at (c_parser_peek_token (parser)->location,
27326 : : "expected %<nothing%> or %<need_device_ptr%> "
27327 : : "followed by %<:%>");
27328 : 2 : goto fail;
27329 : : }
27330 : : }
27331 : 47 : else if (ccode == append_args)
27332 : : {
27333 : 47 : if (append_args_tree)
27334 : : {
27335 : 1 : error_at (append_args_loc, "too many %qs clauses", "append_args");
27336 : 1 : append_args_tree = NULL_TREE;
27337 : : }
27338 : 85 : do
27339 : : {
27340 : 66 : location_t loc = c_parser_peek_token (parser)->location;
27341 : 66 : if (!c_parser_next_token_is (parser, CPP_NAME)
27342 : 66 : || strcmp ("interop",
27343 : 66 : IDENTIFIER_POINTER (
27344 : : c_parser_peek_token (parser)->value)))
27345 : : {
27346 : 0 : error_at (loc, "expected %<interop%>");
27347 : 0 : goto fail;
27348 : : }
27349 : 66 : c_parser_consume_token (parser);
27350 : :
27351 : 66 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
27352 : 0 : goto fail;
27353 : 66 : bool target = false;
27354 : 66 : bool targetsync = false;
27355 : 66 : tree prefer_type_tree = NULL_TREE;
27356 : 66 : if (!c_parser_omp_clause_init_modifiers (parser, &target,
27357 : : &targetsync,
27358 : : &prefer_type_tree)
27359 : 66 : || !c_parser_require (parser, CPP_CLOSE_PAREN,
27360 : : "expected %<)%> or %<,%>"))
27361 : 0 : goto fail;
27362 : 66 : if (!target && !targetsync)
27363 : 3 : error_at (loc,
27364 : : "missing required %<target%> and/or "
27365 : : "%<targetsync%> modifier");
27366 : 66 : tree t = build_tree_list (target ? boolean_true_node
27367 : : : boolean_false_node,
27368 : : targetsync ? boolean_true_node
27369 : : : boolean_false_node);
27370 : 66 : t = build1_loc (loc, NOP_EXPR, void_type_node, t);
27371 : 66 : t = build_tree_list (t, prefer_type_tree);
27372 : 66 : if (append_args_tree)
27373 : : {
27374 : 19 : TREE_CHAIN (append_args_last) = t;
27375 : 19 : append_args_last = t;
27376 : : }
27377 : : else
27378 : : append_args_tree = append_args_last = t;
27379 : 66 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
27380 : : break;
27381 : 19 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
27382 : 0 : goto fail;
27383 : 19 : }
27384 : : while (true);
27385 : : }
27386 : :
27387 : 658 : parens.require_close (parser);
27388 : 658 : } while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL));
27389 : 560 : c_parser_skip_to_pragma_eol (parser);
27390 : :
27391 : 537 : if ((ctx != error_mark_node && variant != error_mark_node)
27392 : 1092 : && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27393 : : OMP_TRAIT_CONSTRUCT_SIMD))
27394 : : {
27395 : 509 : bool fail = false;
27396 : 509 : if (append_args_tree)
27397 : : {
27398 : 46 : int nappend_args = 0;
27399 : 46 : int nbase_args = 0;
27400 : 46 : for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27401 : 188 : t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
27402 : 55 : nbase_args++;
27403 : 111 : for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
27404 : 65 : nappend_args++;
27405 : :
27406 : : /* Store as purpose = arg number after which to append
27407 : : and value = list of interop items. */
27408 : 46 : append_args_tree = build_tree_list (build_int_cst (integer_type_node,
27409 : 46 : nbase_args),
27410 : : append_args_tree);
27411 : 46 : tree args, arg;
27412 : 46 : args = arg = TYPE_ARG_TYPES (TREE_TYPE (variant));
27413 : 97 : for (int j = 0; j < nbase_args && arg; j++, arg = TREE_CHAIN (arg))
27414 : 51 : args = arg;
27415 : 105 : for (int i = 0; i < nappend_args && arg; i++)
27416 : 59 : arg = TREE_CHAIN (arg);
27417 : 46 : tree saved_args;
27418 : 46 : if (nbase_args && args)
27419 : : {
27420 : 21 : saved_args = TREE_CHAIN (args);
27421 : 21 : TREE_CHAIN (args) = arg;
27422 : : }
27423 : : else
27424 : : {
27425 : 25 : saved_args = args;
27426 : 25 : TYPE_ARG_TYPES (TREE_TYPE (variant)) = arg;
27427 : 25 : TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 1;
27428 : : }
27429 : 46 : if (!comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
27430 : 7 : fail = true;
27431 : 46 : if (nbase_args && args)
27432 : 21 : TREE_CHAIN (args) = saved_args;
27433 : : else
27434 : : {
27435 : 25 : TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_args;
27436 : 25 : TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 0;
27437 : : }
27438 : 46 : arg = saved_args;
27439 : 46 : if (!fail)
27440 : 87 : for (int i = 0; i < nappend_args; i++, arg = TREE_CHAIN (arg))
27441 : 107 : if (!arg || !c_omp_interop_t_p (TREE_VALUE (arg)))
27442 : : {
27443 : 7 : error_at (DECL_SOURCE_LOCATION (variant),
27444 : : "argument %d of %qD must be of %<omp_interop_t%>",
27445 : 7 : nbase_args + i + 1, variant);
27446 : 7 : inform (append_args_loc, "%<append_args%> specified here");
27447 : 7 : break;
27448 : : }
27449 : : }
27450 : : else
27451 : : {
27452 : 463 : if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
27453 : : {
27454 : 462 : if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE
27455 : 462 : && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE)
27456 : : {
27457 : 1 : if (!append_args_tree)
27458 : 1 : TYPE_ARG_TYPES (TREE_TYPE (variant))
27459 : 1 : = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27460 : : else
27461 : : {
27462 : : tree new_args = NULL_TREE;
27463 : : tree arg, last_arg = NULL_TREE;
27464 : : for (arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27465 : : arg && arg != void_type_node; arg = TREE_CHAIN (arg))
27466 : : {
27467 : : if (new_args == NULL_TREE)
27468 : : new_args = last_arg = copy_node (arg);
27469 : : else
27470 : : {
27471 : : TREE_CHAIN (last_arg) = copy_node (arg);
27472 : : last_arg = TREE_CHAIN (last_arg);
27473 : : }
27474 : : }
27475 : : for (tree t3 = append_args_tree; t3; t3 = TREE_CHAIN (t3))
27476 : : {
27477 : : tree type = lookup_name (get_identifier ("omp_interop_t"));
27478 : : type = type ? TREE_TYPE (type) : ptr_type_node;
27479 : : last_arg = tree_cons (NULL_TREE, type, last_arg);
27480 : : }
27481 : : TREE_CHAIN (last_arg) = arg;
27482 : : TYPE_ARG_TYPES (TREE_TYPE (variant)) = new_args;
27483 : : }
27484 : : }
27485 : : }
27486 : : else
27487 : : fail = true;
27488 : : }
27489 : 1 : if (fail)
27490 : : {
27491 : 8 : error_at (token->location,
27492 : : "variant %qD and base %qD have incompatible types",
27493 : : variant, fndecl);
27494 : 8 : variant = error_mark_node;
27495 : : }
27496 : : }
27497 : 560 : if (ctx != error_mark_node && variant != error_mark_node)
27498 : : {
27499 : 524 : C_DECL_USED (variant) = 1;
27500 : 524 : tree construct = omp_get_context_selector_list (ctx,
27501 : : OMP_TRAIT_SET_CONSTRUCT);
27502 : 524 : omp_mark_declare_variant (match_loc, variant, construct);
27503 : 524 : if (omp_context_selector_matches (ctx, NULL_TREE, false))
27504 : : {
27505 : 248 : tree attr = tree_cons (get_identifier ("omp declare variant base"),
27506 : : build_tree_list (variant, ctx),
27507 : 248 : DECL_ATTRIBUTES (fndecl));
27508 : 248 : DECL_ATTRIBUTES (fndecl) = attr;
27509 : : }
27510 : : }
27511 : :
27512 : 560 : if (has_adjust_args || append_args_tree)
27513 : : {
27514 : 66 : if (!has_match)
27515 : : {
27516 : 1 : error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
27517 : : "an %qs clause requires a %<match%> clause",
27518 : : has_adjust_args ? "adjust_args" : "append_args");
27519 : : }
27520 : 65 : else if (ctx != error_mark_node && variant != error_mark_node)
27521 : : {
27522 : 57 : tree attr = lookup_attribute ("omp declare variant base",
27523 : 57 : DECL_ATTRIBUTES (fndecl));
27524 : 57 : if (attr != NULL_TREE)
27525 : : {
27526 : 57 : tree ctx = TREE_VALUE (TREE_VALUE (attr));
27527 : 57 : if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27528 : : OMP_TRAIT_CONSTRUCT_DISPATCH))
27529 : 1 : error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
27530 : : "an %qs clause can only be specified if the "
27531 : : "%<dispatch%> selector of the %<construct%> selector "
27532 : : "set appears in the %<match%> clause",
27533 : : has_adjust_args ? "adjust_args" : "append_args");
27534 : : }
27535 : : }
27536 : : }
27537 : :
27538 : 560 : if ((ctx != error_mark_node && variant != error_mark_node)
27539 : 524 : && (need_device_ptr_list || append_args_tree))
27540 : : {
27541 : 54 : tree variant_decl = tree_strip_nop_conversions (variant);
27542 : 54 : tree t = build_tree_list (need_device_ptr_list,
27543 : : NULL_TREE /* need_device_addr */);
27544 : 54 : TREE_CHAIN (t) = append_args_tree;
27545 : 54 : DECL_ATTRIBUTES (variant_decl)
27546 : 108 : = tree_cons (get_identifier ("omp declare variant variant args"), t,
27547 : 54 : DECL_ATTRIBUTES (variant_decl));
27548 : : }
27549 : : }
27550 : :
27551 : : /* Finalize #pragma omp declare simd or #pragma omp declare variant
27552 : : clauses after FNDECL has been parsed, and put that into "omp declare simd"
27553 : : or "omp declare variant base" attribute. */
27554 : :
27555 : : static void
27556 : 772 : c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
27557 : : vec<c_token> *pclauses)
27558 : : {
27559 : 772 : vec<c_token> &clauses = *pclauses;
27560 : :
27561 : : /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
27562 : : indicates error has been reported and CPP_PRAGMA that
27563 : : c_finish_omp_declare_simd has already processed the tokens. */
27564 : 1544 : if (clauses.exists () && clauses[0].type == CPP_EOF)
27565 : : return;
27566 : 768 : const char *kind = "simd";
27567 : 768 : if (clauses.exists ()
27568 : 1536 : && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
27569 : 768 : kind = IDENTIFIER_POINTER (clauses[0].value);
27570 : 768 : gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
27571 : 768 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
27572 : : {
27573 : 15 : error ("%<#pragma omp declare %s%> not immediately followed by "
27574 : : "a function declaration or definition", kind);
27575 : 15 : clauses[0].type = CPP_EOF;
27576 : 15 : return;
27577 : : }
27578 : 1506 : if (clauses.exists () && clauses[0].type != CPP_NAME)
27579 : : {
27580 : 2 : error_at (DECL_SOURCE_LOCATION (fndecl),
27581 : : "%<#pragma omp declare %s%> not immediately followed by "
27582 : : "a single function declaration or definition", kind);
27583 : 2 : clauses[0].type = CPP_EOF;
27584 : 2 : return;
27585 : : }
27586 : :
27587 : 751 : if (parms == NULL_TREE)
27588 : 517 : parms = DECL_ARGUMENTS (fndecl);
27589 : :
27590 : 751 : unsigned int tokens_avail = parser->tokens_avail;
27591 : 751 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27592 : :
27593 : 751 : parser->tokens = clauses.address ();
27594 : 751 : parser->tokens_avail = clauses.length ();
27595 : :
27596 : : /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
27597 : 1724 : while (parser->tokens_avail > 3)
27598 : : {
27599 : 973 : c_token *token = c_parser_peek_token (parser);
27600 : 973 : gcc_assert (token->type == CPP_NAME);
27601 : 973 : kind = IDENTIFIER_POINTER (token->value);
27602 : 973 : c_parser_consume_token (parser);
27603 : 973 : parser->in_pragma = true;
27604 : :
27605 : 973 : if (strcmp (kind, "simd") == 0)
27606 : : {
27607 : 363 : tree c;
27608 : 363 : c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
27609 : : "#pragma omp declare simd");
27610 : 363 : c = c_omp_declare_simd_clauses_to_numbers (parms, c);
27611 : 363 : if (c != NULL_TREE)
27612 : 258 : c = tree_cons (NULL_TREE, c, NULL_TREE);
27613 : 363 : c = build_tree_list (get_identifier ("omp declare simd"), c);
27614 : 363 : TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
27615 : 363 : DECL_ATTRIBUTES (fndecl) = c;
27616 : : }
27617 : : else
27618 : : {
27619 : 610 : gcc_assert (strcmp (kind, "variant") == 0);
27620 : 610 : c_finish_omp_declare_variant (parser, fndecl, parms);
27621 : : }
27622 : : }
27623 : :
27624 : 751 : parser->tokens = &parser->tokens_buf[0];
27625 : 751 : parser->tokens_avail = tokens_avail;
27626 : 751 : if (clauses.exists ())
27627 : 751 : clauses[0].type = CPP_PRAGMA;
27628 : : }
27629 : :
27630 : : /* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
27631 : : a threadprivate, groupprivate, allocate or declare target directive,
27632 : : return true and parse it for DECL. */
27633 : :
27634 : : bool
27635 : 38 : c_maybe_parse_omp_decl (tree decl, tree d)
27636 : : {
27637 : 38 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
27638 : 38 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
27639 : 38 : c_token *first = toks->address ();
27640 : 38 : c_token *last = first + toks->length ();
27641 : 38 : const char *directive[3] = {};
27642 : 109 : for (int j = 0; j < 3; j++)
27643 : : {
27644 : 97 : tree id = NULL_TREE;
27645 : 97 : if (first + j == last)
27646 : : break;
27647 : 78 : if (first[j].type == CPP_NAME)
27648 : 71 : id = first[j].value;
27649 : 7 : else if (first[j].type == CPP_KEYWORD)
27650 : 0 : id = ridpointers[(int) first[j].keyword];
27651 : : else
27652 : : break;
27653 : 71 : directive[j] = IDENTIFIER_POINTER (id);
27654 : : }
27655 : 38 : const c_omp_directive *dir = NULL;
27656 : 38 : if (directive[0])
27657 : 38 : dir = c_omp_categorize_directive (directive[0], directive[1],
27658 : : directive[2]);
27659 : 38 : if (dir == NULL)
27660 : : {
27661 : 0 : error_at (first->location,
27662 : : "unknown OpenMP directive name in "
27663 : : "%qs attribute argument", "omp::decl");
27664 : 0 : return false;
27665 : : }
27666 : 38 : if (dir->id != PRAGMA_OMP_THREADPRIVATE
27667 : : /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
27668 : 23 : && dir->id != PRAGMA_OMP_ALLOCATE
27669 : 21 : && (dir->id != PRAGMA_OMP_DECLARE
27670 : 21 : || strcmp (directive[1], "target") != 0))
27671 : : return false;
27672 : :
27673 : 38 : if (!flag_openmp && !dir->simd)
27674 : : return true;
27675 : :
27676 : 38 : c_parser *parser = the_parser;
27677 : 38 : unsigned int tokens_avail = parser->tokens_avail;
27678 : 38 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27679 : 38 : toks = NULL;
27680 : 38 : vec_safe_reserve (toks, last - first + 2, true);
27681 : 38 : c_token tok = {};
27682 : 38 : tok.type = CPP_PRAGMA;
27683 : 38 : tok.keyword = RID_MAX;
27684 : 38 : tok.pragma_kind = pragma_kind (dir->id);
27685 : 38 : tok.location = first->location;
27686 : 38 : toks->quick_push (tok);
27687 : 176 : while (++first < last)
27688 : 100 : toks->quick_push (*first);
27689 : 38 : tok = {};
27690 : 38 : tok.type = CPP_PRAGMA_EOL;
27691 : 38 : tok.keyword = RID_MAX;
27692 : 38 : tok.location = last[-1].location;
27693 : 38 : toks->quick_push (tok);
27694 : 38 : tok = {};
27695 : 38 : tok.type = CPP_EOF;
27696 : 38 : tok.keyword = RID_MAX;
27697 : 38 : tok.location = last[-1].location;
27698 : 38 : toks->quick_push (tok);
27699 : 38 : parser->in_omp_decl_attribute = decl;
27700 : 38 : gcc_assert (!parser->in_omp_attribute_pragma);
27701 : 38 : parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
27702 : 38 : parser->in_omp_attribute_pragma->token_vec = toks;
27703 : 38 : parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
27704 : 38 : parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
27705 : 38 : parser->tokens = toks->address ();
27706 : 38 : parser->tokens_avail = toks->length ();
27707 : 38 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
27708 : 38 : parser->in_omp_decl_attribute = NULL_TREE;
27709 : 38 : return true;
27710 : : }
27711 : :
27712 : : /* OpenMP 4.0:
27713 : : # pragma omp declare target new-line
27714 : : declarations and definitions
27715 : : # pragma omp end declare target new-line
27716 : :
27717 : : OpenMP 4.5:
27718 : : # pragma omp declare target ( extended-list ) new-line
27719 : :
27720 : : # pragma omp declare target declare-target-clauses[seq] new-line */
27721 : :
27722 : : #define OMP_DECLARE_TARGET_CLAUSE_MASK \
27723 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
27724 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
27725 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
27726 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27727 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
27728 : :
27729 : : static void
27730 : 272 : c_parser_omp_declare_target (c_parser *parser)
27731 : : {
27732 : 272 : tree clauses = NULL_TREE;
27733 : 272 : int device_type = 0;
27734 : 272 : bool indirect = false;
27735 : 272 : bool only_device_type_or_indirect = true;
27736 : 272 : if (flag_openmp)
27737 : 272 : omp_requires_mask
27738 : 272 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27739 : 272 : if (c_parser_next_token_is (parser, CPP_NAME)
27740 : 406 : || (c_parser_next_token_is (parser, CPP_COMMA)
27741 : 5 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
27742 : 142 : clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
27743 : : "#pragma omp declare target");
27744 : 130 : else if (parser->in_omp_decl_attribute
27745 : 254 : || c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27746 : : {
27747 : 20 : clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
27748 : : clauses);
27749 : 20 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
27750 : 20 : c_parser_skip_to_pragma_eol (parser);
27751 : : }
27752 : : else
27753 : : {
27754 : 110 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27755 : 110 : c_parser_skip_to_pragma_eol (parser);
27756 : 110 : c_omp_declare_target_attr attr = { attr_syntax, -1, 0 };
27757 : 110 : vec_safe_push (current_omp_declare_target_attribute, attr);
27758 : 110 : return;
27759 : : }
27760 : 410 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27761 : : {
27762 : 248 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
27763 : 27 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
27764 : 248 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27765 : 16 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
27766 : : }
27767 : 410 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27768 : : {
27769 : 248 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
27770 : 248 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27771 : 248 : continue;
27772 : 205 : tree t = OMP_CLAUSE_DECL (c), id;
27773 : 205 : tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
27774 : 205 : tree at2 = lookup_attribute ("omp declare target link",
27775 : 205 : DECL_ATTRIBUTES (t));
27776 : 205 : only_device_type_or_indirect = false;
27777 : 205 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
27778 : : {
27779 : 34 : id = get_identifier ("omp declare target link");
27780 : 34 : std::swap (at1, at2);
27781 : : }
27782 : : else
27783 : 171 : id = get_identifier ("omp declare target");
27784 : 205 : if (at2)
27785 : : {
27786 : 6 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
27787 : 3 : error_at (OMP_CLAUSE_LOCATION (c),
27788 : : "%qD specified both in declare target %<link%> and %qs"
27789 : 3 : " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
27790 : : else
27791 : 3 : error_at (OMP_CLAUSE_LOCATION (c),
27792 : : "%qD specified both in declare target %<link%> and "
27793 : : "%<to%> or %<enter%> clauses", t);
27794 : 6 : continue;
27795 : : }
27796 : 199 : if (!at1)
27797 : : {
27798 : 170 : DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27799 : 170 : if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
27800 : 1 : continue;
27801 : :
27802 : 169 : symtab_node *node = symtab_node::get (t);
27803 : 169 : if (node != NULL)
27804 : : {
27805 : 123 : node->offloadable = 1;
27806 : 123 : if (ENABLE_OFFLOADING)
27807 : : {
27808 : : g->have_offload = true;
27809 : : if (is_a <varpool_node *> (node))
27810 : : vec_safe_push (offload_vars, t);
27811 : : }
27812 : : }
27813 : : }
27814 : 198 : if (TREE_CODE (t) != FUNCTION_DECL)
27815 : 121 : continue;
27816 : 77 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
27817 : : {
27818 : 13 : tree at3 = lookup_attribute ("omp declare target host",
27819 : 13 : DECL_ATTRIBUTES (t));
27820 : 13 : if (at3 == NULL_TREE)
27821 : : {
27822 : 11 : id = get_identifier ("omp declare target host");
27823 : 11 : DECL_ATTRIBUTES (t)
27824 : 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27825 : : }
27826 : : }
27827 : 77 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
27828 : : {
27829 : 13 : tree at3 = lookup_attribute ("omp declare target nohost",
27830 : 13 : DECL_ATTRIBUTES (t));
27831 : 13 : if (at3 == NULL_TREE)
27832 : : {
27833 : 11 : id = get_identifier ("omp declare target nohost");
27834 : 11 : DECL_ATTRIBUTES (t)
27835 : 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27836 : : }
27837 : : }
27838 : 77 : if (indirect)
27839 : : {
27840 : 9 : tree at4 = lookup_attribute ("omp declare target indirect",
27841 : 9 : DECL_ATTRIBUTES (t));
27842 : 9 : if (at4 == NULL_TREE)
27843 : : {
27844 : 9 : id = get_identifier ("omp declare target indirect");
27845 : 9 : DECL_ATTRIBUTES (t)
27846 : 18 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27847 : : }
27848 : : }
27849 : : }
27850 : 162 : if ((device_type || indirect) && only_device_type_or_indirect)
27851 : 3 : error_at (OMP_CLAUSE_LOCATION (clauses),
27852 : : "directive with only %<device_type%> or %<indirect%> clauses");
27853 : 162 : if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
27854 : 1 : error_at (OMP_CLAUSE_LOCATION (clauses),
27855 : : "%<device_type%> clause must specify 'any' when used with "
27856 : : "an %<indirect%> clause");
27857 : : }
27858 : :
27859 : : /* OpenMP 5.1
27860 : : #pragma omp begin assumes clauses[optseq] new-line
27861 : :
27862 : : #pragma omp begin declare target clauses[optseq] new-line */
27863 : :
27864 : : #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
27865 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27866 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
27867 : :
27868 : : static void
27869 : 91 : c_parser_omp_begin (c_parser *parser)
27870 : : {
27871 : 91 : const char *p = "";
27872 : 91 : c_parser_consume_pragma (parser);
27873 : 91 : if (c_parser_next_token_is (parser, CPP_NAME))
27874 : 91 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27875 : 91 : if (strcmp (p, "declare") == 0)
27876 : : {
27877 : 46 : c_parser_consume_token (parser);
27878 : 46 : p = "";
27879 : 46 : if (c_parser_next_token_is (parser, CPP_NAME))
27880 : 46 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27881 : 46 : if (strcmp (p, "target") == 0)
27882 : : {
27883 : 46 : c_parser_consume_token (parser);
27884 : 46 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27885 : 46 : tree clauses
27886 : 46 : = c_parser_omp_all_clauses (parser,
27887 : 46 : OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
27888 : : "#pragma omp begin declare target");
27889 : 46 : int device_type = 0;
27890 : 46 : int indirect = 0;
27891 : 70 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27892 : : {
27893 : 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
27894 : 15 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
27895 : 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27896 : 9 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
27897 : : }
27898 : 46 : c_omp_declare_target_attr attr = { attr_syntax, device_type,
27899 : 46 : indirect };
27900 : 46 : vec_safe_push (current_omp_declare_target_attribute, attr);
27901 : : }
27902 : : else
27903 : : {
27904 : 0 : c_parser_error (parser, "expected %<target%>");
27905 : 0 : c_parser_skip_to_pragma_eol (parser);
27906 : : }
27907 : : }
27908 : 45 : else if (strcmp (p, "assumes") == 0)
27909 : : {
27910 : 45 : c_parser_consume_token (parser);
27911 : 45 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27912 : 45 : c_parser_omp_assumption_clauses (parser, false);
27913 : 45 : struct c_omp_begin_assumes_data a = { attr_syntax };
27914 : 45 : vec_safe_push (current_omp_begin_assumes, a);
27915 : : }
27916 : : else
27917 : : {
27918 : 0 : c_parser_error (parser, "expected %<declare target%> or %<assumes%>");
27919 : 0 : c_parser_skip_to_pragma_eol (parser);
27920 : : }
27921 : 91 : }
27922 : :
27923 : : /* OpenMP 4.0
27924 : : #pragma omp end declare target
27925 : :
27926 : : OpenMP 5.1
27927 : : #pragma omp end assumes */
27928 : :
27929 : : static void
27930 : 199 : c_parser_omp_end (c_parser *parser)
27931 : : {
27932 : 199 : location_t loc = c_parser_peek_token (parser)->location;
27933 : 199 : const char *p = "";
27934 : 199 : c_parser_consume_pragma (parser);
27935 : 199 : if (c_parser_next_token_is (parser, CPP_NAME))
27936 : 199 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27937 : 199 : if (strcmp (p, "declare") == 0)
27938 : : {
27939 : 154 : c_parser_consume_token (parser);
27940 : 154 : if (c_parser_next_token_is (parser, CPP_NAME)
27941 : 154 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
27942 : : "target") == 0)
27943 : 154 : c_parser_consume_token (parser);
27944 : : else
27945 : : {
27946 : 0 : c_parser_error (parser, "expected %<target%>");
27947 : 0 : c_parser_skip_to_pragma_eol (parser);
27948 : 0 : return;
27949 : : }
27950 : 154 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27951 : 154 : c_parser_skip_to_pragma_eol (parser);
27952 : 154 : if (!vec_safe_length (current_omp_declare_target_attribute))
27953 : 2 : error_at (loc, "%<#pragma omp end declare target%> without "
27954 : : "corresponding %<#pragma omp declare target%> or "
27955 : : "%<#pragma omp begin declare target%>");
27956 : : else
27957 : : {
27958 : 152 : c_omp_declare_target_attr
27959 : 152 : a = current_omp_declare_target_attribute->pop ();
27960 : 152 : if (a.attr_syntax != attr_syntax)
27961 : : {
27962 : 16 : if (a.attr_syntax)
27963 : 12 : error_at (loc,
27964 : : "%qs in attribute syntax terminated "
27965 : : "with %qs in pragma syntax",
27966 : : a.device_type >= 0 ? "begin declare target"
27967 : : : "declare target",
27968 : : "end declare target");
27969 : : else
27970 : 12 : error_at (loc,
27971 : : "%qs in pragma syntax terminated "
27972 : : "with %qs in attribute syntax",
27973 : : a.device_type >= 0 ? "begin declare target"
27974 : : : "declare target",
27975 : : "end declare target");
27976 : : }
27977 : : }
27978 : : }
27979 : 45 : else if (strcmp (p, "assumes") == 0)
27980 : : {
27981 : 45 : c_parser_consume_token (parser);
27982 : 45 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27983 : 45 : c_parser_skip_to_pragma_eol (parser);
27984 : 45 : if (!vec_safe_length (current_omp_begin_assumes))
27985 : 1 : error_at (loc, "%qs without corresponding %qs",
27986 : : "#pragma omp end assumes", "#pragma omp begin assumes");
27987 : : else
27988 : : {
27989 : 44 : c_omp_begin_assumes_data
27990 : 44 : a = current_omp_begin_assumes->pop ();
27991 : 44 : if (a.attr_syntax != attr_syntax)
27992 : : {
27993 : 8 : if (a.attr_syntax)
27994 : 4 : error_at (loc,
27995 : : "%qs in attribute syntax terminated "
27996 : : "with %qs in pragma syntax",
27997 : : "begin assumes", "end assumes");
27998 : : else
27999 : 4 : error_at (loc,
28000 : : "%qs in pragma syntax terminated "
28001 : : "with %qs in attribute syntax",
28002 : : "begin assumes", "end assumes");
28003 : : }
28004 : : }
28005 : : }
28006 : : else
28007 : : {
28008 : 0 : c_parser_error (parser, "expected %<declare%> or %<assumes%>");
28009 : 0 : c_parser_skip_to_pragma_eol (parser);
28010 : : }
28011 : : }
28012 : :
28013 : : /* OpenMP 5.0
28014 : : #pragma omp declare mapper ([mapper-identifier :] type var) \
28015 : : [clause [ [,] clause ] ... ] new-line */
28016 : :
28017 : : static void
28018 : 65 : c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
28019 : : {
28020 : 65 : tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
28021 : 65 : tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
28022 : 65 : c_token *token;
28023 : :
28024 : 65 : if (context == pragma_struct || context == pragma_param)
28025 : : {
28026 : 2 : error ("%<#pragma omp declare mapper%> not at file or block scope");
28027 : 2 : goto fail;
28028 : : }
28029 : :
28030 : 63 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28031 : 0 : goto fail;
28032 : :
28033 : 63 : token = c_parser_peek_token (parser);
28034 : :
28035 : 63 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
28036 : : {
28037 : 22 : switch (token->type)
28038 : : {
28039 : 15 : case CPP_NAME:
28040 : 15 : mapper_name = token->value;
28041 : 15 : c_parser_consume_token (parser);
28042 : 15 : break;
28043 : 7 : case CPP_KEYWORD:
28044 : 7 : if (token->keyword == RID_DEFAULT)
28045 : : {
28046 : 6 : mapper_name = NULL_TREE;
28047 : 6 : c_parser_consume_token (parser);
28048 : 6 : break;
28049 : : }
28050 : : /* Fallthrough. */
28051 : 1 : default:
28052 : 1 : error_at (token->location, "expected identifier or %<default%>");
28053 : 1 : c_parser_skip_to_pragma_eol (parser, false);
28054 : 1 : return;
28055 : : }
28056 : :
28057 : 21 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
28058 : 0 : goto fail;
28059 : : }
28060 : :
28061 : 62 : mapper_id = c_omp_mapper_id (mapper_name);
28062 : 62 : mapper_decl = c_omp_mapper_decl (mapper_id);
28063 : :
28064 : 62 : {
28065 : 62 : location_t loc = c_parser_peek_token (parser)->location;
28066 : 62 : struct c_type_name *ctype = c_parser_type_name (parser);
28067 : 62 : type = groktypename (ctype, NULL, NULL);
28068 : 62 : if (type == error_mark_node)
28069 : 3 : goto fail;
28070 : 59 : if (!RECORD_OR_UNION_TYPE_P (type))
28071 : : {
28072 : 4 : error_at (loc, "%qT is not a struct or union type in "
28073 : : "%<#pragma omp declare mapper%>", type);
28074 : 4 : c_parser_skip_to_pragma_eol (parser, false);
28075 : 4 : return;
28076 : : }
28077 : 65 : for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
28078 : 17 : if (comptypes (TREE_PURPOSE (t), type))
28079 : : {
28080 : 7 : error_at (loc, "redeclaration of %qs %<#pragma omp declare "
28081 : 7 : "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
28082 : : + sizeof ("omp declare mapper ") - 1,
28083 : : type);
28084 : 7 : tree prevmapper = TREE_VALUE (t);
28085 : : /* Hmm, this location might not be very accurate. */
28086 : 7 : location_t ploc
28087 : 7 : = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
28088 : 7 : inform (ploc, "%<#pragma omp declare mapper%> "
28089 : : "previously declared here");
28090 : 7 : c_parser_skip_to_pragma_eol (parser, false);
28091 : 7 : return;
28092 : : }
28093 : : }
28094 : :
28095 : 48 : token = c_parser_peek_token (parser);
28096 : 48 : if (token->type == CPP_NAME)
28097 : : {
28098 : 46 : var = build_decl (token->location, VAR_DECL, token->value, type);
28099 : 46 : c_parser_consume_token (parser);
28100 : 46 : DECL_ARTIFICIAL (var) = 1;
28101 : : }
28102 : : else
28103 : : {
28104 : 2 : error_at (token->location, "expected identifier");
28105 : 2 : goto fail;
28106 : : }
28107 : :
28108 : 46 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28109 : 0 : goto fail;
28110 : :
28111 : 46 : push_scope ();
28112 : 46 : stmtlist = push_stmt_list ();
28113 : 46 : pushdecl (var);
28114 : 46 : DECL_CONTEXT (var) = current_function_decl;
28115 : :
28116 : 115 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28117 : : {
28118 : 70 : location_t here;
28119 : 70 : pragma_omp_clause c_kind;
28120 : 70 : here = c_parser_peek_token (parser)->location;
28121 : 70 : c_kind = c_parser_omp_clause_name (parser);
28122 : 70 : if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
28123 : : {
28124 : 1 : error_at (here, "unexpected clause");
28125 : 1 : goto fail;
28126 : : }
28127 : 69 : maplist = c_parser_omp_clause_map (parser, maplist, true);
28128 : : }
28129 : :
28130 : 45 : if (maplist == NULL_TREE)
28131 : : {
28132 : 1 : error_at (input_location, "missing %<map%> clause");
28133 : 1 : goto fail;
28134 : : }
28135 : :
28136 : 44 : stmt = make_node (OMP_DECLARE_MAPPER);
28137 : 44 : TREE_TYPE (stmt) = type;
28138 : 44 : OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
28139 : 44 : OMP_DECLARE_MAPPER_DECL (stmt) = var;
28140 : 44 : OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
28141 : :
28142 : 44 : add_stmt (stmt);
28143 : :
28144 : 44 : pop_stmt_list (stmtlist);
28145 : 44 : pop_scope ();
28146 : :
28147 : 44 : c_parser_skip_to_pragma_eol (parser);
28148 : :
28149 : 44 : t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
28150 : 44 : DECL_INITIAL (mapper_decl) = t;
28151 : :
28152 : 44 : return;
28153 : :
28154 : 9 : fail:
28155 : 9 : c_parser_skip_to_pragma_eol (parser);
28156 : : }
28157 : :
28158 : : /* OpenMP 4.0
28159 : : #pragma omp declare reduction (reduction-id : typename-list : expression) \
28160 : : initializer-clause[opt] new-line
28161 : :
28162 : : initializer-clause:
28163 : : initializer (omp_priv = initializer)
28164 : : initializer (function-name (argument-list)) */
28165 : :
28166 : : static void
28167 : 164 : c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
28168 : : {
28169 : 164 : unsigned int tokens_avail = 0, i;
28170 : 164 : c_token *saved_tokens = NULL;
28171 : 164 : vec<tree> types = vNULL;
28172 : 164 : vec<c_token> clauses = vNULL;
28173 : 164 : enum tree_code reduc_code = ERROR_MARK;
28174 : 164 : tree reduc_id = NULL_TREE;
28175 : 164 : tree type;
28176 : 164 : location_t rloc = c_parser_peek_token (parser)->location;
28177 : :
28178 : 164 : if (context == pragma_struct || context == pragma_param)
28179 : : {
28180 : 2 : error ("%<#pragma omp declare reduction%> not at file or block scope");
28181 : 2 : goto fail;
28182 : : }
28183 : :
28184 : 162 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28185 : 1 : goto fail;
28186 : :
28187 : 161 : switch (c_parser_peek_token (parser)->type)
28188 : : {
28189 : : case CPP_PLUS:
28190 : : reduc_code = PLUS_EXPR;
28191 : : break;
28192 : 14 : case CPP_MULT:
28193 : 14 : reduc_code = MULT_EXPR;
28194 : 14 : break;
28195 : 0 : case CPP_MINUS:
28196 : 0 : reduc_code = MINUS_EXPR;
28197 : 0 : break;
28198 : 4 : case CPP_AND:
28199 : 4 : reduc_code = BIT_AND_EXPR;
28200 : 4 : break;
28201 : 0 : case CPP_XOR:
28202 : 0 : reduc_code = BIT_XOR_EXPR;
28203 : 0 : break;
28204 : 10 : case CPP_OR:
28205 : 10 : reduc_code = BIT_IOR_EXPR;
28206 : 10 : break;
28207 : 0 : case CPP_AND_AND:
28208 : 0 : reduc_code = TRUTH_ANDIF_EXPR;
28209 : 0 : break;
28210 : 0 : case CPP_OR_OR:
28211 : 0 : reduc_code = TRUTH_ORIF_EXPR;
28212 : 0 : break;
28213 : 89 : case CPP_NAME:
28214 : 89 : const char *p;
28215 : 89 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28216 : 89 : if (strcmp (p, "min") == 0)
28217 : : {
28218 : : reduc_code = MIN_EXPR;
28219 : : break;
28220 : : }
28221 : 83 : if (strcmp (p, "max") == 0)
28222 : : {
28223 : : reduc_code = MAX_EXPR;
28224 : : break;
28225 : : }
28226 : 83 : reduc_id = c_parser_peek_token (parser)->value;
28227 : 83 : break;
28228 : 0 : default:
28229 : 0 : c_parser_error (parser,
28230 : : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
28231 : : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
28232 : 0 : goto fail;
28233 : : }
28234 : :
28235 : 161 : tree orig_reduc_id, reduc_decl;
28236 : 161 : orig_reduc_id = reduc_id;
28237 : 161 : reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
28238 : 161 : reduc_decl = c_omp_reduction_decl (reduc_id);
28239 : 161 : c_parser_consume_token (parser);
28240 : :
28241 : 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
28242 : 0 : goto fail;
28243 : :
28244 : 165 : while (true)
28245 : : {
28246 : 163 : location_t loc = c_parser_peek_token (parser)->location;
28247 : 163 : struct c_type_name *ctype = c_parser_type_name (parser);
28248 : 163 : if (ctype != NULL)
28249 : : {
28250 : 163 : type = groktypename (ctype, NULL, NULL);
28251 : 163 : if (type == error_mark_node)
28252 : : ;
28253 : 163 : else if ((INTEGRAL_TYPE_P (type)
28254 : 163 : || SCALAR_FLOAT_TYPE_P (type)
28255 : 98 : || TREE_CODE (type) == COMPLEX_TYPE)
28256 : 69 : && orig_reduc_id == NULL_TREE)
28257 : 8 : error_at (loc, "predeclared arithmetic type in "
28258 : : "%<#pragma omp declare reduction%>");
28259 : 155 : else if (TREE_CODE (type) == FUNCTION_TYPE
28260 : 150 : || TREE_CODE (type) == ARRAY_TYPE)
28261 : 8 : error_at (loc, "function or array type in "
28262 : : "%<#pragma omp declare reduction%>");
28263 : 147 : else if (TYPE_ATOMIC (type))
28264 : 1 : error_at (loc, "%<_Atomic%> qualified type in "
28265 : : "%<#pragma omp declare reduction%>");
28266 : 146 : else if (TYPE_QUALS_NO_ADDR_SPACE (type))
28267 : 8 : error_at (loc, "const, volatile or restrict qualified type in "
28268 : : "%<#pragma omp declare reduction%>");
28269 : : else
28270 : : {
28271 : 138 : tree t;
28272 : 200 : for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
28273 : 66 : if (comptypes (TREE_PURPOSE (t), type))
28274 : : {
28275 : 4 : error_at (loc, "redeclaration of %qs "
28276 : : "%<#pragma omp declare reduction%> for "
28277 : : "type %qT",
28278 : 4 : IDENTIFIER_POINTER (reduc_id)
28279 : : + sizeof ("omp declare reduction ") - 1,
28280 : : type);
28281 : 4 : location_t ploc
28282 : 4 : = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
28283 : : 0));
28284 : 4 : inform (ploc, "%<#pragma omp declare reduction%> "
28285 : : "previously declared here");
28286 : 4 : break;
28287 : : }
28288 : 4 : if (t == NULL_TREE)
28289 : 134 : types.safe_push (type);
28290 : : }
28291 : 163 : if (c_parser_next_token_is (parser, CPP_COMMA))
28292 : 2 : c_parser_consume_token (parser);
28293 : : else
28294 : : break;
28295 : : }
28296 : : else
28297 : : break;
28298 : 2 : }
28299 : :
28300 : 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
28301 : 161 : || types.is_empty ())
28302 : : {
28303 : 34 : fail:
28304 : 34 : clauses.release ();
28305 : 34 : types.release ();
28306 : 460 : while (true)
28307 : : {
28308 : 247 : c_token *token = c_parser_peek_token (parser);
28309 : 247 : if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
28310 : : break;
28311 : 213 : c_parser_consume_token (parser);
28312 : 213 : }
28313 : 34 : c_parser_skip_to_pragma_eol (parser);
28314 : 34 : return;
28315 : : }
28316 : :
28317 : 132 : if (types.length () > 1)
28318 : : {
28319 : 13 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28320 : : {
28321 : 12 : c_token *token = c_parser_peek_token (parser);
28322 : 12 : if (token->type == CPP_EOF)
28323 : 0 : goto fail;
28324 : 12 : clauses.safe_push (*token);
28325 : 12 : c_parser_consume_token (parser);
28326 : : }
28327 : 1 : clauses.safe_push (*c_parser_peek_token (parser));
28328 : 1 : c_parser_skip_to_pragma_eol (parser);
28329 : :
28330 : : /* Make sure nothing tries to read past the end of the tokens. */
28331 : 1 : c_token eof_token;
28332 : 1 : memset (&eof_token, 0, sizeof (eof_token));
28333 : 1 : eof_token.type = CPP_EOF;
28334 : 1 : clauses.safe_push (eof_token);
28335 : 1 : clauses.safe_push (eof_token);
28336 : : }
28337 : :
28338 : 132 : int errs = errorcount;
28339 : 238 : FOR_EACH_VEC_ELT (types, i, type)
28340 : : {
28341 : 134 : saved_tokens = parser->tokens;
28342 : 134 : tokens_avail = parser->tokens_avail;
28343 : 134 : if (!clauses.is_empty ())
28344 : : {
28345 : 3 : parser->tokens = clauses.address ();
28346 : 3 : parser->tokens_avail = clauses.length ();
28347 : 3 : parser->in_pragma = true;
28348 : : }
28349 : :
28350 : 134 : bool nested = current_function_decl != NULL_TREE;
28351 : 134 : if (nested)
28352 : 27 : c_push_function_context ();
28353 : 134 : tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
28354 : : reduc_id, default_function_type);
28355 : 134 : current_function_decl = fndecl;
28356 : 134 : allocate_struct_function (fndecl, true);
28357 : 134 : push_scope ();
28358 : 134 : tree stmt = push_stmt_list ();
28359 : : /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
28360 : : warn about these. */
28361 : 134 : tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
28362 : : get_identifier ("omp_out"), type);
28363 : 134 : DECL_ARTIFICIAL (omp_out) = 1;
28364 : 134 : DECL_CONTEXT (omp_out) = fndecl;
28365 : 134 : pushdecl (omp_out);
28366 : 134 : tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
28367 : : get_identifier ("omp_in"), type);
28368 : 134 : DECL_ARTIFICIAL (omp_in) = 1;
28369 : 134 : DECL_CONTEXT (omp_in) = fndecl;
28370 : 134 : pushdecl (omp_in);
28371 : 134 : struct c_expr combiner = c_parser_expression (parser);
28372 : 134 : struct c_expr initializer;
28373 : 134 : tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
28374 : 134 : bool bad = false;
28375 : 134 : initializer.set_error ();
28376 : 134 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28377 : : bad = true;
28378 : 134 : else if (c_parser_next_token_is (parser, CPP_COMMA)
28379 : 134 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28380 : 2 : c_parser_consume_token (parser);
28381 : 2 : if (!bad
28382 : 134 : && (c_parser_next_token_is (parser, CPP_NAME)
28383 : 77 : && strcmp (IDENTIFIER_POINTER
28384 : : (c_parser_peek_token (parser)->value),
28385 : : "initializer") == 0))
28386 : : {
28387 : 77 : c_parser_consume_token (parser);
28388 : 77 : pop_scope ();
28389 : 77 : push_scope ();
28390 : 77 : omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
28391 : : get_identifier ("omp_priv"), type);
28392 : 77 : DECL_ARTIFICIAL (omp_priv) = 1;
28393 : 77 : DECL_INITIAL (omp_priv) = error_mark_node;
28394 : 77 : DECL_CONTEXT (omp_priv) = fndecl;
28395 : 77 : pushdecl (omp_priv);
28396 : 77 : omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
28397 : : get_identifier ("omp_orig"), type);
28398 : 77 : DECL_ARTIFICIAL (omp_orig) = 1;
28399 : 77 : DECL_CONTEXT (omp_orig) = fndecl;
28400 : 77 : pushdecl (omp_orig);
28401 : 77 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28402 : : bad = true;
28403 : 77 : else if (!c_parser_next_token_is (parser, CPP_NAME))
28404 : : {
28405 : 0 : c_parser_error (parser, "expected %<omp_priv%> or "
28406 : : "function-name");
28407 : 0 : bad = true;
28408 : : }
28409 : 77 : else if (strcmp (IDENTIFIER_POINTER
28410 : : (c_parser_peek_token (parser)->value),
28411 : : "omp_priv") != 0)
28412 : : {
28413 : 20 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
28414 : 20 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
28415 : : {
28416 : 0 : c_parser_error (parser, "expected function-name %<(%>");
28417 : 0 : bad = true;
28418 : : }
28419 : : else
28420 : 20 : initializer = c_parser_postfix_expression (parser);
28421 : 20 : if (initializer.value
28422 : 20 : && TREE_CODE (initializer.value) == CALL_EXPR)
28423 : : {
28424 : : int j;
28425 : : tree c = initializer.value;
28426 : 21 : for (j = 0; j < call_expr_nargs (c); j++)
28427 : : {
28428 : 20 : tree a = CALL_EXPR_ARG (c, j);
28429 : 20 : STRIP_NOPS (a);
28430 : 20 : if (TREE_CODE (a) == ADDR_EXPR
28431 : 20 : && TREE_OPERAND (a, 0) == omp_priv)
28432 : : break;
28433 : : }
28434 : 20 : if (j == call_expr_nargs (c))
28435 : 1 : error ("one of the initializer call arguments should be "
28436 : : "%<&omp_priv%>");
28437 : : }
28438 : : }
28439 : : else
28440 : : {
28441 : 57 : c_parser_consume_token (parser);
28442 : 57 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
28443 : : bad = true;
28444 : : else
28445 : : {
28446 : 55 : tree st = push_stmt_list ();
28447 : 55 : location_t loc = c_parser_peek_token (parser)->location;
28448 : 55 : rich_location richloc (line_table, loc);
28449 : 55 : start_init (omp_priv, NULL_TREE, false, false, &richloc);
28450 : 55 : struct c_expr init = c_parser_initializer (parser, omp_priv);
28451 : 55 : finish_init ();
28452 : 55 : finish_decl (omp_priv, loc, init.value,
28453 : : init.original_type, NULL_TREE);
28454 : 55 : pop_stmt_list (st);
28455 : 55 : }
28456 : : }
28457 : 0 : if (!bad
28458 : 75 : && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28459 : : bad = true;
28460 : : }
28461 : :
28462 : 134 : if (!bad)
28463 : : {
28464 : 132 : c_parser_skip_to_pragma_eol (parser);
28465 : :
28466 : 189 : tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
28467 : 132 : DECL_INITIAL (reduc_decl));
28468 : 132 : DECL_INITIAL (reduc_decl) = t;
28469 : 132 : DECL_SOURCE_LOCATION (omp_out) = rloc;
28470 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
28471 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
28472 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
28473 : 132 : walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
28474 : : &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
28475 : 132 : if (omp_priv)
28476 : : {
28477 : 75 : DECL_SOURCE_LOCATION (omp_priv) = rloc;
28478 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
28479 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
28480 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
28481 : 75 : walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
28482 : : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28483 : 75 : walk_tree (&DECL_INITIAL (omp_priv),
28484 : : c_check_omp_declare_reduction_r,
28485 : : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28486 : : }
28487 : : }
28488 : :
28489 : 134 : pop_stmt_list (stmt);
28490 : 134 : pop_scope ();
28491 : 134 : if (cfun->language != NULL)
28492 : : {
28493 : 0 : ggc_free (cfun->language);
28494 : 0 : cfun->language = NULL;
28495 : : }
28496 : 134 : set_cfun (NULL);
28497 : 134 : current_function_decl = NULL_TREE;
28498 : 134 : if (nested)
28499 : 27 : c_pop_function_context ();
28500 : :
28501 : 134 : if (!clauses.is_empty ())
28502 : : {
28503 : 3 : parser->tokens = saved_tokens;
28504 : 3 : parser->tokens_avail = tokens_avail;
28505 : : }
28506 : 134 : if (bad)
28507 : 2 : goto fail;
28508 : 132 : if (errs != errorcount)
28509 : : break;
28510 : : }
28511 : :
28512 : 130 : clauses.release ();
28513 : 130 : types.release ();
28514 : : }
28515 : :
28516 : : /* OpenMP 4.0
28517 : : #pragma omp declare simd declare-simd-clauses[optseq] new-line
28518 : : #pragma omp declare reduction (reduction-id : typename-list : expression) \
28519 : : initializer-clause[opt] new-line
28520 : : #pragma omp declare target new-line
28521 : :
28522 : : OpenMP 5.0
28523 : : #pragma omp declare variant (identifier) match (context-selector)
28524 : :
28525 : : OpenMP 5.1
28526 : : #pragma omp declare variant (identifier) match (context-selector) \
28527 : : adjust_args(adjust-op:argument-list) */
28528 : :
28529 : : static bool
28530 : 1201 : c_parser_omp_declare (c_parser *parser, enum pragma_context context)
28531 : : {
28532 : 1201 : c_parser_consume_pragma (parser);
28533 : 1201 : if (c_parser_next_token_is (parser, CPP_NAME))
28534 : : {
28535 : 1201 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28536 : 1201 : if (strcmp (p, "simd") == 0)
28537 : : {
28538 : : /* c_parser_consume_token (parser); done in
28539 : : c_parser_omp_declare_simd. */
28540 : 268 : c_parser_omp_declare_simd (parser, context);
28541 : 268 : return true;
28542 : : }
28543 : 933 : if (strcmp (p, "reduction") == 0)
28544 : : {
28545 : 164 : c_parser_consume_token (parser);
28546 : 164 : c_parser_omp_declare_reduction (parser, context);
28547 : 164 : return false;
28548 : : }
28549 : 769 : if (strcmp (p, "mapper") == 0)
28550 : : {
28551 : 65 : c_parser_consume_token (parser);
28552 : 65 : c_parser_omp_declare_mapper (parser, context);
28553 : 65 : return false;
28554 : : }
28555 : 704 : if (!flag_openmp) /* flag_openmp_simd */
28556 : : {
28557 : 0 : c_parser_skip_to_pragma_eol (parser, false);
28558 : 0 : return false;
28559 : : }
28560 : 704 : if (strcmp (p, "target") == 0)
28561 : : {
28562 : 272 : c_parser_consume_token (parser);
28563 : 272 : c_parser_omp_declare_target (parser);
28564 : 272 : return false;
28565 : : }
28566 : 432 : if (strcmp (p, "variant") == 0)
28567 : : {
28568 : : /* c_parser_consume_token (parser); done in
28569 : : c_parser_omp_declare_simd. */
28570 : 432 : c_parser_omp_declare_simd (parser, context);
28571 : 432 : return true;
28572 : : }
28573 : : }
28574 : :
28575 : 0 : c_parser_error (parser, "expected %<simd%>, %<reduction%>, "
28576 : : "%<target%> or %<variant%>");
28577 : 0 : c_parser_skip_to_pragma_eol (parser);
28578 : 0 : return false;
28579 : : }
28580 : :
28581 : : /* OpenMP 5.0
28582 : : #pragma omp requires clauses[optseq] new-line */
28583 : :
28584 : : static void
28585 : 62 : c_parser_omp_requires (c_parser *parser)
28586 : : {
28587 : 62 : enum omp_requires new_req = (enum omp_requires) 0;
28588 : :
28589 : 62 : c_parser_consume_pragma (parser);
28590 : :
28591 : 62 : location_t loc = c_parser_peek_token (parser)->location;
28592 : 138 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28593 : : {
28594 : 80 : if (c_parser_next_token_is (parser, CPP_COMMA)
28595 : 80 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28596 : 14 : c_parser_consume_token (parser);
28597 : :
28598 : 80 : if (c_parser_next_token_is (parser, CPP_NAME))
28599 : : {
28600 : 79 : const char *p
28601 : 79 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28602 : 79 : location_t cloc = c_parser_peek_token (parser)->location;
28603 : 79 : enum omp_requires this_req = (enum omp_requires) 0;
28604 : :
28605 : 79 : if (!strcmp (p, "unified_address"))
28606 : : this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
28607 : 65 : else if (!strcmp (p, "unified_shared_memory"))
28608 : : this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
28609 : 51 : else if (!strcmp (p, "self_maps"))
28610 : : this_req = OMP_REQUIRES_SELF_MAPS;
28611 : 49 : else if (!strcmp (p, "dynamic_allocators"))
28612 : : this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
28613 : 38 : else if (!strcmp (p, "reverse_offload"))
28614 : : this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
28615 : 21 : else if (!strcmp (p, "atomic_default_mem_order"))
28616 : : {
28617 : 20 : c_parser_consume_token (parser);
28618 : :
28619 : 20 : matching_parens parens;
28620 : 20 : if (parens.require_open (parser))
28621 : : {
28622 : 20 : if (c_parser_next_token_is (parser, CPP_NAME))
28623 : : {
28624 : 19 : tree v = c_parser_peek_token (parser)->value;
28625 : 19 : p = IDENTIFIER_POINTER (v);
28626 : :
28627 : 19 : if (!strcmp (p, "seq_cst"))
28628 : : this_req
28629 : : = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
28630 : 10 : else if (!strcmp (p, "relaxed"))
28631 : : this_req
28632 : : = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
28633 : 9 : else if (!strcmp (p, "release"))
28634 : : this_req
28635 : : = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
28636 : 7 : else if (!strcmp (p, "acq_rel"))
28637 : : this_req
28638 : : = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
28639 : 4 : else if (!strcmp (p, "acquire"))
28640 : : this_req
28641 : : = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
28642 : : }
28643 : : if (this_req == 0)
28644 : : {
28645 : 2 : error_at (c_parser_peek_token (parser)->location,
28646 : : "expected %<acq_rel%>, %<acquire%>, "
28647 : : "%<relaxed%>, %<release%> or %<seq_cst%>");
28648 : 2 : switch (c_parser_peek_token (parser)->type)
28649 : : {
28650 : : case CPP_EOF:
28651 : : case CPP_PRAGMA_EOL:
28652 : : case CPP_CLOSE_PAREN:
28653 : : break;
28654 : 1 : default:
28655 : 1 : if (c_parser_peek_2nd_token (parser)->type
28656 : : == CPP_CLOSE_PAREN)
28657 : 1 : c_parser_consume_token (parser);
28658 : : break;
28659 : : }
28660 : : }
28661 : : else
28662 : 18 : c_parser_consume_token (parser);
28663 : :
28664 : 20 : parens.skip_until_found_close (parser);
28665 : 20 : if (this_req == 0)
28666 : : {
28667 : 2 : c_parser_skip_to_pragma_eol (parser, false);
28668 : 2 : return;
28669 : : }
28670 : : }
28671 : 18 : p = NULL;
28672 : : }
28673 : : else
28674 : : {
28675 : 1 : error_at (cloc, "expected %<unified_address%>, "
28676 : : "%<unified_shared_memory%>, "
28677 : : "%<self_maps%>, "
28678 : : "%<dynamic_allocators%>, "
28679 : : "%<reverse_offload%> "
28680 : : "or %<atomic_default_mem_order%> clause");
28681 : 1 : c_parser_skip_to_pragma_eol (parser, false);
28682 : 1 : return;
28683 : : }
28684 : 18 : if (p)
28685 : 58 : c_parser_consume_token (parser);
28686 : 76 : if (this_req)
28687 : : {
28688 : 76 : if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28689 : : {
28690 : 58 : if ((this_req & new_req) != 0)
28691 : 4 : error_at (cloc, "too many %qs clauses", p);
28692 : 58 : if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
28693 : 47 : && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
28694 : 4 : error_at (cloc, "%qs clause used lexically after first "
28695 : : "target construct or offloading API", p);
28696 : : }
28697 : 18 : else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28698 : : {
28699 : 1 : error_at (cloc, "too many %qs clauses",
28700 : : "atomic_default_mem_order");
28701 : 1 : this_req = (enum omp_requires) 0;
28702 : : }
28703 : 17 : else if ((omp_requires_mask
28704 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28705 : : {
28706 : 2 : error_at (cloc, "more than one %<atomic_default_mem_order%>"
28707 : : " clause in a single compilation unit");
28708 : 2 : this_req
28709 : 2 : = (enum omp_requires)
28710 : 2 : (omp_requires_mask
28711 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
28712 : : }
28713 : 15 : else if ((omp_requires_mask
28714 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
28715 : 1 : error_at (cloc, "%<atomic_default_mem_order%> clause used "
28716 : : "lexically after first %<atomic%> construct "
28717 : : "without memory order clause");
28718 : 76 : new_req = (enum omp_requires) (new_req | this_req);
28719 : 76 : omp_requires_mask
28720 : 76 : = (enum omp_requires) (omp_requires_mask | this_req);
28721 : 76 : continue;
28722 : : }
28723 : : }
28724 : : break;
28725 : : }
28726 : 59 : c_parser_skip_to_pragma_eol (parser);
28727 : :
28728 : 59 : if (new_req == 0)
28729 : 1 : error_at (loc, "%<pragma omp requires%> requires at least one clause");
28730 : : }
28731 : :
28732 : : /* Helper function for c_parser_omp_taskloop.
28733 : : Disallow zero sized or potentially zero sized task reductions. */
28734 : :
28735 : : static tree
28736 : 412 : c_finish_taskloop_clauses (tree clauses)
28737 : : {
28738 : 412 : tree *pc = &clauses;
28739 : 2049 : for (tree c = clauses; c; c = *pc)
28740 : : {
28741 : 1637 : bool remove = false;
28742 : 1637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
28743 : : {
28744 : 142 : tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
28745 : 142 : if (integer_zerop (TYPE_SIZE_UNIT (type)))
28746 : : {
28747 : 2 : error_at (OMP_CLAUSE_LOCATION (c),
28748 : : "zero sized type %qT in %<reduction%> clause", type);
28749 : 2 : remove = true;
28750 : : }
28751 : 140 : else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
28752 : : {
28753 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
28754 : : "variable sized type %qT in %<reduction%> clause",
28755 : : type);
28756 : 0 : remove = true;
28757 : : }
28758 : : }
28759 : 2 : if (remove)
28760 : 2 : *pc = OMP_CLAUSE_CHAIN (c);
28761 : : else
28762 : 1635 : pc = &OMP_CLAUSE_CHAIN (c);
28763 : : }
28764 : 412 : return clauses;
28765 : : }
28766 : :
28767 : : /* OpenMP 4.5:
28768 : : #pragma omp taskloop taskloop-clause[optseq] new-line
28769 : : for-loop
28770 : :
28771 : : #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
28772 : : for-loop */
28773 : :
28774 : : #define OMP_TASKLOOP_CLAUSE_MASK \
28775 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
28776 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
28777 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
28778 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
28779 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
28780 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
28781 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
28782 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
28783 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
28784 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
28785 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
28786 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
28787 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
28788 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
28789 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
28790 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
28791 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
28792 : :
28793 : : static tree
28794 : 417 : c_parser_omp_taskloop (location_t loc, c_parser *parser,
28795 : : char *p_name, omp_clause_mask mask, tree *cclauses,
28796 : : bool *if_p)
28797 : : {
28798 : 417 : tree clauses, block, ret;
28799 : :
28800 : 417 : strcat (p_name, " taskloop");
28801 : 417 : mask |= OMP_TASKLOOP_CLAUSE_MASK;
28802 : : /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
28803 : : clause. */
28804 : 417 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
28805 : 94 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
28806 : :
28807 : 417 : if (c_parser_next_token_is (parser, CPP_NAME))
28808 : : {
28809 : 341 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28810 : :
28811 : 341 : if (strcmp (p, "simd") == 0)
28812 : : {
28813 : 178 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
28814 : 178 : if (cclauses == NULL)
28815 : 84 : cclauses = cclauses_buf;
28816 : 178 : c_parser_consume_token (parser);
28817 : 178 : if (!flag_openmp) /* flag_openmp_simd */
28818 : 3 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
28819 : 3 : if_p);
28820 : 175 : block = c_begin_compound_stmt (true);
28821 : 175 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
28822 : 175 : block = c_end_compound_stmt (loc, block, true);
28823 : 175 : if (ret == NULL)
28824 : : return ret;
28825 : 175 : ret = make_node (OMP_TASKLOOP);
28826 : 175 : TREE_TYPE (ret) = void_type_node;
28827 : 175 : OMP_FOR_BODY (ret) = block;
28828 : 175 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
28829 : 175 : OMP_FOR_CLAUSES (ret)
28830 : 175 : = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
28831 : 175 : SET_EXPR_LOCATION (ret, loc);
28832 : 175 : add_stmt (ret);
28833 : 175 : return ret;
28834 : : }
28835 : : }
28836 : 239 : if (!flag_openmp) /* flag_openmp_simd */
28837 : : {
28838 : 2 : c_parser_skip_to_pragma_eol (parser, false);
28839 : 2 : return NULL_TREE;
28840 : : }
28841 : :
28842 : 237 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
28843 : 237 : if (cclauses)
28844 : : {
28845 : 65 : omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses);
28846 : 65 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
28847 : : }
28848 : :
28849 : 237 : clauses = c_finish_taskloop_clauses (clauses);
28850 : 237 : block = c_begin_compound_stmt (true);
28851 : 237 : ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
28852 : 237 : block = c_end_compound_stmt (loc, block, true);
28853 : 237 : add_stmt (block);
28854 : :
28855 : 237 : return ret;
28856 : : }
28857 : :
28858 : : /* OpenMP 5.1: Parse sizes list for "omp tile sizes"
28859 : : sizes ( size-expr-list ) */
28860 : : static tree
28861 : 476 : c_parser_omp_tile_sizes (c_parser *parser, location_t loc)
28862 : : {
28863 : 476 : tree sizes = NULL_TREE;
28864 : :
28865 : 476 : if (c_parser_next_token_is (parser, CPP_COMMA))
28866 : 2 : c_parser_consume_token (parser);
28867 : :
28868 : 476 : c_token *tok = c_parser_peek_token (parser);
28869 : 476 : if (tok->type != CPP_NAME
28870 : 476 : || strcmp ("sizes", IDENTIFIER_POINTER (tok->value)))
28871 : : {
28872 : 1 : c_parser_error (parser, "expected %<sizes%>");
28873 : 1 : return error_mark_node;
28874 : : }
28875 : 475 : c_parser_consume_token (parser);
28876 : :
28877 : 475 : matching_parens parens;
28878 : 475 : if (!parens.require_open (parser))
28879 : 4 : return error_mark_node;
28880 : :
28881 : 471 : vec<tree, va_gc> *sizes_vec
28882 : 471 : = c_parser_expr_list (parser, true, true, NULL, NULL, NULL, NULL);
28883 : 471 : sizes = build_tree_list_vec (sizes_vec);
28884 : 471 : release_tree_vector (sizes_vec);
28885 : :
28886 : 1198 : for (tree s = sizes; s; s = TREE_CHAIN (s))
28887 : : {
28888 : 734 : tree expr = TREE_VALUE (s);
28889 : 734 : if (expr == error_mark_node)
28890 : : {
28891 : 7 : parens.skip_until_found_close (parser);
28892 : 7 : return error_mark_node;
28893 : : }
28894 : :
28895 : 727 : HOST_WIDE_INT n;
28896 : 1454 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
28897 : 724 : || !tree_fits_shwi_p (expr)
28898 : 722 : || (n = tree_to_shwi (expr)) <= 0
28899 : 1440 : || (int) n != n)
28900 : : {
28901 : 14 : c_parser_error (parser, "%<sizes%> argument needs positive"
28902 : : " integral constant");
28903 : 14 : TREE_VALUE (s) = integer_one_node;
28904 : : }
28905 : : }
28906 : 464 : parens.require_close (parser);
28907 : :
28908 : 464 : gcc_assert (sizes);
28909 : 464 : tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES);
28910 : 464 : OMP_CLAUSE_SIZES_LIST (c) = sizes;
28911 : :
28912 : 464 : return c;
28913 : : }
28914 : :
28915 : : /* OpenMP 5.1:
28916 : : #pragma omp tile sizes ( size-expr-list ) new-line
28917 : : for-loop
28918 : :
28919 : : LOC is the location of the #pragma token. */
28920 : :
28921 : : static tree
28922 : 476 : c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p)
28923 : : {
28924 : 476 : tree clauses = c_parser_omp_tile_sizes (parser, loc);
28925 : 476 : c_parser_skip_to_pragma_eol (parser);
28926 : :
28927 : 476 : if (!clauses || clauses == error_mark_node)
28928 : 12 : return error_mark_node;
28929 : :
28930 : 464 : tree block = c_begin_compound_stmt (true);
28931 : 464 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_TILE, clauses,
28932 : : NULL, if_p);
28933 : 464 : block = c_end_compound_stmt (loc, block, true);
28934 : 464 : add_stmt (block);
28935 : :
28936 : 464 : return ret;
28937 : : }
28938 : :
28939 : : #define OMP_UNROLL_CLAUSE_MASK \
28940 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \
28941 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL))
28942 : :
28943 : : /* OpenMP 5.1
28944 : : #pragma omp unroll unroll-clause[optseq] new-line
28945 : : for-loop
28946 : :
28947 : : LOC is the location of the #pragma token. */
28948 : :
28949 : : static tree
28950 : 313 : c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p)
28951 : : {
28952 : 313 : tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK,
28953 : : "#pragma omp unroll", true);
28954 : :
28955 : 313 : tree block = c_begin_compound_stmt (true);
28956 : 313 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_UNROLL, clauses,
28957 : : NULL, if_p);
28958 : 313 : block = c_end_compound_stmt (loc, block, true);
28959 : 313 : add_stmt (block);
28960 : :
28961 : 313 : return ret;
28962 : : }
28963 : :
28964 : : /* OpenMP 5.1
28965 : : #pragma omp nothing new-line */
28966 : :
28967 : : static void
28968 : 79 : c_parser_omp_nothing (c_parser *parser)
28969 : : {
28970 : 79 : c_parser_consume_pragma (parser);
28971 : 79 : c_parser_skip_to_pragma_eol (parser);
28972 : 79 : }
28973 : :
28974 : : /* OpenMP 5.1
28975 : : #pragma omp error clauses[optseq] new-line */
28976 : :
28977 : : static bool
28978 : 124 : c_parser_omp_error (c_parser *parser, enum pragma_context context)
28979 : : {
28980 : 124 : int at_compilation = -1;
28981 : 124 : int severity_fatal = -1;
28982 : 124 : tree message = NULL_TREE;
28983 : 124 : bool bad = false;
28984 : 124 : location_t loc = c_parser_peek_token (parser)->location;
28985 : :
28986 : 124 : c_parser_consume_pragma (parser);
28987 : :
28988 : 457 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28989 : : {
28990 : 212 : if (c_parser_next_token_is (parser, CPP_COMMA)
28991 : 212 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28992 : 21 : c_parser_consume_token (parser);
28993 : :
28994 : 212 : if (!c_parser_next_token_is (parser, CPP_NAME))
28995 : : break;
28996 : :
28997 : 211 : const char *p
28998 : 211 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28999 : 211 : location_t cloc = c_parser_peek_token (parser)->location;
29000 : 211 : static const char *args[] = {
29001 : : "execution", "compilation", "warning", "fatal"
29002 : : };
29003 : 211 : int *v = NULL;
29004 : 211 : int idx = 0, n = -1;
29005 : 211 : tree m = NULL_TREE;
29006 : :
29007 : 211 : if (!strcmp (p, "at"))
29008 : : v = &at_compilation;
29009 : 127 : else if (!strcmp (p, "severity"))
29010 : : {
29011 : : v = &severity_fatal;
29012 : : idx += 2;
29013 : : }
29014 : 82 : else if (strcmp (p, "message"))
29015 : : {
29016 : 2 : error_at (cloc,
29017 : : "expected %<at%>, %<severity%> or %<message%> clause");
29018 : 2 : c_parser_skip_to_pragma_eol (parser, false);
29019 : 2 : return false;
29020 : : }
29021 : :
29022 : 209 : c_parser_consume_token (parser);
29023 : :
29024 : 209 : matching_parens parens;
29025 : 209 : if (parens.require_open (parser))
29026 : : {
29027 : 206 : if (v == NULL)
29028 : : {
29029 : 79 : location_t expr_loc = c_parser_peek_token (parser)->location;
29030 : 79 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
29031 : 79 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
29032 : 79 : m = convert (const_string_type_node, expr.value);
29033 : 79 : m = c_fully_fold (m, false, NULL);
29034 : : }
29035 : : else
29036 : : {
29037 : 127 : if (c_parser_next_token_is (parser, CPP_NAME))
29038 : : {
29039 : 123 : tree val = c_parser_peek_token (parser)->value;
29040 : 123 : const char *q = IDENTIFIER_POINTER (val);
29041 : :
29042 : 123 : if (!strcmp (q, args[idx]))
29043 : : n = 0;
29044 : 40 : else if (!strcmp (q, args[idx + 1]))
29045 : : n = 1;
29046 : : }
29047 : : if (n == -1)
29048 : : {
29049 : 6 : error_at (c_parser_peek_token (parser)->location,
29050 : 6 : "expected %qs or %qs", args[idx], args[idx + 1]);
29051 : 6 : bad = true;
29052 : 6 : switch (c_parser_peek_token (parser)->type)
29053 : : {
29054 : : case CPP_EOF:
29055 : : case CPP_PRAGMA_EOL:
29056 : : case CPP_CLOSE_PAREN:
29057 : : break;
29058 : 4 : default:
29059 : 4 : if (c_parser_peek_2nd_token (parser)->type
29060 : : == CPP_CLOSE_PAREN)
29061 : 2 : c_parser_consume_token (parser);
29062 : : break;
29063 : : }
29064 : : }
29065 : : else
29066 : 121 : c_parser_consume_token (parser);
29067 : : }
29068 : :
29069 : 206 : parens.skip_until_found_close (parser);
29070 : :
29071 : 206 : if (v == NULL)
29072 : : {
29073 : 79 : if (message)
29074 : : {
29075 : 1 : error_at (cloc, "too many %qs clauses", p);
29076 : 1 : bad = true;
29077 : : }
29078 : : else
29079 : : message = m;
29080 : : }
29081 : 127 : else if (n != -1)
29082 : : {
29083 : 121 : if (*v != -1)
29084 : : {
29085 : 2 : error_at (cloc, "too many %qs clauses", p);
29086 : 2 : bad = true;
29087 : : }
29088 : : else
29089 : 119 : *v = n;
29090 : : }
29091 : : }
29092 : : else
29093 : : bad = true;
29094 : : }
29095 : 122 : c_parser_skip_to_pragma_eol (parser);
29096 : 122 : if (bad)
29097 : : return true;
29098 : :
29099 : 110 : if (at_compilation == -1)
29100 : 33 : at_compilation = 1;
29101 : 110 : if (severity_fatal == -1)
29102 : 72 : severity_fatal = 1;
29103 : 110 : if (!at_compilation)
29104 : : {
29105 : 57 : if (context != pragma_compound)
29106 : : {
29107 : 7 : error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
29108 : : "may only be used in compound statements");
29109 : 7 : return true;
29110 : : }
29111 : 50 : tree fndecl
29112 : 58 : = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
29113 : : : BUILT_IN_GOMP_WARNING);
29114 : 50 : if (!message)
29115 : 4 : message = build_zero_cst (const_string_type_node);
29116 : 50 : tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
29117 : : build_all_ones_cst (size_type_node));
29118 : 50 : add_stmt (stmt);
29119 : 50 : return true;
29120 : : }
29121 : 53 : const char *msg = NULL;
29122 : 53 : if (message)
29123 : : {
29124 : 27 : msg = c_getstr (message);
29125 : 27 : if (msg == NULL)
29126 : 6 : msg = _("<message unknown at compile time>");
29127 : : }
29128 : 6 : if (msg)
29129 : 39 : emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
29130 : : "%<pragma omp error%> encountered: %s", msg);
29131 : : else
29132 : 29 : emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
29133 : : "%<pragma omp error%> encountered");
29134 : : return false;
29135 : : }
29136 : :
29137 : : /* Assumption clauses:
29138 : : OpenMP 5.1
29139 : : absent (directive-name-list)
29140 : : contains (directive-name-list)
29141 : : holds (expression)
29142 : : no_openmp
29143 : : no_openmp_routines
29144 : : no_parallelism */
29145 : :
29146 : : static void
29147 : 124 : c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
29148 : : {
29149 : 124 : bool no_openmp = false;
29150 : 124 : bool no_openmp_routines = false;
29151 : 124 : bool no_parallelism = false;
29152 : 124 : bitmap_head absent_head, contains_head;
29153 : :
29154 : 124 : bitmap_obstack_initialize (NULL);
29155 : 124 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
29156 : 124 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
29157 : :
29158 : 124 : if (c_parser_next_token_is (parser, CPP_PRAGMA_EOL))
29159 : 3 : error_at (c_parser_peek_token (parser)->location,
29160 : : "expected at least one assumption clause");
29161 : :
29162 : 343 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29163 : : {
29164 : 222 : if (c_parser_next_token_is (parser, CPP_COMMA)
29165 : 222 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29166 : 53 : c_parser_consume_token (parser);
29167 : :
29168 : 222 : if (!c_parser_next_token_is (parser, CPP_NAME))
29169 : : break;
29170 : :
29171 : 222 : const char *p
29172 : 222 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29173 : 222 : location_t cloc = c_parser_peek_token (parser)->location;
29174 : :
29175 : 222 : if (!strcmp (p, "no_openmp"))
29176 : : {
29177 : 16 : c_parser_consume_token (parser);
29178 : 16 : if (no_openmp)
29179 : 3 : error_at (cloc, "too many %qs clauses", "no_openmp");
29180 : : no_openmp = true;
29181 : : }
29182 : 206 : else if (!strcmp (p, "no_openmp_routines"))
29183 : : {
29184 : 16 : c_parser_consume_token (parser);
29185 : 16 : if (no_openmp_routines)
29186 : 3 : error_at (cloc, "too many %qs clauses", "no_openmp_routines");
29187 : : no_openmp_routines = true;
29188 : : }
29189 : 190 : else if (!strcmp (p, "no_parallelism"))
29190 : : {
29191 : 18 : c_parser_consume_token (parser);
29192 : 18 : if (no_parallelism)
29193 : 3 : error_at (cloc, "too many %qs clauses", "no_parallelism");
29194 : : no_parallelism = true;
29195 : : }
29196 : 172 : else if (!strcmp (p, "holds"))
29197 : : {
29198 : 18 : c_parser_consume_token (parser);
29199 : 18 : matching_parens parens;
29200 : 18 : if (parens.require_open (parser))
29201 : : {
29202 : 18 : location_t eloc = c_parser_peek_token (parser)->location;
29203 : 18 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
29204 : 18 : tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
29205 : 18 : t = c_objc_common_truthvalue_conversion (eloc, t);
29206 : 18 : t = c_fully_fold (t, false, NULL);
29207 : 18 : if (is_assume && t != error_mark_node)
29208 : : {
29209 : 10 : tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
29210 : : void_type_node, 1,
29211 : : t);
29212 : 10 : add_stmt (fn);
29213 : : }
29214 : 18 : parens.skip_until_found_close (parser);
29215 : : }
29216 : : }
29217 : 154 : else if (!strcmp (p, "absent") || !strcmp (p, "contains"))
29218 : : {
29219 : 145 : c_parser_consume_token (parser);
29220 : 145 : matching_parens parens;
29221 : 145 : if (parens.require_open (parser))
29222 : : {
29223 : 603 : do
29224 : : {
29225 : 374 : const char *directive[3] = {};
29226 : 374 : int i;
29227 : 374 : location_t dloc = c_parser_peek_token (parser)->location;
29228 : 841 : for (i = 0; i < 3; i++)
29229 : : {
29230 : 808 : tree id;
29231 : 808 : if (c_parser_peek_nth_token (parser, i + 1)->type
29232 : : == CPP_NAME)
29233 : 455 : id = c_parser_peek_nth_token (parser, i + 1)->value;
29234 : 353 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
29235 : : != RID_MAX)
29236 : : {
29237 : 12 : enum rid rid
29238 : 12 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
29239 : 12 : id = ridpointers[rid];
29240 : : }
29241 : : else
29242 : : break;
29243 : 467 : directive[i] = IDENTIFIER_POINTER (id);
29244 : : }
29245 : 374 : if (i == 0)
29246 : 0 : error_at (dloc, "expected directive name");
29247 : : else
29248 : : {
29249 : 374 : const struct c_omp_directive *dir
29250 : 374 : = c_omp_categorize_directive (directive[0],
29251 : : directive[1],
29252 : : directive[2]);
29253 : 374 : if (dir
29254 : 371 : && (dir->kind == C_OMP_DIR_DECLARATIVE
29255 : 368 : || dir->kind == C_OMP_DIR_INFORMATIONAL
29256 : 356 : || dir->kind == C_OMP_DIR_META))
29257 : 15 : error_at (dloc, "invalid OpenMP directive name in "
29258 : : "%qs clause argument: declarative, "
29259 : : "informational, and meta directives "
29260 : : "not permitted", p);
29261 : 356 : else if (dir == NULL
29262 : 356 : || dir->id == PRAGMA_OMP_END
29263 : 356 : || (!dir->second && directive[1])
29264 : 347 : || (!dir->third && directive[2]))
29265 : 12 : error_at (dloc, "unknown OpenMP directive name in "
29266 : : "%qs clause argument", p);
29267 : : else
29268 : : {
29269 : 347 : int id = dir - c_omp_directives;
29270 : 392 : if (bitmap_bit_p (p[0] == 'a' ? &contains_head
29271 : : : &absent_head, id))
29272 : 18 : error_at (dloc, "%<%s%s%s%s%s%> directive "
29273 : : "mentioned in both %<absent%> and "
29274 : : "%<contains%> clauses",
29275 : : directive[0],
29276 : : directive[1] ? " " : "",
29277 : : directive[1] ? directive[1] : "",
29278 : : directive[2] ? " " : "",
29279 : : directive[2] ? directive[2] : "");
29280 : 383 : else if (!bitmap_set_bit (p[0] == 'a'
29281 : : ? &absent_head
29282 : : : &contains_head, id))
29283 : 36 : error_at (dloc, "%<%s%s%s%s%s%> directive "
29284 : : "mentioned multiple times in %qs "
29285 : : "clauses",
29286 : : directive[0],
29287 : : directive[1] ? " " : "",
29288 : : directive[1] ? directive[1] : "",
29289 : : directive[2] ? " " : "",
29290 : : directive[2] ? directive[2] : "", p);
29291 : : }
29292 : 841 : for (; i; --i)
29293 : 467 : c_parser_consume_token (parser);
29294 : : }
29295 : 374 : if (c_parser_next_token_is (parser, CPP_COMMA))
29296 : 229 : c_parser_consume_token (parser);
29297 : : else
29298 : : break;
29299 : 229 : }
29300 : : while (1);
29301 : 145 : parens.skip_until_found_close (parser);
29302 : : }
29303 : 145 : }
29304 : 9 : else if (startswith (p, "ext_"))
29305 : : {
29306 : 6 : warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
29307 : 6 : c_parser_consume_token (parser);
29308 : 6 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
29309 : : {
29310 : 3 : matching_parens parens;
29311 : 3 : parens.consume_open (parser);
29312 : 3 : c_parser_balanced_token_sequence (parser);
29313 : 3 : parens.require_close (parser);
29314 : : }
29315 : : }
29316 : : else
29317 : : {
29318 : 3 : c_parser_consume_token (parser);
29319 : 3 : error_at (cloc, "expected assumption clause");
29320 : 3 : break;
29321 : : }
29322 : : }
29323 : 124 : c_parser_skip_to_pragma_eol (parser);
29324 : 124 : }
29325 : :
29326 : : /* OpenMP 5.1
29327 : : #pragma omp assume clauses[optseq] new-line */
29328 : :
29329 : : static void
29330 : 42 : c_parser_omp_assume (c_parser *parser, bool *if_p)
29331 : : {
29332 : 42 : c_parser_omp_assumption_clauses (parser, true);
29333 : 42 : add_stmt (c_parser_omp_structured_block (parser, if_p));
29334 : 42 : }
29335 : :
29336 : : /* OpenMP 5.1
29337 : : #pragma omp assumes clauses[optseq] new-line */
29338 : :
29339 : : static void
29340 : 37 : c_parser_omp_assumes (c_parser *parser)
29341 : : {
29342 : 37 : c_parser_consume_pragma (parser);
29343 : 37 : c_parser_omp_assumption_clauses (parser, false);
29344 : 37 : }
29345 : :
29346 : : /* Helper function for c_parser_omp_metadirective. */
29347 : :
29348 : : static void
29349 : 76 : analyze_metadirective_body (c_parser *parser,
29350 : : vec<c_token> &tokens,
29351 : : vec<tree> &labels)
29352 : : {
29353 : 76 : int nesting_depth = 0;
29354 : 76 : int bracket_depth = 0;
29355 : 76 : bool ignore_label = false;
29356 : :
29357 : : /* Read in the body tokens to the tokens for each candidate directive. */
29358 : 3928 : while (1)
29359 : : {
29360 : 2002 : c_token *token = c_parser_peek_token (parser);
29361 : 2002 : bool stop = false;
29362 : :
29363 : 2002 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
29364 : 0 : ignore_label = true;
29365 : :
29366 : 2002 : switch (token->type)
29367 : : {
29368 : : case CPP_EOF:
29369 : : break;
29370 : 635 : case CPP_NAME:
29371 : 635 : if (!ignore_label
29372 : 635 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
29373 : 8 : labels.safe_push (token->value);
29374 : 635 : goto add;
29375 : 27 : case CPP_OPEN_BRACE:
29376 : 27 : ++nesting_depth;
29377 : 27 : goto add;
29378 : 27 : case CPP_CLOSE_BRACE:
29379 : 27 : if (--nesting_depth == 0 && bracket_depth == 0)
29380 : 27 : stop = true;
29381 : 27 : goto add;
29382 : 102 : case CPP_OPEN_PAREN:
29383 : 102 : ++bracket_depth;
29384 : 102 : goto add;
29385 : 102 : case CPP_CLOSE_PAREN:
29386 : 102 : --bracket_depth;
29387 : 102 : goto add;
29388 : 17 : case CPP_COLON:
29389 : 17 : ignore_label = false;
29390 : 17 : goto add;
29391 : 238 : case CPP_SEMICOLON:
29392 : 238 : if (nesting_depth == 0 && bracket_depth == 0)
29393 : 63 : stop = true;
29394 : 238 : goto add;
29395 : 2002 : default:
29396 : 2002 : add:
29397 : 2002 : tokens.safe_push (*token);
29398 : 2002 : if (token->type == CPP_PRAGMA)
29399 : 5 : c_parser_consume_pragma (parser);
29400 : 1997 : else if (token->type == CPP_PRAGMA_EOL)
29401 : 5 : c_parser_skip_to_pragma_eol (parser);
29402 : : else
29403 : 1992 : c_parser_consume_token (parser);
29404 : 2002 : if (stop)
29405 : : break;
29406 : 1926 : continue;
29407 : : }
29408 : 76 : break;
29409 : 1926 : }
29410 : 76 : }
29411 : :
29412 : : /* OpenMP 5.0:
29413 : :
29414 : : # pragma omp metadirective [clause[, clause]]
29415 : : */
29416 : :
29417 : : static void
29418 : 108 : c_parser_omp_metadirective (c_parser *parser, bool *if_p)
29419 : : {
29420 : 108 : static unsigned int metadirective_region_count = 0;
29421 : :
29422 : 108 : tree ret;
29423 : 108 : auto_vec<c_token> directive_tokens;
29424 : 108 : auto_vec<c_token> body_tokens;
29425 : 108 : auto_vec<tree> body_labels;
29426 : 108 : auto_vec<const struct c_omp_directive *> directives;
29427 : 108 : auto_vec<tree> ctxs;
29428 : 108 : vec<struct omp_variant> candidates;
29429 : 108 : bool default_seen = false;
29430 : 108 : int directive_token_idx = 0;
29431 : 108 : tree standalone_body = NULL_TREE;
29432 : 108 : location_t pragma_loc = c_parser_peek_token (parser)->location;
29433 : 108 : bool requires_body = false;
29434 : :
29435 : 108 : ret = make_node (OMP_METADIRECTIVE);
29436 : 108 : SET_EXPR_LOCATION (ret, pragma_loc);
29437 : 108 : TREE_TYPE (ret) = void_type_node;
29438 : 108 : OMP_METADIRECTIVE_VARIANTS (ret) = NULL_TREE;
29439 : :
29440 : 108 : c_parser_consume_pragma (parser);
29441 : 410 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29442 : : {
29443 : 210 : if (c_parser_next_token_is (parser, CPP_COMMA))
29444 : 15 : c_parser_consume_token (parser);
29445 : 210 : if (c_parser_next_token_is_not (parser, CPP_NAME)
29446 : 272 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
29447 : : {
29448 : 0 : c_parser_error (parser, "expected %<when%>, "
29449 : : "%<otherwise%>, or %<default%> clause");
29450 : 0 : goto error;
29451 : : }
29452 : :
29453 : 210 : location_t match_loc = c_parser_peek_token (parser)->location;
29454 : 210 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29455 : 210 : c_parser_consume_token (parser);
29456 : 420 : bool default_p
29457 : 210 : = strcmp (p, "default") == 0 || strcmp (p, "otherwise") == 0;
29458 : 131 : if (default_p)
29459 : : {
29460 : 79 : if (default_seen)
29461 : : {
29462 : 4 : error_at (match_loc, "too many %<otherwise%> or %<default%> "
29463 : : "clauses in %<metadirective%>");
29464 : 4 : goto error;
29465 : : }
29466 : : default_seen = true;
29467 : : }
29468 : 131 : else if (default_seen)
29469 : : {
29470 : 2 : error_at (match_loc, "%<otherwise%> or %<default%> clause "
29471 : : "must appear last in %<metadirective%>");
29472 : 2 : goto error;
29473 : : }
29474 : 204 : if (!default_p && strcmp (p, "when") != 0)
29475 : : {
29476 : 2 : error_at (match_loc, "%qs is not valid for %qs",
29477 : : p, "metadirective");
29478 : 2 : goto error;
29479 : : }
29480 : :
29481 : 202 : matching_parens parens;
29482 : 202 : tree ctx = NULL_TREE;
29483 : 202 : bool skip = false;
29484 : :
29485 : 202 : if (!parens.require_open (parser))
29486 : 0 : goto error;
29487 : :
29488 : 202 : if (!default_p)
29489 : : {
29490 : 127 : ctx = c_parser_omp_context_selector_specification (parser,
29491 : : NULL_TREE);
29492 : 127 : if (ctx == error_mark_node)
29493 : 2 : goto error;
29494 : 125 : ctx = omp_check_context_selector (match_loc, ctx,
29495 : : OMP_CTX_METADIRECTIVE);
29496 : 125 : if (ctx == error_mark_node)
29497 : 0 : goto error;
29498 : :
29499 : : /* Remove the selector from further consideration if it can be
29500 : : evaluated as a non-match at this point. */
29501 : 125 : skip = (omp_context_selector_matches (ctx, NULL_TREE, false) == 0);
29502 : :
29503 : 125 : if (c_parser_next_token_is_not (parser, CPP_COLON))
29504 : : {
29505 : 2 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
29506 : 2 : goto error;
29507 : : }
29508 : 123 : c_parser_consume_token (parser);
29509 : : }
29510 : :
29511 : : /* Read in the directive type and create a dummy pragma token for
29512 : : it. */
29513 : 198 : location_t loc = c_parser_peek_token (parser)->location;
29514 : :
29515 : 198 : const char *directive[3] = {};
29516 : 198 : int i;
29517 : 554 : for (i = 0; i < 3; i++)
29518 : : {
29519 : 534 : tree id;
29520 : 534 : if (c_parser_peek_nth_token (parser, i + 1)->type
29521 : : == CPP_CLOSE_PAREN)
29522 : : {
29523 : 114 : if (i == 0)
29524 : 1 : directive[i++] = "nothing";
29525 : : break;
29526 : : }
29527 : 420 : else if (c_parser_peek_nth_token (parser, i + 1)->type
29528 : : == CPP_NAME)
29529 : 279 : id = c_parser_peek_nth_token (parser, i + 1)->value;
29530 : 141 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
29531 : : != RID_MAX)
29532 : : {
29533 : 77 : enum rid rid
29534 : 77 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
29535 : 77 : id = ridpointers[rid];
29536 : : }
29537 : : else
29538 : : break;
29539 : :
29540 : 356 : directive[i] = IDENTIFIER_POINTER (id);
29541 : : }
29542 : 85 : if (i == 0)
29543 : : {
29544 : 0 : error_at (loc, "expected directive name");
29545 : 0 : goto error;
29546 : : }
29547 : :
29548 : 198 : const struct c_omp_directive *omp_directive
29549 : 198 : = c_omp_categorize_directive (directive[0],
29550 : : directive[1],
29551 : 198 : directive[2]);
29552 : :
29553 : 198 : if (omp_directive == NULL)
29554 : : {
29555 : 4 : for (int j = 0; j < i; j++)
29556 : 2 : c_parser_consume_token (parser);
29557 : 2 : c_parser_error (parser, "unknown directive name");
29558 : 2 : goto error;
29559 : : }
29560 : : else
29561 : : {
29562 : 196 : int token_count = 0;
29563 : 196 : if (omp_directive->first) token_count++;
29564 : 196 : if (omp_directive->second) token_count++;
29565 : 196 : if (omp_directive->third) token_count++;
29566 : 392 : for (int j = 0; j < token_count; j++)
29567 : 196 : c_parser_consume_token (parser);
29568 : : }
29569 : 196 : if (omp_directive->id == PRAGMA_OMP_METADIRECTIVE)
29570 : : {
29571 : 2 : c_parser_error (parser,
29572 : : "metadirectives cannot be used as variants of a "
29573 : : "%<metadirective%>");
29574 : 2 : goto error;
29575 : : }
29576 : 194 : if (omp_directive->kind == C_OMP_DIR_DECLARATIVE)
29577 : : {
29578 : 0 : sorry_at (loc, "declarative directive variants of a "
29579 : : "%<metadirective%> are not supported");
29580 : 0 : goto error;
29581 : : }
29582 : 194 : if (omp_directive->kind == C_OMP_DIR_CONSTRUCT)
29583 : 116 : requires_body = true;
29584 : :
29585 : 194 : if (!skip)
29586 : : {
29587 : 161 : c_token pragma_token;
29588 : 161 : pragma_token.type = CPP_PRAGMA;
29589 : 161 : pragma_token.location = loc;
29590 : 161 : pragma_token.pragma_kind = (enum pragma_kind) omp_directive->id;
29591 : :
29592 : 161 : directives.safe_push (omp_directive);
29593 : 161 : directive_tokens.safe_push (pragma_token);
29594 : 161 : ctxs.safe_push (ctx);
29595 : : }
29596 : :
29597 : : /* Read in tokens for the directive clauses. */
29598 : : int nesting_depth = 0;
29599 : 1480 : while (1)
29600 : : {
29601 : 837 : c_token *token = c_parser_peek_token (parser);
29602 : 837 : switch (token->type)
29603 : : {
29604 : : case CPP_EOF:
29605 : : case CPP_PRAGMA_EOL:
29606 : : break;
29607 : 117 : case CPP_OPEN_PAREN:
29608 : 117 : ++nesting_depth;
29609 : 117 : goto add;
29610 : 310 : case CPP_CLOSE_PAREN:
29611 : 310 : if (nesting_depth-- == 0)
29612 : : {
29613 : 193 : c_parser_consume_token (parser);
29614 : 193 : break;
29615 : : }
29616 : 117 : goto add;
29617 : 643 : default:
29618 : 643 : add:
29619 : 643 : if (!skip)
29620 : 550 : directive_tokens.safe_push (*token);
29621 : 643 : c_parser_consume_token (parser);
29622 : 643 : continue;
29623 : : }
29624 : 194 : break;
29625 : 643 : }
29626 : :
29627 : 194 : if (!skip)
29628 : : {
29629 : 161 : c_token eol_token;
29630 : 161 : memset (&eol_token, 0, sizeof (eol_token));
29631 : 161 : eol_token.type = CPP_PRAGMA_EOL;
29632 : 161 : directive_tokens.safe_push (eol_token);
29633 : : }
29634 : : }
29635 : 92 : c_parser_skip_to_pragma_eol (parser);
29636 : :
29637 : 92 : if (!default_seen)
29638 : : {
29639 : : /* Add a default clause that evaluates to 'omp nothing'. */
29640 : 27 : const struct c_omp_directive *omp_directive
29641 : 27 : = c_omp_categorize_directive ("nothing", NULL, NULL);
29642 : :
29643 : 27 : c_token pragma_token;
29644 : 27 : pragma_token.type = CPP_PRAGMA;
29645 : 27 : pragma_token.location = UNKNOWN_LOCATION;
29646 : 27 : pragma_token.pragma_kind = PRAGMA_OMP_NOTHING;
29647 : :
29648 : 27 : directives.safe_push (omp_directive);
29649 : 27 : directive_tokens.safe_push (pragma_token);
29650 : 27 : ctxs.safe_push (NULL_TREE);
29651 : :
29652 : 27 : c_token eol_token;
29653 : 27 : memset (&eol_token, 0, sizeof (eol_token));
29654 : 27 : eol_token.type = CPP_PRAGMA_EOL;
29655 : 27 : directive_tokens.safe_push (eol_token);
29656 : : }
29657 : :
29658 : 92 : if (requires_body)
29659 : 76 : analyze_metadirective_body (parser, body_tokens, body_labels);
29660 : :
29661 : : /* Process each candidate directive. */
29662 : : unsigned i;
29663 : : tree ctx;
29664 : :
29665 : 274 : FOR_EACH_VEC_ELT (ctxs, i, ctx)
29666 : : {
29667 : 182 : auto_vec<c_token> tokens;
29668 : :
29669 : : /* Add the directive tokens. */
29670 : 908 : do
29671 : 908 : tokens.safe_push (directive_tokens [directive_token_idx++]);
29672 : 908 : while (tokens.last ().type != CPP_PRAGMA_EOL);
29673 : :
29674 : : /* Add the body tokens. */
29675 : 182 : gcc_assert (requires_body || body_tokens.is_empty ());
29676 : 4042 : for (unsigned j = 0; j < body_tokens.length (); j++)
29677 : 3860 : tokens.safe_push (body_tokens[j]);
29678 : :
29679 : : /* Make sure nothing tries to read past the end of the tokens. */
29680 : 182 : c_token eof_token;
29681 : 182 : memset (&eof_token, 0, sizeof (eof_token));
29682 : 182 : eof_token.type = CPP_EOF;
29683 : 182 : tokens.safe_push (eof_token);
29684 : 182 : tokens.safe_push (eof_token);
29685 : :
29686 : 182 : unsigned int old_tokens_avail = parser->tokens_avail;
29687 : 182 : c_token *old_tokens = parser->tokens;
29688 : 182 : struct omp_attribute_pragma_state *old_in_omp_attribute_pragma
29689 : : = parser->in_omp_attribute_pragma;
29690 : 182 : struct omp_metadirective_parse_data *old_state
29691 : : = parser->omp_metadirective_state;
29692 : :
29693 : 182 : struct omp_metadirective_parse_data new_state;
29694 : 182 : new_state.body_labels = &body_labels;
29695 : 182 : new_state.region_num = ++metadirective_region_count;
29696 : :
29697 : 182 : parser->tokens = tokens.address ();
29698 : 182 : parser->tokens_avail = tokens.length ();
29699 : 182 : parser->in_omp_attribute_pragma = NULL;
29700 : 182 : parser->omp_metadirective_state = &new_state;
29701 : :
29702 : 182 : int prev_errorcount = errorcount;
29703 : 182 : tree directive = c_begin_compound_stmt (true);
29704 : :
29705 : 182 : c_parser_pragma (parser, pragma_compound, if_p, NULL_TREE);
29706 : 182 : directive = c_end_compound_stmt (pragma_loc, directive, true);
29707 : 182 : bool standalone_p
29708 : 182 : = directives[i]->kind == C_OMP_DIR_STANDALONE
29709 : 182 : || directives[i]->kind == C_OMP_DIR_UTILITY;
29710 : 96 : if (standalone_p && requires_body)
29711 : : {
29712 : : /* Parsing standalone directives will not consume the body
29713 : : tokens, so do that here. */
29714 : 58 : if (standalone_body == NULL_TREE)
29715 : : {
29716 : 56 : standalone_body = push_stmt_list ();
29717 : 56 : c_parser_statement (parser, if_p);
29718 : 56 : standalone_body = pop_stmt_list (standalone_body);
29719 : : }
29720 : : else
29721 : 2 : c_parser_skip_to_end_of_block_or_statement (parser, true);
29722 : : }
29723 : :
29724 : 182 : tree body = standalone_p ? standalone_body : NULL_TREE;
29725 : 182 : tree variant = make_omp_metadirective_variant (ctx, directive, body);
29726 : 364 : OMP_METADIRECTIVE_VARIANTS (ret)
29727 : 182 : = chainon (OMP_METADIRECTIVE_VARIANTS (ret), variant);
29728 : :
29729 : : /* Check that all valid tokens have been consumed if no parse errors
29730 : : encountered. */
29731 : 182 : if (errorcount == prev_errorcount)
29732 : : {
29733 : 179 : gcc_assert (parser->tokens_avail == 2);
29734 : 179 : gcc_assert (c_parser_next_token_is (parser, CPP_EOF));
29735 : 179 : gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF);
29736 : : }
29737 : :
29738 : 182 : parser->tokens = old_tokens;
29739 : 182 : parser->tokens_avail = old_tokens_avail;
29740 : 182 : parser->in_omp_attribute_pragma = old_in_omp_attribute_pragma;
29741 : 182 : parser->omp_metadirective_state = old_state;
29742 : 182 : }
29743 : :
29744 : : /* Try to resolve the metadirective early. */
29745 : 92 : candidates = omp_early_resolve_metadirective (ret);
29746 : 92 : if (!candidates.is_empty ())
29747 : 68 : ret = c_omp_expand_variant_construct (candidates);
29748 : :
29749 : 92 : add_stmt (ret);
29750 : 92 : return;
29751 : :
29752 : 16 : error:
29753 : : /* Skip the metadirective pragma. Do not skip the metadirective body. */
29754 : 16 : if (parser->in_pragma)
29755 : 16 : c_parser_skip_to_pragma_eol (parser, false);
29756 : 108 : }
29757 : :
29758 : : /* Main entry point to parsing most OpenMP pragmas. */
29759 : :
29760 : : static void
29761 : 17222 : c_parser_omp_construct (c_parser *parser, bool *if_p)
29762 : : {
29763 : 17222 : enum pragma_kind p_kind;
29764 : 17222 : location_t loc;
29765 : 17222 : tree stmt;
29766 : 17222 : char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
29767 : 17222 : omp_clause_mask mask (0);
29768 : :
29769 : 17222 : loc = c_parser_peek_token (parser)->location;
29770 : 17222 : p_kind = c_parser_peek_token (parser)->pragma_kind;
29771 : 17222 : c_parser_consume_pragma (parser);
29772 : :
29773 : 17222 : switch (p_kind)
29774 : : {
29775 : 309 : case PRAGMA_OACC_ATOMIC:
29776 : 309 : c_parser_omp_atomic (loc, parser, true);
29777 : 2069 : return;
29778 : 137 : case PRAGMA_OACC_CACHE:
29779 : 137 : strcpy (p_name, "#pragma acc");
29780 : 137 : stmt = c_parser_oacc_cache (loc, parser);
29781 : 137 : break;
29782 : 497 : case PRAGMA_OACC_DATA:
29783 : 497 : stmt = c_parser_oacc_data (loc, parser, if_p);
29784 : 497 : break;
29785 : 23 : case PRAGMA_OACC_HOST_DATA:
29786 : 23 : stmt = c_parser_oacc_host_data (loc, parser, if_p);
29787 : 23 : break;
29788 : 2154 : case PRAGMA_OACC_KERNELS:
29789 : 2154 : case PRAGMA_OACC_PARALLEL:
29790 : 2154 : case PRAGMA_OACC_SERIAL:
29791 : 2154 : strcpy (p_name, "#pragma acc");
29792 : 2154 : stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
29793 : 2154 : break;
29794 : 1771 : case PRAGMA_OACC_LOOP:
29795 : 1771 : strcpy (p_name, "#pragma acc");
29796 : 1771 : stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
29797 : 1771 : break;
29798 : 80 : case PRAGMA_OACC_WAIT:
29799 : 80 : strcpy (p_name, "#pragma wait");
29800 : 80 : stmt = c_parser_oacc_wait (loc, parser, p_name);
29801 : 80 : break;
29802 : 1409 : case PRAGMA_OMP_ATOMIC:
29803 : 1409 : c_parser_omp_atomic (loc, parser, false);
29804 : 1409 : return;
29805 : 144 : case PRAGMA_OMP_CRITICAL:
29806 : 144 : stmt = c_parser_omp_critical (loc, parser, if_p);
29807 : 144 : break;
29808 : 1314 : case PRAGMA_OMP_DISTRIBUTE:
29809 : 1314 : strcpy (p_name, "#pragma omp");
29810 : 1314 : stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
29811 : 1314 : break;
29812 : 1806 : case PRAGMA_OMP_FOR:
29813 : 1806 : strcpy (p_name, "#pragma omp");
29814 : 1806 : stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
29815 : 1806 : break;
29816 : 157 : case PRAGMA_OMP_LOOP:
29817 : 157 : strcpy (p_name, "#pragma omp");
29818 : 157 : stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
29819 : 157 : break;
29820 : 60 : case PRAGMA_OMP_MASKED:
29821 : 60 : strcpy (p_name, "#pragma omp");
29822 : 60 : stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
29823 : 60 : break;
29824 : 142 : case PRAGMA_OMP_MASTER:
29825 : 142 : strcpy (p_name, "#pragma omp");
29826 : 142 : stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
29827 : 142 : break;
29828 : 2477 : case PRAGMA_OMP_PARALLEL:
29829 : 2477 : strcpy (p_name, "#pragma omp");
29830 : 2477 : stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
29831 : 2477 : break;
29832 : 61 : case PRAGMA_OMP_SCOPE:
29833 : 61 : stmt = c_parser_omp_scope (loc, parser, if_p);
29834 : 61 : break;
29835 : 106 : case PRAGMA_OMP_SECTIONS:
29836 : 106 : strcpy (p_name, "#pragma omp");
29837 : 106 : stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
29838 : 106 : break;
29839 : 726 : case PRAGMA_OMP_SIMD:
29840 : 726 : strcpy (p_name, "#pragma omp");
29841 : 726 : stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
29842 : 726 : break;
29843 : 222 : case PRAGMA_OMP_SINGLE:
29844 : 222 : stmt = c_parser_omp_single (loc, parser, if_p);
29845 : 222 : break;
29846 : 894 : case PRAGMA_OMP_TASK:
29847 : 894 : stmt = c_parser_omp_task (loc, parser, if_p);
29848 : 894 : break;
29849 : 138 : case PRAGMA_OMP_TASKGROUP:
29850 : 138 : stmt = c_parser_omp_taskgroup (loc, parser, if_p);
29851 : 138 : break;
29852 : 256 : case PRAGMA_OMP_TASKLOOP:
29853 : 256 : strcpy (p_name, "#pragma omp");
29854 : 256 : stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
29855 : 256 : break;
29856 : 1931 : case PRAGMA_OMP_TEAMS:
29857 : 1931 : strcpy (p_name, "#pragma omp");
29858 : 1931 : stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
29859 : 1931 : break;
29860 : 42 : case PRAGMA_OMP_ASSUME:
29861 : 42 : c_parser_omp_assume (parser, if_p);
29862 : 42 : return;
29863 : 110 : case PRAGMA_OMP_TILE:
29864 : 110 : stmt = c_parser_omp_tile (loc, parser, if_p);
29865 : 110 : break;
29866 : 105 : case PRAGMA_OMP_UNROLL:
29867 : 105 : stmt = c_parser_omp_unroll (loc, parser, if_p);
29868 : 105 : break;
29869 : 151 : case PRAGMA_OMP_DISPATCH:
29870 : 151 : stmt = c_parser_omp_dispatch (loc, parser);
29871 : 151 : break;
29872 : 0 : default:
29873 : 0 : gcc_unreachable ();
29874 : : }
29875 : :
29876 : 15462 : if (stmt && stmt != error_mark_node)
29877 : 15154 : gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
29878 : : }
29879 : :
29880 : :
29881 : : /* OpenMP 2.5:
29882 : : # pragma omp threadprivate (variable-list) */
29883 : :
29884 : : static void
29885 : 78 : c_parser_omp_threadprivate (c_parser *parser)
29886 : : {
29887 : 78 : tree vars, t;
29888 : 78 : location_t loc;
29889 : :
29890 : 78 : c_parser_consume_pragma (parser);
29891 : 78 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
29892 : :
29893 : : /* Mark every variable in VARS to be assigned thread local storage. */
29894 : 167 : for (t = vars; t; t = TREE_CHAIN (t))
29895 : : {
29896 : 89 : tree v = TREE_PURPOSE (t);
29897 : 89 : loc = EXPR_LOCATION (TREE_VALUE (t));
29898 : :
29899 : : /* If V had already been marked threadprivate, it doesn't matter
29900 : : whether it had been used prior to this point. */
29901 : 89 : if (!VAR_P (v))
29902 : 1 : error_at (loc, "%qD is not a variable", v);
29903 : 88 : else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
29904 : 2 : error_at (loc, "%qE declared %<threadprivate%> after first use", v);
29905 : 86 : else if (! is_global_var (v))
29906 : 2 : error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
29907 : 84 : else if (TREE_TYPE (v) == error_mark_node)
29908 : : ;
29909 : 83 : else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
29910 : 1 : error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
29911 : : else
29912 : : {
29913 : 82 : if (! DECL_THREAD_LOCAL_P (v))
29914 : : {
29915 : 82 : set_decl_tls_model (v, decl_default_tls_model (v));
29916 : : /* If rtl has been already set for this var, call
29917 : : make_decl_rtl once again, so that encode_section_info
29918 : : has a chance to look at the new decl flags. */
29919 : 82 : if (DECL_RTL_SET_P (v))
29920 : 0 : make_decl_rtl (v);
29921 : : }
29922 : 82 : C_DECL_THREADPRIVATE_P (v) = 1;
29923 : : }
29924 : : }
29925 : :
29926 : 78 : c_parser_skip_to_pragma_eol (parser);
29927 : 78 : }
29928 : :
29929 : : /* Parse a transaction attribute (GCC Extension).
29930 : :
29931 : : transaction-attribute:
29932 : : gnu-attributes
29933 : : attribute-specifier
29934 : : */
29935 : :
29936 : : static tree
29937 : 139 : c_parser_transaction_attributes (c_parser *parser)
29938 : : {
29939 : 139 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
29940 : 0 : return c_parser_gnu_attributes (parser);
29941 : :
29942 : 139 : if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
29943 : : return NULL_TREE;
29944 : 20 : return c_parser_std_attribute_specifier (parser, true);
29945 : : }
29946 : :
29947 : : /* Parse a __transaction_atomic or __transaction_relaxed statement
29948 : : (GCC Extension).
29949 : :
29950 : : transaction-statement:
29951 : : __transaction_atomic transaction-attribute[opt] compound-statement
29952 : : __transaction_relaxed compound-statement
29953 : :
29954 : : Note that the only valid attribute is: "outer".
29955 : : */
29956 : :
29957 : : static tree
29958 : 137 : c_parser_transaction (c_parser *parser, enum rid keyword)
29959 : : {
29960 : 137 : unsigned int old_in = parser->in_transaction;
29961 : 137 : unsigned int this_in = 1, new_in;
29962 : 137 : location_t loc = c_parser_peek_token (parser)->location;
29963 : 137 : tree stmt, attrs;
29964 : :
29965 : 274 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
29966 : : || keyword == RID_TRANSACTION_RELAXED)
29967 : : && c_parser_next_token_is_keyword (parser, keyword));
29968 : 137 : c_parser_consume_token (parser);
29969 : :
29970 : 137 : if (keyword == RID_TRANSACTION_RELAXED)
29971 : : this_in |= TM_STMT_ATTR_RELAXED;
29972 : : else
29973 : : {
29974 : 106 : attrs = c_parser_transaction_attributes (parser);
29975 : 106 : if (attrs)
29976 : 14 : this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
29977 : : }
29978 : :
29979 : : /* Keep track if we're in the lexical scope of an outer transaction. */
29980 : 137 : new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
29981 : :
29982 : 137 : parser->in_transaction = new_in;
29983 : 137 : stmt = c_parser_compound_statement (parser);
29984 : 137 : parser->in_transaction = old_in;
29985 : :
29986 : 137 : if (flag_tm)
29987 : 135 : stmt = c_finish_transaction (loc, stmt, this_in);
29988 : : else
29989 : 2 : error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
29990 : : "%<__transaction_atomic%> without transactional memory support enabled"
29991 : : : "%<__transaction_relaxed %> "
29992 : : "without transactional memory support enabled"));
29993 : :
29994 : 137 : return stmt;
29995 : : }
29996 : :
29997 : : /* Parse a __transaction_atomic or __transaction_relaxed expression
29998 : : (GCC Extension).
29999 : :
30000 : : transaction-expression:
30001 : : __transaction_atomic ( expression )
30002 : : __transaction_relaxed ( expression )
30003 : : */
30004 : :
30005 : : static struct c_expr
30006 : 7 : c_parser_transaction_expression (c_parser *parser, enum rid keyword)
30007 : : {
30008 : 7 : struct c_expr ret;
30009 : 7 : unsigned int old_in = parser->in_transaction;
30010 : 7 : unsigned int this_in = 1;
30011 : 7 : location_t loc = c_parser_peek_token (parser)->location;
30012 : 7 : tree attrs;
30013 : :
30014 : 14 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
30015 : : || keyword == RID_TRANSACTION_RELAXED)
30016 : : && c_parser_next_token_is_keyword (parser, keyword));
30017 : 7 : c_parser_consume_token (parser);
30018 : :
30019 : 7 : if (keyword == RID_TRANSACTION_RELAXED)
30020 : : this_in |= TM_STMT_ATTR_RELAXED;
30021 : : else
30022 : : {
30023 : 5 : attrs = c_parser_transaction_attributes (parser);
30024 : 5 : if (attrs)
30025 : 0 : this_in |= parse_tm_stmt_attr (attrs, 0);
30026 : : }
30027 : :
30028 : 7 : parser->in_transaction = this_in;
30029 : 7 : matching_parens parens;
30030 : 7 : if (parens.require_open (parser))
30031 : : {
30032 : 7 : tree expr = c_parser_expression (parser).value;
30033 : 7 : ret.original_type = TREE_TYPE (expr);
30034 : 7 : ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
30035 : 7 : if (this_in & TM_STMT_ATTR_RELAXED)
30036 : 2 : TRANSACTION_EXPR_RELAXED (ret.value) = 1;
30037 : 7 : SET_EXPR_LOCATION (ret.value, loc);
30038 : 7 : ret.original_code = TRANSACTION_EXPR;
30039 : 7 : ret.m_decimal = 0;
30040 : 7 : if (!parens.require_close (parser))
30041 : : {
30042 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
30043 : 0 : goto error;
30044 : : }
30045 : : }
30046 : : else
30047 : : {
30048 : 0 : error:
30049 : 0 : ret.set_error ();
30050 : 0 : ret.original_code = ERROR_MARK;
30051 : 0 : ret.original_type = NULL;
30052 : : }
30053 : 7 : parser->in_transaction = old_in;
30054 : :
30055 : 7 : if (!flag_tm)
30056 : 6 : error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
30057 : : "%<__transaction_atomic%> without transactional memory support enabled"
30058 : : : "%<__transaction_relaxed %> "
30059 : : "without transactional memory support enabled"));
30060 : :
30061 : 7 : set_c_expr_source_range (&ret, loc, loc);
30062 : :
30063 : 7 : return ret;
30064 : : }
30065 : :
30066 : : /* Parse a __transaction_cancel statement (GCC Extension).
30067 : :
30068 : : transaction-cancel-statement:
30069 : : __transaction_cancel transaction-attribute[opt] ;
30070 : :
30071 : : Note that the only valid attribute is "outer".
30072 : : */
30073 : :
30074 : : static tree
30075 : 28 : c_parser_transaction_cancel (c_parser *parser)
30076 : : {
30077 : 28 : location_t loc = c_parser_peek_token (parser)->location;
30078 : 28 : tree attrs;
30079 : 28 : bool is_outer = false;
30080 : :
30081 : 28 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
30082 : 28 : c_parser_consume_token (parser);
30083 : :
30084 : 28 : attrs = c_parser_transaction_attributes (parser);
30085 : 28 : if (attrs)
30086 : 5 : is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
30087 : :
30088 : 28 : if (!flag_tm)
30089 : : {
30090 : 2 : error_at (loc, "%<__transaction_cancel%> without "
30091 : : "transactional memory support enabled");
30092 : 2 : goto ret_error;
30093 : : }
30094 : 26 : else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
30095 : : {
30096 : 0 : error_at (loc, "%<__transaction_cancel%> within a "
30097 : : "%<__transaction_relaxed%>");
30098 : 0 : goto ret_error;
30099 : : }
30100 : 26 : else if (is_outer)
30101 : : {
30102 : 5 : if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
30103 : 5 : && !is_tm_may_cancel_outer (current_function_decl))
30104 : : {
30105 : 0 : error_at (loc, "outer %<__transaction_cancel%> not "
30106 : : "within outer %<__transaction_atomic%> or "
30107 : : "a %<transaction_may_cancel_outer%> function");
30108 : 0 : goto ret_error;
30109 : : }
30110 : : }
30111 : 21 : else if (parser->in_transaction == 0)
30112 : : {
30113 : 0 : error_at (loc, "%<__transaction_cancel%> not within "
30114 : : "%<__transaction_atomic%>");
30115 : 0 : goto ret_error;
30116 : : }
30117 : :
30118 : 26 : return add_stmt (build_tm_abort_call (loc, is_outer));
30119 : :
30120 : 2 : ret_error:
30121 : 2 : return build1 (NOP_EXPR, void_type_node, error_mark_node);
30122 : : }
30123 : :
30124 : : /* Parse a single source file. */
30125 : :
30126 : : void
30127 : 106165 : c_parse_file (void)
30128 : : {
30129 : : /* Use local storage to begin. If the first token is a pragma, parse it.
30130 : : If it is #pragma GCC pch_preprocess, then this will load a PCH file
30131 : : which will cause garbage collection. */
30132 : 106165 : c_parser tparser;
30133 : :
30134 : 106165 : memset (&tparser, 0, sizeof tparser);
30135 : 106165 : tparser.translate_strings_p = true;
30136 : 106165 : tparser.tokens = &tparser.tokens_buf[0];
30137 : 106165 : the_parser = &tparser;
30138 : :
30139 : 106165 : if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
30140 : 12 : c_parser_pragma_pch_preprocess (&tparser);
30141 : : else
30142 : 106090 : c_common_no_more_pch ();
30143 : :
30144 : 106102 : the_parser = ggc_alloc<c_parser> ();
30145 : 106102 : *the_parser = tparser;
30146 : 106102 : if (tparser.tokens == &tparser.tokens_buf[0])
30147 : 106102 : the_parser->tokens = &the_parser->tokens_buf[0];
30148 : :
30149 : : /* Initialize EH, if we've been told to do so. */
30150 : 106102 : if (flag_exceptions)
30151 : 500 : using_eh_for_cleanups ();
30152 : :
30153 : 106102 : c_parser_translation_unit (the_parser);
30154 : 106012 : the_parser = NULL;
30155 : 106012 : }
30156 : :
30157 : : void
30158 : 4837 : c_init_preprocess (void)
30159 : : {
30160 : : /* Create a parser for use by pragma_lex during preprocessing. */
30161 : 4837 : the_parser = ggc_alloc<c_parser> ();
30162 : 4837 : memset (the_parser, 0, sizeof (c_parser));
30163 : 4837 : the_parser->tokens = &the_parser->tokens_buf[0];
30164 : 4837 : }
30165 : :
30166 : : /* Parse the body of a function declaration marked with "__RTL".
30167 : :
30168 : : The RTL parser works on the level of characters read from a
30169 : : FILE *, whereas c_parser works at the level of tokens.
30170 : : Square this circle by consuming all of the tokens up to and
30171 : : including the closing brace, recording the start/end of the RTL
30172 : : fragment, and reopening the file and re-reading the relevant
30173 : : lines within the RTL parser.
30174 : :
30175 : : This requires the opening and closing braces of the C function
30176 : : to be on separate lines from the RTL they wrap.
30177 : :
30178 : : Take ownership of START_WITH_PASS, if non-NULL. */
30179 : :
30180 : : location_t
30181 : 25 : c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
30182 : : {
30183 : 25 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
30184 : : {
30185 : 0 : free (start_with_pass);
30186 : 0 : return c_parser_peek_token (parser)->location;
30187 : : }
30188 : :
30189 : 25 : location_t start_loc = c_parser_peek_token (parser)->location;
30190 : :
30191 : : /* Consume all tokens, up to the closing brace, handling
30192 : : matching pairs of braces in the rtl dump. */
30193 : 25 : int num_open_braces = 1;
30194 : 25239 : while (1)
30195 : : {
30196 : 12632 : switch (c_parser_peek_token (parser)->type)
30197 : : {
30198 : 1 : case CPP_OPEN_BRACE:
30199 : 1 : num_open_braces++;
30200 : 1 : break;
30201 : 25 : case CPP_CLOSE_BRACE:
30202 : 25 : if (--num_open_braces == 0)
30203 : 24 : goto found_closing_brace;
30204 : : break;
30205 : 1 : case CPP_EOF:
30206 : 1 : error_at (start_loc, "no closing brace");
30207 : 1 : free (start_with_pass);
30208 : 1 : return c_parser_peek_token (parser)->location;
30209 : : default:
30210 : : break;
30211 : : }
30212 : 12607 : c_parser_consume_token (parser);
30213 : : }
30214 : :
30215 : 24 : found_closing_brace:
30216 : : /* At the closing brace; record its location. */
30217 : 24 : location_t end_loc = c_parser_peek_token (parser)->location;
30218 : :
30219 : : /* Consume the closing brace. */
30220 : 24 : c_parser_consume_token (parser);
30221 : :
30222 : : /* Invoke the RTL parser. */
30223 : 24 : if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
30224 : : {
30225 : 0 : free (start_with_pass);
30226 : 0 : return end_loc;
30227 : : }
30228 : :
30229 : : /* Run the backend on the cfun created above, transferring ownership of
30230 : : START_WITH_PASS. */
30231 : 23 : run_rtl_passes (start_with_pass);
30232 : 23 : return end_loc;
30233 : : }
30234 : :
30235 : : #include "gt-c-c-parser.h"
|