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 : 203275438 : set_c_expr_source_range (c_expr *expr,
92 : : location_t start, location_t finish)
93 : : {
94 : 203275438 : expr->src_range.m_start = start;
95 : 203275438 : expr->src_range.m_finish = finish;
96 : 203275438 : if (expr->value)
97 : 203275312 : set_source_range (expr->value, start, finish);
98 : 203275438 : }
99 : :
100 : : void
101 : 225674754 : set_c_expr_source_range (c_expr *expr,
102 : : source_range src_range)
103 : : {
104 : 225674754 : expr->src_range = src_range;
105 : 225674754 : if (expr->value)
106 : 225674749 : set_source_range (expr->value, src_range);
107 : 225674754 : }
108 : :
109 : :
110 : : /* Initialization routine for this file. */
111 : :
112 : : void
113 : 112061 : c_parse_init (void)
114 : : {
115 : : /* The only initialization required is of the reserved word
116 : : identifiers. */
117 : 112061 : unsigned int i;
118 : 112061 : tree id;
119 : 112061 : 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 : 112061 : gcc_assert (RID_MAX <= 255);
124 : :
125 : 112061 : mask |= D_CXXONLY;
126 : 112061 : if (!flag_isoc99)
127 : 6396 : mask |= D_C99;
128 : 112061 : if (!flag_isoc23)
129 : 12600 : mask |= D_C23;
130 : 112061 : if (flag_no_asm)
131 : : {
132 : 5542 : mask |= D_ASM | D_EXT;
133 : 5542 : if (!flag_isoc99)
134 : 3446 : mask |= D_EXT89;
135 : 5542 : if (!flag_isoc23)
136 : 4571 : mask |= D_EXT11;
137 : : }
138 : 112061 : if (!c_dialect_objc ())
139 : 112061 : mask |= D_OBJC | D_CXX_OBJC;
140 : :
141 : 112061 : ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
142 : 25661969 : 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 : 25549908 : if (c_common_reswords[i].disable & mask)
147 : : {
148 : 9812427 : if (warn_cxx_compat
149 : 109357 : && (c_common_reswords[i].disable & D_CXXWARN))
150 : : {
151 : 51111 : id = get_identifier (c_common_reswords[i].word);
152 : 51111 : C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
153 : 51111 : C_IS_RESERVED_WORD (id) = 1;
154 : : }
155 : 9812427 : continue;
156 : : }
157 : :
158 : 15737481 : id = get_identifier (c_common_reswords[i].word);
159 : 15737481 : C_SET_RID_CODE (id, c_common_reswords[i].rid);
160 : 15737481 : C_IS_RESERVED_WORD (id) = 1;
161 : 15737481 : ridpointers [(int) c_common_reswords[i].rid] = id;
162 : : }
163 : :
164 : 224122 : for (i = 0; i < NUM_INT_N_ENTS; i++)
165 : : {
166 : : /* We always create the symbols but they aren't always supported. */
167 : 112061 : char name[50];
168 : 112061 : sprintf (name, "__int%d", int_n_data[i].bitsize);
169 : 112061 : id = get_identifier (name);
170 : 112061 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
171 : 112061 : C_IS_RESERVED_WORD (id) = 1;
172 : :
173 : 112061 : sprintf (name, "__int%d__", int_n_data[i].bitsize);
174 : 112061 : id = get_identifier (name);
175 : 112061 : C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
176 : 112061 : C_IS_RESERVED_WORD (id) = 1;
177 : : }
178 : :
179 : 112061 : if (flag_openmp)
180 : : {
181 : 2195 : id = get_identifier ("omp_all_memory");
182 : 2195 : C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
183 : 2195 : C_IS_RESERVED_WORD (id) = 1;
184 : 2195 : ridpointers [RID_OMP_ALL_MEMORY] = id;
185 : : }
186 : 112061 : }
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 : 197 : c_parser_tokens_buf (c_parser *parser, unsigned n)
293 : : {
294 : 197 : return &parser->tokens_buf[n];
295 : : }
296 : :
297 : : /* Return the error state of PARSER. */
298 : :
299 : : bool
300 : 4093 : c_parser_error (c_parser *parser)
301 : : {
302 : 4093 : 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 : 2264235051 : c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
324 : : {
325 : 2264235051 : timevar_push (TV_LEX);
326 : :
327 : 2264235051 : if (raw || vec_safe_length (parser->raw_tokens) == 0)
328 : : {
329 : 2264174874 : token->type = c_lex_with_flags (&token->value, &token->location,
330 : : &token->flags,
331 : 2264174874 : (parser->lex_joined_string
332 : : ? 0 : C_LEX_STRING_NO_JOIN));
333 : 2264174722 : token->id_kind = C_ID_NONE;
334 : 2264174722 : token->keyword = RID_MAX;
335 : 2264174722 : 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 : 60177 : *token = (*parser->raw_tokens)[parser->raw_tokens_used];
342 : 60177 : ++parser->raw_tokens_used;
343 : 60177 : if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
344 : : {
345 : 14057 : vec_free (parser->raw_tokens);
346 : 14057 : parser->raw_tokens_used = 0;
347 : : }
348 : : }
349 : :
350 : 2264234899 : if (raw)
351 : 60177 : goto out;
352 : :
353 : 2264174722 : switch (token->type)
354 : : {
355 : 1018944865 : case CPP_NAME:
356 : 1018944865 : {
357 : 1018944865 : tree decl;
358 : :
359 : 1018944865 : bool objc_force_identifier = parser->objc_need_raw_identifier;
360 : 1018944865 : if (c_dialect_objc ())
361 : 0 : parser->objc_need_raw_identifier = false;
362 : :
363 : 1018944865 : if (C_IS_RESERVED_WORD (token->value))
364 : : {
365 : 283264212 : enum rid rid_code = C_RID_CODE (token->value);
366 : :
367 : 283264212 : 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 : 283264177 : else if (rid_code >= RID_FIRST_ADDR_SPACE
375 : 283264177 : && 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 : 283264003 : 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 : 283264003 : 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 : 283264003 : 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 : 283264003 : token->type = CPP_KEYWORD;
449 : 283264003 : token->keyword = rid_code;
450 : 283264003 : break;
451 : : }
452 : : }
453 : :
454 : 735680688 : decl = lookup_name (token->value);
455 : 735680688 : if (decl)
456 : : {
457 : 411702679 : if (TREE_CODE (decl) == TYPE_DECL)
458 : : {
459 : 239626368 : token->id_kind = C_ID_TYPENAME;
460 : 239626368 : break;
461 : : }
462 : : }
463 : 323978009 : 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 : 496054320 : token->id_kind = C_ID_ID;
478 : : }
479 : 496054320 : 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 : 682563186 : case CPP_COLON:
505 : 682563186 : case CPP_COMMA:
506 : 682563186 : case CPP_CLOSE_PAREN:
507 : 682563186 : case CPP_SEMICOLON:
508 : : /* These tokens may affect the interpretation of any identifiers
509 : : following, if doing Objective-C. */
510 : 682563186 : if (c_dialect_objc ())
511 : 0 : parser->objc_need_raw_identifier = false;
512 : : break;
513 : 1948794 : case CPP_PRAGMA:
514 : : /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
515 : 1948794 : token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
516 : 1948794 : token->value = NULL;
517 : 1948794 : break;
518 : : default:
519 : : break;
520 : : }
521 : 2264234899 : out:
522 : 2264234899 : timevar_pop (TV_LEX);
523 : 2264234899 : }
524 : :
525 : : /* Return a pointer to the next token from PARSER, reading it in if
526 : : necessary. */
527 : :
528 : : c_token *
529 : 17251740802 : c_parser_peek_token (c_parser *parser)
530 : : {
531 : 17251740802 : if (parser->tokens_avail == 0)
532 : : {
533 : 1856030530 : c_lex_one_token (parser, &parser->tokens[0]);
534 : 1856030378 : parser->tokens_avail = 1;
535 : : }
536 : 17251740650 : 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 : 177779317 : c_parser_peek_2nd_token (c_parser *parser)
544 : : {
545 : 177779317 : if (parser->tokens_avail >= 2)
546 : 30014829 : return &parser->tokens[1];
547 : 147764488 : gcc_assert (parser->tokens_avail == 1);
548 : 147764488 : gcc_assert (parser->tokens[0].type != CPP_EOF);
549 : 147764488 : gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
550 : 147764488 : c_lex_one_token (parser, &parser->tokens[1]);
551 : 147764488 : parser->tokens_avail = 2;
552 : 147764488 : 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 : 874396681 : c_parser_peek_nth_token (c_parser *parser, unsigned int n)
560 : : {
561 : : /* N is 1-based, not zero-based. */
562 : 874396681 : gcc_assert (n > 0);
563 : :
564 : 874396681 : if (parser->tokens_avail >= n)
565 : 614016825 : return &parser->tokens[n - 1];
566 : 260379856 : gcc_assert (parser->tokens_avail == n - 1);
567 : 260379856 : c_lex_one_token (parser, &parser->tokens[n - 1]);
568 : 260379856 : parser->tokens_avail = n;
569 : 260379856 : 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 : 87231 : c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
579 : : {
580 : : /* N is 1-based, not zero-based. */
581 : 87231 : gcc_assert (n > 0);
582 : :
583 : 87231 : if (parser->tokens_avail >= n)
584 : 10297 : return &parser->tokens[n - 1];
585 : 76934 : unsigned int raw_len = vec_safe_length (parser->raw_tokens);
586 : 76934 : unsigned int raw_avail
587 : 76934 : = parser->tokens_avail + raw_len - parser->raw_tokens_used;
588 : 76934 : gcc_assert (raw_avail >= n - 1);
589 : 76934 : if (raw_avail >= n)
590 : 16757 : return &(*parser->raw_tokens)[parser->raw_tokens_used
591 : 16757 : + n - 1 - parser->tokens_avail];
592 : 60177 : vec_safe_reserve (parser->raw_tokens, 1);
593 : 60177 : parser->raw_tokens->quick_grow (raw_len + 1);
594 : 60177 : c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
595 : 60177 : return &(*parser->raw_tokens)[raw_len];
596 : : }
597 : :
598 : : bool
599 : 43707847 : c_keyword_starts_typename (enum rid keyword)
600 : : {
601 : 43707847 : 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 : 35773432 : default:
637 : 35773432 : if (keyword >= RID_FIRST_INT_N
638 : : && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
639 : 497 : && 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 : 437300585 : c_token_starts_typename (c_token *token)
649 : : {
650 : 437300585 : switch (token->type)
651 : : {
652 : 387151593 : case CPP_NAME:
653 : 387151593 : 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 : 43652671 : case CPP_KEYWORD:
668 : 43652671 : 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 : 311560068 : c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
684 : : {
685 : 311560068 : c_token *token = c_parser_peek_token (parser);
686 : 311560068 : if (c_token_starts_typename (token))
687 : : return true;
688 : :
689 : : /* Try a bit harder to detect an unknown typename. */
690 : 68211605 : if (la != cla_prefer_id
691 : 43357423 : && token->type == CPP_NAME
692 : 6354469 : && token->id_kind == C_ID_ID
693 : :
694 : : /* Do not try too hard when we could have "object in array". */
695 : 6354469 : && !parser->objc_could_be_foreach_context
696 : :
697 : 6354469 : && (la == cla_prefer_type
698 : 6354374 : || c_parser_peek_2nd_token (parser)->type == CPP_NAME
699 : 6354290 : || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
700 : :
701 : : /* Only unknown identifiers. */
702 : 68213041 : && !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 : 125736807 : c_token_starts_compound_literal (c_token *token)
713 : : {
714 : 125736807 : switch (token->type)
715 : : {
716 : 4434998 : case CPP_KEYWORD:
717 : 4434998 : 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 : 125736518 : default:
729 : 125736518 : return c_token_starts_typename (token);
730 : : }
731 : : }
732 : :
733 : : /* Return true if TOKEN is a type qualifier, false otherwise. */
734 : : static bool
735 : 426621462 : c_token_is_qualifier (c_token *token)
736 : : {
737 : 426621462 : switch (token->type)
738 : : {
739 : 422848707 : case CPP_NAME:
740 : 422848707 : switch (token->id_kind)
741 : : {
742 : : case C_ID_ADDRSPACE:
743 : : return true;
744 : : default:
745 : : return false;
746 : : }
747 : 3772755 : case CPP_KEYWORD:
748 : 3772755 : 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 : 426621462 : c_parser_next_token_is_qualifier (c_parser *parser)
770 : : {
771 : 426621462 : c_token *token = c_parser_peek_token (parser);
772 : 426621462 : 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 : 172063981 : c_token_starts_declspecs (c_token *token)
779 : : {
780 : 172063981 : switch (token->type)
781 : : {
782 : 95842419 : case CPP_NAME:
783 : 95842419 : 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 : 74564947 : case CPP_KEYWORD:
798 : 74564947 : 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 : 35432097 : default:
843 : 35432097 : if (token->keyword >= RID_FIRST_INT_N
844 : : && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
845 : 413 : && 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 : 49935259 : c_token_starts_declaration (c_token *token)
864 : : {
865 : 49935259 : if (c_token_starts_declspecs (token)
866 : 49935259 : || token->keyword == RID_STATIC_ASSERT)
867 : 7498393 : 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 : 122128722 : c_parser_next_token_starts_declspecs (c_parser *parser)
877 : : {
878 : 122128722 : 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 : 122128722 : if (c_dialect_objc ()
887 : 0 : && token->type == CPP_NAME
888 : 0 : && token->id_kind == C_ID_CLASSNAME
889 : 122128722 : && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
890 : : return false;
891 : :
892 : 122128722 : 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 : 49934497 : c_parser_next_tokens_start_declaration (c_parser *parser)
900 : : {
901 : 49934497 : c_token *token = c_parser_peek_token (parser);
902 : :
903 : : /* Same as above. */
904 : 49934497 : if (c_dialect_objc ()
905 : 0 : && token->type == CPP_NAME
906 : 0 : && token->id_kind == C_ID_CLASSNAME
907 : 49934497 : && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
908 : : return false;
909 : :
910 : : /* Labels do not start declarations. */
911 : 49934497 : if (token->type == CPP_NAME
912 : 49934497 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
913 : : return false;
914 : :
915 : 49934479 : if (c_token_starts_declaration (token))
916 : : return true;
917 : :
918 : 42436157 : 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 : 2262161587 : c_parser_consume_token (c_parser *parser)
928 : : {
929 : 2262161587 : gcc_assert (parser->tokens_avail >= 1);
930 : 2262161587 : gcc_assert (parser->tokens[0].type != CPP_EOF);
931 : 2262161587 : gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
932 : 2262161587 : gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
933 : 2262161587 : parser->last_token_location = parser->tokens[0].location;
934 : 2262161587 : if (parser->tokens != &parser->tokens_buf[0])
935 : 42620 : parser->tokens++;
936 : 2262118967 : else if (parser->tokens_avail >= 2)
937 : : {
938 : 148929329 : parser->tokens[0] = parser->tokens[1];
939 : 148929329 : if (parser->tokens_avail >= 3)
940 : : {
941 : 32308 : parser->tokens[1] = parser->tokens[2];
942 : 32308 : if (parser->tokens_avail >= 4)
943 : 12572 : parser->tokens[2] = parser->tokens[3];
944 : : }
945 : : }
946 : 2262161587 : parser->tokens_avail--;
947 : 2262161587 : parser->seen_string_literal = false;
948 : 2262161587 : }
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 : 1949616 : c_parser_consume_pragma (c_parser *parser)
955 : : {
956 : 1949616 : gcc_assert (!parser->in_pragma);
957 : 1949616 : gcc_assert (parser->tokens_avail >= 1);
958 : 1949616 : gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
959 : 1949616 : if (parser->tokens != &parser->tokens_buf[0])
960 : 932 : parser->tokens++;
961 : 1948684 : 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 : 1949616 : parser->tokens_avail--;
968 : 1949616 : parser->in_pragma = true;
969 : 1949616 : }
970 : :
971 : : /* Update the global input_location from TOKEN. */
972 : : static inline void
973 : 7960005 : c_parser_set_source_position_from_token (c_token *token)
974 : : {
975 : 7960005 : if (token->type != CPP_EOF)
976 : : {
977 : 7959929 : 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 : 3034 : c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1039 : : rich_location *richloc)
1040 : : {
1041 : 3034 : c_token *token = c_parser_peek_token (parser);
1042 : 3034 : if (parser->error)
1043 : : return false;
1044 : 2319 : parser->error = true;
1045 : 2319 : if (!gmsgid)
1046 : : return false;
1047 : :
1048 : : /* If this is actually a conflict marker, report it as such. */
1049 : 2203 : if (token->type == CPP_LSHIFT
1050 : 2203 : || token->type == CPP_RSHIFT
1051 : 2184 : || 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 : 2191 : auto_diagnostic_group d;
1067 : 2191 : name_hint h;
1068 : 2191 : 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 : 2191 : c_parse_error (gmsgid,
1083 : : /* Because c_parse_error does not understand
1084 : : CPP_KEYWORD, keywords are treated like
1085 : : identifiers. */
1086 : 2191 : (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 : 2191 : return true;
1093 : 2191 : }
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 : 1925 : c_parser_error (c_parser *parser, const char *gmsgid)
1101 : : {
1102 : 1925 : c_token *token = c_parser_peek_token (parser);
1103 : 1925 : c_parser_set_source_position_from_token (token);
1104 : 1925 : rich_location richloc (line_table, input_location);
1105 : 1925 : return c_parser_error_richloc (parser, gmsgid, &richloc);
1106 : 1925 : }
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 : 172658902 : 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 : 4442866 : bool require_open (c_parser *parser)
1128 : : {
1129 : 4442866 : c_token *token = c_parser_peek_token (parser);
1130 : 4442866 : if (token)
1131 : 4442866 : m_open_loc = token->location;
1132 : :
1133 : 4442866 : return c_parser_require (parser, traits_t::open_token_type,
1134 : 4442866 : 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 : 168216173 : void consume_open (c_parser *parser)
1141 : : {
1142 : 168216173 : c_token *token = c_parser_peek_token (parser);
1143 : 168216173 : gcc_assert (token->type == traits_t::open_token_type);
1144 : 168216173 : m_open_loc = token->location;
1145 : 168216173 : c_parser_consume_token (parser);
1146 : 168216173 : }
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 : 1757762 : bool require_close (c_parser *parser) const
1154 : : {
1155 : 1757762 : return c_parser_require (parser, traits_t::close_token_type,
1156 : 1757762 : 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 : 169532986 : void skip_until_found_close (c_parser *parser) const
1164 : : {
1165 : 169532986 : c_parser_skip_until_found (parser, traits_t::close_token_type,
1166 : 169532986 : traits_t::close_gmsgid, m_open_loc);
1167 : 48462 : }
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 : 442260576 : 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 : 442260576 : if (c_parser_next_token_is (parser, type))
1251 : : {
1252 : 442259467 : c_parser_consume_token (parser);
1253 : 442259467 : return true;
1254 : : }
1255 : : else
1256 : : {
1257 : 1109 : location_t next_token_loc = c_parser_peek_token (parser)->location;
1258 : 1109 : 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 : 1109 : if (!parser->error && type_is_unique)
1264 : 646 : 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 : 1109 : bool added_matching_location = false;
1271 : 1109 : if (matching_location != UNKNOWN_LOCATION)
1272 : 397 : added_matching_location
1273 : 397 : = richloc.add_location_if_nearby (*global_dc, matching_location);
1274 : :
1275 : 1109 : 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 : 538 : if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1279 : 4 : inform (matching_location, "to match this %qs",
1280 : : get_matching_symbol (type));
1281 : :
1282 : 1109 : return false;
1283 : 1109 : }
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 : 144613 : c_parser_require_keyword (c_parser *parser,
1291 : : enum rid keyword,
1292 : : const char *msgid)
1293 : : {
1294 : 144613 : if (c_parser_next_token_is_keyword (parser, keyword))
1295 : : {
1296 : 144612 : c_parser_consume_token (parser);
1297 : 144612 : 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 : 220444617 : c_parser_skip_until_found (c_parser *parser,
1319 : : enum cpp_ttype type,
1320 : : const char *msgid,
1321 : : location_t matching_location)
1322 : : {
1323 : 220444617 : unsigned nesting_depth = 0;
1324 : :
1325 : 220444617 : if (c_parser_require (parser, type, msgid, matching_location))
1326 : : {
1327 : 220443735 : 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 : 220443735 : return;
1339 : : }
1340 : :
1341 : : /* Skip tokens until the desired token is found. */
1342 : 5860 : while (true)
1343 : : {
1344 : : /* Peek at the next token. */
1345 : 3371 : c_token *token = c_parser_peek_token (parser);
1346 : : /* If we've reached the token we want, consume it and stop. */
1347 : 3371 : if (token->type == type && !nesting_depth)
1348 : : {
1349 : 679 : c_parser_consume_token (parser);
1350 : 679 : 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 : 2692 : if (token->type == CPP_EOF)
1367 : : return;
1368 : 2673 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1369 : : return;
1370 : 2607 : if (token->type == CPP_OPEN_BRACE
1371 : : || token->type == CPP_OPEN_PAREN
1372 : : || token->type == CPP_OPEN_SQUARE)
1373 : 288 : ++nesting_depth;
1374 : : else if (token->type == CPP_CLOSE_BRACE
1375 : : || token->type == CPP_CLOSE_PAREN
1376 : : || token->type == CPP_CLOSE_SQUARE)
1377 : : {
1378 : 406 : if (nesting_depth-- == 0)
1379 : : break;
1380 : : }
1381 : : /* Consume this token. */
1382 : 2489 : c_parser_consume_token (parser);
1383 : 2489 : }
1384 : 797 : 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 : 99 : c_parser_skip_to_end_of_parameter (c_parser *parser)
1392 : : {
1393 : 99 : unsigned nesting_depth = 0;
1394 : :
1395 : 511 : while (true)
1396 : : {
1397 : 305 : c_token *token = c_parser_peek_token (parser);
1398 : 305 : if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1399 : 26 : && !nesting_depth)
1400 : : break;
1401 : : /* If we've run out of tokens, stop. */
1402 : 279 : if (token->type == CPP_EOF)
1403 : : return;
1404 : 279 : if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1405 : : return;
1406 : 279 : 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 : 76 : if (nesting_depth-- == 0)
1415 : : break;
1416 : : }
1417 : : /* Consume this token. */
1418 : 206 : c_parser_consume_token (parser);
1419 : 206 : }
1420 : 99 : 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 : 1950595 : c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1473 : : {
1474 : 1950595 : gcc_assert (parser->in_pragma);
1475 : 1950595 : parser->in_pragma = false;
1476 : :
1477 : 1950595 : 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 : 1951885 : cpp_ttype token_type;
1481 : 1951885 : do
1482 : : {
1483 : 1951885 : c_token *token = c_parser_peek_token (parser);
1484 : 1951885 : token_type = token->type;
1485 : 1951885 : if (token_type == CPP_EOF)
1486 : : break;
1487 : 1951885 : c_parser_consume_token (parser);
1488 : : }
1489 : 1951885 : while (token_type != CPP_PRAGMA_EOL);
1490 : :
1491 : 1950595 : 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 : 1950595 : parser->error = false;
1504 : 1950595 : }
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 : 492 : c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
1511 : : bool metadirective_p = false)
1512 : : {
1513 : 492 : unsigned nesting_depth = 0;
1514 : 492 : int bracket_depth = 0;
1515 : 492 : bool save_error = parser->error;
1516 : :
1517 : 1813 : while (true)
1518 : : {
1519 : 1813 : c_token *token;
1520 : :
1521 : : /* Peek at the next token. */
1522 : 1813 : token = c_parser_peek_token (parser);
1523 : :
1524 : 1813 : 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 : 429 : case CPP_SEMICOLON:
1535 : : /* If the next token is a ';', we have reached the
1536 : : end of the statement. */
1537 : 429 : 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 : 111 : 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 : 62 : if ((nesting_depth == 0 || --nesting_depth == 0)
1549 : 173 : && (!metadirective_p || bracket_depth <= 0))
1550 : : {
1551 : 111 : c_parser_consume_token (parser);
1552 : 111 : goto finished;
1553 : : }
1554 : : break;
1555 : :
1556 : 62 : 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 : 62 : ++nesting_depth;
1560 : 62 : break;
1561 : :
1562 : 68 : 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 : 68 : if (metadirective_p && nesting_depth == 0)
1567 : 2 : ++bracket_depth;
1568 : : break;
1569 : :
1570 : 94 : case CPP_CLOSE_PAREN:
1571 : 94 : 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 : 1314 : c_parser_consume_token (parser);
1592 : : }
1593 : :
1594 : 474 : finished:
1595 : 474 : 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 : 959659 : disable_extension_diagnostics (void)
1605 : : {
1606 : 1919318 : int ret = (pedantic
1607 : 959659 : | (warn_pointer_arith << 1)
1608 : 959659 : | (warn_traditional << 2)
1609 : 959659 : | (flag_iso << 3)
1610 : 959659 : | (warn_long_long << 4)
1611 : 959659 : | (warn_cxx_compat << 5)
1612 : 959659 : | (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 : 959659 : | ((warn_c90_c99_compat == 1) << 7)
1616 : 959659 : | ((warn_c90_c99_compat == -1) << 8)
1617 : : /* Similarly for warn_c99_c11_compat. */
1618 : 959659 : | ((warn_c99_c11_compat == 1) << 9)
1619 : 959659 : | ((warn_c99_c11_compat == -1) << 10)
1620 : : /* Similarly for warn_c11_c23_compat. */
1621 : 959659 : | ((warn_c11_c23_compat == 1) << 11)
1622 : 959659 : | ((warn_c11_c23_compat == -1) << 12)
1623 : : /* Similarly for warn_c23_c2y_compat. */
1624 : 959659 : | ((warn_c23_c2y_compat == 1) << 13)
1625 : 959659 : | ((warn_c23_c2y_compat == -1) << 14)
1626 : : );
1627 : 959659 : cpp_opts->cpp_pedantic = pedantic = 0;
1628 : 959659 : warn_pointer_arith = 0;
1629 : 959659 : cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1630 : 959659 : flag_iso = 0;
1631 : 959659 : cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1632 : 959659 : warn_cxx_compat = 0;
1633 : 959659 : warn_overlength_strings = 0;
1634 : 959659 : warn_c90_c99_compat = 0;
1635 : 959659 : warn_c99_c11_compat = 0;
1636 : 959659 : warn_c11_c23_compat = 0;
1637 : 959659 : warn_c23_c2y_compat = 0;
1638 : 959659 : 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 : 959659 : restore_extension_diagnostics (int flags)
1646 : : {
1647 : 959659 : cpp_opts->cpp_pedantic = pedantic = flags & 1;
1648 : 959659 : warn_pointer_arith = (flags >> 1) & 1;
1649 : 959659 : cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1650 : 959659 : flag_iso = (flags >> 3) & 1;
1651 : 959659 : cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1652 : 959659 : warn_cxx_compat = (flags >> 5) & 1;
1653 : 959659 : warn_overlength_strings = (flags >> 6) & 1;
1654 : : /* See above for why is this needed. */
1655 : 959659 : warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1656 : 959659 : warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1657 : 959659 : warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1658 : 959659 : warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
1659 : 959659 : }
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 : 7115 : tree lookup_constant_by_id (tree id) const final override
1887 : : {
1888 : : /* Consider decls. */
1889 : 7115 : 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 : 7073 : cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1897 : 7073 : 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 : 107157 : c_parser_translation_unit (c_parser *parser)
1996 : : {
1997 : 107157 : if (c_parser_next_token_is (parser, CPP_EOF))
1998 : : {
1999 : 1278 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2000 : : "ISO C forbids an empty translation unit");
2001 : : }
2002 : : else
2003 : : {
2004 : 105879 : void *obstack_position = obstack_alloc (&parser_obstack, 0);
2005 : 105879 : mark_valid_location_for_stdc_pragma (false);
2006 : 57025389 : do
2007 : : {
2008 : 57025389 : ggc_collect ();
2009 : 57025389 : c_parser_external_declaration (parser);
2010 : 57025384 : obstack_free (&parser_obstack, obstack_position);
2011 : : }
2012 : 57025384 : while (c_parser_next_token_is_not (parser, CPP_EOF));
2013 : : }
2014 : :
2015 : : unsigned int i;
2016 : : tree decl;
2017 : 107162 : 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 : 107067 : 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 : 107067 : 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 : 107067 : if (flag_analyzer)
2042 : : {
2043 : 1423 : ana::c_translation_unit tu;
2044 : 1423 : ana::on_finish_translation_unit (tu);
2045 : : }
2046 : : #endif
2047 : 107067 : }
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 : 57469752 : c_parser_external_declaration (c_parser *parser)
2075 : : {
2076 : 57469752 : int ext;
2077 : 57469752 : switch (c_parser_peek_token (parser)->type)
2078 : : {
2079 : 55628932 : case CPP_KEYWORD:
2080 : 55628932 : switch (c_parser_peek_token (parser)->keyword)
2081 : : {
2082 : 444363 : case RID_EXTENSION:
2083 : 444363 : ext = disable_extension_diagnostics ();
2084 : 444363 : c_parser_consume_token (parser);
2085 : 444363 : c_parser_external_declaration (parser);
2086 : 444363 : restore_extension_diagnostics (ext);
2087 : 444363 : 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 : 55184397 : default:
2126 : 55184397 : goto decl_or_fndef;
2127 : : }
2128 : : break;
2129 : 2130 : case CPP_SEMICOLON:
2130 : 2130 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2131 : : "ISO C does not allow extra %<;%> outside of a function");
2132 : 2130 : c_parser_consume_token (parser);
2133 : 2130 : break;
2134 : 1617018 : case CPP_PRAGMA:
2135 : 1617018 : mark_valid_location_for_stdc_pragma (true);
2136 : 1617018 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2137 : 1617018 : mark_valid_location_for_stdc_pragma (false);
2138 : 1617018 : 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 : 55406069 : 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 : 55406069 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
2156 : : false);
2157 : 55406069 : break;
2158 : : }
2159 : 57469747 : }
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 : 104636470 : add_debug_begin_stmt (location_t loc)
2170 : : {
2171 : : /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2172 : 104636470 : if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2173 : 101909714 : return;
2174 : :
2175 : 2726756 : tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2176 : 2726756 : SET_EXPR_LOCATION (stmt, loc);
2177 : 2726756 : 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 : 36984255 : c_parser_maybe_reclassify_token (c_parser *parser)
2226 : : {
2227 : 36984255 : if (c_parser_next_token_is (parser, CPP_NAME))
2228 : : {
2229 : 199988 : c_token *token = c_parser_peek_token (parser);
2230 : :
2231 : 199988 : if (token->id_kind != C_ID_CLASSNAME)
2232 : : {
2233 : 199988 : tree decl = lookup_name (token->value);
2234 : :
2235 : 199988 : token->id_kind = C_ID_ID;
2236 : 199988 : if (decl)
2237 : : {
2238 : 197047 : if (TREE_CODE (decl) == TYPE_DECL)
2239 : 2164 : token->id_kind = C_ID_TYPENAME;
2240 : : }
2241 : 2941 : 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 : 36984255 : }
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 : 62917449 : 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 : 62917449 : struct c_declspecs *specs;
2372 : 62917449 : tree prefix_attrs;
2373 : 62917449 : tree all_prefix_attrs;
2374 : 62917449 : bool diagnosed_no_specs = false;
2375 : 62917449 : location_t here = c_parser_peek_token (parser)->location;
2376 : 62917449 : tree result = NULL_TREE;
2377 : :
2378 : 62917449 : add_debug_begin_stmt (c_parser_peek_token (parser)->location);
2379 : :
2380 : 62917449 : if (static_assert_ok
2381 : 125821552 : && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
2382 : : {
2383 : 1839 : c_parser_static_assert_declaration (parser);
2384 : 1839 : return result;
2385 : : }
2386 : 62915610 : specs = build_null_declspecs ();
2387 : :
2388 : : /* Handle any standard attributes parsed in the caller. */
2389 : 62915610 : if (have_attrs)
2390 : : {
2391 : 143 : declspecs_add_attrs (here, specs, attrs);
2392 : 143 : 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 : 62915610 : if (c_parser_peek_token (parser)->type == CPP_NAME
2397 : 5766434 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
2398 : 9295 : && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2399 : 9185 : || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2400 : 62915744 : && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2401 : : {
2402 : 132 : 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 : 132 : gcc_rich_location richloc (here);
2409 : 132 : 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 : 129 : 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 : 126 : 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 : 123 : auto_diagnostic_group d;
2437 : 123 : name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2438 : 123 : here);
2439 : 123 : 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 : 111 : error_at (here, "unknown type name %qE", name);
2448 : 123 : }
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 : 132 : c_parser_peek_token (parser)->type = CPP_KEYWORD;
2454 : 132 : c_parser_peek_token (parser)->keyword = RID_VOID;
2455 : 132 : c_parser_peek_token (parser)->value = error_mark_node;
2456 : 132 : fndef_ok = !nested;
2457 : 132 : }
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 : 62915610 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
2463 : 528 : have_attrs = true;
2464 : :
2465 : 62915610 : c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2466 : : true, true, start_attr_ok, true, cla_nonabstract_decl);
2467 : 62915610 : if (parser->error)
2468 : : {
2469 : 33 : c_parser_skip_to_end_of_block_or_statement (parser);
2470 : 33 : return result;
2471 : : }
2472 : 62915577 : 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 : 62915514 : finish_declspecs (specs);
2480 : 62915514 : bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2481 : 62915514 : bool std_auto_type_p = specs->c23_auto_p;
2482 : 62915514 : bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2483 : 62915514 : gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2484 : 62915514 : const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2485 : 62915514 : 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 : 358 : 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 : 62915514 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
2513 : : {
2514 : 492190 : bool handled_assume = false;
2515 : 492190 : if (specs->attrs
2516 : 498 : && !nested
2517 : 121 : && specs->typespec_kind == ctsk_none
2518 : 492293 : && 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 : 492108 : if (specs->typespec_kind == ctsk_none
2532 : 492108 : && 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 : 492108 : if (any_auto_type_p)
2539 : 6 : error_at (here, "%qs in empty declaration", auto_type_keyword);
2540 : 492102 : else if (specs->typespec_kind == ctsk_none
2541 : 492102 : && attribute_fallthrough_p (specs->attrs))
2542 : : {
2543 : 328 : if (fallthru_attr_p != NULL)
2544 : 327 : *fallthru_attr_p = true;
2545 : 328 : if (nested)
2546 : : {
2547 : 327 : tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2548 : : void_type_node, 0);
2549 : 327 : add_stmt (fn);
2550 : : }
2551 : : else
2552 : 1 : pedwarn (here, OPT_Wattributes,
2553 : : "%<fallthrough%> attribute at top level");
2554 : : }
2555 : 491774 : else if (empty_ok
2556 : 491757 : && !(have_attrs && specs->non_std_attrs_seen_p)
2557 : 491754 : && !handled_assume)
2558 : 491716 : 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 : 492108 : if (specs->expr)
2567 : 106 : add_stmt (fold_convert (void_type_node, specs->expr));
2568 : 492108 : c_parser_consume_token (parser);
2569 : 492108 : if (oacc_routine_data)
2570 : 0 : c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2571 : 492108 : return result;
2572 : : }
2573 : 62423324 : 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 : 62423405 : && 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 : 62423312 : if (empty_ok
2603 : 62410180 : && specs->typespec_kind == ctsk_tagdef
2604 : 762352 : && c_parser_next_token_starts_declspecs (parser)
2605 : 62423342 : && !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 : 62423303 : 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 : 62423303 : else if (attribute_fallthrough_p (specs->attrs))
2690 : 5 : warning_at (here, OPT_Wattributes,
2691 : : "%<fallthrough%> attribute not followed by %<;%>");
2692 : 62423298 : else if (lookup_attribute ("gnu", "assume", specs->attrs))
2693 : 2 : warning_at (here, OPT_Wattributes,
2694 : : "%<assume%> attribute not followed by %<;%>");
2695 : :
2696 : 124846601 : auto_vec<c_token> omp_declare_simd_attr_clauses;
2697 : 62423303 : c_parser_handle_directive_omp_attributes (specs->attrs,
2698 : : omp_declare_simd_clauses,
2699 : : &omp_declare_simd_attr_clauses);
2700 : 62423303 : pending_xref_error ();
2701 : 62423303 : prefix_attrs = specs->attrs;
2702 : 62423303 : all_prefix_attrs = prefix_attrs;
2703 : 62423303 : specs->attrs = NULL_TREE;
2704 : 62423303 : bool more_than_one_decl = false;
2705 : 63261921 : while (true)
2706 : : {
2707 : 62842612 : struct c_declarator *declarator;
2708 : 62842612 : bool dummy = false;
2709 : 62842612 : timevar_id_t tv;
2710 : 62842612 : tree fnbody = NULL_TREE;
2711 : 62842612 : tree underspec_name = NULL_TREE;
2712 : 62842612 : 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 : 125685224 : declarator = c_parser_declarator (parser,
2718 : 62842612 : specs->typespec_kind != ctsk_none,
2719 : : C_DTR_NORMAL, &dummy);
2720 : 62842612 : if (declarator == NULL)
2721 : : {
2722 : 216 : if (omp_declare_simd_clauses)
2723 : 1 : c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2724 : : omp_declare_simd_clauses);
2725 : 216 : 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 : 216 : if (!simple_ok)
2729 : 196 : c_parser_skip_to_end_of_block_or_statement (parser);
2730 : 216 : return result;
2731 : : }
2732 : 62842396 : if (flag_openmp || flag_openmp_simd)
2733 : : {
2734 : : struct c_declarator *d = declarator;
2735 : 835320 : while (d->kind != cdk_id)
2736 : 362271 : d = d->declarator;
2737 : 473049 : vec<c_token> *dummy = NULL;
2738 : 473049 : c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2739 : : &omp_dsimd_idattr_clauses);
2740 : : }
2741 : 62842396 : 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 : 62842395 : 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 : 62842313 : else if (specs->constexpr_p)
2765 : : {
2766 : : struct c_declarator *d = declarator;
2767 : 420 : while (d->kind != cdk_id)
2768 : 77 : d = d->declarator;
2769 : 343 : underspec_name = d->u.id.id;
2770 : : }
2771 : 62842394 : if (c_parser_next_token_is (parser, CPP_EQ)
2772 : 56646818 : || c_parser_next_token_is (parser, CPP_COMMA)
2773 : 56343691 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
2774 : 48418976 : || c_parser_next_token_is_keyword (parser, RID_ASM)
2775 : 47562424 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
2776 : 98225095 : || c_parser_next_token_is_keyword (parser, RID_IN))
2777 : : {
2778 : 27459693 : tree asm_name = NULL_TREE;
2779 : 27459693 : tree postfix_attrs = NULL_TREE;
2780 : 27459693 : 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 : 27459693 : fndef_ok = false;
2788 : 27459693 : if (c_parser_next_token_is_keyword (parser, RID_ASM))
2789 : 856552 : asm_name = c_parser_simple_asm_expr (parser);
2790 : 27459693 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
2791 : : {
2792 : 12990265 : postfix_attrs = c_parser_gnu_attributes (parser);
2793 : 12990265 : 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 : 27459692 : if (c_parser_next_token_is (parser, CPP_EQ))
2805 : : {
2806 : 6197007 : tree d;
2807 : 6197007 : struct c_expr init;
2808 : 6197007 : location_t init_loc;
2809 : 6197007 : c_parser_consume_token (parser);
2810 : 6197007 : 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 : sanitize_code_type 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 : 6195099 : init_loc = c_parser_peek_token (parser)->location;
2891 : 6195099 : rich_location richloc (line_table, init_loc);
2892 : 6195099 : unsigned int underspec_state = 0;
2893 : 6195099 : if (specs->constexpr_p)
2894 : 339 : underspec_state =
2895 : 339 : start_underspecified_init (init_loc, underspec_name);
2896 : 6195099 : d = start_decl (declarator, specs, true,
2897 : : chainon (postfix_attrs,
2898 : : all_prefix_attrs),
2899 : 6195099 : !specs->constexpr_p);
2900 : 6195099 : if (!d)
2901 : 4 : d = error_mark_node;
2902 : 6195099 : 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 : 6195099 : if (!specs->constexpr_p
2906 : 6195099 : && !omp_dsimd_idattr_clauses.is_empty ())
2907 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2908 : : &omp_dsimd_idattr_clauses);
2909 : 6195099 : start_init (d, asm_name,
2910 : 6018449 : TREE_STATIC (d) || specs->constexpr_p,
2911 : 6195099 : specs->constexpr_p, &richloc);
2912 : : /* A parameter is initialized, which is invalid. Don't
2913 : : attempt to instrument the initializer. */
2914 : 6195099 : sanitize_code_type flag_sanitize_save = flag_sanitize;
2915 : 6195099 : if (TREE_CODE (d) == PARM_DECL)
2916 : 35 : flag_sanitize = 0;
2917 : 6195099 : init = c_parser_initializer (parser, d);
2918 : 6195097 : flag_sanitize = flag_sanitize_save;
2919 : 6195097 : if (specs->constexpr_p)
2920 : : {
2921 : 339 : finish_underspecified_init (underspec_name,
2922 : : underspec_state);
2923 : 339 : d = pushdecl (d);
2924 : 339 : if (omp_declare_simd_clauses)
2925 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2926 : : omp_declare_simd_clauses);
2927 : 339 : if (!specs->constexpr_p
2928 : 339 : && !omp_dsimd_idattr_clauses.is_empty ())
2929 : 0 : c_finish_omp_declare_simd (parser, d, NULL_TREE,
2930 : : &omp_dsimd_idattr_clauses);
2931 : : }
2932 : 6195097 : finish_init ();
2933 : 6195097 : }
2934 : 6197005 : if (oacc_routine_data)
2935 : 0 : c_finish_oacc_routine (oacc_routine_data, d, false);
2936 : 6197005 : if (d != error_mark_node)
2937 : : {
2938 : 6196989 : maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
2939 : 6196989 : finish_decl (d, init_loc, init.value,
2940 : : init.original_type, asm_name);
2941 : 6196989 : result = d;
2942 : : }
2943 : : }
2944 : : else
2945 : : {
2946 : 21262685 : 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 : 21262681 : location_t lastloc = UNKNOWN_LOCATION;
2956 : 21262681 : tree attrs = chainon (postfix_attrs, all_prefix_attrs);
2957 : 21262681 : tree d = start_decl (declarator, specs, false, attrs, true,
2958 : : &lastloc);
2959 : 21262680 : 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 : 29279230 : while (decl)
2967 : 29279230 : switch (decl->kind)
2968 : : {
2969 : 14813512 : case cdk_array:
2970 : 14813512 : case cdk_function:
2971 : 14813512 : case cdk_pointer:
2972 : 14813512 : last_non_id_attrs = decl;
2973 : 14813512 : decl = decl->declarator;
2974 : 14813512 : 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 : 14465607 : if (last_non_id_attrs
2991 : 13856973 : && last_non_id_attrs->kind == cdk_function)
2992 : : {
2993 : 13856973 : tree parms = last_non_id_attrs->u.arg_info->parms;
2994 : 13856973 : if (DECL_ARGUMENTS (d) == NULL_TREE
2995 : 13856973 : && DECL_INITIAL (d) == NULL_TREE)
2996 : 13408660 : DECL_ARGUMENTS (d) = parms;
2997 : :
2998 : 13856973 : warn_parm_array_mismatch (lastloc, d, parms);
2999 : : }
3000 : : }
3001 : 21262680 : if (omp_declare_simd_clauses
3002 : 21262680 : || !omp_dsimd_idattr_clauses.is_empty ())
3003 : : {
3004 : 480 : tree parms = NULL_TREE;
3005 : 480 : if (d && TREE_CODE (d) == FUNCTION_DECL)
3006 : : {
3007 : : struct c_declarator *ce = declarator;
3008 : 469 : while (ce != NULL)
3009 : 469 : if (ce->kind == cdk_function)
3010 : : {
3011 : 466 : parms = ce->u.arg_info->parms;
3012 : 466 : break;
3013 : : }
3014 : : else
3015 : 3 : ce = ce->declarator;
3016 : : }
3017 : 466 : if (parms)
3018 : 240 : temp_store_parm_decls (d, parms);
3019 : 480 : if (omp_declare_simd_clauses)
3020 : 460 : c_finish_omp_declare_simd (parser, d, parms,
3021 : : omp_declare_simd_clauses);
3022 : 480 : if (!specs->constexpr_p
3023 : 480 : && !omp_dsimd_idattr_clauses.is_empty ())
3024 : 22 : c_finish_omp_declare_simd (parser, d, parms,
3025 : : &omp_dsimd_idattr_clauses);
3026 : 480 : if (parms)
3027 : 240 : temp_pop_parm_decls ();
3028 : : }
3029 : 21262680 : if (oacc_routine_data)
3030 : 72 : c_finish_oacc_routine (oacc_routine_data, d, false);
3031 : 21262680 : if (d)
3032 : 21262673 : finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
3033 : : NULL_TREE, asm_name);
3034 : :
3035 : 21262680 : 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 : 27459685 : if (c_parser_next_token_is (parser, CPP_COMMA))
3044 : : {
3045 : 419312 : more_than_one_decl = true;
3046 : 419312 : 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 : 419309 : c_parser_consume_token (parser);
3055 : 419309 : 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 : 419309 : continue;
3061 : : }
3062 : 27040373 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
3063 : : {
3064 : 27040233 : if (!simple_ok)
3065 : 27040134 : c_parser_consume_token (parser);
3066 : 27040233 : 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 : 35382701 : 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 : 35382697 : 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 : 35382641 : if (nested)
3113 : : {
3114 : 1531 : pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
3115 : 1531 : c_push_function_context ();
3116 : : }
3117 : 35382641 : 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 : 35382603 : if (DECL_DECLARED_INLINE_P (current_function_decl))
3156 : : tv = TV_PARSE_INLINE;
3157 : : else
3158 : 677333 : tv = TV_PARSE_FUNC;
3159 : 35382603 : 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 : 35382603 : int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
3174 : 35382603 : debug_nonbind_markers_p = 0;
3175 : 35382603 : c_parser_maybe_reclassify_token (parser);
3176 : 35382603 : while (c_parser_next_token_is_not (parser, CPP_EOF)
3177 : 70791144 : && 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 : 35382603 : debug_nonbind_markers_p = save_debug_nonbind_markers_p;
3181 : 35382603 : store_parm_decls ();
3182 : 35382603 : if (omp_declare_simd_clauses)
3183 : 288 : c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3184 : : omp_declare_simd_clauses);
3185 : 35382603 : 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 : 35382603 : if (oacc_routine_data)
3189 : 130 : c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
3190 : 35382603 : location_t startloc = c_parser_peek_token (parser)->location;
3191 : 35382603 : DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
3192 : 35382603 : = startloc;
3193 : 35382603 : location_t endloc = startloc;
3194 : :
3195 : : /* If the definition was marked with __RTL, use the RTL parser now,
3196 : : consuming the function body. */
3197 : 35382603 : 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 : 35382578 : else if (specs->declspec_il != cdil_none)
3214 : : {
3215 : 244 : bool saved = in_late_binary_op;
3216 : 244 : in_late_binary_op = true;
3217 : 244 : c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3218 : 244 : specs->declspec_il,
3219 : : specs->entry_bb_count);
3220 : 244 : in_late_binary_op = saved;
3221 : : }
3222 : : else
3223 : 35382334 : fnbody = c_parser_compound_statement (parser, &endloc);
3224 : 35382577 : tree fndecl = current_function_decl;
3225 : 35382577 : 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 : 35381047 : if (fnbody)
3241 : 35380803 : add_stmt (fnbody);
3242 : 35381047 : finish_function (endloc);
3243 : : }
3244 : : /* Get rid of the empty stmt list for GIMPLE/RTL. */
3245 : 35382577 : if (specs->declspec_il != cdil_none)
3246 : 244 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
3247 : :
3248 : 35382577 : break;
3249 : 27459992 : }
3250 : :
3251 : 35382615 : 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 : 1839 : c_parser_static_assert_declaration (c_parser *parser)
3340 : : {
3341 : 1839 : c_parser_static_assert_declaration_no_semi (parser);
3342 : 1839 : if (parser->error
3343 : 1839 : || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
3344 : 8 : c_parser_skip_to_end_of_block_or_statement (parser);
3345 : 1839 : }
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 : 1849 : c_parser_static_assert_declaration_no_semi (c_parser *parser)
3360 : : {
3361 : 1849 : location_t assert_loc, value_loc;
3362 : 1849 : tree value;
3363 : 1849 : tree string = NULL_TREE;
3364 : :
3365 : 1849 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3366 : 1849 : tree spelling = c_parser_peek_token (parser)->value;
3367 : 1849 : assert_loc = c_parser_peek_token (parser)->location;
3368 : 1849 : if (flag_isoc99)
3369 : 1846 : 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 : 1849 : c_parser_consume_token (parser);
3375 : 1849 : matching_parens parens;
3376 : 1849 : if (!parens.require_open (parser))
3377 : 12 : return;
3378 : 1848 : location_t value_tok_loc = c_parser_peek_token (parser)->location;
3379 : 1848 : value = convert_lvalue_to_rvalue (value_tok_loc,
3380 : : c_parser_expr_no_commas (parser, NULL),
3381 : : true, true).value;
3382 : 1848 : value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3383 : 1848 : if (c_parser_next_token_is (parser, CPP_COMMA))
3384 : : {
3385 : 1474 : c_parser_consume_token (parser);
3386 : 1474 : switch (c_parser_peek_token (parser)->type)
3387 : : {
3388 : 1471 : case CPP_STRING:
3389 : 1471 : case CPP_STRING16:
3390 : 1471 : case CPP_STRING32:
3391 : 1471 : case CPP_WSTRING:
3392 : 1471 : case CPP_UTF8STRING:
3393 : 1471 : string = c_parser_string_literal (parser, false, true).value;
3394 : 1471 : 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 : 1845 : parens.require_close (parser);
3408 : :
3409 : 1845 : 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 : 1842 : 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 : 1842 : 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 : 1837 : constant_expression_warning (value);
3429 : 1837 : 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 : 325642454 : 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 : 325642454 : bool attrs_ok = start_attr_ok;
3564 : 325642454 : bool seen_type = specs->typespec_kind != ctsk_none;
3565 : :
3566 : 325642454 : if (!typespec_ok)
3567 : 19037825 : gcc_assert (la == cla_prefer_id);
3568 : :
3569 : 325642454 : if (start_std_attr_ok
3570 : 325642454 : && c_parser_nth_token_starts_std_attributes (parser, 1))
3571 : : {
3572 : 563 : gcc_assert (!specs->non_std_attrs_seen_p);
3573 : 563 : location_t loc = c_parser_peek_token (parser)->location;
3574 : 563 : tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3575 : 563 : declspecs_add_attrs (loc, specs, attrs);
3576 : 563 : specs->non_std_attrs_seen_p = false;
3577 : : }
3578 : :
3579 : 789010485 : while (c_parser_next_token_is (parser, CPP_NAME)
3580 : 366161605 : || c_parser_next_token_is (parser, CPP_KEYWORD)
3581 : 931375772 : || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
3582 : : {
3583 : 646645198 : struct c_typespec t;
3584 : 646645198 : tree attrs;
3585 : 646645198 : tree align;
3586 : 646645198 : 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 : 630848264 : if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3593 : 16708391 : && c_parser_next_tokens_start_typename (parser, la)
3594 : 3772806 : && !c_parser_next_token_is_qualifier (parser)
3595 : 646645269 : && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS))
3596 : : break;
3597 : :
3598 : 646645136 : if (c_parser_next_token_is (parser, CPP_NAME))
3599 : : {
3600 : 422848830 : c_token *name_token = c_parser_peek_token (parser);
3601 : 422848830 : tree value = name_token->value;
3602 : 422848830 : c_id_kind kind = name_token->id_kind;
3603 : :
3604 : 422848830 : 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 : 239574807 : continue;
3612 : 174 : }
3613 : :
3614 : 422848656 : 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 : 422848656 : 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 : 239574633 : c_parser_consume_token (parser);
3626 : 239574633 : seen_type = true;
3627 : 239574633 : attrs_ok = true;
3628 : 239574633 : 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 : 239574582 : else if (kind == C_ID_TYPENAME
3647 : 239574582 : && (!c_dialect_objc ()
3648 : 0 : || c_parser_next_token_is_not (parser, CPP_LESS)))
3649 : : {
3650 : 239574582 : t.kind = ctsk_typedef;
3651 : : /* For a typedef name, record the meaning, not the name.
3652 : : In case of 'foo foo, bar;'. */
3653 : 239574582 : 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 : 239574633 : t.expr = NULL_TREE;
3665 : 239574633 : t.expr_const_operands = true;
3666 : 239574633 : t.has_enum_type_specifier = false;
3667 : 239574633 : declspecs_add_type (name_token->location, specs, t);
3668 : 239574633 : continue;
3669 : 239574633 : }
3670 : 223796306 : 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 : 223796306 : gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3688 : 223796306 : switch (c_parser_peek_token (parser)->keyword)
3689 : : {
3690 : 88232225 : case RID_STATIC:
3691 : 88232225 : case RID_EXTERN:
3692 : 88232225 : case RID_REGISTER:
3693 : 88232225 : case RID_TYPEDEF:
3694 : 88232225 : case RID_INLINE:
3695 : 88232225 : case RID_NORETURN:
3696 : 88232225 : case RID_AUTO:
3697 : 88232225 : case RID_THREAD:
3698 : 88232225 : case RID_CONSTEXPR:
3699 : 88232225 : if (!scspec_ok)
3700 : 3082 : goto out;
3701 : 88232092 : 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 : 88232092 : declspecs_add_scspec (loc, specs,
3706 : 88232092 : c_parser_peek_token (parser)->value);
3707 : 88232092 : c_parser_consume_token (parser);
3708 : 88232092 : break;
3709 : 1839 : case RID_AUTO_TYPE:
3710 : 1839 : if (!auto_type_ok)
3711 : 0 : goto out;
3712 : : /* Fall through. */
3713 : 81032799 : case RID_UNSIGNED:
3714 : 81032799 : case RID_LONG:
3715 : 81032799 : case RID_SHORT:
3716 : 81032799 : case RID_SIGNED:
3717 : 81032799 : case RID_COMPLEX:
3718 : 81032799 : case RID_INT:
3719 : 81032799 : case RID_CHAR:
3720 : 81032799 : case RID_FLOAT:
3721 : 81032799 : case RID_DOUBLE:
3722 : 81032799 : case RID_VOID:
3723 : 81032799 : case RID_DFLOAT32:
3724 : 81032799 : case RID_DFLOAT64:
3725 : 81032799 : case RID_DFLOAT128:
3726 : 81032799 : case RID_DFLOAT64X:
3727 : 81032799 : CASE_RID_FLOATN_NX:
3728 : 81032799 : case RID_BOOL:
3729 : 81032799 : case RID_FRACT:
3730 : 81032799 : case RID_ACCUM:
3731 : 81032799 : case RID_SAT:
3732 : 81032799 : case RID_INT_N_0:
3733 : 81032799 : case RID_INT_N_1:
3734 : 81032799 : case RID_INT_N_2:
3735 : 81032799 : case RID_INT_N_3:
3736 : 81032799 : if (!typespec_ok)
3737 : 0 : goto out;
3738 : 81032799 : attrs_ok = true;
3739 : 81032799 : seen_type = true;
3740 : 81032799 : if (c_dialect_objc ())
3741 : 0 : parser->objc_need_raw_identifier = true;
3742 : 81032799 : t.kind = ctsk_resword;
3743 : 81032799 : t.spec = c_parser_peek_token (parser)->value;
3744 : 81032799 : t.expr = NULL_TREE;
3745 : 81032799 : t.expr_const_operands = true;
3746 : 81032799 : t.has_enum_type_specifier = false;
3747 : 81032799 : declspecs_add_type (loc, specs, t);
3748 : 81032799 : c_parser_consume_token (parser);
3749 : 81032799 : break;
3750 : 231979 : case RID_ENUM:
3751 : 231979 : if (!typespec_ok)
3752 : 0 : goto out;
3753 : 231979 : attrs_ok = true;
3754 : 231979 : seen_type = true;
3755 : 231979 : t = c_parser_enum_specifier (parser);
3756 : 231979 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3757 : 231979 : declspecs_add_type (loc, specs, t);
3758 : 231979 : break;
3759 : 2163701 : case RID_STRUCT:
3760 : 2163701 : case RID_UNION:
3761 : 2163701 : if (!typespec_ok)
3762 : 0 : goto out;
3763 : 2163701 : attrs_ok = true;
3764 : 2163701 : seen_type = true;
3765 : 2163701 : t = c_parser_struct_or_union_specifier (parser);
3766 : 2163701 : invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
3767 : 2163701 : declspecs_add_type (loc, specs, t);
3768 : 2163701 : break;
3769 : 806332 : case RID_TYPEOF:
3770 : 806332 : 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 : 806332 : if (!typespec_ok || seen_type)
3775 : 2 : goto out;
3776 : 806330 : attrs_ok = true;
3777 : 806330 : seen_type = true;
3778 : 806330 : t = c_parser_typeof_specifier (parser);
3779 : 806330 : declspecs_add_type (loc, specs, t);
3780 : 806330 : break;
3781 : 45550 : case RID_BITINT:
3782 : 45550 : if (!typespec_ok)
3783 : 0 : goto out;
3784 : : else
3785 : : {
3786 : 45550 : attrs_ok = true;
3787 : 45550 : seen_type = true;
3788 : 45550 : t.kind = ctsk_resword;
3789 : 45550 : t.spec = c_parser_peek_token (parser)->value;
3790 : 45550 : t.expr = error_mark_node;
3791 : 45550 : t.expr_const_operands = true;
3792 : 45550 : t.has_enum_type_specifier = false;
3793 : 45550 : c_parser_consume_token (parser);
3794 : 45550 : matching_parens parens;
3795 : 45550 : if (parens.require_open (parser))
3796 : : {
3797 : 45550 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
3798 : 45550 : t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3799 : 45550 : true).value;
3800 : 45550 : parens.skip_until_found_close (parser);
3801 : : }
3802 : 45550 : declspecs_add_type (loc, specs, t);
3803 : : }
3804 : 45550 : break;
3805 : 32365 : 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 : 32365 : if (c_dialect_objc ())
3814 : 0 : sorry ("%<_Atomic%> in Objective-C");
3815 : 32365 : if (flag_isoc99)
3816 : 32314 : 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 : 32365 : attrs_ok = true;
3822 : 32365 : tree value;
3823 : 32365 : value = c_parser_peek_token (parser)->value;
3824 : 32365 : c_parser_consume_token (parser);
3825 : 64527 : 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 : 18935 : declspecs_add_qual (loc, specs, value);
3856 : : break;
3857 : 16240126 : case RID_CONST:
3858 : 16240126 : case RID_VOLATILE:
3859 : 16240126 : case RID_RESTRICT:
3860 : 16240126 : attrs_ok = true;
3861 : 16240126 : declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3862 : 16240126 : c_parser_consume_token (parser);
3863 : 16240126 : break;
3864 : 35007812 : case RID_ATTRIBUTE:
3865 : 35007812 : if (!attrs_ok)
3866 : 0 : goto out;
3867 : 35007812 : attrs = c_parser_gnu_attributes (parser);
3868 : 35007812 : declspecs_add_attrs (loc, specs, attrs);
3869 : 35007812 : 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 : 245 : case RID_GIMPLE:
3877 : 245 : if (! flag_gimple)
3878 : 0 : error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
3879 : 245 : c_parser_consume_token (parser);
3880 : 245 : specs->declspec_il = cdil_gimple;
3881 : 245 : specs->locations[cdw_gimple] = loc;
3882 : 245 : c_parser_gimple_or_rtl_pass_list (parser, specs);
3883 : 245 : 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 : 2931 : default:
3891 : 2931 : goto out;
3892 : : }
3893 : : }
3894 : 325642454 : out:
3895 : 325642454 : if (end_std_attr_ok
3896 : 325642454 : && c_parser_nth_token_starts_std_attributes (parser, 1))
3897 : 115 : specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
3898 : 325642454 : }
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 : 231979 : c_parser_enum_specifier (c_parser *parser)
3979 : : {
3980 : 231979 : struct c_typespec ret;
3981 : 231979 : bool have_std_attrs;
3982 : 231979 : bool potential_nesting_p = false;
3983 : 231979 : tree std_attrs = NULL_TREE;
3984 : 231979 : tree attrs;
3985 : 231979 : tree ident = NULL_TREE;
3986 : 231979 : tree fixed_underlying_type = NULL_TREE;
3987 : 231979 : location_t enum_loc;
3988 : 231979 : location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3989 : 231979 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
3990 : 231979 : c_parser_consume_token (parser);
3991 : 231979 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3992 : 231979 : if (have_std_attrs)
3993 : 14 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3994 : 231979 : attrs = c_parser_gnu_attributes (parser);
3995 : 231979 : enum_loc = c_parser_peek_token (parser)->location;
3996 : : /* Set the location in case we create a decl now. */
3997 : 231979 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
3998 : 231979 : if (c_parser_next_token_is (parser, CPP_NAME))
3999 : : {
4000 : 126543 : ident = c_parser_peek_token (parser)->value;
4001 : 126543 : ident_loc = c_parser_peek_token (parser)->location;
4002 : 126543 : enum_loc = ident_loc;
4003 : 126543 : c_parser_consume_token (parser);
4004 : : }
4005 : 231979 : 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 : 231979 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
4009 : : {
4010 : 168 : pedwarn_c11 (enum_loc, OPT_Wpedantic,
4011 : : "ISO C does not support specifying %<enum%> underlying "
4012 : : "types before C23");
4013 : 168 : if (ident)
4014 : : {
4015 : : /* The tag is in scope during the enum-type-specifier (which
4016 : : may refer to the tag inside typeof). */
4017 : 164 : ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
4018 : : have_std_attrs, std_attrs, true);
4019 : 164 : 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 : 164 : 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 : 168 : c_parser_consume_token (parser);
4038 : 168 : struct c_declspecs *specs = build_null_declspecs ();
4039 : 168 : c_parser_declspecs (parser, specs, false, true, false, false, false,
4040 : : false, true, cla_prefer_id);
4041 : 168 : finish_declspecs (specs);
4042 : 168 : if (specs->default_int_p)
4043 : 1 : error_at (enum_loc, "no %<enum%> underlying type specified");
4044 : 167 : else if (TREE_CODE (specs->type) != INTEGER_TYPE
4045 : 167 : && 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 : 158 : else if (specs->restrict_p)
4051 : 1 : error_at (enum_loc, "invalid use of %<restrict%>");
4052 : 168 : fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
4053 : 168 : 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 : 164 : if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4059 : 164 : && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
4060 : : {
4061 : 429 : TYPE_MIN_VALUE (ret.spec) =
4062 : 143 : TYPE_MIN_VALUE (fixed_underlying_type);
4063 : 429 : TYPE_MAX_VALUE (ret.spec) =
4064 : 143 : TYPE_MAX_VALUE (fixed_underlying_type);
4065 : 143 : TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
4066 : 143 : SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
4067 : 143 : TYPE_SIZE (ret.spec) = NULL_TREE;
4068 : 143 : TYPE_PRECISION (ret.spec) =
4069 : 143 : TYPE_PRECISION (fixed_underlying_type);
4070 : 143 : ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
4071 : 143 : 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 : 231979 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
4084 : : {
4085 : : /* Parse an enum definition. */
4086 : 175176 : struct c_enum_contents the_enum;
4087 : 175176 : tree type;
4088 : 175176 : tree postfix_attrs;
4089 : : /* We chain the enumerators in reverse order, then put them in
4090 : : forward order at the end. */
4091 : 175176 : tree values;
4092 : 175176 : timevar_push (TV_PARSE_ENUM);
4093 : 175176 : type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
4094 : : potential_nesting_p);
4095 : 175176 : values = NULL_TREE;
4096 : 175176 : c_parser_consume_token (parser);
4097 : 5562312 : while (true)
4098 : : {
4099 : 5562312 : tree enum_id;
4100 : 5562312 : tree enum_value;
4101 : 5562312 : tree enum_decl;
4102 : 5562312 : bool seen_comma;
4103 : 5562312 : c_token *token;
4104 : 5562312 : location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4105 : 5562312 : location_t decl_loc, value_loc;
4106 : 5562312 : 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 : 5562301 : token = c_parser_peek_token (parser);
4114 : 5562301 : enum_id = token->value;
4115 : : /* Set the location in case we create a decl now. */
4116 : 5562301 : c_parser_set_source_position_from_token (token);
4117 : 5562301 : decl_loc = value_loc = token->location;
4118 : 5562301 : c_parser_consume_token (parser);
4119 : : /* Parse any specified attributes. */
4120 : 5562301 : tree std_attrs = NULL_TREE;
4121 : 5562301 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
4122 : 12 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4123 : 5562301 : tree enum_attrs = chainon (std_attrs,
4124 : : c_parser_gnu_attributes (parser));
4125 : 5562301 : if (c_parser_next_token_is (parser, CPP_EQ))
4126 : : {
4127 : 3436839 : c_parser_consume_token (parser);
4128 : 3436839 : value_loc = c_parser_peek_token (parser)->location;
4129 : 3436839 : 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 : 5562301 : enum_decl = build_enumerator (decl_loc, value_loc,
4137 : : &the_enum, enum_id, enum_value);
4138 : 5562301 : if (enum_attrs)
4139 : 20 : decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
4140 : 5562301 : TREE_CHAIN (enum_decl) = values;
4141 : 5562301 : values = enum_decl;
4142 : 5562301 : seen_comma = false;
4143 : 5562301 : if (c_parser_next_token_is (parser, CPP_COMMA))
4144 : : {
4145 : 5407346 : comma_loc = c_parser_peek_token (parser)->location;
4146 : 5407346 : seen_comma = true;
4147 : 5407346 : c_parser_consume_token (parser);
4148 : : }
4149 : 5562301 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4150 : : {
4151 : 175150 : if (seen_comma)
4152 : 20210 : pedwarn_c90 (comma_loc, OPT_Wpedantic,
4153 : : "comma at end of enumerator list");
4154 : 175150 : c_parser_consume_token (parser);
4155 : 175150 : break;
4156 : : }
4157 : 5387151 : 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 : 175176 : postfix_attrs = c_parser_gnu_attributes (parser);
4166 : 175176 : ret.spec = finish_enum (type, nreverse (values),
4167 : : chainon (std_attrs,
4168 : : chainon (attrs, postfix_attrs)));
4169 : 175176 : ret.kind = ctsk_tagdef;
4170 : 175176 : ret.expr = NULL_TREE;
4171 : 175176 : ret.expr_const_operands = true;
4172 : 175176 : ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
4173 : 175176 : timevar_pop (TV_PARSE_ENUM);
4174 : 175176 : return ret;
4175 : : }
4176 : 56803 : 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 : 56803 : if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
4191 : 1 : c_parser_error (parser, "expected %<;%>");
4192 : 56802 : if (fixed_underlying_type == NULL_TREE)
4193 : : {
4194 : 56753 : 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 : 56753 : 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 : 2163701 : c_parser_struct_or_union_specifier (c_parser *parser)
4250 : : {
4251 : 2163701 : struct c_typespec ret;
4252 : 2163701 : bool have_std_attrs;
4253 : 2163701 : tree std_attrs = NULL_TREE;
4254 : 2163701 : tree attrs;
4255 : 2163701 : tree ident = NULL_TREE;
4256 : 2163701 : location_t struct_loc;
4257 : 2163701 : location_t ident_loc = UNKNOWN_LOCATION;
4258 : 2163701 : enum tree_code code;
4259 : 2163701 : switch (c_parser_peek_token (parser)->keyword)
4260 : : {
4261 : : case RID_STRUCT:
4262 : : code = RECORD_TYPE;
4263 : : break;
4264 : 407547 : case RID_UNION:
4265 : 407547 : code = UNION_TYPE;
4266 : 407547 : break;
4267 : 0 : default:
4268 : 0 : gcc_unreachable ();
4269 : : }
4270 : 2163701 : struct_loc = c_parser_peek_token (parser)->location;
4271 : 2163701 : c_parser_consume_token (parser);
4272 : 2163701 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4273 : 2163701 : if (have_std_attrs)
4274 : 34 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4275 : 2163701 : attrs = c_parser_gnu_attributes (parser);
4276 : :
4277 : : /* Set the location in case we create a decl now. */
4278 : 2163701 : c_parser_set_source_position_from_token (c_parser_peek_token (parser));
4279 : :
4280 : 2163701 : if (c_parser_next_token_is (parser, CPP_NAME))
4281 : : {
4282 : 1486115 : ident = c_parser_peek_token (parser)->value;
4283 : 1486115 : ident_loc = c_parser_peek_token (parser)->location;
4284 : 1486115 : struct_loc = ident_loc;
4285 : 1486115 : c_parser_consume_token (parser);
4286 : : }
4287 : 2163701 : 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 : 1153934 : class c_struct_parse_info *struct_info;
4292 : 1153934 : tree type = start_struct (struct_loc, code, ident, &struct_info);
4293 : 1153934 : 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 : 1153934 : tree contents;
4305 : 1153934 : tree expr = NULL;
4306 : 1153934 : timevar_push (TV_PARSE_STRUCT);
4307 : 1153934 : contents = NULL_TREE;
4308 : 1153934 : c_parser_consume_token (parser);
4309 : : /* Handle the Objective-C @defs construct,
4310 : : e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4311 : 1153934 : 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 : 1153934 : end_at_defs:
4335 : : /* Parse the struct-declarations and semicolons. Problems with
4336 : : semicolons are diagnosed here; empty structures are diagnosed
4337 : : elsewhere. */
4338 : 5332491 : while (true)
4339 : : {
4340 : 5332491 : tree decls;
4341 : : /* Parse any stray semicolon. */
4342 : 5332491 : 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 : 5332478 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4355 : : {
4356 : 1153925 : c_parser_consume_token (parser);
4357 : 1153925 : break;
4358 : : }
4359 : : /* Accept #pragmas at struct scope. */
4360 : 4178553 : 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 : 4178533 : decls = c_parser_struct_declaration (parser, &expr);
4368 : 4178533 : 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 : 4178533 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
4373 : 4178497 : 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 : 1153934 : postfix_attrs = c_parser_gnu_attributes (parser);
4393 : 1153934 : ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4394 : : chainon (std_attrs,
4395 : : chainon (attrs, postfix_attrs)),
4396 : : struct_info, &expr);
4397 : 1153934 : ret.kind = ctsk_tagdef;
4398 : 1153934 : ret.expr = expr;
4399 : 1153934 : ret.expr_const_operands = true;
4400 : 1153934 : ret.has_enum_type_specifier = false;
4401 : 1153934 : timevar_pop (TV_PARSE_STRUCT);
4402 : 1153934 : return ret;
4403 : : }
4404 : 1009767 : 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 : 1009767 : 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 : 1009757 : ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4421 : : false);
4422 : 1009757 : 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 : 4242407 : c_parser_struct_declaration (c_parser *parser, tree *expr)
4461 : : {
4462 : 4242407 : struct c_declspecs *specs;
4463 : 4242407 : tree prefix_attrs;
4464 : 4242407 : tree all_prefix_attrs;
4465 : 4242407 : tree decls;
4466 : 4242407 : location_t decl_loc;
4467 : 4242407 : if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
4468 : : {
4469 : 63874 : int ext;
4470 : 63874 : tree decl;
4471 : 63874 : ext = disable_extension_diagnostics ();
4472 : 63874 : c_parser_consume_token (parser);
4473 : 63874 : decl = c_parser_struct_declaration (parser, expr);
4474 : 63874 : restore_extension_diagnostics (ext);
4475 : 63874 : return decl;
4476 : : }
4477 : 4178533 : 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 : 4178523 : specs = build_null_declspecs ();
4483 : 4178523 : 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 : 4178523 : c_parser_declspecs (parser, specs, false, true, true,
4490 : : true, false, true, true, cla_nonabstract_decl);
4491 : 4178523 : if (parser->error)
4492 : : return NULL_TREE;
4493 : 4178515 : if (!specs->declspecs_seen_p)
4494 : : {
4495 : 1 : c_parser_error (parser, "expected specifier-qualifier-list");
4496 : 1 : return NULL_TREE;
4497 : : }
4498 : 4178514 : finish_declspecs (specs);
4499 : 4178514 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4500 : 8346474 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
4501 : : {
4502 : 10558 : tree ret;
4503 : 10558 : 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 : 10555 : tree attrs = NULL;
4516 : :
4517 : 10555 : ret = grokfield (c_parser_peek_token (parser)->location,
4518 : : build_id_declarator (NULL_TREE), specs,
4519 : : NULL_TREE, &attrs, expr);
4520 : 10555 : if (ret)
4521 : 10526 : decl_attributes (&ret, attrs, 0);
4522 : : }
4523 : 10558 : 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 : 4167956 : if (specs->typespec_kind == ctsk_tagdef
4529 : 150017 : && TREE_CODE (specs->type) != ENUMERAL_TYPE
4530 : 149864 : && c_parser_next_token_starts_declspecs (parser)
4531 : 4167959 : && !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 : 4167954 : pending_xref_error ();
4539 : 4167954 : prefix_attrs = specs->attrs;
4540 : 4167954 : all_prefix_attrs = prefix_attrs;
4541 : 4167954 : specs->attrs = NULL_TREE;
4542 : 4167954 : decls = NULL_TREE;
4543 : 57311 : while (true)
4544 : : {
4545 : : /* Declaring one or more declarators or un-named bit-fields. */
4546 : 4225265 : struct c_declarator *declarator;
4547 : 4225265 : bool dummy = false;
4548 : 4225265 : if (c_parser_next_token_is (parser, CPP_COLON))
4549 : 9186 : declarator = build_id_declarator (NULL_TREE);
4550 : : else
4551 : 4216079 : declarator = c_parser_declarator (parser,
4552 : 4216079 : specs->typespec_kind != ctsk_none,
4553 : : C_DTR_NORMAL, &dummy);
4554 : 4225265 : if (declarator == NULL)
4555 : : {
4556 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
4557 : 1 : break;
4558 : : }
4559 : 4225264 : if (c_parser_next_token_is (parser, CPP_COLON)
4560 : 4173386 : || c_parser_next_token_is (parser, CPP_COMMA)
4561 : 4118273 : || c_parser_next_token_is (parser, CPP_SEMICOLON)
4562 : 32621 : || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
4563 : 4257865 : || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4564 : : {
4565 : 4225264 : tree postfix_attrs = NULL_TREE;
4566 : 4225264 : tree width = NULL_TREE;
4567 : 4225264 : tree d;
4568 : 4225264 : if (c_parser_next_token_is (parser, CPP_COLON))
4569 : : {
4570 : 51878 : c_parser_consume_token (parser);
4571 : 51878 : location_t loc = c_parser_peek_token (parser)->location;
4572 : 51878 : width = convert_lvalue_to_rvalue (loc,
4573 : : (c_parser_expr_no_commas
4574 : : (parser, NULL)),
4575 : : true, true).value;
4576 : : }
4577 : 4225264 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
4578 : 32782 : postfix_attrs = c_parser_gnu_attributes (parser);
4579 : 4225264 : d = grokfield (c_parser_peek_token (parser)->location,
4580 : : declarator, specs, width, &all_prefix_attrs, expr);
4581 : 4225264 : decl_attributes (&d, chainon (postfix_attrs,
4582 : : all_prefix_attrs), 0);
4583 : 4225264 : DECL_CHAIN (d) = decls;
4584 : 4225264 : decls = d;
4585 : 4225264 : 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 : 4225264 : all_prefix_attrs = prefix_attrs;
4590 : 4225264 : if (c_parser_next_token_is (parser, CPP_COMMA))
4591 : 57311 : c_parser_consume_token (parser);
4592 : 4167953 : else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
4593 : 4167973 : || 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 : 4167954 : 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 : 806330 : c_parser_typeof_specifier (c_parser *parser)
4626 : : {
4627 : 806330 : bool is_unqual;
4628 : 806330 : bool is_std;
4629 : 806330 : struct c_typespec ret;
4630 : 806330 : ret.kind = ctsk_typeof;
4631 : 806330 : ret.spec = error_mark_node;
4632 : 806330 : ret.expr = NULL_TREE;
4633 : 806330 : ret.expr_const_operands = true;
4634 : 806330 : ret.has_enum_type_specifier = false;
4635 : 806330 : if (c_parser_next_token_is_keyword (parser, RID_TYPEOF))
4636 : : {
4637 : 806238 : is_unqual = false;
4638 : 806238 : tree spelling = c_parser_peek_token (parser)->value;
4639 : 806238 : is_std = (flag_isoc23
4640 : 897350 : && 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 : 806330 : c_parser_consume_token (parser);
4650 : 806330 : c_inhibit_evaluation_warnings++;
4651 : 806330 : in_typeof++;
4652 : 806330 : matching_parens parens;
4653 : 806330 : if (!parens.require_open (parser))
4654 : : {
4655 : 0 : c_inhibit_evaluation_warnings--;
4656 : 0 : in_typeof--;
4657 : 0 : return ret;
4658 : : }
4659 : 806330 : 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 : 805645 : bool was_vm;
4673 : 805645 : location_t here = c_parser_peek_token (parser)->location;
4674 : 805645 : struct c_expr expr = c_parser_expression (parser);
4675 : 805645 : c_inhibit_evaluation_warnings--;
4676 : 805645 : in_typeof--;
4677 : 805645 : if (TREE_CODE (expr.value) == COMPONENT_REF
4678 : 805645 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4679 : 13 : error_at (here, "%<typeof%> applied to a bit-field");
4680 : 805645 : mark_exp_read (expr.value);
4681 : 805645 : ret.spec = TREE_TYPE (expr.value);
4682 : 805645 : 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 : 805645 : if (was_vm)
4686 : 215 : ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4687 : 805645 : pop_maybe_used (was_vm);
4688 : : }
4689 : 806330 : parens.skip_until_found_close (parser);
4690 : 806330 : if (ret.spec != error_mark_node)
4691 : : {
4692 : 806319 : 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 : 806319 : 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 : 324698419 : 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 : 324698419 : if (c_parser_next_token_is (parser, CPP_MULT))
4852 : : {
4853 : 17907299 : struct c_declspecs *quals_attrs = build_null_declspecs ();
4854 : 17907299 : struct c_declarator *inner;
4855 : 17907299 : c_parser_consume_token (parser);
4856 : 17907299 : c_parser_declspecs (parser, quals_attrs, false, false, true,
4857 : : false, false, true, false, cla_prefer_id);
4858 : 17907299 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4859 : 17907299 : if (inner == NULL)
4860 : : return NULL;
4861 : : else
4862 : 17907290 : 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 : 306791120 : 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 : 306791120 : 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 : 306791120 : if (kind != C_DTR_ABSTRACT
4912 : 188409143 : && c_parser_next_token_is (parser, CPP_NAME)
4913 : 490499639 : && ((type_seen_p
4914 : 183698660 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
4915 : 183652788 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
4916 : 183662647 : || c_parser_peek_token (parser)->id_kind == C_ID_ID))
4917 : : {
4918 : 183708519 : struct c_declarator *inner
4919 : 183708519 : = build_id_declarator (c_parser_peek_token (parser)->value);
4920 : 183708519 : *seen_id = true;
4921 : 183708519 : inner->id_loc = c_parser_peek_token (parser)->location;
4922 : 183708519 : c_parser_consume_token (parser);
4923 : 183708519 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
4924 : 84 : inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
4925 : 183708519 : return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4926 : : }
4927 : :
4928 : 123082601 : if (kind != C_DTR_NORMAL
4929 : 122942776 : && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
4930 : 123106431 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
4931 : : {
4932 : 23830 : struct c_declarator *inner = build_id_declarator (NULL_TREE);
4933 : 23830 : inner->id_loc = c_parser_peek_token (parser)->location;
4934 : 23830 : 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 : 123058771 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
4941 : : {
4942 : 222169 : tree attrs;
4943 : 222169 : struct c_declarator *inner;
4944 : 222169 : c_parser_consume_token (parser);
4945 : 222169 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4946 : : RID_ATTRIBUTE);
4947 : 222169 : attrs = c_parser_gnu_attributes (parser);
4948 : 222169 : if (kind != C_DTR_NORMAL
4949 : 222169 : && (c_parser_next_token_starts_declspecs (parser)
4950 : 82412 : || (!have_gnu_attrs
4951 : 82254 : && (c_parser_nth_token_starts_std_attributes (parser, 1)
4952 : 82254 : || c_parser_next_token_is (parser, CPP_ELLIPSIS)))
4953 : 82407 : || 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 : 222105 : inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4980 : 222105 : if (inner != NULL && attrs != NULL)
4981 : 179 : inner = build_attrs_declarator (attrs, inner);
4982 : 222105 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
4983 : : {
4984 : 222091 : c_parser_consume_token (parser);
4985 : 222091 : if (inner == NULL)
4986 : : return NULL;
4987 : : else
4988 : 222091 : 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 : 122836602 : if (kind == C_DTR_NORMAL)
5000 : : {
5001 : 93 : c_parser_error (parser, "expected identifier or %<(%>");
5002 : 93 : return NULL;
5003 : : }
5004 : : else
5005 : 122836509 : 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 : 234514316 : 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 : 234514316 : if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
5020 : 234514316 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5021 : : {
5022 : 1130415 : location_t brace_loc = c_parser_peek_token (parser)->location;
5023 : 1130415 : struct c_declarator *declarator;
5024 : 1130415 : struct c_declspecs *quals_attrs = build_null_declspecs ();
5025 : 1130415 : struct c_expr dimen;
5026 : 1130415 : dimen.value = NULL_TREE;
5027 : 1130415 : dimen.original_code = ERROR_MARK;
5028 : 1130415 : dimen.original_type = NULL_TREE;
5029 : 1130415 : c_parser_consume_token (parser);
5030 : 1130415 : c_parser_declspecs (parser, quals_attrs, false, false, true,
5031 : : false, false, false, false, cla_prefer_id);
5032 : :
5033 : 1130415 : location_t static_loc = UNKNOWN_LOCATION;
5034 : 1130415 : 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 : 1130415 : if (!quals_attrs->declspecs_seen_p)
5043 : 1129477 : 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 : 1130415 : const bool static_seen = (static_loc != UNKNOWN_LOCATION);
5048 : 1130415 : bool star_seen = false;
5049 : 1130415 : if (c_parser_next_token_is (parser, CPP_MULT)
5050 : 1130415 : && 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 : 1130265 : else if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5056 : 961927 : dimen = c_parser_expr_no_commas (parser, NULL);
5057 : :
5058 : 1130415 : 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 : 1130415 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
5075 : 1130400 : 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 : 1130400 : if (dimen.value)
5083 : 961915 : dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
5084 : 1130400 : declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
5085 : : static_seen, star_seen);
5086 : 1130400 : if (declarator == NULL)
5087 : : return NULL;
5088 : 1130396 : 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 : 1130396 : inner = set_array_declarator_inner (declarator, inner);
5096 : 1130396 : return c_parser_direct_declarator_inner (parser, id_present, inner);
5097 : : }
5098 : 233383901 : else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
5099 : : {
5100 : 49429525 : tree attrs;
5101 : 49429525 : struct c_arg_info *args;
5102 : 49429525 : c_parser_consume_token (parser);
5103 : 49429525 : bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5104 : : RID_ATTRIBUTE);
5105 : 49429525 : attrs = c_parser_gnu_attributes (parser);
5106 : 49429525 : args = c_parser_parms_declarator (parser, id_present, attrs,
5107 : : have_gnu_attrs);
5108 : 49429525 : if (args == NULL)
5109 : : return NULL;
5110 : : else
5111 : : {
5112 : 98086923 : if (!(args->types
5113 : 48657507 : && args->types != error_mark_node
5114 : 48657507 : && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5115 : 98078237 : && 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 : 49429416 : inner = build_function_declarator (args, inner);
5123 : 49429416 : 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 : 49429589 : c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
5139 : : bool have_gnu_attrs)
5140 : : {
5141 : 49429589 : push_scope ();
5142 : 49429589 : 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 : 49429589 : if (id_list_ok
5146 : 49429589 : && !attrs
5147 : 49417696 : && c_parser_next_token_is (parser, CPP_NAME)
5148 : 32952253 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
5149 : :
5150 : : /* Look ahead to detect typos in type names. */
5151 : 8698 : && 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 : 49438276 : && 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 : 49420903 : struct c_arg_info *ret
5193 : 49420903 : = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
5194 : 49420903 : pop_scope ();
5195 : 49420903 : 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 : 49420940 : c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
5209 : : bool have_gnu_attrs)
5210 : : {
5211 : 49420940 : 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 : 49420940 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5220 : : {
5221 : 771790 : struct c_arg_info *ret = build_arg_info ();
5222 : 771790 : c_parser_consume_token (parser);
5223 : 771790 : return ret;
5224 : : }
5225 : 48649150 : 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 : 121133016 : while (true)
5251 : : {
5252 : : /* Parse a parameter. */
5253 : 121133016 : struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
5254 : : have_gnu_attrs);
5255 : 121133016 : attrs = NULL_TREE;
5256 : 121133016 : have_gnu_attrs = false;
5257 : 121133016 : if (parm == NULL)
5258 : : bad_parm = true;
5259 : : else
5260 : 121132905 : push_parm_decl (parm, &expr);
5261 : 121133016 : 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 : 121132979 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5273 : : {
5274 : 48438455 : c_parser_consume_token (parser);
5275 : 48438455 : if (bad_parm)
5276 : : return NULL;
5277 : : else
5278 : 48438369 : return get_parm_info (false, expr);
5279 : : }
5280 : 72694524 : 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 : 72694516 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
5288 : : {
5289 : 210515 : c_parser_consume_token (parser);
5290 : 210515 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5291 : : {
5292 : 210508 : c_parser_consume_token (parser);
5293 : 210508 : if (bad_parm)
5294 : : return NULL;
5295 : : else
5296 : 210500 : 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 : 121133016 : c_parser_parameter_declaration (c_parser *parser, tree attrs,
5315 : : bool have_gnu_attrs)
5316 : : {
5317 : 121133016 : struct c_declspecs *specs;
5318 : 121133016 : struct c_declarator *declarator;
5319 : 121133016 : tree prefix_attrs;
5320 : 121133016 : tree postfix_attrs = NULL_TREE;
5321 : 121133016 : bool dummy = false;
5322 : :
5323 : : /* Accept #pragmas between parameter declarations. */
5324 : 121133018 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
5325 : 2 : c_parser_pragma (parser, pragma_param, NULL, NULL_TREE);
5326 : :
5327 : 121133016 : if (!c_parser_next_token_starts_declspecs (parser)
5328 : 121133016 : && !c_parser_nth_token_starts_std_attributes (parser, 1))
5329 : : {
5330 : 99 : c_token *token = c_parser_peek_token (parser);
5331 : 99 : if (parser->error)
5332 : : return NULL;
5333 : 99 : c_parser_set_source_position_from_token (token);
5334 : 99 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
5335 : : {
5336 : 81 : auto_diagnostic_group d;
5337 : 81 : name_hint hint = lookup_name_fuzzy (token->value,
5338 : : FUZZY_LOOKUP_TYPENAME,
5339 : 81 : token->location);
5340 : 81 : 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 : 51 : error_at (token->location, "unknown type name %qE", token->value);
5350 : 81 : parser->error = true;
5351 : 81 : }
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 : 99 : c_parser_skip_to_end_of_parameter (parser);
5358 : 99 : return NULL;
5359 : : }
5360 : :
5361 : 121132917 : location_t start_loc = c_parser_peek_token (parser)->location;
5362 : :
5363 : 121132917 : specs = build_null_declspecs ();
5364 : 121132917 : if (attrs)
5365 : : {
5366 : 338 : declspecs_add_attrs (input_location, specs, attrs);
5367 : 338 : attrs = NULL_TREE;
5368 : : }
5369 : 121132917 : c_parser_declspecs (parser, specs, true, true, true, true, false,
5370 : 121132917 : !have_gnu_attrs, true, cla_nonabstract_decl);
5371 : 121132917 : finish_declspecs (specs);
5372 : 121132917 : pending_xref_error ();
5373 : 121132917 : prefix_attrs = specs->attrs;
5374 : 121132917 : specs->attrs = NULL_TREE;
5375 : 242265834 : declarator = c_parser_declarator (parser,
5376 : 121132917 : specs->typespec_kind != ctsk_none,
5377 : : C_DTR_PARM, &dummy);
5378 : 121132917 : if (declarator == NULL)
5379 : : {
5380 : 12 : c_parser_skip_until_found (parser, CPP_COMMA, NULL);
5381 : 12 : return NULL;
5382 : : }
5383 : 121132905 : 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 : 121132905 : location_t end_loc = parser->last_token_location;
5400 : :
5401 : : /* Find any cdk_id declarator; determine if we have an identifier. */
5402 : 121132905 : c_declarator *id_declarator = declarator;
5403 : 133791620 : while (id_declarator && id_declarator->kind != cdk_id)
5404 : 12658715 : id_declarator = id_declarator->declarator;
5405 : 116648903 : location_t caret_loc = (id_declarator->u.id.id
5406 : 121132905 : ? id_declarator->id_loc
5407 : : : start_loc);
5408 : 121132905 : location_t param_loc = make_location (caret_loc, start_loc, end_loc);
5409 : :
5410 : 121132905 : return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5411 : 121132905 : 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 : 1928966 : c_parser_asm_string_literal (c_parser *parser)
5424 : : {
5425 : 1928966 : tree str;
5426 : 1928966 : int save_flag = warn_overlength_strings;
5427 : 1928966 : warn_overlength_strings = 0;
5428 : 1928966 : str = c_parser_string_literal (parser, false, false).value;
5429 : 1928966 : warn_overlength_strings = save_flag;
5430 : 1928966 : 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 : 856552 : c_parser_simple_asm_expr (c_parser *parser)
5443 : : {
5444 : 856552 : tree str;
5445 : 856552 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5446 : 856552 : c_parser_consume_token (parser);
5447 : 856552 : matching_parens parens;
5448 : 856552 : if (!parens.require_open (parser))
5449 : : return NULL_TREE;
5450 : 856552 : str = c_parser_asm_string_literal (parser);
5451 : 856552 : 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 : 132253711 : c_parser_gnu_attribute_any_word (c_parser *parser)
5461 : : {
5462 : 132253711 : tree attr_name = NULL_TREE;
5463 : :
5464 : 132253711 : if (c_parser_next_token_is (parser, CPP_KEYWORD))
5465 : : {
5466 : : /* ??? See comment above about what keywords are accepted here. */
5467 : 852655 : bool ok;
5468 : 852655 : 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 : 852655 : if (!ok)
5517 : : return NULL_TREE;
5518 : :
5519 : : /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5520 : 852655 : attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5521 : : }
5522 : 131401056 : else if (c_parser_next_token_is (parser, CPP_NAME))
5523 : 131401053 : 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 : 4460033 : c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5541 : : bool require_string, bool assume_attr,
5542 : : bool allow_empty_args)
5543 : : {
5544 : 4460033 : vec<tree, va_gc> *expr_list;
5545 : 4460033 : 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 : 4460033 : if (c_parser_next_token_is (parser, CPP_NAME)
5552 : 563286 : && (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 : 563285 : && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5557 : 38937 : || (c_parser_peek_2nd_token (parser)->type
5558 : : == CPP_CLOSE_PAREN))
5559 : 5023279 : && (takes_identifier
5560 : 142026 : || (c_dialect_objc ()
5561 : 0 : && !assume_attr
5562 : 0 : && c_parser_peek_token (parser)->id_kind
5563 : : == C_ID_CLASSNAME)))
5564 : : {
5565 : 421220 : tree arg1 = c_parser_peek_token (parser)->value;
5566 : 421220 : c_parser_consume_token (parser);
5567 : 421220 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5568 : 35215 : attr_args = build_tree_list (NULL_TREE, arg1);
5569 : : else
5570 : : {
5571 : 386005 : tree tree_list;
5572 : 386005 : c_parser_consume_token (parser);
5573 : 386005 : expr_list = c_parser_expr_list (parser, false, true,
5574 : : NULL, NULL, NULL, NULL);
5575 : 386005 : tree_list = build_tree_list_vec (expr_list);
5576 : 386005 : attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5577 : 386005 : release_tree_vector (expr_list);
5578 : : }
5579 : : }
5580 : : else
5581 : : {
5582 : 4038813 : 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 : 4038797 : 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 : 4038778 : 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 : 4038733 : expr_list = c_parser_expr_list (parser, false, true,
5618 : : NULL, NULL, NULL, NULL);
5619 : 4038733 : attr_args = build_tree_list_vec (expr_list);
5620 : 4038733 : release_tree_vector (expr_list);
5621 : : }
5622 : : }
5623 : 4460033 : 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 : 184146138 : c_parser_gnu_attribute (c_parser *parser, tree attrs,
5655 : : bool expect_comma = false, bool empty_ok = true)
5656 : : {
5657 : 184146138 : bool comma_first = c_parser_next_token_is (parser, CPP_COMMA);
5658 : 184146138 : if (!comma_first
5659 : 103785613 : && !c_parser_next_token_is (parser, CPP_NAME)
5660 : 236891113 : && !c_parser_next_token_is (parser, CPP_KEYWORD))
5661 : : return NULL_TREE;
5662 : :
5663 : 212614243 : while (c_parser_next_token_is (parser, CPP_COMMA))
5664 : : {
5665 : 80360532 : c_parser_consume_token (parser);
5666 : 80360532 : if (!empty_ok)
5667 : : return attrs;
5668 : : }
5669 : :
5670 : 132253711 : tree attr_name = c_parser_gnu_attribute_any_word (parser);
5671 : 132253711 : if (attr_name == NULL_TREE)
5672 : : return NULL_TREE;
5673 : :
5674 : 132253708 : attr_name = canonicalize_attr_name (attr_name);
5675 : 132253708 : c_parser_consume_token (parser);
5676 : :
5677 : 132253708 : tree attr;
5678 : 132253708 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
5679 : : {
5680 : 127793764 : 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 : 127793757 : attr = build_tree_list (attr_name, NULL_TREE);
5689 : : /* Add this attribute to the list. */
5690 : 127793757 : attrs = chainon (attrs, attr);
5691 : 127793757 : return attrs;
5692 : : }
5693 : 4459944 : c_parser_consume_token (parser);
5694 : :
5695 : 4459944 : tree attr_args
5696 : 4459944 : = c_parser_attribute_arguments (parser,
5697 : 4459944 : attribute_takes_identifier_p (attr_name),
5698 : : false,
5699 : 4459944 : is_attribute_p ("assume", attr_name),
5700 : : true);
5701 : :
5702 : 4459944 : attr = build_tree_list (attr_name, attr_args);
5703 : 4459944 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5704 : 4459942 : 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 : 4459942 : 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 : 4459942 : attrs = chainon (attrs, attr);
5723 : 4459942 : return attrs;
5724 : : }
5725 : :
5726 : : static tree
5727 : 107010351 : c_parser_gnu_attributes (c_parser *parser)
5728 : : {
5729 : 107010351 : tree attrs = NULL_TREE;
5730 : 158902777 : while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
5731 : : {
5732 : 51892436 : bool save_translate_strings_p = parser->translate_strings_p;
5733 : 51892436 : parser->translate_strings_p = false;
5734 : : /* Consume the `__attribute__' keyword. */
5735 : 51892436 : c_parser_consume_token (parser);
5736 : : /* Look for the two `(' tokens. */
5737 : 51892436 : 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 : 51892436 : 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 : 184145378 : tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5754 : 184145378 : if (attr == error_mark_node)
5755 : : return attrs;
5756 : 184145369 : if (!attr)
5757 : : break;
5758 : : attrs = attr;
5759 : : }
5760 : :
5761 : : /* Look for the two `)' tokens. */
5762 : 51892427 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5763 : 51892427 : 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 : 51892427 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
5772 : 51892426 : 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 : 51892426 : 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 : 1921 : c_parser_std_attribute (c_parser *parser, bool for_tm)
6021 : : {
6022 : 1921 : c_token *token = c_parser_peek_token (parser);
6023 : 1921 : tree ns, name, attribute;
6024 : :
6025 : : /* Parse the attribute-token. */
6026 : 1921 : 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 : 1919 : name = canonicalize_attr_name (token->value);
6032 : 1919 : c_parser_consume_token (parser);
6033 : 1919 : if (c_parser_next_token_is (parser, CPP_SCOPE)
6034 : 2381 : || (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 : 1467 : ns = name;
6039 : 1467 : if (c_parser_next_token_is (parser, CPP_COLON))
6040 : 10 : c_parser_consume_token (parser);
6041 : 1467 : c_parser_consume_token (parser);
6042 : 1467 : token = c_parser_peek_token (parser);
6043 : 1467 : 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 : 1467 : name = canonicalize_attr_name (token->value);
6049 : 1467 : c_parser_consume_token (parser);
6050 : : }
6051 : : else
6052 : : ns = NULL_TREE;
6053 : 1919 : attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
6054 : :
6055 : : /* Parse the arguments, if any. */
6056 : 1919 : const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
6057 : 1919 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
6058 : : {
6059 : 987 : if ((flag_openmp || flag_openmp_simd)
6060 : 9 : && ns
6061 : 7 : && is_attribute_p ("omp", ns)
6062 : 999 : && (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 : 993 : 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 : 1136 : out:
6141 : 1136 : 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 : 2035 : c_parser_std_attribute_list (c_parser *parser, bool for_tm)
6156 : : {
6157 : 2035 : tree attributes = NULL_TREE;
6158 : 2261 : while (true)
6159 : : {
6160 : 2261 : c_token *token = c_parser_peek_token (parser);
6161 : 2261 : if (token->type == CPP_CLOSE_SQUARE)
6162 : : break;
6163 : 2045 : if (token->type == CPP_COMMA)
6164 : : {
6165 : 124 : c_parser_consume_token (parser);
6166 : 124 : continue;
6167 : : }
6168 : 1921 : tree attribute = c_parser_std_attribute (parser, for_tm);
6169 : 1921 : if (attribute != error_mark_node)
6170 : : {
6171 : 1820 : TREE_CHAIN (attribute) = attributes;
6172 : 1820 : attributes = attribute;
6173 : : }
6174 : 1921 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
6175 : : break;
6176 : : }
6177 : 2035 : return attributes;
6178 : : }
6179 : :
6180 : : static tree
6181 : 2035 : c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
6182 : : {
6183 : 2035 : location_t loc = c_parser_peek_token (parser)->location;
6184 : 2035 : if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
6185 : : return NULL_TREE;
6186 : 2035 : 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 : 2035 : tree attributes;
6192 : 2035 : 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 : 1993 : if (!for_tm)
6202 : 1973 : pedwarn_c11 (loc, OPT_Wpedantic,
6203 : : "ISO C does not support %<[[]]%> attributes before C23");
6204 : 1993 : attributes = c_parser_std_attribute_list (parser, for_tm);
6205 : : }
6206 : 2035 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6207 : 2035 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
6208 : 2035 : 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 : 4372 : c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
6218 : : {
6219 : 20317 : while (true)
6220 : : {
6221 : 20317 : c_token *token = c_parser_peek_nth_token_raw (parser, *n);
6222 : 20317 : 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 : 12719 : default:
6279 : 12719 : ++*n;
6280 : 12719 : break;
6281 : : }
6282 : : }
6283 : : }
6284 : :
6285 : : /* Return whether standard attributes start with the Nth token. */
6286 : :
6287 : : static bool
6288 : 872080347 : c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
6289 : : {
6290 : 872080347 : if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
6291 : 2280101 : && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
6292 : 872077780 : return false;
6293 : : /* In C, '[[' must start attributes. In Objective-C, we need to
6294 : : check whether '[[' is matched by ']]'. */
6295 : 2567 : 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 : 1955 : c_parser_std_attribute_specifier_sequence (c_parser *parser)
6340 : : {
6341 : 1955 : tree attributes = NULL_TREE;
6342 : 2015 : do
6343 : : {
6344 : 2015 : tree attrs = c_parser_std_attribute_specifier (parser, false);
6345 : 2015 : attributes = chainon (attributes, attrs);
6346 : : }
6347 : 2015 : while (c_parser_nth_token_starts_std_attributes (parser, 1));
6348 : 1955 : 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 : 118376398 : c_parser_type_name (c_parser *parser, bool alignas_ok)
6361 : : {
6362 : 118376398 : struct c_declspecs *specs = build_null_declspecs ();
6363 : 118376398 : struct c_declarator *declarator;
6364 : 118376398 : struct c_type_name *ret;
6365 : 118376398 : bool dummy = false;
6366 : 118376398 : c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false,
6367 : : false, true, cla_prefer_type);
6368 : 118376398 : if (!specs->declspecs_seen_p)
6369 : : {
6370 : 4 : c_parser_error (parser, "expected specifier-qualifier-list");
6371 : 4 : return NULL;
6372 : : }
6373 : 118376394 : if (specs->type != error_mark_node)
6374 : : {
6375 : 118376377 : pending_xref_error ();
6376 : 118376377 : finish_declspecs (specs);
6377 : : }
6378 : 236752788 : declarator = c_parser_declarator (parser,
6379 : 118376394 : specs->typespec_kind != ctsk_none,
6380 : : C_DTR_ABSTRACT, &dummy);
6381 : 118376394 : if (declarator == NULL)
6382 : : return NULL;
6383 : 118376391 : ret = XOBNEW (&parser_obstack, struct c_type_name);
6384 : 118376391 : ret->specs = specs;
6385 : 118376391 : ret->declarator = declarator;
6386 : 118376391 : 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 : 6195154 : c_parser_initializer (c_parser *parser, tree decl)
6436 : : {
6437 : 6195154 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
6438 : 104215 : return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
6439 : : else
6440 : : {
6441 : 6090939 : struct c_expr ret;
6442 : 6090939 : location_t loc = c_parser_peek_token (parser)->location;
6443 : 6090939 : ret = c_parser_expr_no_commas (parser, NULL);
6444 : 6090937 : 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 : 6090937 : if (VAR_P (decl)
6455 : 6090889 : && !DECL_EXTERNAL (decl)
6456 : 6090889 : && !TREE_STATIC (decl)
6457 : 5971664 : && ret.value == decl
6458 : 6178157 : && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), OPT_Winit_self))
6459 : 87213 : suppress_warning (decl, OPT_Winit_self);
6460 : 6090937 : if (TREE_CODE (ret.value) != STRING_CST
6461 : 6090937 : && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6462 : 93258 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6463 : : (ret.value))))
6464 : 5983783 : ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6465 : 6090937 : 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 : 1341673 : c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6483 : : struct obstack *outer_obstack, tree decl)
6484 : : {
6485 : 1341673 : struct c_expr ret;
6486 : 1341673 : struct obstack braced_init_obstack;
6487 : 1341673 : location_t brace_loc = c_parser_peek_token (parser)->location;
6488 : 1341673 : gcc_obstack_init (&braced_init_obstack);
6489 : 1341673 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6490 : 1341673 : bool save_c_omp_array_section_p = c_omp_array_section_p;
6491 : 1341673 : c_omp_array_section_p = false;
6492 : 1341673 : bool zero_init_padding_bits = false;
6493 : 1341673 : matching_braces braces;
6494 : 1341673 : braces.consume_open (parser);
6495 : 1341673 : if (nested_p)
6496 : : {
6497 : 339376 : finish_implicit_inits (brace_loc, outer_obstack);
6498 : 339376 : push_init_level (brace_loc, 0, &braced_init_obstack);
6499 : : }
6500 : : else
6501 : 1002297 : really_start_incremental_init (type);
6502 : 1341673 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6503 : : {
6504 : 2470 : pedwarn_c11 (brace_loc, OPT_Wpedantic,
6505 : : "ISO C forbids empty initializer braces before C23");
6506 : 2470 : if (flag_isoc23)
6507 : 1341673 : zero_init_padding_bits = true;
6508 : : }
6509 : : else
6510 : : {
6511 : 1339203 : if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6512 : 52 : 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 : 8747353 : while (true)
6518 : : {
6519 : 8747353 : c_parser_initelt (parser, &braced_init_obstack);
6520 : 8747353 : if (parser->error)
6521 : : break;
6522 : 8747323 : if (c_parser_next_token_is (parser, CPP_COMMA))
6523 : : {
6524 : 7410809 : last_init_list_comma = c_parser_peek_token (parser)->location;
6525 : 7410809 : c_parser_consume_token (parser);
6526 : : /* CPP_EMBED should be always in between two CPP_COMMA
6527 : : tokens. */
6528 : 14821721 : 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 : 7410809 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
6549 : : break;
6550 : : }
6551 : : }
6552 : 1341673 : c_omp_array_section_p = save_c_omp_array_section_p;
6553 : 1341673 : c_token *next_tok = c_parser_peek_token (parser);
6554 : 1341673 : 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 : 1341642 : location_t close_loc = next_tok->location;
6565 : 1341642 : c_parser_consume_token (parser);
6566 : 1341642 : ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6567 : 1341642 : if (zero_init_padding_bits
6568 : 2213 : && ret.value
6569 : 2146 : && TREE_CODE (ret.value) == CONSTRUCTOR)
6570 : 2053 : CONSTRUCTOR_ZERO_PADDING_BITS (ret.value) = 1;
6571 : 1341642 : obstack_free (&braced_init_obstack, NULL);
6572 : 1341642 : set_c_expr_source_range (&ret, brace_loc, close_loc);
6573 : 1341642 : return ret;
6574 : : }
6575 : :
6576 : : /* Parse a nested initializer, including designators. */
6577 : :
6578 : : static void
6579 : 8747353 : 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 : 8747353 : if (c_parser_next_token_is (parser, CPP_NAME)
6585 : 8747353 : && 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 : 8780096 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
6606 : 17559049 : || c_parser_next_token_is (parser, CPP_DOT))
6607 : : {
6608 : 32899 : int des_prev = des_seen;
6609 : 32899 : if (!des_seen)
6610 : 32321 : des_loc = c_parser_peek_token (parser)->location;
6611 : 32899 : if (des_seen < 2)
6612 : 32399 : des_seen++;
6613 : 32899 : if (c_parser_next_token_is (parser, CPP_DOT))
6614 : : {
6615 : 31756 : des_seen = 2;
6616 : 31756 : c_parser_consume_token (parser);
6617 : 31756 : if (c_parser_next_token_is (parser, CPP_NAME))
6618 : : {
6619 : 31756 : set_init_label (des_loc, c_parser_peek_token (parser)->value,
6620 : 31756 : c_parser_peek_token (parser)->location,
6621 : : braced_init_obstack);
6622 : 31756 : 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 : 8747197 : if (des_seen >= 1)
6758 : : {
6759 : 32321 : if (c_parser_next_token_is (parser, CPP_EQ))
6760 : : {
6761 : 32300 : pedwarn_c90 (des_loc, OPT_Wpedantic,
6762 : : "ISO C90 forbids specifying subobject "
6763 : : "to initialize");
6764 : 32300 : 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 : 8747351 : 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 : 8747351 : c_parser_initval (c_parser *parser, struct c_expr *after,
6797 : : struct obstack * braced_init_obstack)
6798 : : {
6799 : 8747351 : struct c_expr init;
6800 : 8747351 : gcc_assert (!after || c_dialect_objc ());
6801 : 8747351 : location_t loc = c_parser_peek_token (parser)->location;
6802 : :
6803 : 8747351 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
6804 : 339376 : init = c_parser_braced_init (parser, NULL_TREE, true,
6805 : : braced_init_obstack, NULL_TREE);
6806 : : else
6807 : : {
6808 : 8407975 : init = c_parser_expr_no_commas (parser, after);
6809 : 8407975 : if (init.value != NULL_TREE
6810 : 8407975 : && TREE_CODE (init.value) != STRING_CST
6811 : 16774482 : && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6812 : 173 : || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6813 : : (init.value))))
6814 : 8366339 : init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6815 : : }
6816 : 8747351 : tree val = init.value;
6817 : 8747351 : 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 : 8747351 : static unsigned vals_to_ignore;
6822 : 8747351 : 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 : 8741329 : else if (val
6829 : 8741203 : && TREE_CODE (val) == INTEGER_CST
6830 : 4126793 : && TREE_TYPE (val) == integer_type_node
6831 : 12319615 : && c_parser_next_token_is (parser, CPP_COMMA))
6832 : 2932212 : if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
6833 : : {
6834 : 8527 : char buf1[64];
6835 : 8527 : unsigned int i;
6836 : 8527 : gcc_checking_assert (len >= 64);
6837 : : location_t last_loc = UNKNOWN_LOCATION;
6838 : 20245 : for (i = 0; i < 64; ++i)
6839 : : {
6840 : 20150 : c_token *tok = c_parser_peek_nth_token_raw (parser, 1 + 2 * i);
6841 : 20150 : if (tok->type != CPP_COMMA)
6842 : : break;
6843 : 19353 : tok = c_parser_peek_nth_token_raw (parser, 2 + 2 * i);
6844 : 19353 : if (tok->type != CPP_NUMBER
6845 : 11718 : || TREE_CODE (tok->value) != INTEGER_CST
6846 : 11718 : || TREE_TYPE (tok->value) != integer_type_node
6847 : 11718 : || wi::neg_p (wi::to_wide (tok->value))
6848 : 31071 : || wi::to_widest (tok->value) > UCHAR_MAX)
6849 : : break;
6850 : 11718 : buf1[i] = (char) tree_to_uhwi (tok->value);
6851 : 11718 : if (i == 0)
6852 : 1110 : loc = tok->location;
6853 : 11718 : last_loc = tok->location;
6854 : : }
6855 : 8527 : if (i < 64)
6856 : : {
6857 : 8432 : vals_to_ignore = i;
6858 : 8438 : return;
6859 : : }
6860 : 95 : 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 : 95 : if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
6866 : : len = i;
6867 : 93 : else if (tok->type != CPP_COMMA
6868 : 93 : || (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 : 89 : unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
6876 : 89 : unsigned int orig_len = len;
6877 : 89 : unsigned int off = 0, last = 0;
6878 : 89 : if (!wi::neg_p (wi::to_wide (val)) && wi::to_widest (val) <= UCHAR_MAX)
6879 : 81 : off = 1;
6880 : 89 : len = MIN (len, max_len - off);
6881 : 89 : char *buf2 = XNEWVEC (char, len + off);
6882 : 89 : if (off)
6883 : 81 : buf2[0] = (char) tree_to_uhwi (val);
6884 : 89 : memcpy (buf2 + off, buf1, i);
6885 : 5785 : for (unsigned int j = 0; j < i; ++j)
6886 : : {
6887 : 5696 : c_parser_peek_token (parser);
6888 : 5696 : c_parser_consume_token (parser);
6889 : 5696 : c_parser_peek_token (parser);
6890 : 5696 : c_parser_consume_token (parser);
6891 : : }
6892 : 19164 : for (; i < len; ++i)
6893 : : {
6894 : 19125 : if (!c_parser_next_token_is (parser, CPP_COMMA))
6895 : : break;
6896 : 19123 : tok = c_parser_peek_2nd_token (parser);
6897 : 19123 : if (tok->type != CPP_NUMBER
6898 : 19115 : || TREE_CODE (tok->value) != INTEGER_CST
6899 : 19115 : || TREE_TYPE (tok->value) != integer_type_node
6900 : 19115 : || wi::neg_p (wi::to_wide (tok->value))
6901 : 38238 : || wi::to_widest (tok->value) > UCHAR_MAX)
6902 : : break;
6903 : 19115 : c_token *tok2 = c_parser_peek_nth_token (parser, 3);
6904 : 19115 : if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
6905 : : break;
6906 : 19112 : 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 : 19112 : if (orig_len == INT_MAX
6913 : 19112 : && (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 : 19075 : last_loc = tok->location;
6921 : 19075 : c_parser_consume_token (parser);
6922 : 19075 : c_parser_consume_token (parser);
6923 : : }
6924 : 89 : val = make_node (RAW_DATA_CST);
6925 : 89 : TREE_TYPE (val) = integer_type_node;
6926 : 89 : RAW_DATA_LENGTH (val) = i;
6927 : 89 : tree owner = build_string (i + off + last, buf2);
6928 : 89 : XDELETEVEC (buf2);
6929 : 89 : TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
6930 : 89 : i + off + last);
6931 : 89 : RAW_DATA_OWNER (val) = owner;
6932 : 89 : RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
6933 : 89 : init.value = val;
6934 : 89 : set_c_expr_source_range (&init, loc, last_loc);
6935 : 89 : init.original_code = RAW_DATA_CST;
6936 : 89 : init.original_type = integer_type_node;
6937 : 89 : init.m_decimal = 0;
6938 : 89 : 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 : 36269219 : c_parser_compound_statement (c_parser *parser, location_t *endlocp)
7010 : : {
7011 : 36269219 : tree stmt;
7012 : 36269219 : location_t brace_loc;
7013 : 36269219 : brace_loc = c_parser_peek_token (parser)->location;
7014 : 36269219 : 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 : 36269203 : stmt = c_begin_compound_stmt (true);
7023 : 36269203 : location_t end_loc = c_parser_compound_statement_nostart (parser);
7024 : 36269202 : if (endlocp)
7025 : 35382317 : *endlocp = end_loc;
7026 : :
7027 : 36269202 : 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 : 870 : c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
7110 : : bool *have_std_attrs)
7111 : : {
7112 : 870 : 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 : 62896352 : c_parser_handle_directive_omp_attributes (tree &attrs,
7347 : : vec<c_token> *&pragma_clauses,
7348 : : vec<c_token> *attr_clauses)
7349 : : {
7350 : 62896352 : if (!flag_openmp && !flag_openmp_simd)
7351 : : return;
7352 : :
7353 : 1581674 : for (tree *pa = &attrs; *pa; )
7354 : 642311 : if (is_attribute_namespace_p ("omp", *pa)
7355 : 642311 : && 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 : 642174 : pa = &TREE_CHAIN (*pa);
7432 : 939363 : 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 : 971 : c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
7450 : : {
7451 : 971 : if (c_parser_next_token_is_keyword (parser, RID_RETURN))
7452 : : {
7453 : 224 : if (tree a = lookup_attribute ("gnu", "musttail", std_attrs))
7454 : : {
7455 : 416 : for (; a; a = lookup_attribute ("gnu", "musttail", TREE_CHAIN (a)))
7456 : 209 : if (TREE_VALUE (a))
7457 : 2 : error ("%qs attribute does not take any arguments",
7458 : : "musttail");
7459 : 207 : std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
7460 : 207 : attr.musttail_p = true;
7461 : : }
7462 : 224 : 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 : 971 : 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 : 86670080 : get_before_labels ()
7480 : : {
7481 : 86670080 : if (!building_stmt_list_p ())
7482 : 0 : return NULL_TREE;
7483 : 86670080 : tree_stmt_iterator tsi = tsi_last (cur_stmt_list);
7484 : 86670080 : if (tsi_end_p (tsi))
7485 : : return NULL_TREE;
7486 : 48022261 : 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 : 36303928 : c_parser_compound_statement_nostart (c_parser *parser)
7495 : : {
7496 : 36303928 : bool last_stmt = false;
7497 : 36303928 : bool last_label = false;
7498 : 36303928 : bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
7499 : 36303928 : location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
7500 : 36303928 : struct omp_for_parse_data *omp_for_parse_state
7501 : : = parser->omp_for_parse_state;
7502 : 72607856 : bool in_omp_loop_block
7503 : 36303928 : = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
7504 : 36303928 : tree sl = NULL_TREE;
7505 : 36303928 : attr_state a = {};
7506 : :
7507 : 36303928 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
7508 : : {
7509 : 23631 : location_t endloc = c_parser_peek_token (parser)->location;
7510 : 23631 : add_debug_begin_stmt (endloc);
7511 : 23631 : c_parser_consume_token (parser);
7512 : 23631 : 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 : 36280297 : if (in_omp_loop_block)
7518 : 172 : sl = push_stmt_list ();
7519 : :
7520 : 36280297 : mark_valid_location_for_stdc_pragma (true);
7521 : 36280297 : 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 : 36280297 : 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 : 36280297 : tree before_labels = get_before_labels ();
7566 : 121979041 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
7567 : : {
7568 : 49418506 : location_t loc = c_parser_peek_token (parser)->location;
7569 : 49418506 : loc = expansion_point_location_if_in_system_header (loc);
7570 : :
7571 : 98837012 : bool want_nested_loop = (omp_for_parse_state
7572 : 49418506 : ? 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 : 49418506 : 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 : 49418348 : bool have_std_attrs
7647 : 49418348 : = c_parser_nth_token_starts_std_attributes (parser, 1);
7648 : 49418348 : tree std_attrs = NULL_TREE;
7649 : 49418348 : if (have_std_attrs)
7650 : : {
7651 : 838 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7652 : 838 : std_attrs = c_parser_handle_musttail (parser, std_attrs, a);
7653 : : }
7654 : 49418348 : if (c_parser_next_token_is_keyword (parser, RID_CASE)
7655 : 48426871 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
7656 : 97812490 : || (c_parser_next_token_is (parser, CPP_NAME)
7657 : 9867855 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7658 : : {
7659 : 1047264 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
7660 : 991477 : label_loc = c_parser_peek_2nd_token (parser)->location;
7661 : : else
7662 : 55787 : label_loc = c_parser_peek_token (parser)->location;
7663 : 1047264 : last_label = true;
7664 : 1047264 : last_stmt = false;
7665 : 1047264 : mark_valid_location_for_stdc_pragma (false);
7666 : 1047264 : if (in_omp_loop_block)
7667 : 26 : check_omp_intervening_code (parser);
7668 : 1047264 : c_parser_label (parser, std_attrs);
7669 : : }
7670 : 48371084 : else if (c_parser_next_tokens_start_declaration (parser)
7671 : 48371084 : || (have_std_attrs
7672 : 703 : && !c_parser_handle_statement_omp_attributes
7673 : 703 : (parser, std_attrs, &have_std_attrs)
7674 : 269 : && c_parser_next_token_is (parser, CPP_SEMICOLON)
7675 : 77 : && (have_std_attrs = true)))
7676 : : {
7677 : 7472531 : 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 : 7472531 : 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 : 7472531 : mark_valid_location_for_stdc_pragma (false);
7689 : 7472531 : bool fallthru_attr_p = false;
7690 : 7472531 : 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 : 7472531 : if (in_omp_loop_block)
7696 : 19 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7697 : 7472531 : if (last_stmt && !fallthru_attr_p)
7698 : 301043 : pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7699 : : "ISO C90 forbids mixed declarations and code");
7700 : 7472531 : last_stmt = fallthru_attr_p;
7701 : 7472531 : last_label = false;
7702 : 7472531 : before_labels = get_before_labels ();
7703 : : }
7704 : 40898553 : 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 : 40897773 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
7750 : : {
7751 : 328390 : if (have_std_attrs && !parser->in_omp_attribute_pragma)
7752 : 0 : c_parser_error (parser, "expected declaration or statement");
7753 : 328390 : 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 : 328390 : if (omp_for_parse_state)
7761 : 9 : omp_for_parse_state->want_nested_loop = false;
7762 : 656700 : if (c_parser_pragma (parser,
7763 : : last_label ? pragma_stmt : pragma_compound,
7764 : : NULL, before_labels))
7765 : : {
7766 : 22634 : last_label = false;
7767 : 22634 : last_stmt = true;
7768 : 22634 : if (omp_for_parse_state)
7769 : 2 : check_omp_intervening_code (parser);
7770 : : }
7771 : 305758 : if (omp_for_parse_state)
7772 : 9 : omp_for_parse_state->want_nested_loop = want_nested_loop;
7773 : 328390 : before_labels = get_before_labels ();
7774 : : }
7775 : 40569383 : 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 : 40569327 : 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 : 40569322 : statement:
7800 : 40570028 : c_warn_unused_attributes (std_attrs);
7801 : 40570028 : last_label = false;
7802 : 40570028 : last_stmt = true;
7803 : 40570028 : mark_valid_location_for_stdc_pragma (false);
7804 : 40570028 : if (!omp_for_parse_state)
7805 : 40569799 : 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 : 40570027 : before_labels = get_before_labels ();
7820 : : }
7821 : :
7822 : 49418286 : parser->error = false;
7823 : : }
7824 : 36280238 : if (last_label)
7825 : 44 : pedwarn_c11 (label_loc, OPT_Wfree_labels,
7826 : : "label at end of compound statement");
7827 : 36280238 : location_t endloc = c_parser_peek_token (parser)->location;
7828 : 36280238 : c_parser_consume_token (parser);
7829 : :
7830 : : /* Restore the value we started with. */
7831 : 36280238 : 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 : 36280238 : 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 : 2018600 : c_parser_all_labels (c_parser *parser)
7854 : : {
7855 : 2018600 : attr_state attr = {};
7856 : 2018600 : bool have_std_attrs;
7857 : 2018600 : tree std_attrs = NULL;
7858 : 2018600 : if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1)))
7859 : : {
7860 : 109 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7861 : 109 : std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
7862 : : }
7863 : :
7864 : 2019553 : while (c_parser_next_token_is_keyword (parser, RID_CASE)
7865 : 2019067 : || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
7866 : 4038609 : || (c_parser_next_token_is (parser, CPP_NAME)
7867 : 494881 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7868 : : {
7869 : 953 : c_parser_label (parser, std_attrs);
7870 : 953 : std_attrs = NULL;
7871 : 953 : 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 : 2018600 : if (std_attrs
7879 : 2018600 : && (!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 : 2018674 : else if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
7887 : 1 : c_parser_error (parser, "expected statement");
7888 : 2018600 : 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 : 1048217 : c_parser_label (c_parser *parser, tree std_attrs)
7937 : : {
7938 : 1048217 : location_t loc1 = c_parser_peek_token (parser)->location;
7939 : 1048217 : tree label = NULL_TREE;
7940 : :
7941 : : /* Remember whether this case or a user-defined label is allowed to fall
7942 : : through to. */
7943 : 1048217 : bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
7944 : :
7945 : 1048217 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
7946 : : {
7947 : 991963 : tree exp1, exp2;
7948 : 991963 : c_parser_consume_token (parser);
7949 : 991963 : exp1 = convert_lvalue_to_rvalue (loc1,
7950 : : c_parser_expr_no_commas (parser, NULL),
7951 : : true, true).value;
7952 : 991963 : if (c_parser_next_token_is (parser, CPP_COLON))
7953 : : {
7954 : 991641 : c_parser_consume_token (parser);
7955 : 991641 : 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 : 56254 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
7971 : : {
7972 : 32740 : c_parser_consume_token (parser);
7973 : 32740 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
7974 : 32740 : label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
7975 : : }
7976 : : else
7977 : : {
7978 : 23514 : tree name = c_parser_peek_token (parser)->value;
7979 : 23514 : tree tlab;
7980 : 23514 : tree attrs;
7981 : 23514 : location_t loc2 = c_parser_peek_token (parser)->location;
7982 : 23514 : gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
7983 : 23514 : c_parser_consume_token (parser);
7984 : 23514 : gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
7985 : 23514 : c_parser_consume_token (parser);
7986 : 23514 : attrs = c_parser_gnu_attributes (parser);
7987 : 23514 : if (parser->omp_metadirective_state)
7988 : 8 : name = mangle_metadirective_region_label (parser, name);
7989 : 23514 : tlab = define_label (loc2, name);
7990 : 23514 : if (tlab)
7991 : : {
7992 : 23486 : decl_attributes (&tlab, attrs, 0);
7993 : 23486 : decl_attributes (&tlab, std_attrs, 0);
7994 : 23486 : label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
7995 : : }
7996 : 23514 : if (attrs
7997 : 23514 : && 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 : 1048217 : if (label)
8002 : : {
8003 : 1048037 : if (TREE_CODE (label) == LABEL_EXPR)
8004 : 23486 : FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
8005 : : else
8006 : 1024551 : FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
8007 : : }
8008 : 1048217 : }
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 : 518864 : c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
8158 : : {
8159 : 518864 : tree before_labels = get_before_labels ();
8160 : 518864 : attr_state a = c_parser_all_labels (parser);
8161 : 518864 : if (loc_after_labels)
8162 : 354138 : *loc_after_labels = c_parser_peek_token (parser)->location;
8163 : 518864 : parser->omp_attrs_forbidden_p = false;
8164 : 518864 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8165 : 518864 : }
8166 : :
8167 : : /* Parse and handle optional identifier after break or continue keywords. */
8168 : :
8169 : : static tree
8170 : 183506 : c_parser_bc_name (c_parser *parser, bool is_break)
8171 : : {
8172 : 183506 : 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 : 42139614 : c_parser_statement_after_labels (c_parser *parser, bool *if_p,
8194 : : tree before_labels,
8195 : : vec<tree> *chain, attr_state astate)
8196 : : {
8197 : 42139614 : location_t loc = c_parser_peek_token (parser)->location;
8198 : 42139614 : tree stmt = NULL_TREE;
8199 : 42139614 : bool in_if_block = parser->in_if_block;
8200 : 42139614 : parser->in_if_block = false;
8201 : 42139614 : if (if_p != NULL)
8202 : 801484 : *if_p = false;
8203 : :
8204 : 42139614 : if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
8205 : 41695390 : add_debug_begin_stmt (loc);
8206 : :
8207 : 444224 : restart:
8208 : 42139650 : switch (c_parser_peek_token (parser)->type)
8209 : : {
8210 : 444228 : case CPP_OPEN_BRACE:
8211 : 444228 : add_stmt (c_parser_compound_statement (parser));
8212 : 444228 : break;
8213 : 35936339 : case CPP_KEYWORD:
8214 : 35936339 : switch (c_parser_peek_token (parser)->keyword)
8215 : : {
8216 : 1247514 : case RID_IF:
8217 : 1247514 : c_parser_if_statement (parser, if_p, chain);
8218 : 1247514 : break;
8219 : 36632 : case RID_SWITCH:
8220 : 36632 : c_parser_switch_statement (parser, if_p, before_labels);
8221 : 36632 : break;
8222 : 43652 : case RID_WHILE:
8223 : 43652 : c_parser_while_statement (parser, false, 0, false, if_p, before_labels);
8224 : 43652 : break;
8225 : 144553 : case RID_DO:
8226 : 144553 : c_parser_do_statement (parser, false, 0, false, before_labels);
8227 : 144553 : break;
8228 : 270896 : case RID_FOR:
8229 : 270896 : c_parser_for_statement (parser, false, 0, false, if_p, before_labels);
8230 : 270896 : break;
8231 : 83439 : case RID_GOTO:
8232 : 83439 : c_parser_consume_token (parser);
8233 : 83439 : if (c_parser_next_token_is (parser, CPP_NAME))
8234 : : {
8235 : 82509 : tree name = c_parser_peek_token (parser)->value;
8236 : 82509 : if (parser->omp_metadirective_state)
8237 : 8 : name = mangle_metadirective_region_label (parser, name);
8238 : 82509 : stmt = c_finish_goto_label (loc, name);
8239 : 82509 : 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 : 83439 : goto expect_semicolon;
8253 : 12245 : case RID_CONTINUE:
8254 : 12245 : c_parser_consume_token (parser);
8255 : 12245 : stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false,
8256 : : c_parser_bc_name (parser, false));
8257 : 12245 : goto expect_semicolon;
8258 : 171261 : case RID_BREAK:
8259 : 171261 : c_parser_consume_token (parser);
8260 : 171261 : stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true,
8261 : : c_parser_bc_name (parser, true));
8262 : 171261 : goto expect_semicolon;
8263 : 33706804 : case RID_RETURN:
8264 : 33706804 : c_parser_consume_token (parser);
8265 : 33706804 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8266 : : {
8267 : 42014 : stmt = c_finish_return (loc, NULL_TREE, NULL_TREE,
8268 : 21007 : astate.musttail_p);
8269 : 21007 : c_parser_consume_token (parser);
8270 : : }
8271 : : else
8272 : : {
8273 : 33685797 : location_t xloc = c_parser_peek_token (parser)->location;
8274 : 33685797 : struct c_expr expr = c_parser_expression_conv (parser);
8275 : 33685797 : mark_exp_read (expr.value);
8276 : 34449493 : stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
8277 : : expr.value, expr.original_type,
8278 : 33685797 : astate.musttail_p);
8279 : 33685797 : goto expect_semicolon;
8280 : : }
8281 : 21007 : break;
8282 : 200948 : case RID_ASM:
8283 : 200948 : stmt = c_parser_asm_statement (parser);
8284 : 200948 : 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 : 18221 : default:
8383 : 18221 : goto expr_stmt;
8384 : : }
8385 : : break;
8386 : 199405 : case CPP_SEMICOLON:
8387 : 199405 : c_parser_consume_token (parser);
8388 : 199405 : 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 : 5575197 : default:
8403 : 5575197 : expr_stmt:
8404 : 5575197 : stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
8405 : 39527966 : expect_semicolon:
8406 : 39527966 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
8407 : 39527966 : 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 : 42139613 : if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
8420 : 2392894 : protected_set_expr_location (stmt, loc);
8421 : :
8422 : 42139613 : parser->in_if_block = in_if_block;
8423 : 42139613 : }
8424 : :
8425 : : /* Parse the condition from an if, do, while or for statements. */
8426 : :
8427 : : static tree
8428 : 459094 : c_parser_condition (c_parser *parser)
8429 : : {
8430 : 459094 : location_t loc = c_parser_peek_token (parser)->location;
8431 : 459094 : tree cond;
8432 : 459094 : cond = c_parser_expression_conv (parser).value;
8433 : 459094 : cond = c_objc_common_truthvalue_conversion (loc, cond);
8434 : 459094 : cond = c_fully_fold (cond, false, NULL);
8435 : 459094 : if (warn_sequence_point)
8436 : 81443 : verify_sequence_points (cond);
8437 : 459094 : 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 : 188279 : c_parser_paren_condition (c_parser *parser)
8448 : : {
8449 : 188279 : tree cond;
8450 : 188279 : matching_parens parens;
8451 : 188279 : if (!parens.require_open (parser))
8452 : 0 : return error_mark_node;
8453 : 188279 : cond = c_parser_condition (parser);
8454 : 188279 : parens.skip_until_found_close (parser);
8455 : 188279 : 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 : 1284138 : c_parser_selection_header (c_parser *parser, bool switch_p)
8474 : : {
8475 : 1284138 : location_t loc = c_parser_peek_token (parser)->location;
8476 : 1284138 : c_expr expr;
8477 : 1284138 : bool parse_expr = true;
8478 : 1284138 : tree std_attrs;
8479 : 1284138 : bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
8480 : 1284138 : if (have_std_attrs)
8481 : 20 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8482 : : else
8483 : : std_attrs = NULL_TREE;
8484 : 1284138 : 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 : 1283899 : 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 : 1283990 : expr = c_parser_expression_conv (parser);
8534 : 1284082 : if (!switch_p)
8535 : : {
8536 : 1247485 : expr.value = c_objc_common_truthvalue_conversion (loc, expr.value);
8537 : 1247485 : expr.value = c_fully_fold (expr.value, false, NULL);
8538 : 1247485 : if (warn_sequence_point)
8539 : 244349 : 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 : 1247514 : c_parser_paren_selection_header (c_parser *parser)
8551 : : {
8552 : 1247514 : matching_parens parens;
8553 : 1247514 : if (!parens.require_open (parser))
8554 : 1 : return error_mark_node;
8555 : 1247513 : tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value;
8556 : 1247513 : parens.skip_until_found_close (parser);
8557 : 1247513 : 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 : 509417 : c_parser_c99_block_statement (c_parser *parser, bool *if_p,
8568 : : location_t *loc_after_labels)
8569 : : {
8570 : 509417 : tree block = c_begin_compound_stmt (flag_isoc99);
8571 : 509417 : location_t loc = c_parser_peek_token (parser)->location;
8572 : 509417 : c_parser_statement (parser, if_p, loc_after_labels);
8573 : 509417 : 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 : 1247514 : c_parser_if_body (c_parser *parser, bool *if_p,
8590 : : const token_indent_info &if_tinfo)
8591 : : {
8592 : 1247514 : tree block = c_begin_compound_stmt (flag_isoc99);
8593 : 1247514 : location_t body_loc = c_parser_peek_token (parser)->location;
8594 : 1247514 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8595 : 1247514 : token_indent_info body_tinfo
8596 : 1247514 : = get_token_indent_info (c_parser_peek_token (parser));
8597 : 1247514 : tree before_labels = get_before_labels ();
8598 : 1247514 : attr_state a = c_parser_all_labels (parser);
8599 : :
8600 : 1247514 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
8601 : : {
8602 : 6642 : location_t loc = c_parser_peek_token (parser)->location;
8603 : 6642 : add_stmt (build_empty_stmt (loc));
8604 : 6642 : c_parser_consume_token (parser);
8605 : 6642 : 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 : 1240872 : else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8610 : 442399 : add_stmt (c_parser_compound_statement (parser));
8611 : : else
8612 : : {
8613 : 798473 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8614 : 798473 : c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8615 : : }
8616 : :
8617 : 1247514 : token_indent_info next_tinfo
8618 : 1247514 : = get_token_indent_info (c_parser_peek_token (parser));
8619 : 1247514 : warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
8620 : 1247514 : if (body_loc_after_labels != UNKNOWN_LOCATION
8621 : 798473 : && next_tinfo.type != CPP_SEMICOLON)
8622 : 793897 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8623 : 793897 : if_tinfo.location, RID_IF);
8624 : :
8625 : 1247514 : 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 : 252222 : c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
8635 : : vec<tree> *chain)
8636 : : {
8637 : 252222 : location_t body_loc = c_parser_peek_token (parser)->location;
8638 : 252222 : tree block = c_begin_compound_stmt (flag_isoc99);
8639 : 252222 : token_indent_info body_tinfo
8640 : 252222 : = get_token_indent_info (c_parser_peek_token (parser));
8641 : 252222 : location_t body_loc_after_labels = UNKNOWN_LOCATION;
8642 : 252222 : tree before_labels = get_before_labels ();
8643 : 252222 : attr_state a = c_parser_all_labels (parser);
8644 : :
8645 : 252222 : 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 : 252193 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
8657 : 216574 : body_loc_after_labels = c_parser_peek_token (parser)->location;
8658 : 252193 : c_parser_statement_after_labels (parser, NULL, before_labels, chain, a);
8659 : : }
8660 : :
8661 : 252222 : token_indent_info next_tinfo
8662 : 252222 : = get_token_indent_info (c_parser_peek_token (parser));
8663 : 252222 : warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
8664 : 252222 : if (body_loc_after_labels != UNKNOWN_LOCATION
8665 : 216574 : && next_tinfo.type != CPP_SEMICOLON)
8666 : 216560 : warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8667 : 216560 : else_tinfo.location, RID_ELSE);
8668 : :
8669 : 252222 : 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 : 1247514 : c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
8685 : : {
8686 : 1247514 : tree block;
8687 : 1247514 : location_t loc;
8688 : 1247514 : tree cond;
8689 : 1247514 : bool nested_if = false;
8690 : 1247514 : tree first_body, second_body;
8691 : 1247514 : bool in_if_block;
8692 : :
8693 : 1247514 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
8694 : 1247514 : token_indent_info if_tinfo
8695 : 1247514 : = get_token_indent_info (c_parser_peek_token (parser));
8696 : 1247514 : c_parser_consume_token (parser);
8697 : 1247514 : block = c_begin_compound_stmt (flag_isoc99);
8698 : 1247514 : loc = c_parser_peek_token (parser)->location;
8699 : 1247514 : cond = c_parser_paren_selection_header (parser);
8700 : 1247514 : in_if_block = parser->in_if_block;
8701 : 1247514 : parser->in_if_block = true;
8702 : 1247514 : first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
8703 : 1247514 : parser->in_if_block = in_if_block;
8704 : :
8705 : 1247514 : if (warn_duplicated_cond)
8706 : 62 : warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
8707 : :
8708 : 1247514 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
8709 : : {
8710 : 252222 : token_indent_info else_tinfo
8711 : 252222 : = get_token_indent_info (c_parser_peek_token (parser));
8712 : 252222 : c_parser_consume_token (parser);
8713 : 252222 : 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 : 252222 : 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 : 252222 : if (if_p != NULL)
8734 : 188 : *if_p = true;
8735 : : }
8736 : : else
8737 : : {
8738 : 995292 : second_body = NULL_TREE;
8739 : :
8740 : : /* Diagnose an ambiguous else if if-then-else is nested inside
8741 : : if-then. */
8742 : 995292 : if (nested_if)
8743 : 142 : warning_at (loc, OPT_Wdangling_else,
8744 : : "suggest explicit braces to avoid ambiguous %<else%>");
8745 : :
8746 : 995292 : 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 : 1247514 : c_finish_if_stmt (loc, cond, first_body, second_body);
8752 : 1247514 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8753 : :
8754 : 1247514 : c_parser_maybe_reclassify_token (parser);
8755 : 1247514 : }
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 : 36632 : c_parser_switch_statement (c_parser *parser, bool *if_p, tree before_labels)
8767 : : {
8768 : 36632 : struct c_expr ce;
8769 : 36632 : tree block, expr, body;
8770 : 36632 : unsigned char save_in_statement;
8771 : 36632 : location_t switch_loc = c_parser_peek_token (parser)->location;
8772 : 36632 : location_t switch_cond_loc;
8773 : 36632 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8774 : 36632 : c_parser_consume_token (parser);
8775 : 36632 : tree switch_name;
8776 : 36632 : int num_names = c_get_loop_names (before_labels, true, &switch_name);
8777 : 36632 : block = c_begin_compound_stmt (flag_isoc99);
8778 : 36632 : bool explicit_cast_p = false;
8779 : 36632 : matching_parens parens;
8780 : 36632 : if (parens.require_open (parser))
8781 : : {
8782 : 36625 : switch_cond_loc = c_parser_peek_token (parser)->location;
8783 : 36625 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
8784 : 36625 : && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
8785 : : explicit_cast_p = true;
8786 : 36625 : 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 : 36625 : ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8791 : 36625 : expr = ce.value;
8792 : : /* ??? expr has no valid location? */
8793 : 36625 : 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 : 36632 : tree stmt
8802 : 36632 : = c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p,
8803 : : switch_name);
8804 : 36632 : save_in_statement = in_statement;
8805 : 36632 : in_statement |= IN_SWITCH_STMT;
8806 : 36632 : if (switch_name)
8807 : : {
8808 : 126 : C_DECL_LOOP_SWITCH_NAME_VALID (switch_name) = 1;
8809 : 126 : in_statement |= IN_NAMED_STMT;
8810 : : }
8811 : : else
8812 : 36506 : in_statement &= ~IN_NAMED_STMT;
8813 : 36632 : location_t loc_after_labels;
8814 : 36632 : bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8815 : 36632 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
8816 : 36632 : location_t next_loc = c_parser_peek_token (parser)->location;
8817 : 36632 : 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 : 36632 : c_finish_switch (body, ce.original_type);
8821 : 36632 : in_statement = save_in_statement;
8822 : 36632 : if (num_names)
8823 : : {
8824 : 126 : if (!C_DECL_LOOP_SWITCH_NAME_USED (switch_name))
8825 : 114 : SWITCH_STMT_NAME (stmt) = NULL_TREE;
8826 : : else
8827 : 12 : SWITCH_STMT_NO_BREAK_P (stmt) = 0;
8828 : 126 : c_release_loop_names (num_names);
8829 : : }
8830 : 36632 : add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8831 : 36632 : c_parser_maybe_reclassify_token (parser);
8832 : 36632 : }
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 : 43667 : c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8848 : : bool novector, bool *if_p, tree before_labels)
8849 : : {
8850 : 43667 : tree block, cond, body;
8851 : 43667 : unsigned char save_in_statement;
8852 : 43667 : location_t loc;
8853 : 43667 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8854 : 43667 : token_indent_info while_tinfo
8855 : 43667 : = get_token_indent_info (c_parser_peek_token (parser));
8856 : 43667 : tree loop_name;
8857 : 43667 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
8858 : :
8859 : 43667 : 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 : 43667 : c_parser_consume_token (parser);
8867 : 43667 : block = c_begin_compound_stmt (flag_isoc99);
8868 : 43667 : loc = c_parser_peek_token (parser)->location;
8869 : 43667 : cond = c_parser_paren_condition (parser);
8870 : 43667 : 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 : 43667 : 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 : 43667 : 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 : 43667 : save_in_statement = in_statement;
8886 : 43667 : in_statement = IN_ITERATION_STMT;
8887 : 43667 : 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 : 43667 : token_indent_info body_tinfo
8894 : 43667 : = get_token_indent_info (c_parser_peek_token (parser));
8895 : :
8896 : 43667 : location_t loc_after_labels;
8897 : 43667 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
8898 : 43667 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
8899 : 43667 : if (loop_name && !C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8900 : 133 : loop_name = NULL_TREE;
8901 : 43667 : add_stmt (build_stmt (loc, WHILE_STMT, cond, body, loop_name, NULL_TREE,
8902 : : NULL_TREE));
8903 : 43667 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8904 : 43667 : c_parser_maybe_reclassify_token (parser);
8905 : 43667 : if (num_names)
8906 : 135 : c_release_loop_names (num_names);
8907 : :
8908 : 43667 : token_indent_info next_tinfo
8909 : 43667 : = get_token_indent_info (c_parser_peek_token (parser));
8910 : 43667 : warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
8911 : :
8912 : 43667 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8913 : 10459 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8914 : : while_tinfo.location, RID_WHILE);
8915 : :
8916 : 43667 : in_statement = save_in_statement;
8917 : 43667 : }
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 : 144612 : c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8929 : : bool novector, tree before_labels)
8930 : : {
8931 : 144612 : tree block, cond, body;
8932 : 144612 : unsigned char save_in_statement;
8933 : 144612 : location_t loc;
8934 : 144612 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
8935 : 144612 : tree loop_name;
8936 : 144612 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
8937 : :
8938 : 144612 : 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 : 144612 : c_parser_consume_token (parser);
8946 : 144612 : 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 : 144612 : block = c_begin_compound_stmt (flag_isoc99);
8951 : 144612 : loc = c_parser_peek_token (parser)->location;
8952 : 144612 : save_in_statement = in_statement;
8953 : 144612 : in_statement = IN_ITERATION_STMT;
8954 : 144612 : if (loop_name)
8955 : : {
8956 : 180 : C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
8957 : 180 : in_statement |= IN_NAMED_STMT;
8958 : : }
8959 : 144612 : body = c_parser_c99_block_statement (parser, NULL);
8960 : 144612 : c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
8961 : 144612 : in_statement = save_in_statement;
8962 : 144612 : if (num_names)
8963 : : {
8964 : 180 : if (!C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8965 : 178 : loop_name = NULL_TREE;
8966 : 180 : c_release_loop_names (num_names);
8967 : : }
8968 : 144612 : cond = c_parser_paren_condition (parser);
8969 : 144612 : 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 : 144612 : 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 : 144612 : 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 : 144612 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
8985 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
8986 : :
8987 : 144612 : add_stmt (build_stmt (loc, DO_STMT, cond, body, loop_name));
8988 : 144612 : add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8989 : 144612 : }
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 : 273839 : c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9055 : : bool novector, bool *if_p, tree before_labels)
9056 : : {
9057 : 273839 : tree block, cond, incr, body;
9058 : 273839 : unsigned char save_in_statement;
9059 : 273839 : tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
9060 : : /* The following are only used when parsing an ObjC foreach statement. */
9061 : 273839 : tree object_expression;
9062 : : /* Silence the bogus uninitialized warning. */
9063 : 273839 : tree collection_expression = NULL;
9064 : 273839 : location_t loc = c_parser_peek_token (parser)->location;
9065 : 273839 : location_t for_loc = loc;
9066 : 273839 : bool is_foreach_statement = false;
9067 : 273839 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
9068 : 273839 : token_indent_info for_tinfo
9069 : 273839 : = get_token_indent_info (c_parser_peek_token (parser));
9070 : 273839 : tree loop_name;
9071 : 273839 : int num_names = c_get_loop_names (before_labels, false, &loop_name);
9072 : :
9073 : 273839 : 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 : 273839 : 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 : 546792 : block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
9084 : 273839 : cond = error_mark_node;
9085 : 273839 : incr = error_mark_node;
9086 : 273839 : matching_parens parens;
9087 : 273839 : if (parens.require_open (parser))
9088 : : {
9089 : : /* Parse the initialization declaration or expression. */
9090 : 273838 : object_expression = error_mark_node;
9091 : 273838 : parser->objc_could_be_foreach_context = c_dialect_objc ();
9092 : 273838 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9093 : : {
9094 : 12237 : parser->objc_could_be_foreach_context = false;
9095 : 12237 : c_parser_consume_token (parser);
9096 : 12237 : c_finish_expr_stmt (loc, NULL_TREE);
9097 : : }
9098 : 261601 : else if (c_parser_next_tokens_start_declaration (parser)
9099 : 261601 : || c_parser_nth_token_starts_std_attributes (parser, 1))
9100 : : {
9101 : 19935 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
9102 : : false, &object_expression);
9103 : 19935 : parser->objc_could_be_foreach_context = false;
9104 : :
9105 : 19935 : 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 : 19935 : check_for_loop_decls (for_loc, flag_isoc99);
9115 : : }
9116 : 241666 : 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 : 241666 : init_expr:
9154 : 241666 : {
9155 : 241666 : struct c_expr ce;
9156 : 241666 : tree init_expression;
9157 : 241666 : ce = c_parser_expression (parser);
9158 : 241666 : init_expression = ce.value;
9159 : 241666 : parser->objc_could_be_foreach_context = false;
9160 : 241666 : 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 : 241666 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9173 : 241666 : init_expression = ce.value;
9174 : 241666 : c_finish_expr_stmt (loc, init_expression);
9175 : 241666 : 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 : 273838 : gcc_assert (!parser->objc_could_be_foreach_context);
9183 : 273838 : if (!is_foreach_statement)
9184 : : {
9185 : 273838 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
9186 : : {
9187 : 3023 : 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 : 3022 : 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 : 3022 : c_parser_consume_token (parser);
9202 : 3022 : cond = NULL_TREE;
9203 : : }
9204 : : }
9205 : : else
9206 : : {
9207 : 270815 : cond = c_parser_condition (parser);
9208 : 270815 : c_parser_skip_until_found (parser, CPP_SEMICOLON,
9209 : : "expected %<;%>");
9210 : : }
9211 : 273838 : 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 : 273838 : 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 : 273838 : if (novector && cond && cond != error_mark_node)
9222 : 2567 : 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 : 273838 : loc = c_parser_peek_token (parser)->location;
9231 : 273838 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9232 : : {
9233 : 4198 : 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 : 4198 : incr = c_process_expr_stmt (loc, NULL_TREE);
9241 : : }
9242 : : else
9243 : : {
9244 : 269640 : if (is_foreach_statement)
9245 : 0 : collection_expression
9246 : 0 : = c_fully_fold (c_parser_expression (parser).value, false, NULL);
9247 : : else
9248 : : {
9249 : 269640 : struct c_expr ce = c_parser_expression (parser);
9250 : 269640 : ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9251 : 269640 : incr = c_process_expr_stmt (loc, ce.value);
9252 : : }
9253 : : }
9254 : 273838 : parens.skip_until_found_close (parser);
9255 : : }
9256 : 273839 : save_in_statement = in_statement;
9257 : 273839 : 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 : 273839 : in_statement = IN_ITERATION_STMT;
9275 : 273839 : 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 : 273839 : token_indent_info body_tinfo
9282 : 273839 : = get_token_indent_info (c_parser_peek_token (parser));
9283 : :
9284 : 273839 : location_t loc_after_labels;
9285 : 273839 : bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
9286 : 273839 : body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
9287 : :
9288 : 273839 : 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 : 273387 : 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 : 547678 : 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 : 273839 : add_stmt (c_end_compound_stmt (for_loc, block,
9309 : 273839 : flag_isoc99 || c_dialect_objc ()));
9310 : 273839 : c_parser_maybe_reclassify_token (parser);
9311 : :
9312 : 273839 : token_indent_info next_tinfo
9313 : 273839 : = get_token_indent_info (c_parser_peek_token (parser));
9314 : 273839 : warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
9315 : :
9316 : 273839 : if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9317 : 161243 : warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9318 : : for_tinfo.location, RID_FOR);
9319 : :
9320 : 273839 : in_statement = save_in_statement;
9321 : 273839 : if (num_names)
9322 : 452 : c_release_loop_names (num_names);
9323 : 273839 : 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 : 273839 : }
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 : 200948 : c_parser_asm_statement (c_parser *parser)
9363 : : {
9364 : 200948 : tree str, outputs, inputs, clobbers, labels, ret;
9365 : 200948 : bool simple;
9366 : 200948 : location_t asm_loc = c_parser_peek_token (parser)->location;
9367 : 200948 : int section, nsections;
9368 : :
9369 : 200948 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
9370 : 200948 : c_parser_consume_token (parser);
9371 : :
9372 : : /* Handle the asm-qualifier-list. */
9373 : 200948 : location_t volatile_loc = UNKNOWN_LOCATION;
9374 : 200948 : location_t inline_loc = UNKNOWN_LOCATION;
9375 : 200948 : location_t goto_loc = UNKNOWN_LOCATION;
9376 : 362681 : for (;;)
9377 : : {
9378 : 362681 : c_token *token = c_parser_peek_token (parser);
9379 : 362681 : location_t loc = token->location;
9380 : 362681 : switch (token->keyword)
9381 : : {
9382 : 161292 : case RID_VOLATILE:
9383 : 161292 : 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 : 161292 : c_parser_consume_token (parser);
9391 : 161292 : 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 : 200948 : default:
9422 : 200948 : break;
9423 : : }
9424 : 200948 : break;
9425 : : }
9426 : :
9427 : 200948 : bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
9428 : 200948 : bool is_inline = (inline_loc != UNKNOWN_LOCATION);
9429 : 200948 : bool is_goto = (goto_loc != UNKNOWN_LOCATION);
9430 : :
9431 : 200948 : ret = NULL;
9432 : :
9433 : 200948 : matching_parens parens;
9434 : 200948 : if (!parens.require_open (parser))
9435 : 0 : goto error;
9436 : :
9437 : 200948 : str = c_parser_asm_string_literal (parser);
9438 : 200948 : if (str == NULL_TREE)
9439 : 12 : goto error_close_paren;
9440 : :
9441 : 200936 : simple = true;
9442 : 200936 : outputs = NULL_TREE;
9443 : 200936 : inputs = NULL_TREE;
9444 : 200936 : clobbers = NULL_TREE;
9445 : 200936 : labels = NULL_TREE;
9446 : :
9447 : 200936 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9448 : 1976 : goto done_asm;
9449 : :
9450 : : /* Parse each colon-delimited section of operands. */
9451 : 198960 : nsections = 3 + is_goto;
9452 : 508829 : for (section = 0; section < nsections; ++section)
9453 : : {
9454 : 508444 : if (c_parser_next_token_is (parser, CPP_SCOPE))
9455 : : {
9456 : 35125 : ++section;
9457 : 35125 : if (section == nsections)
9458 : : {
9459 : 5 : c_parser_error (parser, "expected %<)%>");
9460 : 5 : goto error_close_paren;
9461 : : }
9462 : 35120 : c_parser_consume_token (parser);
9463 : : }
9464 : 945282 : 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 : 508432 : simple = false;
9473 : :
9474 : 508432 : if ((!c_parser_next_token_is (parser, CPP_COLON)
9475 : 412186 : && !c_parser_next_token_is (parser, CPP_SCOPE)
9476 : 412137 : && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
9477 : 513307 : || section == 3)
9478 : 407312 : switch (section)
9479 : : {
9480 : 128916 : case 0:
9481 : 128916 : outputs = c_parser_asm_operands (parser);
9482 : 128916 : break;
9483 : 128353 : case 1:
9484 : 128353 : inputs = c_parser_asm_operands (parser);
9485 : 128353 : break;
9486 : 149658 : case 2:
9487 : 149658 : clobbers = c_parser_asm_clobbers (parser);
9488 : 149658 : 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 : 508432 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
9497 : 198563 : goto done_asm;
9498 : : }
9499 : :
9500 : 385 : done_asm:
9501 : 200924 : 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 : 200924 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
9508 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
9509 : :
9510 : 200924 : ret = build_asm_stmt (is_volatile,
9511 : : build_asm_expr (asm_loc, str, outputs, inputs,
9512 : : clobbers, labels, simple, is_inline));
9513 : :
9514 : 200948 : error:
9515 : 200948 : 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 : 257302 : c_parser_asm_operands (c_parser *parser)
9535 : : {
9536 : 257302 : tree list = NULL_TREE;
9537 : 1131978 : while (true)
9538 : : {
9539 : 694640 : tree name, str;
9540 : 694640 : struct c_expr expr;
9541 : 694640 : 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 : 694640 : str = c_parser_asm_string_literal (parser);
9563 : 694640 : if (str == NULL_TREE)
9564 : : return NULL_TREE;
9565 : 694640 : matching_parens parens;
9566 : 694640 : if (!parens.require_open (parser))
9567 : : return NULL_TREE;
9568 : 694640 : expr = c_parser_expression (parser);
9569 : 694640 : mark_exp_read (expr.value);
9570 : 694640 : 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 : 694640 : list = chainon (list, build_tree_list (build_tree_list (name, str),
9576 : : expr.value));
9577 : 694640 : if (c_parser_next_token_is (parser, CPP_COMMA))
9578 : 437338 : c_parser_consume_token (parser);
9579 : : else
9580 : : break;
9581 : 437338 : }
9582 : 257302 : 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 : 149658 : c_parser_asm_clobbers (c_parser *parser)
9594 : : {
9595 : 149658 : tree list = NULL_TREE;
9596 : 203660 : while (true)
9597 : : {
9598 : 176659 : tree str = c_parser_asm_string_literal (parser);
9599 : 176659 : if (str)
9600 : 176659 : list = tree_cons (NULL_TREE, str, list);
9601 : : else
9602 : : return NULL_TREE;
9603 : 176659 : if (c_parser_next_token_is (parser, CPP_COMMA))
9604 : 27001 : c_parser_consume_token (parser);
9605 : : else
9606 : : break;
9607 : 27001 : }
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 : 3725660 : c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
9658 : : {
9659 : 3725660 : struct c_expr ret;
9660 : 3725660 : size_t count;
9661 : 3725660 : struct obstack str_ob;
9662 : 3725660 : struct obstack loc_ob;
9663 : 3725660 : cpp_string str, istr, *strs;
9664 : 3725660 : c_token *tok;
9665 : 3725660 : location_t loc, last_tok_loc;
9666 : 3725660 : enum cpp_ttype type;
9667 : 3725660 : tree value, string_tree;
9668 : :
9669 : 3725660 : tok = c_parser_peek_token (parser);
9670 : 3725660 : loc = tok->location;
9671 : 3725660 : last_tok_loc = linemap_resolve_location (line_table, loc,
9672 : : LRK_MACRO_DEFINITION_LOCATION,
9673 : : NULL);
9674 : 3725660 : type = tok->type;
9675 : 3725660 : switch (type)
9676 : : {
9677 : 3725643 : case CPP_STRING:
9678 : 3725643 : case CPP_WSTRING:
9679 : 3725643 : case CPP_STRING16:
9680 : 3725643 : case CPP_STRING32:
9681 : 3725643 : case CPP_UTF8STRING:
9682 : 3725643 : string_tree = tok->value;
9683 : 3725643 : 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 : 3725643 : switch (c_parser_peek_2nd_token (parser)->type)
9697 : : {
9698 : 2859498 : default:
9699 : 2859498 : c_parser_consume_token (parser);
9700 : 2859498 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9701 : 2859498 : str.len = TREE_STRING_LENGTH (string_tree);
9702 : 2859498 : count = 1;
9703 : 2859498 : strs = &str;
9704 : 2859498 : break;
9705 : :
9706 : 866145 : case CPP_STRING:
9707 : 866145 : case CPP_WSTRING:
9708 : 866145 : case CPP_STRING16:
9709 : 866145 : case CPP_STRING32:
9710 : 866145 : case CPP_UTF8STRING:
9711 : 866145 : gcc_obstack_init (&str_ob);
9712 : 866145 : gcc_obstack_init (&loc_ob);
9713 : 866145 : count = 0;
9714 : 27843218 : do
9715 : : {
9716 : 27843218 : c_parser_consume_token (parser);
9717 : 27843218 : count++;
9718 : 27843218 : str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9719 : 27843218 : str.len = TREE_STRING_LENGTH (string_tree);
9720 : 27843218 : 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 : 27843218 : obstack_grow (&str_ob, &str, sizeof (cpp_string));
9729 : 27843218 : obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
9730 : 27843218 : tok = c_parser_peek_token (parser);
9731 : 27843218 : string_tree = tok->value;
9732 : 27843218 : last_tok_loc
9733 : 27843218 : = linemap_resolve_location (line_table, tok->location,
9734 : : LRK_MACRO_DEFINITION_LOCATION, NULL);
9735 : : }
9736 : 27843218 : while (tok->type == CPP_STRING
9737 : : || tok->type == CPP_WSTRING
9738 : : || tok->type == CPP_STRING16
9739 : : || tok->type == CPP_STRING32
9740 : 27843218 : || tok->type == CPP_UTF8STRING);
9741 : 866145 : strs = (cpp_string *) obstack_finish (&str_ob);
9742 : : }
9743 : :
9744 : 3725643 : if (count > 1 && !in_system_header_at (input_location))
9745 : 646635 : warning (OPT_Wtraditional,
9746 : : "traditional C rejects string constant concatenation");
9747 : :
9748 : 3725643 : if ((type == CPP_STRING || wide_ok)
9749 : 7451276 : && ((translate
9750 : 3725633 : ? cpp_interpret_string : cpp_interpret_string_notranslate)
9751 : 3725633 : (parse_in, strs, count, &istr, type)))
9752 : : {
9753 : 3725633 : value = build_string (istr.len, (const char *) istr.text);
9754 : 3725633 : free (CONST_CAST (unsigned char *, istr.text));
9755 : 3725633 : if (count > 1)
9756 : : {
9757 : 866145 : location_t *locs = (location_t *) obstack_finish (&loc_ob);
9758 : 866145 : gcc_assert (g_string_concat_db);
9759 : 866145 : 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 : 3725643 : switch (type)
9806 : : {
9807 : 3722386 : default:
9808 : 3722386 : case CPP_STRING:
9809 : 3722386 : TREE_TYPE (value) = char_array_type_node;
9810 : 3722386 : 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 : 3725643 : value = fix_string_type (value);
9827 : :
9828 : 3725643 : if (count > 1)
9829 : : {
9830 : 866145 : obstack_free (&str_ob, 0);
9831 : 866145 : obstack_free (&loc_ob, 0);
9832 : : }
9833 : :
9834 : 3725643 : ret.value = value;
9835 : 3725643 : ret.original_code = STRING_CST;
9836 : 3725643 : ret.original_type = NULL_TREE;
9837 : 3725643 : set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc));
9838 : 3725643 : ret.m_decimal = 0;
9839 : 3725643 : parser->seen_string_literal = true;
9840 : 3725643 : 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 : 222361360 : c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
9861 : : tree omp_atomic_lhs)
9862 : : {
9863 : 222361360 : struct c_expr lhs, rhs, ret;
9864 : 222361360 : enum tree_code code;
9865 : 222361360 : location_t op_location, exp_location;
9866 : 222361360 : bool save_in_omp_for = c_in_omp_for;
9867 : 222361360 : c_in_omp_for = false;
9868 : 222361360 : gcc_assert (!after || c_dialect_objc ());
9869 : 222361360 : lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
9870 : 222361358 : op_location = c_parser_peek_token (parser)->location;
9871 : 222361358 : switch (c_parser_peek_token (parser)->type)
9872 : : {
9873 : : case CPP_EQ:
9874 : : code = NOP_EXPR;
9875 : : break;
9876 : 12086 : case CPP_MULT_EQ:
9877 : 12086 : code = MULT_EXPR;
9878 : 12086 : break;
9879 : 8644 : case CPP_DIV_EQ:
9880 : 8644 : code = TRUNC_DIV_EXPR;
9881 : 8644 : break;
9882 : 2241 : case CPP_MOD_EQ:
9883 : 2241 : code = TRUNC_MOD_EXPR;
9884 : 2241 : break;
9885 : 89529 : case CPP_PLUS_EQ:
9886 : 89529 : code = PLUS_EXPR;
9887 : 89529 : break;
9888 : 28696 : case CPP_MINUS_EQ:
9889 : 28696 : code = MINUS_EXPR;
9890 : 28696 : break;
9891 : 4106 : case CPP_LSHIFT_EQ:
9892 : 4106 : code = LSHIFT_EXPR;
9893 : 4106 : break;
9894 : 16677 : case CPP_RSHIFT_EQ:
9895 : 16677 : code = RSHIFT_EXPR;
9896 : 16677 : break;
9897 : 24528 : case CPP_AND_EQ:
9898 : 24528 : code = BIT_AND_EXPR;
9899 : 24528 : break;
9900 : 3132 : case CPP_XOR_EQ:
9901 : 3132 : code = BIT_XOR_EXPR;
9902 : 3132 : break;
9903 : 19838 : case CPP_OR_EQ:
9904 : 19838 : code = BIT_IOR_EXPR;
9905 : 19838 : break;
9906 : 219535817 : default:
9907 : 219535817 : c_in_omp_for = save_in_omp_for;
9908 : 219535817 : return lhs;
9909 : : }
9910 : 2825541 : c_parser_consume_token (parser);
9911 : 2825541 : exp_location = c_parser_peek_token (parser)->location;
9912 : 2825541 : rhs = c_parser_expr_no_commas (parser, NULL);
9913 : 2825541 : rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
9914 : :
9915 : 2825541 : ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
9916 : : code, exp_location, rhs.value,
9917 : : rhs.original_type);
9918 : 2825541 : ret.m_decimal = 0;
9919 : 2825541 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
9920 : 2825541 : if (code == NOP_EXPR)
9921 : 2616064 : ret.original_code = MODIFY_EXPR;
9922 : : else
9923 : : {
9924 : 209477 : suppress_warning (ret.value, OPT_Wparentheses);
9925 : 209477 : ret.original_code = ERROR_MARK;
9926 : : }
9927 : 2825541 : ret.original_type = NULL;
9928 : 2825541 : c_in_omp_for = save_in_omp_for;
9929 : 2825541 : 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 : 222764753 : c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
9948 : : tree omp_atomic_lhs)
9949 : : {
9950 : 222764753 : struct c_expr cond, exp1, exp2, ret;
9951 : 222764753 : location_t start, cond_loc, colon_loc;
9952 : 222764753 : bool save_c_omp_array_section_p = c_omp_array_section_p;
9953 : :
9954 : 222764753 : gcc_assert (!after || c_dialect_objc ());
9955 : :
9956 : 222764753 : cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
9957 : :
9958 : 222764751 : if (c_parser_next_token_is_not (parser, CPP_QUERY))
9959 : 222361546 : return cond;
9960 : 403205 : c_omp_array_section_p = false;
9961 : 403205 : if (cond.value != error_mark_node)
9962 : 403194 : start = cond.get_start ();
9963 : : else
9964 : : start = UNKNOWN_LOCATION;
9965 : 403205 : cond_loc = c_parser_peek_token (parser)->location;
9966 : 403205 : cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
9967 : 403205 : c_parser_consume_token (parser);
9968 : 403205 : if (c_parser_next_token_is (parser, CPP_COLON))
9969 : : {
9970 : 744 : tree eptype = NULL_TREE;
9971 : :
9972 : 744 : location_t middle_loc = c_parser_peek_token (parser)->location;
9973 : 744 : pedwarn (middle_loc, OPT_Wpedantic,
9974 : : "ISO C forbids omitting the middle term of a %<?:%> expression");
9975 : 744 : 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 : 744 : tree e = cond.value;
9981 : 747 : while (TREE_CODE (e) == COMPOUND_EXPR)
9982 : 3 : e = TREE_OPERAND (e, 1);
9983 : 744 : warn_for_omitted_condop (middle_loc, e);
9984 : : /* Make sure first operand is calculated only once. */
9985 : 744 : exp1.value = save_expr (default_conversion (cond.value));
9986 : 744 : if (eptype)
9987 : 1 : exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
9988 : 744 : exp1.original_type = NULL;
9989 : 744 : exp1.src_range = cond.src_range;
9990 : 744 : cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
9991 : 744 : c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
9992 : : }
9993 : : else
9994 : : {
9995 : 402461 : cond.value
9996 : 402461 : = c_objc_common_truthvalue_conversion
9997 : 402461 : (cond_loc, default_conversion (cond.value));
9998 : 402461 : c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
9999 : 402461 : exp1 = c_parser_expression_conv (parser);
10000 : 402461 : mark_exp_read (exp1.value);
10001 : 402461 : c_inhibit_evaluation_warnings +=
10002 : 402461 : ((cond.value == truthvalue_true_node)
10003 : 402461 : - (cond.value == truthvalue_false_node));
10004 : : }
10005 : :
10006 : 403205 : colon_loc = c_parser_peek_token (parser)->location;
10007 : 403205 : 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 : 403196 : {
10017 : 403196 : location_t exp2_loc = c_parser_peek_token (parser)->location;
10018 : 403196 : exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
10019 : 403196 : exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
10020 : : }
10021 : 403196 : c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10022 : 403196 : location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
10023 : 403196 : location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
10024 : 403196 : 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 : 403254 : && (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 : 403141 : ret.value
10035 : 403141 : = build_conditional_expr (colon_loc, cond.value,
10036 : 403141 : cond.original_code == C_MAYBE_CONST_EXPR,
10037 : : exp1.value, exp1.original_type, loc1,
10038 : : exp2.value, exp2.original_type, loc2);
10039 : 403196 : ret.original_code = ERROR_MARK;
10040 : 403196 : if (exp1.value == error_mark_node || exp2.value == error_mark_node)
10041 : 15 : ret.original_type = NULL;
10042 : : else
10043 : : {
10044 : 403181 : 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 : 403181 : t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
10050 : 403181 : t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
10051 : 403181 : ret.original_type = ((t1 != error_mark_node
10052 : 403181 : && t2 != error_mark_node
10053 : 403181 : && (TYPE_MAIN_VARIANT (t1)
10054 : 403181 : == TYPE_MAIN_VARIANT (t2)))
10055 : 403181 : ? t1
10056 : : : NULL);
10057 : : }
10058 : 403196 : set_c_expr_source_range (&ret, start, exp2.get_finish ());
10059 : 403196 : ret.m_decimal = 0;
10060 : 403196 : c_omp_array_section_p = save_c_omp_array_section_p;
10061 : 403196 : 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 : 222781193 : 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 : 222781193 : 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 : 222781193 : int sp;
10163 : : /* Location of the binary operator. */
10164 : 222781193 : 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 : 222781193 : gcc_assert (!after || c_dialect_objc ());
10260 : 222781193 : stack[0].loc = c_parser_peek_token (parser)->location;
10261 : 222781193 : stack[0].expr = c_parser_cast_expression (parser, after);
10262 : 222781193 : stack[0].prec = PREC_NONE;
10263 : 222781193 : stack[0].sizeof_arg = c_last_sizeof_arg;
10264 : 222781193 : sp = 0;
10265 : 241074145 : while (true)
10266 : : {
10267 : 231927669 : enum c_parser_prec oprec;
10268 : 231927669 : enum tree_code ocode;
10269 : 231927669 : source_range src_range;
10270 : 231927669 : if (parser->error)
10271 : 1070 : goto out;
10272 : 231926599 : switch (c_parser_peek_token (parser)->type)
10273 : : {
10274 : : case CPP_MULT:
10275 : : oprec = PREC_MULT;
10276 : : ocode = MULT_EXPR;
10277 : : break;
10278 : 254422 : case CPP_DIV:
10279 : 254422 : oprec = PREC_MULT;
10280 : 254422 : ocode = TRUNC_DIV_EXPR;
10281 : 254422 : break;
10282 : 54246 : case CPP_MOD:
10283 : 54246 : oprec = PREC_MULT;
10284 : 54246 : ocode = TRUNC_MOD_EXPR;
10285 : 54246 : break;
10286 : 1811198 : case CPP_PLUS:
10287 : 1811198 : oprec = PREC_ADD;
10288 : 1811198 : ocode = PLUS_EXPR;
10289 : 1811198 : break;
10290 : 740489 : case CPP_MINUS:
10291 : 740489 : oprec = PREC_ADD;
10292 : 740489 : ocode = MINUS_EXPR;
10293 : 740489 : break;
10294 : 779199 : case CPP_LSHIFT:
10295 : 779199 : oprec = PREC_SHIFT;
10296 : 779199 : ocode = LSHIFT_EXPR;
10297 : 779199 : break;
10298 : 209870 : case CPP_RSHIFT:
10299 : 209870 : oprec = PREC_SHIFT;
10300 : 209870 : ocode = RSHIFT_EXPR;
10301 : 209870 : break;
10302 : 454820 : case CPP_LESS:
10303 : 454820 : oprec = PREC_REL;
10304 : 454820 : ocode = LT_EXPR;
10305 : 454820 : break;
10306 : 189951 : case CPP_GREATER:
10307 : 189951 : oprec = PREC_REL;
10308 : 189951 : ocode = GT_EXPR;
10309 : 189951 : break;
10310 : 162715 : case CPP_LESS_EQ:
10311 : 162715 : oprec = PREC_REL;
10312 : 162715 : ocode = LE_EXPR;
10313 : 162715 : break;
10314 : 165530 : case CPP_GREATER_EQ:
10315 : 165530 : oprec = PREC_REL;
10316 : 165530 : ocode = GE_EXPR;
10317 : 165530 : break;
10318 : 386282 : case CPP_EQ_EQ:
10319 : 386282 : oprec = PREC_EQ;
10320 : 386282 : ocode = EQ_EXPR;
10321 : 386282 : break;
10322 : 761159 : case CPP_NOT_EQ:
10323 : 761159 : oprec = PREC_EQ;
10324 : 761159 : ocode = NE_EXPR;
10325 : 761159 : break;
10326 : 577192 : case CPP_AND:
10327 : 577192 : oprec = PREC_BITAND;
10328 : 577192 : ocode = BIT_AND_EXPR;
10329 : 577192 : break;
10330 : 75077 : case CPP_XOR:
10331 : 75077 : oprec = PREC_BITXOR;
10332 : 75077 : ocode = BIT_XOR_EXPR;
10333 : 75077 : break;
10334 : 841133 : case CPP_OR:
10335 : 841133 : oprec = PREC_BITOR;
10336 : 841133 : ocode = BIT_IOR_EXPR;
10337 : 841133 : break;
10338 : 181305 : case CPP_AND_AND:
10339 : 181305 : oprec = PREC_LOGAND;
10340 : 181305 : ocode = TRUTH_ANDIF_EXPR;
10341 : 181305 : break;
10342 : 320517 : case CPP_OR_OR:
10343 : 320517 : oprec = PREC_LOGOR;
10344 : 320517 : ocode = TRUTH_ORIF_EXPR;
10345 : 320517 : break;
10346 : 222780123 : default:
10347 : : /* Not a binary operator, so end of the binary
10348 : : expression. */
10349 : 222780123 : goto out;
10350 : : }
10351 : 9146476 : binary_loc = c_parser_peek_token (parser)->location;
10352 : 9146476 : while (oprec <= stack[sp].prec)
10353 : 10581547 : POP;
10354 : 9146476 : c_parser_consume_token (parser);
10355 : 9146476 : switch (ocode)
10356 : : {
10357 : 181305 : case TRUTH_ANDIF_EXPR:
10358 : 181305 : src_range = stack[sp].expr.src_range;
10359 : 181305 : stack[sp].expr
10360 : 181305 : = convert_lvalue_to_rvalue (stack[sp].loc,
10361 : : stack[sp].expr, true, true);
10362 : 362610 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10363 : 181305 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10364 : 181305 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10365 : 181305 : == truthvalue_false_node);
10366 : 181305 : set_c_expr_source_range (&stack[sp].expr, src_range);
10367 : 181305 : break;
10368 : 320517 : case TRUTH_ORIF_EXPR:
10369 : 320517 : src_range = stack[sp].expr.src_range;
10370 : 320517 : stack[sp].expr
10371 : 320517 : = convert_lvalue_to_rvalue (stack[sp].loc,
10372 : : stack[sp].expr, true, true);
10373 : 641034 : stack[sp].expr.value = c_objc_common_truthvalue_conversion
10374 : 320517 : (stack[sp].loc, default_conversion (stack[sp].expr.value));
10375 : 320517 : c_inhibit_evaluation_warnings += (stack[sp].expr.value
10376 : 320517 : == truthvalue_true_node);
10377 : 320517 : set_c_expr_source_range (&stack[sp].expr, src_range);
10378 : 320517 : break;
10379 : : default:
10380 : : break;
10381 : : }
10382 : 9146476 : sp++;
10383 : 9146476 : stack[sp].loc = binary_loc;
10384 : 9146476 : stack[sp].expr = c_parser_cast_expression (parser, NULL);
10385 : 9146476 : stack[sp].prec = oprec;
10386 : 9146476 : stack[sp].op = ocode;
10387 : 9146476 : stack[sp].sizeof_arg = c_last_sizeof_arg;
10388 : 9146476 : }
10389 : 222781193 : out:
10390 : 222781193 : while (sp > 0)
10391 : 230493319 : POP;
10392 : 222781191 : 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 : 118335174 : c_parser_compound_literal_scspecs (c_parser *parser)
10401 : : {
10402 : 118335174 : bool seen_scspec = false;
10403 : 118335174 : struct c_declspecs *specs = build_null_declspecs ();
10404 : 236670670 : while (c_parser_next_token_is (parser, CPP_KEYWORD))
10405 : : {
10406 : 4148654 : 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 : 4148332 : default:
10418 : 4148332 : goto out;
10419 : : }
10420 : : }
10421 : 114186842 : out:
10422 : 118335174 : 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 : 358609456 : c_parser_cast_expression (c_parser *parser, struct c_expr *after)
10436 : : {
10437 : 358609456 : location_t cast_loc = c_parser_peek_token (parser)->location;
10438 : 358609456 : 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 : 358609456 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10448 : 358609456 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10449 : : {
10450 : 117973541 : struct c_declspecs *scspecs;
10451 : 117973541 : struct c_type_name *type_name;
10452 : 117973541 : struct c_expr ret;
10453 : 117973541 : struct c_expr expr;
10454 : 117973541 : matching_parens parens;
10455 : 117973541 : parens.consume_open (parser);
10456 : 117973541 : scspecs = c_parser_compound_literal_scspecs (parser);
10457 : 117973541 : type_name = c_parser_type_name (parser, true);
10458 : 117973541 : parens.skip_until_found_close (parser);
10459 : 117973541 : 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 : 117973540 : used_types_insert (type_name->specs->type);
10469 : :
10470 : 117973540 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10471 : 898054 : return c_parser_postfix_expression_after_paren_type (parser, scspecs,
10472 : : type_name,
10473 : 898054 : cast_loc);
10474 : 117075486 : if (scspecs)
10475 : 1 : error_at (cast_loc, "storage class specifier in cast");
10476 : 117075486 : 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 : 117075486 : {
10480 : 117075486 : location_t expr_loc = c_parser_peek_token (parser)->location;
10481 : 117075486 : expr = c_parser_cast_expression (parser, NULL);
10482 : 117075486 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
10483 : : }
10484 : 117075486 : ret.value = c_cast_expr (cast_loc, type_name, expr.value);
10485 : 117075486 : if (ret.value && expr.value)
10486 : 117075486 : set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
10487 : 117075486 : ret.original_code = ERROR_MARK;
10488 : 117075486 : ret.original_type = NULL;
10489 : 117075486 : ret.m_decimal = 0;
10490 : 117075486 : return ret;
10491 : : }
10492 : : else
10493 : 240635915 : 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 : 240979115 : c_parser_unary_expression (c_parser *parser)
10536 : : {
10537 : 240979115 : int ext;
10538 : 240979115 : struct c_expr ret, op;
10539 : 240979115 : location_t op_loc = c_parser_peek_token (parser)->location;
10540 : 240979115 : location_t exp_loc;
10541 : 240979115 : location_t finish;
10542 : 240979115 : ret.original_code = ERROR_MARK;
10543 : 240979115 : ret.original_type = NULL;
10544 : 240979115 : switch (c_parser_peek_token (parser)->type)
10545 : : {
10546 : 220116 : case CPP_PLUS_PLUS:
10547 : 220116 : c_parser_consume_token (parser);
10548 : 220116 : exp_loc = c_parser_peek_token (parser)->location;
10549 : 220116 : op = c_parser_cast_expression (parser, NULL);
10550 : 4109 : if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10551 : 217138 : && !DECL_READ_P (op.value)
10552 : 226303 : && (VAR_P (op.value) ? warn_unused_but_set_variable
10553 : : : warn_unused_but_set_parameter) > 1)
10554 : : {
10555 : 399 : op = default_function_array_read_conversion (exp_loc, op);
10556 : 399 : DECL_READ_P (op.value) = 0;
10557 : : }
10558 : : else
10559 : 219717 : op = default_function_array_read_conversion (exp_loc, op);
10560 : 220116 : return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
10561 : 19882 : case CPP_MINUS_MINUS:
10562 : 19882 : c_parser_consume_token (parser);
10563 : 19882 : exp_loc = c_parser_peek_token (parser)->location;
10564 : 19882 : op = c_parser_cast_expression (parser, NULL);
10565 : 14590 : if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
10566 : 19249 : && !DECL_READ_P (op.value)
10567 : 21868 : && (VAR_P (op.value) ? warn_unused_but_set_variable
10568 : : : warn_unused_but_set_parameter) > 1)
10569 : : {
10570 : 202 : op = default_function_array_read_conversion (exp_loc, op);
10571 : 202 : DECL_READ_P (op.value) = 0;
10572 : : }
10573 : : else
10574 : 19680 : op = default_function_array_read_conversion (exp_loc, op);
10575 : 19882 : return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
10576 : 441998 : case CPP_AND:
10577 : 441998 : c_parser_consume_token (parser);
10578 : 441998 : op = c_parser_cast_expression (parser, NULL);
10579 : 441998 : mark_exp_read (op.value);
10580 : 441998 : return parser_build_unary_op (op_loc, ADDR_EXPR, op);
10581 : 1183530 : case CPP_MULT:
10582 : 1183530 : {
10583 : 1183530 : c_parser_consume_token (parser);
10584 : 1183530 : exp_loc = c_parser_peek_token (parser)->location;
10585 : 1183530 : op = c_parser_cast_expression (parser, NULL);
10586 : 1183530 : finish = op.get_finish ();
10587 : 1183530 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10588 : 1183530 : location_t combined_loc = make_location (op_loc, op_loc, finish);
10589 : 1183530 : ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
10590 : 1183530 : ret.src_range.m_start = op_loc;
10591 : 1183530 : ret.src_range.m_finish = finish;
10592 : 1183530 : ret.m_decimal = 0;
10593 : 1183530 : return ret;
10594 : : }
10595 : 28536 : case CPP_PLUS:
10596 : 28536 : if (!c_dialect_objc () && !in_system_header_at (input_location))
10597 : 28534 : warning_at (op_loc,
10598 : 28534 : OPT_Wtraditional,
10599 : : "traditional C rejects the unary plus operator");
10600 : 28536 : c_parser_consume_token (parser);
10601 : 28536 : exp_loc = c_parser_peek_token (parser)->location;
10602 : 28536 : op = c_parser_cast_expression (parser, NULL);
10603 : 28536 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10604 : 28536 : return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
10605 : 6518784 : case CPP_MINUS:
10606 : 6518784 : c_parser_consume_token (parser);
10607 : 6518784 : exp_loc = c_parser_peek_token (parser)->location;
10608 : 6518784 : op = c_parser_cast_expression (parser, NULL);
10609 : 6518784 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10610 : 6518784 : return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
10611 : 288672 : case CPP_COMPL:
10612 : 288672 : c_parser_consume_token (parser);
10613 : 288672 : exp_loc = c_parser_peek_token (parser)->location;
10614 : 288672 : op = c_parser_cast_expression (parser, NULL);
10615 : 288672 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10616 : 288672 : return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
10617 : 374237 : case CPP_NOT:
10618 : 374237 : c_parser_consume_token (parser);
10619 : 374237 : exp_loc = c_parser_peek_token (parser)->location;
10620 : 374237 : op = c_parser_cast_expression (parser, NULL);
10621 : 374237 : op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10622 : 374237 : return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
10623 : 1834 : case CPP_AND_AND:
10624 : : /* Refer to the address of a label as a pointer. */
10625 : 1834 : c_parser_consume_token (parser);
10626 : 1834 : if (c_parser_next_token_is (parser, CPP_NAME))
10627 : : {
10628 : 3654 : ret.value = finish_label_address_expr
10629 : 1827 : (c_parser_peek_token (parser)->value, op_loc);
10630 : 1827 : set_c_expr_source_range (&ret, op_loc,
10631 : : c_parser_peek_token (parser)->get_finish ());
10632 : 1827 : c_parser_consume_token (parser);
10633 : : }
10634 : : else
10635 : : {
10636 : 7 : c_parser_error (parser, "expected identifier");
10637 : 7 : ret.set_error ();
10638 : : }
10639 : 1834 : return ret;
10640 : 2832198 : case CPP_KEYWORD:
10641 : 2832198 : switch (c_parser_peek_token (parser)->keyword)
10642 : : {
10643 : 71 : case RID_COUNTOF:
10644 : 71 : return c_parser_countof_expression (parser);
10645 : 632479 : case RID_SIZEOF:
10646 : 632479 : return c_parser_sizeof_expression (parser);
10647 : 72283 : case RID_ALIGNOF:
10648 : 72283 : return c_parser_alignof_expression (parser);
10649 : 764 : case RID_BUILTIN_HAS_ATTRIBUTE:
10650 : 764 : return c_parser_has_attribute_expression (parser);
10651 : 451301 : case RID_EXTENSION:
10652 : 451301 : c_parser_consume_token (parser);
10653 : 451301 : ext = disable_extension_diagnostics ();
10654 : 451301 : ret = c_parser_cast_expression (parser, NULL);
10655 : 451301 : restore_extension_diagnostics (ext);
10656 : 451301 : return ret;
10657 : 38361 : case RID_REALPART:
10658 : 38361 : c_parser_consume_token (parser);
10659 : 38361 : exp_loc = c_parser_peek_token (parser)->location;
10660 : 38361 : op = c_parser_cast_expression (parser, NULL);
10661 : 38361 : op = default_function_array_conversion (exp_loc, op);
10662 : 38361 : return parser_build_unary_op (op_loc, REALPART_EXPR, op);
10663 : 38304 : case RID_IMAGPART:
10664 : 38304 : c_parser_consume_token (parser);
10665 : 38304 : exp_loc = c_parser_peek_token (parser)->location;
10666 : 38304 : op = c_parser_cast_expression (parser, NULL);
10667 : 38304 : op = default_function_array_conversion (exp_loc, op);
10668 : 38304 : return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
10669 : 7 : case RID_TRANSACTION_ATOMIC:
10670 : 7 : case RID_TRANSACTION_RELAXED:
10671 : 14 : return c_parser_transaction_expression (parser,
10672 : 7 : c_parser_peek_token (parser)->keyword);
10673 : 1598628 : default:
10674 : 1598628 : return c_parser_postfix_expression (parser);
10675 : : }
10676 : 229069328 : default:
10677 : 229069328 : return c_parser_postfix_expression (parser);
10678 : : }
10679 : : }
10680 : :
10681 : : /* Parse a sizeof expression. */
10682 : :
10683 : : static inline struct c_expr
10684 : 632479 : c_parser_sizeof_expression (c_parser *parser)
10685 : : {
10686 : 632479 : return c_parser_sizeof_or_countof_expression (parser, RID_SIZEOF);
10687 : : }
10688 : :
10689 : : /* Parse a _Countof expression. */
10690 : :
10691 : : static inline struct c_expr
10692 : 71 : c_parser_countof_expression (c_parser *parser)
10693 : : {
10694 : 71 : return c_parser_sizeof_or_countof_expression (parser, RID_COUNTOF);
10695 : : }
10696 : :
10697 : : /* Parse a sizeof or _Countof expression. */
10698 : :
10699 : : static struct c_expr
10700 : 632550 : c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
10701 : : {
10702 : 632550 : const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
10703 : 632550 : struct c_expr expr;
10704 : 632550 : struct c_expr result;
10705 : 632550 : location_t expr_loc;
10706 : 632550 : gcc_assert (c_parser_next_token_is_keyword (parser, rid));
10707 : :
10708 : 632550 : location_t start;
10709 : 632550 : location_t finish = UNKNOWN_LOCATION;
10710 : :
10711 : 632550 : start = c_parser_peek_token (parser)->location;
10712 : :
10713 : 632550 : if (rid == RID_COUNTOF)
10714 : 71 : pedwarn_c23 (start, OPT_Wpedantic,
10715 : : "ISO C does not support %qs before C2Y", op_name);
10716 : :
10717 : 632550 : c_parser_consume_token (parser);
10718 : 632550 : c_inhibit_evaluation_warnings++;
10719 : 632550 : if (rid == RID_COUNTOF)
10720 : 71 : in_countof++;
10721 : : else
10722 : 632479 : in_sizeof++;
10723 : 632550 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10724 : 632550 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10725 : : {
10726 : : /* Either sizeof ( type-name ) or sizeof unary-expression
10727 : : starting with a compound literal. */
10728 : 330141 : struct c_declspecs *scspecs;
10729 : 330141 : struct c_type_name *type_name;
10730 : 330141 : matching_parens parens;
10731 : 330141 : parens.consume_open (parser);
10732 : 330141 : expr_loc = c_parser_peek_token (parser)->location;
10733 : 330141 : scspecs = c_parser_compound_literal_scspecs (parser);
10734 : 330141 : type_name = c_parser_type_name (parser, true);
10735 : 330141 : parens.skip_until_found_close (parser);
10736 : 330141 : finish = parser->tokens_buf[0].location;
10737 : 330141 : if (type_name == NULL)
10738 : : {
10739 : : /* Let c_expr_sizeof_expr call pop_maybe_used and fill in c_expr
10740 : : for parsing error; the parsing of the expression could have
10741 : : called record_maybe_used_decl. */
10742 : 1 : expr.set_error ();
10743 : 27 : goto Xof_expr;
10744 : : }
10745 : 330140 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10746 : : {
10747 : 26 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10748 : : type_name,
10749 : : expr_loc);
10750 : 26 : finish = expr.get_finish ();
10751 : 26 : goto Xof_expr;
10752 : : }
10753 : : /* sizeof ( type-name ). */
10754 : 330114 : if (scspecs)
10755 : 1 : error_at (expr_loc, "storage class specifier in %qs", op_name);
10756 : 330114 : if (type_name->specs->alignas_p)
10757 : 2 : error_at (type_name->specs->locations[cdw_alignas],
10758 : : "alignment specified for type name in %qs", op_name);
10759 : 330114 : c_inhibit_evaluation_warnings--;
10760 : 330114 : if (rid == RID_COUNTOF)
10761 : : {
10762 : 18 : in_countof--;
10763 : 18 : result = c_expr_countof_type (expr_loc, type_name);
10764 : : }
10765 : : else
10766 : : {
10767 : 330096 : in_sizeof--;
10768 : 330096 : result = c_expr_sizeof_type (expr_loc, type_name);
10769 : : }
10770 : : }
10771 : : else
10772 : : {
10773 : 302409 : expr_loc = c_parser_peek_token (parser)->location;
10774 : 302409 : expr = c_parser_unary_expression (parser);
10775 : 302409 : finish = expr.get_finish ();
10776 : 302436 : Xof_expr:
10777 : 302436 : c_inhibit_evaluation_warnings--;
10778 : 302436 : if (rid == RID_COUNTOF)
10779 : 53 : in_countof--;
10780 : : else
10781 : 302383 : in_sizeof--;
10782 : 302436 : mark_exp_read (expr.value);
10783 : 302436 : if (TREE_CODE (expr.value) == COMPONENT_REF
10784 : 302436 : && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
10785 : 1 : error_at (expr_loc, "%qs applied to a bit-field", op_name);
10786 : 302436 : if (rid == RID_COUNTOF)
10787 : 53 : result = c_expr_countof_expr (expr_loc, expr);
10788 : : else
10789 : 302383 : result = c_expr_sizeof_expr (expr_loc, expr);
10790 : : }
10791 : 632550 : if (finish == UNKNOWN_LOCATION)
10792 : 1 : finish = start;
10793 : 632550 : set_c_expr_source_range (&result, start, finish);
10794 : 632550 : return result;
10795 : : }
10796 : :
10797 : : /* Parse an alignof expression. */
10798 : :
10799 : : static struct c_expr
10800 : 72283 : c_parser_alignof_expression (c_parser *parser)
10801 : : {
10802 : 72283 : struct c_expr expr;
10803 : 72283 : location_t start_loc = c_parser_peek_token (parser)->location;
10804 : 72283 : location_t end_loc;
10805 : 72283 : tree alignof_spelling = c_parser_peek_token (parser)->value;
10806 : 72283 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
10807 : 72283 : bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
10808 : : "_Alignof") == 0
10809 : 72283 : || strcmp (IDENTIFIER_POINTER (alignof_spelling),
10810 : 72512 : "alignof") == 0);
10811 : : /* A diagnostic is not required for the use of this identifier in
10812 : : the implementation namespace; only diagnose it for the C11 or C23
10813 : : spelling because of existing code using the other spellings. */
10814 : 229 : if (is_c11_alignof)
10815 : : {
10816 : 229 : if (flag_isoc99)
10817 : 225 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
10818 : : alignof_spelling);
10819 : : else
10820 : 4 : pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
10821 : : alignof_spelling);
10822 : : }
10823 : 72283 : c_parser_consume_token (parser);
10824 : 72283 : c_inhibit_evaluation_warnings++;
10825 : 72283 : in_alignof++;
10826 : 72283 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
10827 : 72283 : && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
10828 : : {
10829 : : /* Either __alignof__ ( type-name ) or __alignof__
10830 : : unary-expression starting with a compound literal. */
10831 : 31492 : location_t loc;
10832 : 31492 : struct c_declspecs *scspecs;
10833 : 31492 : struct c_type_name *type_name;
10834 : 31492 : struct c_expr ret;
10835 : 31492 : matching_parens parens;
10836 : 31492 : parens.consume_open (parser);
10837 : 31492 : loc = c_parser_peek_token (parser)->location;
10838 : 31492 : scspecs = c_parser_compound_literal_scspecs (parser);
10839 : 31492 : type_name = c_parser_type_name (parser, true);
10840 : 31492 : end_loc = c_parser_peek_token (parser)->location;
10841 : 31492 : parens.skip_until_found_close (parser);
10842 : 31492 : if (type_name == NULL)
10843 : : {
10844 : 0 : struct c_expr ret;
10845 : 0 : c_inhibit_evaluation_warnings--;
10846 : 0 : in_alignof--;
10847 : 0 : ret.set_error ();
10848 : 0 : ret.original_code = ERROR_MARK;
10849 : 0 : ret.original_type = NULL;
10850 : 31490 : return ret;
10851 : : }
10852 : 31492 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
10853 : : {
10854 : 2 : expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10855 : : type_name,
10856 : : loc);
10857 : 2 : goto alignof_expr;
10858 : : }
10859 : : /* alignof ( type-name ). */
10860 : 31490 : if (scspecs)
10861 : 1 : error_at (loc, "storage class specifier in %qE", alignof_spelling);
10862 : 31490 : if (type_name->specs->alignas_p)
10863 : 1 : error_at (type_name->specs->locations[cdw_alignas],
10864 : : "alignment specified for type name in %qE",
10865 : : alignof_spelling);
10866 : 31490 : c_inhibit_evaluation_warnings--;
10867 : 31490 : in_alignof--;
10868 : 31490 : ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
10869 : : NULL, NULL),
10870 : : false, is_c11_alignof, 1);
10871 : 31490 : ret.original_code = ERROR_MARK;
10872 : 31490 : ret.original_type = NULL;
10873 : 31490 : set_c_expr_source_range (&ret, start_loc, end_loc);
10874 : 31490 : ret.m_decimal = 0;
10875 : 31490 : return ret;
10876 : : }
10877 : : else
10878 : : {
10879 : 40791 : struct c_expr ret;
10880 : 40791 : expr = c_parser_unary_expression (parser);
10881 : 40791 : end_loc = expr.src_range.m_finish;
10882 : 40793 : alignof_expr:
10883 : 40793 : mark_exp_read (expr.value);
10884 : 40793 : c_inhibit_evaluation_warnings--;
10885 : 40793 : in_alignof--;
10886 : 40793 : if (is_c11_alignof)
10887 : 36 : pedwarn (start_loc,
10888 : 36 : OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
10889 : : alignof_spelling);
10890 : 40793 : ret.value = c_alignof_expr (start_loc, expr.value);
10891 : 40793 : ret.original_code = ERROR_MARK;
10892 : 40793 : ret.original_type = NULL;
10893 : 40793 : set_c_expr_source_range (&ret, start_loc, end_loc);
10894 : 40793 : ret.m_decimal = 0;
10895 : 40793 : return ret;
10896 : : }
10897 : : }
10898 : :
10899 : : /* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
10900 : : expression. */
10901 : :
10902 : : static struct c_expr
10903 : 764 : c_parser_has_attribute_expression (c_parser *parser)
10904 : : {
10905 : 764 : gcc_assert (c_parser_next_token_is_keyword (parser,
10906 : : RID_BUILTIN_HAS_ATTRIBUTE));
10907 : 764 : location_t start = c_parser_peek_token (parser)->location;
10908 : 764 : c_parser_consume_token (parser);
10909 : :
10910 : 764 : c_inhibit_evaluation_warnings++;
10911 : :
10912 : 764 : matching_parens parens;
10913 : 764 : if (!parens.require_open (parser))
10914 : : {
10915 : 0 : c_inhibit_evaluation_warnings--;
10916 : 0 : in_typeof--;
10917 : :
10918 : 0 : struct c_expr result;
10919 : 0 : result.set_error ();
10920 : 0 : result.original_code = ERROR_MARK;
10921 : 0 : result.original_type = NULL;
10922 : 0 : return result;
10923 : : }
10924 : :
10925 : : /* Treat the type argument the same way as in typeof for the purposes
10926 : : of warnings. FIXME: Generalize this so the warning refers to
10927 : : __builtin_has_attribute rather than typeof. */
10928 : 764 : in_typeof++;
10929 : :
10930 : : /* The first operand: one of DECL, EXPR, or TYPE. */
10931 : 764 : tree oper = NULL_TREE;
10932 : 764 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
10933 : : {
10934 : 148 : struct c_type_name *tname = c_parser_type_name (parser);
10935 : 148 : in_typeof--;
10936 : 148 : if (tname)
10937 : : {
10938 : 148 : oper = groktypename (tname, NULL, NULL);
10939 : 148 : pop_maybe_used (c_type_variably_modified_p (oper));
10940 : : }
10941 : : }
10942 : : else
10943 : : {
10944 : 616 : struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
10945 : 616 : c_inhibit_evaluation_warnings--;
10946 : 616 : in_typeof--;
10947 : 616 : if (cexpr.value != error_mark_node)
10948 : : {
10949 : 613 : mark_exp_read (cexpr.value);
10950 : 613 : oper = cexpr.value;
10951 : 613 : tree etype = TREE_TYPE (oper);
10952 : 613 : bool was_vm = c_type_variably_modified_p (etype);
10953 : : /* This is returned with the type so that when the type is
10954 : : evaluated, this can be evaluated. */
10955 : 613 : if (was_vm)
10956 : 0 : oper = c_fully_fold (oper, false, NULL);
10957 : 613 : pop_maybe_used (was_vm);
10958 : : }
10959 : : }
10960 : :
10961 : 764 : struct c_expr result;
10962 : 764 : result.original_code = ERROR_MARK;
10963 : 764 : result.original_type = NULL;
10964 : :
10965 : 764 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
10966 : : {
10967 : : /* Consume the closing parenthesis if that's the next token
10968 : : in the likely case the built-in was invoked with fewer
10969 : : than two arguments. */
10970 : 4 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
10971 : 4 : c_parser_consume_token (parser);
10972 : 4 : c_inhibit_evaluation_warnings--;
10973 : 4 : result.set_error ();
10974 : 4 : return result;
10975 : : }
10976 : :
10977 : 760 : bool save_translate_strings_p = parser->translate_strings_p;
10978 : :
10979 : 760 : location_t atloc = c_parser_peek_token (parser)->location;
10980 : : /* Parse a single attribute. Require no leading comma and do not
10981 : : allow empty attributes. */
10982 : 760 : tree attr = c_parser_gnu_attribute (parser, NULL_TREE, false, false);
10983 : :
10984 : 760 : parser->translate_strings_p = save_translate_strings_p;
10985 : :
10986 : 760 : location_t finish = c_parser_peek_token (parser)->location;
10987 : 760 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
10988 : 757 : c_parser_consume_token (parser);
10989 : : else
10990 : : {
10991 : 3 : c_parser_error (parser, "expected identifier");
10992 : 3 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
10993 : :
10994 : 3 : result.set_error ();
10995 : 3 : return result;
10996 : : }
10997 : :
10998 : 757 : if (!attr)
10999 : : {
11000 : 0 : error_at (atloc, "expected identifier");
11001 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11002 : : "expected %<)%>");
11003 : 0 : result.set_error ();
11004 : 0 : return result;
11005 : : }
11006 : :
11007 : 757 : result.original_code = INTEGER_CST;
11008 : 757 : result.original_type = boolean_type_node;
11009 : :
11010 : 757 : if (has_attribute (atloc, oper, attr, default_conversion))
11011 : 296 : result.value = boolean_true_node;
11012 : : else
11013 : 461 : result.value = boolean_false_node;
11014 : :
11015 : 757 : set_c_expr_source_range (&result, start, finish);
11016 : 757 : result.m_decimal = 0;
11017 : 757 : return result;
11018 : : }
11019 : :
11020 : : /* Helper function to read arguments of builtins which are interfaces
11021 : : for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
11022 : : others. The name of the builtin is passed using BNAME parameter.
11023 : : Function returns true if there were no errors while parsing and
11024 : : stores the arguments in CEXPR_LIST. If it returns true,
11025 : : *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
11026 : : parenthesis. */
11027 : : static bool
11028 : 1527720 : c_parser_get_builtin_args (c_parser *parser, const char *bname,
11029 : : vec<c_expr_t, va_gc> **ret_cexpr_list,
11030 : : bool choose_expr_p,
11031 : : location_t *out_close_paren_loc)
11032 : : {
11033 : 1527720 : location_t loc = c_parser_peek_token (parser)->location;
11034 : 1527720 : vec<c_expr_t, va_gc> *cexpr_list;
11035 : 1527720 : c_expr_t expr;
11036 : 1527720 : bool saved_force_folding_builtin_constant_p;
11037 : :
11038 : 1527720 : *ret_cexpr_list = NULL;
11039 : 1527720 : if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
11040 : : {
11041 : 1 : error_at (loc, "cannot take address of %qs", bname);
11042 : 1 : return false;
11043 : : }
11044 : :
11045 : 1527719 : c_parser_consume_token (parser);
11046 : :
11047 : 1527719 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11048 : : {
11049 : 18 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11050 : 18 : c_parser_consume_token (parser);
11051 : 18 : return true;
11052 : : }
11053 : :
11054 : 1527701 : saved_force_folding_builtin_constant_p
11055 : 1527701 : = force_folding_builtin_constant_p;
11056 : 1527701 : force_folding_builtin_constant_p |= choose_expr_p;
11057 : 1527701 : expr = c_parser_expr_no_commas (parser, NULL);
11058 : 1527701 : force_folding_builtin_constant_p
11059 : 1527701 : = saved_force_folding_builtin_constant_p;
11060 : 1527701 : vec_alloc (cexpr_list, 1);
11061 : 1527701 : vec_safe_push (cexpr_list, expr);
11062 : 17861303 : while (c_parser_next_token_is (parser, CPP_COMMA))
11063 : : {
11064 : 14805901 : c_parser_consume_token (parser);
11065 : 14805901 : if (c_parser_next_token_is (parser, CPP_EMBED))
11066 : : {
11067 : 2 : c_token *embed = c_parser_peek_token (parser);
11068 : 2 : tree value = embed->value;
11069 : 2 : expr.original_code = INTEGER_CST;
11070 : 2 : expr.original_type = integer_type_node;
11071 : 2 : expr.value = NULL_TREE;
11072 : 2 : set_c_expr_source_range (&expr, embed->get_range ());
11073 : 2 : expr.m_decimal = 0;
11074 : 510 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
11075 : : {
11076 : 1016 : expr.value = build_int_cst (integer_type_node,
11077 : 508 : RAW_DATA_UCHAR_ELT (value, i));
11078 : 508 : vec_safe_push (cexpr_list, expr);
11079 : : }
11080 : 2 : c_parser_consume_token (parser);
11081 : 2 : continue;
11082 : 2 : }
11083 : 14805899 : expr = c_parser_expr_no_commas (parser, NULL);
11084 : 14805899 : vec_safe_push (cexpr_list, expr);
11085 : : }
11086 : :
11087 : 1527701 : *out_close_paren_loc = c_parser_peek_token (parser)->location;
11088 : 1527701 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
11089 : : return false;
11090 : :
11091 : 1527701 : *ret_cexpr_list = cexpr_list;
11092 : 1527701 : return true;
11093 : : }
11094 : :
11095 : : /* This represents a single generic-association. */
11096 : :
11097 : : struct c_generic_association
11098 : : {
11099 : : /* The location of the starting token of the type. */
11100 : : location_t type_location;
11101 : : /* The association's type, or NULL_TREE for 'default'. */
11102 : : tree type;
11103 : : /* The association's expression. */
11104 : : struct c_expr expression;
11105 : : };
11106 : :
11107 : : /* Parse a generic-selection. (C11 6.5.1.1).
11108 : :
11109 : : generic-selection:
11110 : : _Generic ( generic-controlling-operand , generic-assoc-list )
11111 : :
11112 : : generic-controlling-operand:
11113 : : assignment-expression
11114 : : type-name
11115 : :
11116 : : (The use of a type-name is new in C2Y.)
11117 : :
11118 : : generic-assoc-list:
11119 : : generic-association
11120 : : generic-assoc-list , generic-association
11121 : :
11122 : : generic-association:
11123 : : type-name : assignment-expression
11124 : : default : assignment-expression
11125 : : */
11126 : :
11127 : : static struct c_expr
11128 : 622 : c_parser_generic_selection (c_parser *parser)
11129 : : {
11130 : 622 : struct c_expr selector, error_expr;
11131 : 622 : tree selector_type;
11132 : 622 : struct c_generic_association matched_assoc;
11133 : 622 : int match_found = -1;
11134 : 622 : location_t generic_loc, selector_loc;
11135 : :
11136 : 622 : error_expr.original_code = ERROR_MARK;
11137 : 622 : error_expr.original_type = NULL;
11138 : 622 : error_expr.set_error ();
11139 : 622 : matched_assoc.type_location = UNKNOWN_LOCATION;
11140 : 622 : matched_assoc.type = NULL_TREE;
11141 : 622 : matched_assoc.expression = error_expr;
11142 : :
11143 : 622 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
11144 : 622 : generic_loc = c_parser_peek_token (parser)->location;
11145 : 622 : c_parser_consume_token (parser);
11146 : 622 : if (flag_isoc99)
11147 : 620 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11148 : : "ISO C99 does not support %<_Generic%>");
11149 : : else
11150 : 2 : pedwarn_c99 (generic_loc, OPT_Wpedantic,
11151 : : "ISO C90 does not support %<_Generic%>");
11152 : :
11153 : 622 : matching_parens parens;
11154 : 622 : if (!parens.require_open (parser))
11155 : 0 : return error_expr;
11156 : :
11157 : 622 : selector_loc = c_parser_peek_token (parser)->location;
11158 : 622 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
11159 : : {
11160 : 31 : c_inhibit_evaluation_warnings++;
11161 : 31 : pedwarn_c23 (selector_loc, OPT_Wpedantic,
11162 : : "ISO C does not support use of type name as %<_Generic%> "
11163 : : "controlling operand before C2Y");
11164 : 31 : struct c_type_name *type = c_parser_type_name (parser);
11165 : 31 : if (type)
11166 : 30 : selector_type = groktypename (type, NULL, NULL);
11167 : 31 : c_inhibit_evaluation_warnings--;
11168 : 31 : if (!type)
11169 : : {
11170 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11171 : 1 : return error_expr;
11172 : : }
11173 : : }
11174 : : else
11175 : : {
11176 : 591 : c_inhibit_evaluation_warnings++;
11177 : 591 : selector = c_parser_expr_no_commas (parser, NULL);
11178 : 591 : selector = default_function_array_conversion (selector_loc, selector);
11179 : 591 : c_inhibit_evaluation_warnings--;
11180 : :
11181 : 591 : if (selector.value == error_mark_node)
11182 : : {
11183 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11184 : 0 : return selector;
11185 : : }
11186 : 591 : mark_exp_read (selector.value);
11187 : 591 : selector_type = TREE_TYPE (selector.value);
11188 : : /* In ISO C terms, rvalues (including the controlling expression
11189 : : of _Generic) do not have qualified types. */
11190 : 591 : if (TREE_CODE (selector_type) != ARRAY_TYPE)
11191 : 591 : selector_type = TYPE_MAIN_VARIANT (selector_type);
11192 : : /* In ISO C terms, _Noreturn is not part of the type of expressions
11193 : : such as &abort, but in GCC it is represented internally as a type
11194 : : qualifier. */
11195 : 58 : if (FUNCTION_POINTER_TYPE_P (selector_type)
11196 : 595 : && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
11197 : 1 : selector_type
11198 : 1 : = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
11199 : : }
11200 : :
11201 : 621 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11202 : : {
11203 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11204 : 0 : return error_expr;
11205 : : }
11206 : :
11207 : 621 : auto_vec<c_generic_association> associations;
11208 : 1779 : while (1)
11209 : : {
11210 : 1200 : struct c_generic_association assoc, *iter;
11211 : 1200 : unsigned int ix;
11212 : 1200 : c_token *token = c_parser_peek_token (parser);
11213 : :
11214 : 1200 : assoc.type_location = token->location;
11215 : 1200 : if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
11216 : : {
11217 : 476 : c_parser_consume_token (parser);
11218 : 476 : assoc.type = NULL_TREE;
11219 : : }
11220 : : else
11221 : : {
11222 : 724 : struct c_type_name *type_name;
11223 : :
11224 : 724 : type_name = c_parser_type_name (parser);
11225 : 724 : if (type_name == NULL)
11226 : : {
11227 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11228 : 1 : return error_expr;
11229 : : }
11230 : 723 : assoc.type = groktypename (type_name, NULL, NULL);
11231 : 723 : if (assoc.type == error_mark_node)
11232 : : {
11233 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11234 : 0 : return error_expr;
11235 : : }
11236 : :
11237 : 723 : if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
11238 : 9 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11239 : : "ISO C does not support %<_Generic%> association with "
11240 : : "function type before C2Y");
11241 : 714 : else if (!COMPLETE_TYPE_P (assoc.type))
11242 : 13 : pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11243 : : "ISO C does not support %<_Generic%> association with "
11244 : : "incomplete type before C2Y");
11245 : :
11246 : 723 : if (c_type_variably_modified_p (assoc.type))
11247 : 2 : error_at (assoc.type_location,
11248 : : "%<_Generic%> association has "
11249 : : "variable length type");
11250 : : }
11251 : :
11252 : 1199 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
11253 : : {
11254 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11255 : 0 : return error_expr;
11256 : : }
11257 : :
11258 : 1199 : bool match = assoc.type == NULL_TREE
11259 : 1199 : || comptypes (assoc.type, selector_type);
11260 : :
11261 : 147 : if (!match)
11262 : 147 : c_inhibit_evaluation_warnings++;
11263 : :
11264 : 1199 : assoc.expression = c_parser_expr_no_commas (parser, NULL);
11265 : :
11266 : 1199 : if (!match)
11267 : 147 : c_inhibit_evaluation_warnings--;
11268 : :
11269 : 1199 : if (assoc.expression.value == error_mark_node)
11270 : : {
11271 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11272 : 0 : return error_expr;
11273 : : }
11274 : :
11275 : 1892 : for (ix = 0; associations.iterate (ix, &iter); ++ix)
11276 : : {
11277 : 693 : if (assoc.type == NULL_TREE)
11278 : : {
11279 : 190 : if (iter->type == NULL_TREE)
11280 : : {
11281 : 1 : error_at (assoc.type_location,
11282 : : "duplicate %<default%> case in %<_Generic%>");
11283 : 1 : inform (iter->type_location, "original %<default%> is here");
11284 : : }
11285 : : }
11286 : 503 : else if (iter->type != NULL_TREE)
11287 : : {
11288 : 169 : if (comptypes (assoc.type, iter->type))
11289 : : {
11290 : 1 : error_at (assoc.type_location,
11291 : : "%<_Generic%> specifies two compatible types");
11292 : 1 : inform (iter->type_location, "compatible type is here");
11293 : : }
11294 : : }
11295 : : }
11296 : :
11297 : 1199 : if (assoc.type == NULL_TREE)
11298 : : {
11299 : 476 : if (match_found < 0)
11300 : : {
11301 : 333 : matched_assoc = assoc;
11302 : 364 : match_found = associations.length ();
11303 : : }
11304 : : }
11305 : 723 : else if (match)
11306 : : {
11307 : 576 : if (match_found < 0 || matched_assoc.type == NULL_TREE)
11308 : : {
11309 : 576 : matched_assoc = assoc;
11310 : 906 : match_found = associations.length ();
11311 : : }
11312 : : else
11313 : : {
11314 : 0 : error_at (assoc.type_location,
11315 : : "%<_Generic%> selector matches multiple associations");
11316 : 0 : inform (matched_assoc.type_location,
11317 : : "other match is here");
11318 : : }
11319 : : }
11320 : :
11321 : 1199 : associations.safe_push (assoc);
11322 : :
11323 : 1199 : if (c_parser_peek_token (parser)->type != CPP_COMMA)
11324 : : break;
11325 : 579 : c_parser_consume_token (parser);
11326 : 579 : }
11327 : :
11328 : 620 : unsigned int ix;
11329 : 620 : struct c_generic_association *iter;
11330 : 1818 : FOR_EACH_VEC_ELT (associations, ix, iter)
11331 : 1198 : if (ix != (unsigned) match_found)
11332 : 582 : mark_exp_read (iter->expression.value);
11333 : :
11334 : 620 : if (!parens.require_close (parser))
11335 : : {
11336 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11337 : 0 : return error_expr;
11338 : : }
11339 : :
11340 : 620 : if (match_found < 0)
11341 : : {
11342 : 4 : error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
11343 : : "compatible with any association",
11344 : : selector_type);
11345 : 4 : return error_expr;
11346 : : }
11347 : :
11348 : 616 : return matched_assoc.expression;
11349 : 621 : }
11350 : :
11351 : : /* Check the validity of a function pointer argument *EXPR (argument
11352 : : position POS) to __builtin_tgmath. Return the number of function
11353 : : arguments if possibly valid; return 0 having reported an error if
11354 : : not valid. */
11355 : :
11356 : : static unsigned int
11357 : 1755 : check_tgmath_function (c_expr *expr, unsigned int pos)
11358 : : {
11359 : 1755 : tree type = TREE_TYPE (expr->value);
11360 : 1755 : if (!FUNCTION_POINTER_TYPE_P (type))
11361 : : {
11362 : 2 : error_at (expr->get_location (),
11363 : : "argument %u of %<__builtin_tgmath%> is not a function pointer",
11364 : : pos);
11365 : 2 : return 0;
11366 : : }
11367 : 1753 : type = TREE_TYPE (type);
11368 : 1753 : if (!prototype_p (type))
11369 : : {
11370 : 2 : error_at (expr->get_location (),
11371 : : "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
11372 : 2 : return 0;
11373 : : }
11374 : 1751 : if (stdarg_p (type))
11375 : : {
11376 : 2 : error_at (expr->get_location (),
11377 : : "argument %u of %<__builtin_tgmath%> has variable arguments",
11378 : : pos);
11379 : 2 : return 0;
11380 : : }
11381 : 1749 : unsigned int nargs = 0;
11382 : 1749 : function_args_iterator iter;
11383 : 1749 : tree t;
11384 : 4176 : FOREACH_FUNCTION_ARGS (type, t, iter)
11385 : : {
11386 : 4176 : if (t == void_type_node)
11387 : : break;
11388 : 2427 : nargs++;
11389 : : }
11390 : 1749 : if (nargs == 0)
11391 : : {
11392 : 2 : error_at (expr->get_location (),
11393 : : "argument %u of %<__builtin_tgmath%> has no arguments", pos);
11394 : 2 : return 0;
11395 : : }
11396 : : return nargs;
11397 : : }
11398 : :
11399 : : /* Ways in which a parameter or return value of a type-generic macro
11400 : : may vary between the different functions the macro may call. */
11401 : : enum tgmath_parm_kind
11402 : : {
11403 : : tgmath_fixed, tgmath_real, tgmath_complex
11404 : : };
11405 : :
11406 : : /* Helper function for c_parser_postfix_expression. Parse predefined
11407 : : identifiers. */
11408 : :
11409 : : static struct c_expr
11410 : 13087 : c_parser_predefined_identifier (c_parser *parser)
11411 : : {
11412 : 13087 : location_t loc = c_parser_peek_token (parser)->location;
11413 : 13087 : switch (c_parser_peek_token (parser)->keyword)
11414 : : {
11415 : 709 : case RID_FUNCTION_NAME:
11416 : 709 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11417 : : "identifier", "__FUNCTION__");
11418 : 709 : break;
11419 : 6111 : case RID_PRETTY_FUNCTION_NAME:
11420 : 6111 : pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11421 : : "identifier", "__PRETTY_FUNCTION__");
11422 : 6111 : break;
11423 : 6267 : case RID_C99_FUNCTION_NAME:
11424 : 6267 : pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
11425 : : "%<__func__%> predefined identifier");
11426 : 6267 : break;
11427 : 0 : default:
11428 : 0 : gcc_unreachable ();
11429 : : }
11430 : :
11431 : 13087 : struct c_expr expr;
11432 : 13087 : expr.original_code = ERROR_MARK;
11433 : 13087 : expr.original_type = NULL;
11434 : 13087 : expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
11435 : 13087 : c_parser_peek_token (parser)->value);
11436 : 13087 : set_c_expr_source_range (&expr, loc, loc);
11437 : 13087 : expr.m_decimal = 0;
11438 : 13087 : c_parser_consume_token (parser);
11439 : 13087 : return expr;
11440 : : }
11441 : :
11442 : : /* Check whether the ARRAY_REF has an counted-by object associated with it
11443 : : through the "counted_by" attribute. */
11444 : :
11445 : : static bool
11446 : 40 : has_counted_by_object (tree array_ref)
11447 : : {
11448 : : /* Currently, only when the array_ref is an indirect_ref to a call to the
11449 : : .ACCESS_WITH_SIZE, return true.
11450 : : More cases can be included later when the counted_by attribute is
11451 : : extended to other situations. */
11452 : 40 : if (TREE_CODE (array_ref) == INDIRECT_REF
11453 : 40 : && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11454 : : return true;
11455 : : return false;
11456 : : }
11457 : :
11458 : : /* Get the reference to the counted-by object associated with the ARRAY_REF. */
11459 : :
11460 : : static tree
11461 : 25 : get_counted_by_ref (tree array_ref)
11462 : : {
11463 : : /* Currently, only when the array_ref is an indirect_ref to a call to the
11464 : : .ACCESS_WITH_SIZE, get the corresponding counted_by ref.
11465 : : More cases can be included later when the counted_by attribute is
11466 : : extended to other situations. */
11467 : 25 : if (TREE_CODE (array_ref) == INDIRECT_REF
11468 : 25 : && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11469 : 25 : return CALL_EXPR_ARG (TREE_OPERAND (array_ref, 0), 1);
11470 : : return NULL_TREE;
11471 : : }
11472 : :
11473 : : /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
11474 : : C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
11475 : : call c_parser_postfix_expression_after_paren_type on encountering them.
11476 : :
11477 : : postfix-expression:
11478 : : primary-expression
11479 : : postfix-expression [ expression ]
11480 : : postfix-expression ( argument-expression-list[opt] )
11481 : : postfix-expression . identifier
11482 : : postfix-expression -> identifier
11483 : : postfix-expression ++
11484 : : postfix-expression --
11485 : : ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
11486 : : ( storage-class-specifiers[opt] type-name ) { initializer-list , }
11487 : :
11488 : : argument-expression-list:
11489 : : argument-expression
11490 : : argument-expression-list , argument-expression
11491 : :
11492 : : primary-expression:
11493 : : identifier
11494 : : constant
11495 : : string-literal
11496 : : ( expression )
11497 : : generic-selection
11498 : :
11499 : : GNU extensions:
11500 : :
11501 : : primary-expression:
11502 : : __func__
11503 : : (treated as a keyword in GNU C)
11504 : : __FUNCTION__
11505 : : __PRETTY_FUNCTION__
11506 : : ( compound-statement )
11507 : : __builtin_va_arg ( assignment-expression , type-name )
11508 : : __builtin_offsetof ( type-name , offsetof-member-designator )
11509 : : __builtin_choose_expr ( assignment-expression ,
11510 : : assignment-expression ,
11511 : : assignment-expression )
11512 : : __builtin_types_compatible_p ( type-name , type-name )
11513 : : __builtin_tgmath ( expr-list )
11514 : : __builtin_complex ( assignment-expression , assignment-expression )
11515 : : __builtin_shuffle ( assignment-expression , assignment-expression )
11516 : : __builtin_shuffle ( assignment-expression ,
11517 : : assignment-expression ,
11518 : : assignment-expression, )
11519 : : __builtin_convertvector ( assignment-expression , type-name )
11520 : : __builtin_assoc_barrier ( assignment-expression )
11521 : :
11522 : : offsetof-member-designator:
11523 : : identifier
11524 : : offsetof-member-designator . identifier
11525 : : offsetof-member-designator [ expression ]
11526 : :
11527 : : Objective-C:
11528 : :
11529 : : primary-expression:
11530 : : [ objc-receiver objc-message-args ]
11531 : : @selector ( objc-selector-arg )
11532 : : @protocol ( identifier )
11533 : : @encode ( type-name )
11534 : : objc-string-literal
11535 : : Classname . identifier
11536 : : */
11537 : :
11538 : : static struct c_expr
11539 : 230679614 : c_parser_postfix_expression (c_parser *parser)
11540 : : {
11541 : 230679614 : struct c_expr expr, e1;
11542 : 230679614 : struct c_type_name *t1, *t2;
11543 : 230679614 : location_t loc = c_parser_peek_token (parser)->location;
11544 : 230679614 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
11545 : 230679614 : expr.original_code = ERROR_MARK;
11546 : 230679614 : expr.original_type = NULL;
11547 : 230679614 : expr.m_decimal = 0;
11548 : 230679614 : switch (c_parser_peek_token (parser)->type)
11549 : : {
11550 : 49870746 : case CPP_NUMBER:
11551 : 49870746 : expr.value = c_parser_peek_token (parser)->value;
11552 : 49870746 : set_c_expr_source_range (&expr, tok_range);
11553 : 49870746 : loc = c_parser_peek_token (parser)->location;
11554 : 49870746 : expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
11555 : 49870746 : c_parser_consume_token (parser);
11556 : 49870746 : if (TREE_CODE (expr.value) == FIXED_CST
11557 : 49870746 : && !targetm.fixed_point_supported_p ())
11558 : : {
11559 : 6 : error_at (loc, "fixed-point types not supported for this target");
11560 : 6 : expr.set_error ();
11561 : : }
11562 : : break;
11563 : 113067 : case CPP_CHAR:
11564 : 113067 : case CPP_CHAR16:
11565 : 113067 : case CPP_CHAR32:
11566 : 113067 : case CPP_UTF8CHAR:
11567 : 113067 : case CPP_WCHAR:
11568 : 113067 : expr.value = c_parser_peek_token (parser)->value;
11569 : : /* For the purpose of warning when a pointer is compared with
11570 : : a zero character constant. */
11571 : 113067 : expr.original_type = char_type_node;
11572 : 113067 : set_c_expr_source_range (&expr, tok_range);
11573 : 113067 : c_parser_consume_token (parser);
11574 : 113067 : break;
11575 : 1153119 : case CPP_STRING:
11576 : 1153119 : case CPP_STRING16:
11577 : 1153119 : case CPP_STRING32:
11578 : 1153119 : case CPP_WSTRING:
11579 : 1153119 : case CPP_UTF8STRING:
11580 : 1153119 : expr = c_parser_string_literal (parser, parser->translate_strings_p,
11581 : : true);
11582 : 1153119 : break;
11583 : 0 : case CPP_OBJC_STRING:
11584 : 0 : gcc_assert (c_dialect_objc ());
11585 : 0 : expr.value
11586 : 0 : = objc_build_string_object (c_parser_peek_token (parser)->value);
11587 : 0 : set_c_expr_source_range (&expr, tok_range);
11588 : 0 : c_parser_consume_token (parser);
11589 : 0 : break;
11590 : 170541628 : case CPP_NAME:
11591 : 170541628 : switch (c_parser_peek_token (parser)->id_kind)
11592 : : {
11593 : 170541626 : case C_ID_ID:
11594 : 170541626 : {
11595 : 170541626 : tree id = c_parser_peek_token (parser)->value;
11596 : 170541626 : c_parser_consume_token (parser);
11597 : 511624878 : expr.value = build_external_ref (loc, id,
11598 : 170541626 : (c_parser_peek_token (parser)->type
11599 : : == CPP_OPEN_PAREN),
11600 : : &expr.original_type);
11601 : 170541626 : set_c_expr_source_range (&expr, tok_range);
11602 : 170541626 : break;
11603 : : }
11604 : 0 : case C_ID_CLASSNAME:
11605 : 0 : {
11606 : : /* Here we parse the Objective-C 2.0 Class.name dot
11607 : : syntax. */
11608 : 0 : tree class_name = c_parser_peek_token (parser)->value;
11609 : 0 : tree component;
11610 : 0 : c_parser_consume_token (parser);
11611 : 0 : gcc_assert (c_dialect_objc ());
11612 : 0 : if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
11613 : : {
11614 : 0 : expr.set_error ();
11615 : 0 : break;
11616 : : }
11617 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
11618 : : {
11619 : 0 : c_parser_error (parser, "expected identifier");
11620 : 0 : expr.set_error ();
11621 : 0 : break;
11622 : : }
11623 : 0 : c_token *component_tok = c_parser_peek_token (parser);
11624 : 0 : component = component_tok->value;
11625 : 0 : location_t end_loc = component_tok->get_finish ();
11626 : 0 : c_parser_consume_token (parser);
11627 : 0 : expr.value = objc_build_class_component_ref (class_name,
11628 : : component);
11629 : 0 : set_c_expr_source_range (&expr, loc, end_loc);
11630 : 0 : break;
11631 : : }
11632 : 2 : default:
11633 : 2 : c_parser_error (parser, "expected expression");
11634 : 2 : expr.set_error ();
11635 : 2 : break;
11636 : : }
11637 : : break;
11638 : 7401633 : case CPP_OPEN_PAREN:
11639 : : /* A parenthesized expression, statement expression or compound
11640 : : literal. */
11641 : 7401633 : if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
11642 : : {
11643 : : /* A statement expression. */
11644 : 34749 : tree stmt;
11645 : 34749 : location_t brace_loc;
11646 : 34749 : bool save_c_omp_array_section_p = c_omp_array_section_p;
11647 : 34749 : c_parser_consume_token (parser);
11648 : 34749 : brace_loc = c_parser_peek_token (parser)->location;
11649 : 34749 : c_parser_consume_token (parser);
11650 : : /* If we've not yet started the current function's statement list,
11651 : : or we're in the parameter scope of an old-style function
11652 : : declaration, statement expressions are not allowed. */
11653 : 34749 : if (!building_stmt_list_p () || old_style_parameter_scope ())
11654 : : {
11655 : 24 : error_at (loc, "braced-group within expression allowed "
11656 : : "only inside a function");
11657 : 24 : parser->error = true;
11658 : 24 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
11659 : 24 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11660 : 24 : expr.set_error ();
11661 : 24 : break;
11662 : : }
11663 : 34725 : c_omp_array_section_p = false;
11664 : 34725 : stmt = c_begin_stmt_expr ();
11665 : 34725 : c_parser_compound_statement_nostart (parser);
11666 : 34725 : location_t close_loc = c_parser_peek_token (parser)->location;
11667 : 34725 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11668 : : "expected %<)%>");
11669 : 34725 : pedwarn (loc, OPT_Wpedantic,
11670 : : "ISO C forbids braced-groups within expressions");
11671 : 34725 : expr.value = c_finish_stmt_expr (brace_loc, stmt);
11672 : 34725 : set_c_expr_source_range (&expr, loc, close_loc);
11673 : 34725 : mark_exp_read (expr.value);
11674 : 34725 : c_omp_array_section_p = save_c_omp_array_section_p;
11675 : : }
11676 : : else
11677 : : {
11678 : : /* A parenthesized expression. */
11679 : 7366884 : location_t loc_open_paren = c_parser_peek_token (parser)->location;
11680 : 7366884 : c_parser_consume_token (parser);
11681 : 7366884 : expr = c_parser_expression (parser);
11682 : 7366884 : if (TREE_CODE (expr.value) == MODIFY_EXPR)
11683 : 37728 : suppress_warning (expr.value, OPT_Wparentheses);
11684 : 7366884 : if (expr.original_code != C_MAYBE_CONST_EXPR
11685 : 7366872 : && expr.original_code != SIZEOF_EXPR)
11686 : 7361994 : expr.original_code = ERROR_MARK;
11687 : : /* Remember that we saw ( ) around the sizeof. */
11688 : 7366884 : if (expr.original_code == SIZEOF_EXPR)
11689 : 4878 : expr.original_code = PAREN_SIZEOF_EXPR;
11690 : : /* Don't change EXPR.ORIGINAL_TYPE. */
11691 : 7366884 : location_t loc_close_paren = c_parser_peek_token (parser)->location;
11692 : 7366884 : set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
11693 : 7366884 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11694 : : "expected %<)%>", loc_open_paren);
11695 : : }
11696 : : break;
11697 : 1598628 : case CPP_KEYWORD:
11698 : 1598628 : switch (c_parser_peek_token (parser)->keyword)
11699 : : {
11700 : 13067 : case RID_FUNCTION_NAME:
11701 : 13067 : case RID_PRETTY_FUNCTION_NAME:
11702 : 13067 : case RID_C99_FUNCTION_NAME:
11703 : 13067 : expr = c_parser_predefined_identifier (parser);
11704 : 13067 : break;
11705 : 19894 : case RID_VA_ARG:
11706 : 19894 : {
11707 : 19894 : location_t start_loc = loc;
11708 : 19894 : c_parser_consume_token (parser);
11709 : 19894 : matching_parens parens;
11710 : 19894 : if (!parens.require_open (parser))
11711 : : {
11712 : 0 : expr.set_error ();
11713 : 0 : break;
11714 : : }
11715 : 19894 : e1 = c_parser_expr_no_commas (parser, NULL);
11716 : 19894 : mark_exp_read (e1.value);
11717 : 19894 : e1.value = c_fully_fold (e1.value, false, NULL);
11718 : 19894 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11719 : : {
11720 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11721 : 0 : expr.set_error ();
11722 : 0 : break;
11723 : : }
11724 : 19894 : loc = c_parser_peek_token (parser)->location;
11725 : 19894 : t1 = c_parser_type_name (parser);
11726 : 19894 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11727 : 19894 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11728 : : "expected %<)%>");
11729 : 19894 : if (t1 == NULL)
11730 : : {
11731 : 0 : expr.set_error ();
11732 : : }
11733 : : else
11734 : : {
11735 : 19894 : tree type_expr = NULL_TREE;
11736 : 19894 : expr.value = c_build_va_arg (start_loc, e1.value, loc,
11737 : : groktypename (t1, &type_expr, NULL));
11738 : 19894 : if (type_expr)
11739 : : {
11740 : 24 : expr.value = build2 (C_MAYBE_CONST_EXPR,
11741 : 24 : TREE_TYPE (expr.value), type_expr,
11742 : : expr.value);
11743 : 24 : C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
11744 : : }
11745 : 19894 : set_c_expr_source_range (&expr, start_loc, end_loc);
11746 : : }
11747 : : }
11748 : 19894 : break;
11749 : 13587 : case RID_C23_VA_START:
11750 : 13587 : {
11751 : 13587 : c_parser_consume_token (parser);
11752 : 13587 : matching_parens parens;
11753 : 13587 : if (!parens.require_open (parser))
11754 : : {
11755 : 0 : expr.set_error ();
11756 : 0 : break;
11757 : : }
11758 : 13587 : e1 = c_parser_expr_no_commas (parser, NULL);
11759 : 13587 : e1 = convert_lvalue_to_rvalue (e1.get_location (), e1, true, true);
11760 : 13587 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11761 : : {
11762 : 13409 : location_t cloc = c_parser_peek_token (parser)->location;
11763 : 13409 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11764 : : {
11765 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11766 : 0 : expr.set_error ();
11767 : 0 : break;
11768 : : }
11769 : 13409 : if (c_parser_next_token_is (parser, CPP_NAME)
11770 : 13404 : && c_parser_peek_token (parser)->id_kind == C_ID_ID
11771 : 26813 : && (c_parser_peek_2nd_token (parser)->type
11772 : : == CPP_CLOSE_PAREN))
11773 : : {
11774 : 13383 : tree name = c_parser_peek_token (parser)->value;
11775 : 13383 : location_t nloc = c_parser_peek_token (parser)->location;
11776 : 13383 : tree decl = lookup_name (name);
11777 : 13383 : tree last_parm
11778 : 13383 : = tree_last (DECL_ARGUMENTS (current_function_decl));
11779 : 13383 : if (!last_parm || decl != last_parm)
11780 : 4 : warning_at (nloc, OPT_Wvarargs,
11781 : : "optional second parameter of %<va_start%> "
11782 : : "not last named argument");
11783 : 13379 : else if (DECL_REGISTER (decl))
11784 : 2 : warning_at (nloc, OPT_Wvarargs,
11785 : : "undefined behavior when second parameter "
11786 : : "of %<va_start%> is declared with "
11787 : : "%<register%> storage");
11788 : 13383 : c_parser_consume_token (parser);
11789 : : }
11790 : : else
11791 : : {
11792 : 26 : unsigned nesting_depth = 0;
11793 : 26 : location_t sloc = c_parser_peek_token (parser)->location;
11794 : 26 : location_t eloc = sloc;
11795 : :
11796 : : /* For va_start (ap,) the ) comes from stdarg.h.
11797 : : Use location of , in that case, otherwise without
11798 : : -Wsystem-headers nothing is reported. After all,
11799 : : the problematic token is the comma in that case. */
11800 : 26 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
11801 : 1 : sloc = eloc = cloc;
11802 : 492 : while (true)
11803 : : {
11804 : 259 : c_token *token = c_parser_peek_token (parser);
11805 : 259 : if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
11806 : : break;
11807 : :
11808 : 233 : if (token->type == CPP_EOF)
11809 : : break;
11810 : 233 : if (token->type == CPP_OPEN_PAREN)
11811 : 8 : ++nesting_depth;
11812 : 225 : else if (token->type == CPP_CLOSE_PAREN)
11813 : 8 : --nesting_depth;
11814 : 233 : eloc = token->location;
11815 : 233 : c_parser_consume_token (parser);
11816 : 233 : }
11817 : 26 : if (sloc != eloc)
11818 : 25 : sloc = make_location (sloc, sloc, eloc);
11819 : 26 : warning_at (sloc, OPT_Wvarargs,
11820 : : "%<va_start%> macro used with additional "
11821 : : "arguments other than identifier of the "
11822 : : "last named argument");
11823 : : }
11824 : : }
11825 : 13587 : parens.skip_until_found_close (parser);
11826 : 13587 : tree fndecl = builtin_decl_explicit (BUILT_IN_VA_START);
11827 : 13587 : vec<tree, va_gc> *params;
11828 : 13587 : vec_alloc (params, 2);
11829 : 13587 : params->quick_push (e1.value);
11830 : 13587 : params->quick_push (integer_zero_node);
11831 : 13587 : auto_vec<location_t> arg_loc (2);
11832 : 13587 : arg_loc.quick_push (e1.get_location ());
11833 : 13587 : arg_loc.quick_push (UNKNOWN_LOCATION);
11834 : 13587 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
11835 : : params, NULL);
11836 : 13587 : set_c_expr_source_range (&expr, loc,
11837 : : parser->tokens_buf[0].get_finish ());
11838 : 13587 : expr.m_decimal = 0;
11839 : 13587 : expr.original_code = ERROR_MARK;
11840 : 13587 : expr.original_type = NULL;
11841 : 13587 : release_tree_vector (params);
11842 : 13587 : break;
11843 : 13587 : }
11844 : 3612 : case RID_OFFSETOF:
11845 : 3612 : {
11846 : 3612 : c_parser_consume_token (parser);
11847 : 3612 : matching_parens parens;
11848 : 3612 : if (!parens.require_open (parser))
11849 : : {
11850 : 0 : expr.set_error ();
11851 : 1 : break;
11852 : : }
11853 : 3612 : t1 = c_parser_type_name (parser);
11854 : 3612 : if (t1 == NULL)
11855 : 0 : parser->error = true;
11856 : 3612 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11857 : 1 : gcc_assert (parser->error);
11858 : 3612 : if (parser->error)
11859 : : {
11860 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
11861 : 1 : expr.set_error ();
11862 : 1 : break;
11863 : : }
11864 : 3611 : tree type = groktypename (t1, NULL, NULL);
11865 : 3611 : tree offsetof_ref;
11866 : 3611 : if (type == error_mark_node)
11867 : : offsetof_ref = error_mark_node;
11868 : : else
11869 : : {
11870 : 3610 : offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
11871 : 3610 : SET_EXPR_LOCATION (offsetof_ref, loc);
11872 : : }
11873 : : /* Parse the second argument to __builtin_offsetof. We
11874 : : must have one identifier, and beyond that we want to
11875 : : accept sub structure and sub array references. */
11876 : 3611 : if (c_parser_next_token_is (parser, CPP_NAME))
11877 : : {
11878 : 3611 : c_token *comp_tok = c_parser_peek_token (parser);
11879 : 3611 : offsetof_ref
11880 : 3611 : = build_component_ref (loc, offsetof_ref, comp_tok->value,
11881 : : comp_tok->location, UNKNOWN_LOCATION);
11882 : 3611 : c_parser_consume_token (parser);
11883 : 3611 : while (c_parser_next_token_is (parser, CPP_DOT)
11884 : 4069 : || c_parser_next_token_is (parser,
11885 : : CPP_OPEN_SQUARE)
11886 : 7919 : || c_parser_next_token_is (parser,
11887 : : CPP_DEREF))
11888 : : {
11889 : 696 : if (c_parser_next_token_is (parser, CPP_DEREF))
11890 : : {
11891 : 1 : loc = c_parser_peek_token (parser)->location;
11892 : 1 : offsetof_ref = build_array_ref (loc,
11893 : : offsetof_ref,
11894 : : integer_zero_node);
11895 : 1 : goto do_dot;
11896 : : }
11897 : 695 : else if (c_parser_next_token_is (parser, CPP_DOT))
11898 : : {
11899 : 238 : do_dot:
11900 : 239 : c_parser_consume_token (parser);
11901 : 239 : if (c_parser_next_token_is_not (parser,
11902 : : CPP_NAME))
11903 : : {
11904 : 0 : c_parser_error (parser, "expected identifier");
11905 : 0 : break;
11906 : : }
11907 : 239 : c_token *comp_tok = c_parser_peek_token (parser);
11908 : 239 : offsetof_ref
11909 : 239 : = build_component_ref (loc, offsetof_ref,
11910 : : comp_tok->value,
11911 : : comp_tok->location,
11912 : : UNKNOWN_LOCATION);
11913 : 239 : c_parser_consume_token (parser);
11914 : : }
11915 : : else
11916 : : {
11917 : 457 : struct c_expr ce;
11918 : 457 : tree idx;
11919 : 457 : loc = c_parser_peek_token (parser)->location;
11920 : 457 : c_parser_consume_token (parser);
11921 : 457 : ce = c_parser_expression (parser);
11922 : 457 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
11923 : 457 : idx = ce.value;
11924 : 457 : idx = c_fully_fold (idx, false, NULL);
11925 : 457 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
11926 : : "expected %<]%>");
11927 : 457 : offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
11928 : : }
11929 : : }
11930 : : }
11931 : : else
11932 : 0 : c_parser_error (parser, "expected identifier");
11933 : 3611 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11934 : 3611 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
11935 : : "expected %<)%>");
11936 : 3611 : expr.value = fold_offsetof (offsetof_ref);
11937 : 3611 : set_c_expr_source_range (&expr, loc, end_loc);
11938 : : }
11939 : 3611 : break;
11940 : 1233 : case RID_CHOOSE_EXPR:
11941 : 1233 : {
11942 : 1233 : vec<c_expr_t, va_gc> *cexpr_list;
11943 : 1233 : c_expr_t *e1_p, *e2_p, *e3_p;
11944 : 1233 : tree c;
11945 : 1233 : location_t close_paren_loc;
11946 : :
11947 : 1233 : c_parser_consume_token (parser);
11948 : 1233 : if (!c_parser_get_builtin_args (parser,
11949 : : "__builtin_choose_expr",
11950 : : &cexpr_list, true,
11951 : : &close_paren_loc))
11952 : : {
11953 : 0 : expr.set_error ();
11954 : 0 : break;
11955 : : }
11956 : :
11957 : 1233 : if (vec_safe_length (cexpr_list) != 3)
11958 : : {
11959 : 0 : error_at (loc, "wrong number of arguments to "
11960 : : "%<__builtin_choose_expr%>");
11961 : 0 : expr.set_error ();
11962 : 0 : break;
11963 : : }
11964 : :
11965 : 1233 : e1_p = &(*cexpr_list)[0];
11966 : 1233 : e2_p = &(*cexpr_list)[1];
11967 : 1233 : e3_p = &(*cexpr_list)[2];
11968 : :
11969 : 1233 : c = e1_p->value;
11970 : 1233 : mark_exp_read (e2_p->value);
11971 : 1233 : mark_exp_read (e3_p->value);
11972 : 1233 : if (TREE_CODE (c) != INTEGER_CST
11973 : 1233 : || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
11974 : 7 : error_at (loc,
11975 : : "first argument to %<__builtin_choose_expr%> not"
11976 : : " a constant");
11977 : 1233 : constant_expression_warning (c);
11978 : 1233 : expr = integer_zerop (c) ? *e3_p : *e2_p;
11979 : 1233 : set_c_expr_source_range (&expr, loc, close_paren_loc);
11980 : 1233 : break;
11981 : : }
11982 : 700 : case RID_TYPES_COMPATIBLE_P:
11983 : 700 : {
11984 : 700 : c_parser_consume_token (parser);
11985 : 700 : matching_parens parens;
11986 : 700 : if (!parens.require_open (parser))
11987 : : {
11988 : 0 : expr.set_error ();
11989 : 2 : break;
11990 : : }
11991 : 700 : t1 = c_parser_type_name (parser);
11992 : 700 : if (t1 == NULL)
11993 : : {
11994 : 0 : expr.set_error ();
11995 : 0 : break;
11996 : : }
11997 : 700 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
11998 : : {
11999 : 1 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
12000 : 1 : expr.set_error ();
12001 : 1 : break;
12002 : : }
12003 : 699 : t2 = c_parser_type_name (parser);
12004 : 699 : if (t2 == NULL)
12005 : : {
12006 : 0 : expr.set_error ();
12007 : 0 : break;
12008 : : }
12009 : 699 : location_t close_paren_loc = c_parser_peek_token (parser)->location;
12010 : 699 : parens.skip_until_found_close (parser);
12011 : 699 : tree e1, e2;
12012 : 699 : e1 = groktypename (t1, NULL, NULL);
12013 : 699 : e2 = groktypename (t2, NULL, NULL);
12014 : 699 : if (e1 == error_mark_node || e2 == error_mark_node)
12015 : : {
12016 : 1 : expr.set_error ();
12017 : 1 : break;
12018 : : }
12019 : :
12020 : 698 : e1 = TYPE_MAIN_VARIANT (e1);
12021 : 698 : e2 = TYPE_MAIN_VARIANT (e2);
12022 : :
12023 : 698 : expr.value
12024 : 698 : = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
12025 : 698 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12026 : : }
12027 : 698 : break;
12028 : 356 : case RID_BUILTIN_TGMATH:
12029 : 356 : {
12030 : 356 : vec<c_expr_t, va_gc> *cexpr_list;
12031 : 356 : location_t close_paren_loc;
12032 : :
12033 : 356 : c_parser_consume_token (parser);
12034 : 356 : if (!c_parser_get_builtin_args (parser,
12035 : : "__builtin_tgmath",
12036 : : &cexpr_list, false,
12037 : : &close_paren_loc))
12038 : : {
12039 : 0 : expr.set_error ();
12040 : 327 : break;
12041 : : }
12042 : :
12043 : 356 : if (vec_safe_length (cexpr_list) < 3)
12044 : : {
12045 : 3 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12046 : 3 : expr.set_error ();
12047 : 3 : break;
12048 : : }
12049 : :
12050 : : unsigned int i;
12051 : : c_expr_t *p;
12052 : 2587 : FOR_EACH_VEC_ELT (*cexpr_list, i, p)
12053 : 2234 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12054 : 353 : unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1);
12055 : 353 : if (nargs == 0)
12056 : : {
12057 : 4 : expr.set_error ();
12058 : 4 : break;
12059 : : }
12060 : 698 : if (vec_safe_length (cexpr_list) < nargs)
12061 : : {
12062 : 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12063 : 1 : expr.set_error ();
12064 : 1 : break;
12065 : : }
12066 : 348 : unsigned int num_functions = vec_safe_length (cexpr_list) - nargs;
12067 : 348 : if (num_functions < 2)
12068 : : {
12069 : 1 : error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12070 : 1 : expr.set_error ();
12071 : 1 : break;
12072 : : }
12073 : :
12074 : : /* The first NUM_FUNCTIONS expressions are the function
12075 : : pointers. The remaining NARGS expressions are the
12076 : : arguments that are to be passed to one of those
12077 : : functions, chosen following <tgmath.h> rules. */
12078 : 1744 : for (unsigned int j = 1; j < num_functions; j++)
12079 : : {
12080 : 1402 : unsigned int this_nargs
12081 : 1402 : = check_tgmath_function (&(*cexpr_list)[j], j + 1);
12082 : 1402 : if (this_nargs == 0)
12083 : : {
12084 : 4 : expr.set_error ();
12085 : 29 : goto out;
12086 : : }
12087 : 1398 : if (this_nargs != nargs)
12088 : : {
12089 : 1 : error_at ((*cexpr_list)[j].get_location (),
12090 : : "argument %u of %<__builtin_tgmath%> has "
12091 : : "wrong number of arguments", j + 1);
12092 : 1 : expr.set_error ();
12093 : 1 : goto out;
12094 : : }
12095 : : }
12096 : :
12097 : : /* The functions all have the same number of arguments.
12098 : : Determine whether arguments and return types vary in
12099 : : ways permitted for <tgmath.h> functions. */
12100 : : /* The first entry in each of these vectors is for the
12101 : : return type, subsequent entries for parameter
12102 : : types. */
12103 : 342 : auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
12104 : 342 : auto_vec<tree> parm_first (nargs + 1);
12105 : 342 : auto_vec<bool> parm_complex (nargs + 1);
12106 : 342 : auto_vec<bool> parm_varies (nargs + 1);
12107 : 342 : tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
12108 : 342 : tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
12109 : 342 : parm_first.quick_push (first_ret);
12110 : 342 : parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
12111 : 342 : parm_varies.quick_push (false);
12112 : 342 : function_args_iterator iter;
12113 : 342 : tree t;
12114 : 342 : unsigned int argpos;
12115 : 802 : FOREACH_FUNCTION_ARGS (first_type, t, iter)
12116 : : {
12117 : 802 : if (t == void_type_node)
12118 : : break;
12119 : 460 : parm_first.quick_push (TYPE_MAIN_VARIANT (t));
12120 : 460 : parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
12121 : 460 : parm_varies.quick_push (false);
12122 : : }
12123 : 1727 : for (unsigned int j = 1; j < num_functions; j++)
12124 : : {
12125 : 1397 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12126 : 1397 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12127 : 1397 : if (ret != parm_first[0])
12128 : : {
12129 : 1294 : parm_varies[0] = true;
12130 : 1294 : if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
12131 : 1294 : && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
12132 : : {
12133 : 3 : error_at ((*cexpr_list)[0].get_location (),
12134 : : "invalid type-generic return type for "
12135 : : "argument %u of %<__builtin_tgmath%>",
12136 : : 1);
12137 : 3 : expr.set_error ();
12138 : 3 : goto out;
12139 : : }
12140 : 1291 : if (!SCALAR_FLOAT_TYPE_P (ret)
12141 : 1291 : && !COMPLEX_FLOAT_TYPE_P (ret))
12142 : : {
12143 : 3 : error_at ((*cexpr_list)[j].get_location (),
12144 : : "invalid type-generic return type for "
12145 : : "argument %u of %<__builtin_tgmath%>",
12146 : : j + 1);
12147 : 3 : expr.set_error ();
12148 : 3 : goto out;
12149 : : }
12150 : : }
12151 : 1391 : if (TREE_CODE (ret) == COMPLEX_TYPE)
12152 : 342 : parm_complex[0] = true;
12153 : 1391 : argpos = 1;
12154 : 3329 : FOREACH_FUNCTION_ARGS (type, t, iter)
12155 : : {
12156 : 3329 : if (t == void_type_node)
12157 : : break;
12158 : 1944 : t = TYPE_MAIN_VARIANT (t);
12159 : 1944 : if (t != parm_first[argpos])
12160 : : {
12161 : 1919 : parm_varies[argpos] = true;
12162 : 1919 : if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
12163 : 1919 : && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
12164 : : {
12165 : 3 : error_at ((*cexpr_list)[0].get_location (),
12166 : : "invalid type-generic type for "
12167 : : "argument %u of argument %u of "
12168 : : "%<__builtin_tgmath%>", argpos, 1);
12169 : 3 : expr.set_error ();
12170 : 3 : goto out;
12171 : : }
12172 : 1916 : if (!SCALAR_FLOAT_TYPE_P (t)
12173 : 1916 : && !COMPLEX_FLOAT_TYPE_P (t))
12174 : : {
12175 : 3 : error_at ((*cexpr_list)[j].get_location (),
12176 : : "invalid type-generic type for "
12177 : : "argument %u of argument %u of "
12178 : : "%<__builtin_tgmath%>", argpos, j + 1);
12179 : 3 : expr.set_error ();
12180 : 3 : goto out;
12181 : : }
12182 : : }
12183 : 1938 : if (TREE_CODE (t) == COMPLEX_TYPE)
12184 : 674 : parm_complex[argpos] = true;
12185 : 1938 : argpos++;
12186 : : }
12187 : : }
12188 : : enum tgmath_parm_kind max_variation = tgmath_fixed;
12189 : 1108 : for (unsigned int j = 0; j <= nargs; j++)
12190 : : {
12191 : 778 : enum tgmath_parm_kind this_kind;
12192 : 778 : if (parm_varies[j])
12193 : : {
12194 : 731 : if (parm_complex[j])
12195 : 394 : max_variation = this_kind = tgmath_complex;
12196 : : else
12197 : : {
12198 : 337 : this_kind = tgmath_real;
12199 : 337 : if (max_variation != tgmath_complex)
12200 : 778 : max_variation = tgmath_real;
12201 : : }
12202 : : }
12203 : : else
12204 : 47 : this_kind = tgmath_fixed;
12205 : 778 : parm_kind.quick_push (this_kind);
12206 : : }
12207 : 330 : if (max_variation == tgmath_fixed)
12208 : : {
12209 : 1 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12210 : : "all have the same type");
12211 : 1 : expr.set_error ();
12212 : 1 : break;
12213 : : }
12214 : :
12215 : : /* Identify a parameter (not the return type) that varies,
12216 : : including with complex types if any variation includes
12217 : : complex types; there must be at least one such
12218 : : parameter. */
12219 : 341 : unsigned int tgarg = 0;
12220 : 341 : for (unsigned int j = 1; j <= nargs; j++)
12221 : 339 : if (parm_kind[j] == max_variation)
12222 : : {
12223 : : tgarg = j;
12224 : : break;
12225 : : }
12226 : 329 : if (tgarg == 0)
12227 : : {
12228 : 2 : error_at (loc, "function arguments of %<__builtin_tgmath%> "
12229 : : "lack type-generic parameter");
12230 : 2 : expr.set_error ();
12231 : 2 : break;
12232 : : }
12233 : :
12234 : : /* Determine the type of the relevant parameter for each
12235 : : function. */
12236 : 327 : auto_vec<tree> tg_type (num_functions);
12237 : 2035 : for (unsigned int j = 0; j < num_functions; j++)
12238 : : {
12239 : 1708 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12240 : 1708 : argpos = 1;
12241 : 1738 : FOREACH_FUNCTION_ARGS (type, t, iter)
12242 : : {
12243 : 1738 : if (argpos == tgarg)
12244 : : {
12245 : 1708 : tg_type.quick_push (TYPE_MAIN_VARIANT (t));
12246 : 1708 : break;
12247 : : }
12248 : 30 : argpos++;
12249 : : }
12250 : : }
12251 : :
12252 : : /* Verify that the corresponding types are different for
12253 : : all the listed functions. Also determine whether all
12254 : : the types are complex, whether all the types are
12255 : : standard or binary, and whether all the types are
12256 : : decimal. */
12257 : 327 : bool all_complex = true;
12258 : 327 : bool all_binary = true;
12259 : 327 : bool all_decimal = true;
12260 : 327 : hash_set<tree> tg_types;
12261 : 2687 : FOR_EACH_VEC_ELT (tg_type, i, t)
12262 : : {
12263 : 1708 : if (TREE_CODE (t) == COMPLEX_TYPE)
12264 : : all_decimal = false;
12265 : : else
12266 : : {
12267 : 1186 : all_complex = false;
12268 : 1186 : if (DECIMAL_FLOAT_TYPE_P (t))
12269 : : all_binary = false;
12270 : : else
12271 : : all_decimal = false;
12272 : : }
12273 : 1708 : if (tg_types.add (t))
12274 : : {
12275 : 1 : error_at ((*cexpr_list)[i].get_location (),
12276 : : "duplicate type-generic parameter type for "
12277 : : "function argument %u of %<__builtin_tgmath%>",
12278 : : i + 1);
12279 : 1 : expr.set_error ();
12280 : 1 : goto out;
12281 : : }
12282 : : }
12283 : :
12284 : : /* Verify that other parameters and the return type whose
12285 : : types vary have their types varying in the correct
12286 : : way. */
12287 : 2029 : for (unsigned int j = 0; j < num_functions; j++)
12288 : : {
12289 : 1705 : tree exp_type = tg_type[j];
12290 : 1705 : tree exp_real_type = exp_type;
12291 : 1705 : if (TREE_CODE (exp_type) == COMPLEX_TYPE)
12292 : 522 : exp_real_type = TREE_TYPE (exp_type);
12293 : 1705 : tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12294 : 1705 : tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12295 : 2606 : if ((parm_kind[0] == tgmath_complex && ret != exp_type)
12296 : 2606 : || (parm_kind[0] == tgmath_real && ret != exp_real_type))
12297 : : {
12298 : 1 : error_at ((*cexpr_list)[j].get_location (),
12299 : : "bad return type for function argument %u "
12300 : : "of %<__builtin_tgmath%>", j + 1);
12301 : 1 : expr.set_error ();
12302 : 1 : goto out;
12303 : : }
12304 : 1704 : argpos = 1;
12305 : 4078 : FOREACH_FUNCTION_ARGS (type, t, iter)
12306 : : {
12307 : 4078 : if (t == void_type_node)
12308 : : break;
12309 : 2375 : t = TYPE_MAIN_VARIANT (t);
12310 : 2375 : if ((parm_kind[argpos] == tgmath_complex
12311 : 1787 : && t != exp_type)
12312 : 4162 : || (parm_kind[argpos] == tgmath_real
12313 : 558 : && t != exp_real_type))
12314 : : {
12315 : 1 : error_at ((*cexpr_list)[j].get_location (),
12316 : : "bad type for argument %u of "
12317 : : "function argument %u of "
12318 : : "%<__builtin_tgmath%>", argpos, j + 1);
12319 : 1 : expr.set_error ();
12320 : 1 : goto out;
12321 : : }
12322 : 2374 : argpos++;
12323 : : }
12324 : : }
12325 : :
12326 : : /* The functions listed are a valid set of functions for a
12327 : : <tgmath.h> macro to select between. Identify the
12328 : : matching function, if any. First, the argument types
12329 : : must be combined following <tgmath.h> rules. Integer
12330 : : types are treated as _Decimal64 if any type-generic
12331 : : argument is decimal, or if the only alternatives for
12332 : : type-generic arguments are of decimal types, and are
12333 : : otherwise treated as _Float32x (or _Complex _Float32x
12334 : : for complex integer types) if any type-generic argument
12335 : : has _FloatNx type, otherwise as double (or _Complex
12336 : : double for complex integer types). After that
12337 : : adjustment, types are combined following the usual
12338 : : arithmetic conversions. If the function only accepts
12339 : : complex arguments, a complex type is produced. */
12340 : : bool arg_complex = all_complex;
12341 : : bool arg_binary = all_binary;
12342 : : bool arg_int_decimal = all_decimal;
12343 : : bool arg_int_floatnx = false;
12344 : : bool arg_int_decimalx = false;
12345 : 756 : for (unsigned int j = 1; j <= nargs; j++)
12346 : : {
12347 : 441 : if (parm_kind[j] == tgmath_fixed)
12348 : 10 : continue;
12349 : 431 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12350 : 431 : tree type = TREE_TYPE (ce->value);
12351 : 431 : if (!INTEGRAL_TYPE_P (type)
12352 : 431 : && !SCALAR_FLOAT_TYPE_P (type)
12353 : 89 : && TREE_CODE (type) != COMPLEX_TYPE)
12354 : : {
12355 : 1 : error_at (ce->get_location (),
12356 : : "invalid type of argument %u of type-generic "
12357 : : "function", j);
12358 : 1 : expr.set_error ();
12359 : 1 : goto out;
12360 : : }
12361 : 430 : if (DECIMAL_FLOAT_TYPE_P (type))
12362 : : {
12363 : 68 : arg_int_decimal = true;
12364 : 68 : if (all_complex)
12365 : : {
12366 : 1 : error_at (ce->get_location (),
12367 : : "decimal floating-point argument %u to "
12368 : : "complex-only type-generic function", j);
12369 : 1 : expr.set_error ();
12370 : 1 : goto out;
12371 : : }
12372 : 67 : else if (all_binary)
12373 : : {
12374 : 1 : error_at (ce->get_location (),
12375 : : "decimal floating-point argument %u to "
12376 : : "binary-only type-generic function", j);
12377 : 1 : expr.set_error ();
12378 : 1 : goto out;
12379 : : }
12380 : 66 : else if (arg_complex)
12381 : : {
12382 : 1 : error_at (ce->get_location (),
12383 : : "both complex and decimal floating-point "
12384 : : "arguments to type-generic function");
12385 : 1 : expr.set_error ();
12386 : 1 : goto out;
12387 : : }
12388 : 65 : else if (arg_binary)
12389 : : {
12390 : 1 : error_at (ce->get_location (),
12391 : : "both binary and decimal floating-point "
12392 : : "arguments to type-generic function");
12393 : 1 : expr.set_error ();
12394 : 1 : goto out;
12395 : : }
12396 : : }
12397 : 362 : else if (TREE_CODE (type) == COMPLEX_TYPE)
12398 : : {
12399 : 88 : arg_complex = true;
12400 : 88 : if (COMPLEX_FLOAT_TYPE_P (type))
12401 : : arg_binary = true;
12402 : 88 : if (all_decimal)
12403 : : {
12404 : 1 : error_at (ce->get_location (),
12405 : : "complex argument %u to "
12406 : : "decimal-only type-generic function", j);
12407 : 1 : expr.set_error ();
12408 : 1 : goto out;
12409 : : }
12410 : 87 : else if (arg_int_decimal)
12411 : : {
12412 : 1 : error_at (ce->get_location (),
12413 : : "both complex and decimal floating-point "
12414 : : "arguments to type-generic function");
12415 : 1 : expr.set_error ();
12416 : 1 : goto out;
12417 : : }
12418 : : }
12419 : 274 : else if (SCALAR_FLOAT_TYPE_P (type))
12420 : : {
12421 : 180 : arg_binary = true;
12422 : 180 : if (all_decimal)
12423 : : {
12424 : 1 : error_at (ce->get_location (),
12425 : : "binary argument %u to "
12426 : : "decimal-only type-generic function", j);
12427 : 1 : expr.set_error ();
12428 : 1 : goto out;
12429 : : }
12430 : 179 : else if (arg_int_decimal)
12431 : : {
12432 : 1 : error_at (ce->get_location (),
12433 : : "both binary and decimal floating-point "
12434 : : "arguments to type-generic function");
12435 : 1 : expr.set_error ();
12436 : 1 : goto out;
12437 : : }
12438 : : }
12439 : 422 : tree rtype = TYPE_MAIN_VARIANT (type);
12440 : 422 : if (TREE_CODE (rtype) == COMPLEX_TYPE)
12441 : 86 : rtype = TREE_TYPE (rtype);
12442 : 422 : if (SCALAR_FLOAT_TYPE_P (rtype))
12443 : 1208 : for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
12444 : 908 : if (rtype == FLOATNX_TYPE_NODE (j))
12445 : : {
12446 : : arg_int_floatnx = true;
12447 : : break;
12448 : : }
12449 : 422 : if (rtype == dfloat64x_type_node)
12450 : 0 : arg_int_decimalx = true;
12451 : : }
12452 : : tree arg_real = NULL_TREE;
12453 : 743 : for (unsigned int j = 1; j <= nargs; j++)
12454 : : {
12455 : 428 : if (parm_kind[j] == tgmath_fixed)
12456 : 10 : continue;
12457 : 418 : c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12458 : 418 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
12459 : 418 : if (TREE_CODE (type) == COMPLEX_TYPE)
12460 : 85 : type = TREE_TYPE (type);
12461 : 418 : if (INTEGRAL_TYPE_P (type))
12462 : 114 : type = (arg_int_decimalx
12463 : 114 : ? dfloat64x_type_node
12464 : : : arg_int_floatnx
12465 : 114 : ? float32x_type_node
12466 : : : arg_int_decimal
12467 : 106 : ? dfloat64_type_node
12468 : : : double_type_node);
12469 : 418 : if (arg_real == NULL_TREE)
12470 : : arg_real = type;
12471 : : else
12472 : 103 : arg_real = common_type (arg_real, type);
12473 : 418 : if (arg_real == error_mark_node)
12474 : : {
12475 : 0 : expr.set_error ();
12476 : 0 : goto out;
12477 : : }
12478 : : }
12479 : 315 : tree arg_type = (arg_complex
12480 : 315 : ? build_complex_type (arg_real)
12481 : : : arg_real);
12482 : :
12483 : : /* Look for a function to call with type-generic parameter
12484 : : type ARG_TYPE. */
12485 : 315 : c_expr_t *fn = NULL;
12486 : 976 : for (unsigned int j = 0; j < num_functions; j++)
12487 : : {
12488 : 970 : if (tg_type[j] == arg_type)
12489 : : {
12490 : 309 : fn = &(*cexpr_list)[j];
12491 : 309 : break;
12492 : : }
12493 : : }
12494 : 315 : if (fn == NULL
12495 : 6 : && parm_kind[0] == tgmath_fixed
12496 : 4 : && SCALAR_FLOAT_TYPE_P (parm_first[0]))
12497 : : {
12498 : : /* Presume this is a macro that rounds its result to a
12499 : : narrower type, and look for the first function with
12500 : : at least the range and precision of the argument
12501 : : type. */
12502 : 4 : for (unsigned int j = 0; j < num_functions; j++)
12503 : : {
12504 : 8 : if (arg_complex
12505 : 4 : != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
12506 : 0 : continue;
12507 : 4 : tree real_tg_type = (arg_complex
12508 : 4 : ? TREE_TYPE (tg_type[j])
12509 : 0 : : tg_type[j]);
12510 : 8 : if (DECIMAL_FLOAT_TYPE_P (arg_real)
12511 : 4 : != DECIMAL_FLOAT_TYPE_P (real_tg_type))
12512 : 0 : continue;
12513 : 4 : scalar_float_mode arg_mode
12514 : 4 : = SCALAR_FLOAT_TYPE_MODE (arg_real);
12515 : 4 : scalar_float_mode tg_mode
12516 : 4 : = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
12517 : 4 : const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
12518 : 4 : const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
12519 : 4 : if (arg_fmt->b == tg_fmt->b
12520 : 4 : && arg_fmt->p <= tg_fmt->p
12521 : 4 : && arg_fmt->emax <= tg_fmt->emax
12522 : 4 : && (arg_fmt->emin - arg_fmt->p
12523 : 4 : >= tg_fmt->emin - tg_fmt->p))
12524 : : {
12525 : 4 : fn = &(*cexpr_list)[j];
12526 : 4 : break;
12527 : : }
12528 : : }
12529 : : }
12530 : 315 : if (fn == NULL)
12531 : : {
12532 : 2 : error_at (loc, "no matching function for type-generic call");
12533 : 2 : expr.set_error ();
12534 : 2 : break;
12535 : : }
12536 : :
12537 : : /* Construct a call to FN. */
12538 : 313 : vec<tree, va_gc> *args;
12539 : 313 : vec_alloc (args, nargs);
12540 : 313 : vec<tree, va_gc> *origtypes;
12541 : 313 : vec_alloc (origtypes, nargs);
12542 : 313 : auto_vec<location_t> arg_loc (nargs);
12543 : 739 : for (unsigned int j = 0; j < nargs; j++)
12544 : : {
12545 : 426 : c_expr_t *ce = &(*cexpr_list)[num_functions + j];
12546 : 426 : args->quick_push (ce->value);
12547 : 426 : arg_loc.quick_push (ce->get_location ());
12548 : 426 : origtypes->quick_push (ce->original_type);
12549 : : }
12550 : 313 : expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
12551 : : args, origtypes);
12552 : 313 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12553 : 313 : break;
12554 : 982 : }
12555 : 22 : case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
12556 : 22 : {
12557 : 22 : vec<c_expr_t, va_gc> *cexpr_list;
12558 : 22 : c_expr_t *e2_p;
12559 : 22 : tree chain_value;
12560 : 22 : location_t close_paren_loc;
12561 : :
12562 : 22 : c_parser_consume_token (parser);
12563 : 22 : if (!c_parser_get_builtin_args (parser,
12564 : : "__builtin_call_with_static_chain",
12565 : : &cexpr_list, false,
12566 : : &close_paren_loc))
12567 : : {
12568 : 0 : expr.set_error ();
12569 : 0 : break;
12570 : : }
12571 : 22 : if (vec_safe_length (cexpr_list) != 2)
12572 : : {
12573 : 0 : error_at (loc, "wrong number of arguments to "
12574 : : "%<__builtin_call_with_static_chain%>");
12575 : 0 : expr.set_error ();
12576 : 0 : break;
12577 : : }
12578 : :
12579 : 22 : expr = (*cexpr_list)[0];
12580 : 22 : e2_p = &(*cexpr_list)[1];
12581 : 22 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12582 : 22 : chain_value = e2_p->value;
12583 : 22 : mark_exp_read (chain_value);
12584 : :
12585 : 22 : if (TREE_CODE (expr.value) != CALL_EXPR)
12586 : 3 : error_at (loc, "first argument to "
12587 : : "%<__builtin_call_with_static_chain%> "
12588 : : "must be a call expression");
12589 : 19 : else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
12590 : 1 : error_at (loc, "second argument to "
12591 : : "%<__builtin_call_with_static_chain%> "
12592 : : "must be a pointer type");
12593 : : else
12594 : 18 : CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
12595 : 22 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12596 : 22 : break;
12597 : : }
12598 : 12078 : case RID_BUILTIN_COMPLEX:
12599 : 12078 : {
12600 : 12078 : vec<c_expr_t, va_gc> *cexpr_list;
12601 : 12078 : c_expr_t *e1_p, *e2_p;
12602 : 12078 : location_t close_paren_loc;
12603 : :
12604 : 12078 : c_parser_consume_token (parser);
12605 : 12078 : if (!c_parser_get_builtin_args (parser,
12606 : : "__builtin_complex",
12607 : : &cexpr_list, false,
12608 : : &close_paren_loc))
12609 : : {
12610 : 1 : expr.set_error ();
12611 : 1 : break;
12612 : : }
12613 : :
12614 : 12077 : if (vec_safe_length (cexpr_list) != 2)
12615 : : {
12616 : 2 : error_at (loc, "wrong number of arguments to "
12617 : : "%<__builtin_complex%>");
12618 : 2 : expr.set_error ();
12619 : 2 : break;
12620 : : }
12621 : :
12622 : 12075 : e1_p = &(*cexpr_list)[0];
12623 : 12075 : e2_p = &(*cexpr_list)[1];
12624 : :
12625 : 12075 : *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
12626 : 12075 : if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
12627 : 56 : e1_p->value = convert (TREE_TYPE (e1_p->value),
12628 : 56 : TREE_OPERAND (e1_p->value, 0));
12629 : 12075 : *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12630 : 12075 : if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
12631 : 56 : e2_p->value = convert (TREE_TYPE (e2_p->value),
12632 : 56 : TREE_OPERAND (e2_p->value, 0));
12633 : 12075 : if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12634 : 12074 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12635 : 12073 : || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
12636 : 24147 : || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
12637 : : {
12638 : 3 : error_at (loc, "%<__builtin_complex%> operand "
12639 : : "not of real binary floating-point type");
12640 : 3 : expr.set_error ();
12641 : 3 : break;
12642 : : }
12643 : 12072 : if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
12644 : 12072 : != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
12645 : : {
12646 : 1 : error_at (loc,
12647 : : "%<__builtin_complex%> operands of different types");
12648 : 1 : expr.set_error ();
12649 : 1 : break;
12650 : : }
12651 : 12071 : pedwarn_c90 (loc, OPT_Wpedantic,
12652 : : "ISO C90 does not support complex types");
12653 : 12071 : expr.value = build2_loc (loc, COMPLEX_EXPR,
12654 : : build_complex_type
12655 : 12071 : (TYPE_MAIN_VARIANT
12656 : : (TREE_TYPE (e1_p->value))),
12657 : : e1_p->value, e2_p->value);
12658 : 12071 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12659 : 12071 : break;
12660 : : }
12661 : 44 : case RID_BUILTIN_COUNTED_BY_REF:
12662 : 44 : {
12663 : 44 : vec<c_expr_t, va_gc> *cexpr_list;
12664 : 44 : c_expr_t *e_p;
12665 : 44 : location_t close_paren_loc;
12666 : :
12667 : 44 : c_parser_consume_token (parser);
12668 : 44 : if (!c_parser_get_builtin_args (parser,
12669 : : "__builtin_counted_by_ref",
12670 : : &cexpr_list, false,
12671 : : &close_paren_loc))
12672 : : {
12673 : 0 : expr.set_error ();
12674 : 0 : break;
12675 : : }
12676 : 44 : if (vec_safe_length (cexpr_list) != 1)
12677 : : {
12678 : 2 : error_at (loc, "wrong number of arguments to "
12679 : : "%<__builtin_counted_by_ref%>");
12680 : 2 : expr.set_error ();
12681 : 2 : break;
12682 : : }
12683 : :
12684 : 42 : e_p = &(*cexpr_list)[0];
12685 : 42 : tree ref = e_p->value;
12686 : :
12687 : 42 : if (TREE_CODE (TREE_TYPE (ref)) != ARRAY_TYPE)
12688 : : {
12689 : 2 : error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12690 : : " must be an array");
12691 : 2 : expr.set_error ();
12692 : 2 : break;
12693 : : }
12694 : :
12695 : : /* If the array ref is inside TYPEOF or ALIGNOF, the call to
12696 : : .ACCESS_WITH_SIZE was not generated by the routine
12697 : : build_component_ref by default, we should generate it here. */
12698 : 40 : if (TREE_CODE (ref) == COMPONENT_REF)
12699 : 40 : ref = handle_counted_by_for_component_ref (loc, ref);
12700 : :
12701 : 40 : if (has_counted_by_object (ref))
12702 : 25 : expr.value = get_counted_by_ref (ref);
12703 : : else
12704 : 15 : expr.value = null_pointer_node;
12705 : :
12706 : 40 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12707 : 40 : break;
12708 : : }
12709 : 460014 : case RID_BUILTIN_SHUFFLE:
12710 : 460014 : {
12711 : 460014 : vec<c_expr_t, va_gc> *cexpr_list;
12712 : 460014 : unsigned int i;
12713 : 460014 : c_expr_t *p;
12714 : 460014 : location_t close_paren_loc;
12715 : :
12716 : 460014 : c_parser_consume_token (parser);
12717 : 460014 : if (!c_parser_get_builtin_args (parser,
12718 : : "__builtin_shuffle",
12719 : : &cexpr_list, false,
12720 : : &close_paren_loc))
12721 : : {
12722 : 0 : expr.set_error ();
12723 : 0 : break;
12724 : : }
12725 : :
12726 : 1421304 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12727 : 961290 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12728 : :
12729 : 460014 : if (vec_safe_length (cexpr_list) == 2)
12730 : 418752 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12731 : : NULL_TREE,
12732 : 418752 : (*cexpr_list)[1].value);
12733 : :
12734 : 41262 : else if (vec_safe_length (cexpr_list) == 3)
12735 : 41262 : expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12736 : 41262 : (*cexpr_list)[1].value,
12737 : 41262 : (*cexpr_list)[2].value);
12738 : : else
12739 : : {
12740 : 0 : error_at (loc, "wrong number of arguments to "
12741 : : "%<__builtin_shuffle%>");
12742 : 0 : expr.set_error ();
12743 : : }
12744 : 460014 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12745 : 460014 : break;
12746 : : }
12747 : 1052900 : case RID_BUILTIN_SHUFFLEVECTOR:
12748 : 1052900 : {
12749 : 1052900 : vec<c_expr_t, va_gc> *cexpr_list;
12750 : 1052900 : unsigned int i;
12751 : 1052900 : c_expr_t *p;
12752 : 1052900 : location_t close_paren_loc;
12753 : :
12754 : 1052900 : c_parser_consume_token (parser);
12755 : 1052900 : if (!c_parser_get_builtin_args (parser,
12756 : : "__builtin_shufflevector",
12757 : : &cexpr_list, false,
12758 : : &close_paren_loc))
12759 : : {
12760 : 0 : expr.set_error ();
12761 : 0 : break;
12762 : : }
12763 : :
12764 : 16394186 : FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12765 : 15341286 : *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12766 : :
12767 : 1052900 : if (vec_safe_length (cexpr_list) < 3)
12768 : : {
12769 : 0 : error_at (loc, "wrong number of arguments to "
12770 : : "%<__builtin_shuffle%>");
12771 : 0 : expr.set_error ();
12772 : : }
12773 : : else
12774 : : {
12775 : 1052900 : auto_vec<tree, 16> mask;
12776 : 14288386 : for (i = 2; i < cexpr_list->length (); ++i)
12777 : 13235486 : mask.safe_push ((*cexpr_list)[i].value);
12778 : 1052900 : expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
12779 : 1052900 : (*cexpr_list)[1].value,
12780 : : mask);
12781 : 1052900 : }
12782 : 1052900 : set_c_expr_source_range (&expr, loc, close_paren_loc);
12783 : 1052900 : break;
12784 : : }
12785 : 329 : case RID_BUILTIN_CONVERTVECTOR:
12786 : 329 : {
12787 : 329 : location_t start_loc = loc;
12788 : 329 : c_parser_consume_token (parser);
12789 : 329 : matching_parens parens;
12790 : 329 : if (!parens.require_open (parser))
12791 : : {
12792 : 0 : expr.set_error ();
12793 : 2 : break;
12794 : : }
12795 : 329 : e1 = c_parser_expr_no_commas (parser, NULL);
12796 : 329 : mark_exp_read (e1.value);
12797 : 329 : if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
12798 : : {
12799 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
12800 : 2 : expr.set_error ();
12801 : 2 : break;
12802 : : }
12803 : 327 : loc = c_parser_peek_token (parser)->location;
12804 : 327 : t1 = c_parser_type_name (parser);
12805 : 327 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12806 : 327 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
12807 : : "expected %<)%>");
12808 : 327 : if (t1 == NULL)
12809 : 1 : expr.set_error ();
12810 : : else
12811 : : {
12812 : 326 : tree type_expr = NULL_TREE;
12813 : 326 : expr.value = c_build_vec_convert (start_loc, e1.value, loc,
12814 : : groktypename (t1, &type_expr,
12815 : : NULL));
12816 : 326 : set_c_expr_source_range (&expr, start_loc, end_loc);
12817 : : }
12818 : : }
12819 : 327 : break;
12820 : 10 : case RID_BUILTIN_ASSOC_BARRIER:
12821 : 10 : {
12822 : 10 : location_t start_loc = loc;
12823 : 10 : c_parser_consume_token (parser);
12824 : 10 : matching_parens parens;
12825 : 10 : if (!parens.require_open (parser))
12826 : : {
12827 : 0 : expr.set_error ();
12828 : 0 : break;
12829 : : }
12830 : 10 : e1 = c_parser_expr_no_commas (parser, NULL);
12831 : 10 : mark_exp_read (e1.value);
12832 : 10 : location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12833 : 10 : parens.skip_until_found_close (parser);
12834 : 10 : expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
12835 : 10 : set_c_expr_source_range (&expr, start_loc, end_loc);
12836 : : }
12837 : 10 : break;
12838 : 1073 : case RID_BUILTIN_STDC:
12839 : 1073 : {
12840 : 1073 : vec<c_expr_t, va_gc> *cexpr_list;
12841 : 1073 : c_expr_t *arg_p;
12842 : 1073 : location_t close_paren_loc;
12843 : 1073 : enum c_builtin_stdc {
12844 : : C_BUILTIN_STDC_BIT_CEIL,
12845 : : C_BUILTIN_STDC_BIT_FLOOR,
12846 : : C_BUILTIN_STDC_BIT_WIDTH,
12847 : : C_BUILTIN_STDC_COUNT_ONES,
12848 : : C_BUILTIN_STDC_COUNT_ZEROS,
12849 : : C_BUILTIN_STDC_FIRST_LEADING_ONE,
12850 : : C_BUILTIN_STDC_FIRST_LEADING_ZERO,
12851 : : C_BUILTIN_STDC_FIRST_TRAILING_ONE,
12852 : : C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
12853 : : C_BUILTIN_STDC_HAS_SINGLE_BIT,
12854 : : C_BUILTIN_STDC_LEADING_ONES,
12855 : : C_BUILTIN_STDC_LEADING_ZEROS,
12856 : : C_BUILTIN_STDC_ROTATE_LEFT,
12857 : : C_BUILTIN_STDC_ROTATE_RIGHT,
12858 : : C_BUILTIN_STDC_TRAILING_ONES,
12859 : : C_BUILTIN_STDC_TRAILING_ZEROS,
12860 : : C_BUILTIN_STDC_MAX
12861 : 1073 : } stdc_rid = C_BUILTIN_STDC_MAX;
12862 : 1073 : const char *name
12863 : 1073 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
12864 : 1073 : unsigned num_args = 1;
12865 : 1073 : switch (name[sizeof ("__builtin_stdc_") - 1])
12866 : : {
12867 : 202 : case 'b':
12868 : 202 : switch (name[sizeof ("__builtin_stdc_bit_") - 1])
12869 : : {
12870 : : case 'c':
12871 : : stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
12872 : : break;
12873 : 64 : case 'f':
12874 : 64 : stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
12875 : 64 : break;
12876 : 58 : default:
12877 : 58 : stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
12878 : 58 : break;
12879 : : }
12880 : : break;
12881 : 106 : case 'c':
12882 : 106 : if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
12883 : : stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
12884 : : else
12885 : 53 : stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
12886 : : break;
12887 : 215 : case 'f':
12888 : 215 : switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
12889 : : {
12890 : : case 'n':
12891 : : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
12892 : : break;
12893 : : case 'e':
12894 : : stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
12895 : : break;
12896 : : case 'o':
12897 : : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
12898 : : break;
12899 : : default:
12900 : : stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
12901 : : break;
12902 : : }
12903 : : break;
12904 : : case 'h':
12905 : : stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
12906 : : break;
12907 : 106 : case 'l':
12908 : 106 : if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
12909 : : stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
12910 : : else
12911 : 53 : stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
12912 : : break;
12913 : 285 : case 'r':
12914 : 285 : if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l')
12915 : : stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT;
12916 : : else
12917 : 138 : stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT;
12918 : : num_args = 2;
12919 : : break;
12920 : 106 : case 't':
12921 : 106 : if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
12922 : : stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
12923 : : else
12924 : 53 : stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
12925 : : break;
12926 : : }
12927 : 281 : gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
12928 : :
12929 : 1073 : c_parser_consume_token (parser);
12930 : 1073 : if (!c_parser_get_builtin_args (parser, name,
12931 : : &cexpr_list, false,
12932 : : &close_paren_loc))
12933 : : {
12934 : 0 : expr.set_error ();
12935 : 0 : break;
12936 : : }
12937 : :
12938 : 2130 : if (vec_safe_length (cexpr_list) != num_args)
12939 : : {
12940 : 34 : error_at (loc, "wrong number of arguments to %qs", name);
12941 : 34 : expr.set_error ();
12942 : 34 : break;
12943 : : }
12944 : :
12945 : 1039 : arg_p = &(*cexpr_list)[0];
12946 : 1039 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
12947 : 1039 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
12948 : : {
12949 : 80 : error_at (loc, "%qs operand not an integral type", name);
12950 : 80 : expr.set_error ();
12951 : 80 : break;
12952 : : }
12953 : 959 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
12954 : : {
12955 : 16 : error_at (loc, "argument %u in call to function "
12956 : : "%qs has enumerated type", 1, name);
12957 : 16 : expr.set_error ();
12958 : 16 : break;
12959 : : }
12960 : 943 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
12961 : : {
12962 : 16 : error_at (loc, "argument %u in call to function "
12963 : : "%qs has boolean type", 1, name);
12964 : 16 : expr.set_error ();
12965 : 16 : break;
12966 : : }
12967 : 927 : if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
12968 : : {
12969 : 16 : error_at (loc, "argument 1 in call to function "
12970 : : "%qs has signed type", name);
12971 : 16 : expr.set_error ();
12972 : 16 : break;
12973 : : }
12974 : 911 : if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
12975 : 911 : == char_type_node)
12976 : : {
12977 : 16 : error_at (loc, "argument 1 in call to function "
12978 : : "%qs has %<char%> type", name);
12979 : 16 : expr.set_error ();
12980 : 16 : break;
12981 : : }
12982 : 895 : tree arg = arg_p->value;
12983 : 895 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
12984 : : /* Expand:
12985 : : __builtin_stdc_leading_zeros (arg) as
12986 : : (unsigned int) __builtin_clzg (arg, prec)
12987 : : __builtin_stdc_leading_ones (arg) as
12988 : : (unsigned int) __builtin_clzg ((type) ~arg, prec)
12989 : : __builtin_stdc_trailing_zeros (arg) as
12990 : : (unsigned int) __builtin_ctzg (arg, prec)
12991 : : __builtin_stdc_trailing_ones (arg) as
12992 : : (unsigned int) __builtin_ctzg ((type) ~arg, prec)
12993 : : __builtin_stdc_first_leading_zero (arg) as
12994 : : __builtin_clzg ((type) ~arg, -1) + 1U
12995 : : __builtin_stdc_first_leading_one (arg) as
12996 : : __builtin_clzg (arg, -1) + 1U
12997 : : __builtin_stdc_first_trailing_zero (arg) as
12998 : : __builtin_ctzg ((type) ~arg, -1) + 1U
12999 : : __builtin_stdc_first_trailing_one (arg) as
13000 : : __builtin_ctzg (arg, -1) + 1U
13001 : : __builtin_stdc_count_zeros (arg) as
13002 : : (unsigned int) __builtin_popcountg ((type) ~arg)
13003 : : __builtin_stdc_count_ones (arg) as
13004 : : (unsigned int) __builtin_popcountg (arg)
13005 : : __builtin_stdc_has_single_bit (arg) as
13006 : : (_Bool) (__builtin_popcountg (arg) == 1)
13007 : : __builtin_stdc_bit_width (arg) as
13008 : : (unsigned int) (prec - __builtin_clzg (arg, prec))
13009 : : __builtin_stdc_bit_floor (arg) as
13010 : : arg == 0 ? (type) 0
13011 : : : (type) 1 << (prec - 1 - __builtin_clzg (arg))
13012 : : __builtin_stdc_bit_ceil (arg) as
13013 : : arg <= 1 ? (type) 1
13014 : : : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
13015 : : without evaluating arg multiple times, type being
13016 : : __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
13017 : 895 : int prec = TYPE_PRECISION (type);
13018 : 895 : if (num_args == 2)
13019 : : {
13020 : : /* Expand:
13021 : : __builtin_stdc_rotate_left (arg1, arg2) as
13022 : : arg1 r<< (arg2 % prec)
13023 : : __builtin_stdc_rotate_right (arg1, arg2) as
13024 : : arg1 r>> (arg2 % prec). */
13025 : 261 : arg_p = &(*cexpr_list)[1];
13026 : 261 : *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13027 : 261 : if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13028 : : {
13029 : 10 : error_at (loc, "%qs operand not an integral type", name);
13030 : 10 : expr.set_error ();
13031 : 10 : break;
13032 : : }
13033 : 251 : if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13034 : : {
13035 : 2 : error_at (loc, "argument %u in call to function "
13036 : : "%qs has enumerated type", 2, name);
13037 : 2 : expr.set_error ();
13038 : 2 : break;
13039 : : }
13040 : 249 : tree arg1 = save_expr (arg);
13041 : 249 : tree arg2 = save_expr (arg_p->value);
13042 : 249 : tree_code code;
13043 : 249 : if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT)
13044 : : code = LROTATE_EXPR;
13045 : : else
13046 : 120 : code = RROTATE_EXPR;
13047 : :
13048 : 249 : if (TREE_CODE (arg2) == INTEGER_CST
13049 : 249 : && tree_int_cst_sgn (arg2) < 0)
13050 : 20 : warning_at (loc, OPT_Wshift_count_negative,
13051 : : "rotate count is negative");
13052 : :
13053 : 249 : tree instrument_expr = NULL_TREE;
13054 : 249 : if (sanitize_flags_p (SANITIZE_SHIFT))
13055 : 28 : instrument_expr = ubsan_instrument_shift (loc, code,
13056 : : arg1, arg2);
13057 : :
13058 : : /* Promote arg2 to unsigned just so that we don't
13059 : : need to deal with arg2 type not being able to represent
13060 : : prec. In the end gimplification uses unsigned int
13061 : : for all shifts/rotates anyway. */
13062 : 249 : if (TYPE_PRECISION (TREE_TYPE (arg2))
13063 : 249 : < TYPE_PRECISION (integer_type_node))
13064 : 13 : arg2 = fold_convert (unsigned_type_node, arg2);
13065 : :
13066 : 249 : if (TYPE_UNSIGNED (TREE_TYPE (arg2)))
13067 : 26 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg2),
13068 : 26 : arg2, build_int_cst (TREE_TYPE (arg2),
13069 : 26 : prec));
13070 : : else
13071 : : {
13072 : : /* When second argument is signed, just do the modulo in
13073 : : unsigned type, that results in better generated code
13074 : : (for power of 2 precisions bitwise AND). */
13075 : 223 : tree utype = c_common_unsigned_type (TREE_TYPE (arg2));
13076 : 223 : arg2 = build2_loc (loc, TRUNC_MOD_EXPR, utype,
13077 : : fold_convert (utype, arg2),
13078 : 223 : build_int_cst (utype, prec));
13079 : : }
13080 : :
13081 : : /* The middle-end isn't prepared to handle {L,R}ROTATE_EXPR
13082 : : on types without mode precision, except for large/huge
13083 : : _BitInt types. */
13084 : 249 : if (type_has_mode_precision_p (TREE_TYPE (arg1))
13085 : 249 : || (TREE_CODE (TREE_TYPE (arg1)) == BITINT_TYPE
13086 : 150 : && prec > MAX_FIXED_MODE_SIZE))
13087 : 192 : expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg1,
13088 : : arg2);
13089 : : else
13090 : : {
13091 : 57 : arg2 = save_expr (arg2);
13092 : 82 : tree t1 = build2_loc (loc, (code == LROTATE_EXPR
13093 : : ? LSHIFT_EXPR : RSHIFT_EXPR),
13094 : 57 : TREE_TYPE (arg1), arg1, arg2);
13095 : 114 : tree t2 = build2_loc (loc, MINUS_EXPR,
13096 : 57 : TREE_TYPE (arg2),
13097 : 57 : build_int_cst (TREE_TYPE (arg2),
13098 : 57 : prec), arg2);
13099 : 82 : t2 = build2_loc (loc, (code == LROTATE_EXPR
13100 : : ? RSHIFT_EXPR : LSHIFT_EXPR),
13101 : 57 : TREE_TYPE (arg1), arg1, t2);
13102 : 57 : suppress_warning (t2, OPT_Wshift_count_overflow);
13103 : 57 : tree t3 = build2_loc (loc, BIT_IOR_EXPR,
13104 : 57 : TREE_TYPE (arg1), t1, t2);
13105 : 57 : tree t4 = build2_loc (loc, NE_EXPR, boolean_type_node,
13106 : : arg2,
13107 : 57 : build_zero_cst (TREE_TYPE (arg2)));
13108 : 57 : t4 = build2_loc (loc, COMPOUND_EXPR, boolean_type_node,
13109 : : arg1, t4);
13110 : 57 : expr.value = build3_loc (loc, COND_EXPR,
13111 : 57 : TREE_TYPE (arg1), t4, t3, arg1);
13112 : : }
13113 : 249 : if (instrument_expr)
13114 : 28 : expr.value = build2_loc (loc, COMPOUND_EXPR,
13115 : 28 : TREE_TYPE (expr.value),
13116 : : instrument_expr, expr.value);
13117 : 249 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13118 : 249 : break;
13119 : : }
13120 : 634 : tree barg1 = arg;
13121 : 634 : switch (stdc_rid)
13122 : : {
13123 : 69 : case C_BUILTIN_STDC_BIT_CEIL:
13124 : 69 : arg = save_expr (arg);
13125 : 69 : barg1 = build2_loc (loc, PLUS_EXPR, type, arg,
13126 : : build_int_cst (type, -1));
13127 : 69 : break;
13128 : 53 : case C_BUILTIN_STDC_BIT_FLOOR:
13129 : 53 : barg1 = arg = save_expr (arg);
13130 : 53 : break;
13131 : 211 : case C_BUILTIN_STDC_COUNT_ZEROS:
13132 : 211 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13133 : 211 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13134 : 211 : case C_BUILTIN_STDC_LEADING_ONES:
13135 : 211 : case C_BUILTIN_STDC_TRAILING_ONES:
13136 : 211 : barg1 = build1_loc (loc, BIT_NOT_EXPR, type, arg);
13137 : 211 : break;
13138 : : default:
13139 : : break;
13140 : : }
13141 : 634 : tree barg2 = NULL_TREE;
13142 : 634 : switch (stdc_rid)
13143 : : {
13144 : 215 : case C_BUILTIN_STDC_BIT_WIDTH:
13145 : 215 : case C_BUILTIN_STDC_LEADING_ONES:
13146 : 215 : case C_BUILTIN_STDC_LEADING_ZEROS:
13147 : 215 : case C_BUILTIN_STDC_TRAILING_ONES:
13148 : 215 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13149 : 215 : barg2 = build_int_cst (integer_type_node, prec);
13150 : 215 : break;
13151 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13152 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13153 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13154 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13155 : 171 : barg2 = integer_minus_one_node;
13156 : 171 : break;
13157 : : default:
13158 : : break;
13159 : : }
13160 : 634 : tree fndecl = NULL_TREE;
13161 : 634 : switch (stdc_rid)
13162 : : {
13163 : 340 : case C_BUILTIN_STDC_BIT_CEIL:
13164 : 340 : case C_BUILTIN_STDC_BIT_FLOOR:
13165 : 340 : case C_BUILTIN_STDC_BIT_WIDTH:
13166 : 340 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13167 : 340 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13168 : 340 : case C_BUILTIN_STDC_LEADING_ONES:
13169 : 340 : case C_BUILTIN_STDC_LEADING_ZEROS:
13170 : 340 : fndecl = builtin_decl_explicit (BUILT_IN_CLZG);
13171 : 340 : break;
13172 : 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13173 : 168 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13174 : 168 : case C_BUILTIN_STDC_TRAILING_ONES:
13175 : 168 : case C_BUILTIN_STDC_TRAILING_ZEROS:
13176 : 168 : fndecl = builtin_decl_explicit (BUILT_IN_CTZG);
13177 : 168 : break;
13178 : 126 : case C_BUILTIN_STDC_COUNT_ONES:
13179 : 126 : case C_BUILTIN_STDC_COUNT_ZEROS:
13180 : 126 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13181 : 126 : fndecl = builtin_decl_explicit (BUILT_IN_POPCOUNTG);
13182 : 126 : break;
13183 : 0 : default:
13184 : 0 : gcc_unreachable ();
13185 : : }
13186 : : /* Construct a call to __builtin_{clz,ctz,popcount}g. */
13187 : 634 : int nargs = barg2 != NULL_TREE ? 2 : 1;
13188 : 634 : vec<tree, va_gc> *args;
13189 : 634 : vec_alloc (args, nargs);
13190 : 634 : vec<tree, va_gc> *origtypes;
13191 : 634 : vec_alloc (origtypes, nargs);
13192 : 1268 : auto_vec<location_t> arg_loc (nargs);
13193 : 634 : args->quick_push (barg1);
13194 : 634 : arg_loc.quick_push (arg_p->get_location ());
13195 : 634 : origtypes->quick_push (arg_p->original_type);
13196 : 634 : if (nargs == 2)
13197 : : {
13198 : 386 : args->quick_push (barg2);
13199 : 386 : arg_loc.quick_push (loc);
13200 : 386 : origtypes->quick_push (integer_type_node);
13201 : : }
13202 : 634 : expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
13203 : : args, origtypes);
13204 : 634 : set_c_expr_source_range (&expr, loc, close_paren_loc);
13205 : 634 : if (expr.value == error_mark_node)
13206 : : break;
13207 : 634 : switch (stdc_rid)
13208 : : {
13209 : 122 : case C_BUILTIN_STDC_BIT_CEIL:
13210 : 122 : case C_BUILTIN_STDC_BIT_FLOOR:
13211 : 122 : --prec;
13212 : : /* FALLTHRU */
13213 : 169 : case C_BUILTIN_STDC_BIT_WIDTH:
13214 : 169 : expr.value = build2_loc (loc, MINUS_EXPR, integer_type_node,
13215 : : build_int_cst (integer_type_node,
13216 : 169 : prec), expr.value);
13217 : 169 : break;
13218 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13219 : 171 : case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13220 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13221 : 171 : case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13222 : 171 : expr.value = build2_loc (loc, PLUS_EXPR, integer_type_node,
13223 : : expr.value, integer_one_node);
13224 : 171 : break;
13225 : 42 : case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13226 : 42 : expr.value = build2_loc (loc, EQ_EXPR, boolean_type_node,
13227 : : expr.value, integer_one_node);
13228 : 42 : break;
13229 : : default:
13230 : : break;
13231 : : }
13232 : :
13233 : 382 : if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
13234 : : && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
13235 : : {
13236 : 512 : if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
13237 : 470 : expr.value = fold_convert_loc (loc, unsigned_type_node,
13238 : : expr.value);
13239 : : break;
13240 : : }
13241 : : /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
13242 : : or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
13243 : : warnings. The LSHIFT_EXPR is in dead code in that case. */
13244 : 122 : if (integer_zerop (arg)
13245 : 122 : || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
13246 : 42 : expr.value = build_int_cst (type, 0);
13247 : : else
13248 : 80 : expr.value
13249 : 80 : = build2_loc (loc, LSHIFT_EXPR, type,
13250 : : build_int_cst (type,
13251 : : (stdc_rid
13252 : : == C_BUILTIN_STDC_BIT_CEIL
13253 : 114 : ? 2 : 1)), expr.value);
13254 : 122 : if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
13255 : 69 : expr.value = build3_loc (loc, COND_EXPR, type,
13256 : : build2_loc (loc, LE_EXPR,
13257 : : boolean_type_node, arg,
13258 : : build_int_cst (type, 1)),
13259 : : build_int_cst (type, 1),
13260 : : expr.value);
13261 : : else
13262 : 53 : expr.value = build3_loc (loc, COND_EXPR, type,
13263 : : build2_loc (loc, EQ_EXPR,
13264 : : boolean_type_node, arg,
13265 : : build_int_cst (type, 0)),
13266 : : build_int_cst (type, 0),
13267 : : expr.value);
13268 : : break;
13269 : : }
13270 : 0 : case RID_AT_SELECTOR:
13271 : 0 : {
13272 : 0 : gcc_assert (c_dialect_objc ());
13273 : 0 : c_parser_consume_token (parser);
13274 : 0 : matching_parens parens;
13275 : 0 : if (!parens.require_open (parser))
13276 : : {
13277 : 0 : expr.set_error ();
13278 : 0 : break;
13279 : : }
13280 : 0 : tree sel = c_parser_objc_selector_arg (parser);
13281 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13282 : 0 : parens.skip_until_found_close (parser);
13283 : 0 : expr.value = objc_build_selector_expr (loc, sel);
13284 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13285 : : }
13286 : 0 : break;
13287 : 0 : case RID_AT_PROTOCOL:
13288 : 0 : {
13289 : 0 : gcc_assert (c_dialect_objc ());
13290 : 0 : c_parser_consume_token (parser);
13291 : 0 : matching_parens parens;
13292 : 0 : if (!parens.require_open (parser))
13293 : : {
13294 : 0 : expr.set_error ();
13295 : 0 : break;
13296 : : }
13297 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
13298 : : {
13299 : 0 : c_parser_error (parser, "expected identifier");
13300 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13301 : 0 : expr.set_error ();
13302 : 0 : break;
13303 : : }
13304 : 0 : tree id = c_parser_peek_token (parser)->value;
13305 : 0 : c_parser_consume_token (parser);
13306 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13307 : 0 : parens.skip_until_found_close (parser);
13308 : 0 : expr.value = objc_build_protocol_expr (id);
13309 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13310 : : }
13311 : 0 : break;
13312 : 0 : case RID_AT_ENCODE:
13313 : 0 : {
13314 : : /* Extension to support C-structures in the archiver. */
13315 : 0 : gcc_assert (c_dialect_objc ());
13316 : 0 : c_parser_consume_token (parser);
13317 : 0 : matching_parens parens;
13318 : 0 : if (!parens.require_open (parser))
13319 : : {
13320 : 0 : expr.set_error ();
13321 : 0 : break;
13322 : : }
13323 : 0 : t1 = c_parser_type_name (parser);
13324 : 0 : if (t1 == NULL)
13325 : : {
13326 : 0 : expr.set_error ();
13327 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
13328 : 0 : break;
13329 : : }
13330 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13331 : 0 : parens.skip_until_found_close (parser);
13332 : 0 : tree type = groktypename (t1, NULL, NULL);
13333 : 0 : expr.value = objc_build_encode_expr (type);
13334 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13335 : : }
13336 : 0 : break;
13337 : 622 : case RID_GENERIC:
13338 : 622 : expr = c_parser_generic_selection (parser);
13339 : 622 : break;
13340 : 3 : case RID_OMP_ALL_MEMORY:
13341 : 3 : gcc_assert (flag_openmp);
13342 : 3 : c_parser_consume_token (parser);
13343 : 3 : error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
13344 : : "%<depend%> clause");
13345 : 3 : expr.set_error ();
13346 : 3 : break;
13347 : : /* C23 'nullptr' literal. */
13348 : 11217 : case RID_NULLPTR:
13349 : 11217 : c_parser_consume_token (parser);
13350 : 11217 : expr.value = nullptr_node;
13351 : 11217 : set_c_expr_source_range (&expr, tok_range);
13352 : 11217 : pedwarn_c11 (loc, OPT_Wpedantic,
13353 : : "ISO C does not support %qs before C23", "nullptr");
13354 : 11217 : break;
13355 : 3733 : case RID_TRUE:
13356 : 3733 : c_parser_consume_token (parser);
13357 : 3733 : expr.value = boolean_true_node;
13358 : 3733 : set_c_expr_source_range (&expr, tok_range);
13359 : 3733 : break;
13360 : 4097 : case RID_FALSE:
13361 : 4097 : c_parser_consume_token (parser);
13362 : 4097 : expr.value = boolean_false_node;
13363 : 4097 : set_c_expr_source_range (&expr, tok_range);
13364 : 4097 : break;
13365 : 37 : default:
13366 : 37 : c_parser_error (parser, "expected expression");
13367 : 37 : expr.set_error ();
13368 : 37 : break;
13369 : : }
13370 : : break;
13371 : 2 : case CPP_OPEN_SQUARE:
13372 : 2 : if (c_dialect_objc ())
13373 : : {
13374 : 0 : tree receiver, args;
13375 : 0 : c_parser_consume_token (parser);
13376 : 0 : receiver = c_parser_objc_receiver (parser);
13377 : 0 : args = c_parser_objc_message_args (parser);
13378 : 0 : location_t close_loc = c_parser_peek_token (parser)->location;
13379 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13380 : : "expected %<]%>");
13381 : 0 : expr.value = objc_build_message_expr (receiver, args);
13382 : 0 : set_c_expr_source_range (&expr, loc, close_loc);
13383 : 0 : break;
13384 : : }
13385 : : /* Else fall through to report error. */
13386 : : /* FALLTHRU */
13387 : 793 : default:
13388 : 793 : c_parser_error (parser, "expected expression");
13389 : 793 : expr.set_error ();
13390 : 793 : break;
13391 : : }
13392 : 230679614 : out:
13393 : 230679614 : return c_parser_postfix_expression_after_primary
13394 : 230679614 : (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
13395 : : }
13396 : :
13397 : : /* Parse a postfix expression after a parenthesized type name: the
13398 : : brace-enclosed initializer of a compound literal, possibly followed
13399 : : by some postfix operators. This is separate because it is not
13400 : : possible to tell until after the type name whether a cast
13401 : : expression has a cast or a compound literal, or whether the operand
13402 : : of sizeof is a parenthesized type name or starts with a compound
13403 : : literal. TYPE_LOC is the location where TYPE_NAME starts--the
13404 : : location of the first token after the parentheses around the type
13405 : : name. */
13406 : :
13407 : : static struct c_expr
13408 : 898082 : c_parser_postfix_expression_after_paren_type (c_parser *parser,
13409 : : struct c_declspecs *scspecs,
13410 : : struct c_type_name *type_name,
13411 : : location_t type_loc)
13412 : : {
13413 : 898082 : tree type;
13414 : 898082 : struct c_expr init;
13415 : 898082 : bool non_const;
13416 : 898082 : struct c_expr expr;
13417 : 898082 : location_t start_loc;
13418 : 898082 : tree type_expr = NULL_TREE;
13419 : 898082 : bool type_expr_const = true;
13420 : 898082 : bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
13421 : 898082 : unsigned int underspec_state = 0;
13422 : 898082 : check_compound_literal_type (type_loc, type_name);
13423 : 898082 : rich_location richloc (line_table, type_loc);
13424 : 898082 : start_loc = c_parser_peek_token (parser)->location;
13425 : 898082 : if (constexpr_p)
13426 : : {
13427 : 232 : underspec_state = start_underspecified_init (start_loc, NULL_TREE);
13428 : : /* A constexpr compound literal is subject to the constraints on
13429 : : underspecified declarations, which may not declare tags or
13430 : : members or structures or unions; it is undefined behavior to
13431 : : declare the members of an enumeration. Where the structure,
13432 : : union or enumeration type is declared within the compound
13433 : : literal initializer, this is diagnosed elsewhere as a result
13434 : : of the above call to start_underspecified_init. Diagnose
13435 : : here the case of declaring such a type in the type specifiers
13436 : : of the compound literal. */
13437 : 232 : switch (type_name->specs->typespec_kind)
13438 : : {
13439 : 2 : case ctsk_tagfirstref:
13440 : 2 : case ctsk_tagfirstref_attrs:
13441 : 2 : error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
13442 : : type_name->specs->type);
13443 : 2 : break;
13444 : :
13445 : 4 : case ctsk_tagdef:
13446 : 4 : error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
13447 : : type_name->specs->type);
13448 : 4 : break;
13449 : :
13450 : : default:
13451 : : break;
13452 : : }
13453 : : }
13454 : 898082 : start_init (NULL_TREE, NULL,
13455 : 898082 : (global_bindings_p ()
13456 : 897832 : || (scspecs && scspecs->storage_class == csc_static)
13457 : 1795886 : || constexpr_p), constexpr_p, &richloc);
13458 : 898082 : type = groktypename (type_name, &type_expr, &type_expr_const);
13459 : 898082 : if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
13460 : : {
13461 : 9 : error_at (type_loc, "compound literal has variable size");
13462 : 9 : type = error_mark_node;
13463 : : }
13464 : 898073 : else if (TREE_CODE (type) == FUNCTION_TYPE)
13465 : : {
13466 : 3 : error_at (type_loc, "compound literal has function type");
13467 : 3 : type = error_mark_node;
13468 : : }
13469 : 898082 : if (constexpr_p && type != error_mark_node)
13470 : : {
13471 : 232 : tree type_no_array = strip_array_types (type);
13472 : : /* The type of a constexpr object must not be variably modified
13473 : : (which applies to all compound literals), volatile, atomic or
13474 : : restrict qualified or have a member with such a qualifier.
13475 : : const qualification is implicitly added. */
13476 : 232 : if (TYPE_QUALS (type_no_array)
13477 : 232 : & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
13478 : 9 : error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
13479 : 223 : else if (RECORD_OR_UNION_TYPE_P (type_no_array)
13480 : 223 : && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
13481 : 8 : error_at (type_loc, "invalid qualifiers for field of "
13482 : : "%<constexpr%> object");
13483 : 464 : type = c_build_qualified_type (type,
13484 : 232 : (TYPE_QUALS (type_no_array)
13485 : : | TYPE_QUAL_CONST));
13486 : : }
13487 : 898082 : init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE);
13488 : 898082 : if (constexpr_p)
13489 : 232 : finish_underspecified_init (NULL_TREE, underspec_state);
13490 : 898082 : finish_init ();
13491 : 898082 : maybe_warn_string_init (type_loc, type, init);
13492 : :
13493 : 898082 : if (type != error_mark_node
13494 : 898066 : && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
13495 : 898082 : && current_function_decl)
13496 : : {
13497 : 0 : error ("compound literal qualified by address-space qualifier");
13498 : 0 : type = error_mark_node;
13499 : : }
13500 : :
13501 : 1795880 : if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
13502 : 898082 : "ISO C90 forbids compound literals") && scspecs)
13503 : 284 : pedwarn_c11 (start_loc, OPT_Wpedantic,
13504 : : "ISO C forbids storage class specifiers in compound literals "
13505 : : "before C23");
13506 : 898082 : non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
13507 : 1795713 : ? CONSTRUCTOR_NON_CONST (init.value)
13508 : 451 : : init.original_code == C_MAYBE_CONST_EXPR);
13509 : 898082 : non_const |= !type_expr_const;
13510 : 898082 : unsigned int alignas_align = 0;
13511 : 898082 : if (type != error_mark_node
13512 : 898066 : && type_name->specs->align_log != -1)
13513 : : {
13514 : 4 : alignas_align = 1U << type_name->specs->align_log;
13515 : 4 : if (alignas_align < min_align_of_type (type))
13516 : : {
13517 : 1 : error_at (type_name->specs->locations[cdw_alignas],
13518 : : "%<_Alignas%> specifiers cannot reduce "
13519 : : "alignment of compound literal");
13520 : 1 : alignas_align = 0;
13521 : : }
13522 : : }
13523 : 898082 : expr.value = build_compound_literal (start_loc, type, init.value, non_const,
13524 : : alignas_align, scspecs);
13525 : 898082 : set_c_expr_source_range (&expr, init.src_range);
13526 : 898082 : expr.m_decimal = 0;
13527 : 898082 : expr.original_code = ERROR_MARK;
13528 : 898082 : expr.original_type = NULL;
13529 : 898082 : if (type != error_mark_node
13530 : 898066 : && expr.value != error_mark_node
13531 : 897994 : && type_expr)
13532 : : {
13533 : 30 : if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
13534 : : {
13535 : 18 : gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
13536 : 18 : C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
13537 : : }
13538 : : else
13539 : : {
13540 : 12 : gcc_assert (!non_const);
13541 : 12 : expr.value = build2 (C_MAYBE_CONST_EXPR, type,
13542 : : type_expr, expr.value);
13543 : : }
13544 : : }
13545 : 898082 : return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
13546 : 898082 : }
13547 : :
13548 : : /* Callback function for sizeof_pointer_memaccess_warning to compare
13549 : : types. */
13550 : :
13551 : : static bool
13552 : 3456 : sizeof_ptr_memacc_comptypes (tree type1, tree type2)
13553 : : {
13554 : 3456 : return comptypes (type1, type2) == 1;
13555 : : }
13556 : :
13557 : : /* Warn for patterns where abs-like function appears to be used incorrectly,
13558 : : gracefully ignore any non-abs-like function. The warning location should
13559 : : be LOC. FNDECL is the declaration of called function, it must be a
13560 : : BUILT_IN_NORMAL function. ARG is the first and only argument of the
13561 : : call. */
13562 : :
13563 : : static void
13564 : 57387 : warn_for_abs (location_t loc, tree fndecl, tree arg)
13565 : : {
13566 : : /* Avoid warning in unreachable subexpressions. */
13567 : 57387 : if (c_inhibit_evaluation_warnings)
13568 : : return;
13569 : :
13570 : 31049 : tree atype = TREE_TYPE (arg);
13571 : :
13572 : : /* Casts from pointers (and thus arrays and fndecls) will generate
13573 : : -Wint-conversion warnings. Most other wrong types hopefully lead to type
13574 : : mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
13575 : : types and possibly other exotic types. */
13576 : 31049 : if (!INTEGRAL_TYPE_P (atype)
13577 : 31049 : && !SCALAR_FLOAT_TYPE_P (atype)
13578 : 5123 : && TREE_CODE (atype) != COMPLEX_TYPE)
13579 : : return;
13580 : :
13581 : 26404 : enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13582 : :
13583 : 26404 : switch (fcode)
13584 : : {
13585 : 35 : case BUILT_IN_ABS:
13586 : 35 : case BUILT_IN_LABS:
13587 : 35 : case BUILT_IN_LLABS:
13588 : 35 : case BUILT_IN_IMAXABS:
13589 : 35 : if (!INTEGRAL_TYPE_P (atype))
13590 : : {
13591 : 4 : if (SCALAR_FLOAT_TYPE_P (atype))
13592 : 3 : warning_at (loc, OPT_Wabsolute_value,
13593 : : "using integer absolute value function %qD when "
13594 : : "argument is of floating-point type %qT",
13595 : : fndecl, atype);
13596 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13597 : 1 : warning_at (loc, OPT_Wabsolute_value,
13598 : : "using integer absolute value function %qD when "
13599 : : "argument is of complex type %qT", fndecl, atype);
13600 : : else
13601 : : gcc_unreachable ();
13602 : 4 : return;
13603 : : }
13604 : 31 : if (TYPE_UNSIGNED (atype))
13605 : 9 : warning_at (loc, OPT_Wabsolute_value,
13606 : : "taking the absolute value of unsigned type %qT "
13607 : : "has no effect", atype);
13608 : : break;
13609 : :
13610 : 334 : CASE_FLT_FN (BUILT_IN_FABS):
13611 : 334 : CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
13612 : 334 : if (!SCALAR_FLOAT_TYPE_P (atype)
13613 : 334 : || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
13614 : : {
13615 : 4 : if (INTEGRAL_TYPE_P (atype))
13616 : 2 : warning_at (loc, OPT_Wabsolute_value,
13617 : : "using floating-point absolute value function %qD "
13618 : : "when argument is of integer type %qT", fndecl, atype);
13619 : 2 : else if (DECIMAL_FLOAT_TYPE_P (atype))
13620 : 1 : warning_at (loc, OPT_Wabsolute_value,
13621 : : "using floating-point absolute value function %qD "
13622 : : "when argument is of decimal floating-point type %qT",
13623 : : fndecl, atype);
13624 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13625 : 1 : warning_at (loc, OPT_Wabsolute_value,
13626 : : "using floating-point absolute value function %qD when "
13627 : : "argument is of complex type %qT", fndecl, atype);
13628 : : else
13629 : 0 : gcc_unreachable ();
13630 : 4 : return;
13631 : : }
13632 : : break;
13633 : :
13634 : 7 : CASE_FLT_FN (BUILT_IN_CABS):
13635 : 7 : if (TREE_CODE (atype) != COMPLEX_TYPE)
13636 : : {
13637 : 4 : if (INTEGRAL_TYPE_P (atype))
13638 : 2 : warning_at (loc, OPT_Wabsolute_value,
13639 : : "using complex absolute value function %qD when "
13640 : : "argument is of integer type %qT", fndecl, atype);
13641 : 2 : else if (SCALAR_FLOAT_TYPE_P (atype))
13642 : 2 : warning_at (loc, OPT_Wabsolute_value,
13643 : : "using complex absolute value function %qD when "
13644 : : "argument is of floating-point type %qT",
13645 : : fndecl, atype);
13646 : : else
13647 : : gcc_unreachable ();
13648 : :
13649 : 4 : return;
13650 : : }
13651 : : break;
13652 : :
13653 : 6 : case BUILT_IN_FABSD32:
13654 : 6 : case BUILT_IN_FABSD64:
13655 : 6 : case BUILT_IN_FABSD128:
13656 : 6 : case BUILT_IN_FABSD64X:
13657 : 6 : if (!DECIMAL_FLOAT_TYPE_P (atype))
13658 : : {
13659 : 4 : if (INTEGRAL_TYPE_P (atype))
13660 : 1 : warning_at (loc, OPT_Wabsolute_value,
13661 : : "using decimal floating-point absolute value "
13662 : : "function %qD when argument is of integer type %qT",
13663 : : fndecl, atype);
13664 : 3 : else if (SCALAR_FLOAT_TYPE_P (atype))
13665 : 2 : warning_at (loc, OPT_Wabsolute_value,
13666 : : "using decimal floating-point absolute value "
13667 : : "function %qD when argument is of floating-point "
13668 : : "type %qT", fndecl, atype);
13669 : 1 : else if (TREE_CODE (atype) == COMPLEX_TYPE)
13670 : 1 : warning_at (loc, OPT_Wabsolute_value,
13671 : : "using decimal floating-point absolute value "
13672 : : "function %qD when argument is of complex type %qT",
13673 : : fndecl, atype);
13674 : : else
13675 : 0 : gcc_unreachable ();
13676 : 4 : return;
13677 : : }
13678 : : break;
13679 : :
13680 : : default:
13681 : : return;
13682 : : }
13683 : :
13684 : 366 : if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13685 : : return;
13686 : :
13687 : 365 : tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13688 : 365 : if (TREE_CODE (atype) == COMPLEX_TYPE)
13689 : : {
13690 : 3 : gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
13691 : 3 : atype = TREE_TYPE (atype);
13692 : 3 : ftype = TREE_TYPE (ftype);
13693 : : }
13694 : :
13695 : 365 : if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
13696 : 9 : warning_at (loc, OPT_Wabsolute_value,
13697 : : "absolute value function %qD given an argument of type %qT "
13698 : : "but has parameter of type %qT which may cause truncation "
13699 : : "of value", fndecl, atype, ftype);
13700 : : }
13701 : :
13702 : :
13703 : : /* Parse a postfix expression after the initial primary or compound
13704 : : literal; that is, parse a series of postfix operators.
13705 : :
13706 : : EXPR_LOC is the location of the primary expression. */
13707 : :
13708 : : static struct c_expr
13709 : 231577743 : c_parser_postfix_expression_after_primary (c_parser *parser,
13710 : : location_t expr_loc,
13711 : : struct c_expr expr)
13712 : : {
13713 : 231577743 : struct c_expr orig_expr;
13714 : 231577743 : tree ident, idx, len;
13715 : 231577743 : location_t sizeof_arg_loc[6], comp_loc;
13716 : 231577743 : tree sizeof_arg[6];
13717 : 231577743 : unsigned int literal_zero_mask;
13718 : 231577743 : unsigned int i;
13719 : 231577743 : vec<tree, va_gc> *exprlist;
13720 : 231577743 : vec<tree, va_gc> *origtypes = NULL;
13721 : 231577743 : vec<location_t> arg_loc = vNULL;
13722 : 286404138 : location_t start;
13723 : 286404138 : location_t finish;
13724 : :
13725 : 286404138 : while (true)
13726 : : {
13727 : 286404138 : location_t op_loc = c_parser_peek_token (parser)->location;
13728 : 286404138 : switch (c_parser_peek_token (parser)->type)
13729 : : {
13730 : 3392430 : case CPP_OPEN_SQUARE:
13731 : : /* Array reference. */
13732 : 3392430 : c_parser_consume_token (parser);
13733 : 3392430 : idx = len = NULL_TREE;
13734 : 3392430 : if (!c_omp_array_section_p
13735 : 3393144 : || c_parser_next_token_is_not (parser, CPP_COLON))
13736 : 3392238 : idx = c_parser_expression (parser).value;
13737 : :
13738 : 3392430 : if (c_omp_array_section_p
13739 : 3393144 : && c_parser_next_token_is (parser, CPP_COLON))
13740 : : {
13741 : 569 : c_parser_consume_token (parser);
13742 : 569 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
13743 : 534 : len = c_parser_expression (parser).value;
13744 : :
13745 : 569 : expr.value = build_omp_array_section (op_loc, expr.value, idx,
13746 : : len);
13747 : : }
13748 : : else
13749 : 3391861 : expr.value = build_array_ref (op_loc, expr.value, idx);
13750 : :
13751 : 3392430 : c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
13752 : : "expected %<]%>");
13753 : :
13754 : 3392430 : start = expr.get_start ();
13755 : 3392430 : finish = parser->tokens_buf[0].location;
13756 : 3392430 : set_c_expr_source_range (&expr, start, finish);
13757 : 3392430 : expr.original_code = ERROR_MARK;
13758 : 3392430 : expr.original_type = NULL;
13759 : 3392430 : expr.m_decimal = 0;
13760 : 3392430 : break;
13761 : 48537971 : case CPP_OPEN_PAREN:
13762 : : /* Function call. */
13763 : 48537971 : {
13764 : 48537971 : matching_parens parens;
13765 : 48537971 : parens.consume_open (parser);
13766 : 388303768 : for (i = 0; i < 6; i++)
13767 : : {
13768 : 291227826 : sizeof_arg[i] = NULL_TREE;
13769 : 291227826 : sizeof_arg_loc[i] = UNKNOWN_LOCATION;
13770 : : }
13771 : 48537971 : literal_zero_mask = 0;
13772 : 48537971 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
13773 : : exprlist = NULL;
13774 : 37130568 : else if (TREE_CODE (expr.value) == FUNCTION_DECL
13775 : 37063534 : && fndecl_built_in_p (expr.value, BUILT_IN_CLASSIFY_TYPE)
13776 : 37132414 : && c_parser_next_tokens_start_typename (parser,
13777 : : cla_prefer_id))
13778 : : {
13779 : : /* __builtin_classify_type (type) */
13780 : 29 : c_inhibit_evaluation_warnings++;
13781 : 29 : in_alignof++;
13782 : 29 : struct c_type_name *type = c_parser_type_name (parser);
13783 : 29 : c_inhibit_evaluation_warnings--;
13784 : 29 : in_alignof--;
13785 : 29 : struct c_typespec ret;
13786 : 29 : ret.expr = NULL_TREE;
13787 : 29 : ret.spec = error_mark_node;
13788 : 29 : ret.expr_const_operands = false;
13789 : 29 : if (type != NULL)
13790 : 29 : ret.spec = groktypename (type, &ret.expr,
13791 : : &ret.expr_const_operands);
13792 : 29 : parens.skip_until_found_close (parser);
13793 : 29 : expr.value = build_int_cst (integer_type_node,
13794 : 29 : type_to_class (ret.spec));
13795 : 29 : break;
13796 : : }
13797 : : else
13798 : 37130539 : exprlist = c_parser_expr_list (parser, true, false, &origtypes,
13799 : : sizeof_arg_loc, sizeof_arg,
13800 : : &arg_loc, &literal_zero_mask);
13801 : 48537942 : parens.skip_until_found_close (parser);
13802 : : }
13803 : 48537942 : orig_expr = expr;
13804 : 48537942 : mark_exp_read (expr.value);
13805 : 48537942 : if (warn_sizeof_pointer_memaccess)
13806 : 4536316 : sizeof_pointer_memaccess_warning (sizeof_arg_loc,
13807 : : expr.value, exprlist,
13808 : : sizeof_arg,
13809 : : sizeof_ptr_memacc_comptypes);
13810 : 48537942 : if (TREE_CODE (expr.value) == FUNCTION_DECL)
13811 : : {
13812 : 48461177 : if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET)
13813 : 48492372 : && vec_safe_length (exprlist) == 3)
13814 : : {
13815 : 31195 : tree arg0 = (*exprlist)[0];
13816 : 31195 : tree arg2 = (*exprlist)[2];
13817 : 31195 : warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
13818 : : }
13819 : 48461177 : if (warn_absolute_value
13820 : 4265072 : && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL)
13821 : 48600214 : && vec_safe_length (exprlist) == 1)
13822 : 57387 : warn_for_abs (expr_loc, expr.value, (*exprlist)[0]);
13823 : 48461177 : if (parser->omp_for_parse_state
13824 : 177 : && parser->omp_for_parse_state->in_intervening_code
13825 : 48461315 : && omp_runtime_api_call (expr.value))
13826 : : {
13827 : 2 : error_at (expr_loc, "calls to the OpenMP runtime API are "
13828 : : "not permitted in intervening code");
13829 : 2 : parser->omp_for_parse_state->fail = true;
13830 : : }
13831 : 48461177 : if (warn_calloc_transposed_args)
13832 : 4265047 : if (tree attr = lookup_attribute ("alloc_size",
13833 : 4265047 : TYPE_ATTRIBUTES
13834 : : (TREE_TYPE (expr.value))))
13835 : 1259 : if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
13836 : 146 : warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
13837 : : sizeof_arg, attr);
13838 : : }
13839 : :
13840 : 48537942 : start = expr.get_start ();
13841 : 48537942 : finish = parser->tokens_buf[0].get_finish ();
13842 : 48537942 : expr.value
13843 : 48537942 : = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
13844 : : exprlist, origtypes);
13845 : 48537942 : set_c_expr_source_range (&expr, start, finish);
13846 : 48537942 : expr.m_decimal = 0;
13847 : :
13848 : 48537942 : expr.original_code = ERROR_MARK;
13849 : 48537942 : if (TREE_CODE (expr.value) == INTEGER_CST
13850 : 12770 : && TREE_CODE (orig_expr.value) == FUNCTION_DECL
13851 : 48550712 : && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P))
13852 : 1531 : expr.original_code = C_MAYBE_CONST_EXPR;
13853 : 48537942 : expr.original_type = NULL;
13854 : 48537942 : if (exprlist)
13855 : : {
13856 : 37130539 : release_tree_vector (exprlist);
13857 : 37130539 : release_tree_vector (origtypes);
13858 : : }
13859 : 48537942 : arg_loc.release ();
13860 : 48537942 : break;
13861 : 1730316 : case CPP_DOT:
13862 : : /* Structure element reference. */
13863 : 1730316 : c_parser_consume_token (parser);
13864 : 1730316 : expr = default_function_array_conversion (expr_loc, expr);
13865 : 1730316 : if (c_parser_next_token_is (parser, CPP_NAME))
13866 : : {
13867 : 1730316 : c_token *comp_tok = c_parser_peek_token (parser);
13868 : 1730316 : ident = comp_tok->value;
13869 : 1730316 : comp_loc = comp_tok->location;
13870 : : }
13871 : : else
13872 : : {
13873 : 0 : c_parser_error (parser, "expected identifier");
13874 : 0 : expr.set_error ();
13875 : 0 : expr.original_code = ERROR_MARK;
13876 : 0 : expr.original_type = NULL;
13877 : 0 : return expr;
13878 : : }
13879 : 1730316 : start = expr.get_start ();
13880 : 1730316 : finish = c_parser_peek_token (parser)->get_finish ();
13881 : 1730316 : c_parser_consume_token (parser);
13882 : 1730316 : expr.value = build_component_ref (op_loc, expr.value, ident,
13883 : : comp_loc, UNKNOWN_LOCATION);
13884 : 1730316 : set_c_expr_source_range (&expr, start, finish);
13885 : 1730316 : expr.original_code = ERROR_MARK;
13886 : 1730316 : if (TREE_CODE (expr.value) != COMPONENT_REF)
13887 : 30 : expr.original_type = NULL;
13888 : : else
13889 : : {
13890 : : /* Remember the original type of a bitfield. */
13891 : 1730286 : tree field = TREE_OPERAND (expr.value, 1);
13892 : 1730286 : if (TREE_CODE (field) != FIELD_DECL)
13893 : 0 : expr.original_type = NULL;
13894 : : else
13895 : 1730286 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
13896 : : }
13897 : 1730316 : expr.m_decimal = 0;
13898 : 1730316 : break;
13899 : 491658 : case CPP_DEREF:
13900 : : /* Structure element reference. */
13901 : 491658 : c_parser_consume_token (parser);
13902 : 491658 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
13903 : 491658 : if (c_parser_next_token_is (parser, CPP_NAME))
13904 : : {
13905 : 491626 : c_token *comp_tok = c_parser_peek_token (parser);
13906 : 491626 : ident = comp_tok->value;
13907 : 491626 : comp_loc = comp_tok->location;
13908 : : }
13909 : : else
13910 : : {
13911 : 32 : c_parser_error (parser, "expected identifier");
13912 : 32 : expr.set_error ();
13913 : 32 : expr.original_code = ERROR_MARK;
13914 : 32 : expr.original_type = NULL;
13915 : 32 : return expr;
13916 : : }
13917 : 491626 : start = expr.get_start ();
13918 : 491626 : finish = c_parser_peek_token (parser)->get_finish ();
13919 : 491626 : c_parser_consume_token (parser);
13920 : 491626 : expr.value = build_component_ref (op_loc,
13921 : : build_indirect_ref (op_loc,
13922 : : expr.value,
13923 : : RO_ARROW),
13924 : : ident, comp_loc,
13925 : : expr.get_location ());
13926 : 491626 : set_c_expr_source_range (&expr, start, finish);
13927 : 491626 : expr.original_code = ERROR_MARK;
13928 : 491626 : if (TREE_CODE (expr.value) != COMPONENT_REF)
13929 : 119 : expr.original_type = NULL;
13930 : : else
13931 : : {
13932 : : /* Remember the original type of a bitfield. */
13933 : 491507 : tree field = TREE_OPERAND (expr.value, 1);
13934 : 491507 : if (TREE_CODE (field) != FIELD_DECL)
13935 : 0 : expr.original_type = NULL;
13936 : : else
13937 : 491507 : expr.original_type = DECL_BIT_FIELD_TYPE (field);
13938 : : }
13939 : 491626 : expr.m_decimal = 0;
13940 : 491626 : break;
13941 : 656550 : case CPP_PLUS_PLUS:
13942 : : /* Postincrement. */
13943 : 656550 : start = expr.get_start ();
13944 : 656550 : finish = c_parser_peek_token (parser)->get_finish ();
13945 : 656550 : c_parser_consume_token (parser);
13946 : 235481 : if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
13947 : 585341 : && !DECL_READ_P (expr.value)
13948 : 155295 : && (VAR_P (expr.value) ? warn_unused_but_set_variable
13949 : : : warn_unused_but_set_parameter) > 1
13950 : 687491 : && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
13951 : : {
13952 : 30941 : expr = default_function_array_read_conversion (expr_loc, expr);
13953 : 30941 : DECL_READ_P (expr.value) = 0;
13954 : : }
13955 : : else
13956 : 625609 : expr = default_function_array_read_conversion (expr_loc, expr);
13957 : 656550 : expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
13958 : : expr.value, false);
13959 : 656550 : set_c_expr_source_range (&expr, start, finish);
13960 : 656550 : expr.original_code = ERROR_MARK;
13961 : 656550 : expr.original_type = NULL;
13962 : 656550 : break;
13963 : 17502 : case CPP_MINUS_MINUS:
13964 : : /* Postdecrement. */
13965 : 17502 : start = expr.get_start ();
13966 : 17502 : finish = c_parser_peek_token (parser)->get_finish ();
13967 : 17502 : c_parser_consume_token (parser);
13968 : 6394 : if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
13969 : 14514 : && !DECL_READ_P (expr.value)
13970 : 3225 : && (VAR_P (expr.value) ? warn_unused_but_set_variable
13971 : : : warn_unused_but_set_parameter) > 1
13972 : 17838 : && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
13973 : : {
13974 : 336 : expr = default_function_array_read_conversion (expr_loc, expr);
13975 : 336 : DECL_READ_P (expr.value) = 0;
13976 : : }
13977 : : else
13978 : 17166 : expr = default_function_array_read_conversion (expr_loc, expr);
13979 : 17502 : expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
13980 : : expr.value, false);
13981 : 17502 : set_c_expr_source_range (&expr, start, finish);
13982 : 17502 : expr.original_code = ERROR_MARK;
13983 : 17502 : expr.original_type = NULL;
13984 : 17502 : break;
13985 : 231577711 : default:
13986 : 231577711 : return expr;
13987 : : }
13988 : : }
13989 : : }
13990 : :
13991 : : /* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
13992 : :
13993 : : expression:
13994 : : assignment-expression
13995 : : expression , assignment-expression
13996 : : */
13997 : :
13998 : : static struct c_expr
13999 : 54201508 : c_parser_expression (c_parser *parser)
14000 : : {
14001 : 54201508 : location_t tloc = c_parser_peek_token (parser)->location;
14002 : 54201508 : struct c_expr expr;
14003 : 54201508 : expr = c_parser_expr_no_commas (parser, NULL);
14004 : 54201508 : if (c_parser_next_token_is (parser, CPP_COMMA))
14005 : 88265 : expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
14006 : 54302934 : while (c_parser_next_token_is (parser, CPP_COMMA))
14007 : : {
14008 : 101426 : struct c_expr next;
14009 : 101426 : tree lhsval;
14010 : 101426 : location_t loc = c_parser_peek_token (parser)->location;
14011 : 101426 : location_t expr_loc;
14012 : 101426 : c_parser_consume_token (parser);
14013 : 101426 : expr_loc = c_parser_peek_token (parser)->location;
14014 : 101426 : lhsval = expr.value;
14015 : 101426 : while (TREE_CODE (lhsval) == COMPOUND_EXPR
14016 : 115441 : || TREE_CODE (lhsval) == NOP_EXPR)
14017 : : {
14018 : 14015 : if (TREE_CODE (lhsval) == COMPOUND_EXPR)
14019 : 13917 : lhsval = TREE_OPERAND (lhsval, 1);
14020 : : else
14021 : 98 : lhsval = TREE_OPERAND (lhsval, 0);
14022 : : }
14023 : 101426 : if (DECL_P (lhsval) || handled_component_p (lhsval))
14024 : 88 : mark_exp_read (lhsval);
14025 : 101426 : if (c_parser_next_token_is (parser, CPP_EMBED))
14026 : : {
14027 : : /* Users aren't interested in milions of -Wunused-value
14028 : : warnings when using #embed inside of a comma expression,
14029 : : and one CPP_NUMBER plus CPP_COMMA before it and one
14030 : : CPP_COMMA plus CPP_NUMBER after it is guaranteed by
14031 : : the preprocessor. Thus, parse the whole CPP_EMBED just
14032 : : as a single INTEGER_CST, the last byte in it. */
14033 : 1 : c_token *embed = c_parser_peek_token (parser);
14034 : 1 : tree val = embed->value;
14035 : 1 : unsigned last = RAW_DATA_LENGTH (val) - 1;
14036 : 1 : next.value = build_int_cst (TREE_TYPE (val),
14037 : 1 : RAW_DATA_UCHAR_ELT (val, last));
14038 : 1 : next.original_type = integer_type_node;
14039 : 1 : c_parser_consume_token (parser);
14040 : : }
14041 : : else
14042 : : {
14043 : 101425 : next = c_parser_expr_no_commas (parser, NULL);
14044 : 101425 : next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
14045 : : }
14046 : 101426 : expr.value = build_compound_expr (loc, expr.value, next.value);
14047 : 101426 : expr.original_code = COMPOUND_EXPR;
14048 : 101426 : expr.original_type = next.original_type;
14049 : 101426 : expr.m_decimal = 0;
14050 : : }
14051 : 54201508 : return expr;
14052 : : }
14053 : :
14054 : : /* Parse an expression and convert functions or arrays to pointers and
14055 : : lvalues to rvalues. */
14056 : :
14057 : : static struct c_expr
14058 : 41406539 : c_parser_expression_conv (c_parser *parser)
14059 : : {
14060 : 41406539 : struct c_expr expr;
14061 : 41406539 : location_t loc = c_parser_peek_token (parser)->location;
14062 : 41406539 : expr = c_parser_expression (parser);
14063 : 41406539 : expr = convert_lvalue_to_rvalue (loc, expr, true, false);
14064 : 41406539 : return expr;
14065 : : }
14066 : :
14067 : : /* Helper function of c_parser_expr_list. Check if IDXth (0 based)
14068 : : argument is a literal zero alone and if so, set it in literal_zero_mask. */
14069 : :
14070 : : static inline void
14071 : 123095058 : c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
14072 : : unsigned int idx)
14073 : : {
14074 : 123095058 : if (idx >= HOST_BITS_PER_INT)
14075 : : return;
14076 : :
14077 : 123073033 : c_token *tok = c_parser_peek_token (parser);
14078 : 123073033 : switch (tok->type)
14079 : : {
14080 : 6745569 : case CPP_NUMBER:
14081 : 6745569 : case CPP_CHAR:
14082 : 6745569 : case CPP_WCHAR:
14083 : 6745569 : case CPP_CHAR16:
14084 : 6745569 : case CPP_CHAR32:
14085 : 6745569 : case CPP_UTF8CHAR:
14086 : : /* If a parameter is literal zero alone, remember it
14087 : : for -Wmemset-transposed-args warning. */
14088 : 6745569 : if (integer_zerop (tok->value)
14089 : 1235445 : && !TREE_OVERFLOW (tok->value)
14090 : 7981014 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14091 : 855192 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
14092 : 1234611 : *literal_zero_mask |= 1U << idx;
14093 : : default:
14094 : : break;
14095 : : }
14096 : : }
14097 : :
14098 : : /* Parse a non-empty list of expressions. If CONVERT_P, convert
14099 : : functions and arrays to pointers and lvalues to rvalues. If
14100 : : FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
14101 : : locations of function arguments into this vector.
14102 : :
14103 : : nonempty-expr-list:
14104 : : assignment-expression
14105 : : nonempty-expr-list , assignment-expression
14106 : : */
14107 : :
14108 : : static vec<tree, va_gc> *
14109 : 41555873 : c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
14110 : : vec<tree, va_gc> **p_orig_types,
14111 : : location_t *sizeof_arg_loc, tree *sizeof_arg,
14112 : : vec<location_t> *locations,
14113 : : unsigned int *literal_zero_mask)
14114 : : {
14115 : 41555873 : vec<tree, va_gc> *ret;
14116 : 41555873 : vec<tree, va_gc> *orig_types;
14117 : 41555873 : struct c_expr expr;
14118 : 41555873 : unsigned int idx = 0;
14119 : 41555873 : bool save_c_omp_array_section_p = c_omp_array_section_p;
14120 : 41555873 : c_omp_array_section_p = false;
14121 : :
14122 : 41555873 : ret = make_tree_vector ();
14123 : 41555873 : if (p_orig_types == NULL)
14124 : 4425334 : orig_types = NULL;
14125 : : else
14126 : 37130539 : orig_types = make_tree_vector ();
14127 : :
14128 : 41555873 : if (literal_zero_mask)
14129 : 37130539 : c_parser_check_literal_zero (parser, literal_zero_mask, 0);
14130 : 41555873 : expr = c_parser_expr_no_commas (parser, NULL);
14131 : 41555873 : if (convert_p)
14132 : 37131010 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
14133 : 41555873 : if (fold_p)
14134 : 4425334 : expr.value = c_fully_fold (expr.value, false, NULL);
14135 : 41555873 : ret->quick_push (expr.value);
14136 : 41555873 : if (orig_types)
14137 : 37130539 : orig_types->quick_push (expr.original_type);
14138 : 41555873 : if (locations)
14139 : 37130539 : locations->safe_push (expr.get_location ());
14140 : 41555873 : if (sizeof_arg != NULL
14141 : 37130539 : && (expr.original_code == SIZEOF_EXPR
14142 : 37130539 : || expr.original_code == PAREN_SIZEOF_EXPR))
14143 : : {
14144 : 2057 : sizeof_arg[0] = c_last_sizeof_arg;
14145 : 2057 : sizeof_arg_loc[0] = c_last_sizeof_loc;
14146 : : }
14147 : 128843562 : while (c_parser_next_token_is (parser, CPP_COMMA))
14148 : : {
14149 : 87287689 : c_parser_consume_token (parser);
14150 : 87287689 : if (c_parser_next_token_is (parser, CPP_EMBED))
14151 : : {
14152 : 3 : c_token *embed = c_parser_peek_token (parser);
14153 : 3 : tree value = embed->value;
14154 : 3 : expr.original_code = INTEGER_CST;
14155 : 3 : expr.original_type = integer_type_node;
14156 : 3 : expr.value = NULL_TREE;
14157 : 3 : set_c_expr_source_range (&expr, embed->get_range ());
14158 : 3 : expr.m_decimal = 0;
14159 : 381 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
14160 : : {
14161 : 378 : if (literal_zero_mask
14162 : 126 : && idx + 1 < HOST_BITS_PER_INT
14163 : 409 : && RAW_DATA_POINTER (value)[i] == 0)
14164 : 0 : *literal_zero_mask |= 1U << (idx + 1);
14165 : 378 : expr.value = build_int_cst (integer_type_node,
14166 : 378 : RAW_DATA_UCHAR_ELT (value, i));
14167 : 378 : vec_safe_push (ret, expr.value);
14168 : 378 : if (orig_types)
14169 : 126 : vec_safe_push (orig_types, expr.original_type);
14170 : 378 : if (locations)
14171 : 126 : locations->safe_push (expr.get_location ());
14172 : 378 : ++idx;
14173 : : }
14174 : 3 : c_parser_consume_token (parser);
14175 : 3 : continue;
14176 : 3 : }
14177 : 87287686 : if (literal_zero_mask)
14178 : 85964519 : c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
14179 : 87287686 : expr = c_parser_expr_no_commas (parser, NULL);
14180 : 87287686 : if (convert_p)
14181 : 85964785 : expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
14182 : : true);
14183 : 87287686 : if (fold_p)
14184 : 1323167 : expr.value = c_fully_fold (expr.value, false, NULL);
14185 : 87287686 : vec_safe_push (ret, expr.value);
14186 : 87287686 : if (orig_types)
14187 : 85964519 : vec_safe_push (orig_types, expr.original_type);
14188 : 87287686 : if (locations)
14189 : 85964519 : locations->safe_push (expr.get_location ());
14190 : 87287686 : if (++idx < 6
14191 : 85765552 : && sizeof_arg != NULL
14192 : 87287686 : && (expr.original_code == SIZEOF_EXPR
14193 : 84442399 : || expr.original_code == PAREN_SIZEOF_EXPR))
14194 : : {
14195 : 78918 : sizeof_arg[idx] = c_last_sizeof_arg;
14196 : 78918 : sizeof_arg_loc[idx] = c_last_sizeof_loc;
14197 : : }
14198 : : }
14199 : 41555873 : if (orig_types)
14200 : 37130539 : *p_orig_types = orig_types;
14201 : 41555873 : c_omp_array_section_p = save_c_omp_array_section_p;
14202 : 41555873 : return ret;
14203 : : }
14204 : :
14205 : : /* Parse Objective-C-specific constructs. */
14206 : :
14207 : : /* Parse an objc-class-definition.
14208 : :
14209 : : objc-class-definition:
14210 : : @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
14211 : : objc-class-instance-variables[opt] objc-methodprotolist @end
14212 : : @implementation identifier objc-superclass[opt]
14213 : : objc-class-instance-variables[opt]
14214 : : @interface identifier ( identifier ) objc-protocol-refs[opt]
14215 : : objc-methodprotolist @end
14216 : : @interface identifier ( ) objc-protocol-refs[opt]
14217 : : objc-methodprotolist @end
14218 : : @implementation identifier ( identifier )
14219 : :
14220 : : objc-superclass:
14221 : : : identifier
14222 : :
14223 : : "@interface identifier (" must start "@interface identifier (
14224 : : identifier ) ...": objc-methodprotolist in the first production may
14225 : : not start with a parenthesized identifier as a declarator of a data
14226 : : definition with no declaration specifiers if the objc-superclass,
14227 : : objc-protocol-refs and objc-class-instance-variables are omitted. */
14228 : :
14229 : : static void
14230 : 0 : c_parser_objc_class_definition (c_parser *parser, tree attributes)
14231 : : {
14232 : 0 : bool iface_p;
14233 : 0 : tree id1;
14234 : 0 : tree superclass;
14235 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
14236 : : iface_p = true;
14237 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
14238 : : iface_p = false;
14239 : : else
14240 : 0 : gcc_unreachable ();
14241 : :
14242 : 0 : c_parser_consume_token (parser);
14243 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14244 : : {
14245 : 0 : c_parser_error (parser, "expected identifier");
14246 : 0 : return;
14247 : : }
14248 : 0 : id1 = c_parser_peek_token (parser)->value;
14249 : 0 : location_t loc1 = c_parser_peek_token (parser)->location;
14250 : 0 : c_parser_consume_token (parser);
14251 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14252 : : {
14253 : : /* We have a category or class extension. */
14254 : 0 : tree id2;
14255 : 0 : tree proto = NULL_TREE;
14256 : 0 : matching_parens parens;
14257 : 0 : parens.consume_open (parser);
14258 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14259 : : {
14260 : 0 : if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
14261 : : {
14262 : : /* We have a class extension. */
14263 : : id2 = NULL_TREE;
14264 : : }
14265 : : else
14266 : : {
14267 : 0 : c_parser_error (parser, "expected identifier or %<)%>");
14268 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
14269 : 0 : return;
14270 : : }
14271 : : }
14272 : : else
14273 : : {
14274 : 0 : id2 = c_parser_peek_token (parser)->value;
14275 : 0 : c_parser_consume_token (parser);
14276 : : }
14277 : 0 : parens.skip_until_found_close (parser);
14278 : 0 : if (!iface_p)
14279 : : {
14280 : 0 : objc_start_category_implementation (id1, id2);
14281 : 0 : return;
14282 : : }
14283 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14284 : 0 : proto = c_parser_objc_protocol_refs (parser);
14285 : 0 : objc_start_category_interface (id1, id2, proto, attributes);
14286 : 0 : c_parser_objc_methodprotolist (parser);
14287 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14288 : 0 : objc_finish_interface ();
14289 : 0 : return;
14290 : : }
14291 : 0 : if (c_parser_next_token_is (parser, CPP_COLON))
14292 : : {
14293 : 0 : c_parser_consume_token (parser);
14294 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14295 : : {
14296 : 0 : c_parser_error (parser, "expected identifier");
14297 : 0 : return;
14298 : : }
14299 : 0 : superclass = c_parser_peek_token (parser)->value;
14300 : 0 : c_parser_consume_token (parser);
14301 : : }
14302 : : else
14303 : : superclass = NULL_TREE;
14304 : 0 : if (iface_p)
14305 : : {
14306 : 0 : tree proto = NULL_TREE;
14307 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14308 : 0 : proto = c_parser_objc_protocol_refs (parser);
14309 : 0 : objc_start_class_interface (id1, loc1, superclass, proto, attributes);
14310 : : }
14311 : : else
14312 : 0 : objc_start_class_implementation (id1, superclass);
14313 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14314 : 0 : c_parser_objc_class_instance_variables (parser);
14315 : 0 : if (iface_p)
14316 : : {
14317 : 0 : objc_continue_interface ();
14318 : 0 : c_parser_objc_methodprotolist (parser);
14319 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14320 : 0 : objc_finish_interface ();
14321 : : }
14322 : : else
14323 : : {
14324 : 0 : objc_continue_implementation ();
14325 : 0 : return;
14326 : : }
14327 : : }
14328 : :
14329 : : /* Parse objc-class-instance-variables.
14330 : :
14331 : : objc-class-instance-variables:
14332 : : { objc-instance-variable-decl-list[opt] }
14333 : :
14334 : : objc-instance-variable-decl-list:
14335 : : objc-visibility-spec
14336 : : objc-instance-variable-decl ;
14337 : : ;
14338 : : objc-instance-variable-decl-list objc-visibility-spec
14339 : : objc-instance-variable-decl-list objc-instance-variable-decl ;
14340 : : objc-instance-variable-decl-list ;
14341 : :
14342 : : objc-visibility-spec:
14343 : : @private
14344 : : @protected
14345 : : @public
14346 : :
14347 : : objc-instance-variable-decl:
14348 : : struct-declaration
14349 : : */
14350 : :
14351 : : static void
14352 : 0 : c_parser_objc_class_instance_variables (c_parser *parser)
14353 : : {
14354 : 0 : gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
14355 : 0 : c_parser_consume_token (parser);
14356 : 0 : while (c_parser_next_token_is_not (parser, CPP_EOF))
14357 : : {
14358 : 0 : tree decls;
14359 : : /* Parse any stray semicolon. */
14360 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14361 : : {
14362 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14363 : : "extra semicolon");
14364 : 0 : c_parser_consume_token (parser);
14365 : 0 : continue;
14366 : : }
14367 : : /* Stop if at the end of the instance variables. */
14368 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
14369 : : {
14370 : 0 : c_parser_consume_token (parser);
14371 : 0 : break;
14372 : : }
14373 : : /* Parse any objc-visibility-spec. */
14374 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
14375 : : {
14376 : 0 : c_parser_consume_token (parser);
14377 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
14378 : 0 : continue;
14379 : : }
14380 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
14381 : : {
14382 : 0 : c_parser_consume_token (parser);
14383 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
14384 : 0 : continue;
14385 : : }
14386 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
14387 : : {
14388 : 0 : c_parser_consume_token (parser);
14389 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
14390 : 0 : continue;
14391 : : }
14392 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
14393 : : {
14394 : 0 : c_parser_consume_token (parser);
14395 : 0 : objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
14396 : 0 : continue;
14397 : : }
14398 : 0 : else if (c_parser_next_token_is (parser, CPP_PRAGMA))
14399 : : {
14400 : 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14401 : 0 : continue;
14402 : : }
14403 : :
14404 : : /* Parse some comma-separated declarations. */
14405 : 0 : decls = c_parser_struct_declaration (parser, NULL);
14406 : 0 : if (decls == NULL)
14407 : : {
14408 : : /* There is a syntax error. We want to skip the offending
14409 : : tokens up to the next ';' (included) or '}'
14410 : : (excluded). */
14411 : :
14412 : : /* First, skip manually a ')' or ']'. This is because they
14413 : : reduce the nesting level, so c_parser_skip_until_found()
14414 : : wouldn't be able to skip past them. */
14415 : 0 : c_token *token = c_parser_peek_token (parser);
14416 : 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
14417 : 0 : c_parser_consume_token (parser);
14418 : :
14419 : : /* Then, do the standard skipping. */
14420 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14421 : :
14422 : : /* We hopefully recovered. Start normal parsing again. */
14423 : 0 : parser->error = false;
14424 : 0 : continue;
14425 : 0 : }
14426 : : else
14427 : : {
14428 : : /* Comma-separated instance variables are chained together
14429 : : in reverse order; add them one by one. */
14430 : 0 : tree ivar = nreverse (decls);
14431 : 0 : for (; ivar; ivar = DECL_CHAIN (ivar))
14432 : 0 : objc_add_instance_variable (copy_node (ivar));
14433 : : }
14434 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14435 : : }
14436 : 0 : }
14437 : :
14438 : : /* Parse an objc-class-declaration.
14439 : :
14440 : : objc-class-declaration:
14441 : : @class identifier-list ;
14442 : : */
14443 : :
14444 : : static void
14445 : 0 : c_parser_objc_class_declaration (c_parser *parser)
14446 : : {
14447 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
14448 : 0 : c_parser_consume_token (parser);
14449 : : /* Any identifiers, including those declared as type names, are OK
14450 : : here. */
14451 : 0 : while (true)
14452 : : {
14453 : 0 : tree id;
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 : parser->error = false;
14459 : 0 : return;
14460 : : }
14461 : 0 : id = c_parser_peek_token (parser)->value;
14462 : 0 : objc_declare_class (id);
14463 : 0 : c_parser_consume_token (parser);
14464 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14465 : 0 : c_parser_consume_token (parser);
14466 : : else
14467 : : break;
14468 : 0 : }
14469 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14470 : : }
14471 : :
14472 : : /* Parse an objc-alias-declaration.
14473 : :
14474 : : objc-alias-declaration:
14475 : : @compatibility_alias identifier identifier ;
14476 : : */
14477 : :
14478 : : static void
14479 : 0 : c_parser_objc_alias_declaration (c_parser *parser)
14480 : : {
14481 : 0 : tree id1, id2;
14482 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
14483 : 0 : c_parser_consume_token (parser);
14484 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14485 : : {
14486 : 0 : c_parser_error (parser, "expected identifier");
14487 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14488 : 0 : return;
14489 : : }
14490 : 0 : id1 = c_parser_peek_token (parser)->value;
14491 : 0 : c_parser_consume_token (parser);
14492 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14493 : : {
14494 : 0 : c_parser_error (parser, "expected identifier");
14495 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
14496 : 0 : return;
14497 : : }
14498 : 0 : id2 = c_parser_peek_token (parser)->value;
14499 : 0 : c_parser_consume_token (parser);
14500 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14501 : 0 : objc_declare_alias (id1, id2);
14502 : : }
14503 : :
14504 : : /* Parse an objc-protocol-definition.
14505 : :
14506 : : objc-protocol-definition:
14507 : : @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
14508 : : @protocol identifier-list ;
14509 : :
14510 : : "@protocol identifier ;" should be resolved as "@protocol
14511 : : identifier-list ;": objc-methodprotolist may not start with a
14512 : : semicolon in the first alternative if objc-protocol-refs are
14513 : : omitted. */
14514 : :
14515 : : static void
14516 : 0 : c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
14517 : : {
14518 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
14519 : :
14520 : 0 : c_parser_consume_token (parser);
14521 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14522 : : {
14523 : 0 : c_parser_error (parser, "expected identifier");
14524 : 0 : return;
14525 : : }
14526 : 0 : if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14527 : 0 : || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
14528 : : {
14529 : : /* Any identifiers, including those declared as type names, are
14530 : : OK here. */
14531 : 0 : while (true)
14532 : : {
14533 : 0 : tree id;
14534 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14535 : : {
14536 : 0 : c_parser_error (parser, "expected identifier");
14537 : 0 : break;
14538 : : }
14539 : 0 : id = c_parser_peek_token (parser)->value;
14540 : 0 : objc_declare_protocol (id, attributes);
14541 : 0 : c_parser_consume_token (parser);
14542 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14543 : 0 : c_parser_consume_token (parser);
14544 : : else
14545 : : break;
14546 : 0 : }
14547 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14548 : : }
14549 : : else
14550 : : {
14551 : 0 : tree id = c_parser_peek_token (parser)->value;
14552 : 0 : tree proto = NULL_TREE;
14553 : 0 : c_parser_consume_token (parser);
14554 : 0 : if (c_parser_next_token_is (parser, CPP_LESS))
14555 : 0 : proto = c_parser_objc_protocol_refs (parser);
14556 : 0 : parser->objc_pq_context = true;
14557 : 0 : objc_start_protocol (id, proto, attributes);
14558 : 0 : c_parser_objc_methodprotolist (parser);
14559 : 0 : c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
14560 : 0 : parser->objc_pq_context = false;
14561 : 0 : objc_finish_interface ();
14562 : : }
14563 : : }
14564 : :
14565 : : /* Parse an objc-method-type.
14566 : :
14567 : : objc-method-type:
14568 : : +
14569 : : -
14570 : :
14571 : : Return true if it is a class method (+) and false if it is
14572 : : an instance method (-).
14573 : : */
14574 : : static inline bool
14575 : 0 : c_parser_objc_method_type (c_parser *parser)
14576 : : {
14577 : 0 : switch (c_parser_peek_token (parser)->type)
14578 : : {
14579 : 0 : case CPP_PLUS:
14580 : 0 : c_parser_consume_token (parser);
14581 : 0 : return true;
14582 : 0 : case CPP_MINUS:
14583 : 0 : c_parser_consume_token (parser);
14584 : 0 : return false;
14585 : 0 : default:
14586 : 0 : gcc_unreachable ();
14587 : : }
14588 : : }
14589 : :
14590 : : /* Parse an objc-method-definition.
14591 : :
14592 : : objc-method-definition:
14593 : : objc-method-type objc-method-decl ;[opt] compound-statement
14594 : : */
14595 : :
14596 : : static void
14597 : 0 : c_parser_objc_method_definition (c_parser *parser)
14598 : : {
14599 : 0 : bool is_class_method = c_parser_objc_method_type (parser);
14600 : 0 : tree decl, attributes = NULL_TREE, expr = NULL_TREE;
14601 : 0 : parser->objc_pq_context = true;
14602 : 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14603 : : &expr);
14604 : 0 : if (decl == error_mark_node)
14605 : 0 : return; /* Bail here. */
14606 : :
14607 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON))
14608 : : {
14609 : 0 : c_parser_consume_token (parser);
14610 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14611 : : "extra semicolon in method definition specified");
14612 : : }
14613 : :
14614 : 0 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14615 : : {
14616 : 0 : c_parser_error (parser, "expected %<{%>");
14617 : 0 : return;
14618 : : }
14619 : :
14620 : 0 : parser->objc_pq_context = false;
14621 : 0 : if (objc_start_method_definition (is_class_method, decl, attributes, expr))
14622 : : {
14623 : 0 : add_stmt (c_parser_compound_statement (parser));
14624 : 0 : objc_finish_method_definition (current_function_decl);
14625 : : }
14626 : : else
14627 : : {
14628 : : /* This code is executed when we find a method definition
14629 : : outside of an @implementation context (or invalid for other
14630 : : reasons). Parse the method (to keep going) but do not emit
14631 : : any code.
14632 : : */
14633 : 0 : c_parser_compound_statement (parser);
14634 : : }
14635 : : }
14636 : :
14637 : : /* Parse an objc-methodprotolist.
14638 : :
14639 : : objc-methodprotolist:
14640 : : empty
14641 : : objc-methodprotolist objc-methodproto
14642 : : objc-methodprotolist declaration
14643 : : objc-methodprotolist ;
14644 : : @optional
14645 : : @required
14646 : :
14647 : : The declaration is a data definition, which may be missing
14648 : : declaration specifiers under the same rules and diagnostics as
14649 : : other data definitions outside functions, and the stray semicolon
14650 : : is diagnosed the same way as a stray semicolon outside a
14651 : : function. */
14652 : :
14653 : : static void
14654 : 0 : c_parser_objc_methodprotolist (c_parser *parser)
14655 : : {
14656 : 0 : while (true)
14657 : : {
14658 : : /* The list is terminated by @end. */
14659 : 0 : switch (c_parser_peek_token (parser)->type)
14660 : : {
14661 : 0 : case CPP_SEMICOLON:
14662 : 0 : pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14663 : : "ISO C does not allow extra %<;%> outside of a function");
14664 : 0 : c_parser_consume_token (parser);
14665 : 0 : break;
14666 : 0 : case CPP_PLUS:
14667 : 0 : case CPP_MINUS:
14668 : 0 : c_parser_objc_methodproto (parser);
14669 : 0 : break;
14670 : 0 : case CPP_PRAGMA:
14671 : 0 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14672 : 0 : break;
14673 : : case CPP_EOF:
14674 : : return;
14675 : 0 : default:
14676 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_END))
14677 : : return;
14678 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
14679 : 0 : c_parser_objc_at_property_declaration (parser);
14680 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
14681 : : {
14682 : 0 : objc_set_method_opt (true);
14683 : 0 : c_parser_consume_token (parser);
14684 : : }
14685 : 0 : else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
14686 : : {
14687 : 0 : objc_set_method_opt (false);
14688 : 0 : c_parser_consume_token (parser);
14689 : : }
14690 : : else
14691 : 0 : c_parser_declaration_or_fndef (parser, false, false, true,
14692 : : false, true, false);
14693 : : break;
14694 : : }
14695 : : }
14696 : : }
14697 : :
14698 : : /* Parse an objc-methodproto.
14699 : :
14700 : : objc-methodproto:
14701 : : objc-method-type objc-method-decl ;
14702 : : */
14703 : :
14704 : : static void
14705 : 0 : c_parser_objc_methodproto (c_parser *parser)
14706 : : {
14707 : 0 : bool is_class_method = c_parser_objc_method_type (parser);
14708 : 0 : tree decl, attributes = NULL_TREE;
14709 : :
14710 : : /* Remember protocol qualifiers in prototypes. */
14711 : 0 : parser->objc_pq_context = true;
14712 : 0 : decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14713 : : NULL);
14714 : : /* Forget protocol qualifiers now. */
14715 : 0 : parser->objc_pq_context = false;
14716 : :
14717 : : /* Do not allow the presence of attributes to hide an erroneous
14718 : : method implementation in the interface section. */
14719 : 0 : if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
14720 : : {
14721 : 0 : c_parser_error (parser, "expected %<;%>");
14722 : 0 : return;
14723 : : }
14724 : :
14725 : 0 : if (decl != error_mark_node)
14726 : 0 : objc_add_method_declaration (is_class_method, decl, attributes);
14727 : :
14728 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
14729 : : }
14730 : :
14731 : : /* If we are at a position that method attributes may be present, check that
14732 : : there are not any parsed already (a syntax error) and then collect any
14733 : : specified at the current location. Finally, if new attributes were present,
14734 : : check that the next token is legal ( ';' for decls and '{' for defs). */
14735 : :
14736 : : static bool
14737 : 0 : c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
14738 : : {
14739 : 0 : bool bad = false;
14740 : 0 : if (*attributes)
14741 : : {
14742 : 0 : c_parser_error (parser,
14743 : : "method attributes must be specified at the end only");
14744 : 0 : *attributes = NULL_TREE;
14745 : 0 : bad = true;
14746 : : }
14747 : :
14748 : 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
14749 : 0 : *attributes = c_parser_gnu_attributes (parser);
14750 : :
14751 : : /* If there were no attributes here, just report any earlier error. */
14752 : 0 : if (*attributes == NULL_TREE || bad)
14753 : : return bad;
14754 : :
14755 : : /* If the attributes are followed by a ; or {, then just report any earlier
14756 : : error. */
14757 : 0 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
14758 : 0 : || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
14759 : 0 : return bad;
14760 : :
14761 : : /* We've got attributes, but not at the end. */
14762 : 0 : c_parser_error (parser,
14763 : : "expected %<;%> or %<{%> after method attribute definition");
14764 : 0 : return true;
14765 : : }
14766 : :
14767 : : /* Parse an objc-method-decl.
14768 : :
14769 : : objc-method-decl:
14770 : : ( objc-type-name ) objc-selector
14771 : : objc-selector
14772 : : ( objc-type-name ) objc-keyword-selector objc-optparmlist
14773 : : objc-keyword-selector objc-optparmlist
14774 : : gnu-attributes
14775 : :
14776 : : objc-keyword-selector:
14777 : : objc-keyword-decl
14778 : : objc-keyword-selector objc-keyword-decl
14779 : :
14780 : : objc-keyword-decl:
14781 : : objc-selector : ( objc-type-name ) identifier
14782 : : objc-selector : identifier
14783 : : : ( objc-type-name ) identifier
14784 : : : identifier
14785 : :
14786 : : objc-optparmlist:
14787 : : objc-optparms objc-optellipsis
14788 : :
14789 : : objc-optparms:
14790 : : empty
14791 : : objc-opt-parms , parameter-declaration
14792 : :
14793 : : objc-optellipsis:
14794 : : empty
14795 : : , ...
14796 : : */
14797 : :
14798 : : static tree
14799 : 0 : c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
14800 : : tree *attributes, tree *expr)
14801 : : {
14802 : 0 : tree type = NULL_TREE;
14803 : 0 : tree sel;
14804 : 0 : tree parms = NULL_TREE;
14805 : 0 : bool ellipsis = false;
14806 : 0 : bool attr_err = false;
14807 : :
14808 : 0 : *attributes = NULL_TREE;
14809 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14810 : : {
14811 : 0 : matching_parens parens;
14812 : 0 : parens.consume_open (parser);
14813 : 0 : type = c_parser_objc_type_name (parser);
14814 : 0 : parens.skip_until_found_close (parser);
14815 : : }
14816 : 0 : sel = c_parser_objc_selector (parser);
14817 : : /* If there is no selector, or a colon follows, we have an
14818 : : objc-keyword-selector. If there is a selector, and a colon does
14819 : : not follow, that selector ends the objc-method-decl. */
14820 : 0 : if (!sel || c_parser_next_token_is (parser, CPP_COLON))
14821 : : {
14822 : : tree tsel = sel;
14823 : : tree list = NULL_TREE;
14824 : 0 : while (true)
14825 : : {
14826 : 0 : tree atype = NULL_TREE, id, keyworddecl;
14827 : 0 : tree param_attr = NULL_TREE;
14828 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
14829 : : break;
14830 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
14831 : : {
14832 : 0 : c_parser_consume_token (parser);
14833 : 0 : atype = c_parser_objc_type_name (parser);
14834 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
14835 : : "expected %<)%>");
14836 : : }
14837 : : /* New ObjC allows attributes on method parameters. */
14838 : 0 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
14839 : 0 : param_attr = c_parser_gnu_attributes (parser);
14840 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14841 : : {
14842 : 0 : c_parser_error (parser, "expected identifier");
14843 : 0 : return error_mark_node;
14844 : : }
14845 : 0 : id = c_parser_peek_token (parser)->value;
14846 : 0 : c_parser_consume_token (parser);
14847 : 0 : keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
14848 : 0 : list = chainon (list, keyworddecl);
14849 : 0 : tsel = c_parser_objc_selector (parser);
14850 : 0 : if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
14851 : : break;
14852 : : }
14853 : :
14854 : 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14855 : :
14856 : : /* Parse the optional parameter list. Optional Objective-C
14857 : : method parameters follow the C syntax, and may include '...'
14858 : : to denote a variable number of arguments. */
14859 : 0 : parms = make_node (TREE_LIST);
14860 : 0 : while (c_parser_next_token_is (parser, CPP_COMMA))
14861 : : {
14862 : 0 : struct c_parm *parm;
14863 : 0 : c_parser_consume_token (parser);
14864 : 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
14865 : : {
14866 : 0 : ellipsis = true;
14867 : 0 : c_parser_consume_token (parser);
14868 : 0 : attr_err |= c_parser_objc_maybe_method_attributes
14869 : 0 : (parser, attributes) ;
14870 : 0 : break;
14871 : : }
14872 : 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
14873 : 0 : if (parm == NULL)
14874 : : break;
14875 : 0 : parms = chainon (parms,
14876 : : build_tree_list (NULL_TREE, grokparm (parm, expr)));
14877 : : }
14878 : : sel = list;
14879 : : }
14880 : : else
14881 : 0 : attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14882 : :
14883 : 0 : if (sel == NULL)
14884 : : {
14885 : 0 : c_parser_error (parser, "objective-c method declaration is expected");
14886 : 0 : return error_mark_node;
14887 : : }
14888 : :
14889 : 0 : if (attr_err)
14890 : 0 : return error_mark_node;
14891 : :
14892 : 0 : return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
14893 : : }
14894 : :
14895 : : /* Parse an objc-type-name.
14896 : :
14897 : : objc-type-name:
14898 : : objc-type-qualifiers[opt] type-name
14899 : : objc-type-qualifiers[opt]
14900 : :
14901 : : objc-type-qualifiers:
14902 : : objc-type-qualifier
14903 : : objc-type-qualifiers objc-type-qualifier
14904 : :
14905 : : objc-type-qualifier: one of
14906 : : in out inout bycopy byref oneway
14907 : : */
14908 : :
14909 : : static tree
14910 : 0 : c_parser_objc_type_name (c_parser *parser)
14911 : : {
14912 : 0 : tree quals = NULL_TREE;
14913 : 0 : struct c_type_name *type_name = NULL;
14914 : 0 : tree type = NULL_TREE;
14915 : 0 : while (true)
14916 : : {
14917 : 0 : c_token *token = c_parser_peek_token (parser);
14918 : 0 : if (token->type == CPP_KEYWORD
14919 : 0 : && (token->keyword == RID_IN
14920 : : || token->keyword == RID_OUT
14921 : : || token->keyword == RID_INOUT
14922 : : || token->keyword == RID_BYCOPY
14923 : : || token->keyword == RID_BYREF
14924 : 0 : || token->keyword == RID_ONEWAY))
14925 : : {
14926 : 0 : quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
14927 : 0 : c_parser_consume_token (parser);
14928 : : }
14929 : : else
14930 : : break;
14931 : 0 : }
14932 : 0 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
14933 : 0 : type_name = c_parser_type_name (parser);
14934 : 0 : if (type_name)
14935 : 0 : type = groktypename (type_name, NULL, NULL);
14936 : :
14937 : : /* If the type is unknown, and error has already been produced and
14938 : : we need to recover from the error. In that case, use NULL_TREE
14939 : : for the type, as if no type had been specified; this will use the
14940 : : default type ('id') which is good for error recovery. */
14941 : 0 : if (type == error_mark_node)
14942 : 0 : type = NULL_TREE;
14943 : :
14944 : 0 : return build_tree_list (quals, type);
14945 : : }
14946 : :
14947 : : /* Parse objc-protocol-refs.
14948 : :
14949 : : objc-protocol-refs:
14950 : : < identifier-list >
14951 : : */
14952 : :
14953 : : static tree
14954 : 0 : c_parser_objc_protocol_refs (c_parser *parser)
14955 : : {
14956 : 0 : tree list = NULL_TREE;
14957 : 0 : gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
14958 : 0 : c_parser_consume_token (parser);
14959 : : /* Any identifiers, including those declared as type names, are OK
14960 : : here. */
14961 : 0 : while (true)
14962 : : {
14963 : 0 : tree id;
14964 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
14965 : : {
14966 : 0 : c_parser_error (parser, "expected identifier");
14967 : 0 : break;
14968 : : }
14969 : 0 : id = c_parser_peek_token (parser)->value;
14970 : 0 : list = chainon (list, build_tree_list (NULL_TREE, id));
14971 : 0 : c_parser_consume_token (parser);
14972 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
14973 : 0 : c_parser_consume_token (parser);
14974 : : else
14975 : : break;
14976 : 0 : }
14977 : 0 : c_parser_require (parser, CPP_GREATER, "expected %<>%>");
14978 : 0 : return list;
14979 : : }
14980 : :
14981 : : /* Parse an objc-try-catch-finally-statement.
14982 : :
14983 : : objc-try-catch-finally-statement:
14984 : : @try compound-statement objc-catch-list[opt]
14985 : : @try compound-statement objc-catch-list[opt] @finally compound-statement
14986 : :
14987 : : objc-catch-list:
14988 : : @catch ( objc-catch-parameter-declaration ) compound-statement
14989 : : objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
14990 : :
14991 : : objc-catch-parameter-declaration:
14992 : : parameter-declaration
14993 : : '...'
14994 : :
14995 : : where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
14996 : :
14997 : : PS: This function is identical to cp_parser_objc_try_catch_finally_statement
14998 : : for C++. Keep them in sync. */
14999 : :
15000 : : static void
15001 : 0 : c_parser_objc_try_catch_finally_statement (c_parser *parser)
15002 : : {
15003 : 0 : location_t location;
15004 : 0 : tree stmt;
15005 : :
15006 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
15007 : 0 : c_parser_consume_token (parser);
15008 : 0 : location = c_parser_peek_token (parser)->location;
15009 : 0 : objc_maybe_warn_exceptions (location);
15010 : 0 : stmt = c_parser_compound_statement (parser);
15011 : 0 : objc_begin_try_stmt (location, stmt);
15012 : :
15013 : 0 : while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
15014 : : {
15015 : 0 : struct c_parm *parm;
15016 : 0 : tree parameter_declaration = error_mark_node;
15017 : 0 : bool seen_open_paren = false;
15018 : :
15019 : 0 : c_parser_consume_token (parser);
15020 : 0 : matching_parens parens;
15021 : 0 : if (!parens.require_open (parser))
15022 : 0 : seen_open_paren = true;
15023 : 0 : if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
15024 : : {
15025 : : /* We have "@catch (...)" (where the '...' are literally
15026 : : what is in the code). Skip the '...'.
15027 : : parameter_declaration is set to NULL_TREE, and
15028 : : objc_being_catch_clauses() knows that that means
15029 : : '...'. */
15030 : 0 : c_parser_consume_token (parser);
15031 : 0 : parameter_declaration = NULL_TREE;
15032 : : }
15033 : : else
15034 : : {
15035 : : /* We have "@catch (NSException *exception)" or something
15036 : : like that. Parse the parameter declaration. */
15037 : 0 : parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
15038 : 0 : if (parm == NULL)
15039 : 0 : parameter_declaration = error_mark_node;
15040 : : else
15041 : 0 : parameter_declaration = grokparm (parm, NULL);
15042 : : }
15043 : 0 : if (seen_open_paren)
15044 : 0 : parens.require_close (parser);
15045 : : else
15046 : : {
15047 : : /* If there was no open parenthesis, we are recovering from
15048 : : an error, and we are trying to figure out what mistake
15049 : : the user has made. */
15050 : :
15051 : : /* If there is an immediate closing parenthesis, the user
15052 : : probably forgot the opening one (ie, they typed "@catch
15053 : : NSException *e)". Parse the closing parenthesis and keep
15054 : : going. */
15055 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15056 : 0 : c_parser_consume_token (parser);
15057 : :
15058 : : /* If these is no immediate closing parenthesis, the user
15059 : : probably doesn't know that parenthesis are required at
15060 : : all (ie, they typed "@catch NSException *e"). So, just
15061 : : forget about the closing parenthesis and keep going. */
15062 : : }
15063 : 0 : objc_begin_catch_clause (parameter_declaration);
15064 : 0 : if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
15065 : 0 : c_parser_compound_statement_nostart (parser);
15066 : 0 : objc_finish_catch_clause ();
15067 : : }
15068 : 0 : if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
15069 : : {
15070 : 0 : c_parser_consume_token (parser);
15071 : 0 : location = c_parser_peek_token (parser)->location;
15072 : 0 : stmt = c_parser_compound_statement (parser);
15073 : 0 : objc_build_finally_clause (location, stmt);
15074 : : }
15075 : 0 : objc_finish_try_stmt ();
15076 : 0 : }
15077 : :
15078 : : /* Parse an objc-synchronized-statement.
15079 : :
15080 : : objc-synchronized-statement:
15081 : : @synchronized ( expression ) compound-statement
15082 : : */
15083 : :
15084 : : static void
15085 : 0 : c_parser_objc_synchronized_statement (c_parser *parser)
15086 : : {
15087 : 0 : location_t loc;
15088 : 0 : tree expr, stmt;
15089 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
15090 : 0 : c_parser_consume_token (parser);
15091 : 0 : loc = c_parser_peek_token (parser)->location;
15092 : 0 : objc_maybe_warn_exceptions (loc);
15093 : 0 : matching_parens parens;
15094 : 0 : if (parens.require_open (parser))
15095 : : {
15096 : 0 : struct c_expr ce = c_parser_expression (parser);
15097 : 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15098 : 0 : expr = ce.value;
15099 : 0 : expr = c_fully_fold (expr, false, NULL);
15100 : 0 : parens.skip_until_found_close (parser);
15101 : : }
15102 : : else
15103 : 0 : expr = error_mark_node;
15104 : 0 : stmt = c_parser_compound_statement (parser);
15105 : 0 : objc_build_synchronized (loc, expr, stmt);
15106 : 0 : }
15107 : :
15108 : : /* Parse an objc-selector; return NULL_TREE without an error if the
15109 : : next token is not an objc-selector.
15110 : :
15111 : : objc-selector:
15112 : : identifier
15113 : : one of
15114 : : enum struct union if else while do for switch case default
15115 : : break continue return goto asm sizeof typeof typeof_unqual __alignof
15116 : : unsigned long const short volatile signed restrict _Complex
15117 : : in out inout bycopy byref oneway int char float double void _Bool
15118 : : _Atomic
15119 : :
15120 : : ??? Why this selection of keywords but not, for example, storage
15121 : : class specifiers? */
15122 : :
15123 : : static tree
15124 : 0 : c_parser_objc_selector (c_parser *parser)
15125 : : {
15126 : 0 : c_token *token = c_parser_peek_token (parser);
15127 : 0 : tree value = token->value;
15128 : 0 : if (token->type == CPP_NAME)
15129 : : {
15130 : 0 : c_parser_consume_token (parser);
15131 : 0 : return value;
15132 : : }
15133 : 0 : if (token->type != CPP_KEYWORD)
15134 : : return NULL_TREE;
15135 : 0 : switch (token->keyword)
15136 : : {
15137 : 0 : case RID_ENUM:
15138 : 0 : case RID_STRUCT:
15139 : 0 : case RID_UNION:
15140 : 0 : case RID_IF:
15141 : 0 : case RID_ELSE:
15142 : 0 : case RID_WHILE:
15143 : 0 : case RID_DO:
15144 : 0 : case RID_FOR:
15145 : 0 : case RID_SWITCH:
15146 : 0 : case RID_CASE:
15147 : 0 : case RID_DEFAULT:
15148 : 0 : case RID_BREAK:
15149 : 0 : case RID_CONTINUE:
15150 : 0 : case RID_RETURN:
15151 : 0 : case RID_GOTO:
15152 : 0 : case RID_ASM:
15153 : 0 : case RID_SIZEOF:
15154 : 0 : case RID_TYPEOF:
15155 : 0 : case RID_TYPEOF_UNQUAL:
15156 : 0 : case RID_ALIGNOF:
15157 : 0 : case RID_UNSIGNED:
15158 : 0 : case RID_LONG:
15159 : 0 : case RID_CONST:
15160 : 0 : case RID_SHORT:
15161 : 0 : case RID_VOLATILE:
15162 : 0 : case RID_SIGNED:
15163 : 0 : case RID_RESTRICT:
15164 : 0 : case RID_COMPLEX:
15165 : 0 : case RID_IN:
15166 : 0 : case RID_OUT:
15167 : 0 : case RID_INOUT:
15168 : 0 : case RID_BYCOPY:
15169 : 0 : case RID_BYREF:
15170 : 0 : case RID_ONEWAY:
15171 : 0 : case RID_INT:
15172 : 0 : case RID_CHAR:
15173 : 0 : case RID_FLOAT:
15174 : 0 : case RID_DOUBLE:
15175 : 0 : CASE_RID_FLOATN_NX:
15176 : 0 : case RID_VOID:
15177 : 0 : case RID_BOOL:
15178 : 0 : case RID_ATOMIC:
15179 : 0 : case RID_AUTO_TYPE:
15180 : 0 : case RID_INT_N_0:
15181 : 0 : case RID_INT_N_1:
15182 : 0 : case RID_INT_N_2:
15183 : 0 : case RID_INT_N_3:
15184 : 0 : c_parser_consume_token (parser);
15185 : 0 : return value;
15186 : : default:
15187 : : return NULL_TREE;
15188 : : }
15189 : : }
15190 : :
15191 : : /* Parse an objc-selector-arg.
15192 : :
15193 : : objc-selector-arg:
15194 : : objc-selector
15195 : : objc-keywordname-list
15196 : :
15197 : : objc-keywordname-list:
15198 : : objc-keywordname
15199 : : objc-keywordname-list objc-keywordname
15200 : :
15201 : : objc-keywordname:
15202 : : objc-selector :
15203 : : :
15204 : : */
15205 : :
15206 : : static tree
15207 : 0 : c_parser_objc_selector_arg (c_parser *parser)
15208 : : {
15209 : 0 : tree sel = c_parser_objc_selector (parser);
15210 : 0 : tree list = NULL_TREE;
15211 : 0 : if (sel
15212 : 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15213 : 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15214 : : return sel;
15215 : 0 : while (true)
15216 : : {
15217 : 0 : if (c_parser_next_token_is (parser, CPP_SCOPE))
15218 : : {
15219 : 0 : c_parser_consume_token (parser);
15220 : 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15221 : 0 : list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
15222 : : }
15223 : : else
15224 : : {
15225 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15226 : : return list;
15227 : 0 : list = chainon (list, build_tree_list (sel, NULL_TREE));
15228 : : }
15229 : 0 : sel = c_parser_objc_selector (parser);
15230 : 0 : if (!sel
15231 : 0 : && c_parser_next_token_is_not (parser, CPP_COLON)
15232 : 0 : && c_parser_next_token_is_not (parser, CPP_SCOPE))
15233 : : break;
15234 : : }
15235 : : return list;
15236 : : }
15237 : :
15238 : : /* Parse an objc-receiver.
15239 : :
15240 : : objc-receiver:
15241 : : expression
15242 : : class-name
15243 : : type-name
15244 : : */
15245 : :
15246 : : static tree
15247 : 0 : c_parser_objc_receiver (c_parser *parser)
15248 : : {
15249 : 0 : location_t loc = c_parser_peek_token (parser)->location;
15250 : :
15251 : 0 : if (c_parser_peek_token (parser)->type == CPP_NAME
15252 : 0 : && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
15253 : 0 : || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
15254 : : {
15255 : 0 : tree id = c_parser_peek_token (parser)->value;
15256 : 0 : c_parser_consume_token (parser);
15257 : 0 : return objc_get_class_reference (id);
15258 : : }
15259 : 0 : struct c_expr ce = c_parser_expression (parser);
15260 : 0 : ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15261 : 0 : return c_fully_fold (ce.value, false, NULL);
15262 : : }
15263 : :
15264 : : /* Parse objc-message-args.
15265 : :
15266 : : objc-message-args:
15267 : : objc-selector
15268 : : objc-keywordarg-list
15269 : :
15270 : : objc-keywordarg-list:
15271 : : objc-keywordarg
15272 : : objc-keywordarg-list objc-keywordarg
15273 : :
15274 : : objc-keywordarg:
15275 : : objc-selector : objc-keywordexpr
15276 : : : objc-keywordexpr
15277 : : */
15278 : :
15279 : : static tree
15280 : 0 : c_parser_objc_message_args (c_parser *parser)
15281 : : {
15282 : 0 : tree sel = c_parser_objc_selector (parser);
15283 : 0 : tree list = NULL_TREE;
15284 : 0 : if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
15285 : : return sel;
15286 : 0 : while (true)
15287 : : {
15288 : 0 : tree keywordexpr;
15289 : 0 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
15290 : 0 : return error_mark_node;
15291 : 0 : keywordexpr = c_parser_objc_keywordexpr (parser);
15292 : 0 : list = chainon (list, build_tree_list (sel, keywordexpr));
15293 : 0 : sel = c_parser_objc_selector (parser);
15294 : 0 : if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
15295 : : break;
15296 : : }
15297 : : return list;
15298 : : }
15299 : :
15300 : : /* Parse an objc-keywordexpr.
15301 : :
15302 : : objc-keywordexpr:
15303 : : nonempty-expr-list
15304 : : */
15305 : :
15306 : : static tree
15307 : 0 : c_parser_objc_keywordexpr (c_parser *parser)
15308 : : {
15309 : 0 : tree ret;
15310 : 0 : vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true,
15311 : : NULL, NULL, NULL, NULL);
15312 : 0 : if (vec_safe_length (expr_list) == 1)
15313 : : {
15314 : : /* Just return the expression, remove a level of
15315 : : indirection. */
15316 : 0 : ret = (*expr_list)[0];
15317 : : }
15318 : : else
15319 : : {
15320 : : /* We have a comma expression, we will collapse later. */
15321 : 0 : ret = build_tree_list_vec (expr_list);
15322 : : }
15323 : 0 : release_tree_vector (expr_list);
15324 : 0 : return ret;
15325 : : }
15326 : :
15327 : : /* A check, needed in several places, that ObjC interface, implementation or
15328 : : method definitions are not prefixed by incorrect items. */
15329 : : static bool
15330 : 0 : c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
15331 : : struct c_declspecs *specs)
15332 : : {
15333 : 0 : if (!specs->declspecs_seen_p || specs->non_sc_seen_p
15334 : 0 : || specs->typespec_kind != ctsk_none)
15335 : : {
15336 : 0 : c_parser_error (parser,
15337 : : "no type or storage class may be specified here,");
15338 : 0 : c_parser_skip_to_end_of_block_or_statement (parser);
15339 : 0 : return true;
15340 : : }
15341 : : return false;
15342 : : }
15343 : :
15344 : : /* Parse an Objective-C @property declaration. The syntax is:
15345 : :
15346 : : objc-property-declaration:
15347 : : '@property' objc-property-attributes[opt] struct-declaration ;
15348 : :
15349 : : objc-property-attributes:
15350 : : '(' objc-property-attribute-list ')'
15351 : :
15352 : : objc-property-attribute-list:
15353 : : objc-property-attribute
15354 : : objc-property-attribute-list, objc-property-attribute
15355 : :
15356 : : objc-property-attribute
15357 : : 'getter' = identifier
15358 : : 'setter' = identifier
15359 : : 'readonly'
15360 : : 'readwrite'
15361 : : 'assign'
15362 : : 'retain'
15363 : : 'copy'
15364 : : 'nonatomic'
15365 : :
15366 : : For example:
15367 : : @property NSString *name;
15368 : : @property (readonly) id object;
15369 : : @property (retain, nonatomic, getter=getTheName) id name;
15370 : : @property int a, b, c;
15371 : :
15372 : : PS: This function is identical to cp_parser_objc_at_propery_declaration
15373 : : for C++. Keep them in sync. */
15374 : : static void
15375 : 0 : c_parser_objc_at_property_declaration (c_parser *parser)
15376 : : {
15377 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
15378 : 0 : location_t loc = c_parser_peek_token (parser)->location;
15379 : 0 : c_parser_consume_token (parser); /* Eat '@property'. */
15380 : :
15381 : : /* Parse the optional attribute list.
15382 : :
15383 : : A list of parsed, but not verified, attributes. */
15384 : 0 : vec<property_attribute_info *> prop_attr_list = vNULL;
15385 : :
15386 : 0 : bool syntax_error = false;
15387 : 0 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
15388 : : {
15389 : 0 : matching_parens parens;
15390 : :
15391 : 0 : location_t attr_start = c_parser_peek_token (parser)->location;
15392 : : /* Eat the '(' */
15393 : 0 : parens.consume_open (parser);
15394 : :
15395 : : /* Property attribute keywords are valid now. */
15396 : 0 : parser->objc_property_attr_context = true;
15397 : :
15398 : : /* Allow @property (), with a warning. */
15399 : 0 : location_t attr_end = c_parser_peek_token (parser)->location;
15400 : :
15401 : 0 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
15402 : : {
15403 : 0 : location_t attr_comb = make_location (attr_end, attr_start, attr_end);
15404 : 0 : warning_at (attr_comb, OPT_Wattributes,
15405 : : "empty property attribute list");
15406 : : }
15407 : : else
15408 : 0 : while (true)
15409 : : {
15410 : 0 : c_token *token = c_parser_peek_token (parser);
15411 : 0 : attr_start = token->location;
15412 : 0 : attr_end = get_finish (token->location);
15413 : 0 : location_t attr_comb = make_location (attr_start, attr_start,
15414 : : attr_end);
15415 : :
15416 : 0 : if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
15417 : : {
15418 : 0 : warning_at (attr_comb, OPT_Wattributes,
15419 : : "missing property attribute");
15420 : 0 : if (token->type == CPP_CLOSE_PAREN)
15421 : : break;
15422 : 0 : c_parser_consume_token (parser);
15423 : 0 : continue;
15424 : : }
15425 : :
15426 : 0 : tree attr_name = NULL_TREE;
15427 : 0 : enum rid keyword = RID_MAX; /* Not a valid property attribute. */
15428 : 0 : bool add_at = false;
15429 : 0 : if (token->type == CPP_KEYWORD)
15430 : : {
15431 : 0 : keyword = token->keyword;
15432 : 0 : if (OBJC_IS_AT_KEYWORD (keyword))
15433 : : {
15434 : : /* For '@' keywords the token value has the keyword,
15435 : : prepend the '@' for diagnostics. */
15436 : 0 : attr_name = token->value;
15437 : 0 : add_at = true;
15438 : : }
15439 : : else
15440 : 0 : attr_name = ridpointers[(int)keyword];
15441 : : }
15442 : 0 : else if (token->type == CPP_NAME)
15443 : 0 : attr_name = token->value;
15444 : 0 : c_parser_consume_token (parser);
15445 : :
15446 : 0 : enum objc_property_attribute_kind prop_kind
15447 : 0 : = objc_prop_attr_kind_for_rid (keyword);
15448 : 0 : property_attribute_info *prop
15449 : 0 : = new property_attribute_info (attr_name, attr_comb, prop_kind);
15450 : 0 : prop_attr_list.safe_push (prop);
15451 : :
15452 : 0 : tree meth_name;
15453 : 0 : switch (prop->prop_kind)
15454 : : {
15455 : : default: break;
15456 : 0 : case OBJC_PROPERTY_ATTR_UNKNOWN:
15457 : 0 : if (attr_name)
15458 : 0 : error_at (attr_comb, "unknown property attribute %<%s%s%>",
15459 : 0 : add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
15460 : : else
15461 : 0 : error_at (attr_comb, "unknown property attribute");
15462 : 0 : prop->parse_error = syntax_error = true;
15463 : 0 : break;
15464 : :
15465 : 0 : case OBJC_PROPERTY_ATTR_GETTER:
15466 : 0 : case OBJC_PROPERTY_ATTR_SETTER:
15467 : 0 : if (c_parser_next_token_is_not (parser, CPP_EQ))
15468 : : {
15469 : 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15470 : 0 : error_at (attr_comb, "expected %<=%> after Objective-C %qE",
15471 : : attr_name);
15472 : 0 : prop->parse_error = syntax_error = true;
15473 : 0 : break;
15474 : : }
15475 : 0 : token = c_parser_peek_token (parser);
15476 : 0 : attr_end = token->location;
15477 : 0 : c_parser_consume_token (parser); /* eat the = */
15478 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15479 : : {
15480 : 0 : attr_comb = make_location (attr_end, attr_start, attr_end);
15481 : 0 : error_at (attr_comb, "expected %qE selector name",
15482 : : attr_name);
15483 : 0 : prop->parse_error = syntax_error = true;
15484 : 0 : break;
15485 : : }
15486 : : /* Get the end of the method name, and consume the name. */
15487 : 0 : token = c_parser_peek_token (parser);
15488 : 0 : attr_end = get_finish (token->location);
15489 : 0 : meth_name = token->value;
15490 : 0 : c_parser_consume_token (parser);
15491 : 0 : if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
15492 : : {
15493 : 0 : if (c_parser_next_token_is_not (parser, CPP_COLON))
15494 : : {
15495 : 0 : attr_comb = make_location (attr_end, attr_start,
15496 : : attr_end);
15497 : 0 : error_at (attr_comb, "setter method names must"
15498 : : " terminate with %<:%>");
15499 : 0 : prop->parse_error = syntax_error = true;
15500 : : }
15501 : : else
15502 : : {
15503 : 0 : attr_end = get_finish (c_parser_peek_token
15504 : 0 : (parser)->location);
15505 : 0 : c_parser_consume_token (parser);
15506 : : }
15507 : 0 : attr_comb = make_location (attr_start, attr_start,
15508 : : attr_end);
15509 : : }
15510 : : else
15511 : 0 : attr_comb = make_location (attr_start, attr_start,
15512 : : attr_end);
15513 : 0 : prop->ident = meth_name;
15514 : : /* Updated location including all that was successfully
15515 : : parsed. */
15516 : 0 : prop->prop_loc = attr_comb;
15517 : 0 : break;
15518 : : }
15519 : :
15520 : : /* If we see a comma here, then keep going - even if we already
15521 : : saw a syntax error. For simple mistakes e.g. (asign, getter=x)
15522 : : this makes a more useful output and avoid spurious warnings about
15523 : : missing attributes that are, in fact, specified after the one with
15524 : : the syntax error. */
15525 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15526 : 0 : c_parser_consume_token (parser);
15527 : : else
15528 : : break;
15529 : : }
15530 : 0 : parser->objc_property_attr_context = false;
15531 : :
15532 : 0 : if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
15533 : : /* We don't really want to chew the whole of the file looking for a
15534 : : matching closing parenthesis, so we will try to read the decl and
15535 : : let the error handling for that close out the statement. */
15536 : : ;
15537 : : else
15538 : 0 : syntax_error = false, parens.skip_until_found_close (parser);
15539 : : }
15540 : :
15541 : : /* 'properties' is the list of properties that we read. Usually a
15542 : : single one, but maybe more (eg, in "@property int a, b, c;" there
15543 : : are three). */
15544 : 0 : tree properties = c_parser_struct_declaration (parser, NULL);
15545 : :
15546 : 0 : if (properties == error_mark_node)
15547 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15548 : : else
15549 : : {
15550 : 0 : if (properties == NULL_TREE)
15551 : 0 : c_parser_error (parser, "expected identifier");
15552 : : else
15553 : : {
15554 : : /* Comma-separated properties are chained together in reverse order;
15555 : : add them one by one. */
15556 : 0 : properties = nreverse (properties);
15557 : 0 : for (; properties; properties = TREE_CHAIN (properties))
15558 : 0 : objc_add_property_declaration (loc, copy_node (properties),
15559 : : prop_attr_list);
15560 : : }
15561 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15562 : : }
15563 : :
15564 : 0 : while (!prop_attr_list.is_empty())
15565 : 0 : delete prop_attr_list.pop ();
15566 : 0 : prop_attr_list.release ();
15567 : 0 : parser->error = false;
15568 : 0 : }
15569 : :
15570 : : /* Parse an Objective-C @synthesize declaration. The syntax is:
15571 : :
15572 : : objc-synthesize-declaration:
15573 : : @synthesize objc-synthesize-identifier-list ;
15574 : :
15575 : : objc-synthesize-identifier-list:
15576 : : objc-synthesize-identifier
15577 : : objc-synthesize-identifier-list, objc-synthesize-identifier
15578 : :
15579 : : objc-synthesize-identifier
15580 : : identifier
15581 : : identifier = identifier
15582 : :
15583 : : For example:
15584 : : @synthesize MyProperty;
15585 : : @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
15586 : :
15587 : : PS: This function is identical to cp_parser_objc_at_synthesize_declaration
15588 : : for C++. Keep them in sync.
15589 : : */
15590 : : static void
15591 : 0 : c_parser_objc_at_synthesize_declaration (c_parser *parser)
15592 : : {
15593 : 0 : tree list = NULL_TREE;
15594 : 0 : location_t loc;
15595 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
15596 : 0 : loc = c_parser_peek_token (parser)->location;
15597 : :
15598 : 0 : c_parser_consume_token (parser);
15599 : 0 : while (true)
15600 : : {
15601 : 0 : tree property, ivar;
15602 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15603 : : {
15604 : 0 : c_parser_error (parser, "expected identifier");
15605 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15606 : : /* Once we find the semicolon, we can resume normal parsing.
15607 : : We have to reset parser->error manually because
15608 : : c_parser_skip_until_found() won't reset it for us if the
15609 : : next token is precisely a semicolon. */
15610 : 0 : parser->error = false;
15611 : 0 : return;
15612 : : }
15613 : 0 : property = c_parser_peek_token (parser)->value;
15614 : 0 : c_parser_consume_token (parser);
15615 : 0 : if (c_parser_next_token_is (parser, CPP_EQ))
15616 : : {
15617 : 0 : c_parser_consume_token (parser);
15618 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15619 : : {
15620 : 0 : c_parser_error (parser, "expected identifier");
15621 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15622 : 0 : parser->error = false;
15623 : 0 : return;
15624 : : }
15625 : 0 : ivar = c_parser_peek_token (parser)->value;
15626 : 0 : c_parser_consume_token (parser);
15627 : : }
15628 : : else
15629 : : ivar = NULL_TREE;
15630 : 0 : list = chainon (list, build_tree_list (ivar, property));
15631 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15632 : 0 : c_parser_consume_token (parser);
15633 : : else
15634 : : break;
15635 : 0 : }
15636 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15637 : 0 : objc_add_synthesize_declaration (loc, list);
15638 : : }
15639 : :
15640 : : /* Parse an Objective-C @dynamic declaration. The syntax is:
15641 : :
15642 : : objc-dynamic-declaration:
15643 : : @dynamic identifier-list ;
15644 : :
15645 : : For example:
15646 : : @dynamic MyProperty;
15647 : : @dynamic MyProperty, AnotherProperty;
15648 : :
15649 : : PS: This function is identical to cp_parser_objc_at_dynamic_declaration
15650 : : for C++. Keep them in sync.
15651 : : */
15652 : : static void
15653 : 0 : c_parser_objc_at_dynamic_declaration (c_parser *parser)
15654 : : {
15655 : 0 : tree list = NULL_TREE;
15656 : 0 : location_t loc;
15657 : 0 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
15658 : 0 : loc = c_parser_peek_token (parser)->location;
15659 : :
15660 : 0 : c_parser_consume_token (parser);
15661 : 0 : while (true)
15662 : : {
15663 : 0 : tree property;
15664 : 0 : if (c_parser_next_token_is_not (parser, CPP_NAME))
15665 : : {
15666 : 0 : c_parser_error (parser, "expected identifier");
15667 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
15668 : 0 : parser->error = false;
15669 : 0 : return;
15670 : : }
15671 : 0 : property = c_parser_peek_token (parser)->value;
15672 : 0 : list = chainon (list, build_tree_list (NULL_TREE, property));
15673 : 0 : c_parser_consume_token (parser);
15674 : 0 : if (c_parser_next_token_is (parser, CPP_COMMA))
15675 : 0 : c_parser_consume_token (parser);
15676 : : else
15677 : : break;
15678 : 0 : }
15679 : 0 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
15680 : 0 : objc_add_dynamic_declaration (loc, list);
15681 : : }
15682 : :
15683 : :
15684 : : /* Parse a pragma GCC ivdep. */
15685 : :
15686 : : static bool
15687 : 128 : c_parse_pragma_ivdep (c_parser *parser)
15688 : : {
15689 : 0 : c_parser_consume_pragma (parser);
15690 : 0 : c_parser_skip_to_pragma_eol (parser);
15691 : 128 : return true;
15692 : : }
15693 : :
15694 : : /* Parse a pragma GCC novector. */
15695 : :
15696 : : static bool
15697 : 2628 : c_parse_pragma_novector (c_parser *parser)
15698 : : {
15699 : 0 : c_parser_consume_pragma (parser);
15700 : 0 : c_parser_skip_to_pragma_eol (parser);
15701 : 2628 : return true;
15702 : : }
15703 : :
15704 : : /* Parse a pragma GCC unroll. */
15705 : :
15706 : : static unsigned short
15707 : 277 : c_parser_pragma_unroll (c_parser *parser)
15708 : : {
15709 : 277 : unsigned short unroll;
15710 : 277 : c_parser_consume_pragma (parser);
15711 : 277 : location_t location = c_parser_peek_token (parser)->location;
15712 : 277 : tree expr = c_parser_expr_no_commas (parser, NULL).value;
15713 : 277 : mark_exp_read (expr);
15714 : 277 : expr = c_fully_fold (expr, false, NULL);
15715 : 277 : HOST_WIDE_INT lunroll = 0;
15716 : 554 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
15717 : 276 : || TREE_CODE (expr) != INTEGER_CST
15718 : 275 : || (lunroll = tree_to_shwi (expr)) < 0
15719 : 551 : || lunroll >= USHRT_MAX)
15720 : : {
15721 : 4 : error_at (location, "%<#pragma GCC unroll%> requires an"
15722 : : " assignment-expression that evaluates to a non-negative"
15723 : : " integral constant less than %u", USHRT_MAX);
15724 : 4 : unroll = 0;
15725 : : }
15726 : : else
15727 : : {
15728 : 273 : unroll = (unsigned short)lunroll;
15729 : 273 : if (unroll == 0)
15730 : : unroll = 1;
15731 : : }
15732 : :
15733 : 277 : c_parser_skip_to_pragma_eol (parser);
15734 : 277 : return unroll;
15735 : : }
15736 : :
15737 : : /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
15738 : : should be considered, statements. ALLOW_STMT is true if we're within
15739 : : the context of a function and such pragmas are to be allowed. Returns
15740 : : true if we actually parsed such a pragma. BEFORE_LABELS is last statement
15741 : : before possible labels, see get_before_labels description for details. */
15742 : :
15743 : : static bool
15744 : 1948432 : c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
15745 : : tree before_labels)
15746 : : {
15747 : 1948432 : unsigned int id;
15748 : 1948432 : const char *construct = NULL;
15749 : :
15750 : 1948432 : input_location = c_parser_peek_token (parser)->location;
15751 : 1948432 : id = c_parser_peek_token (parser)->pragma_kind;
15752 : 1948432 : gcc_assert (id != PRAGMA_NONE);
15753 : 1948432 : if (parser->omp_for_parse_state
15754 : 12 : && parser->omp_for_parse_state->in_intervening_code
15755 : : && id >= PRAGMA_OMP__START_
15756 : 9 : && id <= PRAGMA_OMP__LAST_)
15757 : : {
15758 : 3 : error_at (input_location,
15759 : : "intervening code must not contain OpenMP directives");
15760 : 3 : parser->omp_for_parse_state->fail = true;
15761 : 3 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15762 : 3 : return false;
15763 : : }
15764 : :
15765 : 1948429 : switch (id)
15766 : : {
15767 : 144 : case PRAGMA_OACC_DECLARE:
15768 : 144 : c_parser_oacc_declare (parser);
15769 : 144 : return false;
15770 : :
15771 : 136 : case PRAGMA_OACC_ENTER_DATA:
15772 : 136 : if (context != pragma_compound)
15773 : : {
15774 : : construct = "acc enter data";
15775 : 62 : in_compound:
15776 : 62 : if (context == pragma_stmt)
15777 : : {
15778 : 59 : error_at (c_parser_peek_token (parser)->location,
15779 : : "%<#pragma %s%> may only be used in compound "
15780 : : "statements", construct);
15781 : 59 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15782 : 59 : return true;
15783 : : }
15784 : 3 : goto bad_stmt;
15785 : : }
15786 : 133 : c_parser_oacc_enter_exit_data (parser, true);
15787 : 133 : return false;
15788 : :
15789 : 131 : case PRAGMA_OACC_EXIT_DATA:
15790 : 131 : if (context != pragma_compound)
15791 : : {
15792 : 3 : construct = "acc exit data";
15793 : 3 : goto in_compound;
15794 : : }
15795 : 128 : c_parser_oacc_enter_exit_data (parser, false);
15796 : 128 : return false;
15797 : :
15798 : 350 : case PRAGMA_OACC_ROUTINE:
15799 : 350 : if (context != pragma_external)
15800 : : {
15801 : 5 : error_at (c_parser_peek_token (parser)->location,
15802 : : "%<#pragma acc routine%> must be at file scope");
15803 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15804 : 5 : return false;
15805 : : }
15806 : 345 : c_parser_oacc_routine (parser, context);
15807 : 345 : return false;
15808 : :
15809 : 100 : case PRAGMA_OACC_UPDATE:
15810 : 100 : if (context != pragma_compound)
15811 : : {
15812 : 8 : construct = "acc update";
15813 : 8 : goto in_compound;
15814 : : }
15815 : 92 : c_parser_oacc_update (parser);
15816 : 92 : return false;
15817 : :
15818 : 359 : case PRAGMA_OMP_BARRIER:
15819 : 359 : if (context != pragma_compound)
15820 : : {
15821 : 11 : construct = "omp barrier";
15822 : 11 : goto in_compound;
15823 : : }
15824 : 348 : c_parser_omp_barrier (parser);
15825 : 348 : return false;
15826 : :
15827 : 76 : case PRAGMA_OMP_DEPOBJ:
15828 : 76 : if (context != pragma_compound)
15829 : : {
15830 : 1 : construct = "omp depobj";
15831 : 1 : goto in_compound;
15832 : : }
15833 : 75 : c_parser_omp_depobj (parser);
15834 : 75 : return false;
15835 : :
15836 : 70 : case PRAGMA_OMP_FLUSH:
15837 : 70 : if (context != pragma_compound)
15838 : : {
15839 : 9 : construct = "omp flush";
15840 : 9 : goto in_compound;
15841 : : }
15842 : 61 : c_parser_omp_flush (parser);
15843 : 61 : return false;
15844 : :
15845 : 183 : case PRAGMA_OMP_INTEROP:
15846 : 183 : if (context != pragma_compound)
15847 : : {
15848 : 0 : construct = "omp interop";
15849 : 0 : goto in_compound;
15850 : : }
15851 : 183 : c_parser_omp_interop (parser);
15852 : 183 : return false;
15853 : :
15854 : 101 : case PRAGMA_OMP_TASKWAIT:
15855 : 101 : if (context != pragma_compound)
15856 : : {
15857 : 8 : construct = "omp taskwait";
15858 : 8 : goto in_compound;
15859 : : }
15860 : 93 : c_parser_omp_taskwait (parser);
15861 : 93 : return false;
15862 : :
15863 : 14 : case PRAGMA_OMP_TASKYIELD:
15864 : 14 : if (context != pragma_compound)
15865 : : {
15866 : 8 : construct = "omp taskyield";
15867 : 8 : goto in_compound;
15868 : : }
15869 : 6 : c_parser_omp_taskyield (parser);
15870 : 6 : return false;
15871 : :
15872 : 221 : case PRAGMA_OMP_CANCEL:
15873 : 221 : if (context != pragma_compound)
15874 : : {
15875 : 8 : construct = "omp cancel";
15876 : 8 : goto in_compound;
15877 : : }
15878 : 213 : c_parser_omp_cancel (parser);
15879 : 213 : return false;
15880 : :
15881 : 179 : case PRAGMA_OMP_CANCELLATION_POINT:
15882 : 179 : return c_parser_omp_cancellation_point (parser, context);
15883 : :
15884 : 78 : case PRAGMA_OMP_THREADPRIVATE:
15885 : 78 : c_parser_omp_threadprivate (parser);
15886 : 78 : return false;
15887 : :
15888 : 7395 : case PRAGMA_OMP_TARGET:
15889 : 7395 : return c_parser_omp_target (parser, context, if_p);
15890 : :
15891 : 91 : case PRAGMA_OMP_BEGIN:
15892 : 91 : c_parser_omp_begin (parser);
15893 : 91 : return false;
15894 : :
15895 : 199 : case PRAGMA_OMP_END:
15896 : 199 : c_parser_omp_end (parser);
15897 : 199 : return false;
15898 : :
15899 : 22 : case PRAGMA_OMP_SCAN:
15900 : 22 : error_at (c_parser_peek_token (parser)->location,
15901 : : "%<#pragma omp scan%> may only be used in "
15902 : : "a loop construct with %<inscan%> %<reduction%> clause");
15903 : 22 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15904 : 22 : return false;
15905 : :
15906 : 5 : case PRAGMA_OMP_SECTION:
15907 : 5 : error_at (c_parser_peek_token (parser)->location,
15908 : : "%<#pragma omp section%> may only be used in "
15909 : : "%<#pragma omp sections%> construct");
15910 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15911 : 5 : return false;
15912 : :
15913 : 1205 : case PRAGMA_OMP_DECLARE:
15914 : 1205 : return c_parser_omp_declare (parser, context);
15915 : :
15916 : 70 : case PRAGMA_OMP_REQUIRES:
15917 : 70 : if (context != pragma_external)
15918 : : {
15919 : 8 : error_at (c_parser_peek_token (parser)->location,
15920 : : "%<#pragma %s%> may only be used at file scope",
15921 : : "omp requires");
15922 : 8 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15923 : 8 : return false;
15924 : : }
15925 : 62 : c_parser_omp_requires (parser);
15926 : 62 : return false;
15927 : :
15928 : 69 : case PRAGMA_OMP_ALLOCATE:
15929 : 69 : c_parser_omp_allocate (parser);
15930 : 69 : return false;
15931 : :
15932 : 38 : case PRAGMA_OMP_ASSUMES:
15933 : 38 : if (context != pragma_external)
15934 : : {
15935 : 1 : error_at (c_parser_peek_token (parser)->location,
15936 : : "%<#pragma %s%> may only be used at file scope",
15937 : : "omp assumes");
15938 : 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
15939 : 1 : return false;
15940 : : }
15941 : 37 : c_parser_omp_assumes (parser);
15942 : 37 : return false;
15943 : :
15944 : 79 : case PRAGMA_OMP_NOTHING:
15945 : 79 : c_parser_omp_nothing (parser);
15946 : 79 : return false;
15947 : :
15948 : 108 : case PRAGMA_OMP_METADIRECTIVE:
15949 : 108 : c_parser_omp_metadirective (parser, if_p);
15950 : 108 : return true;
15951 : :
15952 : 124 : case PRAGMA_OMP_ERROR:
15953 : 124 : return c_parser_omp_error (parser, context);
15954 : :
15955 : 543 : case PRAGMA_OMP_ORDERED:
15956 : 543 : return c_parser_omp_ordered (parser, context, if_p);
15957 : :
15958 : 3017 : case PRAGMA_NOVECTOR:
15959 : 3017 : case PRAGMA_UNROLL:
15960 : 3017 : case PRAGMA_IVDEP:
15961 : 3017 : {
15962 : 3017 : bool novector = false;
15963 : 3017 : unsigned short unroll = 0;
15964 : 3017 : bool ivdep = false;
15965 : :
15966 : 3017 : switch (id)
15967 : : {
15968 : 2624 : case PRAGMA_NOVECTOR:
15969 : 2624 : novector = c_parse_pragma_novector (parser);
15970 : 2624 : break;
15971 : 268 : case PRAGMA_UNROLL:
15972 : 268 : unroll = c_parser_pragma_unroll (parser);
15973 : 268 : break;
15974 : 125 : case PRAGMA_IVDEP:
15975 : 125 : ivdep = c_parse_pragma_ivdep (parser);
15976 : 125 : break;
15977 : : default:
15978 : : gcc_unreachable ();
15979 : : }
15980 : :
15981 : 3017 : c_token *tok = c_parser_peek_token (parser);
15982 : 3017 : bool has_more = tok->type == CPP_PRAGMA;
15983 : 3033 : while (has_more)
15984 : : {
15985 : 16 : switch (tok->pragma_kind)
15986 : : {
15987 : 3 : case PRAGMA_IVDEP:
15988 : 3 : ivdep = c_parse_pragma_ivdep (parser);
15989 : 3 : break;
15990 : 9 : case PRAGMA_UNROLL:
15991 : 9 : unroll = c_parser_pragma_unroll (parser);
15992 : 9 : break;
15993 : 4 : case PRAGMA_NOVECTOR:
15994 : 4 : novector = c_parse_pragma_novector (parser);
15995 : 4 : break;
15996 : : default:
15997 : : has_more = false;
15998 : : break;
15999 : : }
16000 : 16 : tok = c_parser_peek_token (parser);
16001 : 16 : has_more = has_more && tok->type == CPP_PRAGMA;
16002 : : }
16003 : 3017 : if (!c_parser_next_token_is_keyword (parser, RID_FOR)
16004 : 74 : && !c_parser_next_token_is_keyword (parser, RID_WHILE)
16005 : 3076 : && !c_parser_next_token_is_keyword (parser, RID_DO))
16006 : : {
16007 : 0 : c_parser_error (parser, "for, while or do statement expected");
16008 : 0 : return false;
16009 : : }
16010 : 3017 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
16011 : 2943 : c_parser_for_statement (parser, ivdep, unroll, novector, if_p,
16012 : : before_labels);
16013 : 74 : else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
16014 : 15 : c_parser_while_statement (parser, ivdep, unroll, novector, if_p,
16015 : : before_labels);
16016 : : else
16017 : 59 : c_parser_do_statement (parser, ivdep, unroll, novector,
16018 : : before_labels);
16019 : : }
16020 : : return true;
16021 : :
16022 : 1 : case PRAGMA_GCC_PCH_PREPROCESS:
16023 : 1 : c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
16024 : 1 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16025 : 1 : return false;
16026 : :
16027 : 89 : case PRAGMA_OACC_WAIT:
16028 : 89 : if (context != pragma_compound)
16029 : : {
16030 : 3 : construct = "acc wait";
16031 : 3 : goto in_compound;
16032 : : }
16033 : : /* FALL THROUGH. */
16034 : :
16035 : 1933318 : default:
16036 : 1933318 : if (id < PRAGMA_FIRST_EXTERNAL)
16037 : : {
16038 : 17232 : if (context != pragma_stmt && context != pragma_compound)
16039 : : {
16040 : 2 : bad_stmt:
16041 : 5 : c_parser_error (parser, "expected declaration specifiers");
16042 : 5 : c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
16043 : 5 : return false;
16044 : : }
16045 : 17230 : c_parser_omp_construct (parser, if_p);
16046 : 17230 : return true;
16047 : : }
16048 : 1916086 : break;
16049 : : }
16050 : :
16051 : 1916086 : c_parser_consume_pragma (parser);
16052 : 1916086 : c_invoke_pragma_handler (id);
16053 : :
16054 : : /* Skip to EOL, but suppress any error message. Those will have been
16055 : : generated by the handler routine through calling error, as opposed
16056 : : to calling c_parser_error. */
16057 : 1916086 : parser->error = true;
16058 : 1916086 : c_parser_skip_to_pragma_eol (parser);
16059 : :
16060 : 1916086 : return false;
16061 : : }
16062 : :
16063 : : /* The interface the pragma parsers have to the lexer. */
16064 : :
16065 : : enum cpp_ttype
16066 : 3628385 : pragma_lex (tree *value, location_t *loc)
16067 : : {
16068 : 3628385 : c_token *tok = c_parser_peek_token (the_parser);
16069 : 3628385 : enum cpp_ttype ret = tok->type;
16070 : :
16071 : 3628385 : *value = tok->value;
16072 : 3628385 : if (loc)
16073 : 1507931 : *loc = tok->location;
16074 : :
16075 : 3628385 : if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
16076 : : ret = CPP_EOF;
16077 : 2041271 : else if (ret == CPP_STRING)
16078 : 641556 : *value = c_parser_string_literal (the_parser, false, false).value;
16079 : : else
16080 : : {
16081 : 1399715 : if (ret == CPP_KEYWORD)
16082 : 344 : ret = CPP_NAME;
16083 : 1399715 : c_parser_consume_token (the_parser);
16084 : : }
16085 : :
16086 : 3628385 : return ret;
16087 : : }
16088 : :
16089 : : void
16090 : 9508 : pragma_lex_discard_to_eol ()
16091 : : {
16092 : 9508 : cpp_ttype type;
16093 : 9508 : do
16094 : : {
16095 : 9508 : type = c_parser_peek_token (the_parser)->type;
16096 : 9508 : gcc_assert (type != CPP_EOF);
16097 : 9508 : c_parser_consume_token (the_parser);
16098 : 9508 : } while (type != CPP_PRAGMA_EOL);
16099 : 9508 : }
16100 : :
16101 : : static void
16102 : 12 : c_parser_pragma_pch_preprocess (c_parser *parser)
16103 : : {
16104 : 12 : tree name = NULL;
16105 : :
16106 : 12 : parser->lex_joined_string = true;
16107 : 12 : c_parser_consume_pragma (parser);
16108 : 12 : if (c_parser_next_token_is (parser, CPP_STRING))
16109 : : {
16110 : 12 : name = c_parser_peek_token (parser)->value;
16111 : 12 : c_parser_consume_token (parser);
16112 : : }
16113 : : else
16114 : 0 : c_parser_error (parser, "expected string literal");
16115 : 12 : c_parser_skip_to_pragma_eol (parser);
16116 : 12 : parser->lex_joined_string = false;
16117 : :
16118 : 12 : if (name)
16119 : 12 : c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
16120 : 12 : }
16121 : :
16122 : : /* OpenACC and OpenMP parsing routines. */
16123 : :
16124 : : /* Returns name of the next clause.
16125 : : If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
16126 : : the token is not consumed. Otherwise appropriate pragma_omp_clause is
16127 : : returned and the token is consumed. */
16128 : :
16129 : : static pragma_omp_clause
16130 : 34084 : c_parser_omp_clause_name (c_parser *parser)
16131 : : {
16132 : 34084 : pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
16133 : :
16134 : 34084 : if (c_parser_next_token_is_keyword (parser, RID_AUTO))
16135 : : result = PRAGMA_OACC_CLAUSE_AUTO;
16136 : 33959 : else if (c_parser_next_token_is_keyword (parser, RID_IF))
16137 : : result = PRAGMA_OMP_CLAUSE_IF;
16138 : 33076 : else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
16139 : : result = PRAGMA_OMP_CLAUSE_DEFAULT;
16140 : 32348 : else if (c_parser_next_token_is_keyword (parser, RID_FOR))
16141 : : result = PRAGMA_OMP_CLAUSE_FOR;
16142 : 32264 : else if (c_parser_next_token_is (parser, CPP_NAME))
16143 : : {
16144 : 32181 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16145 : :
16146 : 32181 : switch (p[0])
16147 : : {
16148 : 1111 : case 'a':
16149 : 1111 : if (!strcmp ("affinity", p))
16150 : : result = PRAGMA_OMP_CLAUSE_AFFINITY;
16151 : 965 : else if (!strcmp ("aligned", p))
16152 : : result = PRAGMA_OMP_CLAUSE_ALIGNED;
16153 : 737 : else if (!strcmp ("allocate", p))
16154 : : result = PRAGMA_OMP_CLAUSE_ALLOCATE;
16155 : 270 : else if (!strcmp ("async", p))
16156 : : result = PRAGMA_OACC_CLAUSE_ASYNC;
16157 : 30 : else if (!strcmp ("attach", p))
16158 : 34084 : result = PRAGMA_OACC_CLAUSE_ATTACH;
16159 : : break;
16160 : 116 : case 'b':
16161 : 116 : if (!strcmp ("bind", p))
16162 : 34084 : result = PRAGMA_OMP_CLAUSE_BIND;
16163 : : break;
16164 : 4584 : case 'c':
16165 : 4584 : if (!strcmp ("collapse", p))
16166 : : result = PRAGMA_OMP_CLAUSE_COLLAPSE;
16167 : 1638 : else if (!strcmp ("copy", p))
16168 : : result = PRAGMA_OACC_CLAUSE_COPY;
16169 : 854 : else if (!strcmp ("copyin", p))
16170 : : result = PRAGMA_OMP_CLAUSE_COPYIN;
16171 : 419 : else if (!strcmp ("copyout", p))
16172 : : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16173 : 96 : else if (!strcmp ("copyprivate", p))
16174 : : result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
16175 : 75 : else if (!strcmp ("create", p))
16176 : 34084 : result = PRAGMA_OACC_CLAUSE_CREATE;
16177 : : break;
16178 : 3503 : case 'd':
16179 : 3503 : if (!strcmp ("defaultmap", p))
16180 : : result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
16181 : 3264 : else if (!strcmp ("delete", p))
16182 : : result = PRAGMA_OACC_CLAUSE_DELETE;
16183 : 3196 : else if (!strcmp ("depend", p))
16184 : : result = PRAGMA_OMP_CLAUSE_DEPEND;
16185 : 2341 : else if (!strcmp ("destroy", p))
16186 : : result = PRAGMA_OMP_CLAUSE_DESTROY;
16187 : 2300 : else if (!strcmp ("detach", p))
16188 : : result = PRAGMA_OACC_CLAUSE_DETACH;
16189 : 2246 : else if (!strcmp ("device", p))
16190 : : result = PRAGMA_OMP_CLAUSE_DEVICE;
16191 : 1843 : else if (!strcmp ("deviceptr", p))
16192 : : result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
16193 : 1786 : else if (!strcmp ("device_resident", p))
16194 : : result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
16195 : 1770 : else if (!strcmp ("device_type", p))
16196 : : result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
16197 : 1728 : else if (!strcmp ("dist_schedule", p))
16198 : : result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
16199 : 146 : else if (!strcmp ("doacross", p))
16200 : 34084 : result = PRAGMA_OMP_CLAUSE_DOACROSS;
16201 : : break;
16202 : 42 : case 'e':
16203 : 42 : if (!strcmp ("enter", p))
16204 : 34084 : result = PRAGMA_OMP_CLAUSE_ENTER;
16205 : : break;
16206 : 3471 : case 'f':
16207 : 3471 : if (!strcmp ("filter", p))
16208 : : result = PRAGMA_OMP_CLAUSE_FILTER;
16209 : 3409 : else if (!strcmp ("final", p))
16210 : : result = PRAGMA_OMP_CLAUSE_FINAL;
16211 : 3311 : else if (!strcmp ("finalize", p))
16212 : : result = PRAGMA_OACC_CLAUSE_FINALIZE;
16213 : 3299 : else if (!strcmp ("firstprivate", p))
16214 : : result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
16215 : 2521 : else if (!strcmp ("from", p))
16216 : : result = PRAGMA_OMP_CLAUSE_FROM;
16217 : 71 : else if (!strcmp ("full", p))
16218 : 34084 : result = PRAGMA_OMP_CLAUSE_FULL;
16219 : : break;
16220 : 651 : case 'g':
16221 : 651 : if (!strcmp ("gang", p))
16222 : : result = PRAGMA_OACC_CLAUSE_GANG;
16223 : 62 : else if (!strcmp ("grainsize", p))
16224 : 34084 : result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
16225 : : break;
16226 : 157 : case 'h':
16227 : 157 : if (!strcmp ("has_device_addr", p))
16228 : : result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
16229 : 70 : else if (!strcmp ("hint", p))
16230 : : result = PRAGMA_OMP_CLAUSE_HINT;
16231 : 41 : else if (!strcmp ("host", p))
16232 : 34084 : result = PRAGMA_OACC_CLAUSE_HOST;
16233 : : break;
16234 : 797 : case 'i':
16235 : 797 : if (!strcmp ("if_present", p))
16236 : : result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
16237 : 778 : else if (!strcmp ("in_reduction", p))
16238 : : result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
16239 : 458 : else if (!strcmp ("inbranch", p))
16240 : : result = PRAGMA_OMP_CLAUSE_INBRANCH;
16241 : 395 : else if (!strcmp ("independent", p))
16242 : : result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
16243 : 350 : else if (!strcmp ("indirect", p))
16244 : : result = PRAGMA_OMP_CLAUSE_INDIRECT;
16245 : 324 : else if (!strcmp ("init", p))
16246 : : result = PRAGMA_OMP_CLAUSE_INIT;
16247 : 157 : else if (!strcmp ("is_device_ptr", p))
16248 : : result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
16249 : 43 : else if (!strcmp ("interop", p))
16250 : 34084 : result = PRAGMA_OMP_CLAUSE_INTEROP;
16251 : : break;
16252 : 1250 : case 'l':
16253 : 1250 : if (!strcmp ("lastprivate", p))
16254 : : result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
16255 : 519 : else if (!strcmp ("linear", p))
16256 : : result = PRAGMA_OMP_CLAUSE_LINEAR;
16257 : 45 : else if (!strcmp ("link", p))
16258 : 34084 : result = PRAGMA_OMP_CLAUSE_LINK;
16259 : : break;
16260 : 1809 : case 'm':
16261 : 1809 : if (!strcmp ("map", p))
16262 : : result = PRAGMA_OMP_CLAUSE_MAP;
16263 : 78 : else if (!strcmp ("mergeable", p))
16264 : 34084 : result = PRAGMA_OMP_CLAUSE_MERGEABLE;
16265 : : break;
16266 : 1922 : case 'n':
16267 : 1922 : if (!strcmp ("no_create", p))
16268 : : result = PRAGMA_OACC_CLAUSE_NO_CREATE;
16269 : 1912 : else if (!strcmp ("nocontext", p))
16270 : : result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
16271 : 1889 : else if (!strcmp ("nogroup", p))
16272 : : result = PRAGMA_OMP_CLAUSE_NOGROUP;
16273 : 1871 : else if (!strcmp ("nohost", p))
16274 : : result = PRAGMA_OACC_CLAUSE_NOHOST;
16275 : 1846 : else if (!strcmp ("nontemporal", p))
16276 : : result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
16277 : 1725 : else if (!strcmp ("notinbranch", p))
16278 : : result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
16279 : 1589 : else if (!strcmp ("novariants", p))
16280 : : result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
16281 : 1568 : else if (!strcmp ("nowait", p))
16282 : : result = PRAGMA_OMP_CLAUSE_NOWAIT;
16283 : 1177 : else if (!strcmp ("num_gangs", p))
16284 : : result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
16285 : 875 : else if (!strcmp ("num_tasks", p))
16286 : : result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
16287 : 826 : else if (!strcmp ("num_teams", p))
16288 : : result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
16289 : 631 : else if (!strcmp ("num_threads", p))
16290 : : result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
16291 : 207 : else if (!strcmp ("num_workers", p))
16292 : 34084 : result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
16293 : : break;
16294 : 689 : case 'o':
16295 : 689 : if (!strcmp ("ordered", p))
16296 : : result = PRAGMA_OMP_CLAUSE_ORDERED;
16297 : 380 : else if (!strcmp ("order", p))
16298 : 34084 : result = PRAGMA_OMP_CLAUSE_ORDER;
16299 : : break;
16300 : 1634 : case 'p':
16301 : 1634 : if (!strcmp ("parallel", p))
16302 : : result = PRAGMA_OMP_CLAUSE_PARALLEL;
16303 : 1527 : else if (!strcmp ("partial", p))
16304 : : result = PRAGMA_OMP_CLAUSE_PARTIAL;
16305 : 1297 : else if (!strcmp ("present", p))
16306 : : result = PRAGMA_OACC_CLAUSE_PRESENT;
16307 : : /* As of OpenACC 2.5, these are now aliases of the non-present_or
16308 : : clauses. */
16309 : 1169 : else if (!strcmp ("present_or_copy", p)
16310 : 1156 : || !strcmp ("pcopy", p))
16311 : : result = PRAGMA_OACC_CLAUSE_COPY;
16312 : 1147 : else if (!strcmp ("present_or_copyin", p)
16313 : 1131 : || !strcmp ("pcopyin", p))
16314 : : result = PRAGMA_OACC_CLAUSE_COPYIN;
16315 : 1122 : else if (!strcmp ("present_or_copyout", p)
16316 : 1069 : || !strcmp ("pcopyout", p))
16317 : : result = PRAGMA_OACC_CLAUSE_COPYOUT;
16318 : 1055 : else if (!strcmp ("present_or_create", p)
16319 : 1041 : || !strcmp ("pcreate", p))
16320 : : result = PRAGMA_OACC_CLAUSE_CREATE;
16321 : 1036 : else if (!strcmp ("priority", p))
16322 : : result = PRAGMA_OMP_CLAUSE_PRIORITY;
16323 : 939 : else if (!strcmp ("private", p))
16324 : : result = PRAGMA_OMP_CLAUSE_PRIVATE;
16325 : 204 : else if (!strcmp ("proc_bind", p))
16326 : 34084 : result = PRAGMA_OMP_CLAUSE_PROC_BIND;
16327 : : break;
16328 : 2683 : case 'r':
16329 : 2683 : if (!strcmp ("reduction", p))
16330 : 34084 : result = PRAGMA_OMP_CLAUSE_REDUCTION;
16331 : : break;
16332 : 5162 : case 's':
16333 : 5162 : if (!strcmp ("safelen", p))
16334 : : result = PRAGMA_OMP_CLAUSE_SAFELEN;
16335 : 4935 : else if (!strcmp ("schedule", p))
16336 : : result = PRAGMA_OMP_CLAUSE_SCHEDULE;
16337 : 1468 : else if (!strcmp ("sections", p))
16338 : : result = PRAGMA_OMP_CLAUSE_SECTIONS;
16339 : 1390 : else if (!strcmp ("self", p))
16340 : : result = PRAGMA_OACC_CLAUSE_SELF;
16341 : 1324 : else if (!strcmp ("seq", p))
16342 : : result = PRAGMA_OACC_CLAUSE_SEQ;
16343 : 1063 : else if (!strcmp ("shared", p))
16344 : : result = PRAGMA_OMP_CLAUSE_SHARED;
16345 : 374 : else if (!strcmp ("simd", p))
16346 : : result = PRAGMA_OMP_CLAUSE_SIMD;
16347 : 317 : else if (!strcmp ("simdlen", p))
16348 : 34084 : result = PRAGMA_OMP_CLAUSE_SIMDLEN;
16349 : : break;
16350 : 996 : case 't':
16351 : 996 : if (!strcmp ("task_reduction", p))
16352 : : result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
16353 : 910 : else if (!strcmp ("taskgroup", p))
16354 : : result = PRAGMA_OMP_CLAUSE_TASKGROUP;
16355 : 800 : else if (!strcmp ("thread_limit", p))
16356 : : result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
16357 : 646 : else if (!strcmp ("threads", p))
16358 : : result = PRAGMA_OMP_CLAUSE_THREADS;
16359 : 600 : else if (!strcmp ("tile", p))
16360 : : result = PRAGMA_OACC_CLAUSE_TILE;
16361 : 477 : else if (!strcmp ("to", p))
16362 : 34084 : result = PRAGMA_OMP_CLAUSE_TO;
16363 : : break;
16364 : 320 : case 'u':
16365 : 320 : if (!strcmp ("uniform", p))
16366 : : result = PRAGMA_OMP_CLAUSE_UNIFORM;
16367 : 205 : else if (!strcmp ("untied", p))
16368 : : result = PRAGMA_OMP_CLAUSE_UNTIED;
16369 : 109 : else if (!strcmp ("use", p))
16370 : : result = PRAGMA_OMP_CLAUSE_USE;
16371 : 66 : else if (!strcmp ("use_device", p))
16372 : : result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
16373 : 45 : else if (!strcmp ("use_device_addr", p))
16374 : : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
16375 : 10 : else if (!strcmp ("use_device_ptr", p))
16376 : 34084 : result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
16377 : : break;
16378 : 741 : case 'v':
16379 : 741 : if (!strcmp ("vector", p))
16380 : : result = PRAGMA_OACC_CLAUSE_VECTOR;
16381 : 223 : else if (!strcmp ("vector_length", p))
16382 : 34084 : result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
16383 : : break;
16384 : 542 : case 'w':
16385 : 542 : if (!strcmp ("wait", p))
16386 : : result = PRAGMA_OACC_CLAUSE_WAIT;
16387 : 453 : else if (!strcmp ("worker", p))
16388 : 34084 : result = PRAGMA_OACC_CLAUSE_WORKER;
16389 : : break;
16390 : : }
16391 : : }
16392 : :
16393 : 34084 : if (result != PRAGMA_OMP_CLAUSE_NONE)
16394 : 33975 : c_parser_consume_token (parser);
16395 : :
16396 : 34084 : return result;
16397 : : }
16398 : :
16399 : : /* Validate that a clause of the given type does not already exist. */
16400 : :
16401 : : static void
16402 : 17528 : check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
16403 : : const char *name)
16404 : : {
16405 : 17528 : if (tree c = omp_find_clause (clauses, code))
16406 : 347 : error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
16407 : 17528 : }
16408 : :
16409 : : /* OpenACC 2.0
16410 : : Parse wait clause or wait directive parameters. */
16411 : :
16412 : : static tree
16413 : 123 : c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
16414 : : {
16415 : 123 : vec<tree, va_gc> *args;
16416 : 123 : tree t, args_tree;
16417 : :
16418 : 123 : matching_parens parens;
16419 : 123 : if (!parens.require_open (parser))
16420 : : return list;
16421 : :
16422 : 123 : args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL);
16423 : 123 : args_tree = build_tree_list_vec (args);
16424 : :
16425 : 289 : for (t = args_tree; t; t = TREE_CHAIN (t))
16426 : : {
16427 : 166 : tree targ = TREE_VALUE (t);
16428 : :
16429 : 166 : if (targ != error_mark_node)
16430 : : {
16431 : 152 : if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
16432 : : {
16433 : 6 : c_parser_error (parser, "expression must be integral");
16434 : 6 : targ = error_mark_node;
16435 : : }
16436 : : else
16437 : : {
16438 : 146 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16439 : :
16440 : 146 : OMP_CLAUSE_DECL (c) = targ;
16441 : 146 : OMP_CLAUSE_CHAIN (c) = list;
16442 : 146 : list = c;
16443 : : }
16444 : : }
16445 : : }
16446 : :
16447 : 123 : release_tree_vector (args);
16448 : 123 : parens.require_close (parser);
16449 : 123 : return list;
16450 : : }
16451 : :
16452 : : /* OpenACC 2.0, OpenMP 2.5:
16453 : : variable-list:
16454 : : identifier
16455 : : variable-list , identifier
16456 : :
16457 : : If KIND is nonzero, create the appropriate node and install the
16458 : : decl in OMP_CLAUSE_DECL and add the node to the head of the list.
16459 : : If KIND is nonzero, CLAUSE_LOC is the location of the clause.
16460 : :
16461 : : If KIND is zero (= OMP_CLAUSE_ERROR), create a TREE_LIST with the decl
16462 : : in TREE_PURPOSE and the location in TREE_VALUE (accessible using
16463 : : EXPR_LOCATION); return the list created.
16464 : :
16465 : : The optional ALLOW_DEREF argument is true if list items can use the deref
16466 : : (->) operator. */
16467 : :
16468 : : struct omp_dim
16469 : : {
16470 : : tree low_bound, length;
16471 : : location_t loc;
16472 : : bool no_colon;
16473 : 3306 : omp_dim (tree lb, tree len, location_t lo, bool nc)
16474 : 3306 : : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
16475 : : };
16476 : :
16477 : : static tree
16478 : 16261 : c_parser_omp_variable_list (c_parser *parser,
16479 : : location_t clause_loc,
16480 : : enum omp_clause_code kind, tree list,
16481 : : bool map_lvalue = false)
16482 : : {
16483 : 16261 : auto_vec<omp_dim> dims;
16484 : 16261 : bool array_section_p;
16485 : 16261 : auto_vec<c_token> tokens;
16486 : 16261 : unsigned int tokens_avail = 0;
16487 : 16261 : c_token *saved_tokens = NULL;
16488 : :
16489 : 19447 : while (1)
16490 : : {
16491 : 19447 : tree t = NULL_TREE;
16492 : 19447 : location_t tloc = c_parser_peek_token (parser)->location;
16493 : :
16494 : 19447 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16495 : : {
16496 : 888 : if (c_parser_next_token_is_not (parser, CPP_NAME)
16497 : 888 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
16498 : : {
16499 : 29 : struct c_expr expr;
16500 : 29 : if (kind == OMP_CLAUSE_DEPEND
16501 : 27 : && c_parser_next_token_is_keyword (parser,
16502 : : RID_OMP_ALL_MEMORY)
16503 : 45 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16504 : 13 : || (c_parser_peek_2nd_token (parser)->type
16505 : : == CPP_CLOSE_PAREN)))
16506 : : {
16507 : 15 : expr.value = ridpointers[RID_OMP_ALL_MEMORY];
16508 : 15 : c_parser_consume_token (parser);
16509 : : }
16510 : : else
16511 : 14 : expr = c_parser_expr_no_commas (parser, NULL);
16512 : 29 : if (expr.value != error_mark_node)
16513 : : {
16514 : 27 : tree u = build_omp_clause (clause_loc, kind);
16515 : 27 : OMP_CLAUSE_DECL (u) = expr.value;
16516 : 27 : OMP_CLAUSE_CHAIN (u) = list;
16517 : 27 : list = u;
16518 : : }
16519 : :
16520 : 29 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
16521 : : break;
16522 : :
16523 : 4 : c_parser_consume_token (parser);
16524 : 4 : continue;
16525 : 4 : }
16526 : :
16527 : 859 : tokens.truncate (0);
16528 : 859 : unsigned int nesting_depth = 0;
16529 : 11227 : while (1)
16530 : : {
16531 : 6043 : c_token *token = c_parser_peek_token (parser);
16532 : 6043 : switch (token->type)
16533 : : {
16534 : : case CPP_EOF:
16535 : : case CPP_PRAGMA_EOL:
16536 : : break;
16537 : 930 : case CPP_OPEN_BRACE:
16538 : 930 : case CPP_OPEN_PAREN:
16539 : 930 : case CPP_OPEN_SQUARE:
16540 : 930 : ++nesting_depth;
16541 : 930 : goto add;
16542 : 1723 : case CPP_CLOSE_BRACE:
16543 : 1723 : case CPP_CLOSE_PAREN:
16544 : 1723 : case CPP_CLOSE_SQUARE:
16545 : 1723 : if (nesting_depth-- == 0)
16546 : : break;
16547 : 930 : goto add;
16548 : 138 : case CPP_COMMA:
16549 : 138 : if (nesting_depth == 0)
16550 : : break;
16551 : 72 : goto add;
16552 : 5184 : default:
16553 : 5184 : add:
16554 : 5184 : tokens.safe_push (*token);
16555 : 5184 : c_parser_consume_token (parser);
16556 : 5184 : continue;
16557 : : }
16558 : 859 : break;
16559 : 5184 : }
16560 : :
16561 : : /* Make sure nothing tries to read past the end of the tokens. */
16562 : 859 : c_token eof_token;
16563 : 859 : memset (&eof_token, 0, sizeof (eof_token));
16564 : 859 : eof_token.type = CPP_EOF;
16565 : 859 : tokens.safe_push (eof_token);
16566 : 859 : tokens.safe_push (eof_token);
16567 : :
16568 : 859 : saved_tokens = parser->tokens;
16569 : 859 : tokens_avail = parser->tokens_avail;
16570 : 859 : parser->tokens = tokens.address ();
16571 : 1718 : parser->tokens_avail = tokens.length ();
16572 : : }
16573 : 18559 : else if (map_lvalue
16574 : 2119 : && (kind == OMP_CLAUSE_MAP
16575 : : || kind == OMP_CLAUSE_TO
16576 : 2119 : || kind == OMP_CLAUSE_FROM))
16577 : : {
16578 : 2119 : location_t loc = c_parser_peek_token (parser)->location;
16579 : 2119 : bool save_c_omp_array_section_p = c_omp_array_section_p;
16580 : 2119 : c_omp_array_section_p = true;
16581 : 2119 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
16582 : 2119 : if (expr.value != error_mark_node)
16583 : 2111 : mark_exp_read (expr.value);
16584 : 2119 : c_omp_array_section_p = save_c_omp_array_section_p;
16585 : 2119 : tree decl = expr.value;
16586 : :
16587 : : /* This code rewrites a parsed expression containing various tree
16588 : : codes used to represent array accesses into a more uniform nest of
16589 : : OMP_ARRAY_SECTION nodes before it is processed by
16590 : : c-typeck.cc:handle_omp_array_sections_1. It might be more
16591 : : efficient to move this logic to that function instead, analysing
16592 : : the parsed expression directly rather than this preprocessed
16593 : : form. (See also equivalent code in cp/parser.cc,
16594 : : cp/semantics.cc). */
16595 : 2119 : dims.truncate (0);
16596 : 2119 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16597 : : {
16598 : 1050 : while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16599 : : {
16600 : 555 : tree low_bound = TREE_OPERAND (decl, 1);
16601 : 555 : tree length = TREE_OPERAND (decl, 2);
16602 : 555 : dims.safe_push (omp_dim (low_bound, length, loc, false));
16603 : 555 : decl = TREE_OPERAND (decl, 0);
16604 : : }
16605 : :
16606 : 528 : while (TREE_CODE (decl) == ARRAY_REF
16607 : : || TREE_CODE (decl) == INDIRECT_REF
16608 : 528 : || TREE_CODE (decl) == COMPOUND_EXPR)
16609 : : {
16610 : 33 : if (TREE_CODE (decl) == COMPOUND_EXPR)
16611 : : {
16612 : 2 : decl = TREE_OPERAND (decl, 1);
16613 : 2 : STRIP_NOPS (decl);
16614 : : }
16615 : 31 : else if (TREE_CODE (decl) == INDIRECT_REF)
16616 : : {
16617 : 46 : dims.safe_push (omp_dim (integer_zero_node,
16618 : 23 : integer_one_node, loc, true));
16619 : 23 : decl = TREE_OPERAND (decl, 0);
16620 : : }
16621 : : else /* ARRAY_REF. */
16622 : : {
16623 : 8 : tree index = TREE_OPERAND (decl, 1);
16624 : 16 : dims.safe_push (omp_dim (index, integer_one_node, loc,
16625 : 8 : true));
16626 : 8 : decl = TREE_OPERAND (decl, 0);
16627 : : }
16628 : : }
16629 : :
16630 : 1576 : for (int i = dims.length () - 1; i >= 0; i--)
16631 : 586 : decl = build_omp_array_section (loc, decl, dims[i].low_bound,
16632 : 586 : dims[i].length);
16633 : : }
16634 : 1624 : else if (TREE_CODE (decl) == INDIRECT_REF)
16635 : : {
16636 : : /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
16637 : 50 : decl = TREE_OPERAND (decl, 0);
16638 : 50 : STRIP_NOPS (decl);
16639 : :
16640 : 50 : decl = build_omp_array_section (loc, decl, integer_zero_node,
16641 : : integer_one_node);
16642 : : }
16643 : 1574 : else if (TREE_CODE (decl) == ARRAY_REF)
16644 : : {
16645 : 12 : tree idx = TREE_OPERAND (decl, 1);
16646 : :
16647 : 12 : decl = TREE_OPERAND (decl, 0);
16648 : 12 : STRIP_NOPS (decl);
16649 : :
16650 : 12 : decl = build_omp_array_section (loc, decl, idx, integer_one_node);
16651 : : }
16652 : 1562 : else if (TREE_CODE (decl) == NON_LVALUE_EXPR
16653 : 1562 : || CONVERT_EXPR_P (decl))
16654 : 0 : decl = TREE_OPERAND (decl, 0);
16655 : :
16656 : 2119 : tree u = build_omp_clause (loc, kind);
16657 : 2119 : OMP_CLAUSE_DECL (u) = decl;
16658 : 2119 : OMP_CLAUSE_CHAIN (u) = list;
16659 : 2119 : list = u;
16660 : :
16661 : 2119 : goto next_item;
16662 : : }
16663 : :
16664 : 17299 : if (c_parser_next_token_is (parser, CPP_NAME)
16665 : 17299 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
16666 : : {
16667 : 17262 : t = lookup_name (c_parser_peek_token (parser)->value);
16668 : :
16669 : 17262 : if (t == NULL_TREE)
16670 : : {
16671 : 14 : undeclared_variable (c_parser_peek_token (parser)->location,
16672 : 14 : c_parser_peek_token (parser)->value);
16673 : 14 : t = error_mark_node;
16674 : : }
16675 : :
16676 : 17262 : c_parser_consume_token (parser);
16677 : : }
16678 : 37 : else if (c_parser_next_token_is (parser, CPP_KEYWORD)
16679 : 37 : && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
16680 : 15 : || (c_parser_peek_token (parser)->keyword
16681 : : == RID_PRETTY_FUNCTION_NAME)
16682 : 9 : || (c_parser_peek_token (parser)->keyword
16683 : : == RID_C99_FUNCTION_NAME)))
16684 : 20 : t = c_parser_predefined_identifier (parser).value;
16685 : : else
16686 : : {
16687 : 17 : c_parser_error (parser, "expected identifier");
16688 : 17 : break;
16689 : : }
16690 : :
16691 : 17282 : if (t == error_mark_node)
16692 : : ;
16693 : 17264 : else if (kind != 0) /* kind != OMP_CLAUSE_ERROR */
16694 : : {
16695 : 17037 : switch (kind)
16696 : : {
16697 : 139 : case OMP_CLAUSE__CACHE_:
16698 : : /* The OpenACC cache directive explicitly only allows "array
16699 : : elements or subarrays". */
16700 : 139 : if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
16701 : : {
16702 : 3 : c_parser_error (parser, "expected %<[%>");
16703 : 3 : t = error_mark_node;
16704 : 3 : break;
16705 : : }
16706 : : /* FALLTHROUGH */
16707 : : case OMP_CLAUSE_MAP:
16708 : : case OMP_CLAUSE_FROM:
16709 : : case OMP_CLAUSE_TO:
16710 : 136 : start_component_ref:
16711 : 5963 : while (c_parser_next_token_is (parser, CPP_DOT)
16712 : 11719 : || c_parser_next_token_is (parser, CPP_DEREF))
16713 : : {
16714 : 316 : location_t op_loc = c_parser_peek_token (parser)->location;
16715 : 316 : location_t arrow_loc = UNKNOWN_LOCATION;
16716 : 316 : if (c_parser_next_token_is (parser, CPP_DEREF))
16717 : : {
16718 : 109 : c_expr t_expr;
16719 : 109 : t_expr.value = t;
16720 : 109 : t_expr.original_code = ERROR_MARK;
16721 : 109 : t_expr.original_type = NULL;
16722 : 109 : set_c_expr_source_range (&t_expr, op_loc, op_loc);
16723 : 109 : t_expr.m_decimal = 0;
16724 : 109 : t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
16725 : : true, false);
16726 : 109 : t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
16727 : 109 : arrow_loc = t_expr.get_location ();
16728 : : }
16729 : 316 : c_parser_consume_token (parser);
16730 : 316 : if (!c_parser_next_token_is (parser, CPP_NAME))
16731 : : {
16732 : 0 : c_parser_error (parser, "expected identifier");
16733 : 0 : t = error_mark_node;
16734 : 0 : break;
16735 : : }
16736 : :
16737 : 316 : c_token *comp_tok = c_parser_peek_token (parser);
16738 : 316 : tree ident = comp_tok->value;
16739 : 316 : location_t comp_loc = comp_tok->location;
16740 : 316 : c_parser_consume_token (parser);
16741 : 316 : t = build_component_ref (op_loc, t, ident, comp_loc,
16742 : : arrow_loc);
16743 : : }
16744 : : /* FALLTHROUGH */
16745 : 10292 : case OMP_CLAUSE_AFFINITY:
16746 : 10292 : case OMP_CLAUSE_DEPEND:
16747 : 10292 : case OMP_CLAUSE_REDUCTION:
16748 : 10292 : case OMP_CLAUSE_IN_REDUCTION:
16749 : 10292 : case OMP_CLAUSE_TASK_REDUCTION:
16750 : 10292 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
16751 : 10292 : array_section_p = false;
16752 : 10292 : dims.truncate (0);
16753 : 23304 : while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
16754 : : {
16755 : 2720 : location_t loc = UNKNOWN_LOCATION;
16756 : 2720 : tree low_bound = NULL_TREE, length = NULL_TREE;
16757 : 2720 : bool no_colon = false;
16758 : :
16759 : 2720 : c_parser_consume_token (parser);
16760 : 2720 : if (!c_parser_next_token_is (parser, CPP_COLON))
16761 : : {
16762 : 2300 : location_t expr_loc
16763 : 2300 : = c_parser_peek_token (parser)->location;
16764 : 2300 : c_expr expr = c_parser_expression (parser);
16765 : 2300 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
16766 : : false, true);
16767 : 2300 : low_bound = expr.value;
16768 : 2300 : loc = expr_loc;
16769 : : }
16770 : 2720 : if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
16771 : : {
16772 : 432 : length = integer_one_node;
16773 : 432 : no_colon = true;
16774 : : }
16775 : : else
16776 : : {
16777 : : /* Look for `:'. */
16778 : 2288 : if (!c_parser_require (parser, CPP_COLON,
16779 : : "expected %<:%>"))
16780 : : {
16781 : 0 : t = error_mark_node;
16782 : 0 : break;
16783 : : }
16784 : 2288 : array_section_p = true;
16785 : 2288 : if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
16786 : : {
16787 : 2103 : location_t expr_loc
16788 : 2103 : = c_parser_peek_token (parser)->location;
16789 : 2103 : c_expr expr = c_parser_expression (parser);
16790 : 2103 : expr = convert_lvalue_to_rvalue (expr_loc, expr,
16791 : : false, true);
16792 : 2103 : length = expr.value;
16793 : : }
16794 : : }
16795 : : /* Look for the closing `]'. */
16796 : 2720 : if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
16797 : : "expected %<]%>"))
16798 : : {
16799 : 0 : t = error_mark_node;
16800 : 0 : break;
16801 : : }
16802 : :
16803 : 2720 : dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
16804 : : }
16805 : :
16806 : 10292 : if (t != error_mark_node)
16807 : : {
16808 : 10292 : if ((kind == OMP_CLAUSE_MAP
16809 : 10292 : || kind == OMP_CLAUSE_FROM
16810 : 5188 : || kind == OMP_CLAUSE_TO)
16811 : 5511 : && !array_section_p
16812 : 14548 : && (c_parser_next_token_is (parser, CPP_DOT)
16813 : 4252 : || c_parser_next_token_is (parser, CPP_DEREF)))
16814 : : {
16815 : 8 : for (unsigned i = 0; i < dims.length (); i++)
16816 : : {
16817 : 4 : gcc_assert (dims[i].length == integer_one_node);
16818 : 4 : t = build_array_ref (dims[i].loc,
16819 : 4 : t, dims[i].low_bound);
16820 : : }
16821 : 4 : goto start_component_ref;
16822 : : }
16823 : : else
16824 : 13004 : for (unsigned i = 0; i < dims.length (); i++)
16825 : 5432 : t = build_omp_array_section (clause_loc, t,
16826 : 2716 : dims[i].low_bound,
16827 : 2716 : dims[i].length);
16828 : : }
16829 : :
16830 : 10288 : if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16831 : 855 : && t != error_mark_node
16832 : 855 : && parser->tokens_avail != 2)
16833 : : {
16834 : 44 : if (array_section_p)
16835 : : {
16836 : 12 : error_at (c_parser_peek_token (parser)->location,
16837 : : "expected %<)%> or %<,%>");
16838 : 12 : t = error_mark_node;
16839 : : }
16840 : : else
16841 : : {
16842 : 32 : parser->tokens = tokens.address ();
16843 : 32 : parser->tokens_avail = tokens.length ();
16844 : :
16845 : 32 : t = c_parser_expr_no_commas (parser, NULL).value;
16846 : 32 : if (t != error_mark_node && parser->tokens_avail != 2)
16847 : : {
16848 : 0 : error_at (c_parser_peek_token (parser)->location,
16849 : : "expected %<)%> or %<,%>");
16850 : 0 : t = error_mark_node;
16851 : : }
16852 : : }
16853 : : }
16854 : : break;
16855 : : default:
16856 : : break;
16857 : : }
16858 : :
16859 : 17037 : if (t != error_mark_node)
16860 : : {
16861 : 17022 : tree u = build_omp_clause (clause_loc, kind);
16862 : 17022 : OMP_CLAUSE_DECL (u) = t;
16863 : 17022 : OMP_CLAUSE_CHAIN (u) = list;
16864 : 17022 : list = u;
16865 : : }
16866 : : }
16867 : : else /* kind == OMP_CLAUSE_ERROR */
16868 : 227 : list = tree_cons (t, build_empty_stmt (tloc), list);
16869 : :
16870 : 17282 : if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16871 : : {
16872 : 859 : parser->tokens = saved_tokens;
16873 : 859 : parser->tokens_avail = tokens_avail;
16874 : : }
16875 : :
16876 : 16423 : next_item:
16877 : 19401 : if (c_parser_next_token_is_not (parser, CPP_COMMA))
16878 : : break;
16879 : :
16880 : 3182 : c_parser_consume_token (parser);
16881 : : }
16882 : :
16883 : 16261 : return list;
16884 : 16261 : }
16885 : :
16886 : : /* Similarly, but expect leading and trailing parenthesis. This is a very
16887 : : common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
16888 : : argument is true if list items can use the deref (->) operator. */
16889 : :
16890 : : static tree
16891 : 3492 : c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
16892 : : tree list, bool map_lvalue = false)
16893 : : {
16894 : : /* The clauses location. */
16895 : 3492 : location_t loc = c_parser_peek_token (parser)->location;
16896 : :
16897 : 3492 : if (parser->in_omp_decl_attribute)
16898 : : {
16899 : 37 : if (kind)
16900 : : {
16901 : 22 : tree u = build_omp_clause (loc, kind);
16902 : 22 : OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
16903 : 22 : OMP_CLAUSE_CHAIN (u) = list;
16904 : 22 : return u;
16905 : : }
16906 : : else
16907 : 15 : return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
16908 : : }
16909 : :
16910 : 3455 : matching_parens parens;
16911 : 3455 : if (parens.require_open (parser))
16912 : : {
16913 : 3451 : list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue);
16914 : 3451 : parens.skip_until_found_close (parser);
16915 : : }
16916 : : return list;
16917 : : }
16918 : :
16919 : : /* OpenACC 2.0:
16920 : : copy ( variable-list )
16921 : : copyin ( variable-list )
16922 : : copyout ( variable-list )
16923 : : create ( variable-list )
16924 : : delete ( variable-list )
16925 : : present ( variable-list )
16926 : :
16927 : : OpenACC 2.6:
16928 : : no_create ( variable-list )
16929 : : attach ( variable-list )
16930 : : detach ( variable-list )
16931 : :
16932 : : OpenACC 2.7:
16933 : : copyin (readonly : variable-list )
16934 : : */
16935 : :
16936 : : static tree
16937 : 2026 : c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
16938 : : tree list)
16939 : : {
16940 : 2026 : enum gomp_map_kind kind;
16941 : 2026 : switch (c_kind)
16942 : : {
16943 : : case PRAGMA_OACC_CLAUSE_ATTACH:
16944 : : kind = GOMP_MAP_ATTACH;
16945 : : break;
16946 : 806 : case PRAGMA_OACC_CLAUSE_COPY:
16947 : 806 : kind = GOMP_MAP_TOFROM;
16948 : 806 : break;
16949 : 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
16950 : 359 : kind = GOMP_MAP_TO;
16951 : 359 : break;
16952 : 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
16953 : 390 : kind = GOMP_MAP_FROM;
16954 : 390 : break;
16955 : 94 : case PRAGMA_OACC_CLAUSE_CREATE:
16956 : 94 : kind = GOMP_MAP_ALLOC;
16957 : 94 : break;
16958 : 68 : case PRAGMA_OACC_CLAUSE_DELETE:
16959 : 68 : kind = GOMP_MAP_RELEASE;
16960 : 68 : break;
16961 : 20 : case PRAGMA_OACC_CLAUSE_DETACH:
16962 : 20 : kind = GOMP_MAP_DETACH;
16963 : 20 : break;
16964 : 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
16965 : 36 : kind = GOMP_MAP_FORCE_TO;
16966 : 36 : break;
16967 : 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
16968 : 16 : kind = GOMP_MAP_DEVICE_RESIDENT;
16969 : 16 : break;
16970 : 13 : case PRAGMA_OACC_CLAUSE_LINK:
16971 : 13 : kind = GOMP_MAP_LINK;
16972 : 13 : break;
16973 : 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
16974 : 10 : kind = GOMP_MAP_IF_PRESENT;
16975 : 10 : break;
16976 : 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
16977 : 128 : kind = GOMP_MAP_FORCE_PRESENT;
16978 : 128 : break;
16979 : 59 : case PRAGMA_OACC_CLAUSE_SELF:
16980 : : /* "The 'host' clause is a synonym for the 'self' clause." */
16981 : 59 : case PRAGMA_OACC_CLAUSE_HOST:
16982 : 59 : kind = GOMP_MAP_FORCE_FROM;
16983 : 59 : break;
16984 : 0 : default:
16985 : 0 : gcc_unreachable ();
16986 : : }
16987 : :
16988 : 2026 : tree nl = list;
16989 : 2026 : bool readonly = false;
16990 : 2026 : location_t open_loc = c_parser_peek_token (parser)->location;
16991 : 2026 : matching_parens parens;
16992 : 2026 : if (parens.require_open (parser))
16993 : : {
16994 : : /* Turn on readonly modifier parsing for copyin clause. */
16995 : 2026 : if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
16996 : : {
16997 : 359 : c_token *token = c_parser_peek_token (parser);
16998 : 359 : if (token->type == CPP_NAME
16999 : 359 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
17000 : 366 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17001 : : {
17002 : 7 : c_parser_consume_token (parser);
17003 : 7 : c_parser_consume_token (parser);
17004 : 7 : readonly = true;
17005 : : }
17006 : : }
17007 : 2026 : nl = c_parser_omp_variable_list (parser, open_loc, OMP_CLAUSE_MAP, list,
17008 : : false);
17009 : 2026 : parens.skip_until_found_close (parser);
17010 : : }
17011 : :
17012 : 4671 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
17013 : : {
17014 : 2645 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
17015 : 2645 : if (readonly)
17016 : 13 : OMP_CLAUSE_MAP_READONLY (c) = 1;
17017 : : }
17018 : :
17019 : 2026 : return nl;
17020 : : }
17021 : :
17022 : : /* OpenACC 2.0:
17023 : : deviceptr ( variable-list ) */
17024 : :
17025 : : static tree
17026 : 57 : c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
17027 : : {
17028 : 57 : tree vars, t;
17029 : :
17030 : : /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
17031 : : c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
17032 : : variable-list must only allow for pointer variables. */
17033 : 57 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
17034 : 118 : for (t = vars; t && t; t = TREE_CHAIN (t))
17035 : : {
17036 : 61 : tree v = TREE_PURPOSE (t);
17037 : 61 : location_t loc = EXPR_LOCATION (TREE_VALUE (t));
17038 : :
17039 : 61 : if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
17040 : 3 : error_at (loc, "%qD is not a variable", v);
17041 : 58 : else if (TREE_TYPE (v) == error_mark_node)
17042 : : ;
17043 : 57 : else if (!POINTER_TYPE_P (TREE_TYPE (v)))
17044 : 7 : error_at (loc, "%qD is not a pointer variable", v);
17045 : :
17046 : 61 : tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
17047 : 61 : OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
17048 : 61 : OMP_CLAUSE_DECL (u) = v;
17049 : 61 : OMP_CLAUSE_CHAIN (u) = list;
17050 : 61 : list = u;
17051 : : }
17052 : :
17053 : 57 : return list;
17054 : : }
17055 : :
17056 : : /* OpenACC 2.0, OpenMP 3.0:
17057 : : collapse ( constant-expression ) */
17058 : :
17059 : : static tree
17060 : 2946 : c_parser_omp_clause_collapse (c_parser *parser, tree list)
17061 : : {
17062 : 2946 : tree c, num = error_mark_node;
17063 : 2946 : HOST_WIDE_INT n;
17064 : 2946 : location_t loc;
17065 : :
17066 : 2946 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
17067 : 2946 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
17068 : :
17069 : 2946 : loc = c_parser_peek_token (parser)->location;
17070 : 2946 : matching_parens parens;
17071 : 2946 : if (parens.require_open (parser))
17072 : : {
17073 : 2946 : num = c_parser_expr_no_commas (parser, NULL).value;
17074 : 2946 : parens.skip_until_found_close (parser);
17075 : : }
17076 : 2946 : if (num == error_mark_node)
17077 : : return list;
17078 : 2946 : mark_exp_read (num);
17079 : 2946 : num = c_fully_fold (num, false, NULL);
17080 : 5892 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17081 : 2946 : || !tree_fits_shwi_p (num)
17082 : 2946 : || (n = tree_to_shwi (num)) <= 0
17083 : 5892 : || (int) n != n)
17084 : : {
17085 : 0 : error_at (loc,
17086 : : "collapse argument needs positive constant integer expression");
17087 : 0 : return list;
17088 : : }
17089 : 2946 : c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
17090 : 2946 : OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
17091 : 2946 : OMP_CLAUSE_CHAIN (c) = list;
17092 : 2946 : return c;
17093 : : }
17094 : :
17095 : : /* OpenMP 2.5:
17096 : : copyin ( variable-list ) */
17097 : :
17098 : : static tree
17099 : 101 : c_parser_omp_clause_copyin (c_parser *parser, tree list)
17100 : : {
17101 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
17102 : : }
17103 : :
17104 : : /* OpenMP 2.5:
17105 : : copyprivate ( variable-list ) */
17106 : :
17107 : : static tree
17108 : 21 : c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
17109 : : {
17110 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
17111 : : }
17112 : :
17113 : : /* OpenMP 2.5:
17114 : : default ( none | shared )
17115 : :
17116 : : OpenMP 5.1:
17117 : : default ( private | firstprivate )
17118 : :
17119 : : OpenACC:
17120 : : default ( none | present ) */
17121 : :
17122 : : static tree
17123 : 728 : c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
17124 : : {
17125 : 728 : enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
17126 : 728 : location_t loc = c_parser_peek_token (parser)->location;
17127 : 728 : tree c;
17128 : :
17129 : 728 : matching_parens parens;
17130 : 728 : if (!parens.require_open (parser))
17131 : : return list;
17132 : 725 : if (c_parser_next_token_is (parser, CPP_NAME))
17133 : : {
17134 : 713 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17135 : :
17136 : 713 : switch (p[0])
17137 : : {
17138 : 391 : case 'n':
17139 : 391 : if (strcmp ("none", p) != 0)
17140 : 0 : goto invalid_kind;
17141 : : kind = OMP_CLAUSE_DEFAULT_NONE;
17142 : : break;
17143 : :
17144 : 23 : case 'p':
17145 : 23 : if (is_oacc)
17146 : : {
17147 : 18 : if (strcmp ("present", p) != 0)
17148 : 3 : goto invalid_kind;
17149 : : kind = OMP_CLAUSE_DEFAULT_PRESENT;
17150 : : }
17151 : : else
17152 : : {
17153 : 5 : if (strcmp ("private", p) != 0)
17154 : 0 : goto invalid_kind;
17155 : : kind = OMP_CLAUSE_DEFAULT_PRIVATE;
17156 : : }
17157 : : break;
17158 : :
17159 : 9 : case 'f':
17160 : 9 : if (strcmp ("firstprivate", p) != 0 || is_oacc)
17161 : 0 : goto invalid_kind;
17162 : : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
17163 : : break;
17164 : :
17165 : 286 : case 's':
17166 : 286 : if (strcmp ("shared", p) != 0 || is_oacc)
17167 : 0 : goto invalid_kind;
17168 : : kind = OMP_CLAUSE_DEFAULT_SHARED;
17169 : : break;
17170 : :
17171 : 4 : default:
17172 : 4 : goto invalid_kind;
17173 : : }
17174 : :
17175 : 700 : c_parser_consume_token (parser);
17176 : : }
17177 : : else
17178 : : {
17179 : 25 : invalid_kind:
17180 : 25 : if (is_oacc)
17181 : 21 : c_parser_error (parser, "expected %<none%> or %<present%>");
17182 : : else
17183 : 4 : c_parser_error (parser, "expected %<none%>, %<shared%>, "
17184 : : "%<private%> or %<firstprivate%>");
17185 : : }
17186 : 725 : parens.skip_until_found_close (parser);
17187 : :
17188 : 725 : if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
17189 : : return list;
17190 : :
17191 : 700 : check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
17192 : 700 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
17193 : 700 : OMP_CLAUSE_CHAIN (c) = list;
17194 : 700 : OMP_CLAUSE_DEFAULT_KIND (c) = kind;
17195 : :
17196 : 700 : return c;
17197 : : }
17198 : :
17199 : : /* OpenMP 2.5:
17200 : : firstprivate ( variable-list ) */
17201 : :
17202 : : static tree
17203 : 777 : c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
17204 : : {
17205 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
17206 : : }
17207 : :
17208 : : /* OpenMP 3.1:
17209 : : final ( expression ) */
17210 : :
17211 : : static tree
17212 : 98 : c_parser_omp_clause_final (c_parser *parser, tree list)
17213 : : {
17214 : 98 : location_t loc = c_parser_peek_token (parser)->location;
17215 : 98 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
17216 : : {
17217 : 98 : matching_parens parens;
17218 : 98 : tree t, c;
17219 : 98 : if (!parens.require_open (parser))
17220 : 0 : t = error_mark_node;
17221 : : else
17222 : : {
17223 : 98 : location_t eloc = c_parser_peek_token (parser)->location;
17224 : 98 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17225 : 98 : t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
17226 : 98 : t = c_objc_common_truthvalue_conversion (eloc, t);
17227 : 98 : t = c_fully_fold (t, false, NULL);
17228 : 98 : parens.skip_until_found_close (parser);
17229 : : }
17230 : :
17231 : 98 : check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
17232 : :
17233 : 98 : c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
17234 : 98 : OMP_CLAUSE_FINAL_EXPR (c) = t;
17235 : 98 : OMP_CLAUSE_CHAIN (c) = list;
17236 : 98 : list = c;
17237 : : }
17238 : : else
17239 : 0 : c_parser_error (parser, "expected %<(%>");
17240 : :
17241 : 98 : return list;
17242 : : }
17243 : :
17244 : : /* OpenMP 5.1:
17245 : : indirect [( expression )]
17246 : : */
17247 : :
17248 : : static tree
17249 : 26 : c_parser_omp_clause_indirect (c_parser *parser, tree list)
17250 : : {
17251 : 26 : location_t location = c_parser_peek_token (parser)->location;
17252 : 26 : tree t;
17253 : :
17254 : 26 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17255 : : {
17256 : 17 : matching_parens parens;
17257 : 17 : if (!parens.require_open (parser))
17258 : 1 : return list;
17259 : :
17260 : 17 : location_t loc = c_parser_peek_token (parser)->location;
17261 : 17 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17262 : 17 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17263 : 17 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
17264 : 17 : t = c_fully_fold (t, false, NULL);
17265 : 34 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17266 : 34 : || TREE_CODE (t) != INTEGER_CST)
17267 : : {
17268 : 1 : c_parser_error (parser, "expected constant logical expression");
17269 : 1 : return list;
17270 : : }
17271 : 16 : parens.skip_until_found_close (parser);
17272 : : }
17273 : : else
17274 : 9 : t = integer_one_node;
17275 : :
17276 : 25 : check_no_duplicate_clause (list, OMP_CLAUSE_INDIRECT, "indirect");
17277 : :
17278 : 25 : tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
17279 : 25 : OMP_CLAUSE_INDIRECT_EXPR (c) = t;
17280 : 25 : OMP_CLAUSE_CHAIN (c) = list;
17281 : :
17282 : 25 : return c;
17283 : : }
17284 : :
17285 : : /* OpenACC, OpenMP 2.5:
17286 : : if ( expression )
17287 : :
17288 : : OpenMP 4.5:
17289 : : if ( directive-name-modifier : expression )
17290 : :
17291 : : directive-name-modifier:
17292 : : parallel | task | taskloop | target data | target | target update
17293 : : | target enter data | target exit data
17294 : :
17295 : : OpenMP 5.0:
17296 : : directive-name-modifier:
17297 : : ... | simd | cancel */
17298 : :
17299 : : static tree
17300 : 883 : c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
17301 : : {
17302 : 883 : location_t location = c_parser_peek_token (parser)->location;
17303 : 883 : enum tree_code if_modifier = ERROR_MARK;
17304 : :
17305 : 883 : matching_parens parens;
17306 : 883 : if (!parens.require_open (parser))
17307 : : return list;
17308 : :
17309 : 1661 : if (is_omp && c_parser_next_token_is (parser, CPP_NAME))
17310 : : {
17311 : 637 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17312 : 637 : int n = 2;
17313 : 637 : if (strcmp (p, "cancel") == 0)
17314 : : if_modifier = VOID_CST;
17315 : 622 : else if (strcmp (p, "parallel") == 0)
17316 : : if_modifier = OMP_PARALLEL;
17317 : 483 : else if (strcmp (p, "simd") == 0)
17318 : : if_modifier = OMP_SIMD;
17319 : 377 : else if (strcmp (p, "task") == 0)
17320 : : if_modifier = OMP_TASK;
17321 : 366 : else if (strcmp (p, "taskloop") == 0)
17322 : : if_modifier = OMP_TASKLOOP;
17323 : 315 : else if (strcmp (p, "target") == 0)
17324 : : {
17325 : 102 : if_modifier = OMP_TARGET;
17326 : 102 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17327 : : {
17328 : 37 : p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
17329 : 37 : if (strcmp ("data", p) == 0)
17330 : : if_modifier = OMP_TARGET_DATA;
17331 : 29 : else if (strcmp ("update", p) == 0)
17332 : : if_modifier = OMP_TARGET_UPDATE;
17333 : 18 : else if (strcmp ("enter", p) == 0)
17334 : : if_modifier = OMP_TARGET_ENTER_DATA;
17335 : 10 : else if (strcmp ("exit", p) == 0)
17336 : : if_modifier = OMP_TARGET_EXIT_DATA;
17337 : 0 : if (if_modifier != OMP_TARGET)
17338 : : {
17339 : 37 : n = 3;
17340 : 37 : c_parser_consume_token (parser);
17341 : : }
17342 : : else
17343 : : {
17344 : 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17345 : 0 : error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
17346 : : "or %<exit%>");
17347 : 0 : if_modifier = ERROR_MARK;
17348 : : }
17349 : 0 : if (if_modifier == OMP_TARGET_ENTER_DATA
17350 : 37 : || if_modifier == OMP_TARGET_EXIT_DATA)
17351 : : {
17352 : 18 : if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17353 : : {
17354 : 18 : p = IDENTIFIER_POINTER
17355 : : (c_parser_peek_2nd_token (parser)->value);
17356 : 18 : if (strcmp ("data", p) == 0)
17357 : 18 : n = 4;
17358 : : }
17359 : 18 : if (n == 4)
17360 : 18 : c_parser_consume_token (parser);
17361 : : else
17362 : : {
17363 : 0 : location_t loc
17364 : 0 : = c_parser_peek_2nd_token (parser)->location;
17365 : 0 : error_at (loc, "expected %<data%>");
17366 : 0 : if_modifier = ERROR_MARK;
17367 : : }
17368 : : }
17369 : : }
17370 : : }
17371 : 37 : if (if_modifier != ERROR_MARK)
17372 : : {
17373 : 424 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17374 : : {
17375 : 423 : c_parser_consume_token (parser);
17376 : 423 : c_parser_consume_token (parser);
17377 : : }
17378 : : else
17379 : : {
17380 : 1 : if (n > 2)
17381 : : {
17382 : 0 : location_t loc = c_parser_peek_2nd_token (parser)->location;
17383 : 0 : error_at (loc, "expected %<:%>");
17384 : : }
17385 : : if_modifier = ERROR_MARK;
17386 : : }
17387 : : }
17388 : : }
17389 : :
17390 : 883 : location_t loc = c_parser_peek_token (parser)->location;
17391 : 883 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17392 : 883 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17393 : 883 : tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
17394 : 883 : t = c_fully_fold (t, false, NULL);
17395 : 883 : parens.skip_until_found_close (parser);
17396 : :
17397 : 3979 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17398 : 3136 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
17399 : : {
17400 : 174 : if (if_modifier != ERROR_MARK
17401 : 174 : && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17402 : : {
17403 : 9 : const char *p = NULL;
17404 : 9 : switch (if_modifier)
17405 : : {
17406 : : case VOID_CST: p = "cancel"; break;
17407 : 1 : case OMP_PARALLEL: p = "parallel"; break;
17408 : 0 : case OMP_SIMD: p = "simd"; break;
17409 : 1 : case OMP_TASK: p = "task"; break;
17410 : 1 : case OMP_TASKLOOP: p = "taskloop"; break;
17411 : 1 : case OMP_TARGET_DATA: p = "target data"; break;
17412 : 1 : case OMP_TARGET: p = "target"; break;
17413 : 1 : case OMP_TARGET_UPDATE: p = "target update"; break;
17414 : 1 : case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
17415 : 1 : case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
17416 : 0 : default: gcc_unreachable ();
17417 : : }
17418 : 9 : error_at (location, "too many %<if%> clauses with %qs modifier",
17419 : : p);
17420 : 9 : return list;
17421 : : }
17422 : 165 : else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17423 : : {
17424 : 13 : if (!is_omp)
17425 : 1 : error_at (location, "too many %<if%> clauses");
17426 : : else
17427 : 12 : error_at (location, "too many %<if%> clauses without modifier");
17428 : 13 : return list;
17429 : : }
17430 : 152 : else if (if_modifier == ERROR_MARK
17431 : 152 : || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
17432 : : {
17433 : 18 : error_at (location, "if any %<if%> clause has modifier, then all "
17434 : : "%<if%> clauses have to use modifier");
17435 : 18 : return list;
17436 : : }
17437 : : }
17438 : :
17439 : 843 : c = build_omp_clause (location, OMP_CLAUSE_IF);
17440 : 843 : OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
17441 : 843 : OMP_CLAUSE_IF_EXPR (c) = t;
17442 : 843 : OMP_CLAUSE_CHAIN (c) = list;
17443 : 843 : return c;
17444 : : }
17445 : :
17446 : : /* OpenMP 2.5:
17447 : : lastprivate ( variable-list )
17448 : :
17449 : : OpenMP 5.0:
17450 : : lastprivate ( [ lastprivate-modifier : ] variable-list ) */
17451 : :
17452 : : static tree
17453 : 731 : c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
17454 : : {
17455 : : /* The clauses location. */
17456 : 731 : location_t loc = c_parser_peek_token (parser)->location;
17457 : :
17458 : 731 : if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
17459 : : {
17460 : 731 : bool conditional = false;
17461 : 731 : if (c_parser_next_token_is (parser, CPP_NAME)
17462 : 731 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17463 : : {
17464 : 107 : const char *p
17465 : 107 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17466 : 107 : if (strcmp (p, "conditional") == 0)
17467 : : {
17468 : 107 : conditional = true;
17469 : 107 : c_parser_consume_token (parser);
17470 : 107 : c_parser_consume_token (parser);
17471 : : }
17472 : : }
17473 : 731 : tree nlist = c_parser_omp_variable_list (parser, loc,
17474 : : OMP_CLAUSE_LASTPRIVATE, list);
17475 : 731 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
17476 : 731 : if (conditional)
17477 : 246 : for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
17478 : 139 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
17479 : 731 : return nlist;
17480 : : }
17481 : : return list;
17482 : : }
17483 : :
17484 : : /* OpenMP 3.1:
17485 : : mergeable */
17486 : :
17487 : : static tree
17488 : 78 : c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17489 : : {
17490 : 78 : tree c;
17491 : :
17492 : : /* FIXME: Should we allow duplicates? */
17493 : 78 : check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
17494 : :
17495 : 78 : c = build_omp_clause (c_parser_peek_token (parser)->location,
17496 : : OMP_CLAUSE_MERGEABLE);
17497 : 78 : OMP_CLAUSE_CHAIN (c) = list;
17498 : :
17499 : 78 : return c;
17500 : : }
17501 : :
17502 : : /* OpenMP 2.5:
17503 : : nowait */
17504 : :
17505 : : static tree
17506 : 391 : c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17507 : : {
17508 : 391 : tree c;
17509 : 391 : location_t loc = c_parser_peek_token (parser)->location;
17510 : :
17511 : 391 : check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
17512 : :
17513 : 391 : c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
17514 : 391 : OMP_CLAUSE_CHAIN (c) = list;
17515 : 391 : return c;
17516 : : }
17517 : :
17518 : : /* OpenMP 2.5:
17519 : : num_threads ( expression ) */
17520 : :
17521 : : static tree
17522 : 424 : c_parser_omp_clause_num_threads (c_parser *parser, tree list)
17523 : : {
17524 : 424 : location_t num_threads_loc = c_parser_peek_token (parser)->location;
17525 : 424 : matching_parens parens;
17526 : 424 : if (parens.require_open (parser))
17527 : : {
17528 : 424 : location_t expr_loc = c_parser_peek_token (parser)->location;
17529 : 424 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17530 : 424 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17531 : 424 : tree c, t = expr.value;
17532 : 424 : t = c_fully_fold (t, false, NULL);
17533 : :
17534 : 424 : parens.skip_until_found_close (parser);
17535 : :
17536 : 424 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17537 : : {
17538 : 0 : c_parser_error (parser, "expected integer expression");
17539 : 0 : return list;
17540 : : }
17541 : :
17542 : : /* Attempt to statically determine when the number isn't positive. */
17543 : 424 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17544 : 424 : build_int_cst (TREE_TYPE (t), 0));
17545 : 424 : protected_set_expr_location (c, expr_loc);
17546 : 424 : if (c == boolean_true_node)
17547 : : {
17548 : 1 : warning_at (expr_loc, OPT_Wopenmp,
17549 : : "%<num_threads%> value must be positive");
17550 : 1 : t = integer_one_node;
17551 : : }
17552 : :
17553 : 424 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
17554 : :
17555 : 424 : c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
17556 : 424 : OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
17557 : 424 : OMP_CLAUSE_CHAIN (c) = list;
17558 : 424 : list = c;
17559 : : }
17560 : :
17561 : : return list;
17562 : : }
17563 : :
17564 : : /* OpenMP 4.5:
17565 : : num_tasks ( expression )
17566 : :
17567 : : OpenMP 5.1:
17568 : : num_tasks ( strict : expression ) */
17569 : :
17570 : : static tree
17571 : 49 : c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
17572 : : {
17573 : 49 : location_t num_tasks_loc = c_parser_peek_token (parser)->location;
17574 : 49 : matching_parens parens;
17575 : 49 : if (parens.require_open (parser))
17576 : : {
17577 : 49 : bool strict = false;
17578 : 49 : if (c_parser_next_token_is (parser, CPP_NAME)
17579 : 39 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17580 : 50 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17581 : : "strict") == 0)
17582 : : {
17583 : 1 : strict = true;
17584 : 1 : c_parser_consume_token (parser);
17585 : 1 : c_parser_consume_token (parser);
17586 : : }
17587 : :
17588 : 49 : location_t expr_loc = c_parser_peek_token (parser)->location;
17589 : 49 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17590 : 49 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17591 : 49 : tree c, t = expr.value;
17592 : 49 : t = c_fully_fold (t, false, NULL);
17593 : :
17594 : 49 : parens.skip_until_found_close (parser);
17595 : :
17596 : 49 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17597 : : {
17598 : 0 : c_parser_error (parser, "expected integer expression");
17599 : 0 : return list;
17600 : : }
17601 : :
17602 : : /* Attempt to statically determine when the number isn't positive. */
17603 : 49 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17604 : 49 : build_int_cst (TREE_TYPE (t), 0));
17605 : 49 : if (CAN_HAVE_LOCATION_P (c))
17606 : 39 : SET_EXPR_LOCATION (c, expr_loc);
17607 : 49 : if (c == boolean_true_node)
17608 : : {
17609 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17610 : : "%<num_tasks%> value must be positive");
17611 : 0 : t = integer_one_node;
17612 : : }
17613 : :
17614 : 49 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks");
17615 : :
17616 : 49 : c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
17617 : 49 : OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
17618 : 49 : OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
17619 : 49 : OMP_CLAUSE_CHAIN (c) = list;
17620 : 49 : list = c;
17621 : : }
17622 : :
17623 : : return list;
17624 : : }
17625 : :
17626 : : /* OpenMP 4.5:
17627 : : grainsize ( expression )
17628 : :
17629 : : OpenMP 5.1:
17630 : : grainsize ( strict : expression ) */
17631 : :
17632 : : static tree
17633 : 62 : c_parser_omp_clause_grainsize (c_parser *parser, tree list)
17634 : : {
17635 : 62 : location_t grainsize_loc = c_parser_peek_token (parser)->location;
17636 : 62 : matching_parens parens;
17637 : 62 : if (parens.require_open (parser))
17638 : : {
17639 : 62 : bool strict = false;
17640 : 62 : if (c_parser_next_token_is (parser, CPP_NAME)
17641 : 47 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17642 : 63 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17643 : : "strict") == 0)
17644 : : {
17645 : 1 : strict = true;
17646 : 1 : c_parser_consume_token (parser);
17647 : 1 : c_parser_consume_token (parser);
17648 : : }
17649 : :
17650 : 62 : location_t expr_loc = c_parser_peek_token (parser)->location;
17651 : 62 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17652 : 62 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17653 : 62 : tree c, t = expr.value;
17654 : 62 : t = c_fully_fold (t, false, NULL);
17655 : :
17656 : 62 : parens.skip_until_found_close (parser);
17657 : :
17658 : 62 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17659 : : {
17660 : 0 : c_parser_error (parser, "expected integer expression");
17661 : 0 : return list;
17662 : : }
17663 : :
17664 : : /* Attempt to statically determine when the number isn't positive. */
17665 : 62 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17666 : 62 : build_int_cst (TREE_TYPE (t), 0));
17667 : 62 : if (CAN_HAVE_LOCATION_P (c))
17668 : 47 : SET_EXPR_LOCATION (c, expr_loc);
17669 : 62 : if (c == boolean_true_node)
17670 : : {
17671 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17672 : : "%<grainsize%> value must be positive");
17673 : 0 : t = integer_one_node;
17674 : : }
17675 : :
17676 : 62 : check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize");
17677 : :
17678 : 62 : c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
17679 : 62 : OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
17680 : 62 : OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
17681 : 62 : OMP_CLAUSE_CHAIN (c) = list;
17682 : 62 : list = c;
17683 : : }
17684 : :
17685 : : return list;
17686 : : }
17687 : :
17688 : : /* OpenMP 4.5:
17689 : : priority ( expression ) */
17690 : :
17691 : : static tree
17692 : 97 : c_parser_omp_clause_priority (c_parser *parser, tree list)
17693 : : {
17694 : 97 : location_t priority_loc = c_parser_peek_token (parser)->location;
17695 : 97 : matching_parens parens;
17696 : 97 : if (parens.require_open (parser))
17697 : : {
17698 : 97 : location_t expr_loc = c_parser_peek_token (parser)->location;
17699 : 97 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17700 : 97 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17701 : 97 : tree c, t = expr.value;
17702 : 97 : t = c_fully_fold (t, false, NULL);
17703 : :
17704 : 97 : parens.skip_until_found_close (parser);
17705 : :
17706 : 97 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17707 : : {
17708 : 0 : c_parser_error (parser, "expected integer expression");
17709 : 0 : return list;
17710 : : }
17711 : :
17712 : : /* Attempt to statically determine when the number isn't
17713 : : non-negative. */
17714 : 97 : c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
17715 : 97 : build_int_cst (TREE_TYPE (t), 0));
17716 : 97 : if (CAN_HAVE_LOCATION_P (c))
17717 : 86 : SET_EXPR_LOCATION (c, expr_loc);
17718 : 97 : if (c == boolean_true_node)
17719 : : {
17720 : 0 : warning_at (expr_loc, OPT_Wopenmp,
17721 : : "%<priority%> value must be non-negative");
17722 : 0 : t = integer_one_node;
17723 : : }
17724 : :
17725 : 97 : check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority");
17726 : :
17727 : 97 : c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
17728 : 97 : OMP_CLAUSE_PRIORITY_EXPR (c) = t;
17729 : 97 : OMP_CLAUSE_CHAIN (c) = list;
17730 : 97 : list = c;
17731 : : }
17732 : :
17733 : : return list;
17734 : : }
17735 : :
17736 : : /* OpenMP 4.5:
17737 : : hint ( expression ) */
17738 : :
17739 : : static tree
17740 : 58 : c_parser_omp_clause_hint (c_parser *parser, tree list)
17741 : : {
17742 : 58 : location_t hint_loc = c_parser_peek_token (parser)->location;
17743 : 58 : matching_parens parens;
17744 : 58 : if (parens.require_open (parser))
17745 : : {
17746 : 58 : location_t expr_loc = c_parser_peek_token (parser)->location;
17747 : 58 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17748 : 58 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17749 : 58 : tree c, t = expr.value;
17750 : 58 : t = c_fully_fold (t, false, NULL);
17751 : 116 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17752 : 57 : || TREE_CODE (t) != INTEGER_CST
17753 : 111 : || tree_int_cst_sgn (t) == -1)
17754 : : {
17755 : 6 : c_parser_error (parser, "expected constant integer expression "
17756 : : "with valid sync-hint value");
17757 : 6 : return list;
17758 : : }
17759 : 52 : parens.skip_until_found_close (parser);
17760 : 52 : check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
17761 : :
17762 : 52 : c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
17763 : 52 : OMP_CLAUSE_HINT_EXPR (c) = t;
17764 : 52 : OMP_CLAUSE_CHAIN (c) = list;
17765 : 52 : list = c;
17766 : : }
17767 : :
17768 : : return list;
17769 : : }
17770 : :
17771 : : /* OpenMP 5.1:
17772 : : filter ( integer-expression ) */
17773 : :
17774 : : static tree
17775 : 62 : c_parser_omp_clause_filter (c_parser *parser, tree list)
17776 : : {
17777 : 62 : location_t hint_loc = c_parser_peek_token (parser)->location;
17778 : 62 : matching_parens parens;
17779 : 62 : if (parens.require_open (parser))
17780 : : {
17781 : 62 : location_t expr_loc = c_parser_peek_token (parser)->location;
17782 : 62 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
17783 : 62 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17784 : 62 : tree c, t = expr.value;
17785 : 62 : t = c_fully_fold (t, false, NULL);
17786 : 62 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17787 : : {
17788 : 2 : c_parser_error (parser, "expected integer expression");
17789 : 2 : return list;
17790 : : }
17791 : 60 : parens.skip_until_found_close (parser);
17792 : 60 : check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
17793 : :
17794 : 60 : c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
17795 : 60 : OMP_CLAUSE_FILTER_EXPR (c) = t;
17796 : 60 : OMP_CLAUSE_CHAIN (c) = list;
17797 : 60 : list = c;
17798 : : }
17799 : :
17800 : : return list;
17801 : : }
17802 : :
17803 : : /* OpenMP 4.5:
17804 : : defaultmap ( tofrom : scalar )
17805 : :
17806 : : OpenMP 5.0:
17807 : : defaultmap ( implicit-behavior [ : variable-category ] ) */
17808 : :
17809 : : static tree
17810 : 239 : c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
17811 : : {
17812 : 239 : location_t loc = c_parser_peek_token (parser)->location;
17813 : 239 : tree c;
17814 : 239 : const char *p;
17815 : 239 : enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17816 : 239 : enum omp_clause_defaultmap_kind category
17817 : : = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
17818 : :
17819 : 239 : matching_parens parens;
17820 : 239 : if (!parens.require_open (parser))
17821 : : return list;
17822 : 239 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
17823 : : p = "default";
17824 : 231 : else if (!c_parser_next_token_is (parser, CPP_NAME))
17825 : : {
17826 : 2 : invalid_behavior:
17827 : 3 : c_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
17828 : : "%<tofrom%>, %<firstprivate%>, %<none%> "
17829 : : "or %<default%>");
17830 : 3 : goto out_err;
17831 : : }
17832 : : else
17833 : 229 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17834 : :
17835 : 237 : switch (p[0])
17836 : : {
17837 : 7 : case 'a':
17838 : 7 : if (strcmp ("alloc", p) == 0)
17839 : : behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
17840 : : else
17841 : 0 : goto invalid_behavior;
17842 : : break;
17843 : :
17844 : 8 : case 'd':
17845 : 8 : if (strcmp ("default", p) == 0)
17846 : : behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17847 : : else
17848 : 0 : goto invalid_behavior;
17849 : : break;
17850 : :
17851 : 27 : case 'f':
17852 : 27 : if (strcmp ("firstprivate", p) == 0)
17853 : : behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
17854 : 3 : else if (strcmp ("from", p) == 0)
17855 : : behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
17856 : : else
17857 : 0 : goto invalid_behavior;
17858 : : break;
17859 : :
17860 : 101 : case 'n':
17861 : 101 : if (strcmp ("none", p) == 0)
17862 : : behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
17863 : : else
17864 : 0 : goto invalid_behavior;
17865 : : break;
17866 : :
17867 : 4 : case 'p':
17868 : 4 : if (strcmp ("present", p) == 0)
17869 : : behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
17870 : : else
17871 : 0 : goto invalid_behavior;
17872 : : break;
17873 : :
17874 : 89 : case 't':
17875 : 89 : if (strcmp ("tofrom", p) == 0)
17876 : : behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
17877 : 4 : else if (strcmp ("to", p) == 0)
17878 : : behavior = OMP_CLAUSE_DEFAULTMAP_TO;
17879 : : else
17880 : 0 : goto invalid_behavior;
17881 : : break;
17882 : :
17883 : 1 : default:
17884 : 1 : goto invalid_behavior;
17885 : : }
17886 : 236 : c_parser_consume_token (parser);
17887 : :
17888 : 236 : if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
17889 : : {
17890 : 132 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
17891 : 3 : goto out_err;
17892 : 129 : if (!c_parser_next_token_is (parser, CPP_NAME))
17893 : : {
17894 : 1 : invalid_category:
17895 : 2 : c_parser_error (parser, "expected %<scalar%>, %<aggregate%>, "
17896 : : "%<pointer%> or %<all%>");
17897 : 2 : goto out_err;
17898 : : }
17899 : 128 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17900 : 128 : switch (p[0])
17901 : : {
17902 : 22 : case 'a':
17903 : 22 : if (strcmp ("aggregate", p) == 0)
17904 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
17905 : 8 : else if (strcmp ("all", p) == 0)
17906 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
17907 : : else
17908 : 0 : goto invalid_category;
17909 : : break;
17910 : :
17911 : 15 : case 'p':
17912 : 15 : if (strcmp ("pointer", p) == 0)
17913 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
17914 : : else
17915 : 0 : goto invalid_category;
17916 : : break;
17917 : :
17918 : 90 : case 's':
17919 : 90 : if (strcmp ("scalar", p) == 0)
17920 : : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
17921 : : else
17922 : 0 : goto invalid_category;
17923 : : break;
17924 : :
17925 : 1 : default:
17926 : 1 : goto invalid_category;
17927 : : }
17928 : :
17929 : 127 : c_parser_consume_token (parser);
17930 : : }
17931 : 231 : parens.skip_until_found_close (parser);
17932 : :
17933 : 961 : for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17934 : 512 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
17935 : 512 : && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17936 : : || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17937 : 32 : || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
17938 : 31 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17939 : : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
17940 : 29 : || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17941 : : == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
17942 : : {
17943 : 13 : enum omp_clause_defaultmap_kind cat = category;
17944 : 13 : location_t loc = OMP_CLAUSE_LOCATION (c);
17945 : 13 : if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17946 : 13 : || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17947 : 3 : && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17948 : : != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
17949 : 8 : cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
17950 : 13 : p = NULL;
17951 : 13 : switch (cat)
17952 : : {
17953 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
17954 : : p = NULL;
17955 : : break;
17956 : 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
17957 : 3 : p = "all";
17958 : 3 : break;
17959 : 2 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
17960 : 2 : p = "aggregate";
17961 : 2 : break;
17962 : 3 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
17963 : 3 : p = "pointer";
17964 : 3 : break;
17965 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
17966 : : p = "scalar";
17967 : : break;
17968 : 0 : default:
17969 : 0 : gcc_unreachable ();
17970 : : }
17971 : 8 : if (p)
17972 : 10 : error_at (loc, "too many %<defaultmap%> clauses with %qs category",
17973 : : p);
17974 : : else
17975 : 3 : error_at (loc, "too many %<defaultmap%> clauses with unspecified "
17976 : : "category");
17977 : : break;
17978 : : }
17979 : :
17980 : 231 : c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
17981 : 231 : OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
17982 : 231 : OMP_CLAUSE_CHAIN (c) = list;
17983 : 231 : return c;
17984 : :
17985 : 8 : out_err:
17986 : 8 : parens.skip_until_found_close (parser);
17987 : 8 : return list;
17988 : : }
17989 : :
17990 : : /* OpenACC 2.0:
17991 : : use_device ( variable-list )
17992 : :
17993 : : OpenMP 4.5:
17994 : : use_device_ptr ( variable-list ) */
17995 : :
17996 : : static tree
17997 : 31 : c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
17998 : : {
17999 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_PTR,
18000 : 0 : list);
18001 : : }
18002 : :
18003 : : /* OpenMP 5.0:
18004 : : use_device_addr ( variable-list ) */
18005 : :
18006 : : static tree
18007 : 35 : c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
18008 : : {
18009 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_ADDR,
18010 : 0 : list);
18011 : : }
18012 : :
18013 : : /* OpenMP 5.1:
18014 : : has_device_addr ( variable-list ) */
18015 : :
18016 : : static tree
18017 : 87 : c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
18018 : : {
18019 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_HAS_DEVICE_ADDR,
18020 : 0 : list);
18021 : : }
18022 : :
18023 : : /* OpenMP 4.5:
18024 : : is_device_ptr ( variable-list ) */
18025 : :
18026 : : static tree
18027 : 114 : c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
18028 : : {
18029 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_IS_DEVICE_PTR, list);
18030 : : }
18031 : :
18032 : : /* OpenACC:
18033 : : num_gangs ( expression )
18034 : : num_workers ( expression )
18035 : : vector_length ( expression ) */
18036 : :
18037 : : static tree
18038 : 732 : c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
18039 : : tree list)
18040 : : {
18041 : 732 : location_t loc = c_parser_peek_token (parser)->location;
18042 : :
18043 : 732 : matching_parens parens;
18044 : 732 : if (!parens.require_open (parser))
18045 : : return list;
18046 : :
18047 : 726 : location_t expr_loc = c_parser_peek_token (parser)->location;
18048 : 726 : c_expr expr = c_parser_expression (parser);
18049 : 726 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18050 : 726 : tree c, t = expr.value;
18051 : 726 : t = c_fully_fold (t, false, NULL);
18052 : :
18053 : 726 : parens.skip_until_found_close (parser);
18054 : :
18055 : 726 : if (t == error_mark_node)
18056 : : return list;
18057 : 702 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18058 : : {
18059 : 16 : error_at (expr_loc, "%qs expression must be integral",
18060 : 16 : omp_clause_code_name[code]);
18061 : 16 : return list;
18062 : : }
18063 : :
18064 : : /* Attempt to statically determine when the number isn't positive. */
18065 : 686 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
18066 : 686 : build_int_cst (TREE_TYPE (t), 0));
18067 : 686 : protected_set_expr_location (c, expr_loc);
18068 : 686 : if (c == boolean_true_node)
18069 : : {
18070 : 36 : warning_at (expr_loc, 0,
18071 : : "%qs value must be positive",
18072 : 18 : omp_clause_code_name[code]);
18073 : 18 : t = integer_one_node;
18074 : : }
18075 : :
18076 : 686 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18077 : :
18078 : 686 : c = build_omp_clause (loc, code);
18079 : 686 : OMP_CLAUSE_OPERAND (c, 0) = t;
18080 : 686 : OMP_CLAUSE_CHAIN (c) = list;
18081 : 686 : return c;
18082 : : }
18083 : :
18084 : : /* OpenACC:
18085 : :
18086 : : gang [( gang-arg-list )]
18087 : : worker [( [num:] int-expr )]
18088 : : vector [( [length:] int-expr )]
18089 : :
18090 : : where gang-arg is one of:
18091 : :
18092 : : [num:] int-expr
18093 : : static: size-expr
18094 : :
18095 : : and size-expr may be:
18096 : :
18097 : : *
18098 : : int-expr
18099 : : */
18100 : :
18101 : : static tree
18102 : 1560 : c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
18103 : : omp_clause_code kind,
18104 : : const char *str, tree list)
18105 : : {
18106 : 1560 : const char *id = "num";
18107 : 1560 : tree ops[2] = { NULL_TREE, NULL_TREE }, c;
18108 : :
18109 : 1560 : if (kind == OMP_CLAUSE_VECTOR)
18110 : 518 : id = "length";
18111 : :
18112 : 1560 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18113 : : {
18114 : 246 : c_parser_consume_token (parser);
18115 : :
18116 : 276 : do
18117 : : {
18118 : 261 : c_token *next = c_parser_peek_token (parser);
18119 : 261 : int idx = 0;
18120 : :
18121 : : /* Gang static argument. */
18122 : 261 : if (kind == OMP_CLAUSE_GANG
18123 : 403 : && c_parser_next_token_is_keyword (parser, RID_STATIC))
18124 : : {
18125 : 70 : c_parser_consume_token (parser);
18126 : :
18127 : 70 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18128 : 12 : goto cleanup_error;
18129 : :
18130 : 70 : idx = 1;
18131 : 70 : if (ops[idx] != NULL_TREE)
18132 : : {
18133 : 0 : c_parser_error (parser, "too many %<static%> arguments");
18134 : 0 : goto cleanup_error;
18135 : : }
18136 : :
18137 : : /* Check for the '*' argument. */
18138 : 70 : if (c_parser_next_token_is (parser, CPP_MULT)
18139 : 70 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18140 : 30 : || c_parser_peek_2nd_token (parser)->type
18141 : : == CPP_CLOSE_PAREN))
18142 : : {
18143 : 29 : c_parser_consume_token (parser);
18144 : 29 : ops[idx] = integer_minus_one_node;
18145 : :
18146 : 29 : if (c_parser_next_token_is (parser, CPP_COMMA))
18147 : : {
18148 : 1 : c_parser_consume_token (parser);
18149 : 1 : continue;
18150 : : }
18151 : : else
18152 : : break;
18153 : : }
18154 : : }
18155 : : /* Worker num: argument and vector length: arguments. */
18156 : 191 : else if (c_parser_next_token_is (parser, CPP_NAME)
18157 : 149 : && strcmp (id, IDENTIFIER_POINTER (next->value)) == 0
18158 : 324 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18159 : : {
18160 : 127 : c_parser_consume_token (parser); /* id */
18161 : 127 : c_parser_consume_token (parser); /* ':' */
18162 : : }
18163 : :
18164 : : /* Now collect the actual argument. */
18165 : 232 : if (ops[idx] != NULL_TREE)
18166 : : {
18167 : 5 : c_parser_error (parser, "unexpected argument");
18168 : 5 : goto cleanup_error;
18169 : : }
18170 : :
18171 : 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
18172 : 227 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18173 : 227 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18174 : 227 : tree expr = cexpr.value;
18175 : 227 : if (expr == error_mark_node)
18176 : 7 : goto cleanup_error;
18177 : :
18178 : 220 : expr = c_fully_fold (expr, false, NULL);
18179 : :
18180 : : /* Attempt to statically determine when the number isn't a
18181 : : positive integer. */
18182 : :
18183 : 220 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
18184 : : {
18185 : 14 : c_parser_error (parser, "expected integer expression");
18186 : 14 : return list;
18187 : : }
18188 : :
18189 : 206 : tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
18190 : 206 : build_int_cst (TREE_TYPE (expr), 0));
18191 : 206 : if (c == boolean_true_node)
18192 : : {
18193 : 1 : warning_at (loc, 0,
18194 : : "%qs value must be positive", str);
18195 : 1 : expr = integer_one_node;
18196 : : }
18197 : :
18198 : 206 : ops[idx] = expr;
18199 : :
18200 : 220 : if (kind == OMP_CLAUSE_GANG
18201 : 305 : && c_parser_next_token_is (parser, CPP_COMMA))
18202 : : {
18203 : 14 : c_parser_consume_token (parser);
18204 : 14 : continue;
18205 : : }
18206 : : break;
18207 : 15 : }
18208 : : while (1);
18209 : :
18210 : 220 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18211 : 7 : goto cleanup_error;
18212 : : }
18213 : :
18214 : 1527 : check_no_duplicate_clause (list, kind, str);
18215 : :
18216 : 1527 : c = build_omp_clause (loc, kind);
18217 : :
18218 : 1527 : if (ops[1])
18219 : 67 : OMP_CLAUSE_OPERAND (c, 1) = ops[1];
18220 : :
18221 : 1527 : OMP_CLAUSE_OPERAND (c, 0) = ops[0];
18222 : 1527 : OMP_CLAUSE_CHAIN (c) = list;
18223 : :
18224 : 1527 : return c;
18225 : :
18226 : 19 : cleanup_error:
18227 : 19 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18228 : 19 : return list;
18229 : : }
18230 : :
18231 : : /* OpenACC 2.5:
18232 : : auto
18233 : : finalize
18234 : : independent
18235 : : nohost
18236 : : seq */
18237 : :
18238 : : static tree
18239 : 487 : c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
18240 : : tree list)
18241 : : {
18242 : 487 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18243 : :
18244 : 487 : tree c = build_omp_clause (loc, code);
18245 : 487 : OMP_CLAUSE_CHAIN (c) = list;
18246 : :
18247 : 487 : return c;
18248 : : }
18249 : :
18250 : : /* OpenACC:
18251 : : async [( int-expr )] */
18252 : :
18253 : : static tree
18254 : 240 : c_parser_oacc_clause_async (c_parser *parser, tree list)
18255 : : {
18256 : 240 : tree c, t;
18257 : 240 : location_t loc = c_parser_peek_token (parser)->location;
18258 : :
18259 : 240 : t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18260 : :
18261 : 240 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18262 : : {
18263 : 187 : c_parser_consume_token (parser);
18264 : :
18265 : 187 : t = c_parser_expr_no_commas (parser, NULL).value;
18266 : 187 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18267 : 9 : c_parser_error (parser, "expected integer expression");
18268 : 178 : else if (t == error_mark_node
18269 : 178 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
18270 : 14 : return list;
18271 : : }
18272 : : else
18273 : 53 : t = c_fully_fold (t, false, NULL);
18274 : :
18275 : 226 : check_no_duplicate_clause (list, OMP_CLAUSE_ASYNC, "async");
18276 : :
18277 : 226 : c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
18278 : 226 : OMP_CLAUSE_ASYNC_EXPR (c) = t;
18279 : 226 : OMP_CLAUSE_CHAIN (c) = list;
18280 : 226 : list = c;
18281 : :
18282 : 226 : return list;
18283 : : }
18284 : :
18285 : : /* OpenACC 2.0:
18286 : : tile ( size-expr-list ) */
18287 : :
18288 : : static tree
18289 : 123 : c_parser_oacc_clause_tile (c_parser *parser, tree list)
18290 : : {
18291 : 123 : tree c, expr = error_mark_node;
18292 : 123 : location_t loc;
18293 : 123 : tree tile = NULL_TREE;
18294 : :
18295 : 123 : check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
18296 : 123 : check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
18297 : :
18298 : 123 : loc = c_parser_peek_token (parser)->location;
18299 : 123 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
18300 : : return list;
18301 : :
18302 : 163 : do
18303 : : {
18304 : 163 : if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
18305 : : return list;
18306 : :
18307 : 163 : if (c_parser_next_token_is (parser, CPP_MULT)
18308 : 163 : && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18309 : 53 : || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
18310 : : {
18311 : 60 : c_parser_consume_token (parser);
18312 : 60 : expr = integer_zero_node;
18313 : : }
18314 : : else
18315 : : {
18316 : 103 : location_t expr_loc = c_parser_peek_token (parser)->location;
18317 : 103 : c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18318 : 103 : cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18319 : 103 : expr = cexpr.value;
18320 : :
18321 : 103 : if (expr == error_mark_node)
18322 : : {
18323 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
18324 : : "expected %<)%>");
18325 : 7 : return list;
18326 : : }
18327 : :
18328 : 96 : expr = c_fully_fold (expr, false, NULL);
18329 : :
18330 : 192 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
18331 : 95 : || !tree_fits_shwi_p (expr)
18332 : 183 : || tree_to_shwi (expr) <= 0)
18333 : : {
18334 : 16 : error_at (expr_loc, "%<tile%> argument needs positive"
18335 : : " integral constant");
18336 : 16 : expr = integer_zero_node;
18337 : : }
18338 : : }
18339 : :
18340 : 156 : tile = tree_cons (NULL_TREE, expr, tile);
18341 : : }
18342 : 156 : while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
18343 : :
18344 : : /* Consume the trailing ')'. */
18345 : 111 : c_parser_consume_token (parser);
18346 : :
18347 : 111 : c = build_omp_clause (loc, OMP_CLAUSE_TILE);
18348 : 111 : tile = nreverse (tile);
18349 : 111 : OMP_CLAUSE_TILE_LIST (c) = tile;
18350 : 111 : OMP_CLAUSE_CHAIN (c) = list;
18351 : 111 : return c;
18352 : : }
18353 : :
18354 : : /* OpenACC:
18355 : : wait [( int-expr-list )] */
18356 : :
18357 : : static tree
18358 : 89 : c_parser_oacc_clause_wait (c_parser *parser, tree list)
18359 : : {
18360 : 89 : location_t clause_loc = c_parser_peek_token (parser)->location;
18361 : :
18362 : 89 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18363 : 74 : list = c_parser_oacc_wait_list (parser, clause_loc, list);
18364 : : else
18365 : : {
18366 : 15 : tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
18367 : :
18368 : 15 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18369 : 15 : OMP_CLAUSE_CHAIN (c) = list;
18370 : 15 : list = c;
18371 : : }
18372 : :
18373 : 89 : return list;
18374 : : }
18375 : :
18376 : : /* OpenACC 2.7:
18377 : : self [( expression )] */
18378 : :
18379 : : static tree
18380 : 48 : c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
18381 : : {
18382 : 48 : tree t;
18383 : 48 : location_t location = c_parser_peek_token (parser)->location;
18384 : 48 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18385 : : {
18386 : 42 : matching_parens parens;
18387 : 42 : parens.consume_open (parser);
18388 : :
18389 : 42 : location_t loc = c_parser_peek_token (parser)->location;
18390 : 42 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18391 : 42 : expr = convert_lvalue_to_rvalue (loc, expr, true, true);
18392 : 42 : t = c_objc_common_truthvalue_conversion (loc, expr.value);
18393 : 42 : t = c_fully_fold (t, false, NULL);
18394 : 42 : parens.skip_until_found_close (parser);
18395 : : }
18396 : : else
18397 : 6 : t = truthvalue_true_node;
18398 : :
18399 : 78 : for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
18400 : 36 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
18401 : : {
18402 : 6 : error_at (location, "too many %<self%> clauses");
18403 : 6 : return list;
18404 : : }
18405 : :
18406 : 42 : tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
18407 : 42 : OMP_CLAUSE_SELF_EXPR (c) = t;
18408 : 42 : OMP_CLAUSE_CHAIN (c) = list;
18409 : 42 : return c;
18410 : : }
18411 : :
18412 : : /* OpenMP 5.0:
18413 : : order ( concurrent )
18414 : :
18415 : : OpenMP 5.1:
18416 : : order ( order-modifier : concurrent )
18417 : :
18418 : : order-modifier:
18419 : : reproducible
18420 : : unconstrained */
18421 : :
18422 : : static tree
18423 : 375 : c_parser_omp_clause_order (c_parser *parser, tree list)
18424 : : {
18425 : 375 : location_t loc = c_parser_peek_token (parser)->location;
18426 : 375 : tree c;
18427 : 375 : const char *p;
18428 : 375 : bool unconstrained = false;
18429 : 375 : bool reproducible = false;
18430 : :
18431 : 375 : matching_parens parens;
18432 : 375 : if (!parens.require_open (parser))
18433 : : return list;
18434 : 373 : if (c_parser_next_token_is (parser, CPP_NAME)
18435 : 373 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18436 : : {
18437 : 107 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18438 : 107 : if (strcmp (p, "unconstrained") == 0)
18439 : : unconstrained = true;
18440 : 56 : else if (strcmp (p, "reproducible") == 0)
18441 : : reproducible = true;
18442 : : else
18443 : : {
18444 : 1 : c_parser_error (parser, "expected %<reproducible%> or "
18445 : : "%<unconstrained%>");
18446 : 1 : goto out_err;
18447 : : }
18448 : 106 : c_parser_consume_token (parser);
18449 : 106 : c_parser_consume_token (parser);
18450 : : }
18451 : 372 : if (!c_parser_next_token_is (parser, CPP_NAME))
18452 : : {
18453 : 0 : c_parser_error (parser, "expected %<concurrent%>");
18454 : 0 : goto out_err;
18455 : : }
18456 : 372 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18457 : 372 : if (strcmp (p, "concurrent") != 0)
18458 : : {
18459 : 1 : c_parser_error (parser, "expected %<concurrent%>");
18460 : 1 : goto out_err;
18461 : : }
18462 : 371 : c_parser_consume_token (parser);
18463 : 371 : parens.skip_until_found_close (parser);
18464 : 371 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
18465 : 371 : c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
18466 : 371 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
18467 : 371 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
18468 : 371 : OMP_CLAUSE_CHAIN (c) = list;
18469 : 371 : return c;
18470 : :
18471 : 2 : out_err:
18472 : 2 : parens.skip_until_found_close (parser);
18473 : 2 : return list;
18474 : : }
18475 : :
18476 : :
18477 : : /* OpenMP 5.0:
18478 : : bind ( teams | parallel | thread ) */
18479 : :
18480 : : static tree
18481 : 115 : c_parser_omp_clause_bind (c_parser *parser, tree list)
18482 : : {
18483 : 115 : location_t loc = c_parser_peek_token (parser)->location;
18484 : 115 : tree c;
18485 : 115 : const char *p;
18486 : 115 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18487 : :
18488 : 115 : matching_parens parens;
18489 : 115 : if (!parens.require_open (parser))
18490 : : return list;
18491 : 113 : if (!c_parser_next_token_is (parser, CPP_NAME))
18492 : : {
18493 : 3 : invalid:
18494 : 4 : c_parser_error (parser,
18495 : : "expected %<teams%>, %<parallel%> or %<thread%>");
18496 : 4 : parens.skip_until_found_close (parser);
18497 : 4 : return list;
18498 : : }
18499 : 110 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18500 : 110 : if (strcmp (p, "teams") == 0)
18501 : : kind = OMP_CLAUSE_BIND_TEAMS;
18502 : 72 : else if (strcmp (p, "parallel") == 0)
18503 : : kind = OMP_CLAUSE_BIND_PARALLEL;
18504 : 35 : else if (strcmp (p, "thread") != 0)
18505 : 1 : goto invalid;
18506 : 109 : c_parser_consume_token (parser);
18507 : 109 : parens.skip_until_found_close (parser);
18508 : : /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
18509 : 109 : c = build_omp_clause (loc, OMP_CLAUSE_BIND);
18510 : 109 : OMP_CLAUSE_BIND_KIND (c) = kind;
18511 : 109 : OMP_CLAUSE_CHAIN (c) = list;
18512 : 109 : return c;
18513 : : }
18514 : :
18515 : :
18516 : : /* OpenMP 2.5:
18517 : : ordered
18518 : :
18519 : : OpenMP 4.5:
18520 : : ordered ( constant-expression ) */
18521 : :
18522 : : static tree
18523 : 309 : c_parser_omp_clause_ordered (c_parser *parser, tree list)
18524 : : {
18525 : 309 : check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
18526 : :
18527 : 309 : tree c, num = NULL_TREE;
18528 : 309 : HOST_WIDE_INT n;
18529 : 309 : location_t loc = c_parser_peek_token (parser)->location;
18530 : 309 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
18531 : : {
18532 : 168 : matching_parens parens;
18533 : 168 : parens.consume_open (parser);
18534 : 168 : num = c_parser_expr_no_commas (parser, NULL).value;
18535 : 168 : parens.skip_until_found_close (parser);
18536 : : }
18537 : 309 : if (num == error_mark_node)
18538 : : return list;
18539 : 309 : if (num)
18540 : : {
18541 : 168 : mark_exp_read (num);
18542 : 168 : num = c_fully_fold (num, false, NULL);
18543 : 336 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
18544 : 168 : || !tree_fits_shwi_p (num)
18545 : 168 : || (n = tree_to_shwi (num)) <= 0
18546 : 336 : || (int) n != n)
18547 : : {
18548 : 0 : error_at (loc, "ordered argument needs positive "
18549 : : "constant integer expression");
18550 : 0 : return list;
18551 : : }
18552 : : }
18553 : 309 : c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
18554 : 309 : OMP_CLAUSE_ORDERED_EXPR (c) = num;
18555 : 309 : OMP_CLAUSE_CHAIN (c) = list;
18556 : 309 : return c;
18557 : : }
18558 : :
18559 : : /* OpenMP 2.5:
18560 : : private ( variable-list ) */
18561 : :
18562 : : static tree
18563 : 735 : c_parser_omp_clause_private (c_parser *parser, tree list)
18564 : : {
18565 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
18566 : : }
18567 : :
18568 : : /* OpenMP 2.5:
18569 : : reduction ( reduction-operator : variable-list )
18570 : :
18571 : : reduction-operator:
18572 : : One of: + * - & ^ | && ||
18573 : :
18574 : : OpenMP 3.1:
18575 : :
18576 : : reduction-operator:
18577 : : One of: + * - & ^ | && || max min
18578 : :
18579 : : OpenMP 4.0:
18580 : :
18581 : : reduction-operator:
18582 : : One of: + * - & ^ | && ||
18583 : : identifier
18584 : :
18585 : : OpenMP 5.0:
18586 : : reduction ( reduction-modifier, reduction-operator : variable-list )
18587 : : in_reduction ( reduction-operator : variable-list )
18588 : : task_reduction ( reduction-operator : variable-list ) */
18589 : :
18590 : : static tree
18591 : 3089 : c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
18592 : : bool is_omp, tree list)
18593 : : {
18594 : 3089 : location_t clause_loc = c_parser_peek_token (parser)->location;
18595 : 3089 : matching_parens parens;
18596 : 3089 : if (parens.require_open (parser))
18597 : : {
18598 : 3089 : bool task = false;
18599 : 3089 : bool inscan = false;
18600 : 3089 : enum tree_code code = ERROR_MARK;
18601 : 3089 : tree reduc_id = NULL_TREE;
18602 : :
18603 : 3089 : if (kind == OMP_CLAUSE_REDUCTION && is_omp)
18604 : : {
18605 : 1778 : if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
18606 : 1778 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18607 : : {
18608 : 86 : c_parser_consume_token (parser);
18609 : 86 : c_parser_consume_token (parser);
18610 : : }
18611 : 1692 : else if (c_parser_next_token_is (parser, CPP_NAME)
18612 : 1692 : && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18613 : : {
18614 : 465 : const char *p
18615 : 465 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18616 : 465 : if (strcmp (p, "task") == 0)
18617 : : task = true;
18618 : 285 : else if (strcmp (p, "inscan") == 0)
18619 : : inscan = true;
18620 : : if (task || inscan)
18621 : : {
18622 : 465 : c_parser_consume_token (parser);
18623 : 465 : c_parser_consume_token (parser);
18624 : : }
18625 : : }
18626 : : }
18627 : :
18628 : 3089 : switch (c_parser_peek_token (parser)->type)
18629 : : {
18630 : : case CPP_PLUS:
18631 : : code = PLUS_EXPR;
18632 : : break;
18633 : 253 : case CPP_MULT:
18634 : 253 : code = MULT_EXPR;
18635 : 253 : break;
18636 : 155 : case CPP_MINUS:
18637 : 155 : code = MINUS_EXPR;
18638 : 155 : break;
18639 : 27 : case CPP_AND:
18640 : 27 : code = BIT_AND_EXPR;
18641 : 27 : break;
18642 : 14 : case CPP_XOR:
18643 : 14 : code = BIT_XOR_EXPR;
18644 : 14 : break;
18645 : 82 : case CPP_OR:
18646 : 82 : code = BIT_IOR_EXPR;
18647 : 82 : break;
18648 : 67 : case CPP_AND_AND:
18649 : 67 : code = TRUTH_ANDIF_EXPR;
18650 : 67 : break;
18651 : 78 : case CPP_OR_OR:
18652 : 78 : code = TRUTH_ORIF_EXPR;
18653 : 78 : break;
18654 : 253 : case CPP_NAME:
18655 : 253 : {
18656 : 253 : const char *p
18657 : 253 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18658 : 253 : if (strcmp (p, "min") == 0)
18659 : : {
18660 : : code = MIN_EXPR;
18661 : : break;
18662 : : }
18663 : 213 : if (strcmp (p, "max") == 0)
18664 : : {
18665 : : code = MAX_EXPR;
18666 : : break;
18667 : : }
18668 : 130 : reduc_id = c_parser_peek_token (parser)->value;
18669 : 130 : break;
18670 : : }
18671 : 0 : default:
18672 : 0 : c_parser_error (parser,
18673 : : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
18674 : : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
18675 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18676 : 0 : return list;
18677 : : }
18678 : 3089 : c_parser_consume_token (parser);
18679 : 3089 : reduc_id = c_omp_reduction_id (code, reduc_id);
18680 : 3089 : if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
18681 : : {
18682 : 3089 : tree nl, c;
18683 : :
18684 : 3089 : nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
18685 : 6791 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18686 : : {
18687 : 3702 : tree d = OMP_CLAUSE_DECL (c), type;
18688 : 3702 : if (TREE_CODE (d) != OMP_ARRAY_SECTION)
18689 : 3183 : type = TREE_TYPE (d);
18690 : : else
18691 : : {
18692 : : int cnt = 0;
18693 : : tree t;
18694 : 636 : for (t = d;
18695 : 1155 : TREE_CODE (t) == OMP_ARRAY_SECTION;
18696 : 636 : t = TREE_OPERAND (t, 0))
18697 : 636 : cnt++;
18698 : 519 : type = TREE_TYPE (t);
18699 : 1153 : while (cnt > 0)
18700 : : {
18701 : 636 : if (TREE_CODE (type) != POINTER_TYPE
18702 : 399 : && TREE_CODE (type) != ARRAY_TYPE)
18703 : : break;
18704 : 634 : type = TREE_TYPE (type);
18705 : 634 : cnt--;
18706 : : }
18707 : : }
18708 : 3795 : while (TREE_CODE (type) == ARRAY_TYPE)
18709 : 93 : type = TREE_TYPE (type);
18710 : 3702 : OMP_CLAUSE_REDUCTION_CODE (c) = code;
18711 : 3702 : if (task)
18712 : 212 : OMP_CLAUSE_REDUCTION_TASK (c) = 1;
18713 : 3490 : else if (inscan)
18714 : 400 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
18715 : 3702 : if (code == ERROR_MARK
18716 : 219 : || !(INTEGRAL_TYPE_P (type)
18717 : 3562 : || SCALAR_FLOAT_TYPE_P (type)
18718 : : || TREE_CODE (type) == COMPLEX_TYPE))
18719 : 273 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
18720 : 546 : = c_omp_reduction_lookup (reduc_id,
18721 : 273 : TYPE_MAIN_VARIANT (type));
18722 : : }
18723 : :
18724 : : list = nl;
18725 : : }
18726 : 3089 : parens.skip_until_found_close (parser);
18727 : : }
18728 : : return list;
18729 : : }
18730 : :
18731 : : /* OpenMP 2.5:
18732 : : schedule ( schedule-kind )
18733 : : schedule ( schedule-kind , expression )
18734 : :
18735 : : schedule-kind:
18736 : : static | dynamic | guided | runtime | auto
18737 : :
18738 : : OpenMP 4.5:
18739 : : schedule ( schedule-modifier : schedule-kind )
18740 : : schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
18741 : :
18742 : : schedule-modifier:
18743 : : simd
18744 : : monotonic
18745 : : nonmonotonic */
18746 : :
18747 : : static tree
18748 : 3467 : c_parser_omp_clause_schedule (c_parser *parser, tree list)
18749 : : {
18750 : 3467 : tree c, t;
18751 : 3467 : location_t loc = c_parser_peek_token (parser)->location;
18752 : 3467 : int modifiers = 0, nmodifiers = 0;
18753 : :
18754 : 3467 : matching_parens parens;
18755 : 3467 : if (!parens.require_open (parser))
18756 : : return list;
18757 : :
18758 : 3465 : c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
18759 : :
18760 : 3465 : location_t comma = UNKNOWN_LOCATION;
18761 : 6944 : while (c_parser_next_token_is (parser, CPP_NAME))
18762 : : {
18763 : 1780 : tree kind = c_parser_peek_token (parser)->value;
18764 : 1780 : const char *p = IDENTIFIER_POINTER (kind);
18765 : 1780 : if (strcmp ("simd", p) == 0)
18766 : 31 : OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
18767 : 1749 : else if (strcmp ("monotonic", p) == 0)
18768 : 74 : modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
18769 : 1675 : else if (strcmp ("nonmonotonic", p) == 0)
18770 : 84 : modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
18771 : : else
18772 : : break;
18773 : 189 : comma = UNKNOWN_LOCATION;
18774 : 189 : c_parser_consume_token (parser);
18775 : 189 : if (nmodifiers++ == 0
18776 : 367 : && c_parser_next_token_is (parser, CPP_COMMA))
18777 : : {
18778 : 14 : comma = c_parser_peek_token (parser)->location;
18779 : 14 : c_parser_consume_token (parser);
18780 : : }
18781 : : else
18782 : : {
18783 : 175 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
18784 : 175 : break;
18785 : : }
18786 : : }
18787 : 3465 : if (comma != UNKNOWN_LOCATION)
18788 : 3 : error_at (comma, "expected %<:%>");
18789 : :
18790 : 3465 : if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
18791 : : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18792 : : == (OMP_CLAUSE_SCHEDULE_MONOTONIC
18793 : : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18794 : : {
18795 : 2 : error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
18796 : : "specified");
18797 : 2 : modifiers = 0;
18798 : : }
18799 : :
18800 : 3465 : if (c_parser_next_token_is (parser, CPP_NAME))
18801 : : {
18802 : 1708 : tree kind = c_parser_peek_token (parser)->value;
18803 : 1708 : const char *p = IDENTIFIER_POINTER (kind);
18804 : :
18805 : 1708 : switch (p[0])
18806 : : {
18807 : 169 : case 'd':
18808 : 169 : if (strcmp ("dynamic", p) != 0)
18809 : 0 : goto invalid_kind;
18810 : 169 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
18811 : 169 : break;
18812 : :
18813 : 761 : case 'g':
18814 : 761 : if (strcmp ("guided", p) != 0)
18815 : 0 : goto invalid_kind;
18816 : 761 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
18817 : 761 : break;
18818 : :
18819 : 777 : case 'r':
18820 : 777 : if (strcmp ("runtime", p) != 0)
18821 : 0 : goto invalid_kind;
18822 : 777 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
18823 : 777 : break;
18824 : :
18825 : 1 : default:
18826 : 1 : goto invalid_kind;
18827 : : }
18828 : : }
18829 : 1757 : else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
18830 : 1076 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
18831 : 681 : else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
18832 : 680 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
18833 : : else
18834 : 1 : goto invalid_kind;
18835 : :
18836 : 3463 : c_parser_consume_token (parser);
18837 : 3463 : if (c_parser_next_token_is (parser, CPP_COMMA))
18838 : : {
18839 : 1795 : location_t here;
18840 : 1795 : c_parser_consume_token (parser);
18841 : :
18842 : 1795 : here = c_parser_peek_token (parser)->location;
18843 : 1795 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18844 : 1795 : expr = convert_lvalue_to_rvalue (here, expr, false, true);
18845 : 1795 : t = expr.value;
18846 : 1795 : t = c_fully_fold (t, false, NULL);
18847 : :
18848 : 1795 : if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
18849 : 1 : error_at (here, "schedule %<runtime%> does not take "
18850 : : "a %<chunk_size%> parameter");
18851 : 1794 : else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
18852 : 0 : error_at (here,
18853 : : "schedule %<auto%> does not take "
18854 : : "a %<chunk_size%> parameter");
18855 : 1794 : else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
18856 : 1794 : || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
18857 : : {
18858 : : /* Attempt to statically determine when the number isn't
18859 : : positive. */
18860 : 1793 : tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
18861 : 1793 : build_int_cst (TREE_TYPE (t), 0));
18862 : 1793 : protected_set_expr_location (s, loc);
18863 : 1793 : if (s == boolean_true_node)
18864 : : {
18865 : 2 : warning_at (loc, OPT_Wopenmp,
18866 : : "chunk size value must be positive");
18867 : 2 : t = integer_one_node;
18868 : : }
18869 : 1793 : OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
18870 : : }
18871 : : else
18872 : 1 : c_parser_error (parser, "expected integer expression");
18873 : :
18874 : 1795 : parens.skip_until_found_close (parser);
18875 : : }
18876 : : else
18877 : 1668 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
18878 : : "expected %<,%> or %<)%>");
18879 : :
18880 : 6926 : OMP_CLAUSE_SCHEDULE_KIND (c)
18881 : 6926 : = (enum omp_clause_schedule_kind)
18882 : 3463 : (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
18883 : :
18884 : 3463 : check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
18885 : 3463 : OMP_CLAUSE_CHAIN (c) = list;
18886 : 3463 : return c;
18887 : :
18888 : 2 : invalid_kind:
18889 : 2 : c_parser_error (parser, "invalid schedule kind");
18890 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
18891 : 2 : return list;
18892 : : }
18893 : :
18894 : : /* OpenMP 2.5:
18895 : : shared ( variable-list ) */
18896 : :
18897 : : static tree
18898 : 689 : c_parser_omp_clause_shared (c_parser *parser, tree list)
18899 : : {
18900 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
18901 : : }
18902 : :
18903 : : /* OpenMP 3.0:
18904 : : untied */
18905 : :
18906 : : static tree
18907 : 96 : c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18908 : : {
18909 : 96 : tree c;
18910 : :
18911 : : /* FIXME: Should we allow duplicates? */
18912 : 96 : check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
18913 : :
18914 : 96 : c = build_omp_clause (c_parser_peek_token (parser)->location,
18915 : : OMP_CLAUSE_UNTIED);
18916 : 96 : OMP_CLAUSE_CHAIN (c) = list;
18917 : :
18918 : 96 : return c;
18919 : : }
18920 : :
18921 : : /* OpenMP 4.0:
18922 : : inbranch
18923 : : notinbranch */
18924 : :
18925 : : static tree
18926 : 199 : c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
18927 : : enum omp_clause_code code, tree list)
18928 : : {
18929 : 199 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18930 : :
18931 : 199 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18932 : 199 : OMP_CLAUSE_CHAIN (c) = list;
18933 : :
18934 : 199 : return c;
18935 : : }
18936 : :
18937 : : /* OpenMP 4.0:
18938 : : parallel
18939 : : for
18940 : : sections
18941 : : taskgroup */
18942 : :
18943 : : static tree
18944 : 379 : c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
18945 : : enum omp_clause_code code, tree list)
18946 : : {
18947 : 379 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18948 : 379 : OMP_CLAUSE_CHAIN (c) = list;
18949 : :
18950 : 379 : return c;
18951 : : }
18952 : :
18953 : : /* OpenMP 4.5:
18954 : : nogroup */
18955 : :
18956 : : static tree
18957 : 18 : c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18958 : : {
18959 : 18 : check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup");
18960 : 18 : tree c = build_omp_clause (c_parser_peek_token (parser)->location,
18961 : : OMP_CLAUSE_NOGROUP);
18962 : 18 : OMP_CLAUSE_CHAIN (c) = list;
18963 : 18 : return c;
18964 : : }
18965 : :
18966 : : /* OpenMP 4.5:
18967 : : simd
18968 : : threads */
18969 : :
18970 : : static tree
18971 : 103 : c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
18972 : : enum omp_clause_code code, tree list)
18973 : : {
18974 : 103 : check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
18975 : 103 : tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18976 : 103 : OMP_CLAUSE_CHAIN (c) = list;
18977 : 103 : return c;
18978 : : }
18979 : :
18980 : : /* OpenMP 4.0:
18981 : : num_teams ( expression )
18982 : :
18983 : : OpenMP 5.1:
18984 : : num_teams ( expression : expression ) */
18985 : :
18986 : : static tree
18987 : 195 : c_parser_omp_clause_num_teams (c_parser *parser, tree list)
18988 : : {
18989 : 195 : location_t num_teams_loc = c_parser_peek_token (parser)->location;
18990 : 195 : matching_parens parens;
18991 : 195 : if (parens.require_open (parser))
18992 : : {
18993 : 195 : location_t upper_loc = c_parser_peek_token (parser)->location;
18994 : 195 : location_t lower_loc = UNKNOWN_LOCATION;
18995 : 195 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
18996 : 195 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
18997 : 195 : tree c, upper = expr.value, lower = NULL_TREE;
18998 : 195 : upper = c_fully_fold (upper, false, NULL);
18999 : :
19000 : 195 : if (c_parser_next_token_is (parser, CPP_COLON))
19001 : : {
19002 : 51 : c_parser_consume_token (parser);
19003 : 51 : lower_loc = upper_loc;
19004 : 51 : lower = upper;
19005 : 51 : upper_loc = c_parser_peek_token (parser)->location;
19006 : 51 : expr = c_parser_expr_no_commas (parser, NULL);
19007 : 51 : expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
19008 : 51 : upper = expr.value;
19009 : 51 : upper = c_fully_fold (upper, false, NULL);
19010 : : }
19011 : :
19012 : 195 : parens.skip_until_found_close (parser);
19013 : :
19014 : 390 : if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
19015 : 390 : || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
19016 : : {
19017 : 0 : c_parser_error (parser, "expected integer expression");
19018 : 0 : return list;
19019 : : }
19020 : :
19021 : : /* Attempt to statically determine when the number isn't positive. */
19022 : 195 : c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
19023 : 195 : build_int_cst (TREE_TYPE (upper), 0));
19024 : 195 : protected_set_expr_location (c, upper_loc);
19025 : 195 : if (c == boolean_true_node)
19026 : : {
19027 : 4 : warning_at (upper_loc, OPT_Wopenmp,
19028 : : "%<num_teams%> value must be positive");
19029 : 4 : upper = integer_one_node;
19030 : : }
19031 : 195 : if (lower)
19032 : : {
19033 : 51 : c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
19034 : 51 : build_int_cst (TREE_TYPE (lower), 0));
19035 : 51 : protected_set_expr_location (c, lower_loc);
19036 : 51 : if (c == boolean_true_node)
19037 : : {
19038 : 2 : warning_at (lower_loc, OPT_Wopenmp,
19039 : : "%<num_teams%> value must be positive");
19040 : 2 : lower = NULL_TREE;
19041 : : }
19042 : 49 : else if (TREE_CODE (lower) == INTEGER_CST
19043 : 7 : && TREE_CODE (upper) == INTEGER_CST
19044 : 54 : && tree_int_cst_lt (upper, lower))
19045 : : {
19046 : 2 : warning_at (lower_loc, OPT_Wopenmp,
19047 : : "%<num_teams%> lower bound %qE bigger than upper "
19048 : : "bound %qE", lower, upper);
19049 : 2 : lower = NULL_TREE;
19050 : : }
19051 : : }
19052 : :
19053 : 195 : check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
19054 : :
19055 : 195 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
19056 : 195 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
19057 : 195 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
19058 : 195 : OMP_CLAUSE_CHAIN (c) = list;
19059 : 195 : list = c;
19060 : : }
19061 : :
19062 : : return list;
19063 : : }
19064 : :
19065 : : /* OpenMP 4.0:
19066 : : thread_limit ( expression ) */
19067 : :
19068 : : static tree
19069 : 154 : c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
19070 : : {
19071 : 154 : location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
19072 : 154 : matching_parens parens;
19073 : 154 : if (parens.require_open (parser))
19074 : : {
19075 : 154 : location_t expr_loc = c_parser_peek_token (parser)->location;
19076 : 154 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19077 : 154 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19078 : 154 : tree c, t = expr.value;
19079 : 154 : t = c_fully_fold (t, false, NULL);
19080 : :
19081 : 154 : parens.skip_until_found_close (parser);
19082 : :
19083 : 154 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
19084 : : {
19085 : 0 : c_parser_error (parser, "expected integer expression");
19086 : 0 : return list;
19087 : : }
19088 : :
19089 : : /* Attempt to statically determine when the number isn't positive. */
19090 : 154 : c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
19091 : 154 : build_int_cst (TREE_TYPE (t), 0));
19092 : 154 : protected_set_expr_location (c, expr_loc);
19093 : 154 : if (c == boolean_true_node)
19094 : : {
19095 : 0 : warning_at (expr_loc, OPT_Wopenmp,
19096 : : "%<thread_limit%> value must be positive");
19097 : 0 : t = integer_one_node;
19098 : : }
19099 : :
19100 : 154 : check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
19101 : : "thread_limit");
19102 : :
19103 : 154 : c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
19104 : 154 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
19105 : 154 : OMP_CLAUSE_CHAIN (c) = list;
19106 : 154 : list = c;
19107 : : }
19108 : :
19109 : : return list;
19110 : : }
19111 : :
19112 : : /* OpenMP 4.0:
19113 : : aligned ( variable-list )
19114 : : aligned ( variable-list : constant-expression ) */
19115 : :
19116 : : static tree
19117 : 228 : c_parser_omp_clause_aligned (c_parser *parser, tree list)
19118 : : {
19119 : 228 : location_t clause_loc = c_parser_peek_token (parser)->location;
19120 : 228 : tree nl, c;
19121 : :
19122 : 228 : matching_parens parens;
19123 : 228 : if (!parens.require_open (parser))
19124 : : return list;
19125 : :
19126 : 228 : nl = c_parser_omp_variable_list (parser, clause_loc,
19127 : : OMP_CLAUSE_ALIGNED, list);
19128 : :
19129 : 228 : if (c_parser_next_token_is (parser, CPP_COLON))
19130 : : {
19131 : 212 : c_parser_consume_token (parser);
19132 : 212 : location_t expr_loc = c_parser_peek_token (parser)->location;
19133 : 212 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19134 : 212 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19135 : 212 : tree alignment = expr.value;
19136 : 212 : alignment = c_fully_fold (alignment, false, NULL);
19137 : 212 : if (TREE_CODE (alignment) != INTEGER_CST
19138 : 210 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
19139 : 422 : || tree_int_cst_sgn (alignment) != 1)
19140 : : {
19141 : 4 : error_at (clause_loc, "%<aligned%> clause alignment expression must "
19142 : : "be positive constant integer expression");
19143 : 4 : alignment = NULL_TREE;
19144 : : }
19145 : :
19146 : 444 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19147 : 232 : OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
19148 : : }
19149 : :
19150 : 228 : parens.skip_until_found_close (parser);
19151 : 228 : return nl;
19152 : : }
19153 : :
19154 : : /* OpenMP 5.0:
19155 : : allocate ( variable-list )
19156 : : allocate ( expression : variable-list )
19157 : :
19158 : : OpenMP 5.1:
19159 : : allocate ( allocator-modifier : variable-list )
19160 : : allocate ( allocator-modifier , allocator-modifier : variable-list )
19161 : :
19162 : : allocator-modifier:
19163 : : allocator ( expression )
19164 : : align ( expression ) */
19165 : :
19166 : : static tree
19167 : 467 : c_parser_omp_clause_allocate (c_parser *parser, tree list)
19168 : : {
19169 : 467 : location_t clause_loc = c_parser_peek_token (parser)->location;
19170 : 467 : tree nl, c;
19171 : 467 : tree allocator = NULL_TREE;
19172 : 467 : tree align = NULL_TREE;
19173 : :
19174 : 467 : matching_parens parens;
19175 : 467 : if (!parens.require_open (parser))
19176 : : return list;
19177 : :
19178 : 467 : if ((c_parser_next_token_is_not (parser, CPP_NAME)
19179 : 5 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
19180 : 467 : || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
19181 : 448 : && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
19182 : : {
19183 : 202 : bool has_modifiers = false;
19184 : 202 : tree orig_type = NULL_TREE;
19185 : 202 : if (c_parser_next_token_is (parser, CPP_NAME)
19186 : 202 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19187 : : {
19188 : 61 : unsigned int n = 3;
19189 : 61 : const char *p
19190 : 61 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19191 : 29 : if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
19192 : 59 : && c_parser_check_balanced_raw_token_sequence (parser, &n)
19193 : 120 : && (c_parser_peek_nth_token_raw (parser, n)->type
19194 : : == CPP_CLOSE_PAREN))
19195 : : {
19196 : 59 : if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19197 : : == CPP_COLON)
19198 : : has_modifiers = true;
19199 : 27 : else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
19200 : : == CPP_COMMA
19201 : 27 : && (c_parser_peek_nth_token_raw (parser, n + 2)->type
19202 : : == CPP_NAME)
19203 : 54 : && (c_parser_peek_nth_token_raw (parser, n + 3)->type
19204 : : == CPP_OPEN_PAREN))
19205 : : {
19206 : 27 : c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
19207 : 27 : const char *q = IDENTIFIER_POINTER (tok->value);
19208 : 27 : n += 4;
19209 : 27 : if ((strcmp (q, "allocator") == 0
19210 : 14 : || strcmp (q, "align") == 0)
19211 : 27 : && c_parser_check_balanced_raw_token_sequence (parser,
19212 : : &n)
19213 : 27 : && (c_parser_peek_nth_token_raw (parser, n)->type
19214 : : == CPP_CLOSE_PAREN)
19215 : 54 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
19216 : : == CPP_COLON))
19217 : : has_modifiers = true;
19218 : : }
19219 : : }
19220 : : if (has_modifiers)
19221 : : {
19222 : 59 : c_parser_consume_token (parser);
19223 : 59 : matching_parens parens2;
19224 : 59 : parens2.require_open (parser);
19225 : 59 : location_t expr_loc = c_parser_peek_token (parser)->location;
19226 : 59 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19227 : 59 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19228 : 59 : if (expr.value == error_mark_node)
19229 : : ;
19230 : 58 : else if (strcmp (p, "allocator") == 0)
19231 : : {
19232 : 31 : allocator = expr.value;
19233 : 31 : allocator = c_fully_fold (allocator, false, NULL);
19234 : 3 : orig_type = expr.original_type
19235 : 31 : ? expr.original_type : TREE_TYPE (allocator);
19236 : 31 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19237 : : }
19238 : : else
19239 : : {
19240 : 27 : align = expr.value;
19241 : 27 : align = c_fully_fold (align, false, NULL);
19242 : : }
19243 : 59 : parens2.skip_until_found_close (parser);
19244 : 59 : if (c_parser_next_token_is (parser, CPP_COMMA))
19245 : : {
19246 : 27 : c_parser_consume_token (parser);
19247 : 27 : c_token *tok = c_parser_peek_token (parser);
19248 : 27 : const char *q = "";
19249 : 27 : if (c_parser_next_token_is (parser, CPP_NAME))
19250 : 27 : q = IDENTIFIER_POINTER (tok->value);
19251 : 27 : if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
19252 : : {
19253 : 0 : c_parser_error (parser, "expected %<allocator%> or "
19254 : : "%<align%>");
19255 : 0 : parens.skip_until_found_close (parser);
19256 : 2 : return list;
19257 : : }
19258 : 27 : else if (strcmp (p, q) == 0)
19259 : : {
19260 : 2 : error_at (tok->location, "duplicate %qs modifier", p);
19261 : 2 : parens.skip_until_found_close (parser);
19262 : 2 : return list;
19263 : : }
19264 : 25 : c_parser_consume_token (parser);
19265 : 25 : if (!parens2.require_open (parser))
19266 : : {
19267 : 0 : parens.skip_until_found_close (parser);
19268 : 0 : return list;
19269 : : }
19270 : 25 : expr_loc = c_parser_peek_token (parser)->location;
19271 : 25 : expr = c_parser_expr_no_commas (parser, NULL);
19272 : 25 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19273 : : true);
19274 : 25 : if (strcmp (q, "allocator") == 0)
19275 : : {
19276 : 12 : allocator = expr.value;
19277 : 12 : allocator = c_fully_fold (allocator, false, NULL);
19278 : 2 : orig_type = expr.original_type
19279 : 12 : ? expr.original_type : TREE_TYPE (allocator);
19280 : 12 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19281 : : }
19282 : : else
19283 : : {
19284 : 13 : align = expr.value;
19285 : 13 : align = c_fully_fold (align, false, NULL);
19286 : : }
19287 : 25 : parens2.skip_until_found_close (parser);
19288 : : }
19289 : : }
19290 : : }
19291 : 59 : if (!has_modifiers)
19292 : : {
19293 : 143 : location_t expr_loc = c_parser_peek_token (parser)->location;
19294 : 143 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19295 : 143 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19296 : 143 : allocator = expr.value;
19297 : 143 : allocator = c_fully_fold (allocator, false, NULL);
19298 : 7 : orig_type = expr.original_type
19299 : 143 : ? expr.original_type : TREE_TYPE (allocator);
19300 : 143 : orig_type = TYPE_MAIN_VARIANT (orig_type);
19301 : : }
19302 : 200 : if (allocator
19303 : 200 : && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
19304 : 183 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
19305 : 362 : || (TYPE_NAME (orig_type)
19306 : 181 : != get_identifier ("omp_allocator_handle_t"))))
19307 : : {
19308 : 8 : error_at (clause_loc, "%<allocate%> clause allocator expression "
19309 : : "has type %qT rather than "
19310 : : "%<omp_allocator_handle_t%>",
19311 : 4 : TREE_TYPE (allocator));
19312 : 4 : allocator = NULL_TREE;
19313 : : }
19314 : 200 : if (align
19315 : 200 : && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
19316 : 38 : || !tree_fits_uhwi_p (align)
19317 : 37 : || !integer_pow2p (align)))
19318 : : {
19319 : 4 : error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
19320 : : "argument needs to be positive constant "
19321 : : "power of two integer expression");
19322 : 4 : align = NULL_TREE;
19323 : : }
19324 : 200 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19325 : : {
19326 : 0 : parens.skip_until_found_close (parser);
19327 : 0 : return list;
19328 : : }
19329 : : }
19330 : :
19331 : 465 : nl = c_parser_omp_variable_list (parser, clause_loc,
19332 : : OMP_CLAUSE_ALLOCATE, list);
19333 : :
19334 : 465 : if (allocator || align)
19335 : 465 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19336 : : {
19337 : 274 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
19338 : 274 : OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
19339 : : }
19340 : :
19341 : 465 : parens.skip_until_found_close (parser);
19342 : 465 : return nl;
19343 : : }
19344 : :
19345 : : /* OpenMP 4.0:
19346 : : linear ( variable-list )
19347 : : linear ( variable-list : expression )
19348 : :
19349 : : OpenMP 4.5:
19350 : : linear ( modifier ( variable-list ) )
19351 : : linear ( modifier ( variable-list ) : expression )
19352 : :
19353 : : modifier:
19354 : : val
19355 : :
19356 : : OpenMP 5.2:
19357 : : linear ( variable-list : modifiers-list )
19358 : :
19359 : : modifiers:
19360 : : val
19361 : : step ( expression ) */
19362 : :
19363 : : static tree
19364 : 474 : c_parser_omp_clause_linear (c_parser *parser, tree list)
19365 : : {
19366 : 474 : location_t clause_loc = c_parser_peek_token (parser)->location;
19367 : 474 : tree nl, c, step;
19368 : 474 : enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
19369 : 474 : bool old_linear_modifier = false;
19370 : :
19371 : 474 : matching_parens parens;
19372 : 474 : if (!parens.require_open (parser))
19373 : : return list;
19374 : :
19375 : 474 : if (c_parser_next_token_is (parser, CPP_NAME))
19376 : : {
19377 : 474 : c_token *tok = c_parser_peek_token (parser);
19378 : 474 : const char *p = IDENTIFIER_POINTER (tok->value);
19379 : 474 : if (strcmp ("val", p) == 0)
19380 : 12 : kind = OMP_CLAUSE_LINEAR_VAL;
19381 : 474 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
19382 : : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19383 : 12 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19384 : : {
19385 : 12 : old_linear_modifier = true;
19386 : 12 : c_parser_consume_token (parser);
19387 : 12 : c_parser_consume_token (parser);
19388 : : }
19389 : : }
19390 : :
19391 : 474 : nl = c_parser_omp_variable_list (parser, clause_loc,
19392 : : OMP_CLAUSE_LINEAR, list);
19393 : :
19394 : 474 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19395 : 12 : parens.skip_until_found_close (parser);
19396 : :
19397 : 474 : if (c_parser_next_token_is (parser, CPP_COLON))
19398 : : {
19399 : 348 : c_parser_consume_token (parser);
19400 : 348 : location_t expr_loc = c_parser_peek_token (parser)->location;
19401 : 348 : bool has_modifiers = false;
19402 : 348 : if (kind == OMP_CLAUSE_LINEAR_DEFAULT
19403 : 684 : && c_parser_next_token_is (parser, CPP_NAME))
19404 : : {
19405 : 72 : c_token *tok = c_parser_peek_token (parser);
19406 : 72 : const char *p = IDENTIFIER_POINTER (tok->value);
19407 : 72 : unsigned int pos = 0;
19408 : 72 : if (strcmp ("val", p) == 0)
19409 : 7 : pos = 2;
19410 : 65 : else if (strcmp ("step", p) == 0
19411 : 65 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19412 : : {
19413 : 13 : pos = 3;
19414 : 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &pos)
19415 : 13 : && (c_parser_peek_nth_token_raw (parser, pos)->type
19416 : : == CPP_CLOSE_PAREN))
19417 : 13 : ++pos;
19418 : : else
19419 : 0 : pos = 0;
19420 : : }
19421 : 72 : if (pos)
19422 : : {
19423 : 20 : tok = c_parser_peek_nth_token_raw (parser, pos);
19424 : 20 : if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
19425 : 17 : has_modifiers = true;
19426 : : }
19427 : : }
19428 : 72 : if (has_modifiers)
19429 : : {
19430 : : step = NULL_TREE;
19431 : 25 : while (c_parser_next_token_is (parser, CPP_NAME))
19432 : : {
19433 : 25 : c_token *tok = c_parser_peek_token (parser);
19434 : 25 : const char *p = IDENTIFIER_POINTER (tok->value);
19435 : 25 : if (strcmp ("val", p) == 0)
19436 : : {
19437 : 9 : if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19438 : : error_at (tok->location, "multiple linear modifiers");
19439 : 9 : kind = OMP_CLAUSE_LINEAR_DEFAULT;
19440 : 9 : c_parser_consume_token (parser);
19441 : : }
19442 : 16 : else if (strcmp ("step", p) == 0)
19443 : : {
19444 : 16 : c_parser_consume_token (parser);
19445 : 16 : matching_parens parens2;
19446 : 16 : if (parens2.require_open (parser))
19447 : : {
19448 : 16 : if (step)
19449 : 0 : error_at (tok->location,
19450 : : "multiple %<step%> modifiers");
19451 : 16 : expr_loc = c_parser_peek_token (parser)->location;
19452 : 16 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19453 : 16 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19454 : : true);
19455 : 16 : step = c_fully_fold (expr.value, false, NULL);
19456 : 16 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19457 : : {
19458 : 0 : error_at (clause_loc, "%<linear%> clause step "
19459 : : "expression must be integral");
19460 : 0 : step = integer_one_node;
19461 : : }
19462 : 16 : parens2.skip_until_found_close (parser);
19463 : : }
19464 : : else
19465 : : break;
19466 : : }
19467 : : else
19468 : : break;
19469 : 25 : if (c_parser_next_token_is (parser, CPP_COMMA))
19470 : : {
19471 : 8 : c_parser_consume_token (parser);
19472 : 8 : continue;
19473 : : }
19474 : : break;
19475 : : }
19476 : 17 : if (!step)
19477 : 1 : step = integer_one_node;
19478 : : }
19479 : : else
19480 : : {
19481 : 331 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19482 : 331 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19483 : 331 : step = c_fully_fold (expr.value, false, NULL);
19484 : 331 : if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19485 : : {
19486 : 2 : error_at (clause_loc, "%<linear%> clause step expression must "
19487 : : "be integral");
19488 : 2 : step = integer_one_node;
19489 : : }
19490 : : }
19491 : :
19492 : : }
19493 : : else
19494 : 126 : step = integer_one_node;
19495 : :
19496 : 957 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19497 : : {
19498 : 483 : OMP_CLAUSE_LINEAR_STEP (c) = step;
19499 : 483 : OMP_CLAUSE_LINEAR_KIND (c) = kind;
19500 : 483 : OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
19501 : : }
19502 : :
19503 : 474 : parens.skip_until_found_close (parser);
19504 : 474 : return nl;
19505 : : }
19506 : :
19507 : : /* OpenMP 5.0:
19508 : : nontemporal ( variable-list ) */
19509 : :
19510 : : static tree
19511 : 121 : c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
19512 : : {
19513 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_NONTEMPORAL, list);
19514 : : }
19515 : :
19516 : : /* OpenMP 4.0:
19517 : : safelen ( constant-expression ) */
19518 : :
19519 : : static tree
19520 : 227 : c_parser_omp_clause_safelen (c_parser *parser, tree list)
19521 : : {
19522 : 227 : location_t clause_loc = c_parser_peek_token (parser)->location;
19523 : 227 : tree c, t;
19524 : :
19525 : 227 : matching_parens parens;
19526 : 227 : if (!parens.require_open (parser))
19527 : : return list;
19528 : :
19529 : 227 : location_t expr_loc = c_parser_peek_token (parser)->location;
19530 : 227 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19531 : 227 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19532 : 227 : t = expr.value;
19533 : 227 : t = c_fully_fold (t, false, NULL);
19534 : 227 : if (TREE_CODE (t) != INTEGER_CST
19535 : 225 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19536 : 452 : || tree_int_cst_sgn (t) != 1)
19537 : : {
19538 : 4 : error_at (clause_loc, "%<safelen%> clause expression must "
19539 : : "be positive constant integer expression");
19540 : 4 : t = NULL_TREE;
19541 : : }
19542 : :
19543 : 227 : parens.skip_until_found_close (parser);
19544 : 227 : if (t == NULL_TREE || t == error_mark_node)
19545 : : return list;
19546 : :
19547 : 223 : check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen");
19548 : :
19549 : 223 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
19550 : 223 : OMP_CLAUSE_SAFELEN_EXPR (c) = t;
19551 : 223 : OMP_CLAUSE_CHAIN (c) = list;
19552 : 223 : return c;
19553 : : }
19554 : :
19555 : : /* OpenMP 4.0:
19556 : : simdlen ( constant-expression ) */
19557 : :
19558 : : static tree
19559 : 317 : c_parser_omp_clause_simdlen (c_parser *parser, tree list)
19560 : : {
19561 : 317 : location_t clause_loc = c_parser_peek_token (parser)->location;
19562 : 317 : tree c, t;
19563 : :
19564 : 317 : matching_parens parens;
19565 : 317 : if (!parens.require_open (parser))
19566 : : return list;
19567 : :
19568 : 317 : location_t expr_loc = c_parser_peek_token (parser)->location;
19569 : 317 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19570 : 317 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19571 : 317 : t = expr.value;
19572 : 317 : t = c_fully_fold (t, false, NULL);
19573 : 317 : if (TREE_CODE (t) != INTEGER_CST
19574 : 315 : || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19575 : 632 : || tree_int_cst_sgn (t) != 1)
19576 : : {
19577 : 4 : error_at (clause_loc, "%<simdlen%> clause expression must "
19578 : : "be positive constant integer expression");
19579 : 4 : t = NULL_TREE;
19580 : : }
19581 : :
19582 : 317 : parens.skip_until_found_close (parser);
19583 : 317 : if (t == NULL_TREE || t == error_mark_node)
19584 : : return list;
19585 : :
19586 : 313 : check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen");
19587 : :
19588 : 313 : c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
19589 : 313 : OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
19590 : 313 : OMP_CLAUSE_CHAIN (c) = list;
19591 : 313 : return c;
19592 : : }
19593 : :
19594 : : /* OpenMP 4.5:
19595 : : vec:
19596 : : identifier [+/- integer]
19597 : : vec , identifier [+/- integer]
19598 : : */
19599 : :
19600 : : static tree
19601 : 206 : c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
19602 : : tree list, bool depend_p)
19603 : : {
19604 : 206 : tree vec = NULL;
19605 : 206 : if (c_parser_next_token_is_not (parser, CPP_NAME)
19606 : 206 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
19607 : : {
19608 : 0 : c_parser_error (parser, "expected identifier");
19609 : 0 : return list;
19610 : : }
19611 : :
19612 : 206 : if (!depend_p)
19613 : : {
19614 : 83 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19615 : 83 : if (strcmp (p, "omp_cur_iteration") == 0
19616 : 36 : && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
19617 : 34 : && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
19618 : 116 : && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
19619 : : {
19620 : 33 : tree val = c_parser_peek_nth_token (parser, 3)->value;
19621 : 33 : if (integer_onep (val))
19622 : : {
19623 : 33 : c_parser_consume_token (parser);
19624 : 33 : c_parser_consume_token (parser);
19625 : 33 : c_parser_consume_token (parser);
19626 : 33 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19627 : 33 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19628 : 33 : OMP_CLAUSE_CHAIN (u) = list;
19629 : 33 : return u;
19630 : : }
19631 : : }
19632 : : }
19633 : :
19634 : :
19635 : :
19636 : 1151 : while (c_parser_next_token_is (parser, CPP_NAME)
19637 : 1151 : && c_parser_peek_token (parser)->id_kind == C_ID_ID)
19638 : : {
19639 : 1151 : tree t = lookup_name (c_parser_peek_token (parser)->value);
19640 : 1151 : tree addend = NULL;
19641 : :
19642 : 1151 : if (t == NULL_TREE)
19643 : : {
19644 : 6 : undeclared_variable (c_parser_peek_token (parser)->location,
19645 : 6 : c_parser_peek_token (parser)->value);
19646 : 6 : t = error_mark_node;
19647 : : }
19648 : :
19649 : 1151 : c_parser_consume_token (parser);
19650 : :
19651 : 1151 : bool neg = false;
19652 : 1151 : if (c_parser_next_token_is (parser, CPP_MINUS))
19653 : : neg = true;
19654 : 920 : else if (!c_parser_next_token_is (parser, CPP_PLUS))
19655 : : {
19656 : 857 : addend = integer_zero_node;
19657 : 857 : neg = false;
19658 : 857 : goto add_to_vector;
19659 : : }
19660 : 294 : c_parser_consume_token (parser);
19661 : :
19662 : 294 : if (c_parser_next_token_is_not (parser, CPP_NUMBER))
19663 : : {
19664 : 1 : c_parser_error (parser, "expected integer");
19665 : 1 : return list;
19666 : : }
19667 : :
19668 : 293 : addend = c_parser_peek_token (parser)->value;
19669 : 293 : if (TREE_CODE (addend) != INTEGER_CST)
19670 : : {
19671 : 0 : c_parser_error (parser, "expected integer");
19672 : 0 : return list;
19673 : : }
19674 : 293 : c_parser_consume_token (parser);
19675 : :
19676 : 1150 : add_to_vector:
19677 : 1150 : if (t != error_mark_node)
19678 : : {
19679 : 1145 : vec = tree_cons (addend, t, vec);
19680 : 1145 : if (neg)
19681 : 228 : OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
19682 : : }
19683 : :
19684 : 1150 : if (c_parser_next_token_is_not (parser, CPP_COMMA)
19685 : 979 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
19686 : 2128 : || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
19687 : : break;
19688 : :
19689 : 978 : c_parser_consume_token (parser);
19690 : : }
19691 : :
19692 : 172 : if (vec == NULL_TREE)
19693 : : return list;
19694 : :
19695 : 168 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19696 : 168 : OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19697 : 168 : OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
19698 : 168 : OMP_CLAUSE_DECL (u) = nreverse (vec);
19699 : 168 : OMP_CLAUSE_CHAIN (u) = list;
19700 : 168 : return u;
19701 : : }
19702 : :
19703 : : /* OpenMP 5.0:
19704 : : iterators ( iterators-definition )
19705 : :
19706 : : iterators-definition:
19707 : : iterator-specifier
19708 : : iterator-specifier , iterators-definition
19709 : :
19710 : : iterator-specifier:
19711 : : identifier = range-specification
19712 : : iterator-type identifier = range-specification
19713 : :
19714 : : range-specification:
19715 : : begin : end
19716 : : begin : end : step */
19717 : :
19718 : : static tree
19719 : 150 : c_parser_omp_iterators (c_parser *parser)
19720 : : {
19721 : 150 : tree ret = NULL_TREE, *last = &ret;
19722 : 150 : c_parser_consume_token (parser);
19723 : :
19724 : 150 : push_scope ();
19725 : :
19726 : 150 : matching_parens parens;
19727 : 150 : if (!parens.require_open (parser))
19728 : 1 : return error_mark_node;
19729 : :
19730 : 215 : do
19731 : : {
19732 : 182 : tree iter_type = NULL_TREE, type_expr = NULL_TREE;
19733 : 182 : if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
19734 : : {
19735 : 50 : struct c_type_name *type = c_parser_type_name (parser);
19736 : 50 : if (type != NULL)
19737 : 50 : iter_type = groktypename (type, &type_expr, NULL);
19738 : : }
19739 : 50 : if (iter_type == NULL_TREE)
19740 : 132 : iter_type = integer_type_node;
19741 : :
19742 : 182 : location_t loc = c_parser_peek_token (parser)->location;
19743 : 182 : if (!c_parser_next_token_is (parser, CPP_NAME))
19744 : : {
19745 : 8 : c_parser_error (parser, "expected identifier");
19746 : 8 : break;
19747 : : }
19748 : :
19749 : 174 : tree id = c_parser_peek_token (parser)->value;
19750 : 174 : c_parser_consume_token (parser);
19751 : :
19752 : 174 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
19753 : : break;
19754 : :
19755 : 172 : location_t eloc = c_parser_peek_token (parser)->location;
19756 : 172 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
19757 : 172 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19758 : 172 : tree begin = expr.value;
19759 : :
19760 : 172 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19761 : : break;
19762 : :
19763 : 170 : eloc = c_parser_peek_token (parser)->location;
19764 : 170 : expr = c_parser_expr_no_commas (parser, NULL);
19765 : 170 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19766 : 170 : tree end = expr.value;
19767 : :
19768 : 170 : tree step = integer_one_node;
19769 : 170 : if (c_parser_next_token_is (parser, CPP_COLON))
19770 : : {
19771 : 58 : c_parser_consume_token (parser);
19772 : 58 : eloc = c_parser_peek_token (parser)->location;
19773 : 58 : expr = c_parser_expr_no_commas (parser, NULL);
19774 : 58 : expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19775 : 58 : step = expr.value;
19776 : : }
19777 : :
19778 : 170 : tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
19779 : 170 : DECL_ARTIFICIAL (iter_var) = 1;
19780 : 170 : DECL_CONTEXT (iter_var) = current_function_decl;
19781 : 170 : pushdecl (iter_var);
19782 : :
19783 : 170 : *last = make_tree_vec (6);
19784 : 170 : TREE_VEC_ELT (*last, 0) = iter_var;
19785 : 170 : TREE_VEC_ELT (*last, 1) = begin;
19786 : 170 : TREE_VEC_ELT (*last, 2) = end;
19787 : 170 : TREE_VEC_ELT (*last, 3) = step;
19788 : 170 : last = &TREE_CHAIN (*last);
19789 : :
19790 : 170 : if (c_parser_next_token_is (parser, CPP_COMMA))
19791 : : {
19792 : 33 : c_parser_consume_token (parser);
19793 : 33 : continue;
19794 : : }
19795 : : break;
19796 : : }
19797 : : while (1);
19798 : :
19799 : 149 : parens.skip_until_found_close (parser);
19800 : 149 : return ret ? ret : error_mark_node;
19801 : : }
19802 : :
19803 : : /* OpenMP 5.0:
19804 : : affinity ( [aff-modifier :] variable-list )
19805 : : aff-modifier:
19806 : : iterator ( iterators-definition ) */
19807 : :
19808 : : static tree
19809 : 146 : c_parser_omp_clause_affinity (c_parser *parser, tree list)
19810 : : {
19811 : 146 : location_t clause_loc = c_parser_peek_token (parser)->location;
19812 : 146 : tree nl, iterators = NULL_TREE;
19813 : :
19814 : 146 : matching_parens parens;
19815 : 146 : if (!parens.require_open (parser))
19816 : : return list;
19817 : :
19818 : 146 : if (c_parser_next_token_is (parser, CPP_NAME))
19819 : : {
19820 : 144 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19821 : 144 : bool parse_iter = ((strcmp ("iterator", p) == 0)
19822 : 144 : && (c_parser_peek_2nd_token (parser)->type
19823 : 50 : == CPP_OPEN_PAREN));
19824 : 50 : if (parse_iter)
19825 : : {
19826 : 50 : unsigned n = 3;
19827 : 50 : parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, &n)
19828 : 50 : && (c_parser_peek_nth_token_raw (parser, n)->type
19829 : : == CPP_CLOSE_PAREN)
19830 : 100 : && (c_parser_peek_nth_token_raw (parser, n + 1)->type
19831 : : == CPP_COLON));
19832 : : }
19833 : 3 : if (parse_iter)
19834 : : {
19835 : 47 : iterators = c_parser_omp_iterators (parser);
19836 : 47 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19837 : : {
19838 : 0 : if (iterators)
19839 : 0 : pop_scope ();
19840 : 0 : parens.skip_until_found_close (parser);
19841 : 0 : return list;
19842 : : }
19843 : : }
19844 : : }
19845 : 146 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_AFFINITY,
19846 : : list);
19847 : 146 : if (iterators)
19848 : : {
19849 : 47 : tree block = pop_scope ();
19850 : 47 : if (iterators != error_mark_node)
19851 : : {
19852 : 43 : TREE_VEC_ELT (iterators, 5) = block;
19853 : 99 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19854 : 112 : OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
19855 : 56 : OMP_CLAUSE_DECL (c));
19856 : : }
19857 : : }
19858 : :
19859 : 146 : parens.skip_until_found_close (parser);
19860 : 146 : return nl;
19861 : : }
19862 : :
19863 : :
19864 : : /* OpenMP 4.0:
19865 : : depend ( depend-kind: variable-list )
19866 : :
19867 : : depend-kind:
19868 : : in | out | inout
19869 : :
19870 : : OpenMP 4.5:
19871 : : depend ( source )
19872 : :
19873 : : depend ( sink : vec )
19874 : :
19875 : : OpenMP 5.0:
19876 : : depend ( depend-modifier , depend-kind: variable-list )
19877 : :
19878 : : depend-kind:
19879 : : in | out | inout | mutexinoutset | depobj | inoutset
19880 : :
19881 : : depend-modifier:
19882 : : iterator ( iterators-definition ) */
19883 : :
19884 : : static tree
19885 : 893 : c_parser_omp_clause_depend (c_parser *parser, tree list)
19886 : : {
19887 : 893 : location_t clause_loc = c_parser_peek_token (parser)->location;
19888 : 893 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
19889 : 893 : enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
19890 : 893 : tree nl, c, iterators = NULL_TREE;
19891 : :
19892 : 893 : matching_parens parens;
19893 : 893 : if (!parens.require_open (parser))
19894 : : return list;
19895 : :
19896 : 1047 : do
19897 : : {
19898 : 970 : if (c_parser_next_token_is_not (parser, CPP_NAME))
19899 : 0 : goto invalid_kind;
19900 : :
19901 : 970 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19902 : 970 : if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
19903 : : {
19904 : 77 : iterators = c_parser_omp_iterators (parser);
19905 : 77 : c_parser_require (parser, CPP_COMMA, "expected %<,%>");
19906 : 77 : continue;
19907 : : }
19908 : 893 : if (strcmp ("in", p) == 0)
19909 : : kind = OMP_CLAUSE_DEPEND_IN;
19910 : 642 : else if (strcmp ("inout", p) == 0)
19911 : : kind = OMP_CLAUSE_DEPEND_INOUT;
19912 : 423 : else if (strcmp ("inoutset", p) == 0)
19913 : : kind = OMP_CLAUSE_DEPEND_INOUTSET;
19914 : 408 : else if (strcmp ("mutexinoutset", p) == 0)
19915 : : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
19916 : 387 : else if (strcmp ("out", p) == 0)
19917 : : kind = OMP_CLAUSE_DEPEND_OUT;
19918 : 242 : else if (strcmp ("depobj", p) == 0)
19919 : : kind = OMP_CLAUSE_DEPEND_DEPOBJ;
19920 : 221 : else if (strcmp ("sink", p) == 0)
19921 : : dkind = OMP_CLAUSE_DOACROSS_SINK;
19922 : 98 : else if (strcmp ("source", p) == 0)
19923 : : dkind = OMP_CLAUSE_DOACROSS_SOURCE;
19924 : : else
19925 : 2 : goto invalid_kind;
19926 : 891 : break;
19927 : 77 : }
19928 : : while (1);
19929 : :
19930 : 891 : c_parser_consume_token (parser);
19931 : :
19932 : 891 : if (iterators
19933 : 891 : && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
19934 : 891 : || dkind == OMP_CLAUSE_DOACROSS_SINK))
19935 : : {
19936 : 2 : pop_scope ();
19937 : 2 : error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
19938 : : dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
19939 : 2 : iterators = NULL_TREE;
19940 : : }
19941 : :
19942 : 891 : if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
19943 : : {
19944 : 96 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19945 : 96 : OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
19946 : 96 : OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
19947 : 96 : OMP_CLAUSE_DECL (c) = NULL_TREE;
19948 : 96 : OMP_CLAUSE_CHAIN (c) = list;
19949 : 96 : parens.skip_until_found_close (parser);
19950 : 96 : return c;
19951 : : }
19952 : :
19953 : 795 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
19954 : 0 : goto resync_fail;
19955 : :
19956 : 795 : if (dkind == OMP_CLAUSE_DOACROSS_SINK)
19957 : 123 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
19958 : : else
19959 : : {
19960 : 672 : nl = c_parser_omp_variable_list (parser, clause_loc,
19961 : : OMP_CLAUSE_DEPEND, list);
19962 : :
19963 : 672 : if (iterators)
19964 : : {
19965 : 73 : tree block = pop_scope ();
19966 : 73 : if (iterators == error_mark_node)
19967 : : iterators = NULL_TREE;
19968 : : else
19969 : 68 : TREE_VEC_ELT (iterators, 5) = block;
19970 : : }
19971 : :
19972 : 1385 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19973 : : {
19974 : 713 : OMP_CLAUSE_DEPEND_KIND (c) = kind;
19975 : 713 : if (iterators)
19976 : 150 : OMP_CLAUSE_DECL (c)
19977 : 150 : = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
19978 : : }
19979 : : }
19980 : :
19981 : 795 : parens.skip_until_found_close (parser);
19982 : 795 : return nl;
19983 : :
19984 : 2 : invalid_kind:
19985 : 2 : c_parser_error (parser, "invalid depend kind");
19986 : 2 : resync_fail:
19987 : 2 : parens.skip_until_found_close (parser);
19988 : 2 : if (iterators)
19989 : 2 : pop_scope ();
19990 : : return list;
19991 : : }
19992 : :
19993 : : /* OpenMP 5.2:
19994 : : doacross ( source : )
19995 : : doacross ( source : omp_cur_iteration )
19996 : :
19997 : : doacross ( sink : vec )
19998 : : doacross ( sink : omp_cur_iteration - logical_iteration ) */
19999 : :
20000 : : static tree
20001 : 145 : c_parser_omp_clause_doacross (c_parser *parser, tree list)
20002 : : {
20003 : 145 : location_t clause_loc = c_parser_peek_token (parser)->location;
20004 : 145 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
20005 : 145 : tree nl;
20006 : 145 : const char *p;
20007 : :
20008 : 145 : matching_parens parens;
20009 : 145 : if (!parens.require_open (parser))
20010 : : return list;
20011 : :
20012 : 145 : if (c_parser_next_token_is_not (parser, CPP_NAME))
20013 : 0 : goto invalid_kind;
20014 : :
20015 : 145 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20016 : 145 : if (strcmp ("sink", p) == 0)
20017 : : kind = OMP_CLAUSE_DOACROSS_SINK;
20018 : 60 : else if (strcmp ("source", p) == 0)
20019 : : kind = OMP_CLAUSE_DOACROSS_SOURCE;
20020 : : else
20021 : 0 : goto invalid_kind;
20022 : :
20023 : 145 : c_parser_consume_token (parser);
20024 : :
20025 : 145 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
20026 : 4 : goto resync_fail;
20027 : :
20028 : 141 : if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
20029 : : {
20030 : 58 : if (c_parser_next_token_is (parser, CPP_NAME)
20031 : 58 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
20032 : : "omp_cur_iteration") == 0)
20033 : 28 : c_parser_consume_token (parser);
20034 : 58 : nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20035 : 58 : OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
20036 : 58 : OMP_CLAUSE_DECL (nl) = NULL_TREE;
20037 : 58 : OMP_CLAUSE_CHAIN (nl) = list;
20038 : : }
20039 : : else
20040 : 83 : nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
20041 : :
20042 : 141 : parens.skip_until_found_close (parser);
20043 : 141 : return nl;
20044 : :
20045 : 0 : invalid_kind:
20046 : 0 : c_parser_error (parser, "invalid doacross kind");
20047 : 4 : resync_fail:
20048 : 4 : parens.skip_until_found_close (parser);
20049 : 4 : return list;
20050 : : }
20051 : :
20052 : : /* OpenMP 4.0:
20053 : : map ( map-kind: variable-list )
20054 : : map ( variable-list )
20055 : :
20056 : : map-kind:
20057 : : alloc | to | from | tofrom
20058 : :
20059 : : OpenMP 4.5:
20060 : : map-kind:
20061 : : alloc | to | from | tofrom | release | delete
20062 : :
20063 : : map ( always [,] map-kind: variable-list )
20064 : :
20065 : : OpenMP 5.0:
20066 : : map ( [map-type-modifier[,] ...] map-kind: variable-list )
20067 : :
20068 : : map-type-modifier:
20069 : : always | close | present | iterator (iterators-definition) */
20070 : :
20071 : : static tree
20072 : 1731 : c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
20073 : : {
20074 : 1731 : location_t clause_loc = c_parser_peek_token (parser)->location;
20075 : 1731 : tree nl, c;
20076 : 1731 : enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
20077 : :
20078 : 1731 : matching_parens parens;
20079 : 1731 : if (!parens.require_open (parser))
20080 : : return list;
20081 : :
20082 : : int pos = 1;
20083 : 2300 : int map_kind_pos = 0;
20084 : : int iterator_length = 0;
20085 : 2869 : for (;;)
20086 : : {
20087 : 2300 : c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
20088 : 2300 : if (tok->type != CPP_NAME)
20089 : : break;
20090 : :
20091 : 1984 : const char *p = IDENTIFIER_POINTER (tok->value);
20092 : 1984 : c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
20093 : 1984 : if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
20094 : : {
20095 : 16 : unsigned n = pos + 2;
20096 : 16 : if (c_parser_check_balanced_raw_token_sequence (parser, &n)
20097 : 16 : && c_parser_peek_nth_token_raw (parser, n)->type
20098 : : == CPP_CLOSE_PAREN)
20099 : : {
20100 : 16 : iterator_length = n - pos + 1;
20101 : 16 : pos = n;
20102 : 16 : next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
20103 : : }
20104 : : }
20105 : :
20106 : 1984 : if (next_tok->type == CPP_COLON)
20107 : : {
20108 : : map_kind_pos = pos;
20109 : : break;
20110 : : }
20111 : :
20112 : 569 : if (next_tok->type == CPP_COMMA)
20113 : 191 : pos++;
20114 : 378 : else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
20115 : : == CPP_OPEN_PAREN)
20116 : : {
20117 : 13 : unsigned int npos = pos + 2;
20118 : 13 : if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
20119 : 13 : && (c_parser_peek_nth_token_raw (parser, npos)->type
20120 : : == CPP_CLOSE_PAREN)
20121 : 26 : && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
20122 : : == CPP_COMMA))
20123 : 12 : pos = npos + 1;
20124 : : }
20125 : :
20126 : 569 : pos++;
20127 : 569 : }
20128 : :
20129 : 1731 : int always_modifier = 0;
20130 : 1731 : int close_modifier = 0;
20131 : 1731 : int present_modifier = 0;
20132 : 1731 : int mapper_modifier = 0;
20133 : 1731 : tree mapper_name = NULL_TREE;
20134 : 1731 : tree iterators = NULL_TREE;
20135 : 2097 : for (int pos = 1; pos < map_kind_pos; ++pos)
20136 : : {
20137 : 384 : c_token *tok = c_parser_peek_token (parser);
20138 : :
20139 : 384 : if (tok->type == CPP_COMMA)
20140 : : {
20141 : 162 : c_parser_consume_token (parser);
20142 : 162 : continue;
20143 : : }
20144 : :
20145 : 222 : const char *p = IDENTIFIER_POINTER (tok->value);
20146 : 222 : if (strcmp ("always", p) == 0)
20147 : : {
20148 : 75 : if (always_modifier)
20149 : : {
20150 : 4 : c_parser_error (parser, "too many %<always%> modifiers");
20151 : 4 : parens.skip_until_found_close (parser);
20152 : 4 : return list;
20153 : : }
20154 : 71 : always_modifier++;
20155 : 71 : c_parser_consume_token (parser);
20156 : : }
20157 : 147 : else if (strcmp ("close", p) == 0)
20158 : : {
20159 : 62 : if (close_modifier)
20160 : : {
20161 : 4 : c_parser_error (parser, "too many %<close%> modifiers");
20162 : 4 : parens.skip_until_found_close (parser);
20163 : 4 : return list;
20164 : : }
20165 : 58 : close_modifier++;
20166 : 58 : c_parser_consume_token (parser);
20167 : : }
20168 : 85 : else if (strcmp ("iterator", p) == 0)
20169 : : {
20170 : 16 : if (iterators)
20171 : : {
20172 : 1 : c_parser_error (parser, "too many %<iterator%> modifiers");
20173 : 1 : parens.skip_until_found_close (parser);
20174 : 1 : return list;
20175 : : }
20176 : 15 : iterators = c_parser_omp_iterators (parser);
20177 : 15 : pos += iterator_length - 1;
20178 : : }
20179 : 69 : else if (strcmp ("mapper", p) == 0)
20180 : : {
20181 : 12 : c_parser_consume_token (parser);
20182 : :
20183 : 12 : matching_parens mparens;
20184 : 12 : if (mparens.require_open (parser))
20185 : : {
20186 : 12 : if (mapper_modifier)
20187 : : {
20188 : 0 : c_parser_error (parser, "too many %<mapper%> modifiers");
20189 : : /* Assume it's a well-formed mapper modifier, even if it
20190 : : seems to be in the wrong place. */
20191 : 0 : c_parser_consume_token (parser);
20192 : 0 : mparens.require_close (parser);
20193 : 0 : parens.skip_until_found_close (parser);
20194 : 0 : return list;
20195 : : }
20196 : :
20197 : 12 : tok = c_parser_peek_token (parser);
20198 : :
20199 : 12 : switch (tok->type)
20200 : : {
20201 : 5 : case CPP_NAME:
20202 : 5 : {
20203 : 5 : mapper_name = tok->value;
20204 : 5 : c_parser_consume_token (parser);
20205 : 5 : if (declare_mapper_p)
20206 : : {
20207 : 1 : error_at (tok->location,
20208 : : "in %<declare mapper%> directives, parameter "
20209 : : "to %<mapper%> modifier must be %<default%>");
20210 : : }
20211 : : }
20212 : : break;
20213 : :
20214 : 7 : case CPP_KEYWORD:
20215 : 7 : if (tok->keyword == RID_DEFAULT)
20216 : : {
20217 : 7 : c_parser_consume_token (parser);
20218 : 7 : break;
20219 : : }
20220 : : /* Fallthrough. */
20221 : :
20222 : 0 : default:
20223 : 0 : error_at (tok->location,
20224 : : "expected identifier or %<default%>");
20225 : 0 : return list;
20226 : : }
20227 : :
20228 : 12 : if (!mparens.require_close (parser))
20229 : : {
20230 : 0 : parens.skip_until_found_close (parser);
20231 : 0 : return list;
20232 : : }
20233 : :
20234 : 12 : mapper_modifier++;
20235 : 12 : pos += 3;
20236 : : }
20237 : : }
20238 : 57 : else if (strcmp ("present", p) == 0)
20239 : : {
20240 : 52 : if (present_modifier)
20241 : : {
20242 : 4 : c_parser_error (parser, "too many %<present%> modifiers");
20243 : 4 : parens.skip_until_found_close (parser);
20244 : 4 : return list;
20245 : : }
20246 : 48 : present_modifier++;
20247 : 48 : c_parser_consume_token (parser);
20248 : : }
20249 : : else
20250 : : {
20251 : 5 : c_parser_error (parser, "%<map%> clause with map-type modifier other "
20252 : : "than %<always%>, %<close%>, %<iterator%>, "
20253 : : "%<mapper%> or %<present%>");
20254 : 5 : parens.skip_until_found_close (parser);
20255 : 5 : return list;
20256 : : }
20257 : : }
20258 : :
20259 : 1713 : if (c_parser_next_token_is (parser, CPP_NAME)
20260 : 1713 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20261 : : {
20262 : 1397 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20263 : 1397 : int always_present_modifier = always_modifier && present_modifier;
20264 : :
20265 : 1397 : if (strcmp ("alloc", p) == 0)
20266 : 128 : kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
20267 : 1269 : else if (strcmp ("to", p) == 0)
20268 : 869 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
20269 : 447 : : present_modifier ? GOMP_MAP_PRESENT_TO
20270 : 439 : : always_modifier ? GOMP_MAP_ALWAYS_TO
20271 : : : GOMP_MAP_TO);
20272 : 819 : else if (strcmp ("from", p) == 0)
20273 : 954 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
20274 : 479 : : present_modifier ? GOMP_MAP_PRESENT_FROM
20275 : 476 : : always_modifier ? GOMP_MAP_ALWAYS_FROM
20276 : : : GOMP_MAP_FROM);
20277 : 335 : else if (strcmp ("tofrom", p) == 0)
20278 : 544 : kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
20279 : 280 : : present_modifier ? GOMP_MAP_PRESENT_TOFROM
20280 : 274 : : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
20281 : : : GOMP_MAP_TOFROM);
20282 : 50 : else if (strcmp ("release", p) == 0)
20283 : : kind = GOMP_MAP_RELEASE;
20284 : 15 : else if (strcmp ("delete", p) == 0)
20285 : : kind = GOMP_MAP_DELETE;
20286 : : else
20287 : : {
20288 : 0 : c_parser_error (parser, "invalid map kind");
20289 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20290 : : "expected %<)%>");
20291 : 0 : return list;
20292 : : }
20293 : 1397 : c_parser_consume_token (parser);
20294 : 1397 : c_parser_consume_token (parser);
20295 : : }
20296 : :
20297 : 1713 : nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
20298 : : true);
20299 : :
20300 : 1713 : tree last_new = NULL_TREE;
20301 : :
20302 : 1713 : if (iterators)
20303 : : {
20304 : 14 : tree block = pop_scope ();
20305 : 14 : if (iterators == error_mark_node)
20306 : : iterators = NULL_TREE;
20307 : : else
20308 : 14 : TREE_VEC_ELT (iterators, 5) = block;
20309 : : }
20310 : :
20311 : 3832 : for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20312 : : {
20313 : 2119 : OMP_CLAUSE_SET_MAP_KIND (c, kind);
20314 : 2119 : OMP_CLAUSE_ITERATORS (c) = iterators;
20315 : 2119 : last_new = c;
20316 : : }
20317 : :
20318 : 1713 : if (mapper_name)
20319 : : {
20320 : 5 : tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20321 : 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
20322 : 5 : OMP_CLAUSE_DECL (name) = mapper_name;
20323 : 5 : OMP_CLAUSE_CHAIN (name) = nl;
20324 : 5 : nl = name;
20325 : :
20326 : 5 : gcc_assert (last_new);
20327 : :
20328 : 5 : name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20329 : 5 : OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
20330 : 5 : OMP_CLAUSE_DECL (name) = null_pointer_node;
20331 : 5 : OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
20332 : 5 : OMP_CLAUSE_CHAIN (last_new) = name;
20333 : : }
20334 : :
20335 : 1713 : parens.skip_until_found_close (parser);
20336 : 1713 : return nl;
20337 : : }
20338 : :
20339 : : /* OpenMP 4.0:
20340 : : device ( expression )
20341 : :
20342 : : OpenMP 5.0:
20343 : : device ( [device-modifier :] integer-expression )
20344 : :
20345 : : device-modifier:
20346 : : ancestor | device_num */
20347 : :
20348 : : static tree
20349 : 367 : c_parser_omp_clause_device (c_parser *parser, tree list)
20350 : : {
20351 : 367 : location_t clause_loc = c_parser_peek_token (parser)->location;
20352 : 367 : location_t expr_loc;
20353 : 367 : c_expr expr;
20354 : 367 : tree c, t;
20355 : 367 : bool ancestor = false;
20356 : :
20357 : 367 : matching_parens parens;
20358 : 367 : if (!parens.require_open (parser))
20359 : : return list;
20360 : :
20361 : 367 : if (c_parser_next_token_is (parser, CPP_NAME)
20362 : 367 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20363 : : {
20364 : 50 : c_token *tok = c_parser_peek_token (parser);
20365 : 50 : const char *p = IDENTIFIER_POINTER (tok->value);
20366 : 50 : if (strcmp ("ancestor", p) == 0)
20367 : : {
20368 : : /* A requires directive with the reverse_offload clause must be
20369 : : specified. */
20370 : 25 : if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
20371 : : {
20372 : 1 : error_at (tok->location, "%<ancestor%> device modifier not "
20373 : : "preceded by %<requires%> directive "
20374 : : "with %<reverse_offload%> clause");
20375 : 1 : parens.skip_until_found_close (parser);
20376 : 1 : return list;
20377 : : }
20378 : : ancestor = true;
20379 : : }
20380 : 25 : else if (strcmp ("device_num", p) == 0)
20381 : : ;
20382 : : else
20383 : : {
20384 : 1 : error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
20385 : 1 : parens.skip_until_found_close (parser);
20386 : 1 : return list;
20387 : : }
20388 : 48 : c_parser_consume_token (parser);
20389 : 48 : c_parser_consume_token (parser);
20390 : : }
20391 : :
20392 : 365 : expr_loc = c_parser_peek_token (parser)->location;
20393 : 365 : expr = c_parser_expr_no_commas (parser, NULL);
20394 : 365 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20395 : 365 : t = expr.value;
20396 : 365 : t = c_fully_fold (t, false, NULL);
20397 : :
20398 : 365 : parens.skip_until_found_close (parser);
20399 : :
20400 : 365 : if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
20401 : : {
20402 : 2 : c_parser_error (parser, "expected integer expression");
20403 : 2 : return list;
20404 : : }
20405 : 363 : if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
20406 : : {
20407 : 1 : error_at (expr_loc, "the %<device%> clause expression must evaluate to "
20408 : : "%<1%>");
20409 : 1 : return list;
20410 : : }
20411 : :
20412 : 362 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
20413 : :
20414 : 362 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
20415 : :
20416 : 362 : OMP_CLAUSE_DEVICE_ID (c) = t;
20417 : 362 : OMP_CLAUSE_CHAIN (c) = list;
20418 : 362 : OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
20419 : :
20420 : 362 : list = c;
20421 : 362 : return list;
20422 : : }
20423 : :
20424 : : /* OpenMP 4.0:
20425 : : dist_schedule ( static )
20426 : : dist_schedule ( static , expression ) */
20427 : :
20428 : : static tree
20429 : 1582 : c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
20430 : : {
20431 : 1582 : tree c, t = NULL_TREE;
20432 : 1582 : location_t loc = c_parser_peek_token (parser)->location;
20433 : :
20434 : 1582 : matching_parens parens;
20435 : 1582 : if (!parens.require_open (parser))
20436 : : return list;
20437 : :
20438 : 1582 : if (!c_parser_next_token_is_keyword (parser, RID_STATIC))
20439 : : {
20440 : 0 : c_parser_error (parser, "invalid dist_schedule kind");
20441 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20442 : : "expected %<)%>");
20443 : 0 : return list;
20444 : : }
20445 : :
20446 : 1582 : c_parser_consume_token (parser);
20447 : 1582 : if (c_parser_next_token_is (parser, CPP_COMMA))
20448 : : {
20449 : 1575 : c_parser_consume_token (parser);
20450 : :
20451 : 1575 : location_t expr_loc = c_parser_peek_token (parser)->location;
20452 : 1575 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20453 : 1575 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20454 : 1575 : t = expr.value;
20455 : 1575 : t = c_fully_fold (t, false, NULL);
20456 : 1575 : parens.skip_until_found_close (parser);
20457 : : }
20458 : : else
20459 : 7 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
20460 : : "expected %<,%> or %<)%>");
20461 : :
20462 : : /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
20463 : : "dist_schedule"); */
20464 : 1582 : if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE))
20465 : 2 : warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
20466 : 1582 : if (t == error_mark_node)
20467 : : return list;
20468 : :
20469 : 1582 : c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
20470 : 1582 : OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
20471 : 1582 : OMP_CLAUSE_CHAIN (c) = list;
20472 : 1582 : return c;
20473 : : }
20474 : :
20475 : : /* OpenMP 4.0:
20476 : : proc_bind ( proc-bind-kind )
20477 : :
20478 : : proc-bind-kind:
20479 : : primary | master | close | spread
20480 : : where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
20481 : :
20482 : : static tree
20483 : 194 : c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
20484 : : {
20485 : 194 : location_t clause_loc = c_parser_peek_token (parser)->location;
20486 : 194 : enum omp_clause_proc_bind_kind kind;
20487 : 194 : tree c;
20488 : :
20489 : 194 : matching_parens parens;
20490 : 194 : if (!parens.require_open (parser))
20491 : : return list;
20492 : :
20493 : 194 : if (c_parser_next_token_is (parser, CPP_NAME))
20494 : : {
20495 : 194 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20496 : 194 : if (strcmp ("primary", p) == 0)
20497 : : kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
20498 : 193 : else if (strcmp ("master", p) == 0)
20499 : : kind = OMP_CLAUSE_PROC_BIND_MASTER;
20500 : 177 : else if (strcmp ("close", p) == 0)
20501 : : kind = OMP_CLAUSE_PROC_BIND_CLOSE;
20502 : 165 : else if (strcmp ("spread", p) == 0)
20503 : : kind = OMP_CLAUSE_PROC_BIND_SPREAD;
20504 : : else
20505 : 0 : goto invalid_kind;
20506 : : }
20507 : : else
20508 : 0 : goto invalid_kind;
20509 : :
20510 : 194 : check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind");
20511 : 194 : c_parser_consume_token (parser);
20512 : 194 : parens.skip_until_found_close (parser);
20513 : 194 : c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
20514 : 194 : OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
20515 : 194 : OMP_CLAUSE_CHAIN (c) = list;
20516 : 194 : return c;
20517 : :
20518 : 0 : invalid_kind:
20519 : 0 : c_parser_error (parser, "invalid proc_bind kind");
20520 : 0 : parens.skip_until_found_close (parser);
20521 : 0 : return list;
20522 : : }
20523 : :
20524 : : /* OpenMP 5.0:
20525 : : device_type ( host | nohost | any ) */
20526 : :
20527 : : static tree
20528 : 42 : c_parser_omp_clause_device_type (c_parser *parser, tree list)
20529 : : {
20530 : 42 : location_t clause_loc = c_parser_peek_token (parser)->location;
20531 : 42 : enum omp_clause_device_type_kind kind;
20532 : 42 : tree c;
20533 : :
20534 : 42 : matching_parens parens;
20535 : 42 : if (!parens.require_open (parser))
20536 : : return list;
20537 : :
20538 : 42 : if (c_parser_next_token_is (parser, CPP_NAME))
20539 : : {
20540 : 42 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20541 : 42 : if (strcmp ("host", p) == 0)
20542 : : kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
20543 : 26 : else if (strcmp ("nohost", p) == 0)
20544 : : kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
20545 : 17 : else if (strcmp ("any", p) == 0)
20546 : : kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
20547 : : else
20548 : 0 : goto invalid_kind;
20549 : : }
20550 : : else
20551 : 0 : goto invalid_kind;
20552 : :
20553 : 42 : check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
20554 : : "device_type");
20555 : 42 : c_parser_consume_token (parser);
20556 : 42 : parens.skip_until_found_close (parser);
20557 : 42 : c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
20558 : 42 : OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
20559 : 42 : OMP_CLAUSE_CHAIN (c) = list;
20560 : 42 : return c;
20561 : :
20562 : 0 : invalid_kind:
20563 : 0 : c_parser_error (parser, "expected %<host%>, %<nohost%> or %<any%>");
20564 : 0 : parens.skip_until_found_close (parser);
20565 : 0 : return list;
20566 : : }
20567 : :
20568 : : /* OpenMP 4.0:
20569 : : from ( variable-list )
20570 : : to ( variable-list )
20571 : :
20572 : : OpenMP 5.1:
20573 : : from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
20574 : : to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
20575 : :
20576 : : motion-modifier:
20577 : : present | iterator (iterators-definition) */
20578 : :
20579 : : static tree
20580 : 2842 : c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
20581 : : tree list)
20582 : : {
20583 : 2842 : location_t loc = c_parser_peek_token (parser)->location;
20584 : 2842 : matching_parens parens;
20585 : 2842 : if (!parens.require_open (parser))
20586 : : return list;
20587 : :
20588 : 5676 : int pos = 1, colon_pos = 0;
20589 : : int iterator_length = 0;
20590 : :
20591 : 5676 : while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
20592 : : {
20593 : 2850 : const char *identifier =
20594 : 2850 : IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
20595 : 2850 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
20596 : : == CPP_OPEN_PAREN)
20597 : : {
20598 : 12 : unsigned int npos = pos + 2;
20599 : 12 : if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
20600 : 12 : && (c_parser_peek_nth_token_raw (parser, npos)->type
20601 : : == CPP_CLOSE_PAREN))
20602 : : {
20603 : 12 : if (strcmp (identifier, "iterator") == 0)
20604 : 12 : iterator_length = npos - pos + 1;
20605 : 12 : pos = npos;
20606 : : }
20607 : : }
20608 : 2850 : if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
20609 : 8 : pos += 2;
20610 : : else
20611 : : pos++;
20612 : 2850 : if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
20613 : : {
20614 : : colon_pos = pos;
20615 : : break;
20616 : : }
20617 : : }
20618 : :
20619 : 2842 : bool present = false;
20620 : 2842 : tree iterators = NULL_TREE;
20621 : :
20622 : 2862 : for (int pos = 1; pos < colon_pos; ++pos)
20623 : : {
20624 : 22 : c_token *token = c_parser_peek_token (parser);
20625 : 22 : if (token->type == CPP_COMMA)
20626 : : {
20627 : 3 : c_parser_consume_token (parser);
20628 : 3 : continue;
20629 : : }
20630 : 19 : const char *p = IDENTIFIER_POINTER (token->value);
20631 : 19 : if (strcmp ("present", p) == 0)
20632 : : {
20633 : 6 : if (present)
20634 : : {
20635 : 0 : c_parser_error (parser, "too many %<present%> modifiers");
20636 : 0 : parens.skip_until_found_close (parser);
20637 : 0 : return list;
20638 : : }
20639 : 6 : present = true;
20640 : 6 : c_parser_consume_token (parser);
20641 : : }
20642 : 13 : else if (strcmp ("iterator", p) == 0)
20643 : : {
20644 : 12 : if (iterators)
20645 : : {
20646 : 1 : c_parser_error (parser, "too many %<iterator%> modifiers");
20647 : 1 : parens.skip_until_found_close (parser);
20648 : 1 : return list;
20649 : : }
20650 : 11 : iterators = c_parser_omp_iterators (parser);
20651 : 11 : pos += iterator_length - 1;
20652 : : }
20653 : : else
20654 : : {
20655 : 2 : error_at (token->location,
20656 : : "%qs clause with modifier other than %<iterator%> or "
20657 : : "%<present%>",
20658 : : kind == OMP_CLAUSE_TO ? "to" : "from");
20659 : 1 : parens.skip_until_found_close (parser);
20660 : 1 : return list;
20661 : : }
20662 : : }
20663 : :
20664 : 2840 : if (colon_pos)
20665 : 14 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
20666 : :
20667 : 2840 : tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
20668 : 2840 : parens.skip_until_found_close (parser);
20669 : :
20670 : 2840 : if (present)
20671 : 12 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20672 : 6 : OMP_CLAUSE_MOTION_PRESENT (c) = 1;
20673 : :
20674 : 2840 : if (iterators)
20675 : : {
20676 : 9 : tree block = pop_scope ();
20677 : 9 : if (iterators == error_mark_node)
20678 : : iterators = NULL_TREE;
20679 : : else
20680 : 9 : TREE_VEC_ELT (iterators, 5) = block;
20681 : : }
20682 : :
20683 : 9 : if (iterators)
20684 : 22 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20685 : 13 : OMP_CLAUSE_ITERATORS (c) = iterators;
20686 : :
20687 : : return nl;
20688 : : }
20689 : :
20690 : : /* OpenMP 4.0:
20691 : : uniform ( variable-list ) */
20692 : :
20693 : : static tree
20694 : 115 : c_parser_omp_clause_uniform (c_parser *parser, tree list)
20695 : : {
20696 : : /* The clauses location. */
20697 : 115 : location_t loc = c_parser_peek_token (parser)->location;
20698 : :
20699 : 115 : matching_parens parens;
20700 : 115 : if (parens.require_open (parser))
20701 : : {
20702 : 115 : list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
20703 : : list);
20704 : 115 : parens.skip_until_found_close (parser);
20705 : : }
20706 : 115 : return list;
20707 : : }
20708 : :
20709 : : /* OpenMP 5.1
20710 : : full */
20711 : :
20712 : : static tree
20713 : 69 : c_parser_omp_clause_full (c_parser *parser, tree list)
20714 : : {
20715 : 69 : check_no_duplicate_clause (list, OMP_CLAUSE_FULL, "full");
20716 : :
20717 : 69 : location_t loc = c_parser_peek_token (parser)->location;
20718 : 69 : tree c = build_omp_clause (loc, OMP_CLAUSE_FULL);
20719 : 69 : OMP_CLAUSE_CHAIN (c) = list;
20720 : 69 : return c;
20721 : : }
20722 : :
20723 : : /* OpenMP 5.1
20724 : : partial ( constant-expression ) */
20725 : :
20726 : : static tree
20727 : 230 : c_parser_omp_clause_partial (c_parser *parser, tree list)
20728 : : {
20729 : 230 : tree num = NULL_TREE;
20730 : 230 : location_t loc = c_parser_peek_token (parser)->location;
20731 : :
20732 : 230 : check_no_duplicate_clause (list, OMP_CLAUSE_PARTIAL, "partial");
20733 : :
20734 : 230 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
20735 : : {
20736 : 173 : matching_parens parens;
20737 : 173 : parens.consume_open (parser);
20738 : 173 : num = c_parser_expr_no_commas (parser, NULL).value;
20739 : 173 : parens.skip_until_found_close (parser);
20740 : :
20741 : 173 : if (num == error_mark_node)
20742 : 7 : return list;
20743 : :
20744 : 171 : mark_exp_read (num);
20745 : 171 : num = c_fully_fold (num, false, NULL);
20746 : 171 : HOST_WIDE_INT n;
20747 : 342 : if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
20748 : 170 : || !tree_fits_shwi_p (num)
20749 : 168 : || (n = tree_to_shwi (num)) <= 0
20750 : 337 : || (int) n != n)
20751 : : {
20752 : 5 : error_at (loc, "%<partial%> argument needs positive constant "
20753 : : "integer expression");
20754 : 5 : return list;
20755 : : }
20756 : : }
20757 : :
20758 : 223 : tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL);
20759 : 223 : OMP_CLAUSE_PARTIAL_EXPR (c) = num;
20760 : 223 : OMP_CLAUSE_CHAIN (c) = list;
20761 : 223 : return c;
20762 : : }
20763 : :
20764 : : /* OpenMP 5.1
20765 : : novariants ( scalar-expression ) */
20766 : :
20767 : : static tree
20768 : 21 : c_parser_omp_clause_novariants (c_parser *parser, tree list)
20769 : : {
20770 : 21 : matching_parens parens;
20771 : 21 : if (!parens.require_open (parser))
20772 : : return list;
20773 : :
20774 : 21 : location_t loc = c_parser_peek_token (parser)->location;
20775 : 21 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20776 : 21 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20777 : 21 : t = c_objc_common_truthvalue_conversion (loc, t);
20778 : 21 : t = c_fully_fold (t, false, NULL);
20779 : 21 : parens.skip_until_found_close (parser);
20780 : :
20781 : 21 : check_no_duplicate_clause (list, OMP_CLAUSE_NOVARIANTS, "novariants");
20782 : :
20783 : 21 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
20784 : 21 : OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
20785 : 21 : OMP_CLAUSE_CHAIN (c) = list;
20786 : 21 : list = c;
20787 : :
20788 : 21 : return list;
20789 : : }
20790 : :
20791 : : /* OpenMP 5.1
20792 : : nocontext ( scalar-expression ) */
20793 : :
20794 : : static tree
20795 : 23 : c_parser_omp_clause_nocontext (c_parser *parser, tree list)
20796 : : {
20797 : 23 : matching_parens parens;
20798 : 23 : if (!parens.require_open (parser))
20799 : : return list;
20800 : :
20801 : 23 : location_t loc = c_parser_peek_token (parser)->location;
20802 : 23 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
20803 : 23 : tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20804 : 23 : t = c_objc_common_truthvalue_conversion (loc, t);
20805 : 23 : t = c_fully_fold (t, false, NULL);
20806 : 23 : parens.skip_until_found_close (parser);
20807 : :
20808 : 23 : check_no_duplicate_clause (list, OMP_CLAUSE_NOCONTEXT, "nocontext");
20809 : :
20810 : 23 : tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
20811 : 23 : OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
20812 : 23 : OMP_CLAUSE_CHAIN (c) = list;
20813 : 23 : list = c;
20814 : :
20815 : 23 : return list;
20816 : : }
20817 : :
20818 : : /* OpenMP 5.0:
20819 : : detach ( event-handle ) */
20820 : :
20821 : : static tree
20822 : 34 : c_parser_omp_clause_detach (c_parser *parser, tree list)
20823 : : {
20824 : 34 : matching_parens parens;
20825 : 34 : location_t clause_loc = c_parser_peek_token (parser)->location;
20826 : :
20827 : 34 : if (!parens.require_open (parser))
20828 : : return list;
20829 : :
20830 : 34 : if (c_parser_next_token_is_not (parser, CPP_NAME)
20831 : 34 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
20832 : : {
20833 : 1 : c_parser_error (parser, "expected identifier");
20834 : 1 : parens.skip_until_found_close (parser);
20835 : 1 : return list;
20836 : : }
20837 : :
20838 : 33 : tree t = lookup_name (c_parser_peek_token (parser)->value);
20839 : 33 : if (t == NULL_TREE)
20840 : : {
20841 : 0 : undeclared_variable (c_parser_peek_token (parser)->location,
20842 : 0 : c_parser_peek_token (parser)->value);
20843 : 0 : parens.skip_until_found_close (parser);
20844 : 0 : return list;
20845 : : }
20846 : 33 : c_parser_consume_token (parser);
20847 : :
20848 : 33 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
20849 : 33 : if (!INTEGRAL_TYPE_P (type)
20850 : : || TREE_CODE (type) != ENUMERAL_TYPE
20851 : 33 : || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
20852 : : {
20853 : 1 : error_at (clause_loc, "%<detach%> clause event handle "
20854 : : "has type %qT rather than "
20855 : : "%<omp_event_handle_t%>",
20856 : : type);
20857 : 1 : parens.skip_until_found_close (parser);
20858 : 1 : return list;
20859 : : }
20860 : :
20861 : 32 : tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
20862 : 32 : OMP_CLAUSE_DECL (u) = t;
20863 : 32 : OMP_CLAUSE_CHAIN (u) = list;
20864 : 32 : parens.skip_until_found_close (parser);
20865 : 32 : return u;
20866 : : }
20867 : :
20868 : : /* OpenMP 5.0:
20869 : : destroy ( variable-list ) */
20870 : :
20871 : : static tree
20872 : 41 : c_parser_omp_clause_destroy (c_parser *parser, tree list)
20873 : : {
20874 : 41 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_DESTROY, list);
20875 : 86 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20876 : 45 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
20877 : 41 : return nl;
20878 : : }
20879 : :
20880 : : /* OpenMP 5.1:
20881 : : prefer_type ( const-int-expr-or-string-literal-list )
20882 : :
20883 : : OpenMP 6.0:
20884 : : prefer_type ( { preference-selector-list }, { ... } )
20885 : :
20886 : : with preference-selector being:
20887 : : fr ( identifier-or-string-literal-list )
20888 : : attr ( string-list )
20889 : :
20890 : : Data format:
20891 : : For the foreign runtime identifiers, string values are converted to
20892 : : their integer value; unknown string or integer values are set to
20893 : : GOMP_INTEROP_IFR_KNOWN.
20894 : :
20895 : : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
20896 : : (b) for any 'fr', its integer value.
20897 : : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
20898 : : (c) GOMP_INTEROP_IFR_SEPARATOR
20899 : : (d) list of \0-terminated non-empty strings for 'attr'
20900 : : (e) '\0'
20901 : : Tailing '\0'. */
20902 : :
20903 : : static tree
20904 : 125 : c_parser_omp_modifier_prefer_type (c_parser *parser)
20905 : : {
20906 : 125 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
20907 : 2 : return error_mark_node;
20908 : :
20909 : 123 : std::string str;
20910 : :
20911 : : /* Old Format: const-int-expr-or-string-literal-list */
20912 : 123 : if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
20913 : 240 : while (true)
20914 : : {
20915 : 150 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20916 : 150 : if (c_parser_next_token_is (parser, CPP_STRING))
20917 : : {
20918 : 117 : c_expr cval = c_parser_string_literal (parser, false, false);
20919 : 117 : if (cval.value == error_mark_node)
20920 : 1 : return error_mark_node;
20921 : 117 : if ((size_t) TREE_STRING_LENGTH (cval.value)
20922 : 117 : != strlen (TREE_STRING_POINTER (cval.value)) + 1)
20923 : : {
20924 : 1 : error_at (cval.get_location (), "string literal must "
20925 : : "not contain %<\\0%>");
20926 : 1 : parser->error = true;
20927 : 1 : return error_mark_node;
20928 : : }
20929 : :
20930 : 116 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (cval.value));
20931 : 116 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
20932 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
20933 : : "unknown foreign runtime identifier %qs",
20934 : 3 : TREE_STRING_POINTER (cval.value));
20935 : 116 : str += c;
20936 : : }
20937 : : else
20938 : : {
20939 : 33 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
20940 : 33 : tree value = c_fully_fold (cval.value, false, NULL);
20941 : 64 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
20942 : 61 : && TREE_CODE (value) != INTEGER_CST)
20943 : 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
20944 : : false, true).value;
20945 : 33 : if (TREE_CODE (value) != INTEGER_CST
20946 : 28 : || !tree_fits_shwi_p (value))
20947 : : {
20948 : 5 : c_parser_error (parser, "expected string literal or constant "
20949 : : "integer expression");
20950 : 5 : return error_mark_node;
20951 : : }
20952 : 28 : HOST_WIDE_INT n = tree_to_shwi (value);
20953 : 28 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
20954 : : {
20955 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
20956 : : "unknown foreign runtime identifier %qwd", n);
20957 : 3 : n = GOMP_INTEROP_IFR_UNKNOWN;
20958 : : }
20959 : 28 : str += (char) n;
20960 : : }
20961 : 144 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20962 : 144 : str += '\0';
20963 : 144 : if (c_parser_next_token_is (parser, CPP_COMMA))
20964 : : {
20965 : 90 : c_parser_consume_token (parser);
20966 : 90 : continue;
20967 : : }
20968 : 54 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
20969 : : "expected %<,%> or %<)%>"))
20970 : 0 : return error_mark_node;
20971 : 54 : str += '\0';
20972 : 54 : tree res = build_string (str.length (), str.data ());
20973 : 54 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
20974 : 54 : str.length ());
20975 : 54 : return res;
20976 : 90 : }
20977 : :
20978 : : /* New format. */
20979 : 63 : std::string str2;
20980 : 128 : while (true)
20981 : : {
20982 : 128 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
20983 : 1 : return error_mark_node;
20984 : 127 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20985 : 127 : str2.clear ();
20986 : 127 : bool has_fr = false;
20987 : 205 : while (true)
20988 : : {
20989 : 166 : c_token *tok = c_parser_peek_token (parser);
20990 : 166 : if (tok->type != CPP_NAME
20991 : 166 : || (strcmp("fr", IDENTIFIER_POINTER (tok->value)) != 0
20992 : 63 : && strcmp("attr", IDENTIFIER_POINTER (tok->value)) != 0))
20993 : : {
20994 : 0 : c_parser_error (parser, "expected %<fr%> or %<attr%> preference "
20995 : : "selector");
20996 : 0 : return error_mark_node;
20997 : : }
20998 : 166 : c_parser_consume_token (parser);
20999 : 166 : bool is_fr = IDENTIFIER_POINTER (tok->value)[0] == 'f';
21000 : 166 : if (is_fr && has_fr)
21001 : : {
21002 : 1 : c_parser_error (parser, "duplicated %<fr%> preference selector");
21003 : 1 : return error_mark_node;
21004 : : }
21005 : 165 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
21006 : 0 : return error_mark_node;
21007 : 175 : while (true)
21008 : : {
21009 : 170 : if (c_parser_next_token_is (parser, CPP_STRING))
21010 : : {
21011 : 133 : c_expr cval = c_parser_string_literal (parser, false, false);
21012 : 133 : tree value = cval.value;
21013 : 133 : if (value == error_mark_node)
21014 : 6 : return error_mark_node;
21015 : 133 : if ((size_t) TREE_STRING_LENGTH (value)
21016 : 133 : != strlen (TREE_STRING_POINTER (value)) + 1)
21017 : : {
21018 : 2 : error_at (cval.get_location (), "string literal must "
21019 : : "not contain %<\\0%>");
21020 : 2 : parser->error = true;
21021 : 2 : return error_mark_node;
21022 : : }
21023 : 131 : if (!is_fr)
21024 : : {
21025 : 67 : if (!startswith (TREE_STRING_POINTER (value), "ompx_"))
21026 : : {
21027 : 1 : error_at (cval.get_location (),
21028 : : "%<attr%> string literal must start with "
21029 : : "%<ompx_%>");
21030 : 1 : parser->error = true;
21031 : 1 : return error_mark_node;
21032 : : }
21033 : 66 : if (strchr (TREE_STRING_POINTER (value), ','))
21034 : : {
21035 : 2 : error_at (cval.get_location (),
21036 : : "%<attr%> string literal must not contain "
21037 : : "a comma");
21038 : 2 : parser->error = true;
21039 : 2 : return error_mark_node;
21040 : : }
21041 : 64 : str2 += TREE_STRING_POINTER (value);
21042 : 64 : str2 += '\0';
21043 : : }
21044 : : else
21045 : : {
21046 : 64 : if (*TREE_STRING_POINTER (value) == '\0')
21047 : : {
21048 : 1 : c_parser_error (parser, "non-empty string literal expected");
21049 : 1 : return error_mark_node;
21050 : : }
21051 : 63 : char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (value));
21052 : 63 : if (c == GOMP_INTEROP_IFR_UNKNOWN)
21053 : 3 : warning_at (cval.get_location (), OPT_Wopenmp,
21054 : : "unknown foreign runtime identifier %qs",
21055 : 3 : TREE_STRING_POINTER (value));
21056 : 63 : str += c;
21057 : 63 : has_fr = true;
21058 : : }
21059 : : }
21060 : 37 : else if (!is_fr)
21061 : : {
21062 : 1 : c_parser_error (parser, "expected string literal");
21063 : 1 : return error_mark_node;
21064 : : }
21065 : : else
21066 : : {
21067 : 36 : c_expr cval = c_parser_expr_no_commas (parser, NULL);
21068 : 36 : tree value = c_fully_fold (cval.value, false, NULL);
21069 : 70 : if (INTEGRAL_TYPE_P (TREE_TYPE (value))
21070 : 68 : && TREE_CODE (value) != INTEGER_CST)
21071 : 3 : value = convert_lvalue_to_rvalue (cval.get_start (), cval,
21072 : : false, true).value;
21073 : :
21074 : 36 : if (TREE_CODE (value) != INTEGER_CST
21075 : 32 : || !tree_fits_shwi_p (value))
21076 : : {
21077 : 4 : c_parser_error (parser, "expected string literal or "
21078 : : "constant integer expression");
21079 : 4 : return error_mark_node;
21080 : : }
21081 : 32 : HOST_WIDE_INT n = tree_to_shwi (value);
21082 : 32 : if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
21083 : : {
21084 : 0 : warning_at (cval.get_location (), OPT_Wopenmp,
21085 : : "unknown foreign runtime identifier %qwd", n);
21086 : 0 : n = GOMP_INTEROP_IFR_UNKNOWN;
21087 : : }
21088 : 32 : str += (char) n;
21089 : 32 : has_fr = true;
21090 : : }
21091 : 164 : if (!is_fr
21092 : 223 : && c_parser_next_token_is (parser, CPP_COMMA))
21093 : : {
21094 : 5 : c_parser_consume_token (parser);
21095 : 5 : continue;
21096 : : }
21097 : 213 : if (!c_parser_require (parser, CPP_CLOSE_PAREN,
21098 : : is_fr ? G_("expected %<)%>")
21099 : : : G_("expected %<)%> or %<,%>")))
21100 : 4 : return error_mark_node;
21101 : 150 : break;
21102 : 5 : }
21103 : 150 : if (c_parser_next_token_is (parser, CPP_COMMA))
21104 : : {
21105 : 39 : c_parser_consume_token (parser);
21106 : 39 : continue;
21107 : : }
21108 : 111 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
21109 : : break;
21110 : 2 : c_parser_error (parser, "expected %<,%> or %<}%>");
21111 : 2 : return error_mark_node;
21112 : 39 : }
21113 : 109 : str += (char) GOMP_INTEROP_IFR_SEPARATOR;
21114 : 109 : str += str2;
21115 : 109 : str += '\0';
21116 : 109 : c_parser_consume_token (parser);
21117 : 109 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
21118 : : break;
21119 : 66 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
21120 : 1 : return error_mark_node;
21121 : : }
21122 : 43 : c_parser_consume_token (parser);
21123 : 43 : str += '\0';
21124 : 43 : tree res = build_string (str.length (), str.data ());
21125 : 43 : TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
21126 : 43 : str.length ());
21127 : 43 : return res;
21128 : 186 : }
21129 : :
21130 : : /* OpenMP 5.1
21131 : : modifiers of the 'init' clause, used by the 'init' and the
21132 : : 'append_args' clauses.
21133 : :
21134 : : Modifiers:
21135 : : target
21136 : : targetsync
21137 : : prefer_type (preference-specification)
21138 : :
21139 : : Returns 'false' if an error has been issued. */
21140 : :
21141 : : static bool
21142 : 234 : c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target,
21143 : : bool *targetsync, tree *prefer_type_tree)
21144 : : {
21145 : 234 : *target = false;
21146 : 234 : *targetsync = false;
21147 : 234 : *prefer_type_tree = NULL_TREE;
21148 : :
21149 : 540 : do
21150 : : {
21151 : 387 : c_token *tok = c_parser_peek_token (parser);
21152 : 387 : if (tok->type != CPP_NAME)
21153 : 1 : goto fail;
21154 : 386 : const char *p = IDENTIFIER_POINTER (tok->value);
21155 : 386 : if (strcmp ("targetsync", p) == 0)
21156 : : {
21157 : 105 : if (*targetsync)
21158 : 1 : error_at (tok->location, "duplicate %<targetsync%> modifier");
21159 : 105 : *targetsync = true;
21160 : 105 : c_parser_consume_token (parser);
21161 : : }
21162 : 281 : else if (strcmp ("target", p) == 0)
21163 : : {
21164 : 148 : if (*target)
21165 : 3 : error_at (tok->location, "duplicate %<target%> modifier");
21166 : 148 : *target = true;
21167 : 148 : c_parser_consume_token (parser);
21168 : : }
21169 : 133 : else if (strcmp ("prefer_type", p) == 0)
21170 : : {
21171 : 125 : if (*prefer_type_tree != NULL_TREE)
21172 : 1 : error_at (tok->location, "duplicate %<prefer_type%> modifier");
21173 : 125 : c_parser_consume_token (parser);
21174 : 125 : *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser);
21175 : 125 : if (*prefer_type_tree == error_mark_node)
21176 : : return false;
21177 : : }
21178 : : else
21179 : 8 : goto fail;
21180 : 350 : tok = c_parser_peek_token (parser);
21181 : 350 : if (tok->type == CPP_COMMA)
21182 : : {
21183 : 153 : c_parser_consume_token (parser);
21184 : 153 : continue;
21185 : : }
21186 : : /* Unknown token - either done or an error; handle it in the caller. */
21187 : : return true;
21188 : 153 : }
21189 : : while (true);
21190 : :
21191 : 9 : fail:
21192 : 9 : c_parser_error (parser,
21193 : : "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
21194 : 9 : return false;
21195 : : }
21196 : :
21197 : : /* OpenMP 5.1:
21198 : : init ( [init-modifier-list : ] variable-list )
21199 : :
21200 : : Modifiers:
21201 : : target
21202 : : targetsync
21203 : : prefer_type (preference-specification) */
21204 : :
21205 : : static tree
21206 : 167 : c_parser_omp_clause_init (c_parser *parser, tree list)
21207 : : {
21208 : 167 : location_t loc = c_parser_peek_token (parser)->location;
21209 : :
21210 : 167 : matching_parens parens;
21211 : 167 : if (!parens.require_open (parser))
21212 : : return list;
21213 : :
21214 : 167 : bool target = false;
21215 : 167 : bool targetsync = false;
21216 : 167 : tree prefer_type_tree = NULL_TREE;
21217 : :
21218 : 167 : if (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
21219 : : &prefer_type_tree)
21220 : 167 : || !c_parser_require (parser, CPP_COLON, "expected %<:%>"))
21221 : : {
21222 : 39 : if (prefer_type_tree != error_mark_node)
21223 : 11 : parens.skip_until_found_close (parser);
21224 : 39 : return list;
21225 : : }
21226 : :
21227 : 128 : if (!target && !targetsync)
21228 : 2 : error_at (loc,
21229 : : "missing required %<target%> and/or %<targetsync%> modifier");
21230 : :
21231 : 128 : tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list,
21232 : : false);
21233 : 128 : parens.skip_until_found_close (parser);
21234 : :
21235 : 280 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21236 : : {
21237 : 152 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21238 : 152 : if (target)
21239 : 90 : OMP_CLAUSE_INIT_TARGET (c) = 1;
21240 : 152 : if (targetsync)
21241 : 81 : OMP_CLAUSE_INIT_TARGETSYNC (c) = 1;
21242 : 152 : if (prefer_type_tree)
21243 : 73 : OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree;
21244 : : }
21245 : : return nl;
21246 : : }
21247 : :
21248 : : /* OpenMP 5.0:
21249 : : use ( variable-list ) */
21250 : :
21251 : : static tree
21252 : 43 : c_parser_omp_clause_use (c_parser *parser, tree list)
21253 : : {
21254 : 0 : return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE, list);
21255 : : }
21256 : :
21257 : : /* OpenMP 6.0:
21258 : : interop ( variable-list ) */
21259 : :
21260 : : static tree
21261 : 43 : c_parser_omp_clause_interop (c_parser *parser, tree list)
21262 : : {
21263 : 43 : check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop");
21264 : 43 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list);
21265 : 102 : for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21266 : : {
21267 : 59 : TREE_USED (OMP_CLAUSE_DECL (c)) = 1;
21268 : 59 : DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1;
21269 : : }
21270 : 43 : return nl;
21271 : : }
21272 : :
21273 : : /* Parse all OpenACC clauses. The set clauses allowed by the directive
21274 : : is a bitmask in MASK. Return the list of clauses found. */
21275 : :
21276 : : static tree
21277 : 5352 : c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
21278 : : const char *where, bool finish_p = true,
21279 : : bool target_p = false)
21280 : : {
21281 : 5352 : tree clauses = NULL;
21282 : 5352 : bool first = true;
21283 : :
21284 : 12071 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
21285 : : {
21286 : 6765 : location_t here;
21287 : 6765 : pragma_omp_clause c_kind;
21288 : 6765 : const char *c_name;
21289 : 6765 : tree prev = clauses;
21290 : :
21291 : 9375 : if (!first && c_parser_next_token_is (parser, CPP_COMMA))
21292 : 11 : c_parser_consume_token (parser);
21293 : :
21294 : 6765 : here = c_parser_peek_token (parser)->location;
21295 : 6765 : c_kind = c_parser_omp_clause_name (parser);
21296 : :
21297 : 6765 : switch (c_kind)
21298 : : {
21299 : 240 : case PRAGMA_OACC_CLAUSE_ASYNC:
21300 : 240 : clauses = c_parser_oacc_clause_async (parser, clauses);
21301 : 240 : c_name = "async";
21302 : 240 : break;
21303 : 125 : case PRAGMA_OACC_CLAUSE_AUTO:
21304 : 125 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
21305 : : clauses);
21306 : 125 : c_name = "auto";
21307 : 125 : break;
21308 : 27 : case PRAGMA_OACC_CLAUSE_ATTACH:
21309 : 27 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21310 : 27 : c_name = "attach";
21311 : 27 : break;
21312 : 59 : case PRAGMA_OACC_CLAUSE_COLLAPSE:
21313 : 59 : clauses = c_parser_omp_clause_collapse (parser, clauses);
21314 : 59 : c_name = "collapse";
21315 : 59 : break;
21316 : 806 : case PRAGMA_OACC_CLAUSE_COPY:
21317 : 806 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21318 : 806 : c_name = "copy";
21319 : 806 : break;
21320 : 359 : case PRAGMA_OACC_CLAUSE_COPYIN:
21321 : 359 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21322 : 359 : c_name = "copyin";
21323 : 359 : break;
21324 : 390 : case PRAGMA_OACC_CLAUSE_COPYOUT:
21325 : 390 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21326 : 390 : c_name = "copyout";
21327 : 390 : break;
21328 : 94 : case PRAGMA_OACC_CLAUSE_CREATE:
21329 : 94 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21330 : 94 : c_name = "create";
21331 : 94 : break;
21332 : 68 : case PRAGMA_OACC_CLAUSE_DELETE:
21333 : 68 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21334 : 68 : c_name = "delete";
21335 : 68 : break;
21336 : 88 : case PRAGMA_OMP_CLAUSE_DEFAULT:
21337 : 88 : clauses = c_parser_omp_clause_default (parser, clauses, true);
21338 : 88 : c_name = "default";
21339 : 88 : break;
21340 : 20 : case PRAGMA_OACC_CLAUSE_DETACH:
21341 : 20 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21342 : 20 : c_name = "detach";
21343 : 20 : break;
21344 : 36 : case PRAGMA_OACC_CLAUSE_DEVICE:
21345 : 36 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21346 : 36 : c_name = "device";
21347 : 36 : break;
21348 : 57 : case PRAGMA_OACC_CLAUSE_DEVICEPTR:
21349 : 57 : clauses = c_parser_oacc_data_clause_deviceptr (parser, clauses);
21350 : 57 : c_name = "deviceptr";
21351 : 57 : break;
21352 : 16 : case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
21353 : 16 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21354 : 16 : c_name = "device_resident";
21355 : 16 : break;
21356 : 12 : case PRAGMA_OACC_CLAUSE_FINALIZE:
21357 : 12 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
21358 : : clauses);
21359 : 12 : c_name = "finalize";
21360 : 12 : break;
21361 : 113 : case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
21362 : 113 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
21363 : 113 : c_name = "firstprivate";
21364 : 113 : break;
21365 : 589 : case PRAGMA_OACC_CLAUSE_GANG:
21366 : 589 : c_name = "gang";
21367 : 589 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
21368 : : c_name, clauses);
21369 : 589 : break;
21370 : 41 : case PRAGMA_OACC_CLAUSE_HOST:
21371 : 41 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21372 : 41 : c_name = "host";
21373 : 41 : break;
21374 : 105 : case PRAGMA_OACC_CLAUSE_IF:
21375 : 105 : clauses = c_parser_omp_clause_if (parser, clauses, false);
21376 : 105 : c_name = "if";
21377 : 105 : break;
21378 : 19 : case PRAGMA_OACC_CLAUSE_IF_PRESENT:
21379 : 19 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
21380 : : clauses);
21381 : 19 : c_name = "if_present";
21382 : 19 : break;
21383 : 45 : case PRAGMA_OACC_CLAUSE_INDEPENDENT:
21384 : 45 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
21385 : : clauses);
21386 : 45 : c_name = "independent";
21387 : 45 : break;
21388 : 13 : case PRAGMA_OACC_CLAUSE_LINK:
21389 : 13 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21390 : 13 : c_name = "link";
21391 : 13 : break;
21392 : 10 : case PRAGMA_OACC_CLAUSE_NO_CREATE:
21393 : 10 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21394 : 10 : c_name = "no_create";
21395 : 10 : break;
21396 : 25 : case PRAGMA_OACC_CLAUSE_NOHOST:
21397 : 25 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST,
21398 : : clauses);
21399 : 25 : c_name = "nohost";
21400 : 25 : break;
21401 : 302 : case PRAGMA_OACC_CLAUSE_NUM_GANGS:
21402 : 302 : clauses = c_parser_oacc_single_int_clause (parser,
21403 : : OMP_CLAUSE_NUM_GANGS,
21404 : : clauses);
21405 : 302 : c_name = "num_gangs";
21406 : 302 : break;
21407 : 207 : case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
21408 : 207 : clauses = c_parser_oacc_single_int_clause (parser,
21409 : : OMP_CLAUSE_NUM_WORKERS,
21410 : : clauses);
21411 : 207 : c_name = "num_workers";
21412 : 207 : break;
21413 : 128 : case PRAGMA_OACC_CLAUSE_PRESENT:
21414 : 128 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21415 : 128 : c_name = "present";
21416 : 128 : break;
21417 : 66 : case PRAGMA_OACC_CLAUSE_PRIVATE:
21418 : 66 : clauses = c_parser_omp_clause_private (parser, clauses);
21419 : 66 : c_name = "private";
21420 : 66 : break;
21421 : 905 : case PRAGMA_OACC_CLAUSE_REDUCTION:
21422 : 905 : clauses
21423 : 905 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
21424 : : false, clauses);
21425 : 905 : c_name = "reduction";
21426 : 905 : break;
21427 : 66 : case PRAGMA_OACC_CLAUSE_SELF:
21428 : 66 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
21429 : : /* OpenACC compute construct */
21430 : 48 : clauses = c_parser_oacc_compute_clause_self (parser, clauses);
21431 : : else
21432 : : /* OpenACC 'update' directive */
21433 : 18 : clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
21434 : : c_name = "self";
21435 : : break;
21436 : 261 : case PRAGMA_OACC_CLAUSE_SEQ:
21437 : 261 : clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
21438 : : clauses);
21439 : 261 : c_name = "seq";
21440 : 261 : break;
21441 : 123 : case PRAGMA_OACC_CLAUSE_TILE:
21442 : 123 : clauses = c_parser_oacc_clause_tile (parser, clauses);
21443 : 123 : c_name = "tile";
21444 : 123 : break;
21445 : 21 : case PRAGMA_OACC_CLAUSE_USE_DEVICE:
21446 : 21 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
21447 : 21 : c_name = "use_device";
21448 : 21 : break;
21449 : 518 : case PRAGMA_OACC_CLAUSE_VECTOR:
21450 : 518 : c_name = "vector";
21451 : 518 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_VECTOR,
21452 : : c_name, clauses);
21453 : 518 : break;
21454 : 223 : case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
21455 : 223 : clauses = c_parser_oacc_single_int_clause (parser,
21456 : : OMP_CLAUSE_VECTOR_LENGTH,
21457 : : clauses);
21458 : 223 : c_name = "vector_length";
21459 : 223 : break;
21460 : 89 : case PRAGMA_OACC_CLAUSE_WAIT:
21461 : 89 : clauses = c_parser_oacc_clause_wait (parser, clauses);
21462 : 89 : c_name = "wait";
21463 : 89 : break;
21464 : 453 : case PRAGMA_OACC_CLAUSE_WORKER:
21465 : 453 : c_name = "worker";
21466 : 453 : clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_WORKER,
21467 : : c_name, clauses);
21468 : 453 : break;
21469 : 46 : default:
21470 : 46 : c_parser_error (parser, "expected an OpenACC clause");
21471 : 46 : goto saw_error;
21472 : : }
21473 : :
21474 : 6719 : first = false;
21475 : :
21476 : 6719 : if (((mask >> c_kind) & 1) == 0)
21477 : : {
21478 : : /* Remove the invalid clause(s) from the list to avoid
21479 : : confusing the rest of the compiler. */
21480 : 18 : clauses = prev;
21481 : 18 : error_at (here, "%qs is not valid for %qs", c_name, where);
21482 : : }
21483 : : }
21484 : :
21485 : 5306 : saw_error:
21486 : 5352 : c_parser_skip_to_pragma_eol (parser);
21487 : :
21488 : 5352 : if (finish_p)
21489 : 7831 : return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
21490 : 4656 : : C_ORT_ACC);
21491 : :
21492 : : return clauses;
21493 : : }
21494 : :
21495 : : /* Parse all OpenMP clauses. The set clauses allowed by the directive
21496 : : is a bitmask in MASK. Return the list of clauses found.
21497 : : FINISH_P set if c_finish_omp_clauses should be called.
21498 : : NESTED non-zero if clauses should be terminated by closing paren instead
21499 : : of end of pragma. If it is 2, additionally commas are required in between
21500 : : the clauses. */
21501 : :
21502 : : static tree
21503 : 19910 : c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
21504 : : const char *where, bool finish_p = true,
21505 : : int nested = 0)
21506 : : {
21507 : 19910 : tree clauses = NULL;
21508 : 19910 : bool first = true;
21509 : :
21510 : 47096 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
21511 : : {
21512 : 27271 : location_t here;
21513 : 27271 : pragma_omp_clause c_kind;
21514 : 27271 : const char *c_name;
21515 : 27271 : tree prev = clauses;
21516 : :
21517 : 27368 : if (nested && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
21518 : : break;
21519 : :
21520 : 27249 : if (!first || nested != 2)
21521 : : {
21522 : 27226 : if (c_parser_next_token_is (parser, CPP_COMMA))
21523 : 2693 : c_parser_consume_token (parser);
21524 : 24533 : else if (nested == 2)
21525 : 3 : error_at (c_parser_peek_token (parser)->location,
21526 : : "clauses in %<simd%> trait should be separated "
21527 : : "by %<,%>");
21528 : : }
21529 : :
21530 : 27249 : here = c_parser_peek_token (parser)->location;
21531 : 27249 : c_kind = c_parser_omp_clause_name (parser);
21532 : :
21533 : 27249 : switch (c_kind)
21534 : : {
21535 : 115 : case PRAGMA_OMP_CLAUSE_BIND:
21536 : 115 : clauses = c_parser_omp_clause_bind (parser, clauses);
21537 : 115 : c_name = "bind";
21538 : 115 : break;
21539 : 2887 : case PRAGMA_OMP_CLAUSE_COLLAPSE:
21540 : 2887 : clauses = c_parser_omp_clause_collapse (parser, clauses);
21541 : 2887 : c_name = "collapse";
21542 : 2887 : break;
21543 : 101 : case PRAGMA_OMP_CLAUSE_COPYIN:
21544 : 101 : clauses = c_parser_omp_clause_copyin (parser, clauses);
21545 : 101 : c_name = "copyin";
21546 : 101 : break;
21547 : 21 : case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
21548 : 21 : clauses = c_parser_omp_clause_copyprivate (parser, clauses);
21549 : 21 : c_name = "copyprivate";
21550 : 21 : break;
21551 : 640 : case PRAGMA_OMP_CLAUSE_DEFAULT:
21552 : 640 : clauses = c_parser_omp_clause_default (parser, clauses, false);
21553 : 640 : c_name = "default";
21554 : 640 : break;
21555 : 34 : case PRAGMA_OMP_CLAUSE_DETACH:
21556 : 34 : clauses = c_parser_omp_clause_detach (parser, clauses);
21557 : 34 : c_name = "detach";
21558 : 34 : break;
21559 : 62 : case PRAGMA_OMP_CLAUSE_FILTER:
21560 : 62 : clauses = c_parser_omp_clause_filter (parser, clauses);
21561 : 62 : c_name = "filter";
21562 : 62 : break;
21563 : 664 : case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
21564 : 664 : clauses = c_parser_omp_clause_firstprivate (parser, clauses);
21565 : 664 : c_name = "firstprivate";
21566 : 664 : break;
21567 : 98 : case PRAGMA_OMP_CLAUSE_FINAL:
21568 : 98 : clauses = c_parser_omp_clause_final (parser, clauses);
21569 : 98 : c_name = "final";
21570 : 98 : break;
21571 : 62 : case PRAGMA_OMP_CLAUSE_GRAINSIZE:
21572 : 62 : clauses = c_parser_omp_clause_grainsize (parser, clauses);
21573 : 62 : c_name = "grainsize";
21574 : 62 : break;
21575 : 29 : case PRAGMA_OMP_CLAUSE_HINT:
21576 : 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
21577 : 29 : c_name = "hint";
21578 : 29 : break;
21579 : 239 : case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
21580 : 239 : clauses = c_parser_omp_clause_defaultmap (parser, clauses);
21581 : 239 : c_name = "defaultmap";
21582 : 239 : break;
21583 : 778 : case PRAGMA_OMP_CLAUSE_IF:
21584 : 778 : clauses = c_parser_omp_clause_if (parser, clauses, true);
21585 : 778 : c_name = "if";
21586 : 778 : break;
21587 : 320 : case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
21588 : 320 : clauses
21589 : 320 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
21590 : : true, clauses);
21591 : 320 : c_name = "in_reduction";
21592 : 320 : break;
21593 : 26 : case PRAGMA_OMP_CLAUSE_INDIRECT:
21594 : 26 : clauses = c_parser_omp_clause_indirect (parser, clauses);
21595 : 26 : c_name = "indirect";
21596 : 26 : break;
21597 : 731 : case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
21598 : 731 : clauses = c_parser_omp_clause_lastprivate (parser, clauses);
21599 : 731 : c_name = "lastprivate";
21600 : 731 : break;
21601 : 78 : case PRAGMA_OMP_CLAUSE_MERGEABLE:
21602 : 78 : clauses = c_parser_omp_clause_mergeable (parser, clauses);
21603 : 78 : c_name = "mergeable";
21604 : 78 : break;
21605 : 391 : case PRAGMA_OMP_CLAUSE_NOWAIT:
21606 : 391 : clauses = c_parser_omp_clause_nowait (parser, clauses);
21607 : 391 : c_name = "nowait";
21608 : 391 : break;
21609 : 49 : case PRAGMA_OMP_CLAUSE_NUM_TASKS:
21610 : 49 : clauses = c_parser_omp_clause_num_tasks (parser, clauses);
21611 : 49 : c_name = "num_tasks";
21612 : 49 : break;
21613 : 424 : case PRAGMA_OMP_CLAUSE_NUM_THREADS:
21614 : 424 : clauses = c_parser_omp_clause_num_threads (parser, clauses);
21615 : 424 : c_name = "num_threads";
21616 : 424 : break;
21617 : 375 : case PRAGMA_OMP_CLAUSE_ORDER:
21618 : 375 : clauses = c_parser_omp_clause_order (parser, clauses);
21619 : 375 : c_name = "order";
21620 : 375 : break;
21621 : 309 : case PRAGMA_OMP_CLAUSE_ORDERED:
21622 : 309 : clauses = c_parser_omp_clause_ordered (parser, clauses);
21623 : 309 : c_name = "ordered";
21624 : 309 : break;
21625 : 97 : case PRAGMA_OMP_CLAUSE_PRIORITY:
21626 : 97 : clauses = c_parser_omp_clause_priority (parser, clauses);
21627 : 97 : c_name = "priority";
21628 : 97 : break;
21629 : 669 : case PRAGMA_OMP_CLAUSE_PRIVATE:
21630 : 669 : clauses = c_parser_omp_clause_private (parser, clauses);
21631 : 669 : c_name = "private";
21632 : 669 : break;
21633 : 1778 : case PRAGMA_OMP_CLAUSE_REDUCTION:
21634 : 1778 : clauses
21635 : 1778 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
21636 : : true, clauses);
21637 : 1778 : c_name = "reduction";
21638 : 1778 : break;
21639 : 3467 : case PRAGMA_OMP_CLAUSE_SCHEDULE:
21640 : 3467 : clauses = c_parser_omp_clause_schedule (parser, clauses);
21641 : 3467 : c_name = "schedule";
21642 : 3467 : break;
21643 : 689 : case PRAGMA_OMP_CLAUSE_SHARED:
21644 : 689 : clauses = c_parser_omp_clause_shared (parser, clauses);
21645 : 689 : c_name = "shared";
21646 : 689 : break;
21647 : 86 : case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
21648 : 86 : clauses
21649 : 86 : = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
21650 : : true, clauses);
21651 : 86 : c_name = "task_reduction";
21652 : 86 : break;
21653 : 96 : case PRAGMA_OMP_CLAUSE_UNTIED:
21654 : 96 : clauses = c_parser_omp_clause_untied (parser, clauses);
21655 : 96 : c_name = "untied";
21656 : 96 : break;
21657 : 63 : case PRAGMA_OMP_CLAUSE_INBRANCH:
21658 : 63 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
21659 : : clauses);
21660 : 63 : c_name = "inbranch";
21661 : 63 : break;
21662 : 121 : case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
21663 : 121 : clauses = c_parser_omp_clause_nontemporal (parser, clauses);
21664 : 121 : c_name = "nontemporal";
21665 : 121 : break;
21666 : 136 : case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
21667 : 136 : clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH,
21668 : : clauses);
21669 : 136 : c_name = "notinbranch";
21670 : 136 : break;
21671 : 107 : case PRAGMA_OMP_CLAUSE_PARALLEL:
21672 : 107 : clauses
21673 : 107 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
21674 : : clauses);
21675 : 107 : c_name = "parallel";
21676 : 107 : if (!first)
21677 : : {
21678 : 0 : clause_not_first:
21679 : 0 : error_at (here, "%qs must be the first clause of %qs",
21680 : : c_name, where);
21681 : 0 : clauses = prev;
21682 : : }
21683 : : break;
21684 : 84 : case PRAGMA_OMP_CLAUSE_FOR:
21685 : 84 : clauses
21686 : 84 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
21687 : : clauses);
21688 : 84 : c_name = "for";
21689 : 84 : if (!first)
21690 : 0 : goto clause_not_first;
21691 : : break;
21692 : 78 : case PRAGMA_OMP_CLAUSE_SECTIONS:
21693 : 78 : clauses
21694 : 78 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
21695 : : clauses);
21696 : 78 : c_name = "sections";
21697 : 78 : if (!first)
21698 : 0 : goto clause_not_first;
21699 : : break;
21700 : 110 : case PRAGMA_OMP_CLAUSE_TASKGROUP:
21701 : 110 : clauses
21702 : 110 : = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
21703 : : clauses);
21704 : 110 : c_name = "taskgroup";
21705 : 110 : if (!first)
21706 : 0 : goto clause_not_first;
21707 : : break;
21708 : 32 : case PRAGMA_OMP_CLAUSE_LINK:
21709 : 32 : clauses
21710 : 32 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LINK, clauses);
21711 : 32 : c_name = "link";
21712 : 32 : break;
21713 : 475 : case PRAGMA_OMP_CLAUSE_TO:
21714 : 475 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
21715 : : {
21716 : 83 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
21717 : : clauses);
21718 : 185 : for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
21719 : 102 : OMP_CLAUSE_ENTER_TO (c) = 1;
21720 : : clauses = nl;
21721 : : }
21722 : : else
21723 : 392 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_TO,
21724 : : clauses);
21725 : : c_name = "to";
21726 : : break;
21727 : 2450 : case PRAGMA_OMP_CLAUSE_FROM:
21728 : 2450 : clauses = c_parser_omp_clause_from_to (parser, OMP_CLAUSE_FROM,
21729 : : clauses);
21730 : 2450 : c_name = "from";
21731 : 2450 : break;
21732 : 115 : case PRAGMA_OMP_CLAUSE_UNIFORM:
21733 : 115 : clauses = c_parser_omp_clause_uniform (parser, clauses);
21734 : 115 : c_name = "uniform";
21735 : 115 : break;
21736 : 195 : case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
21737 : 195 : clauses = c_parser_omp_clause_num_teams (parser, clauses);
21738 : 195 : c_name = "num_teams";
21739 : 195 : break;
21740 : 154 : case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
21741 : 154 : clauses = c_parser_omp_clause_thread_limit (parser, clauses);
21742 : 154 : c_name = "thread_limit";
21743 : 154 : break;
21744 : 228 : case PRAGMA_OMP_CLAUSE_ALIGNED:
21745 : 228 : clauses = c_parser_omp_clause_aligned (parser, clauses);
21746 : 228 : c_name = "aligned";
21747 : 228 : break;
21748 : 467 : case PRAGMA_OMP_CLAUSE_ALLOCATE:
21749 : 467 : clauses = c_parser_omp_clause_allocate (parser, clauses);
21750 : 467 : c_name = "allocate";
21751 : 467 : break;
21752 : 474 : case PRAGMA_OMP_CLAUSE_LINEAR:
21753 : 474 : clauses = c_parser_omp_clause_linear (parser, clauses);
21754 : 474 : c_name = "linear";
21755 : 474 : break;
21756 : 146 : case PRAGMA_OMP_CLAUSE_AFFINITY:
21757 : 146 : clauses = c_parser_omp_clause_affinity (parser, clauses);
21758 : 146 : c_name = "affinity";
21759 : 146 : break;
21760 : 855 : case PRAGMA_OMP_CLAUSE_DEPEND:
21761 : 855 : clauses = c_parser_omp_clause_depend (parser, clauses);
21762 : 855 : c_name = "depend";
21763 : 855 : break;
21764 : 145 : case PRAGMA_OMP_CLAUSE_DOACROSS:
21765 : 145 : clauses = c_parser_omp_clause_doacross (parser, clauses);
21766 : 145 : c_name = "doacross";
21767 : 145 : break;
21768 : 41 : case PRAGMA_OMP_CLAUSE_DESTROY:
21769 : 41 : clauses = c_parser_omp_clause_destroy (parser, clauses);
21770 : 41 : c_name = "destroy";
21771 : 41 : break;
21772 : 167 : case PRAGMA_OMP_CLAUSE_INIT:
21773 : 167 : clauses = c_parser_omp_clause_init (parser, clauses);
21774 : 167 : c_name = "init";
21775 : 167 : break;
21776 : 43 : case PRAGMA_OMP_CLAUSE_USE:
21777 : 43 : clauses = c_parser_omp_clause_use (parser, clauses);
21778 : 43 : c_name = "use";
21779 : 43 : break;
21780 : 43 : case PRAGMA_OMP_CLAUSE_INTEROP:
21781 : 43 : clauses = c_parser_omp_clause_interop (parser, clauses);
21782 : 43 : c_name = "interop";
21783 : 43 : break;
21784 : 1662 : case PRAGMA_OMP_CLAUSE_MAP:
21785 : 1662 : clauses = c_parser_omp_clause_map (parser, clauses, false);
21786 : 1662 : c_name = "map";
21787 : 1662 : break;
21788 : 10 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
21789 : 10 : clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
21790 : 10 : c_name = "use_device_ptr";
21791 : 10 : break;
21792 : 35 : case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
21793 : 35 : clauses = c_parser_omp_clause_use_device_addr (parser, clauses);
21794 : 35 : c_name = "use_device_addr";
21795 : 35 : break;
21796 : 87 : case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
21797 : 87 : clauses = c_parser_omp_clause_has_device_addr (parser, clauses);
21798 : 87 : c_name = "has_device_addr";
21799 : 87 : break;
21800 : 114 : case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
21801 : 114 : clauses = c_parser_omp_clause_is_device_ptr (parser, clauses);
21802 : 114 : c_name = "is_device_ptr";
21803 : 114 : break;
21804 : 367 : case PRAGMA_OMP_CLAUSE_DEVICE:
21805 : 367 : clauses = c_parser_omp_clause_device (parser, clauses);
21806 : 367 : c_name = "device";
21807 : 367 : break;
21808 : 1582 : case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
21809 : 1582 : clauses = c_parser_omp_clause_dist_schedule (parser, clauses);
21810 : 1582 : c_name = "dist_schedule";
21811 : 1582 : break;
21812 : 194 : case PRAGMA_OMP_CLAUSE_PROC_BIND:
21813 : 194 : clauses = c_parser_omp_clause_proc_bind (parser, clauses);
21814 : 194 : c_name = "proc_bind";
21815 : 194 : break;
21816 : 42 : case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
21817 : 42 : clauses = c_parser_omp_clause_device_type (parser, clauses);
21818 : 42 : c_name = "device_type";
21819 : 42 : break;
21820 : 227 : case PRAGMA_OMP_CLAUSE_SAFELEN:
21821 : 227 : clauses = c_parser_omp_clause_safelen (parser, clauses);
21822 : 227 : c_name = "safelen";
21823 : 227 : break;
21824 : 317 : case PRAGMA_OMP_CLAUSE_SIMDLEN:
21825 : 317 : clauses = c_parser_omp_clause_simdlen (parser, clauses);
21826 : 317 : c_name = "simdlen";
21827 : 317 : break;
21828 : 18 : case PRAGMA_OMP_CLAUSE_NOGROUP:
21829 : 18 : clauses = c_parser_omp_clause_nogroup (parser, clauses);
21830 : 18 : c_name = "nogroup";
21831 : 18 : break;
21832 : 46 : case PRAGMA_OMP_CLAUSE_THREADS:
21833 : 46 : clauses
21834 : 46 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS,
21835 : : clauses);
21836 : 46 : c_name = "threads";
21837 : 46 : break;
21838 : 57 : case PRAGMA_OMP_CLAUSE_SIMD:
21839 : 57 : clauses
21840 : 57 : = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD,
21841 : : clauses);
21842 : 57 : c_name = "simd";
21843 : 57 : break;
21844 : 41 : case PRAGMA_OMP_CLAUSE_ENTER:
21845 : 41 : clauses
21846 : 41 : = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
21847 : : clauses);
21848 : 41 : c_name = "enter";
21849 : 41 : break;
21850 : 69 : case PRAGMA_OMP_CLAUSE_FULL:
21851 : 69 : c_name = "full";
21852 : 69 : clauses = c_parser_omp_clause_full (parser, clauses);
21853 : 69 : break;
21854 : 230 : case PRAGMA_OMP_CLAUSE_PARTIAL:
21855 : 230 : c_name = "partial";
21856 : 230 : clauses = c_parser_omp_clause_partial (parser, clauses);
21857 : 230 : break;
21858 : 21 : case PRAGMA_OMP_CLAUSE_NOVARIANTS:
21859 : 21 : c_name = "novariants";
21860 : 21 : clauses = c_parser_omp_clause_novariants (parser, clauses);
21861 : 21 : break;
21862 : 23 : case PRAGMA_OMP_CLAUSE_NOCONTEXT:
21863 : 23 : c_name = "nocontext";
21864 : 23 : clauses = c_parser_omp_clause_nocontext (parser, clauses);
21865 : 23 : break;
21866 : 63 : default:
21867 : 63 : c_parser_error (parser, "expected an OpenMP clause");
21868 : 63 : goto saw_error;
21869 : : }
21870 : :
21871 : 27186 : first = false;
21872 : :
21873 : 27186 : if (((mask >> c_kind) & 1) == 0)
21874 : : {
21875 : : /* Remove the invalid clause(s) from the list to avoid
21876 : : confusing the rest of the compiler. */
21877 : 24 : clauses = prev;
21878 : 24 : error_at (here, "%qs is not valid for %qs", c_name, where);
21879 : : }
21880 : : }
21881 : :
21882 : 19825 : saw_error:
21883 : 19910 : if (!nested)
21884 : 19887 : c_parser_skip_to_pragma_eol (parser);
21885 : :
21886 : 19910 : if (finish_p)
21887 : : {
21888 : 11357 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
21889 : 386 : return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
21890 : 10971 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE)) != 0)
21891 : 183 : return c_finish_omp_clauses (clauses, C_ORT_OMP_INTEROP);
21892 : 10788 : return c_finish_omp_clauses (clauses, C_ORT_OMP);
21893 : : }
21894 : :
21895 : : return clauses;
21896 : : }
21897 : :
21898 : : /* OpenACC 2.0, OpenMP 2.5:
21899 : : structured-block:
21900 : : statement
21901 : :
21902 : : In practice, we're also interested in adding the statement to an
21903 : : outer node. So it is convenient if we work around the fact that
21904 : : c_parser_statement calls add_stmt. */
21905 : :
21906 : : static tree
21907 : 6545 : c_parser_omp_structured_block (c_parser *parser, bool *if_p)
21908 : : {
21909 : 6545 : tree stmt = push_stmt_list ();
21910 : 6545 : parser->omp_attrs_forbidden_p = true;
21911 : 6545 : c_parser_statement (parser, if_p);
21912 : 6545 : return pop_stmt_list (stmt);
21913 : : }
21914 : :
21915 : : /* OpenACC 2.0:
21916 : : # pragma acc cache (variable-list) new-line
21917 : :
21918 : : OpenACC 2.7:
21919 : : # pragma acc cache (readonly: variable-list) new-line
21920 : :
21921 : : LOC is the location of the #pragma token.
21922 : : */
21923 : :
21924 : : static tree
21925 : 137 : c_parser_oacc_cache (location_t loc, c_parser *parser)
21926 : : {
21927 : 137 : tree stmt, clauses = NULL_TREE;
21928 : 137 : bool readonly = false;
21929 : 137 : location_t open_loc = c_parser_peek_token (parser)->location;
21930 : 137 : matching_parens parens;
21931 : 137 : if (parens.require_open (parser))
21932 : : {
21933 : 135 : c_token *token = c_parser_peek_token (parser);
21934 : 135 : if (token->type == CPP_NAME
21935 : 131 : && !strcmp (IDENTIFIER_POINTER (token->value), "readonly")
21936 : 139 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
21937 : : {
21938 : 4 : c_parser_consume_token (parser);
21939 : 4 : c_parser_consume_token (parser);
21940 : 4 : readonly = true;
21941 : : }
21942 : 135 : clauses = c_parser_omp_variable_list (parser, open_loc,
21943 : : OMP_CLAUSE__CACHE_, NULL_TREE);
21944 : 135 : parens.skip_until_found_close (parser);
21945 : : }
21946 : :
21947 : 135 : if (readonly)
21948 : 8 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
21949 : 4 : OMP_CLAUSE__CACHE__READONLY (c) = 1;
21950 : :
21951 : 137 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
21952 : :
21953 : 137 : c_parser_skip_to_pragma_eol (parser);
21954 : :
21955 : 137 : stmt = make_node (OACC_CACHE);
21956 : 137 : TREE_TYPE (stmt) = void_type_node;
21957 : 137 : OACC_CACHE_CLAUSES (stmt) = clauses;
21958 : 137 : SET_EXPR_LOCATION (stmt, loc);
21959 : 137 : add_stmt (stmt);
21960 : :
21961 : 137 : return stmt;
21962 : : }
21963 : :
21964 : : /* OpenACC 2.0:
21965 : : # pragma acc data oacc-data-clause[optseq] new-line
21966 : : structured-block
21967 : :
21968 : : LOC is the location of the #pragma token.
21969 : : */
21970 : :
21971 : : #define OACC_DATA_CLAUSE_MASK \
21972 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
21973 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
21974 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
21975 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
21976 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
21977 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
21978 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
21979 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
21980 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
21981 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
21982 : :
21983 : : static tree
21984 : 497 : c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
21985 : : {
21986 : 497 : tree stmt, clauses, block;
21987 : :
21988 : 497 : clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
21989 : : "#pragma acc data");
21990 : :
21991 : 497 : block = c_begin_omp_parallel ();
21992 : 497 : add_stmt (c_parser_omp_structured_block (parser, if_p));
21993 : :
21994 : 497 : stmt = c_finish_oacc_data (loc, clauses, block);
21995 : :
21996 : 497 : return stmt;
21997 : : }
21998 : :
21999 : : /* OpenACC 2.0:
22000 : : # pragma acc declare oacc-data-clause[optseq] new-line
22001 : : */
22002 : :
22003 : : #define OACC_DECLARE_CLAUSE_MASK \
22004 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22005 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22006 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22007 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22008 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22009 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
22010 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
22011 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
22012 : :
22013 : : static void
22014 : 144 : c_parser_oacc_declare (c_parser *parser)
22015 : : {
22016 : 144 : location_t pragma_loc = c_parser_peek_token (parser)->location;
22017 : 144 : tree clauses, stmt, t, decl;
22018 : :
22019 : 144 : bool error = false;
22020 : :
22021 : 144 : c_parser_consume_pragma (parser);
22022 : :
22023 : 144 : clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
22024 : : "#pragma acc declare");
22025 : 144 : if (!clauses)
22026 : : {
22027 : 2 : error_at (pragma_loc,
22028 : : "no valid clauses specified in %<#pragma acc declare%>");
22029 : 2 : return;
22030 : : }
22031 : :
22032 : 296 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
22033 : : {
22034 : 154 : location_t loc = OMP_CLAUSE_LOCATION (t);
22035 : 154 : decl = OMP_CLAUSE_DECL (t);
22036 : 154 : if (!DECL_P (decl))
22037 : : {
22038 : 1 : error_at (loc, "array section in %<#pragma acc declare%>");
22039 : 1 : error = true;
22040 : 1 : continue;
22041 : : }
22042 : :
22043 : 153 : switch (OMP_CLAUSE_MAP_KIND (t))
22044 : : {
22045 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
22046 : : case GOMP_MAP_ALLOC:
22047 : : case GOMP_MAP_TO:
22048 : : case GOMP_MAP_FORCE_DEVICEPTR:
22049 : : case GOMP_MAP_DEVICE_RESIDENT:
22050 : : break;
22051 : :
22052 : 13 : case GOMP_MAP_LINK:
22053 : 13 : if (!global_bindings_p ()
22054 : 13 : && (TREE_STATIC (decl)
22055 : 6 : || !DECL_EXTERNAL (decl)))
22056 : : {
22057 : 2 : error_at (loc,
22058 : : "%qD must be a global variable in "
22059 : : "%<#pragma acc declare link%>",
22060 : : decl);
22061 : 2 : error = true;
22062 : 2 : continue;
22063 : : }
22064 : : break;
22065 : :
22066 : 42 : default:
22067 : 42 : if (global_bindings_p ())
22068 : : {
22069 : 5 : error_at (loc, "invalid OpenACC clause at file scope");
22070 : 5 : error = true;
22071 : 5 : continue;
22072 : : }
22073 : 37 : if (DECL_EXTERNAL (decl))
22074 : : {
22075 : 10 : error_at (loc,
22076 : : "invalid use of %<extern%> variable %qD "
22077 : : "in %<#pragma acc declare%>", decl);
22078 : 10 : error = true;
22079 : 10 : continue;
22080 : : }
22081 : 27 : else if (TREE_PUBLIC (decl))
22082 : : {
22083 : 2 : error_at (loc,
22084 : : "invalid use of %<global%> variable %qD "
22085 : : "in %<#pragma acc declare%>", decl);
22086 : 2 : error = true;
22087 : 2 : continue;
22088 : : }
22089 : : break;
22090 : : }
22091 : :
22092 : 134 : if (!c_check_in_current_scope (decl))
22093 : : {
22094 : 2 : error_at (loc,
22095 : : "%qD must be a variable declared in the same scope as "
22096 : : "%<#pragma acc declare%>", decl);
22097 : 2 : error = true;
22098 : 2 : continue;
22099 : : }
22100 : :
22101 : 132 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
22102 : 250 : || lookup_attribute ("omp declare target link",
22103 : 118 : DECL_ATTRIBUTES (decl)))
22104 : : {
22105 : 17 : error_at (loc, "variable %qD used more than once with "
22106 : : "%<#pragma acc declare%>", decl);
22107 : 17 : error = true;
22108 : 17 : continue;
22109 : : }
22110 : :
22111 : 115 : if (!error)
22112 : : {
22113 : 115 : tree id;
22114 : :
22115 : 115 : if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
22116 : 7 : id = get_identifier ("omp declare target link");
22117 : : else
22118 : 108 : id = get_identifier ("omp declare target");
22119 : :
22120 : 115 : DECL_ATTRIBUTES (decl)
22121 : 115 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
22122 : :
22123 : 115 : if (global_bindings_p ())
22124 : : {
22125 : 45 : symtab_node *node = symtab_node::get (decl);
22126 : 45 : if (node != NULL)
22127 : : {
22128 : 33 : node->offloadable = 1;
22129 : 33 : if (ENABLE_OFFLOADING)
22130 : : {
22131 : : g->have_offload = true;
22132 : : if (is_a <varpool_node *> (node))
22133 : : vec_safe_push (offload_vars, decl);
22134 : : }
22135 : : }
22136 : : }
22137 : : }
22138 : : }
22139 : :
22140 : 142 : if (error || global_bindings_p ())
22141 : 74 : return;
22142 : :
22143 : 68 : stmt = make_node (OACC_DECLARE);
22144 : 68 : TREE_TYPE (stmt) = void_type_node;
22145 : 68 : OACC_DECLARE_CLAUSES (stmt) = clauses;
22146 : 68 : SET_EXPR_LOCATION (stmt, pragma_loc);
22147 : :
22148 : 68 : add_stmt (stmt);
22149 : :
22150 : 68 : return;
22151 : : }
22152 : :
22153 : : /* OpenACC 2.0:
22154 : : # pragma acc enter data oacc-enter-data-clause[optseq] new-line
22155 : :
22156 : : or
22157 : :
22158 : : # pragma acc exit data oacc-exit-data-clause[optseq] new-line
22159 : :
22160 : :
22161 : : LOC is the location of the #pragma token.
22162 : : */
22163 : :
22164 : : #define OACC_ENTER_DATA_CLAUSE_MASK \
22165 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22166 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22167 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22168 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22169 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22170 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22171 : :
22172 : : #define OACC_EXIT_DATA_CLAUSE_MASK \
22173 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22174 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22175 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22176 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
22177 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
22178 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
22179 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22180 : :
22181 : : static void
22182 : 261 : c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
22183 : : {
22184 : 261 : location_t loc = c_parser_peek_token (parser)->location;
22185 : 261 : tree clauses, stmt;
22186 : 261 : const char *p = "";
22187 : :
22188 : 261 : c_parser_consume_pragma (parser);
22189 : :
22190 : 261 : if (c_parser_next_token_is (parser, CPP_NAME))
22191 : : {
22192 : 258 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22193 : 258 : c_parser_consume_token (parser);
22194 : : }
22195 : :
22196 : 261 : if (strcmp (p, "data") != 0)
22197 : : {
22198 : 8 : error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
22199 : : enter ? "enter" : "exit");
22200 : 6 : parser->error = true;
22201 : 6 : c_parser_skip_to_pragma_eol (parser);
22202 : 6 : return;
22203 : : }
22204 : :
22205 : 255 : if (enter)
22206 : 129 : clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
22207 : : "#pragma acc enter data");
22208 : : else
22209 : 126 : clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
22210 : : "#pragma acc exit data");
22211 : :
22212 : 255 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
22213 : : {
22214 : 15 : error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
22215 : : enter ? "enter" : "exit");
22216 : 15 : return;
22217 : : }
22218 : :
22219 : 240 : stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
22220 : 240 : TREE_TYPE (stmt) = void_type_node;
22221 : 240 : OMP_STANDALONE_CLAUSES (stmt) = clauses;
22222 : 240 : SET_EXPR_LOCATION (stmt, loc);
22223 : 240 : add_stmt (stmt);
22224 : : }
22225 : :
22226 : :
22227 : : /* OpenACC 2.0:
22228 : : # pragma acc host_data oacc-data-clause[optseq] new-line
22229 : : structured-block
22230 : : */
22231 : :
22232 : : #define OACC_HOST_DATA_CLAUSE_MASK \
22233 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
22234 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22235 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
22236 : :
22237 : : static tree
22238 : 23 : c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
22239 : : {
22240 : 23 : tree stmt, clauses, block;
22241 : :
22242 : 23 : clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
22243 : : "#pragma acc host_data", false);
22244 : 23 : if (!omp_find_clause (clauses, OMP_CLAUSE_USE_DEVICE_PTR))
22245 : : {
22246 : 2 : error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
22247 : 2 : return error_mark_node;
22248 : : }
22249 : 21 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22250 : 21 : block = c_begin_omp_parallel ();
22251 : 21 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22252 : 21 : stmt = c_finish_oacc_host_data (loc, clauses, block);
22253 : 21 : return stmt;
22254 : : }
22255 : :
22256 : :
22257 : : /* OpenACC 2.0:
22258 : :
22259 : : # pragma acc loop oacc-loop-clause[optseq] new-line
22260 : : structured-block
22261 : :
22262 : : LOC is the location of the #pragma token.
22263 : : */
22264 : :
22265 : : #define OACC_LOOP_CLAUSE_MASK \
22266 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
22267 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22268 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22269 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22270 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22271 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22272 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
22273 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
22274 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22275 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
22276 : : static tree
22277 : 2444 : c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
22278 : : omp_clause_mask mask, tree *cclauses, bool *if_p)
22279 : : {
22280 : 2444 : bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
22281 : :
22282 : 2444 : strcat (p_name, " loop");
22283 : 2444 : mask |= OACC_LOOP_CLAUSE_MASK;
22284 : :
22285 : 2444 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
22286 : : /*finish_p=*/cclauses == NULL,
22287 : : /*target=*/is_parallel);
22288 : 2444 : if (cclauses)
22289 : : {
22290 : 673 : clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
22291 : 673 : if (*cclauses)
22292 : 152 : *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
22293 : 673 : if (clauses)
22294 : 271 : clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22295 : : }
22296 : :
22297 : 2444 : tree block = c_begin_compound_stmt (true);
22298 : 2444 : tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
22299 : : if_p);
22300 : 2444 : block = c_end_compound_stmt (loc, block, true);
22301 : 2444 : add_stmt (block);
22302 : :
22303 : 2444 : return stmt;
22304 : : }
22305 : :
22306 : : /* OpenACC 2.0:
22307 : : # pragma acc kernels oacc-kernels-clause[optseq] new-line
22308 : : structured-block
22309 : :
22310 : : or
22311 : :
22312 : : # pragma acc parallel oacc-parallel-clause[optseq] new-line
22313 : : structured-block
22314 : :
22315 : : OpenACC 2.6:
22316 : :
22317 : : # pragma acc serial oacc-serial-clause[optseq] new-line
22318 : : structured-block
22319 : :
22320 : : LOC is the location of the #pragma token.
22321 : : */
22322 : :
22323 : : #define OACC_KERNELS_CLAUSE_MASK \
22324 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22325 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22326 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22327 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22328 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22329 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22330 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22331 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22332 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22333 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22334 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22335 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22336 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22337 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22338 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22339 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22340 : :
22341 : : #define OACC_PARALLEL_CLAUSE_MASK \
22342 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22343 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22344 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22345 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22346 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22347 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22348 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22349 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22350 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22351 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22352 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22353 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22354 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22355 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22356 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22357 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22358 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22359 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22360 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22361 : :
22362 : : #define OACC_SERIAL_CLAUSE_MASK \
22363 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22364 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22365 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22366 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22367 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22368 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22369 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22370 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22371 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22372 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22373 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22374 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22375 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22376 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22377 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22378 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22379 : :
22380 : : static tree
22381 : 2154 : c_parser_oacc_compute (location_t loc, c_parser *parser,
22382 : : enum pragma_kind p_kind, char *p_name, bool *if_p)
22383 : : {
22384 : 2154 : omp_clause_mask mask;
22385 : 2154 : enum tree_code code;
22386 : 2154 : switch (p_kind)
22387 : : {
22388 : 522 : case PRAGMA_OACC_KERNELS:
22389 : 522 : strcat (p_name, " kernels");
22390 : 522 : mask = OACC_KERNELS_CLAUSE_MASK;
22391 : 522 : code = OACC_KERNELS;
22392 : 522 : break;
22393 : 1457 : case PRAGMA_OACC_PARALLEL:
22394 : 1457 : strcat (p_name, " parallel");
22395 : 1457 : mask = OACC_PARALLEL_CLAUSE_MASK;
22396 : 1457 : code = OACC_PARALLEL;
22397 : 1457 : break;
22398 : 175 : case PRAGMA_OACC_SERIAL:
22399 : 175 : strcat (p_name, " serial");
22400 : 175 : mask = OACC_SERIAL_CLAUSE_MASK;
22401 : 175 : code = OACC_SERIAL;
22402 : 175 : break;
22403 : 0 : default:
22404 : 0 : gcc_unreachable ();
22405 : : }
22406 : :
22407 : 2154 : if (c_parser_next_token_is (parser, CPP_NAME))
22408 : : {
22409 : 1710 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22410 : 1710 : if (strcmp (p, "loop") == 0)
22411 : : {
22412 : 673 : c_parser_consume_token (parser);
22413 : 673 : tree block = c_begin_omp_parallel ();
22414 : 673 : tree clauses;
22415 : 673 : c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
22416 : 673 : return c_finish_omp_construct (loc, code, block, clauses);
22417 : : }
22418 : : }
22419 : :
22420 : 1481 : tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
22421 : : /*finish_p=*/true,
22422 : : /*target=*/true);
22423 : :
22424 : 1481 : tree block = c_begin_omp_parallel ();
22425 : 1481 : add_stmt (c_parser_omp_structured_block (parser, if_p));
22426 : :
22427 : 1481 : return c_finish_omp_construct (loc, code, block, clauses);
22428 : : }
22429 : :
22430 : : /* OpenACC 2.0:
22431 : : # pragma acc routine oacc-routine-clause[optseq] new-line
22432 : : function-definition
22433 : :
22434 : : # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
22435 : : */
22436 : :
22437 : : #define OACC_ROUTINE_CLAUSE_MASK \
22438 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22439 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22440 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22441 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22442 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
22443 : :
22444 : : /* Parse an OpenACC routine directive. For named directives, we apply
22445 : : immediately to the named function. For unnamed ones we then parse
22446 : : a declaration or definition, which must be for a function. */
22447 : :
22448 : : static void
22449 : 345 : c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
22450 : : {
22451 : 345 : gcc_checking_assert (context == pragma_external);
22452 : :
22453 : 345 : oacc_routine_data data;
22454 : 345 : data.error_seen = false;
22455 : 345 : data.fndecl_seen = false;
22456 : 345 : data.loc = c_parser_peek_token (parser)->location;
22457 : :
22458 : 345 : c_parser_consume_pragma (parser);
22459 : :
22460 : : /* Look for optional '( name )'. */
22461 : 345 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
22462 : : {
22463 : 143 : c_parser_consume_token (parser); /* '(' */
22464 : :
22465 : 143 : tree decl = NULL_TREE;
22466 : 143 : c_token *name_token = c_parser_peek_token (parser);
22467 : 143 : location_t name_loc = name_token->location;
22468 : 143 : if (name_token->type == CPP_NAME
22469 : 135 : && (name_token->id_kind == C_ID_ID
22470 : : || name_token->id_kind == C_ID_TYPENAME))
22471 : : {
22472 : 135 : decl = lookup_name (name_token->value);
22473 : 135 : if (!decl)
22474 : 5 : error_at (name_loc,
22475 : : "%qE has not been declared", name_token->value);
22476 : 135 : c_parser_consume_token (parser);
22477 : : }
22478 : : else
22479 : 8 : c_parser_error (parser, "expected function name");
22480 : :
22481 : 8 : if (!decl
22482 : 135 : || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
22483 : : {
22484 : 15 : c_parser_skip_to_pragma_eol (parser, false);
22485 : 43 : return;
22486 : : }
22487 : :
22488 : 128 : data.clauses
22489 : 128 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22490 : : "#pragma acc routine");
22491 : : /* The clauses are in reverse order; fix that to make later diagnostic
22492 : : emission easier. */
22493 : 128 : data.clauses = nreverse (data.clauses);
22494 : :
22495 : 128 : if (TREE_CODE (decl) != FUNCTION_DECL)
22496 : : {
22497 : 3 : error_at (name_loc, "%qD does not refer to a function", decl);
22498 : 3 : return;
22499 : : }
22500 : :
22501 : 125 : c_finish_oacc_routine (&data, decl, false);
22502 : : }
22503 : : else /* No optional '( name )'. */
22504 : : {
22505 : 202 : data.clauses
22506 : 202 : = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22507 : : "#pragma acc routine");
22508 : : /* The clauses are in reverse order; fix that to make later diagnostic
22509 : : emission easier. */
22510 : 202 : data.clauses = nreverse (data.clauses);
22511 : :
22512 : : /* Emit a helpful diagnostic if there's another pragma following this
22513 : : one. Also don't allow a static assertion declaration, as in the
22514 : : following we'll just parse a *single* "declaration or function
22515 : : definition", and the static assertion counts an one. */
22516 : 202 : if (c_parser_next_token_is (parser, CPP_PRAGMA)
22517 : 395 : || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
22518 : : {
22519 : 10 : error_at (data.loc,
22520 : : "%<#pragma acc routine%> not immediately followed by"
22521 : : " function declaration or definition");
22522 : : /* ..., and then just keep going. */
22523 : 10 : return;
22524 : : }
22525 : :
22526 : : /* We only have to consider the pragma_external case here. */
22527 : 192 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
22528 : 192 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
22529 : : {
22530 : 3 : int ext = disable_extension_diagnostics ();
22531 : 7 : do
22532 : 7 : c_parser_consume_token (parser);
22533 : 7 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
22534 : 10 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
22535 : 3 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
22536 : : false, NULL, NULL, false, NULL, &data);
22537 : 3 : restore_extension_diagnostics (ext);
22538 : : }
22539 : : else
22540 : 189 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
22541 : : false, NULL, NULL, false, NULL, &data);
22542 : : }
22543 : : }
22544 : :
22545 : : /* Finalize an OpenACC routine pragma, applying it to FNDECL.
22546 : : IS_DEFN is true if we're applying it to the definition. */
22547 : :
22548 : : static void
22549 : 327 : c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
22550 : : bool is_defn)
22551 : : {
22552 : : /* Keep going if we're in error reporting mode. */
22553 : 327 : if (data->error_seen
22554 : 321 : || fndecl == error_mark_node)
22555 : : return;
22556 : :
22557 : 321 : if (data->fndecl_seen)
22558 : : {
22559 : 4 : error_at (data->loc,
22560 : : "%<#pragma acc routine%> not immediately followed by"
22561 : : " a single function declaration or definition");
22562 : 4 : data->error_seen = true;
22563 : 4 : return;
22564 : : }
22565 : 317 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
22566 : : {
22567 : 10 : error_at (data->loc,
22568 : : "%<#pragma acc routine%> not immediately followed by"
22569 : : " function declaration or definition");
22570 : 10 : data->error_seen = true;
22571 : 10 : return;
22572 : : }
22573 : :
22574 : 307 : int compatible
22575 : 307 : = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
22576 : : "#pragma acc routine");
22577 : 307 : if (compatible < 0)
22578 : : {
22579 : 47 : data->error_seen = true;
22580 : 47 : return;
22581 : : }
22582 : 260 : if (compatible > 0)
22583 : : {
22584 : : }
22585 : : else
22586 : : {
22587 : 269 : if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
22588 : : {
22589 : 3 : error_at (data->loc,
22590 : : TREE_USED (fndecl)
22591 : : ? G_("%<#pragma acc routine%> must be applied before use")
22592 : : : G_("%<#pragma acc routine%> must be applied before"
22593 : : " definition"));
22594 : 2 : data->error_seen = true;
22595 : 2 : return;
22596 : : }
22597 : :
22598 : : /* Set the routine's level of parallelism. */
22599 : 197 : tree dims = oacc_build_routine_dims (data->clauses);
22600 : 197 : oacc_replace_fn_attrib (fndecl, dims);
22601 : :
22602 : : /* Add an "omp declare target" attribute. */
22603 : 197 : DECL_ATTRIBUTES (fndecl)
22604 : 394 : = tree_cons (get_identifier ("omp declare target"),
22605 : 197 : data->clauses, DECL_ATTRIBUTES (fndecl));
22606 : : }
22607 : :
22608 : : /* Remember that we've used this "#pragma acc routine". */
22609 : 258 : data->fndecl_seen = true;
22610 : : }
22611 : :
22612 : : /* OpenACC 2.0:
22613 : : # pragma acc update oacc-update-clause[optseq] new-line
22614 : : */
22615 : :
22616 : : #define OACC_UPDATE_CLAUSE_MASK \
22617 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22618 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
22619 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
22620 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22621 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
22622 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22623 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22624 : :
22625 : : static void
22626 : 92 : c_parser_oacc_update (c_parser *parser)
22627 : : {
22628 : 92 : location_t loc = c_parser_peek_token (parser)->location;
22629 : :
22630 : 92 : c_parser_consume_pragma (parser);
22631 : :
22632 : 92 : tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
22633 : : "#pragma acc update");
22634 : 92 : if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
22635 : : {
22636 : 1 : error_at (loc,
22637 : : "%<#pragma acc update%> must contain at least one "
22638 : : "%<device%> or %<host%> or %<self%> clause");
22639 : 1 : return;
22640 : : }
22641 : :
22642 : 91 : if (parser->error)
22643 : : return;
22644 : :
22645 : 91 : tree stmt = make_node (OACC_UPDATE);
22646 : 91 : TREE_TYPE (stmt) = void_type_node;
22647 : 91 : OACC_UPDATE_CLAUSES (stmt) = clauses;
22648 : 91 : SET_EXPR_LOCATION (stmt, loc);
22649 : 91 : add_stmt (stmt);
22650 : : }
22651 : :
22652 : : /* OpenACC 2.0:
22653 : : # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
22654 : :
22655 : : LOC is the location of the #pragma token.
22656 : : */
22657 : :
22658 : : #define OACC_WAIT_CLAUSE_MASK \
22659 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22660 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) )
22661 : :
22662 : : static tree
22663 : 86 : c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
22664 : : {
22665 : 86 : tree clauses, list = NULL_TREE, stmt = NULL_TREE;
22666 : :
22667 : 86 : if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
22668 : 49 : list = c_parser_oacc_wait_list (parser, loc, list);
22669 : :
22670 : 86 : strcpy (p_name, " wait");
22671 : 86 : clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, p_name);
22672 : 86 : stmt = c_finish_oacc_wait (loc, list, clauses);
22673 : 86 : add_stmt (stmt);
22674 : :
22675 : 86 : return stmt;
22676 : : }
22677 : :
22678 : : struct c_omp_loc_tree
22679 : : {
22680 : : location_t loc;
22681 : : tree var;
22682 : : };
22683 : :
22684 : : /* Check whether the expression used in the allocator clause is declared or
22685 : : modified between the variable declaration and its allocate directive. */
22686 : : static tree
22687 : 48 : c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
22688 : : {
22689 : 48 : tree var = ((struct c_omp_loc_tree *) data)->var;
22690 : 48 : location_t loc = ((struct c_omp_loc_tree *) data)->loc;
22691 : 48 : if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
22692 : : {
22693 : 10 : if (linemap_location_before_p (line_table, DECL_SOURCE_LOCATION (var),
22694 : 10 : DECL_SOURCE_LOCATION (*tp)))
22695 : : {
22696 : 2 : error_at (loc, "variable %qD used in the %<allocator%> clause must "
22697 : : "be declared before %qD", *tp, var);
22698 : 2 : inform (DECL_SOURCE_LOCATION (*tp), "declared here");
22699 : 2 : inform (DECL_SOURCE_LOCATION (var),
22700 : : "to be allocated variable declared here");
22701 : 2 : return *tp;
22702 : : }
22703 : : else
22704 : : {
22705 : 8 : gcc_assert (cur_stmt_list
22706 : : && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
22707 : :
22708 : 8 : tree_stmt_iterator l = tsi_last (cur_stmt_list);
22709 : 9 : while (!tsi_end_p (l))
22710 : : {
22711 : 9 : if (linemap_location_before_p (line_table, EXPR_LOCATION (*l),
22712 : 9 : DECL_SOURCE_LOCATION (var)))
22713 : : break;
22714 : 3 : if (TREE_CODE (*l) == MODIFY_EXPR
22715 : 3 : && TREE_OPERAND (*l, 0) == *tp)
22716 : : {
22717 : 2 : error_at (loc,
22718 : : "variable %qD used in the %<allocator%> clause "
22719 : : "must not be modified between declaration of %qD "
22720 : : "and its %<allocate%> directive", *tp, var);
22721 : 2 : inform (EXPR_LOCATION (*l), "modified here");
22722 : 2 : inform (DECL_SOURCE_LOCATION (var),
22723 : : "to be allocated variable declared here");
22724 : 2 : return *tp;
22725 : : }
22726 : 1 : --l;
22727 : : }
22728 : : }
22729 : : }
22730 : : return NULL_TREE;
22731 : : }
22732 : :
22733 : : /* OpenMP 5.x:
22734 : : # pragma omp allocate (list) clauses
22735 : :
22736 : : OpenMP 5.0 clause:
22737 : : allocator (omp_allocator_handle_t expression)
22738 : :
22739 : : OpenMP 5.1 additional clause:
22740 : : align (constant-expression)] */
22741 : :
22742 : : static void
22743 : 69 : c_parser_omp_allocate (c_parser *parser)
22744 : : {
22745 : 69 : tree alignment = NULL_TREE;
22746 : 69 : tree allocator = NULL_TREE;
22747 : 69 : c_parser_consume_pragma (parser);
22748 : 69 : location_t loc = c_parser_peek_token (parser)->location;
22749 : 69 : location_t allocator_loc = UNKNOWN_LOCATION;
22750 : 69 : tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
22751 : 215 : do
22752 : : {
22753 : 142 : if (c_parser_next_token_is (parser, CPP_COMMA)
22754 : 142 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22755 : 9 : c_parser_consume_token (parser);
22756 : 142 : if (!c_parser_next_token_is (parser, CPP_NAME))
22757 : : break;
22758 : 76 : matching_parens parens;
22759 : 76 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22760 : 76 : c_parser_consume_token (parser);
22761 : 76 : location_t expr_loc = c_parser_peek_token (parser)->location;
22762 : 76 : if (strcmp ("align", p) != 0 && strcmp ("allocator", p) != 0)
22763 : : {
22764 : 1 : error_at (c_parser_peek_token (parser)->location,
22765 : : "expected %<allocator%> or %<align%>");
22766 : 1 : break;
22767 : : }
22768 : 75 : if (!parens.require_open (parser))
22769 : : break;
22770 : :
22771 : 75 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
22772 : 75 : expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
22773 : 75 : expr_loc = c_parser_peek_token (parser)->location;
22774 : 75 : if (expr.value == error_mark_node)
22775 : : ;
22776 : 74 : else if (p[2] == 'i' && alignment)
22777 : : {
22778 : 1 : error_at (expr_loc, "too many %qs clauses", "align");
22779 : 1 : break;
22780 : : }
22781 : 73 : else if (p[2] == 'i')
22782 : : {
22783 : 32 : alignment = c_fully_fold (expr.value, false, NULL);
22784 : 32 : if (TREE_CODE (alignment) != INTEGER_CST
22785 : 31 : || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
22786 : 31 : || tree_int_cst_sgn (alignment) != 1
22787 : 62 : || !integer_pow2p (alignment))
22788 : : {
22789 : 4 : error_at (expr_loc, "%<align%> clause argument needs to be "
22790 : : "positive constant power of two integer "
22791 : : "expression");
22792 : 4 : alignment = NULL_TREE;
22793 : : }
22794 : : }
22795 : 41 : else if (allocator)
22796 : : {
22797 : 1 : error_at (expr_loc, "too many %qs clauses", "allocator");
22798 : 1 : break;
22799 : : }
22800 : : else
22801 : : {
22802 : 40 : allocator = c_fully_fold (expr.value, false, NULL);
22803 : 40 : allocator_loc = expr_loc;
22804 : 40 : tree orig_type
22805 : 40 : = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
22806 : 40 : orig_type = TYPE_MAIN_VARIANT (orig_type);
22807 : 41 : if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
22808 : 40 : || TREE_CODE (orig_type) != ENUMERAL_TYPE
22809 : 118 : || TYPE_NAME (orig_type)
22810 : 39 : != get_identifier ("omp_allocator_handle_t"))
22811 : : {
22812 : 1 : error_at (expr_loc,
22813 : : "%<allocator%> clause allocator expression has type "
22814 : : "%qT rather than %<omp_allocator_handle_t%>",
22815 : 1 : TREE_TYPE (allocator));
22816 : 1 : allocator = NULL_TREE;
22817 : : }
22818 : : }
22819 : 73 : parens.skip_until_found_close (parser);
22820 : 73 : } while (true);
22821 : 69 : c_parser_skip_to_pragma_eol (parser);
22822 : :
22823 : 69 : c_mark_decl_jump_unsafe_in_current_scope ();
22824 : 149 : for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
22825 : : {
22826 : 80 : tree var = OMP_CLAUSE_DECL (c);
22827 : 80 : if (TREE_CODE (var) == PARM_DECL)
22828 : : {
22829 : 1 : error_at (OMP_CLAUSE_LOCATION (nl),
22830 : : "function parameter %qD may not appear as list item in an "
22831 : : "%<allocate%> directive", var);
22832 : 1 : continue;
22833 : : }
22834 : 79 : if (!parser->in_omp_decl_attribute && !c_check_in_current_scope (var))
22835 : : {
22836 : 2 : error_at (OMP_CLAUSE_LOCATION (nl),
22837 : : "%<allocate%> directive must be in the same scope as %qD",
22838 : : var);
22839 : 2 : inform (DECL_SOURCE_LOCATION (var), "declared here");
22840 : 2 : continue;
22841 : : }
22842 : 77 : if (lookup_attribute ("omp allocate", DECL_ATTRIBUTES (var)))
22843 : : {
22844 : 1 : error_at (OMP_CLAUSE_LOCATION (nl),
22845 : : "%qD already appeared as list item in an "
22846 : : "%<allocate%> directive", var);
22847 : 1 : continue;
22848 : : }
22849 : 76 : if (TREE_STATIC (var))
22850 : : {
22851 : 19 : if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
22852 : : {
22853 : 3 : error_at (loc,
22854 : : "%<allocator%> clause required for "
22855 : : "static variable %qD", var);
22856 : 3 : continue;
22857 : : }
22858 : 16 : else if (allocator
22859 : 16 : && (wi::to_widest (allocator) < 1
22860 : 15 : || wi::to_widest (allocator) > GOMP_OMP_PREDEF_ALLOC_MAX)
22861 : 23 : && (wi::to_widest (allocator) < GOMP_OMPX_PREDEF_ALLOC_MIN
22862 : 12 : || wi::to_widest (allocator) > GOMP_OMPX_PREDEF_ALLOC_MAX))
22863 : : {
22864 : 6 : error_at (allocator_loc,
22865 : : "%<allocator%> clause requires a predefined allocator as "
22866 : : "%qD is static", var);
22867 : : }
22868 : : }
22869 : 73 : if (allocator)
22870 : : {
22871 : 40 : struct c_omp_loc_tree data
22872 : 78 : = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), var};
22873 : 40 : walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
22874 : : }
22875 : 73 : DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
22876 : : build_tree_list (allocator, alignment),
22877 : 73 : DECL_ATTRIBUTES (var));
22878 : : }
22879 : 69 : }
22880 : :
22881 : : /* OpenMP 2.5:
22882 : : # pragma omp atomic new-line
22883 : : expression-stmt
22884 : :
22885 : : expression-stmt:
22886 : : x binop= expr | x++ | ++x | x-- | --x
22887 : : binop:
22888 : : +, *, -, /, &, ^, |, <<, >>
22889 : :
22890 : : where x is an lvalue expression with scalar type.
22891 : :
22892 : : OpenMP 3.1:
22893 : : # pragma omp atomic new-line
22894 : : update-stmt
22895 : :
22896 : : # pragma omp atomic read new-line
22897 : : read-stmt
22898 : :
22899 : : # pragma omp atomic write new-line
22900 : : write-stmt
22901 : :
22902 : : # pragma omp atomic update new-line
22903 : : update-stmt
22904 : :
22905 : : # pragma omp atomic capture new-line
22906 : : capture-stmt
22907 : :
22908 : : # pragma omp atomic capture new-line
22909 : : capture-block
22910 : :
22911 : : read-stmt:
22912 : : v = x
22913 : : write-stmt:
22914 : : x = expr
22915 : : update-stmt:
22916 : : expression-stmt | x = x binop expr
22917 : : capture-stmt:
22918 : : v = expression-stmt
22919 : : capture-block:
22920 : : { v = x; update-stmt; } | { update-stmt; v = x; }
22921 : :
22922 : : OpenMP 4.0:
22923 : : update-stmt:
22924 : : expression-stmt | x = x binop expr | x = expr binop x
22925 : : capture-stmt:
22926 : : v = update-stmt
22927 : : capture-block:
22928 : : { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
22929 : :
22930 : : OpenMP 5.1:
22931 : : # pragma omp atomic compare new-line
22932 : : conditional-update-atomic
22933 : :
22934 : : # pragma omp atomic compare capture new-line
22935 : : conditional-update-capture-atomic
22936 : :
22937 : : conditional-update-atomic:
22938 : : cond-expr-stmt | cond-update-stmt
22939 : : cond-expr-stmt:
22940 : : x = expr ordop x ? expr : x;
22941 : : x = x ordop expr ? expr : x;
22942 : : x = x == e ? d : x;
22943 : : cond-update-stmt:
22944 : : if (expr ordop x) { x = expr; }
22945 : : if (x ordop expr) { x = expr; }
22946 : : if (x == e) { x = d; }
22947 : : ordop:
22948 : : <, >
22949 : : conditional-update-capture-atomic:
22950 : : v = cond-expr-stmt
22951 : : { v = x; cond-expr-stmt }
22952 : : { cond-expr-stmt v = x; }
22953 : : { v = x; cond-update-stmt }
22954 : : { cond-update-stmt v = x; }
22955 : : if (x == e) { x = d; } else { v = x; }
22956 : : { r = x == e; if (r) { x = d; } }
22957 : : { r = x == e; if (r) { x = d; } else { v = x; } }
22958 : :
22959 : : where x, r and v are lvalue expressions with scalar type,
22960 : : expr, e and d are expressions with scalar type and e might be
22961 : : the same as v.
22962 : :
22963 : : LOC is the location of the #pragma token. */
22964 : :
22965 : : static void
22966 : 1718 : c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
22967 : : {
22968 : 1718 : tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
22969 : 1718 : tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
22970 : 1718 : tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
22971 : 1718 : enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
22972 : 1718 : enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
22973 : 1718 : struct c_expr expr;
22974 : 1718 : location_t eloc;
22975 : 1718 : bool structured_block = false;
22976 : 1718 : bool swapped = false;
22977 : 1718 : bool non_lvalue_p;
22978 : 1718 : tree clauses = NULL_TREE;
22979 : 1718 : bool capture = false;
22980 : 1718 : bool compare = false;
22981 : 1718 : bool weak = false;
22982 : 1718 : enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22983 : 1718 : bool no_semicolon = false;
22984 : 1718 : bool extra_scope = false;
22985 : :
22986 : 3197 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
22987 : : {
22988 : 1489 : if (c_parser_next_token_is (parser, CPP_COMMA)
22989 : 1489 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22990 : 82 : c_parser_consume_token (parser);
22991 : :
22992 : 1489 : if (c_parser_next_token_is (parser, CPP_NAME))
22993 : : {
22994 : 1485 : const char *p
22995 : 1485 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22996 : 1485 : location_t cloc = c_parser_peek_token (parser)->location;
22997 : 1485 : enum tree_code new_code = ERROR_MARK;
22998 : 1485 : enum omp_memory_order new_memory_order
22999 : : = OMP_MEMORY_ORDER_UNSPECIFIED;
23000 : 1485 : bool new_capture = false;
23001 : 1485 : bool new_compare = false;
23002 : 1485 : bool new_weak = false;
23003 : 1485 : enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23004 : :
23005 : 1485 : if (!strcmp (p, "read"))
23006 : : new_code = OMP_ATOMIC_READ;
23007 : 1227 : else if (!strcmp (p, "write"))
23008 : : new_code = NOP_EXPR;
23009 : 1050 : else if (!strcmp (p, "update"))
23010 : : new_code = OMP_ATOMIC;
23011 : 890 : else if (openacc && !strcmp (p, "capture"))
23012 : : new_code = OMP_ATOMIC_CAPTURE_NEW;
23013 : 4 : else if (openacc)
23014 : : {
23015 : 4 : p = NULL;
23016 : 4 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23017 : : "or %<capture%> clause");
23018 : : }
23019 : 652 : else if (!strcmp (p, "capture"))
23020 : : new_capture = true;
23021 : 408 : else if (!strcmp (p, "compare"))
23022 : : new_compare = true;
23023 : 235 : else if (!strcmp (p, "weak"))
23024 : : new_weak = true;
23025 : 222 : else if (!strcmp (p, "fail"))
23026 : : {
23027 : 33 : matching_parens parens;
23028 : :
23029 : 33 : c_parser_consume_token (parser);
23030 : 33 : if (!parens.require_open (parser))
23031 : 1 : continue;
23032 : :
23033 : 32 : if (c_parser_next_token_is (parser, CPP_NAME))
23034 : : {
23035 : 30 : const char *q
23036 : 30 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23037 : :
23038 : 30 : if (!strcmp (q, "seq_cst"))
23039 : : new_fail = OMP_MEMORY_ORDER_SEQ_CST;
23040 : 24 : else if (!strcmp (q, "acquire"))
23041 : : new_fail = OMP_MEMORY_ORDER_ACQUIRE;
23042 : 17 : else if (!strcmp (q, "relaxed"))
23043 : : new_fail = OMP_MEMORY_ORDER_RELAXED;
23044 : : }
23045 : :
23046 : : if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23047 : : {
23048 : 27 : c_parser_consume_token (parser);
23049 : 27 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23050 : 2 : error_at (cloc, "too many %qs clauses", "fail");
23051 : : else
23052 : : fail = new_fail;
23053 : : }
23054 : : else
23055 : 5 : c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
23056 : : "or %<relaxed%>");
23057 : 32 : parens.skip_until_found_close (parser);
23058 : 32 : continue;
23059 : 32 : }
23060 : 189 : else if (!strcmp (p, "seq_cst"))
23061 : : new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23062 : 112 : else if (!strcmp (p, "acq_rel"))
23063 : : new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23064 : 100 : else if (!strcmp (p, "release"))
23065 : : new_memory_order = OMP_MEMORY_ORDER_RELEASE;
23066 : 70 : else if (!strcmp (p, "acquire"))
23067 : : new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23068 : 57 : else if (!strcmp (p, "relaxed"))
23069 : : new_memory_order = OMP_MEMORY_ORDER_RELAXED;
23070 : 31 : else if (!strcmp (p, "hint"))
23071 : : {
23072 : 29 : c_parser_consume_token (parser);
23073 : 29 : clauses = c_parser_omp_clause_hint (parser, clauses);
23074 : 29 : continue;
23075 : : }
23076 : : else
23077 : : {
23078 : 2 : p = NULL;
23079 : 2 : error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
23080 : : "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
23081 : : "%<seq_cst%>, %<acq_rel%>, %<release%>, "
23082 : : "%<relaxed%> or %<hint%> clause");
23083 : : }
23084 : 6 : if (p)
23085 : : {
23086 : 1417 : if (new_code != ERROR_MARK)
23087 : : {
23088 : : /* OpenACC permits 'update capture'. */
23089 : 829 : if (openacc
23090 : 829 : && code == OMP_ATOMIC
23091 : 4 : && new_code == OMP_ATOMIC_CAPTURE_NEW)
23092 : : code = new_code;
23093 : 826 : else if (code != ERROR_MARK)
23094 : 5 : error_at (cloc, "too many atomic clauses");
23095 : : else
23096 : : code = new_code;
23097 : : }
23098 : 588 : else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23099 : : {
23100 : 158 : if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
23101 : 35 : error_at (cloc, "too many memory order clauses");
23102 : : else
23103 : : memory_order = new_memory_order;
23104 : : }
23105 : 430 : else if (new_capture)
23106 : : {
23107 : 244 : if (capture)
23108 : 1 : error_at (cloc, "too many %qs clauses", "capture");
23109 : : else
23110 : : capture = true;
23111 : : }
23112 : 186 : else if (new_compare)
23113 : : {
23114 : 173 : if (compare)
23115 : 1 : error_at (cloc, "too many %qs clauses", "compare");
23116 : : else
23117 : : compare = true;
23118 : : }
23119 : 13 : else if (new_weak)
23120 : : {
23121 : 13 : if (weak)
23122 : 1 : error_at (cloc, "too many %qs clauses", "weak");
23123 : : else
23124 : : weak = true;
23125 : : }
23126 : 1417 : c_parser_consume_token (parser);
23127 : 1417 : continue;
23128 : : }
23129 : : }
23130 : : break;
23131 : : }
23132 : 1718 : c_parser_skip_to_pragma_eol (parser);
23133 : :
23134 : 1718 : if (code == ERROR_MARK)
23135 : 897 : code = OMP_ATOMIC;
23136 : 1718 : if (capture)
23137 : : {
23138 : 243 : if (code != OMP_ATOMIC)
23139 : 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23140 : : "clauses", "capture");
23141 : : else
23142 : : code = OMP_ATOMIC_CAPTURE_NEW;
23143 : : }
23144 : 1718 : if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
23145 : : {
23146 : 2 : error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
23147 : : "clauses", "compare");
23148 : 2 : compare = false;
23149 : : }
23150 : 1718 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
23151 : : {
23152 : 5 : error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
23153 : 5 : fail = OMP_MEMORY_ORDER_UNSPECIFIED;
23154 : : }
23155 : 1718 : if (weak && !compare)
23156 : : {
23157 : 5 : error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
23158 : 5 : weak = false;
23159 : : }
23160 : 1718 : if (openacc)
23161 : : memory_order = OMP_MEMORY_ORDER_RELAXED;
23162 : 1409 : else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
23163 : : {
23164 : 1286 : omp_requires_mask
23165 : 1286 : = (enum omp_requires) (omp_requires_mask
23166 : : | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
23167 : 1286 : switch ((enum omp_memory_order)
23168 : : (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
23169 : : {
23170 : : case OMP_MEMORY_ORDER_UNSPECIFIED:
23171 : : case OMP_MEMORY_ORDER_RELAXED:
23172 : : memory_order = OMP_MEMORY_ORDER_RELAXED;
23173 : : break;
23174 : : case OMP_MEMORY_ORDER_SEQ_CST:
23175 : 9 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23176 : : break;
23177 : 4 : case OMP_MEMORY_ORDER_ACQUIRE:
23178 : 4 : if (code == NOP_EXPR) /* atomic write */
23179 : : {
23180 : 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23181 : : "%<acquire%> clause implicitly provided by a "
23182 : : "%<requires%> directive");
23183 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23184 : : }
23185 : : else
23186 : : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23187 : : break;
23188 : 3 : case OMP_MEMORY_ORDER_RELEASE:
23189 : 3 : if (code == OMP_ATOMIC_READ)
23190 : : {
23191 : 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23192 : : "%<release%> clause implicitly provided by a "
23193 : : "%<requires%> directive");
23194 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23195 : : }
23196 : : else
23197 : : memory_order = OMP_MEMORY_ORDER_RELEASE;
23198 : : break;
23199 : 9 : case OMP_MEMORY_ORDER_ACQ_REL:
23200 : 9 : switch (code)
23201 : : {
23202 : : case OMP_ATOMIC_READ:
23203 : : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23204 : : break;
23205 : : case NOP_EXPR: /* atomic write */
23206 : 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23207 : : break;
23208 : : default:
23209 : 1718 : memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23210 : : break;
23211 : : }
23212 : : break;
23213 : 0 : default:
23214 : 0 : gcc_unreachable ();
23215 : : }
23216 : : }
23217 : : else
23218 : 123 : switch (code)
23219 : : {
23220 : 25 : case OMP_ATOMIC_READ:
23221 : 25 : if (memory_order == OMP_MEMORY_ORDER_RELEASE)
23222 : : {
23223 : 1 : error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23224 : : "%<release%> clause");
23225 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23226 : : }
23227 : 24 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23228 : 6 : memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23229 : : break;
23230 : 16 : case NOP_EXPR: /* atomic write */
23231 : 16 : if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
23232 : : {
23233 : 1 : error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23234 : : "%<acquire%> clause");
23235 : 1 : memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23236 : : }
23237 : 15 : else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23238 : 5 : memory_order = OMP_MEMORY_ORDER_RELEASE;
23239 : : break;
23240 : : default:
23241 : : break;
23242 : : }
23243 : 1718 : if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23244 : 20 : memory_order
23245 : 20 : = (enum omp_memory_order) (memory_order
23246 : : | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
23247 : :
23248 : 1718 : switch (code)
23249 : : {
23250 : 434 : case OMP_ATOMIC_READ:
23251 : 434 : case NOP_EXPR: /* atomic write */
23252 : 434 : v = c_parser_cast_expression (parser, NULL).value;
23253 : 434 : non_lvalue_p = !lvalue_p (v);
23254 : 434 : v = c_fully_fold (v, false, NULL, true);
23255 : 434 : if (v == error_mark_node)
23256 : 0 : goto saw_error;
23257 : 434 : if (non_lvalue_p)
23258 : 4 : v = non_lvalue (v);
23259 : 434 : loc = c_parser_peek_token (parser)->location;
23260 : 434 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23261 : 0 : goto saw_error;
23262 : 434 : if (code == NOP_EXPR)
23263 : : {
23264 : 176 : eloc = c_parser_peek_token (parser)->location;
23265 : 176 : expr = c_parser_expression (parser);
23266 : 176 : expr = default_function_array_read_conversion (eloc, expr);
23267 : : /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
23268 : : opcode. */
23269 : 176 : code = OMP_ATOMIC;
23270 : 176 : lhs = v;
23271 : 176 : v = NULL_TREE;
23272 : 176 : rhs = c_fully_fold (expr.value, false, NULL);
23273 : 176 : if (rhs == error_mark_node)
23274 : 0 : goto saw_error;
23275 : : }
23276 : : else
23277 : : {
23278 : 258 : lhs = c_parser_cast_expression (parser, NULL).value;
23279 : 258 : non_lvalue_p = !lvalue_p (lhs);
23280 : 258 : lhs = c_fully_fold (lhs, false, NULL, true);
23281 : 258 : if (lhs == error_mark_node)
23282 : 0 : goto saw_error;
23283 : 258 : if (non_lvalue_p)
23284 : 2 : lhs = non_lvalue (lhs);
23285 : : }
23286 : 434 : goto done;
23287 : 473 : case OMP_ATOMIC_CAPTURE_NEW:
23288 : 473 : if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
23289 : : {
23290 : 314 : c_parser_consume_token (parser);
23291 : 314 : structured_block = true;
23292 : : }
23293 : 159 : else if (compare
23294 : 188 : && c_parser_next_token_is_keyword (parser, RID_IF))
23295 : : break;
23296 : : else
23297 : : {
23298 : 142 : v = c_parser_cast_expression (parser, NULL).value;
23299 : 142 : non_lvalue_p = !lvalue_p (v);
23300 : 142 : v = c_fully_fold (v, false, NULL, true);
23301 : 142 : if (v == error_mark_node)
23302 : 0 : goto saw_error;
23303 : 142 : if (non_lvalue_p)
23304 : 2 : v = non_lvalue (v);
23305 : 142 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23306 : 0 : goto saw_error;
23307 : 154 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23308 : : {
23309 : 1 : eloc = c_parser_peek_token (parser)->location;
23310 : 1 : error_at (eloc, "expected expression");
23311 : 1 : goto saw_error;
23312 : : }
23313 : : }
23314 : : break;
23315 : : default:
23316 : : break;
23317 : : }
23318 : :
23319 : : /* For structured_block case we don't know yet whether
23320 : : old or new x should be captured. */
23321 : 1283 : restart:
23322 : 1675 : if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
23323 : : {
23324 : 85 : c_parser_consume_token (parser);
23325 : :
23326 : 85 : matching_parens parens;
23327 : 85 : if (!parens.require_open (parser))
23328 : 34 : goto saw_error;
23329 : 84 : eloc = c_parser_peek_token (parser)->location;
23330 : 84 : c_expr cmp_expr;
23331 : 84 : if (r)
23332 : : {
23333 : 17 : cmp_expr = c_parser_cast_expression (parser, NULL);
23334 : 17 : cmp_expr = default_function_array_conversion (eloc, cmp_expr);
23335 : : }
23336 : : else
23337 : 67 : cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
23338 : 84 : parens.skip_until_found_close (parser);
23339 : 84 : if (cmp_expr.value == error_mark_node)
23340 : 0 : goto saw_error;
23341 : 84 : if (r)
23342 : : {
23343 : 17 : if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
23344 : 1 : goto bad_if;
23345 : 16 : cmp_expr.value = rhs1;
23346 : 16 : rhs1 = NULL_TREE;
23347 : 16 : gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
23348 : : }
23349 : 83 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23350 : : ;
23351 : 36 : else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23352 : : {
23353 : 4 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23354 : : "expected %<==%> comparison in %<if%> condition");
23355 : 2 : goto saw_error;
23356 : : }
23357 : 34 : else if (TREE_CODE (cmp_expr.value) != GT_EXPR
23358 : 25 : && TREE_CODE (cmp_expr.value) != LT_EXPR)
23359 : : {
23360 : 16 : error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23361 : : "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
23362 : : "condition");
23363 : 10 : goto saw_error;
23364 : : }
23365 : 71 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
23366 : 2 : goto saw_error;
23367 : :
23368 : 69 : extra_scope = true;
23369 : 69 : eloc = c_parser_peek_token (parser)->location;
23370 : 69 : expr = c_parser_cast_expression (parser, NULL);
23371 : 69 : lhs = expr.value;
23372 : 69 : expr = default_function_array_conversion (eloc, expr);
23373 : 69 : unfolded_lhs = expr.value;
23374 : 69 : lhs = c_fully_fold (lhs, false, NULL, true);
23375 : 69 : orig_lhs = lhs;
23376 : 69 : if (lhs == error_mark_node)
23377 : 0 : goto saw_error;
23378 : 69 : if (!lvalue_p (unfolded_lhs))
23379 : 0 : lhs = non_lvalue (lhs);
23380 : 69 : if (!c_parser_next_token_is (parser, CPP_EQ))
23381 : : {
23382 : 1 : c_parser_error (parser, "expected %<=%>");
23383 : 1 : goto saw_error;
23384 : : }
23385 : 68 : c_parser_consume_token (parser);
23386 : 68 : eloc = c_parser_peek_token (parser)->location;
23387 : 68 : expr = c_parser_expr_no_commas (parser, NULL);
23388 : 68 : rhs1 = expr.value;
23389 : :
23390 : 68 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23391 : 1 : goto saw_error;
23392 : :
23393 : 67 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
23394 : 1 : goto saw_error;
23395 : :
23396 : 66 : extra_scope = false;
23397 : 66 : no_semicolon = true;
23398 : :
23399 : 66 : if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
23400 : : {
23401 : 59 : if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23402 : : {
23403 : 44 : opcode = COND_EXPR;
23404 : 44 : rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23405 : : false, NULL, true);
23406 : 44 : rhs1 = c_fully_fold (rhs1, false, NULL, true);
23407 : : }
23408 : 15 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
23409 : : {
23410 : 7 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23411 : 13 : ? MIN_EXPR : MAX_EXPR);
23412 : 13 : rhs = c_fully_fold (rhs1, false, NULL, true);
23413 : 13 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
23414 : : false, NULL, true);
23415 : : }
23416 : : else
23417 : 2 : goto bad_if;
23418 : : }
23419 : 7 : else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23420 : 2 : goto bad_if;
23421 : 5 : else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
23422 : 5 : && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
23423 : : {
23424 : 2 : opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23425 : 3 : ? MAX_EXPR : MIN_EXPR);
23426 : 3 : rhs = c_fully_fold (rhs1, false, NULL, true);
23427 : 3 : rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23428 : : false, NULL, true);
23429 : : }
23430 : : else
23431 : : {
23432 : 8 : bad_if:
23433 : 8 : c_parser_error (parser,
23434 : : "invalid form of %<#pragma omp atomic compare%>");
23435 : 8 : goto saw_error;
23436 : : }
23437 : :
23438 : 60 : if (c_parser_next_token_is_keyword (parser, RID_ELSE))
23439 : : {
23440 : 24 : if (code != OMP_ATOMIC_CAPTURE_NEW
23441 : 22 : || (structured_block && r == NULL_TREE)
23442 : 21 : || TREE_CODE (cmp_expr.value) != EQ_EXPR)
23443 : : {
23444 : 3 : eloc = c_parser_peek_token (parser)->location;
23445 : 3 : error_at (eloc, "unexpected %<else%>");
23446 : 3 : goto saw_error;
23447 : : }
23448 : :
23449 : 21 : c_parser_consume_token (parser);
23450 : :
23451 : 21 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
23452 : 1 : goto saw_error;
23453 : :
23454 : 20 : extra_scope = true;
23455 : 20 : v = c_parser_cast_expression (parser, NULL).value;
23456 : 20 : non_lvalue_p = !lvalue_p (v);
23457 : 20 : v = c_fully_fold (v, false, NULL, true);
23458 : 20 : if (v == error_mark_node)
23459 : 0 : goto saw_error;
23460 : 20 : if (non_lvalue_p)
23461 : 0 : v = non_lvalue (v);
23462 : 20 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23463 : 1 : goto saw_error;
23464 : :
23465 : 19 : expr = c_parser_expr_no_commas (parser, NULL);
23466 : :
23467 : 19 : if (!c_tree_equal (expr.value, unfolded_lhs))
23468 : 1 : goto bad_if;
23469 : :
23470 : 18 : if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23471 : 1 : goto saw_error;
23472 : :
23473 : 17 : if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
23474 : 0 : goto saw_error;
23475 : :
23476 : 17 : extra_scope = false;
23477 : 17 : code = OMP_ATOMIC_CAPTURE_OLD;
23478 : 17 : if (r == NULL_TREE)
23479 : : /* Signal to c_finish_omp_atomic that in
23480 : : if (x == e) { x = d; } else { v = x; }
23481 : : case the store to v should be conditional. */
23482 : 10 : r = void_list_node;
23483 : : }
23484 : 36 : else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23485 : : {
23486 : 1 : c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
23487 : 1 : goto saw_error;
23488 : : }
23489 : 35 : else if (code == OMP_ATOMIC_CAPTURE_NEW
23490 : 35 : && r != NULL_TREE
23491 : 9 : && v == NULL_TREE)
23492 : 52 : code = OMP_ATOMIC;
23493 : 52 : goto stmt_done;
23494 : : }
23495 : 1382 : eloc = c_parser_peek_token (parser)->location;
23496 : 1382 : expr = c_parser_cast_expression (parser, NULL);
23497 : 1382 : lhs = expr.value;
23498 : 1382 : expr = default_function_array_conversion (eloc, expr);
23499 : 1382 : unfolded_lhs = expr.value;
23500 : 1382 : lhs = c_fully_fold (lhs, false, NULL, true);
23501 : 1382 : orig_lhs = lhs;
23502 : 1382 : switch (TREE_CODE (lhs))
23503 : : {
23504 : 4 : invalid_compare:
23505 : 4 : error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
23506 : : /* FALLTHRU */
23507 : 84 : case ERROR_MARK:
23508 : 84 : saw_error:
23509 : 84 : c_parser_skip_to_end_of_block_or_statement (parser);
23510 : 90 : if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23511 : 4 : c_parser_consume_token (parser);
23512 : 84 : if (structured_block)
23513 : : {
23514 : 10 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23515 : 9 : c_parser_consume_token (parser);
23516 : 1 : else if (code == OMP_ATOMIC_CAPTURE_NEW)
23517 : : {
23518 : 1 : c_parser_skip_to_end_of_block_or_statement (parser);
23519 : 1 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
23520 : 1 : c_parser_consume_token (parser);
23521 : : }
23522 : : }
23523 : 84 : return;
23524 : :
23525 : 158 : case POSTINCREMENT_EXPR:
23526 : 158 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23527 : 20 : code = OMP_ATOMIC_CAPTURE_OLD;
23528 : : /* FALLTHROUGH */
23529 : 220 : case PREINCREMENT_EXPR:
23530 : 220 : lhs = TREE_OPERAND (lhs, 0);
23531 : 220 : unfolded_lhs = NULL_TREE;
23532 : 220 : opcode = PLUS_EXPR;
23533 : 220 : rhs = integer_one_node;
23534 : 220 : if (compare)
23535 : 2 : goto invalid_compare;
23536 : : break;
23537 : :
23538 : 24 : case POSTDECREMENT_EXPR:
23539 : 24 : if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23540 : 2 : code = OMP_ATOMIC_CAPTURE_OLD;
23541 : : /* FALLTHROUGH */
23542 : 52 : case PREDECREMENT_EXPR:
23543 : 52 : lhs = TREE_OPERAND (lhs, 0);
23544 : 52 : unfolded_lhs = NULL_TREE;
23545 : 52 : opcode = MINUS_EXPR;
23546 : 52 : rhs = integer_one_node;
23547 : 52 : if (compare)
23548 : 2 : goto invalid_compare;
23549 : : break;
23550 : :
23551 : 12 : case COMPOUND_EXPR:
23552 : 12 : if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
23553 : 12 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
23554 : 12 : && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
23555 : 12 : && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
23556 : 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
23557 : : (TREE_OPERAND (lhs, 1), 0), 0))))
23558 : : /* Undo effects of boolean_increment for post {in,de}crement. */
23559 : 12 : lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
23560 : : /* FALLTHRU */
23561 : 24 : case MODIFY_EXPR:
23562 : 24 : if (TREE_CODE (lhs) == MODIFY_EXPR
23563 : 24 : && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
23564 : : {
23565 : : /* Undo effects of boolean_increment. */
23566 : 24 : if (integer_onep (TREE_OPERAND (lhs, 1)))
23567 : : {
23568 : : /* This is pre or post increment. */
23569 : 12 : rhs = TREE_OPERAND (lhs, 1);
23570 : 12 : lhs = TREE_OPERAND (lhs, 0);
23571 : 12 : unfolded_lhs = NULL_TREE;
23572 : 12 : opcode = NOP_EXPR;
23573 : 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
23574 : 12 : && !structured_block
23575 : 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23576 : 1 : code = OMP_ATOMIC_CAPTURE_OLD;
23577 : 12 : if (compare)
23578 : 0 : goto invalid_compare;
23579 : : break;
23580 : : }
23581 : 12 : if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
23582 : 12 : && TREE_OPERAND (lhs, 0)
23583 : 12 : == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
23584 : : {
23585 : : /* This is pre or post decrement. */
23586 : 12 : rhs = TREE_OPERAND (lhs, 1);
23587 : 12 : lhs = TREE_OPERAND (lhs, 0);
23588 : 12 : unfolded_lhs = NULL_TREE;
23589 : 12 : opcode = NOP_EXPR;
23590 : 12 : if (code == OMP_ATOMIC_CAPTURE_NEW
23591 : 12 : && !structured_block
23592 : 2 : && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23593 : 1 : code = OMP_ATOMIC_CAPTURE_OLD;
23594 : 12 : if (compare)
23595 : 0 : goto invalid_compare;
23596 : : break;
23597 : : }
23598 : : }
23599 : : /* FALLTHRU */
23600 : 1082 : default:
23601 : 1082 : if (!lvalue_p (unfolded_lhs))
23602 : 5 : lhs = non_lvalue (lhs);
23603 : 1201 : if (compare && !c_parser_next_token_is (parser, CPP_EQ))
23604 : : {
23605 : 7 : c_parser_error (parser, "expected %<=%>");
23606 : 7 : goto saw_error;
23607 : : }
23608 : 1075 : switch (c_parser_peek_token (parser)->type)
23609 : : {
23610 : : case CPP_MULT_EQ:
23611 : : opcode = MULT_EXPR;
23612 : : break;
23613 : : case CPP_DIV_EQ:
23614 : : opcode = TRUNC_DIV_EXPR;
23615 : : break;
23616 : : case CPP_PLUS_EQ:
23617 : : opcode = PLUS_EXPR;
23618 : : break;
23619 : : case CPP_MINUS_EQ:
23620 : : opcode = MINUS_EXPR;
23621 : : break;
23622 : : case CPP_LSHIFT_EQ:
23623 : : opcode = LSHIFT_EXPR;
23624 : : break;
23625 : : case CPP_RSHIFT_EQ:
23626 : : opcode = RSHIFT_EXPR;
23627 : : break;
23628 : : case CPP_AND_EQ:
23629 : : opcode = BIT_AND_EXPR;
23630 : : break;
23631 : : case CPP_OR_EQ:
23632 : : opcode = BIT_IOR_EXPR;
23633 : : break;
23634 : : case CPP_XOR_EQ:
23635 : : opcode = BIT_XOR_EXPR;
23636 : : break;
23637 : 556 : case CPP_EQ:
23638 : 556 : c_parser_consume_token (parser);
23639 : 556 : eloc = c_parser_peek_token (parser)->location;
23640 : 556 : expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
23641 : 556 : rhs1 = expr.value;
23642 : 556 : switch (TREE_CODE (rhs1))
23643 : : {
23644 : 289 : case MULT_EXPR:
23645 : 289 : case TRUNC_DIV_EXPR:
23646 : 289 : case RDIV_EXPR:
23647 : 289 : case PLUS_EXPR:
23648 : 289 : case MINUS_EXPR:
23649 : 289 : case LSHIFT_EXPR:
23650 : 289 : case RSHIFT_EXPR:
23651 : 289 : case BIT_AND_EXPR:
23652 : 289 : case BIT_IOR_EXPR:
23653 : 289 : case BIT_XOR_EXPR:
23654 : 289 : if (compare)
23655 : : break;
23656 : 282 : if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
23657 : : {
23658 : 147 : opcode = TREE_CODE (rhs1);
23659 : 147 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23660 : : true);
23661 : 147 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23662 : : true);
23663 : 147 : goto stmt_done;
23664 : : }
23665 : 135 : if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
23666 : : {
23667 : 117 : opcode = TREE_CODE (rhs1);
23668 : 117 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23669 : : true);
23670 : 117 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23671 : : true);
23672 : 117 : swapped = !commutative_tree_code (opcode);
23673 : 117 : goto stmt_done;
23674 : : }
23675 : : break;
23676 : 69 : case COND_EXPR:
23677 : 69 : if (!compare)
23678 : : break;
23679 : 66 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
23680 : 44 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
23681 : 97 : && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
23682 : : break;
23683 : 63 : if (!TREE_OPERAND (rhs1, 1))
23684 : : break;
23685 : 63 : if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
23686 : : break;
23687 : 58 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23688 : : unfolded_lhs))
23689 : : {
23690 : 39 : if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23691 : : {
23692 : 23 : opcode = COND_EXPR;
23693 : 23 : rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23694 : : 0), 1),
23695 : : false, NULL, true);
23696 : 23 : rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
23697 : : NULL, true);
23698 : 23 : goto stmt_done;
23699 : : }
23700 : 16 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23701 : 16 : TREE_OPERAND (rhs1, 1)))
23702 : : {
23703 : 21 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23704 : 14 : ? MIN_EXPR : MAX_EXPR);
23705 : 14 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23706 : : true);
23707 : 14 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23708 : : 0), 0),
23709 : : false, NULL, true);
23710 : 14 : goto stmt_done;
23711 : : }
23712 : : }
23713 : 19 : else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23714 : : break;
23715 : 17 : else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23716 : : unfolded_lhs))
23717 : : {
23718 : 15 : if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23719 : 15 : TREE_OPERAND (rhs1, 1)))
23720 : : {
23721 : 18 : opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23722 : 15 : ? MAX_EXPR : MIN_EXPR);
23723 : 15 : rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23724 : : true);
23725 : 15 : rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23726 : : 0), 1),
23727 : : false, NULL, true);
23728 : 15 : goto stmt_done;
23729 : : }
23730 : : }
23731 : : break;
23732 : 17 : case EQ_EXPR:
23733 : 17 : if (!compare
23734 : 17 : || code != OMP_ATOMIC_CAPTURE_NEW
23735 : 17 : || !structured_block
23736 : 17 : || v
23737 : 17 : || r)
23738 : : break;
23739 : 17 : if (c_parser_next_token_is (parser, CPP_SEMICOLON)
23740 : 17 : && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
23741 : : {
23742 : 17 : r = lhs;
23743 : 17 : lhs = NULL_TREE;
23744 : 17 : c_parser_consume_token (parser);
23745 : 17 : goto restart;
23746 : : }
23747 : : break;
23748 : 0 : case ERROR_MARK:
23749 : 0 : goto saw_error;
23750 : : default:
23751 : : break;
23752 : : }
23753 : 223 : if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
23754 : : {
23755 : 223 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23756 : : {
23757 : 167 : code = OMP_ATOMIC_CAPTURE_OLD;
23758 : 167 : v = lhs;
23759 : 167 : lhs = NULL_TREE;
23760 : 167 : expr = default_function_array_read_conversion (eloc, expr);
23761 : 167 : unfolded_lhs1 = expr.value;
23762 : 167 : lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
23763 : 167 : rhs1 = NULL_TREE;
23764 : 167 : c_parser_consume_token (parser);
23765 : 167 : goto restart;
23766 : : }
23767 : 56 : if (structured_block && !compare)
23768 : : {
23769 : 26 : opcode = NOP_EXPR;
23770 : 26 : expr = default_function_array_read_conversion (eloc, expr);
23771 : 26 : rhs = c_fully_fold (expr.value, false, NULL, true);
23772 : 26 : rhs1 = NULL_TREE;
23773 : 26 : goto stmt_done;
23774 : : }
23775 : : }
23776 : 30 : c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
23777 : 30 : goto saw_error;
23778 : 5 : default:
23779 : 5 : c_parser_error (parser,
23780 : : "invalid operator for %<#pragma omp atomic%>");
23781 : 5 : goto saw_error;
23782 : : }
23783 : :
23784 : : /* Arrange to pass the location of the assignment operator to
23785 : : c_finish_omp_atomic. */
23786 : 514 : loc = c_parser_peek_token (parser)->location;
23787 : 514 : c_parser_consume_token (parser);
23788 : 514 : eloc = c_parser_peek_token (parser)->location;
23789 : 514 : expr = c_parser_expression (parser);
23790 : 514 : expr = default_function_array_read_conversion (eloc, expr);
23791 : 514 : rhs = expr.value;
23792 : 514 : rhs = c_fully_fold (rhs, false, NULL, true);
23793 : 514 : break;
23794 : : }
23795 : 1200 : stmt_done:
23796 : 1200 : if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
23797 : : {
23798 : 129 : if (!no_semicolon
23799 : 129 : && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
23800 : 0 : goto saw_error;
23801 : 129 : no_semicolon = false;
23802 : 129 : v = c_parser_cast_expression (parser, NULL).value;
23803 : 129 : non_lvalue_p = !lvalue_p (v);
23804 : 129 : v = c_fully_fold (v, false, NULL, true);
23805 : 129 : if (v == error_mark_node)
23806 : 0 : goto saw_error;
23807 : 129 : if (non_lvalue_p)
23808 : 2 : v = non_lvalue (v);
23809 : 129 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
23810 : 0 : goto saw_error;
23811 : 129 : eloc = c_parser_peek_token (parser)->location;
23812 : 129 : expr = c_parser_cast_expression (parser, NULL);
23813 : 129 : lhs1 = expr.value;
23814 : 129 : expr = default_function_array_read_conversion (eloc, expr);
23815 : 129 : unfolded_lhs1 = expr.value;
23816 : 129 : lhs1 = c_fully_fold (lhs1, false, NULL, true);
23817 : 129 : if (lhs1 == error_mark_node)
23818 : 0 : goto saw_error;
23819 : 129 : if (!lvalue_p (unfolded_lhs1))
23820 : 2 : lhs1 = non_lvalue (lhs1);
23821 : : }
23822 : 1200 : if (structured_block)
23823 : : {
23824 : 304 : if (!no_semicolon)
23825 : 280 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
23826 : 304 : c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
23827 : : }
23828 : 896 : done:
23829 : 1634 : if (weak && opcode != COND_EXPR)
23830 : : {
23831 : 1 : error_at (loc, "%<weak%> clause requires atomic equality comparison");
23832 : 1 : weak = false;
23833 : : }
23834 : 1634 : if (unfolded_lhs && unfolded_lhs1
23835 : 1634 : && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
23836 : : {
23837 : 5 : error ("%<#pragma omp atomic capture%> uses two different "
23838 : : "expressions for memory");
23839 : 5 : stmt = error_mark_node;
23840 : : }
23841 : : else
23842 : 1629 : stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
23843 : : swapped, memory_order, weak);
23844 : 1634 : if (stmt != error_mark_node)
23845 : 1604 : add_stmt (stmt);
23846 : :
23847 : 1634 : if (!structured_block && !no_semicolon)
23848 : 1311 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
23849 : : }
23850 : :
23851 : :
23852 : : /* OpenMP 2.5:
23853 : : # pragma omp barrier new-line
23854 : : */
23855 : :
23856 : : static void
23857 : 348 : c_parser_omp_barrier (c_parser *parser)
23858 : : {
23859 : 348 : location_t loc = c_parser_peek_token (parser)->location;
23860 : 348 : c_parser_consume_pragma (parser);
23861 : 348 : c_parser_skip_to_pragma_eol (parser);
23862 : :
23863 : 348 : c_finish_omp_barrier (loc);
23864 : 348 : }
23865 : :
23866 : : /* OpenMP 2.5:
23867 : : # pragma omp critical [(name)] new-line
23868 : : structured-block
23869 : :
23870 : : OpenMP 4.5:
23871 : : # pragma omp critical [(name) [hint(expression)]] new-line
23872 : :
23873 : : LOC is the location of the #pragma itself. */
23874 : :
23875 : : #define OMP_CRITICAL_CLAUSE_MASK \
23876 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
23877 : :
23878 : : static tree
23879 : 144 : c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
23880 : : {
23881 : 144 : tree stmt, name = NULL_TREE, clauses = NULL_TREE;
23882 : :
23883 : 144 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
23884 : : {
23885 : 49 : c_parser_consume_token (parser);
23886 : 49 : if (c_parser_next_token_is (parser, CPP_NAME))
23887 : : {
23888 : 48 : name = c_parser_peek_token (parser)->value;
23889 : 48 : c_parser_consume_token (parser);
23890 : 48 : c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
23891 : : }
23892 : : else
23893 : 1 : c_parser_error (parser, "expected identifier");
23894 : :
23895 : 49 : if (c_parser_next_token_is (parser, CPP_COMMA)
23896 : 49 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23897 : 4 : c_parser_consume_token (parser);
23898 : : }
23899 : 144 : clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
23900 : : "#pragma omp critical");
23901 : 144 : stmt = c_parser_omp_structured_block (parser, if_p);
23902 : 144 : return c_finish_omp_critical (loc, stmt, name, clauses);
23903 : : }
23904 : :
23905 : : /* OpenMP 5.0:
23906 : : # pragma omp depobj ( depobj ) depobj-clause new-line
23907 : :
23908 : : depobj-clause:
23909 : : depend (dependence-type : locator)
23910 : : destroy
23911 : : update (dependence-type)
23912 : :
23913 : : OpenMP 5.2 additionally:
23914 : : destroy ( depobj )
23915 : :
23916 : : dependence-type:
23917 : : in
23918 : : out
23919 : : inout
23920 : : mutexinout */
23921 : :
23922 : : static void
23923 : 75 : c_parser_omp_depobj (c_parser *parser)
23924 : : {
23925 : 75 : location_t loc = c_parser_peek_token (parser)->location;
23926 : 75 : c_parser_consume_pragma (parser);
23927 : 75 : matching_parens parens;
23928 : 75 : if (!parens.require_open (parser))
23929 : : {
23930 : 3 : c_parser_skip_to_pragma_eol (parser);
23931 : 3 : return;
23932 : : }
23933 : :
23934 : 72 : tree depobj = c_parser_expr_no_commas (parser, NULL).value;
23935 : 72 : if (depobj != error_mark_node)
23936 : : {
23937 : 71 : if (!lvalue_p (depobj))
23938 : : {
23939 : 1 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
23940 : : "%<depobj%> expression is not lvalue expression");
23941 : 1 : depobj = error_mark_node;
23942 : : }
23943 : : else
23944 : : {
23945 : 123 : tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
23946 : : depobj, false);
23947 : 70 : if (addr == error_mark_node)
23948 : : depobj = error_mark_node;
23949 : : else
23950 : 123 : depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
23951 : : addr, RO_UNARY_STAR);
23952 : : }
23953 : : }
23954 : :
23955 : 72 : parens.skip_until_found_close (parser);
23956 : 72 : tree clause = NULL_TREE;
23957 : 72 : enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
23958 : 72 : if (c_parser_next_token_is (parser, CPP_COMMA))
23959 : 3 : c_parser_consume_token (parser);
23960 : 72 : location_t c_loc = c_parser_peek_token (parser)->location;
23961 : 72 : if (c_parser_next_token_is (parser, CPP_NAME))
23962 : : {
23963 : 71 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23964 : :
23965 : 71 : c_parser_consume_token (parser);
23966 : 71 : if (!strcmp ("depend", p))
23967 : : {
23968 : 38 : clause = c_parser_omp_clause_depend (parser, NULL_TREE);
23969 : 38 : clause = c_finish_omp_clauses (clause, C_ORT_OMP);
23970 : 38 : if (!clause)
23971 : 2 : clause = error_mark_node;
23972 : : }
23973 : 33 : else if (!strcmp ("destroy", p))
23974 : : {
23975 : 22 : matching_parens c_parens;
23976 : 22 : kind = OMP_CLAUSE_DEPEND_LAST;
23977 : 22 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
23978 : 22 : && c_parens.require_open (parser))
23979 : : {
23980 : 7 : tree destobj = c_parser_expr_no_commas (parser, NULL).value;
23981 : 7 : if (!lvalue_p (destobj))
23982 : 1 : error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
23983 : : "%<destroy%> expression is not lvalue expression");
23984 : 6 : else if (depobj != error_mark_node
23985 : 6 : && !operand_equal_p (destobj, depobj,
23986 : : OEP_MATCH_SIDE_EFFECTS
23987 : : | OEP_LEXICOGRAPHIC))
23988 : 4 : warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
23989 : : "the %<destroy%> expression %qE should be the same "
23990 : : "as the %<depobj%> argument %qE", destobj, depobj);
23991 : 7 : c_parens.skip_until_found_close (parser);
23992 : : }
23993 : : }
23994 : 11 : else if (!strcmp ("update", p))
23995 : : {
23996 : 10 : matching_parens c_parens;
23997 : 10 : if (c_parens.require_open (parser))
23998 : : {
23999 : 10 : location_t c2_loc = c_parser_peek_token (parser)->location;
24000 : 10 : if (c_parser_next_token_is (parser, CPP_NAME))
24001 : : {
24002 : 10 : const char *p2
24003 : 10 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24004 : :
24005 : 10 : c_parser_consume_token (parser);
24006 : 10 : if (!strcmp ("in", p2))
24007 : : kind = OMP_CLAUSE_DEPEND_IN;
24008 : 8 : else if (!strcmp ("out", p2))
24009 : : kind = OMP_CLAUSE_DEPEND_OUT;
24010 : 7 : else if (!strcmp ("inout", p2))
24011 : : kind = OMP_CLAUSE_DEPEND_INOUT;
24012 : 4 : else if (!strcmp ("mutexinoutset", p2))
24013 : : kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
24014 : 3 : else if (!strcmp ("inoutset", p2))
24015 : : kind = OMP_CLAUSE_DEPEND_INOUTSET;
24016 : : }
24017 : : if (kind == OMP_CLAUSE_DEPEND_INVALID)
24018 : : {
24019 : 1 : clause = error_mark_node;
24020 : 1 : error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
24021 : : "%<mutexinoutset%> or %<inoutset%>");
24022 : : }
24023 : 10 : c_parens.skip_until_found_close (parser);
24024 : : }
24025 : : else
24026 : 0 : clause = error_mark_node;
24027 : : }
24028 : : }
24029 : 72 : if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
24030 : : {
24031 : 2 : clause = error_mark_node;
24032 : 2 : error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
24033 : : }
24034 : 72 : c_parser_skip_to_pragma_eol (parser);
24035 : :
24036 : 72 : c_finish_omp_depobj (loc, depobj, kind, clause);
24037 : : }
24038 : :
24039 : :
24040 : : /* OpenMP 2.5:
24041 : : # pragma omp flush flush-vars[opt] new-line
24042 : :
24043 : : flush-vars:
24044 : : ( variable-list )
24045 : :
24046 : : OpenMP 5.0:
24047 : : # pragma omp flush memory-order-clause new-line */
24048 : :
24049 : : static void
24050 : 61 : c_parser_omp_flush (c_parser *parser)
24051 : : {
24052 : 61 : location_t loc = c_parser_peek_token (parser)->location;
24053 : 61 : c_parser_consume_pragma (parser);
24054 : 61 : enum memmodel mo = MEMMODEL_LAST;
24055 : 61 : if (c_parser_next_token_is (parser, CPP_COMMA)
24056 : 61 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
24057 : 8 : c_parser_consume_token (parser);
24058 : 61 : if (c_parser_next_token_is (parser, CPP_NAME))
24059 : : {
24060 : 27 : const char *p
24061 : 27 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24062 : :
24063 : 27 : if (!strcmp (p, "seq_cst"))
24064 : : mo = MEMMODEL_SEQ_CST;
24065 : 21 : else if (!strcmp (p, "acq_rel"))
24066 : : mo = MEMMODEL_ACQ_REL;
24067 : 15 : else if (!strcmp (p, "release"))
24068 : : mo = MEMMODEL_RELEASE;
24069 : 9 : else if (!strcmp (p, "acquire"))
24070 : : mo = MEMMODEL_ACQUIRE;
24071 : : else
24072 : 3 : error_at (c_parser_peek_token (parser)->location,
24073 : : "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
24074 : : "%<acquire%>");
24075 : 27 : c_parser_consume_token (parser);
24076 : : }
24077 : 61 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
24078 : : {
24079 : 20 : if (mo != MEMMODEL_LAST)
24080 : 4 : error_at (c_parser_peek_token (parser)->location,
24081 : : "%<flush%> list specified together with memory order "
24082 : : "clause");
24083 : 20 : c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
24084 : : }
24085 : 41 : else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
24086 : 1 : c_parser_error (parser, "expected %<(%> or end of line");
24087 : 61 : c_parser_skip_to_pragma_eol (parser);
24088 : :
24089 : 61 : c_finish_omp_flush (loc, mo);
24090 : 61 : }
24091 : :
24092 : : /* Return true if next tokens contain a standard attribute that contains
24093 : : omp::directive (DIRECTIVE). */
24094 : :
24095 : : static bool
24096 : 363 : c_parser_omp_section_scan (c_parser *parser, const char *directive,
24097 : : bool tentative)
24098 : : {
24099 : 363 : if (!c_parser_nth_token_starts_std_attributes (parser, 1))
24100 : : return false;
24101 : 36 : unsigned int n = 3;
24102 : 36 : if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
24103 : : return false;
24104 : 36 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
24105 : 36 : if (token->type != CPP_CLOSE_SQUARE)
24106 : : return false;
24107 : 36 : token = c_parser_peek_nth_token_raw (parser, n + 1);
24108 : 36 : if (token->type != CPP_CLOSE_SQUARE)
24109 : : return false;
24110 : 36 : if (n < 9)
24111 : : return false;
24112 : 35 : if (c_parser_peek_nth_token_raw (parser, 3)->type == CPP_NAME
24113 : 35 : && c_parser_peek_nth_token_raw (parser, 4)->type == CPP_OPEN_PAREN
24114 : 35 : && c_parser_peek_nth_token_raw (parser, 5)->type == CPP_NAME)
24115 : : {
24116 : 0 : tree first = c_parser_peek_nth_token_raw (parser, 3)->value;
24117 : 0 : tree second = c_parser_peek_nth_token_raw (parser, 5)->value;
24118 : 0 : if (strcmp (IDENTIFIER_POINTER (first), "directive")
24119 : 0 : && strcmp (IDENTIFIER_POINTER (first), "__directive__"))
24120 : : return false;
24121 : 0 : if (strcmp (IDENTIFIER_POINTER (second), directive))
24122 : : return false;
24123 : : }
24124 : 35 : if (tentative)
24125 : : return true;
24126 : 32 : location_t first_loc = c_parser_peek_token (parser)->location;
24127 : 32 : location_t last_loc = c_parser_peek_nth_token_raw (parser, n + 1)->location;
24128 : 32 : location_t middle_loc = UNKNOWN_LOCATION;
24129 : 32 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24130 : 32 : bool seen = false;
24131 : 32 : int cnt = 0;
24132 : 67 : for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
24133 : 35 : if (is_attribute_namespace_p ("omp", attr)
24134 : 35 : && is_attribute_p ("directive", get_attribute_name (attr)))
24135 : : {
24136 : 68 : for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
24137 : : {
24138 : 36 : tree d = TREE_VALUE (a);
24139 : 36 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
24140 : 36 : c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
24141 : 36 : cnt++;
24142 : 36 : if (first->type == CPP_NAME
24143 : 36 : && strcmp (IDENTIFIER_POINTER (first->value),
24144 : : directive) == 0)
24145 : : {
24146 : 31 : seen = true;
24147 : 31 : if (middle_loc == UNKNOWN_LOCATION)
24148 : 31 : middle_loc = first->location;
24149 : : }
24150 : : }
24151 : : }
24152 : 32 : if (!seen)
24153 : : return false;
24154 : 31 : if (cnt != 1 || TREE_CHAIN (std_attrs))
24155 : : {
24156 : 7 : error_at (make_location (first_loc, last_loc, middle_loc),
24157 : : "%<[[omp::directive(%s)]]%> must be the only specified "
24158 : : "attribute on a statement", directive);
24159 : 7 : return false;
24160 : : }
24161 : 24 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
24162 : 24 : return true;
24163 : : }
24164 : :
24165 : : /* Parse an OpenMP structured block sequence. KIND is the corresponding
24166 : : separating directive. */
24167 : :
24168 : : static tree
24169 : 815 : c_parser_omp_structured_block_sequence (c_parser *parser,
24170 : : enum pragma_kind kind)
24171 : : {
24172 : 815 : tree stmt = push_stmt_list ();
24173 : 815 : c_parser_statement (parser, NULL);
24174 : 909 : do
24175 : : {
24176 : 862 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24177 : : break;
24178 : 461 : if (c_parser_next_token_is (parser, CPP_EOF))
24179 : : break;
24180 : :
24181 : 461 : if (kind != PRAGMA_NONE
24182 : 461 : && c_parser_peek_token (parser)->pragma_kind == kind)
24183 : : break;
24184 : :
24185 : 69 : if (kind != PRAGMA_NONE
24186 : 104 : && c_parser_omp_section_scan (parser,
24187 : : kind == PRAGMA_OMP_SCAN
24188 : : ? "scan" : "section", false))
24189 : : break;
24190 : :
24191 : 47 : c_parser_statement (parser, NULL);
24192 : : }
24193 : : while (1);
24194 : 815 : return pop_stmt_list (stmt);
24195 : : }
24196 : :
24197 : : /* OpenMP 5.0:
24198 : :
24199 : : scan-loop-body:
24200 : : { structured-block scan-directive structured-block } */
24201 : :
24202 : : static void
24203 : 264 : c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
24204 : : {
24205 : 264 : tree substmt;
24206 : 264 : location_t loc;
24207 : 264 : tree clauses = NULL_TREE;
24208 : 264 : bool found_scan = false;
24209 : :
24210 : 264 : loc = c_parser_peek_token (parser)->location;
24211 : 264 : if (!open_brace_parsed
24212 : 264 : && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
24213 : : {
24214 : : /* Avoid skipping until the end of the block. */
24215 : 1 : parser->error = false;
24216 : 1 : return;
24217 : : }
24218 : :
24219 : 263 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
24220 : 261 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
24221 : : else
24222 : : {
24223 : 2 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24224 : : "%<#pragma omp scan%> with zero preceding executable "
24225 : : "statements");
24226 : 2 : substmt = build_empty_stmt (loc);
24227 : : }
24228 : 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
24229 : 263 : SET_EXPR_LOCATION (substmt, loc);
24230 : 263 : add_stmt (substmt);
24231 : :
24232 : 263 : loc = c_parser_peek_token (parser)->location;
24233 : 263 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
24234 : : {
24235 : 256 : enum omp_clause_code clause = OMP_CLAUSE_ERROR;
24236 : 256 : found_scan = true;
24237 : :
24238 : 256 : c_parser_consume_pragma (parser);
24239 : :
24240 : 256 : if (c_parser_next_token_is (parser, CPP_COMMA))
24241 : 4 : c_parser_consume_token (parser);
24242 : :
24243 : 256 : if (c_parser_next_token_is (parser, CPP_NAME))
24244 : : {
24245 : 254 : const char *p
24246 : 254 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24247 : 254 : if (strcmp (p, "inclusive") == 0)
24248 : : clause = OMP_CLAUSE_INCLUSIVE;
24249 : 126 : else if (strcmp (p, "exclusive") == 0)
24250 : : clause = OMP_CLAUSE_EXCLUSIVE;
24251 : : }
24252 : : if (clause != OMP_CLAUSE_ERROR)
24253 : : {
24254 : 254 : c_parser_consume_token (parser);
24255 : 254 : clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
24256 : : }
24257 : : else
24258 : 2 : c_parser_error (parser, "expected %<inclusive%> or "
24259 : : "%<exclusive%> clause");
24260 : 256 : c_parser_skip_to_pragma_eol (parser);
24261 : : }
24262 : : else
24263 : 7 : error ("expected %<#pragma omp scan%>");
24264 : :
24265 : 263 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24266 : 263 : if (!c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
24267 : 254 : substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
24268 : : else
24269 : : {
24270 : 9 : if (found_scan)
24271 : 2 : warning_at (loc, OPT_Wopenmp,
24272 : : "%<#pragma omp scan%> with zero succeeding executable "
24273 : : "statements");
24274 : 9 : substmt = build_empty_stmt (loc);
24275 : : }
24276 : 263 : substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
24277 : 263 : SET_EXPR_LOCATION (substmt, loc);
24278 : 263 : add_stmt (substmt);
24279 : :
24280 : 263 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
24281 : : "expected %<}%>");
24282 : : }
24283 : :
24284 : :
24285 : : /* Check if the next tokens can start a canonical loop. Return true if yes,
24286 : : otherwise diagnose an error if ERROR_P is true, and return false. */
24287 : : static bool
24288 : 17287 : c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser,
24289 : : enum tree_code code,
24290 : : bool error_p)
24291 : : {
24292 : 17287 : if (code == OACC_LOOP)
24293 : : {
24294 : 2581 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24295 : : return true;
24296 : 27 : if (error_p)
24297 : 4 : c_parser_error (parser, "for statement expected");
24298 : : }
24299 : : else
24300 : : {
24301 : 14706 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
24302 : : return true;
24303 : :
24304 : 887 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
24305 : 578 : switch (c_parser_peek_token (parser)->pragma_kind)
24306 : : {
24307 : : case PRAGMA_OMP_UNROLL:
24308 : : case PRAGMA_OMP_TILE:
24309 : : return true;
24310 : : default:
24311 : : break;
24312 : : }
24313 : :
24314 : : /* Skip standard attributes on next for in case they are
24315 : : [[omp::directive (unroll partial (4))]] or
24316 : : [[omp::directive (tile sizes (1, 2, 3))]] etc. */
24317 : 319 : size_t n = c_parser_skip_std_attribute_spec_seq (parser, 1);
24318 : 319 : c_token *token = c_parser_peek_nth_token_raw (parser, n);
24319 : : /* TOKEN is a raw token that hasn't been converted to a keyword yet,
24320 : : we have to do the lookup explicitly. */
24321 : 319 : if (token->type == CPP_NAME
24322 : 108 : && C_IS_RESERVED_WORD (token->value)
24323 : 331 : && C_RID_CODE (token->value) == RID_FOR)
24324 : : return true;
24325 : 307 : if (error_p)
24326 : 7 : c_parser_error (parser, "loop nest expected");
24327 : : }
24328 : :
24329 : : return false;
24330 : : }
24331 : :
24332 : : static tree c_parser_omp_tile (location_t, c_parser *, bool *);
24333 : : static tree c_parser_omp_unroll (location_t, c_parser *, bool *);
24334 : :
24335 : : /* This function parses a single level of a loop nest, invoking itself
24336 : : recursively if necessary.
24337 : :
24338 : : loop-nest :: for (...) loop-body
24339 : : loop-body :: loop-nest
24340 : : | { [intervening-code] loop-body [intervening-code] }
24341 : : | final-loop-body
24342 : : intervening-code :: structured-block-sequence
24343 : : final-loop-body :: structured-block
24344 : :
24345 : : For a collapsed loop nest, only a single OMP_FOR is built, pulling out
24346 : : all the iterator information from the inner loops into the
24347 : : parser->omp_for_parse_state structure.
24348 : :
24349 : : The iterator decl, init, cond, and incr are stored in vectors.
24350 : :
24351 : : Initialization code for iterator variables is collected into
24352 : : parser->omp_for_parse_state->pre_body and ends up inserted directly
24353 : : into the OMP_FOR structure. */
24354 : :
24355 : : static tree
24356 : 16953 : c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
24357 : : {
24358 : 16953 : tree decl = NULL_TREE, cond = NULL_TREE, incr = NULL_TREE, init = NULL_TREE;
24359 : 16953 : tree body = NULL_TREE;
24360 : 16953 : matching_parens parens;
24361 : 16953 : bool moreloops;
24362 : 16953 : unsigned char save_in_statement;
24363 : 16953 : tree loop_scope;
24364 : 16953 : location_t loc;
24365 : 16953 : struct omp_for_parse_data *omp_for_parse_state
24366 : : = parser->omp_for_parse_state;
24367 : 16953 : gcc_assert (omp_for_parse_state);
24368 : 16953 : int depth = omp_for_parse_state->depth;
24369 : :
24370 : : /* Arrange for C23 standard attribute syntax to be parsed as regular
24371 : : pragmas. */
24372 : 16953 : if (c_parser_nth_token_starts_std_attributes (parser, 1))
24373 : : {
24374 : 12 : tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24375 : 12 : c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL);
24376 : 12 : if (std_attrs)
24377 : 0 : error_at (c_parser_peek_token (parser)->location,
24378 : : "attributes other than OpenMP directives "
24379 : : "are not allowed on %<for%> in loop nest");
24380 : : }
24381 : :
24382 : 16953 : loc = c_parser_peek_token (parser)->location;
24383 : :
24384 : : /* Handle loop transformations first. */
24385 : 16953 : if (c_parser_next_token_is (parser, CPP_PRAGMA))
24386 : : {
24387 : 576 : tree transform = NULL_TREE, sizes, body = NULL_TREE;
24388 : 576 : int count = 0;
24389 : 576 : switch (c_parser_peek_token (parser)->pragma_kind)
24390 : : {
24391 : 208 : case PRAGMA_OMP_UNROLL:
24392 : 208 : c_parser_consume_pragma (parser);
24393 : 208 : body = push_stmt_list ();
24394 : 208 : transform = c_parser_omp_unroll (loc, parser, if_p);
24395 : 208 : body = pop_stmt_list (body);
24396 : 208 : if (transform == NULL_TREE || transform == error_mark_node)
24397 : : {
24398 : 7 : transform = error_mark_node;
24399 : 7 : break;
24400 : : }
24401 : 201 : gcc_assert (TREE_CODE (transform) == OMP_UNROLL);
24402 : 201 : if (omp_find_clause (OMP_FOR_CLAUSES (transform),
24403 : : OMP_CLAUSE_PARTIAL))
24404 : : {
24405 : 172 : if (omp_for_parse_state->count - depth > 1)
24406 : : {
24407 : 10 : error_at (loc, "%<unroll%> construct with %<partial%> "
24408 : : "clause generates just one loop with "
24409 : : "canonical form but %d loops are needed",
24410 : : omp_for_parse_state->count - depth);
24411 : 10 : transform = error_mark_node;
24412 : : }
24413 : : else
24414 : 576 : count = 1;
24415 : : }
24416 : : else
24417 : : {
24418 : 29 : error_at (loc, "generated loop of %<unroll%> construct "
24419 : : "without %<partial%> clause does not have "
24420 : : "canonical form");
24421 : 29 : transform = error_mark_node;
24422 : : }
24423 : : break;
24424 : 366 : case PRAGMA_OMP_TILE:
24425 : 366 : c_parser_consume_pragma (parser);
24426 : 366 : body = push_stmt_list ();
24427 : 366 : transform = c_parser_omp_tile (loc, parser, if_p);
24428 : 366 : body = pop_stmt_list (body);
24429 : 366 : if (transform == NULL_TREE || transform == error_mark_node)
24430 : : {
24431 : 40 : transform = error_mark_node;
24432 : 40 : break;
24433 : : }
24434 : 326 : gcc_assert (TREE_CODE (transform) == OMP_TILE);
24435 : 326 : sizes = omp_find_clause (OMP_FOR_CLAUSES (transform),
24436 : : OMP_CLAUSE_SIZES);
24437 : 326 : gcc_assert (sizes);
24438 : 326 : count = list_length (OMP_CLAUSE_SIZES_LIST (sizes));
24439 : 326 : if (depth + count < omp_for_parse_state->count)
24440 : : {
24441 : 16 : error_at (loc, "%<tile%> construct generates %d loops "
24442 : : "with canonical form but %d loops are needed",
24443 : : count, omp_for_parse_state->count - depth);
24444 : 16 : transform = error_mark_node;
24445 : : }
24446 : : break;
24447 : 2 : default:
24448 : 2 : c_parser_pragma (parser, pragma_stmt, NULL, void_list_node);
24449 : 2 : break;
24450 : : }
24451 : 576 : if (transform == NULL_TREE)
24452 : 2 : error_at (loc, "expected %<for%> loop or OpenMP loop "
24453 : : "transformation construct");
24454 : 576 : if (transform == NULL_TREE || transform == error_mark_node)
24455 : : {
24456 : 104 : omp_for_parse_state->fail = true;
24457 : 104 : return NULL_TREE;
24458 : : }
24459 : 1030 : for (count = omp_for_parse_state->count; depth < count; ++depth)
24460 : : {
24461 : 558 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE;
24462 : 558 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE;
24463 : 558 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE;
24464 : 558 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE;
24465 : : }
24466 : 472 : omp_for_parse_state->want_nested_loop = false;
24467 : 472 : return body;
24468 : : }
24469 : :
24470 : : /* We have already matched the FOR token but not consumed it yet. */
24471 : 16377 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
24472 : 16377 : c_parser_consume_token (parser);
24473 : :
24474 : : /* Forbid break/continue in the loop initializer, condition, and
24475 : : increment expressions. */
24476 : 16377 : save_in_statement = in_statement;
24477 : 16377 : in_statement = IN_OMP_BLOCK;
24478 : :
24479 : : /* We are not in intervening code now. */
24480 : 16377 : omp_for_parse_state->in_intervening_code = false;
24481 : :
24482 : 16377 : if (!parens.require_open (parser))
24483 : : {
24484 : 0 : omp_for_parse_state->fail = true;
24485 : 0 : return NULL_TREE;
24486 : : }
24487 : :
24488 : : /* An implicit scope block surrounds each level of FOR loop, for
24489 : : declarations of iteration variables at this loop depth. */
24490 : 16377 : loop_scope = c_begin_compound_stmt (true);
24491 : :
24492 : : /* Parse the initialization declaration or expression. */
24493 : 16377 : if (c_parser_next_tokens_start_declaration (parser))
24494 : : {
24495 : : /* This is a declaration, which must be added to the pre_body code. */
24496 : 4737 : tree this_pre_body = push_stmt_list ();
24497 : 4737 : c_in_omp_for = true;
24498 : 4737 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
24499 : : false);
24500 : 4737 : c_in_omp_for = false;
24501 : 4737 : this_pre_body = pop_stmt_list (this_pre_body);
24502 : 4737 : append_to_statement_list_force (this_pre_body,
24503 : : &(omp_for_parse_state->pre_body));
24504 : 4737 : decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
24505 : 4737 : if (decl == NULL)
24506 : 0 : goto error_init;
24507 : 4737 : if (DECL_INITIAL (decl) == error_mark_node)
24508 : 1 : decl = error_mark_node;
24509 : : init = decl;
24510 : : }
24511 : 11640 : else if (c_parser_next_token_is (parser, CPP_NAME)
24512 : 11640 : && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
24513 : : {
24514 : 11638 : struct c_expr decl_exp;
24515 : 11638 : struct c_expr init_exp;
24516 : 11638 : location_t init_loc;
24517 : :
24518 : 11638 : decl_exp = c_parser_postfix_expression (parser);
24519 : 11638 : decl = decl_exp.value;
24520 : :
24521 : 11638 : c_parser_require (parser, CPP_EQ, "expected %<=%>");
24522 : :
24523 : 11638 : init_loc = c_parser_peek_token (parser)->location;
24524 : 11638 : init_exp = c_parser_expr_no_commas (parser, NULL);
24525 : 11638 : init_exp = default_function_array_read_conversion (init_loc,
24526 : : init_exp);
24527 : 11638 : c_in_omp_for = true;
24528 : 11638 : init = build_modify_expr (init_loc, decl, decl_exp.original_type,
24529 : : NOP_EXPR, init_loc, init_exp.value,
24530 : : init_exp.original_type);
24531 : 11638 : c_in_omp_for = false;
24532 : 11638 : init = c_process_expr_stmt (init_loc, init);
24533 : :
24534 : 11638 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24535 : : }
24536 : : else
24537 : : {
24538 : 2 : error_init:
24539 : 2 : c_parser_error (parser,
24540 : : "expected iteration declaration or initialization");
24541 : 2 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
24542 : : "expected %<)%>");
24543 : 2 : omp_for_parse_state->fail = true;
24544 : 2 : goto parse_next;
24545 : : }
24546 : :
24547 : : /* Parse the loop condition. */
24548 : 16375 : if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
24549 : : {
24550 : 16373 : location_t cond_loc = c_parser_peek_token (parser)->location;
24551 : 16373 : c_in_omp_for = true;
24552 : 16373 : struct c_expr cond_expr
24553 : 16373 : = c_parser_binary_expression (parser, NULL, NULL_TREE);
24554 : 16373 : c_in_omp_for = false;
24555 : :
24556 : 16373 : cond = cond_expr.value;
24557 : 16373 : cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
24558 : 16373 : switch (cond_expr.original_code)
24559 : : {
24560 : : case GT_EXPR:
24561 : : case GE_EXPR:
24562 : : case LT_EXPR:
24563 : : case LE_EXPR:
24564 : : break;
24565 : 2425 : case NE_EXPR:
24566 : 2425 : if (omp_for_parse_state->code != OACC_LOOP)
24567 : : break;
24568 : : /* FALLTHRU. */
24569 : 7 : default:
24570 : : /* Can't be cond = error_mark_node, because we want to preserve
24571 : : the location until c_finish_omp_for. */
24572 : 7 : cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
24573 : 7 : break;
24574 : : }
24575 : 16373 : protected_set_expr_location (cond, cond_loc);
24576 : : }
24577 : 16375 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
24578 : :
24579 : : /* Parse the increment expression. */
24580 : 16375 : if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
24581 : : {
24582 : 16375 : location_t incr_loc = c_parser_peek_token (parser)->location;
24583 : :
24584 : 16375 : incr = c_process_expr_stmt (incr_loc,
24585 : 32750 : c_parser_expression (parser).value);
24586 : : }
24587 : 16375 : parens.skip_until_found_close (parser);
24588 : :
24589 : 16375 : if (decl == NULL || decl == error_mark_node || init == error_mark_node)
24590 : 3 : omp_for_parse_state->fail = true;
24591 : : else
24592 : : {
24593 : 16372 : TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
24594 : 16372 : TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
24595 : 16372 : TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
24596 : 16372 : TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
24597 : : }
24598 : :
24599 : 16377 : parse_next:
24600 : 16377 : moreloops = depth < omp_for_parse_state->count - 1;
24601 : 16377 : omp_for_parse_state->want_nested_loop = moreloops;
24602 : 16377 : if (moreloops
24603 : 16377 : && c_parser_omp_next_tokens_can_be_canon_loop (parser,
24604 : : omp_for_parse_state->code,
24605 : : false))
24606 : : {
24607 : 5325 : omp_for_parse_state->depth++;
24608 : 5325 : body = c_parser_omp_loop_nest (parser, if_p);
24609 : 5325 : omp_for_parse_state->depth--;
24610 : : }
24611 : 11192 : else if (moreloops && c_parser_next_token_is (parser, CPP_OPEN_BRACE))
24612 : : {
24613 : : /* This is the open brace in the loop-body grammar production. Rather
24614 : : than trying to special-case braces, just parse it as a compound
24615 : : statement and handle the nested loop-body case there. Note that
24616 : : when we see a further open brace inside the compound statement
24617 : : loop-body, we don't know whether it is the start of intervening
24618 : : code that is a compound statement, or a level of braces
24619 : : surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
24620 : : bit to ensure we have only one nested loop at each level. */
24621 : 121 : omp_for_parse_state->in_intervening_code = true;
24622 : 121 : body = c_parser_compound_statement (parser, NULL);
24623 : 121 : omp_for_parse_state->in_intervening_code = false;
24624 : 121 : if (omp_for_parse_state->want_nested_loop)
24625 : : {
24626 : : /* We have already parsed the whole loop body and not found a
24627 : : nested loop. */
24628 : 11 : error_at (omp_for_parse_state->for_loc,
24629 : : "not enough nested loops");
24630 : 11 : omp_for_parse_state->fail = true;
24631 : : }
24632 : 16377 : if_p = NULL;
24633 : : }
24634 : : else
24635 : : {
24636 : : /* This is the final-loop-body case in the grammar: we have
24637 : : something that is not a FOR and not an open brace. */
24638 : 10931 : if (moreloops)
24639 : : {
24640 : : /* If we were expecting a nested loop, give an error and mark
24641 : : that parsing has failed, and try to recover by parsing the
24642 : : body as regular code without further collapsing. */
24643 : 19 : error_at (omp_for_parse_state->for_loc,
24644 : : "not enough nested loops");
24645 : 19 : omp_for_parse_state->fail = true;
24646 : : }
24647 : 10931 : in_statement = IN_OMP_FOR;
24648 : 10931 : parser->omp_for_parse_state = NULL;
24649 : 10931 : body = push_stmt_list ();
24650 : 10931 : if (omp_for_parse_state->inscan)
24651 : 264 : c_parser_omp_scan_loop_body (parser, false);
24652 : : else
24653 : 10667 : add_stmt (c_parser_c99_block_statement (parser, if_p));
24654 : 10931 : body = pop_stmt_list (body);
24655 : 10931 : parser->omp_for_parse_state = omp_for_parse_state;
24656 : : }
24657 : 16377 : in_statement = save_in_statement;
24658 : 16377 : omp_for_parse_state->want_nested_loop = false;
24659 : 16377 : omp_for_parse_state->in_intervening_code = true;
24660 : :
24661 : : /* Pop and return the implicit scope surrounding this level of loop.
24662 : : If the iteration variable at this depth was bound in the for loop,
24663 : : pull out and save the binding. Later in c_parser_omp_for_loop,
24664 : : these bindings will be moved to the scope surrounding the entire
24665 : : OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
24666 : : we have already resolved all references to the iteration variable
24667 : : in its true scope. */
24668 : 16377 : if (body)
24669 : 16371 : add_stmt (body);
24670 : 16377 : body = c_end_compound_stmt (loc, loop_scope, true);
24671 : 16377 : if (decl && TREE_CODE (body) == BIND_EXPR)
24672 : : {
24673 : 5123 : tree t = BIND_EXPR_VARS (body);
24674 : 5123 : tree prev = NULL_TREE, next = NULL_TREE;
24675 : 5559 : while (t)
24676 : : {
24677 : 5172 : next = DECL_CHAIN (t);
24678 : 5172 : if (t == decl)
24679 : : {
24680 : 4736 : if (prev)
24681 : 0 : DECL_CHAIN (prev) = next;
24682 : : else
24683 : : {
24684 : 4736 : BIND_EXPR_VARS (body) = next;
24685 : 4736 : BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
24686 : : }
24687 : 4736 : DECL_CHAIN (t) = omp_for_parse_state->bindings;
24688 : 4736 : omp_for_parse_state->bindings = t;
24689 : 4736 : break;
24690 : : }
24691 : : else
24692 : : {
24693 : : prev = t;
24694 : : t = next;
24695 : : }
24696 : : }
24697 : 5123 : if (BIND_EXPR_VARS (body) == NULL_TREE)
24698 : 4736 : body = BIND_EXPR_BODY (body);
24699 : : }
24700 : :
24701 : : return body;
24702 : : }
24703 : :
24704 : : /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
24705 : : The real trick here is to determine the loop control variable early
24706 : : so that we can push a new decl if necessary to make it private.
24707 : : LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
24708 : : respectively. */
24709 : :
24710 : : static tree
24711 : 11529 : c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
24712 : : tree clauses, tree *cclauses, bool *if_p)
24713 : : {
24714 : 11529 : tree body, stmt, cl;
24715 : 11529 : tree ret = NULL_TREE;
24716 : 11529 : tree ordered_cl = NULL_TREE;
24717 : 11529 : int i, collapse = 1, ordered = 0, count;
24718 : 11529 : bool oacc_tiling = false;
24719 : 11529 : bool inscan = false;
24720 : 11529 : struct omp_for_parse_data data;
24721 : 11529 : struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
24722 : :
24723 : 27444 : for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
24724 : 15915 : if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
24725 : 2946 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
24726 : 12969 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
24727 : : {
24728 : 111 : oacc_tiling = true;
24729 : 111 : collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
24730 : : }
24731 : 12858 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES)
24732 : 464 : collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl));
24733 : 12394 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
24734 : 12394 : && OMP_CLAUSE_ORDERED_EXPR (cl))
24735 : : {
24736 : 160 : ordered_cl = cl;
24737 : 160 : ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
24738 : : }
24739 : 12234 : else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
24740 : 2106 : && OMP_CLAUSE_REDUCTION_INSCAN (cl)
24741 : 12619 : && (code == OMP_SIMD || code == OMP_FOR))
24742 : : inscan = true;
24743 : :
24744 : 11529 : if (ordered && ordered < collapse)
24745 : : {
24746 : 2 : error_at (OMP_CLAUSE_LOCATION (ordered_cl),
24747 : : "%<ordered%> clause parameter is less than %<collapse%>");
24748 : 2 : OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
24749 : 2 : = build_int_cst (NULL_TREE, collapse);
24750 : 2 : ordered = collapse;
24751 : : }
24752 : :
24753 : 11529 : gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0));
24754 : 11529 : count = ordered ? ordered : collapse;
24755 : :
24756 : 11529 : if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, true))
24757 : : return NULL;
24758 : :
24759 : : /* Initialize parse state for recursive descent. */
24760 : 11518 : data.declv = make_tree_vec (count);
24761 : 11518 : data.initv = make_tree_vec (count);
24762 : 11518 : data.condv = make_tree_vec (count);
24763 : 11518 : data.incrv = make_tree_vec (count);
24764 : 11518 : data.pre_body = NULL_TREE;
24765 : 11518 : data.bindings = NULL_TREE;
24766 : 11518 : data.for_loc = c_parser_peek_token (parser)->location;
24767 : 11518 : data.count = count;
24768 : 11518 : data.depth = 0;
24769 : 11518 : data.want_nested_loop = true;
24770 : 11518 : data.ordered = ordered > 0;
24771 : 11518 : data.in_intervening_code = false;
24772 : 11518 : data.perfect_nesting_fail = false;
24773 : 11518 : data.fail = false;
24774 : 11518 : data.inscan = inscan;
24775 : 11518 : data.saw_intervening_code = false;
24776 : 11518 : data.code = code;
24777 : 11518 : parser->omp_for_parse_state = &data;
24778 : :
24779 : 11518 : body = c_parser_omp_loop_nest (parser, if_p);
24780 : :
24781 : : /* Add saved bindings for iteration variables that were declared in
24782 : : the nested for loop to the scope surrounding the entire loop. */
24783 : 16254 : for (tree t = data.bindings; t; )
24784 : : {
24785 : 4736 : tree n = TREE_CHAIN (t);
24786 : 4736 : TREE_CHAIN (t) = NULL_TREE;
24787 : 4736 : pushdecl (t);
24788 : 4736 : t = n;
24789 : : }
24790 : :
24791 : : /* Only bother calling c_finish_omp_for if we haven't already generated
24792 : : an error from the initialization parsing. */
24793 : 11518 : if (!data.fail)
24794 : : {
24795 : 11355 : c_in_omp_for = true;
24796 : 11355 : stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
24797 : : data.condv, data.incrv,
24798 : : body, data.pre_body, true);
24799 : 11355 : c_in_omp_for = false;
24800 : :
24801 : : /* Check for iterators appearing in lb, b or incr expressions. */
24802 : 11355 : if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
24803 : : stmt = NULL_TREE;
24804 : :
24805 : : /* Check for errors involving lb/ub/incr expressions referencing
24806 : : variables declared in intervening code. */
24807 : 11355 : if (data.saw_intervening_code
24808 : 38 : && stmt
24809 : 11393 : && !c_omp_check_loop_binding_exprs (stmt, NULL))
24810 : : stmt = NULL_TREE;
24811 : :
24812 : 11345 : if (stmt)
24813 : : {
24814 : 11200 : add_stmt (stmt);
24815 : :
24816 : 27275 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
24817 : : {
24818 : 16533 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
24819 : 16533 : if (init == NULL_TREE)
24820 : : break;
24821 : 16075 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
24822 : 16075 : tree decl = TREE_OPERAND (init, 0);
24823 : 16075 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
24824 : 16075 : gcc_assert (COMPARISON_CLASS_P (cond));
24825 : 16075 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
24826 : :
24827 : 16075 : tree op0 = TREE_OPERAND (init, 1);
24828 : 16075 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
24829 : 16075 : || TREE_CODE (op0) != TREE_VEC)
24830 : 15888 : TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
24831 : : else
24832 : : {
24833 : 187 : TREE_VEC_ELT (op0, 1)
24834 : 187 : = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
24835 : 187 : TREE_VEC_ELT (op0, 2)
24836 : 374 : = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
24837 : : }
24838 : :
24839 : 16075 : tree op1 = TREE_OPERAND (cond, 1);
24840 : 16075 : if (!OMP_FOR_NON_RECTANGULAR (stmt)
24841 : 16075 : || TREE_CODE (op1) != TREE_VEC)
24842 : 15869 : TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
24843 : : else
24844 : : {
24845 : 206 : TREE_VEC_ELT (op1, 1)
24846 : 206 : = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
24847 : 206 : TREE_VEC_ELT (op1, 2)
24848 : 412 : = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
24849 : : }
24850 : : }
24851 : :
24852 : 11200 : if (cclauses != NULL
24853 : 5258 : && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
24854 : : {
24855 : 755 : tree *c;
24856 : 3313 : for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
24857 : 2558 : if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
24858 : 2558 : && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
24859 : 1858 : c = &OMP_CLAUSE_CHAIN (*c);
24860 : : else
24861 : : {
24862 : 1441 : for (i = 0; i < count; i++)
24863 : 923 : if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
24864 : : break;
24865 : 700 : if (i == count)
24866 : 518 : c = &OMP_CLAUSE_CHAIN (*c);
24867 : 182 : else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
24868 : : {
24869 : 1 : error_at (loc,
24870 : : "iteration variable %qD should not be firstprivate",
24871 : 1 : OMP_CLAUSE_DECL (*c));
24872 : 1 : *c = OMP_CLAUSE_CHAIN (*c);
24873 : : }
24874 : : else
24875 : : {
24876 : : /* Move lastprivate (decl) clause to
24877 : : OMP_FOR_CLAUSES. */
24878 : 181 : tree l = *c;
24879 : 181 : *c = OMP_CLAUSE_CHAIN (*c);
24880 : 181 : if (code == OMP_SIMD)
24881 : : {
24882 : 46 : OMP_CLAUSE_CHAIN (l)
24883 : 46 : = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24884 : 46 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
24885 : : }
24886 : : else
24887 : : {
24888 : 135 : OMP_CLAUSE_CHAIN (l) = clauses;
24889 : 135 : clauses = l;
24890 : : }
24891 : : }
24892 : : }
24893 : : }
24894 : 11200 : OMP_FOR_CLAUSES (stmt) = clauses;
24895 : : }
24896 : : ret = stmt;
24897 : : }
24898 : :
24899 : 11518 : parser->omp_for_parse_state = save_data;
24900 : 11518 : return ret;
24901 : : }
24902 : :
24903 : : /* Helper function for OpenMP parsing, split clauses and call
24904 : : finish_omp_clauses on each of the set of clauses afterwards. */
24905 : :
24906 : : static void
24907 : 6564 : omp_split_clauses (location_t loc, enum tree_code code,
24908 : : omp_clause_mask mask, tree clauses, tree *cclauses)
24909 : : {
24910 : 6564 : int i;
24911 : 6564 : c_omp_split_clauses (loc, code, mask, clauses, cclauses);
24912 : 52512 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
24913 : 39384 : if (cclauses[i])
24914 : 20230 : cclauses[i] = c_finish_omp_clauses (cclauses[i],
24915 : : i == C_OMP_CLAUSE_SPLIT_TARGET
24916 : : ? C_ORT_OMP_TARGET : C_ORT_OMP);
24917 : 6564 : }
24918 : :
24919 : : /* OpenMP 5.0:
24920 : : #pragma omp loop loop-clause[optseq] new-line
24921 : : for-loop
24922 : :
24923 : : LOC is the location of the #pragma token.
24924 : : */
24925 : :
24926 : : #define OMP_LOOP_CLAUSE_MASK \
24927 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24928 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24929 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24930 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24931 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
24932 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24933 : :
24934 : : static tree
24935 : 237 : c_parser_omp_loop (location_t loc, c_parser *parser,
24936 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24937 : : bool *if_p)
24938 : : {
24939 : 237 : tree block, clauses, ret;
24940 : :
24941 : 237 : strcat (p_name, " loop");
24942 : 237 : mask |= OMP_LOOP_CLAUSE_MASK;
24943 : :
24944 : 237 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
24945 : 237 : if (cclauses)
24946 : : {
24947 : 80 : omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses);
24948 : 80 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
24949 : : }
24950 : :
24951 : 237 : block = c_begin_compound_stmt (true);
24952 : 237 : ret = c_parser_omp_for_loop (loc, parser, OMP_LOOP, clauses, cclauses, if_p);
24953 : 237 : block = c_end_compound_stmt (loc, block, true);
24954 : 237 : add_stmt (block);
24955 : :
24956 : 237 : return ret;
24957 : : }
24958 : :
24959 : : /* OpenMP 4.0:
24960 : : #pragma omp simd simd-clause[optseq] new-line
24961 : : for-loop
24962 : :
24963 : : LOC is the location of the #pragma token.
24964 : : */
24965 : :
24966 : : #define OMP_SIMD_CLAUSE_MASK \
24967 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
24968 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
24969 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24970 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
24971 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24972 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24973 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24974 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24975 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
24976 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
24977 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24978 : :
24979 : : static tree
24980 : 3507 : c_parser_omp_simd (location_t loc, c_parser *parser,
24981 : : char *p_name, omp_clause_mask mask, tree *cclauses,
24982 : : bool *if_p)
24983 : : {
24984 : 3507 : tree block, clauses, ret;
24985 : :
24986 : 3507 : strcat (p_name, " simd");
24987 : 3507 : mask |= OMP_SIMD_CLAUSE_MASK;
24988 : :
24989 : 3507 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
24990 : 3507 : if (cclauses)
24991 : : {
24992 : 2781 : omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
24993 : 2781 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
24994 : : }
24995 : :
24996 : 3507 : block = c_begin_compound_stmt (true);
24997 : 3507 : ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
24998 : 3507 : block = c_end_compound_stmt (loc, block, true);
24999 : 3507 : add_stmt (block);
25000 : :
25001 : 3507 : return ret;
25002 : : }
25003 : :
25004 : : /* OpenMP 2.5:
25005 : : #pragma omp for for-clause[optseq] new-line
25006 : : for-loop
25007 : :
25008 : : OpenMP 4.0:
25009 : : #pragma omp for simd for-simd-clause[optseq] new-line
25010 : : for-loop
25011 : :
25012 : : LOC is the location of the #pragma token.
25013 : : */
25014 : :
25015 : : #define OMP_FOR_CLAUSE_MASK \
25016 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25017 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25018 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25019 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
25020 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25021 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
25022 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
25023 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25024 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25025 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25026 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25027 : :
25028 : : static tree
25029 : 6178 : c_parser_omp_for (location_t loc, c_parser *parser,
25030 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25031 : : bool *if_p)
25032 : : {
25033 : 6178 : tree block, clauses, ret;
25034 : :
25035 : 6178 : strcat (p_name, " for");
25036 : 6178 : mask |= OMP_FOR_CLAUSE_MASK;
25037 : : /* parallel for{, simd} disallows nowait clause, but for
25038 : : target {teams distribute ,}parallel for{, simd} it should be accepted. */
25039 : 6178 : if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
25040 : 3247 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25041 : : /* Composite distribute parallel for{, simd} disallows ordered clause. */
25042 : 6178 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25043 : 2724 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
25044 : :
25045 : 6178 : if (c_parser_next_token_is (parser, CPP_NAME))
25046 : : {
25047 : 5430 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25048 : :
25049 : 5430 : if (strcmp (p, "simd") == 0)
25050 : : {
25051 : 2203 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25052 : 2203 : if (cclauses == NULL)
25053 : 300 : cclauses = cclauses_buf;
25054 : :
25055 : 2203 : c_parser_consume_token (parser);
25056 : 2203 : if (!flag_openmp) /* flag_openmp_simd */
25057 : 14 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25058 : 14 : if_p);
25059 : 2189 : block = c_begin_compound_stmt (true);
25060 : 2189 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
25061 : 2189 : block = c_end_compound_stmt (loc, block, true);
25062 : 2189 : if (ret == NULL_TREE)
25063 : : return ret;
25064 : 2178 : ret = make_node (OMP_FOR);
25065 : 2178 : TREE_TYPE (ret) = void_type_node;
25066 : 2178 : OMP_FOR_BODY (ret) = block;
25067 : 2178 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25068 : 2178 : SET_EXPR_LOCATION (ret, loc);
25069 : 2178 : add_stmt (ret);
25070 : 2178 : return ret;
25071 : : }
25072 : : }
25073 : 3975 : if (!flag_openmp) /* flag_openmp_simd */
25074 : : {
25075 : 9 : c_parser_skip_to_pragma_eol (parser, false);
25076 : 9 : return NULL_TREE;
25077 : : }
25078 : :
25079 : : /* Composite distribute parallel for disallows linear clause. */
25080 : 3966 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25081 : 1371 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
25082 : :
25083 : 3966 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25084 : 3966 : if (cclauses)
25085 : : {
25086 : 2461 : omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
25087 : 2461 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
25088 : : }
25089 : :
25090 : 3966 : block = c_begin_compound_stmt (true);
25091 : 3966 : ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
25092 : 3966 : block = c_end_compound_stmt (loc, block, true);
25093 : 3966 : add_stmt (block);
25094 : :
25095 : 3966 : return ret;
25096 : : }
25097 : :
25098 : : static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
25099 : : omp_clause_mask, tree *, bool *);
25100 : :
25101 : : /* OpenMP 2.5:
25102 : : # pragma omp master new-line
25103 : : structured-block
25104 : :
25105 : : LOC is the location of the #pragma token.
25106 : : */
25107 : :
25108 : : static tree
25109 : 231 : c_parser_omp_master (location_t loc, c_parser *parser,
25110 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25111 : : bool *if_p)
25112 : : {
25113 : 231 : tree block, clauses, ret;
25114 : :
25115 : 231 : strcat (p_name, " master");
25116 : :
25117 : 231 : if (c_parser_next_token_is (parser, CPP_NAME))
25118 : : {
25119 : 123 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25120 : :
25121 : 123 : if (strcmp (p, "taskloop") == 0)
25122 : : {
25123 : 94 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25124 : 94 : if (cclauses == NULL)
25125 : 47 : cclauses = cclauses_buf;
25126 : :
25127 : 94 : c_parser_consume_token (parser);
25128 : 94 : if (!flag_openmp) /* flag_openmp_simd */
25129 : 4 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25130 : 4 : if_p);
25131 : 90 : block = c_begin_compound_stmt (true);
25132 : 90 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25133 : : if_p);
25134 : 90 : block = c_end_compound_stmt (loc, block, true);
25135 : 90 : if (ret == NULL_TREE)
25136 : : return ret;
25137 : 90 : ret = c_finish_omp_master (loc, block);
25138 : 90 : OMP_MASTER_COMBINED (ret) = 1;
25139 : 90 : return ret;
25140 : : }
25141 : : }
25142 : 137 : if (!flag_openmp) /* flag_openmp_simd */
25143 : : {
25144 : 2 : c_parser_skip_to_pragma_eol (parser, false);
25145 : 2 : return NULL_TREE;
25146 : : }
25147 : :
25148 : 135 : if (cclauses)
25149 : : {
25150 : 41 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
25151 : 41 : omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
25152 : : }
25153 : : else
25154 : 94 : c_parser_skip_to_pragma_eol (parser);
25155 : :
25156 : 135 : return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
25157 : 135 : if_p));
25158 : : }
25159 : :
25160 : : /* OpenMP 5.1:
25161 : : # pragma omp masked masked-clauses new-line
25162 : : structured-block
25163 : :
25164 : : LOC is the location of the #pragma token.
25165 : : */
25166 : :
25167 : : #define OMP_MASKED_CLAUSE_MASK \
25168 : : (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
25169 : :
25170 : : static tree
25171 : 116 : c_parser_omp_masked (location_t loc, c_parser *parser,
25172 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25173 : : bool *if_p)
25174 : : {
25175 : 116 : tree block, clauses, ret;
25176 : :
25177 : 116 : strcat (p_name, " masked");
25178 : 116 : mask |= OMP_MASKED_CLAUSE_MASK;
25179 : :
25180 : 116 : if (c_parser_next_token_is (parser, CPP_NAME))
25181 : : {
25182 : 86 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25183 : :
25184 : 86 : if (strcmp (p, "taskloop") == 0)
25185 : : {
25186 : 67 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25187 : 67 : if (cclauses == NULL)
25188 : 20 : cclauses = cclauses_buf;
25189 : :
25190 : 67 : c_parser_consume_token (parser);
25191 : 67 : if (!flag_openmp) /* flag_openmp_simd */
25192 : 0 : return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25193 : 0 : if_p);
25194 : 67 : block = c_begin_compound_stmt (true);
25195 : 67 : ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25196 : : if_p);
25197 : 67 : block = c_end_compound_stmt (loc, block, true);
25198 : 67 : if (ret == NULL_TREE)
25199 : : return ret;
25200 : 67 : ret = c_finish_omp_masked (loc, block,
25201 : : cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
25202 : 67 : OMP_MASKED_COMBINED (ret) = 1;
25203 : 67 : return ret;
25204 : : }
25205 : : }
25206 : 49 : if (!flag_openmp) /* flag_openmp_simd */
25207 : : {
25208 : 0 : c_parser_skip_to_pragma_eol (parser, false);
25209 : 0 : return NULL_TREE;
25210 : : }
25211 : :
25212 : 49 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25213 : 49 : if (cclauses)
25214 : : {
25215 : 9 : omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
25216 : 9 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
25217 : : }
25218 : :
25219 : 49 : return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
25220 : : if_p),
25221 : 49 : clauses);
25222 : : }
25223 : :
25224 : : /* OpenMP 5.1:
25225 : : # pragma omp interop clauses[opt] new-line */
25226 : :
25227 : : #define OMP_INTEROP_CLAUSE_MASK \
25228 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25229 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DESTROY) \
25230 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25231 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INIT) \
25232 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25233 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE))
25234 : :
25235 : : static void
25236 : 183 : c_parser_omp_interop (c_parser *parser)
25237 : : {
25238 : 183 : location_t loc = c_parser_peek_token (parser)->location;
25239 : 183 : c_parser_consume_pragma (parser);
25240 : 366 : tree clauses = c_parser_omp_all_clauses (parser,
25241 : 183 : OMP_INTEROP_CLAUSE_MASK,
25242 : : "#pragma omp interop");
25243 : 183 : tree stmt = make_node (OMP_INTEROP);
25244 : 183 : TREE_TYPE (stmt) = void_type_node;
25245 : 183 : OMP_INTEROP_CLAUSES (stmt) = clauses;
25246 : 183 : SET_EXPR_LOCATION (stmt, loc);
25247 : 183 : add_stmt (stmt);
25248 : 183 : }
25249 : :
25250 : : /* OpenMP 2.5:
25251 : : # pragma omp ordered new-line
25252 : : structured-block
25253 : :
25254 : : OpenMP 4.5:
25255 : : # pragma omp ordered ordered-clauses new-line
25256 : : structured-block
25257 : :
25258 : : # pragma omp ordered depend-clauses new-line
25259 : :
25260 : : OpenMP 5.2
25261 : : # pragma omp ordered doacross-clauses new-line */
25262 : :
25263 : : #define OMP_ORDERED_CLAUSE_MASK \
25264 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
25265 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
25266 : :
25267 : : #define OMP_ORDERED_DEPEND_CLAUSE_MASK \
25268 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25269 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
25270 : :
25271 : : static bool
25272 : 543 : c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
25273 : : bool *if_p)
25274 : : {
25275 : 543 : location_t loc = c_parser_peek_token (parser)->location;
25276 : 543 : c_parser_consume_pragma (parser);
25277 : :
25278 : 543 : if (context != pragma_stmt && context != pragma_compound)
25279 : : {
25280 : 1 : c_parser_error (parser, "expected declaration specifiers");
25281 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25282 : 1 : return false;
25283 : : }
25284 : :
25285 : 542 : int n = 1;
25286 : 542 : if (c_parser_next_token_is (parser, CPP_COMMA))
25287 : 8 : n = 2;
25288 : :
25289 : 542 : if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
25290 : : {
25291 : 431 : const char *p
25292 : 431 : = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
25293 : :
25294 : 431 : if (!strcmp ("depend", p) || !strcmp ("doacross", p))
25295 : : {
25296 : 347 : if (!flag_openmp) /* flag_openmp_simd */
25297 : : {
25298 : 2 : c_parser_skip_to_pragma_eol (parser, false);
25299 : 2 : return false;
25300 : : }
25301 : 345 : if (context == pragma_stmt)
25302 : : {
25303 : 16 : error_at (loc,
25304 : : "%<#pragma omp ordered%> with %qs clause may "
25305 : : "only be used in compound statements", p);
25306 : 16 : c_parser_skip_to_pragma_eol (parser, false);
25307 : 16 : return true;
25308 : : }
25309 : :
25310 : 329 : tree clauses
25311 : 658 : = c_parser_omp_all_clauses (parser,
25312 : 329 : OMP_ORDERED_DEPEND_CLAUSE_MASK,
25313 : : "#pragma omp ordered");
25314 : 329 : c_finish_omp_ordered (loc, clauses, NULL_TREE);
25315 : 329 : return false;
25316 : : }
25317 : : }
25318 : :
25319 : 195 : tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
25320 : : "#pragma omp ordered");
25321 : :
25322 : 195 : if (!flag_openmp /* flag_openmp_simd */
25323 : 195 : && omp_find_clause (clauses, OMP_CLAUSE_SIMD) == NULL_TREE)
25324 : : return false;
25325 : :
25326 : 193 : c_finish_omp_ordered (loc, clauses,
25327 : : c_parser_omp_structured_block (parser, if_p));
25328 : 193 : return true;
25329 : : }
25330 : :
25331 : : /* OpenMP 2.5:
25332 : :
25333 : : section-scope:
25334 : : { section-sequence }
25335 : :
25336 : : section-sequence:
25337 : : section-directive[opt] structured-block
25338 : : section-sequence section-directive structured-block
25339 : :
25340 : : OpenMP 5.1 allows structured-block-sequence instead of structured-block.
25341 : :
25342 : : SECTIONS_LOC is the location of the #pragma omp sections. */
25343 : :
25344 : : static tree
25345 : 142 : c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
25346 : : {
25347 : 142 : tree stmt, substmt;
25348 : 142 : bool error_suppress = false;
25349 : 142 : location_t loc;
25350 : :
25351 : 142 : loc = c_parser_peek_token (parser)->location;
25352 : 142 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
25353 : : {
25354 : : /* Avoid skipping until the end of the block. */
25355 : 2 : parser->error = false;
25356 : 2 : return NULL_TREE;
25357 : : }
25358 : :
25359 : 140 : stmt = push_stmt_list ();
25360 : :
25361 : 140 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
25362 : 140 : && !c_parser_omp_section_scan (parser, "section", true))
25363 : : {
25364 : 81 : substmt = c_parser_omp_structured_block_sequence (parser,
25365 : : PRAGMA_OMP_SECTION);
25366 : 81 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
25367 : 81 : SET_EXPR_LOCATION (substmt, loc);
25368 : 81 : add_stmt (substmt);
25369 : : }
25370 : :
25371 : 578 : while (1)
25372 : : {
25373 : 359 : if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
25374 : : break;
25375 : 219 : if (c_parser_next_token_is (parser, CPP_EOF))
25376 : : break;
25377 : :
25378 : 219 : loc = c_parser_peek_token (parser)->location;
25379 : 219 : c_parser_omp_section_scan (parser, "section", false);
25380 : 219 : if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
25381 : : {
25382 : 218 : c_parser_consume_pragma (parser);
25383 : 218 : c_parser_skip_to_pragma_eol (parser);
25384 : 218 : error_suppress = false;
25385 : : }
25386 : 1 : else if (!error_suppress)
25387 : : {
25388 : 1 : error_at (loc, "expected %<#pragma omp section%> or %<}%>");
25389 : 1 : error_suppress = true;
25390 : : }
25391 : :
25392 : 219 : substmt = c_parser_omp_structured_block_sequence (parser,
25393 : : PRAGMA_OMP_SECTION);
25394 : 219 : substmt = build1 (OMP_SECTION, void_type_node, substmt);
25395 : 219 : SET_EXPR_LOCATION (substmt, loc);
25396 : 219 : add_stmt (substmt);
25397 : : }
25398 : 140 : c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
25399 : : "expected %<#pragma omp section%> or %<}%>");
25400 : :
25401 : 140 : substmt = pop_stmt_list (stmt);
25402 : :
25403 : 140 : stmt = make_node (OMP_SECTIONS);
25404 : 140 : SET_EXPR_LOCATION (stmt, sections_loc);
25405 : 140 : TREE_TYPE (stmt) = void_type_node;
25406 : 140 : OMP_SECTIONS_BODY (stmt) = substmt;
25407 : :
25408 : 140 : return add_stmt (stmt);
25409 : : }
25410 : :
25411 : : /* OpenMP 2.5:
25412 : : # pragma omp sections sections-clause[optseq] newline
25413 : : sections-scope
25414 : :
25415 : : LOC is the location of the #pragma token.
25416 : : */
25417 : :
25418 : : #define OMP_SECTIONS_CLAUSE_MASK \
25419 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25420 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25421 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25422 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25423 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25424 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25425 : :
25426 : : static tree
25427 : 142 : c_parser_omp_sections (location_t loc, c_parser *parser,
25428 : : char *p_name, omp_clause_mask mask, tree *cclauses)
25429 : : {
25430 : 142 : tree block, clauses, ret;
25431 : :
25432 : 142 : strcat (p_name, " sections");
25433 : 142 : mask |= OMP_SECTIONS_CLAUSE_MASK;
25434 : 142 : if (cclauses)
25435 : 36 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25436 : :
25437 : 142 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25438 : 142 : if (cclauses)
25439 : : {
25440 : 36 : omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
25441 : 36 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
25442 : : }
25443 : :
25444 : 142 : block = c_begin_compound_stmt (true);
25445 : 142 : ret = c_parser_omp_sections_scope (loc, parser);
25446 : 142 : if (ret)
25447 : 140 : OMP_SECTIONS_CLAUSES (ret) = clauses;
25448 : 142 : block = c_end_compound_stmt (loc, block, true);
25449 : 142 : add_stmt (block);
25450 : :
25451 : 142 : return ret;
25452 : : }
25453 : :
25454 : : /* OpenMP 2.5:
25455 : : # pragma omp parallel parallel-clause[optseq] new-line
25456 : : structured-block
25457 : : # pragma omp parallel for parallel-for-clause[optseq] new-line
25458 : : structured-block
25459 : : # pragma omp parallel sections parallel-sections-clause[optseq] new-line
25460 : : structured-block
25461 : :
25462 : : OpenMP 4.0:
25463 : : # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
25464 : : structured-block
25465 : :
25466 : : LOC is the location of the #pragma token.
25467 : : */
25468 : :
25469 : : #define OMP_PARALLEL_CLAUSE_MASK \
25470 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25471 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25472 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25473 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25474 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25475 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
25476 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25477 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
25478 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25479 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
25480 : :
25481 : : static tree
25482 : 5691 : c_parser_omp_parallel (location_t loc, c_parser *parser,
25483 : : char *p_name, omp_clause_mask mask, tree *cclauses,
25484 : : bool *if_p)
25485 : : {
25486 : 5691 : tree stmt, clauses, block;
25487 : :
25488 : 5691 : strcat (p_name, " parallel");
25489 : 5691 : mask |= OMP_PARALLEL_CLAUSE_MASK;
25490 : : /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
25491 : 5691 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
25492 : 1165 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
25493 : 489 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
25494 : :
25495 : 5691 : if (c_parser_next_token_is_keyword (parser, RID_FOR))
25496 : : {
25497 : 4372 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25498 : 4372 : if (cclauses == NULL)
25499 : 1199 : cclauses = cclauses_buf;
25500 : :
25501 : 4372 : c_parser_consume_token (parser);
25502 : 4372 : if (!flag_openmp) /* flag_openmp_simd */
25503 : 20 : return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25504 : 4352 : block = c_begin_omp_parallel ();
25505 : 4352 : tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25506 : 4352 : stmt
25507 : 4352 : = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25508 : : block);
25509 : 4352 : if (ret == NULL_TREE)
25510 : : return ret;
25511 : 4291 : OMP_PARALLEL_COMBINED (stmt) = 1;
25512 : 4291 : return stmt;
25513 : : }
25514 : : /* When combined with distribute, parallel has to be followed by for.
25515 : : #pragma omp target parallel is allowed though. */
25516 : 1319 : else if (cclauses
25517 : 1319 : && (mask & (OMP_CLAUSE_MASK_1
25518 : 40 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25519 : : {
25520 : 0 : error_at (loc, "expected %<for%> after %qs", p_name);
25521 : 0 : c_parser_skip_to_pragma_eol (parser);
25522 : 0 : return NULL_TREE;
25523 : : }
25524 : 1319 : else if (c_parser_next_token_is (parser, CPP_NAME))
25525 : : {
25526 : 713 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25527 : 713 : if (cclauses == NULL && strcmp (p, "masked") == 0)
25528 : : {
25529 : 56 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25530 : 56 : cclauses = cclauses_buf;
25531 : :
25532 : 56 : c_parser_consume_token (parser);
25533 : 56 : if (!flag_openmp) /* flag_openmp_simd */
25534 : 0 : return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25535 : 0 : if_p);
25536 : 56 : block = c_begin_omp_parallel ();
25537 : 56 : tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25538 : : if_p);
25539 : 56 : stmt = c_finish_omp_parallel (loc,
25540 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25541 : : block);
25542 : 56 : if (ret == NULL)
25543 : : return ret;
25544 : : /* masked does have just filter clause, but during gimplification
25545 : : isn't represented by a gimplification omp context, so for
25546 : : #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
25547 : : so that
25548 : : #pragma omp parallel masked
25549 : : #pragma omp taskloop simd lastprivate (x)
25550 : : isn't confused with
25551 : : #pragma omp parallel masked taskloop simd lastprivate (x) */
25552 : 56 : if (OMP_MASKED_COMBINED (ret))
25553 : 47 : OMP_PARALLEL_COMBINED (stmt) = 1;
25554 : 56 : return stmt;
25555 : : }
25556 : 622 : else if (cclauses == NULL && strcmp (p, "master") == 0)
25557 : : {
25558 : 89 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25559 : 89 : cclauses = cclauses_buf;
25560 : :
25561 : 89 : c_parser_consume_token (parser);
25562 : 89 : if (!flag_openmp) /* flag_openmp_simd */
25563 : 3 : return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25564 : 3 : if_p);
25565 : 86 : block = c_begin_omp_parallel ();
25566 : 86 : tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25567 : : if_p);
25568 : 86 : stmt = c_finish_omp_parallel (loc,
25569 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25570 : : block);
25571 : 86 : if (ret == NULL)
25572 : : return ret;
25573 : : /* master doesn't have any clauses and during gimplification
25574 : : isn't represented by a gimplification omp context, so for
25575 : : #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
25576 : : so that
25577 : : #pragma omp parallel master
25578 : : #pragma omp taskloop simd lastprivate (x)
25579 : : isn't confused with
25580 : : #pragma omp parallel master taskloop simd lastprivate (x) */
25581 : 86 : if (OMP_MASTER_COMBINED (ret))
25582 : 45 : OMP_PARALLEL_COMBINED (stmt) = 1;
25583 : 86 : return stmt;
25584 : : }
25585 : 568 : else if (strcmp (p, "loop") == 0)
25586 : : {
25587 : 46 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25588 : 46 : if (cclauses == NULL)
25589 : 27 : cclauses = cclauses_buf;
25590 : :
25591 : 46 : c_parser_consume_token (parser);
25592 : 46 : if (!flag_openmp) /* flag_openmp_simd */
25593 : 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25594 : 2 : if_p);
25595 : 44 : block = c_begin_omp_parallel ();
25596 : 44 : tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25597 : : if_p);
25598 : 44 : stmt
25599 : 44 : = c_finish_omp_parallel (loc,
25600 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25601 : : block);
25602 : 44 : if (ret == NULL_TREE)
25603 : : return ret;
25604 : 44 : OMP_PARALLEL_COMBINED (stmt) = 1;
25605 : 44 : return stmt;
25606 : : }
25607 : 522 : else if (!flag_openmp) /* flag_openmp_simd */
25608 : : {
25609 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25610 : 1 : return NULL_TREE;
25611 : : }
25612 : 521 : else if (cclauses == NULL && strcmp (p, "sections") == 0)
25613 : : {
25614 : 36 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25615 : 36 : cclauses = cclauses_buf;
25616 : :
25617 : 36 : c_parser_consume_token (parser);
25618 : 36 : block = c_begin_omp_parallel ();
25619 : 36 : c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
25620 : 36 : stmt = c_finish_omp_parallel (loc,
25621 : : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25622 : : block);
25623 : 36 : OMP_PARALLEL_COMBINED (stmt) = 1;
25624 : 36 : return stmt;
25625 : : }
25626 : : }
25627 : 606 : else if (!flag_openmp) /* flag_openmp_simd */
25628 : : {
25629 : 1 : c_parser_skip_to_pragma_eol (parser, false);
25630 : 1 : return NULL_TREE;
25631 : : }
25632 : :
25633 : 1090 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
25634 : 1090 : if (cclauses)
25635 : : {
25636 : 20 : omp_split_clauses (loc, OMP_PARALLEL, mask, clauses, cclauses);
25637 : 20 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
25638 : : }
25639 : :
25640 : 1090 : block = c_begin_omp_parallel ();
25641 : 1090 : parser->omp_attrs_forbidden_p = true;
25642 : 1090 : c_parser_statement (parser, if_p);
25643 : 1090 : stmt = c_finish_omp_parallel (loc, clauses, block);
25644 : :
25645 : 1090 : return stmt;
25646 : : }
25647 : :
25648 : : /* OpenMP 2.5:
25649 : : # pragma omp single single-clause[optseq] new-line
25650 : : structured-block
25651 : :
25652 : : LOC is the location of the #pragma.
25653 : : */
25654 : :
25655 : : #define OMP_SINGLE_CLAUSE_MASK \
25656 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25657 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25658 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
25659 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25660 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25661 : :
25662 : : static tree
25663 : 222 : c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
25664 : : {
25665 : 222 : tree stmt = make_node (OMP_SINGLE);
25666 : 222 : SET_EXPR_LOCATION (stmt, loc);
25667 : 222 : TREE_TYPE (stmt) = void_type_node;
25668 : :
25669 : 222 : OMP_SINGLE_CLAUSES (stmt)
25670 : 222 : = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
25671 : : "#pragma omp single");
25672 : 222 : OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25673 : :
25674 : 222 : return add_stmt (stmt);
25675 : : }
25676 : :
25677 : : /* OpenMP 5.1:
25678 : : # pragma omp scope scope-clause[optseq] new-line
25679 : : structured-block
25680 : :
25681 : : LOC is the location of the #pragma.
25682 : : */
25683 : :
25684 : : #define OMP_SCOPE_CLAUSE_MASK \
25685 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25686 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25687 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25688 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25689 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25690 : :
25691 : : static tree
25692 : 61 : c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
25693 : : {
25694 : 61 : tree stmt = make_node (OMP_SCOPE);
25695 : 61 : SET_EXPR_LOCATION (stmt, loc);
25696 : 61 : TREE_TYPE (stmt) = void_type_node;
25697 : :
25698 : 61 : OMP_SCOPE_CLAUSES (stmt)
25699 : 61 : = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
25700 : : "#pragma omp scope");
25701 : 61 : OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25702 : :
25703 : 61 : return add_stmt (stmt);
25704 : : }
25705 : :
25706 : : /* Parse a function dispatch structured block:
25707 : :
25708 : : lvalue-expression = target-call ( [expression-list] );
25709 : : or
25710 : : target-call ( [expression-list] );
25711 : :
25712 : : Adapted from c_parser_expr_no_commas and c_parser_postfix_expression
25713 : : (CPP_NAME/C_ID_ID) for the function name.
25714 : : */
25715 : : static tree
25716 : 152 : c_parser_omp_dispatch_body (c_parser *parser)
25717 : : {
25718 : 152 : struct c_expr lhs, rhs, ret;
25719 : 152 : location_t expr_loc = c_parser_peek_token (parser)->location;
25720 : 152 : source_range tok_range = c_parser_peek_token (parser)->get_range ();
25721 : :
25722 : 152 : lhs = c_parser_conditional_expression (parser, NULL, NULL);
25723 : 152 : if (TREE_CODE (lhs.value) == CALL_EXPR)
25724 : : return lhs.value;
25725 : :
25726 : 53 : location_t op_location = c_parser_peek_token (parser)->location;
25727 : 53 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
25728 : 4 : return error_mark_node;
25729 : :
25730 : : /* Parse function name. */
25731 : 49 : if (!c_parser_next_token_is (parser, CPP_NAME))
25732 : : {
25733 : 1 : c_parser_error (parser, "expected a function name");
25734 : 1 : return error_mark_node;
25735 : : }
25736 : 48 : expr_loc = c_parser_peek_token (parser)->location;
25737 : 48 : tree id = c_parser_peek_token (parser)->value;
25738 : 48 : c_parser_consume_token (parser);
25739 : 48 : if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
25740 : : {
25741 : 1 : c_parser_error (parser, "expected a function name");
25742 : 1 : return error_mark_node;
25743 : : }
25744 : :
25745 : 47 : rhs.value = build_external_ref (expr_loc, id, true, &rhs.original_type);
25746 : 47 : set_c_expr_source_range (&rhs, tok_range);
25747 : :
25748 : : /* Parse argument list. */
25749 : 47 : rhs = c_parser_postfix_expression_after_primary (
25750 : 47 : parser, EXPR_LOC_OR_LOC (rhs.value, expr_loc), rhs);
25751 : 47 : if (TREE_CODE (rhs.value) != CALL_EXPR)
25752 : : {
25753 : 0 : error_at (EXPR_LOC_OR_LOC (rhs.value, expr_loc),
25754 : : "expected target-function call");
25755 : 0 : return error_mark_node;
25756 : : }
25757 : :
25758 : : /* Build assignment. */
25759 : 47 : rhs = convert_lvalue_to_rvalue (expr_loc, rhs, true, true);
25760 : 47 : ret.value
25761 : 47 : = build_modify_expr (op_location, lhs.value, lhs.original_type, NOP_EXPR,
25762 : : expr_loc, rhs.value, rhs.original_type);
25763 : 47 : ret.m_decimal = 0;
25764 : 47 : set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
25765 : 47 : ret.original_code = MODIFY_EXPR;
25766 : 47 : ret.original_type = NULL;
25767 : 47 : return ret.value;
25768 : : }
25769 : :
25770 : : /* OpenMP 5.1:
25771 : : # pragma omp dispatch dispatch-clause[optseq] new-line
25772 : : expression-stmt
25773 : :
25774 : : LOC is the location of the #pragma.
25775 : : */
25776 : :
25777 : : #define OMP_DISPATCH_CLAUSE_MASK \
25778 : : ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25779 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25780 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
25781 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
25782 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
25783 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \
25784 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
25785 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25786 : :
25787 : : static tree
25788 : 152 : c_parser_omp_dispatch (location_t loc, c_parser *parser)
25789 : : {
25790 : 152 : tree stmt = make_node (OMP_DISPATCH);
25791 : 152 : SET_EXPR_LOCATION (stmt, loc);
25792 : 152 : TREE_TYPE (stmt) = void_type_node;
25793 : :
25794 : 152 : OMP_DISPATCH_CLAUSES (stmt)
25795 : 152 : = c_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
25796 : : "#pragma omp dispatch");
25797 : :
25798 : : // Extract depend clauses and create taskwait
25799 : 152 : tree depend_clauses = NULL_TREE;
25800 : 152 : tree *depend_clauses_ptr = &depend_clauses;
25801 : 336 : for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
25802 : : {
25803 : 184 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
25804 : : {
25805 : 5 : *depend_clauses_ptr = c;
25806 : 5 : depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
25807 : : }
25808 : : }
25809 : 152 : if (depend_clauses != NULL_TREE)
25810 : : {
25811 : 5 : tree stmt = make_node (OMP_TASK);
25812 : 5 : TREE_TYPE (stmt) = void_node;
25813 : 5 : OMP_TASK_CLAUSES (stmt) = depend_clauses;
25814 : 5 : OMP_TASK_BODY (stmt) = NULL_TREE;
25815 : 5 : SET_EXPR_LOCATION (stmt, loc);
25816 : 5 : add_stmt (stmt);
25817 : : }
25818 : :
25819 : : // Parse body as expression statement
25820 : 152 : loc = c_parser_peek_token (parser)->location;
25821 : 152 : tree dispatch_body = c_parser_omp_dispatch_body (parser);
25822 : 152 : if (dispatch_body == error_mark_node)
25823 : : {
25824 : 6 : inform (loc, "%<#pragma omp dispatch%> must be followed by a function "
25825 : : "call with optional assignment");
25826 : 6 : c_parser_skip_to_end_of_block_or_statement (parser);
25827 : 6 : return NULL_TREE;
25828 : : }
25829 : :
25830 : : // Walk the tree to find the dispatch function call and wrap it into an IFN
25831 : 146 : gcc_assert (TREE_CODE (dispatch_body) == CALL_EXPR
25832 : : || TREE_CODE (dispatch_body) == MODIFY_EXPR);
25833 : 146 : tree *dispatch_call = TREE_CODE (dispatch_body) == MODIFY_EXPR
25834 : 146 : ? &TREE_OPERAND (dispatch_body, 1)
25835 : : : &dispatch_body;
25836 : 151 : while (TREE_CODE (*dispatch_call) == FLOAT_EXPR
25837 : : || TREE_CODE (*dispatch_call) == CONVERT_EXPR
25838 : 151 : || TREE_CODE (*dispatch_call) == NOP_EXPR)
25839 : 5 : dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
25840 : 146 : *dispatch_call = build_call_expr_internal_loc (
25841 : : loc, IFN_GOMP_DISPATCH,
25842 : 146 : TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*dispatch_call))), 1, *dispatch_call);
25843 : :
25844 : 146 : c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
25845 : 146 : OMP_DISPATCH_BODY (stmt) = dispatch_body;
25846 : :
25847 : 146 : return add_stmt (stmt);
25848 : : }
25849 : :
25850 : : /* OpenMP 3.0:
25851 : : # pragma omp task task-clause[optseq] new-line
25852 : :
25853 : : LOC is the location of the #pragma.
25854 : : */
25855 : :
25856 : : #define OMP_TASK_CLAUSE_MASK \
25857 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25858 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
25859 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25860 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25861 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25862 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25863 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
25864 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
25865 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25866 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
25867 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25868 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
25869 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
25870 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
25871 : :
25872 : : static tree
25873 : 894 : c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
25874 : : {
25875 : 894 : tree clauses, block;
25876 : :
25877 : 894 : clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
25878 : : "#pragma omp task");
25879 : :
25880 : 894 : block = c_begin_omp_task ();
25881 : 894 : parser->omp_attrs_forbidden_p = true;
25882 : 894 : c_parser_statement (parser, if_p);
25883 : 894 : return c_finish_omp_task (loc, clauses, block);
25884 : : }
25885 : :
25886 : : /* OpenMP 3.0:
25887 : : # pragma omp taskwait new-line
25888 : :
25889 : : OpenMP 5.0:
25890 : : # pragma omp taskwait taskwait-clause[optseq] new-line
25891 : : */
25892 : :
25893 : : #define OMP_TASKWAIT_CLAUSE_MASK \
25894 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25895 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25896 : :
25897 : : static void
25898 : 93 : c_parser_omp_taskwait (c_parser *parser)
25899 : : {
25900 : 93 : location_t loc = c_parser_peek_token (parser)->location;
25901 : 93 : c_parser_consume_pragma (parser);
25902 : :
25903 : 93 : tree clauses
25904 : 93 : = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
25905 : : "#pragma omp taskwait");
25906 : :
25907 : 93 : if (clauses)
25908 : : {
25909 : 21 : tree stmt = make_node (OMP_TASK);
25910 : 21 : TREE_TYPE (stmt) = void_node;
25911 : 21 : OMP_TASK_CLAUSES (stmt) = clauses;
25912 : 21 : OMP_TASK_BODY (stmt) = NULL_TREE;
25913 : 21 : SET_EXPR_LOCATION (stmt, loc);
25914 : 21 : add_stmt (stmt);
25915 : : }
25916 : : else
25917 : 72 : c_finish_omp_taskwait (loc);
25918 : 93 : }
25919 : :
25920 : : /* OpenMP 3.1:
25921 : : # pragma omp taskyield new-line
25922 : : */
25923 : :
25924 : : static void
25925 : 6 : c_parser_omp_taskyield (c_parser *parser)
25926 : : {
25927 : 6 : location_t loc = c_parser_peek_token (parser)->location;
25928 : 6 : c_parser_consume_pragma (parser);
25929 : 6 : c_parser_skip_to_pragma_eol (parser);
25930 : :
25931 : 6 : c_finish_omp_taskyield (loc);
25932 : 6 : }
25933 : :
25934 : : /* OpenMP 4.0:
25935 : : # pragma omp taskgroup new-line
25936 : :
25937 : : OpenMP 5.0:
25938 : : # pragma omp taskgroup taskgroup-clause[optseq] new-line
25939 : : */
25940 : :
25941 : : #define OMP_TASKGROUP_CLAUSE_MASK \
25942 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25943 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
25944 : :
25945 : : static tree
25946 : 138 : c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
25947 : : {
25948 : 138 : tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
25949 : : "#pragma omp taskgroup");
25950 : :
25951 : 138 : tree body = c_parser_omp_structured_block (parser, if_p);
25952 : 138 : return c_finish_omp_taskgroup (loc, body, clauses);
25953 : : }
25954 : :
25955 : : /* OpenMP 4.0:
25956 : : # pragma omp cancel cancel-clause[optseq] new-line
25957 : :
25958 : : LOC is the location of the #pragma.
25959 : : */
25960 : :
25961 : : #define OMP_CANCEL_CLAUSE_MASK \
25962 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25963 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25964 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25965 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
25966 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
25967 : :
25968 : : static void
25969 : 213 : c_parser_omp_cancel (c_parser *parser)
25970 : : {
25971 : 213 : location_t loc = c_parser_peek_token (parser)->location;
25972 : :
25973 : 213 : c_parser_consume_pragma (parser);
25974 : 213 : tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
25975 : : "#pragma omp cancel");
25976 : :
25977 : 213 : c_finish_omp_cancel (loc, clauses);
25978 : 213 : }
25979 : :
25980 : : /* OpenMP 4.0:
25981 : : # pragma omp cancellation point cancelpt-clause[optseq] new-line
25982 : :
25983 : : LOC is the location of the #pragma.
25984 : : */
25985 : :
25986 : : #define OMP_CANCELLATION_POINT_CLAUSE_MASK \
25987 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25988 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25989 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25990 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
25991 : :
25992 : : static bool
25993 : 179 : c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
25994 : : {
25995 : 179 : location_t loc = c_parser_peek_token (parser)->location;
25996 : 179 : tree clauses;
25997 : 179 : bool point_seen = false;
25998 : :
25999 : 179 : c_parser_consume_pragma (parser);
26000 : 179 : if (c_parser_next_token_is (parser, CPP_NAME))
26001 : : {
26002 : 179 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26003 : 179 : if (strcmp (p, "point") == 0)
26004 : : {
26005 : 177 : c_parser_consume_token (parser);
26006 : 177 : point_seen = true;
26007 : : }
26008 : : }
26009 : 177 : if (!point_seen)
26010 : : {
26011 : 2 : c_parser_error (parser, "expected %<point%>");
26012 : 2 : c_parser_skip_to_pragma_eol (parser);
26013 : 2 : return false;
26014 : : }
26015 : :
26016 : 177 : if (context != pragma_compound)
26017 : : {
26018 : 10 : if (context == pragma_stmt)
26019 : 9 : error_at (loc,
26020 : : "%<#pragma %s%> may only be used in compound statements",
26021 : : "omp cancellation point");
26022 : : else
26023 : 1 : c_parser_error (parser, "expected declaration specifiers");
26024 : 10 : c_parser_skip_to_pragma_eol (parser, false);
26025 : 10 : return true;
26026 : : }
26027 : :
26028 : 167 : clauses
26029 : 167 : = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
26030 : : "#pragma omp cancellation point");
26031 : :
26032 : 167 : c_finish_omp_cancellation_point (loc, clauses);
26033 : 167 : return true;
26034 : : }
26035 : :
26036 : : /* OpenMP 4.0:
26037 : : #pragma omp distribute distribute-clause[optseq] new-line
26038 : : for-loop */
26039 : :
26040 : : #define OMP_DISTRIBUTE_CLAUSE_MASK \
26041 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26042 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26043 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
26044 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
26045 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26046 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
26047 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
26048 : :
26049 : : static tree
26050 : 3427 : c_parser_omp_distribute (location_t loc, c_parser *parser,
26051 : : char *p_name, omp_clause_mask mask, tree *cclauses,
26052 : : bool *if_p)
26053 : : {
26054 : 3427 : tree clauses, block, ret;
26055 : :
26056 : 3427 : strcat (p_name, " distribute");
26057 : 3427 : mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
26058 : :
26059 : 3427 : if (c_parser_next_token_is (parser, CPP_NAME))
26060 : : {
26061 : 3331 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26062 : 3331 : bool simd = false;
26063 : 3331 : bool parallel = false;
26064 : :
26065 : 3331 : if (strcmp (p, "simd") == 0)
26066 : : simd = true;
26067 : : else
26068 : 2991 : parallel = strcmp (p, "parallel") == 0;
26069 : 2991 : if (parallel || simd)
26070 : : {
26071 : 3064 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26072 : 3064 : if (cclauses == NULL)
26073 : 1147 : cclauses = cclauses_buf;
26074 : 3064 : c_parser_consume_token (parser);
26075 : 3064 : if (!flag_openmp) /* flag_openmp_simd */
26076 : : {
26077 : 15 : if (simd)
26078 : 6 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26079 : 6 : if_p);
26080 : : else
26081 : 9 : return c_parser_omp_parallel (loc, parser, p_name, mask,
26082 : 9 : cclauses, if_p);
26083 : : }
26084 : 3049 : block = c_begin_compound_stmt (true);
26085 : 3049 : if (simd)
26086 : 334 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
26087 : : if_p);
26088 : : else
26089 : 2715 : ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
26090 : : if_p);
26091 : 3049 : block = c_end_compound_stmt (loc, block, true);
26092 : 3049 : if (ret == NULL)
26093 : : return ret;
26094 : 3044 : ret = make_node (OMP_DISTRIBUTE);
26095 : 3044 : TREE_TYPE (ret) = void_type_node;
26096 : 3044 : OMP_FOR_BODY (ret) = block;
26097 : 3044 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26098 : 3044 : SET_EXPR_LOCATION (ret, loc);
26099 : 3044 : add_stmt (ret);
26100 : 3044 : return ret;
26101 : : }
26102 : : }
26103 : 363 : if (!flag_openmp) /* flag_openmp_simd */
26104 : : {
26105 : 2 : c_parser_skip_to_pragma_eol (parser, false);
26106 : 2 : return NULL_TREE;
26107 : : }
26108 : :
26109 : 361 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26110 : 361 : if (cclauses)
26111 : : {
26112 : 194 : omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
26113 : 194 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
26114 : : }
26115 : :
26116 : 361 : block = c_begin_compound_stmt (true);
26117 : 361 : ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
26118 : : if_p);
26119 : 361 : block = c_end_compound_stmt (loc, block, true);
26120 : 361 : add_stmt (block);
26121 : :
26122 : 361 : return ret;
26123 : : }
26124 : :
26125 : : /* OpenMP 4.0:
26126 : : # pragma omp teams teams-clause[optseq] new-line
26127 : : structured-block */
26128 : :
26129 : : #define OMP_TEAMS_CLAUSE_MASK \
26130 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26131 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26132 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
26133 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
26134 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
26135 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26136 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26137 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
26138 : :
26139 : : static tree
26140 : 3669 : c_parser_omp_teams (location_t loc, c_parser *parser,
26141 : : char *p_name, omp_clause_mask mask, tree *cclauses,
26142 : : bool *if_p)
26143 : : {
26144 : 3669 : tree clauses, block, ret;
26145 : :
26146 : 3669 : strcat (p_name, " teams");
26147 : 3669 : mask |= OMP_TEAMS_CLAUSE_MASK;
26148 : :
26149 : 3669 : if (c_parser_next_token_is (parser, CPP_NAME))
26150 : : {
26151 : 2340 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26152 : 2340 : if (strcmp (p, "distribute") == 0)
26153 : : {
26154 : 2113 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26155 : 2113 : if (cclauses == NULL)
26156 : 1271 : cclauses = cclauses_buf;
26157 : :
26158 : 2113 : c_parser_consume_token (parser);
26159 : 2113 : if (!flag_openmp) /* flag_openmp_simd */
26160 : 12 : return c_parser_omp_distribute (loc, parser, p_name, mask,
26161 : 12 : cclauses, if_p);
26162 : 2101 : block = c_begin_omp_parallel ();
26163 : 2101 : ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
26164 : : if_p);
26165 : 2101 : block = c_end_compound_stmt (loc, block, true);
26166 : 2101 : if (ret == NULL)
26167 : : return ret;
26168 : 2101 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26169 : 2101 : ret = make_node (OMP_TEAMS);
26170 : 2101 : TREE_TYPE (ret) = void_type_node;
26171 : 2101 : OMP_TEAMS_CLAUSES (ret) = clauses;
26172 : 2101 : OMP_TEAMS_BODY (ret) = block;
26173 : 2101 : OMP_TEAMS_COMBINED (ret) = 1;
26174 : 2101 : SET_EXPR_LOCATION (ret, loc);
26175 : 2101 : return add_stmt (ret);
26176 : : }
26177 : 227 : else if (strcmp (p, "loop") == 0)
26178 : : {
26179 : 34 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26180 : 34 : if (cclauses == NULL)
26181 : 16 : cclauses = cclauses_buf;
26182 : :
26183 : 34 : c_parser_consume_token (parser);
26184 : 34 : if (!flag_openmp) /* flag_openmp_simd */
26185 : 2 : return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26186 : 2 : if_p);
26187 : 32 : block = c_begin_omp_parallel ();
26188 : 32 : ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
26189 : 32 : block = c_end_compound_stmt (loc, block, true);
26190 : 32 : if (ret == NULL)
26191 : : return ret;
26192 : 31 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26193 : 31 : ret = make_node (OMP_TEAMS);
26194 : 31 : TREE_TYPE (ret) = void_type_node;
26195 : 31 : OMP_TEAMS_CLAUSES (ret) = clauses;
26196 : 31 : OMP_TEAMS_BODY (ret) = block;
26197 : 31 : OMP_TEAMS_COMBINED (ret) = 1;
26198 : 31 : SET_EXPR_LOCATION (ret, loc);
26199 : 31 : return add_stmt (ret);
26200 : : }
26201 : : }
26202 : 1522 : if (!flag_openmp) /* flag_openmp_simd */
26203 : : {
26204 : 2 : c_parser_skip_to_pragma_eol (parser, false);
26205 : 2 : return NULL_TREE;
26206 : : }
26207 : :
26208 : 1520 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
26209 : 1520 : if (cclauses)
26210 : : {
26211 : 877 : omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
26212 : 877 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26213 : : }
26214 : :
26215 : 1520 : tree stmt = make_node (OMP_TEAMS);
26216 : 1520 : TREE_TYPE (stmt) = void_type_node;
26217 : 1520 : OMP_TEAMS_CLAUSES (stmt) = clauses;
26218 : 1520 : block = c_begin_omp_parallel ();
26219 : 1520 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26220 : 1520 : OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26221 : 1520 : SET_EXPR_LOCATION (stmt, loc);
26222 : :
26223 : 1520 : return add_stmt (stmt);
26224 : : }
26225 : :
26226 : : /* OpenMP 4.0:
26227 : : # pragma omp target data target-data-clause[optseq] new-line
26228 : : structured-block */
26229 : :
26230 : : #define OMP_TARGET_DATA_CLAUSE_MASK \
26231 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26232 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26233 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26234 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
26235 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
26236 : :
26237 : : static tree
26238 : 155 : c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
26239 : : {
26240 : 155 : if (flag_openmp)
26241 : 155 : omp_requires_mask
26242 : 155 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26243 : :
26244 : 155 : tree clauses
26245 : 155 : = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
26246 : 155 : "#pragma omp target data");
26247 : 155 : c_omp_adjust_map_clauses (clauses, false);
26248 : 155 : int map_seen = 0;
26249 : 455 : for (tree *pc = &clauses; *pc;)
26250 : : {
26251 : 300 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26252 : 218 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26253 : : {
26254 : : case GOMP_MAP_TO:
26255 : : case GOMP_MAP_ALWAYS_TO:
26256 : : case GOMP_MAP_PRESENT_TO:
26257 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26258 : : case GOMP_MAP_FROM:
26259 : : case GOMP_MAP_ALWAYS_FROM:
26260 : : case GOMP_MAP_PRESENT_FROM:
26261 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26262 : : case GOMP_MAP_TOFROM:
26263 : : case GOMP_MAP_ALWAYS_TOFROM:
26264 : : case GOMP_MAP_PRESENT_TOFROM:
26265 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26266 : : case GOMP_MAP_ALLOC:
26267 : : case GOMP_MAP_PRESENT_ALLOC:
26268 : 300 : map_seen = 3;
26269 : : break;
26270 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26271 : : case GOMP_MAP_ALWAYS_POINTER:
26272 : : case GOMP_MAP_ATTACH_DETACH:
26273 : : case GOMP_MAP_ATTACH:
26274 : : break;
26275 : 0 : default:
26276 : 0 : map_seen |= 1;
26277 : 0 : error_at (OMP_CLAUSE_LOCATION (*pc),
26278 : : "%<#pragma omp target data%> with map-type other "
26279 : : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26280 : : "on %<map%> clause");
26281 : 0 : *pc = OMP_CLAUSE_CHAIN (*pc);
26282 : 0 : continue;
26283 : : }
26284 : 82 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
26285 : 82 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
26286 : : map_seen = 3;
26287 : 300 : pc = &OMP_CLAUSE_CHAIN (*pc);
26288 : : }
26289 : :
26290 : 155 : if (map_seen != 3)
26291 : : {
26292 : 3 : if (map_seen == 0)
26293 : 3 : error_at (loc,
26294 : : "%<#pragma omp target data%> must contain at least "
26295 : : "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
26296 : : "clause");
26297 : 3 : return NULL_TREE;
26298 : : }
26299 : :
26300 : 152 : tree stmt = make_node (OMP_TARGET_DATA);
26301 : 152 : TREE_TYPE (stmt) = void_type_node;
26302 : 152 : OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
26303 : 152 : keep_next_level ();
26304 : 152 : tree block = c_begin_compound_stmt (true);
26305 : 152 : add_stmt (c_parser_omp_structured_block (parser, if_p));
26306 : 152 : OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26307 : :
26308 : 152 : SET_EXPR_LOCATION (stmt, loc);
26309 : 152 : return add_stmt (stmt);
26310 : : }
26311 : :
26312 : : /* OpenMP 4.0:
26313 : : # pragma omp target update target-update-clause[optseq] new-line */
26314 : :
26315 : : #define OMP_TARGET_UPDATE_CLAUSE_MASK \
26316 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
26317 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
26318 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
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 : 2837 : c_parser_omp_target_update (location_t loc, c_parser *parser,
26325 : : enum pragma_context context)
26326 : : {
26327 : 2837 : if (context == pragma_stmt)
26328 : : {
26329 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26330 : : "omp target update");
26331 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26332 : 8 : return true;
26333 : : }
26334 : :
26335 : 2829 : tree clauses
26336 : 2829 : = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
26337 : : "#pragma omp target update");
26338 : 2829 : if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
26339 : 2829 : && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
26340 : : {
26341 : 5 : error_at (loc,
26342 : : "%<#pragma omp target update%> must contain at least one "
26343 : : "%<from%> or %<to%> clauses");
26344 : 5 : return false;
26345 : : }
26346 : :
26347 : 2824 : if (flag_openmp)
26348 : 2824 : omp_requires_mask
26349 : 2824 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26350 : :
26351 : 2824 : tree stmt = make_node (OMP_TARGET_UPDATE);
26352 : 2824 : TREE_TYPE (stmt) = void_type_node;
26353 : 2824 : OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
26354 : 2824 : SET_EXPR_LOCATION (stmt, loc);
26355 : 2824 : add_stmt (stmt);
26356 : 2824 : return false;
26357 : : }
26358 : :
26359 : : /* OpenMP 4.5:
26360 : : # pragma omp target enter data target-data-clause[optseq] new-line */
26361 : :
26362 : : #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
26363 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26364 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26365 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26366 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26367 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26368 : :
26369 : : static bool
26370 : 116 : c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
26371 : : enum pragma_context context)
26372 : : {
26373 : 116 : bool data_seen = false;
26374 : 116 : if (c_parser_next_token_is (parser, CPP_NAME))
26375 : : {
26376 : 116 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26377 : 116 : if (strcmp (p, "data") == 0)
26378 : : {
26379 : 116 : c_parser_consume_token (parser);
26380 : 116 : data_seen = true;
26381 : : }
26382 : : }
26383 : 116 : if (!data_seen)
26384 : : {
26385 : 0 : c_parser_error (parser, "expected %<data%>");
26386 : 0 : c_parser_skip_to_pragma_eol (parser);
26387 : 0 : return false;
26388 : : }
26389 : :
26390 : 116 : if (context == pragma_stmt)
26391 : : {
26392 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26393 : : "omp target enter data");
26394 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26395 : 8 : return true;
26396 : : }
26397 : :
26398 : 108 : if (flag_openmp)
26399 : 108 : omp_requires_mask
26400 : 108 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26401 : :
26402 : 108 : tree clauses
26403 : 108 : = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
26404 : 108 : "#pragma omp target enter data");
26405 : 108 : c_omp_adjust_map_clauses (clauses, false);
26406 : 108 : int map_seen = 0;
26407 : 388 : for (tree *pc = &clauses; *pc;)
26408 : : {
26409 : 280 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26410 : 237 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26411 : : {
26412 : : case GOMP_MAP_TO:
26413 : : case GOMP_MAP_ALWAYS_TO:
26414 : : case GOMP_MAP_PRESENT_TO:
26415 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26416 : : case GOMP_MAP_ALLOC:
26417 : : case GOMP_MAP_PRESENT_ALLOC:
26418 : 184 : map_seen = 3;
26419 : : break;
26420 : 34 : case GOMP_MAP_TOFROM:
26421 : 34 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
26422 : 34 : map_seen = 3;
26423 : 34 : break;
26424 : 3 : case GOMP_MAP_ALWAYS_TOFROM:
26425 : 3 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
26426 : 3 : map_seen = 3;
26427 : 3 : break;
26428 : 2 : case GOMP_MAP_PRESENT_TOFROM:
26429 : 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
26430 : 2 : map_seen = 3;
26431 : 2 : break;
26432 : 2 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26433 : 2 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
26434 : 2 : map_seen = 3;
26435 : 2 : break;
26436 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26437 : : case GOMP_MAP_ALWAYS_POINTER:
26438 : : case GOMP_MAP_ATTACH_DETACH:
26439 : : case GOMP_MAP_ATTACH:
26440 : : break;
26441 : 2 : default:
26442 : 2 : map_seen |= 1;
26443 : 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
26444 : : "%<#pragma omp target enter data%> with map-type other "
26445 : : "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
26446 : 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
26447 : 2 : continue;
26448 : : }
26449 : 278 : pc = &OMP_CLAUSE_CHAIN (*pc);
26450 : : }
26451 : :
26452 : 108 : if (map_seen != 3)
26453 : : {
26454 : 4 : if (map_seen == 0)
26455 : 2 : error_at (loc,
26456 : : "%<#pragma omp target enter data%> must contain at least "
26457 : : "one %<map%> clause");
26458 : 4 : return true;
26459 : : }
26460 : :
26461 : 104 : tree stmt = make_node (OMP_TARGET_ENTER_DATA);
26462 : 104 : TREE_TYPE (stmt) = void_type_node;
26463 : 104 : OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
26464 : 104 : SET_EXPR_LOCATION (stmt, loc);
26465 : 104 : add_stmt (stmt);
26466 : 104 : return true;
26467 : : }
26468 : :
26469 : : /* OpenMP 4.5:
26470 : : # pragma omp target exit data target-data-clause[optseq] new-line */
26471 : :
26472 : : #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
26473 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26474 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26475 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26476 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26477 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26478 : :
26479 : : static bool
26480 : 107 : c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
26481 : : enum pragma_context context)
26482 : : {
26483 : 107 : bool data_seen = false;
26484 : 107 : if (c_parser_next_token_is (parser, CPP_NAME))
26485 : : {
26486 : 107 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26487 : 107 : if (strcmp (p, "data") == 0)
26488 : : {
26489 : 107 : c_parser_consume_token (parser);
26490 : 107 : data_seen = true;
26491 : : }
26492 : : }
26493 : 107 : if (!data_seen)
26494 : : {
26495 : 0 : c_parser_error (parser, "expected %<data%>");
26496 : 0 : c_parser_skip_to_pragma_eol (parser);
26497 : 0 : return false;
26498 : : }
26499 : :
26500 : 107 : if (context == pragma_stmt)
26501 : : {
26502 : 8 : error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26503 : : "omp target exit data");
26504 : 8 : c_parser_skip_to_pragma_eol (parser, false);
26505 : 8 : return true;
26506 : : }
26507 : :
26508 : 99 : if (flag_openmp)
26509 : 99 : omp_requires_mask
26510 : 99 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26511 : :
26512 : 99 : tree clauses
26513 : 99 : = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
26514 : : "#pragma omp target exit data", false);
26515 : 99 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
26516 : 99 : c_omp_adjust_map_clauses (clauses, false);
26517 : 99 : int map_seen = 0;
26518 : 349 : for (tree *pc = &clauses; *pc;)
26519 : : {
26520 : 250 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26521 : 207 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26522 : : {
26523 : : case GOMP_MAP_FROM:
26524 : : case GOMP_MAP_ALWAYS_FROM:
26525 : : case GOMP_MAP_PRESENT_FROM:
26526 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26527 : : case GOMP_MAP_RELEASE:
26528 : : case GOMP_MAP_DELETE:
26529 : 158 : map_seen = 3;
26530 : : break;
26531 : 30 : case GOMP_MAP_TOFROM:
26532 : 30 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
26533 : 30 : map_seen = 3;
26534 : 30 : break;
26535 : 1 : case GOMP_MAP_ALWAYS_TOFROM:
26536 : 1 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
26537 : 1 : map_seen = 3;
26538 : 1 : break;
26539 : 0 : case GOMP_MAP_PRESENT_TOFROM:
26540 : 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
26541 : 0 : map_seen = 3;
26542 : 0 : break;
26543 : 0 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26544 : 0 : OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
26545 : 0 : map_seen = 3;
26546 : 0 : break;
26547 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26548 : : case GOMP_MAP_ALWAYS_POINTER:
26549 : : case GOMP_MAP_ATTACH_DETACH:
26550 : : case GOMP_MAP_DETACH:
26551 : : break;
26552 : 2 : default:
26553 : 2 : map_seen |= 1;
26554 : 2 : error_at (OMP_CLAUSE_LOCATION (*pc),
26555 : : "%<#pragma omp target exit data%> with map-type other "
26556 : : "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
26557 : : "on %<map%> clause");
26558 : 2 : *pc = OMP_CLAUSE_CHAIN (*pc);
26559 : 2 : continue;
26560 : : }
26561 : 248 : pc = &OMP_CLAUSE_CHAIN (*pc);
26562 : : }
26563 : :
26564 : 99 : if (map_seen != 3)
26565 : : {
26566 : 2 : if (map_seen == 0)
26567 : 0 : error_at (loc,
26568 : : "%<#pragma omp target exit data%> must contain at least one "
26569 : : "%<map%> clause");
26570 : 2 : return true;
26571 : : }
26572 : :
26573 : 97 : tree stmt = make_node (OMP_TARGET_EXIT_DATA);
26574 : 97 : TREE_TYPE (stmt) = void_type_node;
26575 : 97 : OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
26576 : 97 : SET_EXPR_LOCATION (stmt, loc);
26577 : 97 : add_stmt (stmt);
26578 : 97 : return true;
26579 : : }
26580 : :
26581 : : /* OpenMP 4.0:
26582 : : # pragma omp target target-clause[optseq] new-line
26583 : : structured-block */
26584 : :
26585 : : #define OMP_TARGET_CLAUSE_MASK \
26586 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26587 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26588 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26589 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26590 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
26591 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26592 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26593 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26594 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
26595 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
26596 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26597 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
26598 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
26599 : :
26600 : : static bool
26601 : 7395 : c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
26602 : : {
26603 : 7395 : location_t loc = c_parser_peek_token (parser)->location;
26604 : 7395 : c_parser_consume_pragma (parser);
26605 : 7395 : tree *pc = NULL, stmt, block, body, clauses;
26606 : :
26607 : 7395 : if (context != pragma_stmt && context != pragma_compound)
26608 : : {
26609 : 2 : c_parser_error (parser, "expected declaration specifiers");
26610 : 2 : c_parser_skip_to_pragma_eol (parser);
26611 : 2 : return false;
26612 : : }
26613 : :
26614 : 7393 : if (flag_openmp)
26615 : 7379 : omp_requires_mask
26616 : 7379 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26617 : :
26618 : 7393 : if (c_parser_next_token_is (parser, CPP_NAME))
26619 : : {
26620 : 6470 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26621 : 6470 : enum tree_code ccode = ERROR_MARK;
26622 : :
26623 : 6470 : if (strcmp (p, "teams") == 0)
26624 : : ccode = OMP_TEAMS;
26625 : 4732 : else if (strcmp (p, "parallel") == 0)
26626 : : ccode = OMP_PARALLEL;
26627 : 4243 : else if (strcmp (p, "simd") == 0)
26628 : : ccode = OMP_SIMD;
26629 : 4183 : if (ccode != ERROR_MARK)
26630 : : {
26631 : 2287 : tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
26632 : 2287 : char p_name[sizeof ("#pragma omp target teams distribute "
26633 : : "parallel for simd")];
26634 : :
26635 : 2287 : c_parser_consume_token (parser);
26636 : 2287 : strcpy (p_name, "#pragma omp target");
26637 : 2287 : if (!flag_openmp) /* flag_openmp_simd */
26638 : : {
26639 : 13 : tree stmt;
26640 : 13 : switch (ccode)
26641 : : {
26642 : 8 : case OMP_TEAMS:
26643 : 8 : stmt = c_parser_omp_teams (loc, parser, p_name,
26644 : 8 : OMP_TARGET_CLAUSE_MASK,
26645 : : cclauses, if_p);
26646 : 8 : break;
26647 : 4 : case OMP_PARALLEL:
26648 : 4 : stmt = c_parser_omp_parallel (loc, parser, p_name,
26649 : 4 : OMP_TARGET_CLAUSE_MASK,
26650 : : cclauses, if_p);
26651 : 4 : break;
26652 : 1 : case OMP_SIMD:
26653 : 1 : stmt = c_parser_omp_simd (loc, parser, p_name,
26654 : 1 : OMP_TARGET_CLAUSE_MASK,
26655 : : cclauses, if_p);
26656 : 1 : break;
26657 : 0 : default:
26658 : 0 : gcc_unreachable ();
26659 : : }
26660 : 22 : return stmt != NULL_TREE;
26661 : : }
26662 : 2274 : keep_next_level ();
26663 : 2274 : tree block = c_begin_compound_stmt (true), ret;
26664 : 2274 : switch (ccode)
26665 : : {
26666 : 1730 : case OMP_TEAMS:
26667 : 1730 : ret = c_parser_omp_teams (loc, parser, p_name,
26668 : 1730 : OMP_TARGET_CLAUSE_MASK, cclauses,
26669 : : if_p);
26670 : 1730 : break;
26671 : 485 : case OMP_PARALLEL:
26672 : 485 : ret = c_parser_omp_parallel (loc, parser, p_name,
26673 : 485 : OMP_TARGET_CLAUSE_MASK, cclauses,
26674 : : if_p);
26675 : 485 : break;
26676 : 59 : case OMP_SIMD:
26677 : 59 : ret = c_parser_omp_simd (loc, parser, p_name,
26678 : 59 : OMP_TARGET_CLAUSE_MASK, cclauses,
26679 : : if_p);
26680 : 59 : break;
26681 : 0 : default:
26682 : 0 : gcc_unreachable ();
26683 : : }
26684 : 2274 : block = c_end_compound_stmt (loc, block, true);
26685 : 2274 : if (ret == NULL_TREE)
26686 : : return false;
26687 : 2265 : if (ccode == OMP_TEAMS)
26688 : : /* For combined target teams, ensure the num_teams and
26689 : : thread_limit clause expressions are evaluated on the host,
26690 : : before entering the target construct. */
26691 : 2210 : for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26692 : 2210 : c; c = OMP_CLAUSE_CHAIN (c))
26693 : 481 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
26694 : 481 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
26695 : 202 : for (int i = 0;
26696 : 332 : i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
26697 : 202 : if (OMP_CLAUSE_OPERAND (c, i)
26698 : 202 : && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
26699 : : {
26700 : 129 : tree expr = OMP_CLAUSE_OPERAND (c, i);
26701 : 129 : tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
26702 : 129 : expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
26703 : : expr, NULL_TREE, NULL_TREE);
26704 : 129 : add_stmt (expr);
26705 : 129 : OMP_CLAUSE_OPERAND (c, i) = expr;
26706 : 129 : tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
26707 : : OMP_CLAUSE_FIRSTPRIVATE);
26708 : 129 : OMP_CLAUSE_DECL (tc) = tmp;
26709 : 129 : OMP_CLAUSE_CHAIN (tc)
26710 : 129 : = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26711 : 129 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
26712 : : }
26713 : 2265 : tree stmt = make_node (OMP_TARGET);
26714 : 2265 : TREE_TYPE (stmt) = void_type_node;
26715 : 2265 : OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26716 : 2265 : c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
26717 : 2265 : OMP_TARGET_BODY (stmt) = block;
26718 : 2265 : OMP_TARGET_COMBINED (stmt) = 1;
26719 : 2265 : SET_EXPR_LOCATION (stmt, loc);
26720 : 2265 : add_stmt (stmt);
26721 : 2265 : pc = &OMP_TARGET_CLAUSES (stmt);
26722 : 2265 : goto check_clauses;
26723 : : }
26724 : 4183 : else if (!flag_openmp) /* flag_openmp_simd */
26725 : : {
26726 : 0 : c_parser_skip_to_pragma_eol (parser, false);
26727 : 0 : return false;
26728 : : }
26729 : 4183 : else if (strcmp (p, "data") == 0)
26730 : : {
26731 : 155 : c_parser_consume_token (parser);
26732 : 155 : c_parser_omp_target_data (loc, parser, if_p);
26733 : 155 : return true;
26734 : : }
26735 : 4028 : else if (strcmp (p, "enter") == 0)
26736 : : {
26737 : 116 : c_parser_consume_token (parser);
26738 : 116 : return c_parser_omp_target_enter_data (loc, parser, context);
26739 : : }
26740 : 3912 : else if (strcmp (p, "exit") == 0)
26741 : : {
26742 : 107 : c_parser_consume_token (parser);
26743 : 107 : return c_parser_omp_target_exit_data (loc, parser, context);
26744 : : }
26745 : 3805 : else if (strcmp (p, "update") == 0)
26746 : : {
26747 : 2837 : c_parser_consume_token (parser);
26748 : 2837 : return c_parser_omp_target_update (loc, parser, context);
26749 : : }
26750 : : }
26751 : 1891 : if (!flag_openmp) /* flag_openmp_simd */
26752 : : {
26753 : 1 : c_parser_skip_to_pragma_eol (parser, false);
26754 : 1 : return false;
26755 : : }
26756 : :
26757 : 1890 : stmt = make_node (OMP_TARGET);
26758 : 1890 : TREE_TYPE (stmt) = void_type_node;
26759 : :
26760 : 1890 : clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
26761 : : "#pragma omp target", false);
26762 : 3701 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
26763 : 1811 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
26764 : : {
26765 : 50 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
26766 : 50 : OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
26767 : 50 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
26768 : 50 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
26769 : 50 : OMP_CLAUSE_CHAIN (c) = nc;
26770 : : }
26771 : 1890 : clauses = c_omp_instantiate_mappers (clauses);
26772 : 1890 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
26773 : 1890 : c_omp_adjust_map_clauses (clauses, true);
26774 : :
26775 : 1890 : keep_next_level ();
26776 : 1890 : block = c_begin_compound_stmt (true);
26777 : 1890 : body = c_parser_omp_structured_block (parser, if_p);
26778 : :
26779 : 1890 : c_omp_scan_mapper_bindings (loc, &clauses, body);
26780 : :
26781 : 1890 : add_stmt (body);
26782 : 1890 : OMP_TARGET_CLAUSES (stmt) = clauses;
26783 : 1890 : pc = &OMP_TARGET_CLAUSES (stmt);
26784 : 1890 : OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26785 : :
26786 : 1890 : SET_EXPR_LOCATION (stmt, loc);
26787 : 1890 : add_stmt (stmt);
26788 : :
26789 : : check_clauses:
26790 : 7746 : while (*pc)
26791 : : {
26792 : 3591 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26793 : 1991 : switch (OMP_CLAUSE_MAP_KIND (*pc))
26794 : : {
26795 : : case GOMP_MAP_TO:
26796 : : case GOMP_MAP_ALWAYS_TO:
26797 : : case GOMP_MAP_PRESENT_TO:
26798 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
26799 : : case GOMP_MAP_FROM:
26800 : : case GOMP_MAP_ALWAYS_FROM:
26801 : : case GOMP_MAP_PRESENT_FROM:
26802 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
26803 : : case GOMP_MAP_TOFROM:
26804 : : case GOMP_MAP_ALWAYS_TOFROM:
26805 : : case GOMP_MAP_PRESENT_TOFROM:
26806 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26807 : : case GOMP_MAP_ALLOC:
26808 : : case GOMP_MAP_PRESENT_ALLOC:
26809 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
26810 : : case GOMP_MAP_ALWAYS_POINTER:
26811 : : case GOMP_MAP_POINTER:
26812 : : case GOMP_MAP_ATTACH_DETACH:
26813 : : case GOMP_MAP_ATTACH:
26814 : : break;
26815 : 1 : default:
26816 : 1 : error_at (OMP_CLAUSE_LOCATION (*pc),
26817 : : "%<#pragma omp target%> with map-type other "
26818 : : "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26819 : : "on %<map%> clause");
26820 : 1 : *pc = OMP_CLAUSE_CHAIN (*pc);
26821 : 1 : continue;
26822 : : }
26823 : 3590 : pc = &OMP_CLAUSE_CHAIN (*pc);
26824 : : }
26825 : 4155 : cfun->has_omp_target = true;
26826 : 4155 : return true;
26827 : : }
26828 : :
26829 : : /* OpenMP 4.0:
26830 : : # pragma omp declare simd declare-simd-clauses[optseq] new-line
26831 : :
26832 : : OpenMP 5.0:
26833 : : # pragma omp declare variant (identifier) match(context-selector) new-line
26834 : :
26835 : : OpenMP 5.1
26836 : : # pragma omp declare variant (identifier) match(context-selector) \
26837 : : adjust_args(adjust-op:argument-list) append_args(interop-list) new-line
26838 : : */
26839 : :
26840 : : #define OMP_DECLARE_SIMD_CLAUSE_MASK \
26841 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
26842 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
26843 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
26844 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
26845 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
26846 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
26847 : :
26848 : : static void
26849 : 703 : c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
26850 : : {
26851 : 703 : c_token *token = c_parser_peek_token (parser);
26852 : 703 : gcc_assert (token->type == CPP_NAME);
26853 : 703 : tree kind = token->value;
26854 : 703 : gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
26855 : : || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
26856 : :
26857 : 703 : auto_vec<c_token> clauses;
26858 : 11153 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
26859 : : {
26860 : 10450 : c_token *token = c_parser_peek_token (parser);
26861 : 10450 : if (token->type == CPP_EOF)
26862 : : {
26863 : 0 : c_parser_skip_to_pragma_eol (parser);
26864 : 0 : return;
26865 : : }
26866 : 10450 : clauses.safe_push (*token);
26867 : 10450 : c_parser_consume_token (parser);
26868 : : }
26869 : 703 : clauses.safe_push (*c_parser_peek_token (parser));
26870 : 703 : c_parser_skip_to_pragma_eol (parser);
26871 : :
26872 : 1610 : while (c_parser_next_token_is (parser, CPP_PRAGMA))
26873 : : {
26874 : 206 : if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
26875 : 204 : || c_parser_peek_2nd_token (parser)->type != CPP_NAME
26876 : 410 : || c_parser_peek_2nd_token (parser)->value != kind)
26877 : : {
26878 : 2 : error ("%<#pragma omp declare %s%> must be followed by "
26879 : : "function declaration or definition or another "
26880 : : "%<#pragma omp declare %s%>",
26881 : 2 : IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
26882 : 2 : return;
26883 : : }
26884 : 204 : c_parser_consume_pragma (parser);
26885 : 4460 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
26886 : : {
26887 : 4052 : c_token *token = c_parser_peek_token (parser);
26888 : 4052 : if (token->type == CPP_EOF)
26889 : : {
26890 : 0 : c_parser_skip_to_pragma_eol (parser);
26891 : 0 : return;
26892 : : }
26893 : 4052 : clauses.safe_push (*token);
26894 : 4052 : c_parser_consume_token (parser);
26895 : : }
26896 : 204 : clauses.safe_push (*c_parser_peek_token (parser));
26897 : 204 : c_parser_skip_to_pragma_eol (parser);
26898 : : }
26899 : :
26900 : : /* Make sure nothing tries to read past the end of the tokens. */
26901 : 701 : c_token eof_token;
26902 : 701 : memset (&eof_token, 0, sizeof (eof_token));
26903 : 701 : eof_token.type = CPP_EOF;
26904 : 701 : clauses.safe_push (eof_token);
26905 : 701 : clauses.safe_push (eof_token);
26906 : :
26907 : 701 : switch (context)
26908 : : {
26909 : 684 : case pragma_external:
26910 : 684 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26911 : 684 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26912 : : {
26913 : 1 : int ext = disable_extension_diagnostics ();
26914 : 1 : do
26915 : 1 : c_parser_consume_token (parser);
26916 : 1 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
26917 : 2 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26918 : 1 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
26919 : : false, NULL, &clauses);
26920 : 1 : restore_extension_diagnostics (ext);
26921 : : }
26922 : : else
26923 : 683 : c_parser_declaration_or_fndef (parser, true, true, true, false, true,
26924 : : false, NULL, &clauses);
26925 : : break;
26926 : 6 : case pragma_struct:
26927 : 6 : case pragma_param:
26928 : 6 : case pragma_stmt:
26929 : 6 : error ("%<#pragma omp declare %s%> must be followed by "
26930 : : "function declaration or definition",
26931 : 6 : IDENTIFIER_POINTER (kind));
26932 : 6 : break;
26933 : 11 : case pragma_compound:
26934 : 11 : bool have_std_attrs;
26935 : 11 : tree std_attrs;
26936 : 11 : have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
26937 : 11 : if (have_std_attrs)
26938 : 1 : std_attrs = c_parser_std_attribute_specifier_sequence (parser);
26939 : : else
26940 : : std_attrs = NULL_TREE;
26941 : 11 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26942 : 11 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26943 : : {
26944 : 1 : int ext = disable_extension_diagnostics ();
26945 : 3 : do
26946 : 3 : c_parser_consume_token (parser);
26947 : 3 : while (c_parser_next_token_is (parser, CPP_KEYWORD)
26948 : 4 : && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26949 : 1 : if (c_parser_next_tokens_start_declaration (parser)
26950 : 1 : || c_parser_nth_token_starts_std_attributes (parser, 1))
26951 : : {
26952 : 1 : c_parser_declaration_or_fndef (parser, true, true, true, true,
26953 : : true, false, NULL, &clauses,
26954 : : have_std_attrs, std_attrs);
26955 : 1 : restore_extension_diagnostics (ext);
26956 : 1 : break;
26957 : : }
26958 : 0 : restore_extension_diagnostics (ext);
26959 : : }
26960 : 10 : else if (c_parser_next_tokens_start_declaration (parser))
26961 : : {
26962 : 10 : c_parser_declaration_or_fndef (parser, true, true, true, true, true,
26963 : : false, NULL, &clauses, have_std_attrs,
26964 : : std_attrs);
26965 : 10 : break;
26966 : : }
26967 : 0 : error ("%<#pragma omp declare %s%> must be followed by "
26968 : : "function declaration or definition",
26969 : 0 : IDENTIFIER_POINTER (kind));
26970 : 0 : break;
26971 : 0 : default:
26972 : 0 : gcc_unreachable ();
26973 : : }
26974 : 703 : }
26975 : :
26976 : : /* OpenMP 5.0:
26977 : :
26978 : : trait-selector:
26979 : : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
26980 : :
26981 : : trait-score:
26982 : : score(score-expression)
26983 : :
26984 : : Note that this function returns a list of trait selectors for the
26985 : : trait-selector-set SET. */
26986 : :
26987 : : static tree
26988 : 948 : c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
26989 : : tree parms)
26990 : : {
26991 : 948 : tree ret = NULL_TREE;
26992 : 1126 : do
26993 : : {
26994 : 1126 : tree selector;
26995 : 1126 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
26996 : 2194 : || c_parser_next_token_is (parser, CPP_NAME))
26997 : 1124 : selector = c_parser_peek_token (parser)->value;
26998 : : else
26999 : : {
27000 : 2 : c_parser_error (parser, "expected trait selector name");
27001 : 2 : return error_mark_node;
27002 : : }
27003 : 1124 : enum omp_ts_code sel
27004 : 1124 : = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
27005 : :
27006 : 1124 : if (sel == OMP_TRAIT_INVALID)
27007 : : {
27008 : : /* Per the spec, "Implementations can ignore specified selectors
27009 : : that are not those described in this section"; however, we
27010 : : must record such selectors because they cause match failures. */
27011 : 18 : warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
27012 : : "unknown selector %qs for context selector set %qs",
27013 : 18 : IDENTIFIER_POINTER (selector), omp_tss_map[set]);
27014 : 18 : c_parser_consume_token (parser);
27015 : 18 : ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
27016 : 18 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27017 : 5 : c_parser_balanced_token_sequence (parser);
27018 : 18 : if (c_parser_next_token_is (parser, CPP_COMMA))
27019 : : {
27020 : 1 : c_parser_consume_token (parser);
27021 : 1 : continue;
27022 : : }
27023 : : else
27024 : : break;
27025 : : }
27026 : :
27027 : 1106 : c_parser_consume_token (parser);
27028 : :
27029 : 1106 : tree properties = NULL_TREE;
27030 : 1106 : tree scoreval = NULL_TREE;
27031 : 1106 : enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
27032 : 1106 : bool allow_score = omp_ts_map[sel].allow_score;
27033 : 1106 : tree t;
27034 : :
27035 : 1106 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27036 : : {
27037 : 641 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
27038 : : {
27039 : 12 : error_at (c_parser_peek_token (parser)->location,
27040 : : "selector %qs does not accept any properties",
27041 : 6 : IDENTIFIER_POINTER (selector));
27042 : 16 : return error_mark_node;
27043 : : }
27044 : :
27045 : 635 : matching_parens parens;
27046 : 635 : parens.require_open (parser);
27047 : :
27048 : 635 : c_token *token = c_parser_peek_token (parser);
27049 : 635 : if (c_parser_next_token_is (parser, CPP_NAME)
27050 : 472 : && strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
27051 : 723 : && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
27052 : : {
27053 : 88 : c_parser_consume_token (parser);
27054 : :
27055 : 88 : matching_parens parens2;
27056 : 88 : parens2.require_open (parser);
27057 : 88 : tree score = c_parser_expr_no_commas (parser, NULL).value;
27058 : 88 : parens2.skip_until_found_close (parser);
27059 : 88 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
27060 : 88 : if (!allow_score)
27061 : 13 : error_at (token->location,
27062 : : "%<score%> cannot be specified in traits "
27063 : : "in the %qs trait-selector-set",
27064 : : omp_tss_map[set]);
27065 : 75 : else if (score != error_mark_node)
27066 : : {
27067 : 75 : mark_exp_read (score);
27068 : 75 : score = c_fully_fold (score, false, NULL);
27069 : 150 : if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
27070 : 149 : || TREE_CODE (score) != INTEGER_CST)
27071 : 1 : error_at (token->location, "%<score%> argument must "
27072 : : "be constant integer expression");
27073 : 74 : else if (tree_int_cst_sgn (score) < 0)
27074 : 1 : error_at (token->location, "%<score%> argument must "
27075 : : "be non-negative");
27076 : : else
27077 : : scoreval = score;
27078 : : }
27079 : 88 : token = c_parser_peek_token (parser);
27080 : : }
27081 : :
27082 : 635 : switch (property_kind)
27083 : : {
27084 : 25 : case OMP_TRAIT_PROPERTY_ID:
27085 : 25 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27086 : 50 : || c_parser_next_token_is (parser, CPP_NAME))
27087 : : {
27088 : 24 : tree prop = c_parser_peek_token (parser)->value;
27089 : 24 : c_parser_consume_token (parser);
27090 : 24 : properties = make_trait_property (prop, NULL_TREE,
27091 : : properties);
27092 : : }
27093 : : else
27094 : : {
27095 : 1 : c_parser_error (parser, "expected identifier");
27096 : 1 : return error_mark_node;
27097 : : }
27098 : 24 : break;
27099 : 523 : case OMP_TRAIT_PROPERTY_NAME_LIST:
27100 : 581 : do
27101 : : {
27102 : 523 : tree prop = OMP_TP_NAMELIST_NODE;
27103 : 523 : tree value = NULL_TREE;
27104 : 523 : if (c_parser_next_token_is (parser, CPP_KEYWORD)
27105 : 1046 : || c_parser_next_token_is (parser, CPP_NAME))
27106 : : {
27107 : 390 : value = c_parser_peek_token (parser)->value;
27108 : 390 : c_parser_consume_token (parser);
27109 : : }
27110 : 133 : else if (c_parser_next_token_is (parser, CPP_STRING))
27111 : 128 : value = c_parser_string_literal (parser, false,
27112 : : false).value;
27113 : : else
27114 : : {
27115 : 5 : c_parser_error (parser, "expected identifier or "
27116 : : "string literal");
27117 : 5 : return error_mark_node;
27118 : : }
27119 : :
27120 : 518 : properties = make_trait_property (prop, value, properties);
27121 : :
27122 : 518 : if (c_parser_next_token_is (parser, CPP_COMMA))
27123 : 58 : c_parser_consume_token (parser);
27124 : : else
27125 : : break;
27126 : 58 : }
27127 : : while (1);
27128 : : break;
27129 : 122 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
27130 : 122 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
27131 : 122 : {
27132 : 122 : c_expr texpr = c_parser_expr_no_commas (parser, NULL);
27133 : 122 : texpr = convert_lvalue_to_rvalue (token->location, texpr,
27134 : : true, true);
27135 : 122 : t = texpr.value;
27136 : : }
27137 : 122 : if (t == error_mark_node)
27138 : : return error_mark_node;
27139 : 120 : mark_exp_read (t);
27140 : 120 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
27141 : : {
27142 : 97 : t = c_objc_common_truthvalue_conversion (token->location,
27143 : : t,
27144 : : boolean_type_node);
27145 : 97 : if (t == error_mark_node)
27146 : : return error_mark_node;
27147 : : }
27148 : 23 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
27149 : : {
27150 : 0 : error_at (token->location,
27151 : : "property must be integer expression");
27152 : 0 : return error_mark_node;
27153 : : }
27154 : 118 : t = c_fully_fold (t, false, NULL);
27155 : 118 : properties = make_trait_property (NULL_TREE, t, properties);
27156 : 118 : break;
27157 : 23 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
27158 : 23 : if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
27159 : : {
27160 : 23 : if (parms == NULL_TREE)
27161 : : {
27162 : 0 : error_at (token->location, "properties for %<simd%> "
27163 : : "selector may not be specified in "
27164 : : "%<metadirective%>");
27165 : 0 : return error_mark_node;
27166 : : }
27167 : 23 : tree c;
27168 : 46 : c = c_parser_omp_all_clauses (parser,
27169 : 23 : OMP_DECLARE_SIMD_CLAUSE_MASK,
27170 : : "simd", true, 2);
27171 : 46 : c = c_omp_declare_simd_clauses_to_numbers (parms
27172 : 23 : == error_mark_node
27173 : : ? NULL_TREE : parms,
27174 : : c);
27175 : 23 : properties = c;
27176 : : }
27177 : 0 : else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
27178 : : {
27179 : : /* FIXME: The "requires" selector was added in OpenMP 5.1.
27180 : : Currently only the now-deprecated syntax
27181 : : from OpenMP 5.0 is supported. */
27182 : 0 : sorry_at (token->location,
27183 : : "%<requires%> selector is not supported yet");
27184 : 0 : return error_mark_node;
27185 : : }
27186 : : else
27187 : 0 : gcc_unreachable ();
27188 : 23 : break;
27189 : 0 : default:
27190 : 0 : gcc_unreachable ();
27191 : : }
27192 : :
27193 : 625 : parens.skip_until_found_close (parser);
27194 : 625 : properties = nreverse (properties);
27195 : : }
27196 : 465 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
27197 : 465 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
27198 : 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
27199 : : {
27200 : 8 : c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
27201 : 8 : return error_mark_node;
27202 : : }
27203 : :
27204 : 1082 : ret = make_trait_selector (sel, scoreval, properties, ret);
27205 : :
27206 : 1082 : if (c_parser_next_token_is (parser, CPP_COMMA))
27207 : 177 : c_parser_consume_token (parser);
27208 : : else
27209 : : break;
27210 : : }
27211 : : while (1);
27212 : :
27213 : 922 : return nreverse (ret);
27214 : : }
27215 : :
27216 : : /* OpenMP 5.0:
27217 : :
27218 : : trait-set-selector[,trait-set-selector[,...]]
27219 : :
27220 : : trait-set-selector:
27221 : : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
27222 : :
27223 : : trait-set-selector-name:
27224 : : constructor
27225 : : device
27226 : : implementation
27227 : : user */
27228 : :
27229 : : static tree
27230 : 730 : c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
27231 : : {
27232 : 730 : tree ret = NULL_TREE;
27233 : 1182 : do
27234 : : {
27235 : 956 : const char *setp = "";
27236 : 956 : if (c_parser_next_token_is (parser, CPP_NAME))
27237 : 954 : setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27238 : 956 : enum omp_tss_code set = omp_lookup_tss_code (setp);
27239 : :
27240 : 956 : if (set == OMP_TRAIT_SET_INVALID)
27241 : : {
27242 : 5 : c_parser_error (parser, "expected context selector set name");
27243 : 8 : return error_mark_node;
27244 : : }
27245 : :
27246 : 951 : c_parser_consume_token (parser);
27247 : :
27248 : 951 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
27249 : 1 : return error_mark_node;
27250 : :
27251 : 950 : matching_braces braces;
27252 : 950 : if (!braces.require_open (parser))
27253 : 2 : return error_mark_node;
27254 : :
27255 : 948 : tree selectors = c_parser_omp_context_selector (parser, set, parms);
27256 : 948 : if (selectors == error_mark_node)
27257 : : {
27258 : 26 : c_parser_skip_to_closing_brace (parser);
27259 : 26 : ret = error_mark_node;
27260 : : }
27261 : 922 : else if (ret != error_mark_node)
27262 : 922 : ret = make_trait_set_selector (set, selectors, ret);
27263 : :
27264 : 948 : braces.require_close (parser);
27265 : :
27266 : 948 : if (c_parser_next_token_is (parser, CPP_COMMA))
27267 : 226 : c_parser_consume_token (parser);
27268 : : else
27269 : : break;
27270 : 226 : }
27271 : : while (1);
27272 : :
27273 : 722 : if (ret == error_mark_node)
27274 : : return ret;
27275 : 696 : return nreverse (ret);
27276 : : }
27277 : :
27278 : : /* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
27279 : : that into "omp declare variant base" attribute. */
27280 : :
27281 : : static void
27282 : 613 : c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
27283 : : {
27284 : 613 : matching_parens parens;
27285 : 613 : if (!parens.require_open (parser))
27286 : : {
27287 : 3 : fail:
27288 : 50 : c_parser_skip_to_pragma_eol (parser, false);
27289 : 50 : return;
27290 : : }
27291 : :
27292 : 610 : if (c_parser_next_token_is_not (parser, CPP_NAME)
27293 : 610 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
27294 : : {
27295 : 3 : c_parser_error (parser, "expected identifier");
27296 : 3 : goto fail;
27297 : : }
27298 : :
27299 : 607 : c_token *token = c_parser_peek_token (parser);
27300 : 607 : tree variant = lookup_name (token->value);
27301 : :
27302 : 607 : if (variant == NULL_TREE)
27303 : : {
27304 : 3 : undeclared_variable (token->location, token->value);
27305 : 3 : variant = error_mark_node;
27306 : : }
27307 : 604 : else if (TREE_CODE (variant) != FUNCTION_DECL)
27308 : : {
27309 : 1 : error_at (token->location, "variant %qD is not a function",
27310 : : variant);
27311 : 1 : variant = error_mark_node;
27312 : : }
27313 : 603 : else if (fndecl_built_in_p (variant)
27314 : 603 : && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27315 : : "__builtin_", strlen ("__builtin_")) == 0
27316 : 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27317 : : "__sync_", strlen ("__sync_")) == 0
27318 : 0 : || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27319 : : "__atomic_", strlen ("__atomic_")) == 0))
27320 : : {
27321 : 1 : error_at (token->location, "variant %qD is a built-in",
27322 : : variant);
27323 : 1 : variant = error_mark_node;
27324 : : }
27325 : 602 : else if (variant == fndecl)
27326 : : {
27327 : 2 : error_at (token->location, "variant %qD is the same as base function",
27328 : : variant);
27329 : 2 : variant = error_mark_node;
27330 : : }
27331 : :
27332 : 607 : c_parser_consume_token (parser);
27333 : :
27334 : 607 : parens.require_close (parser);
27335 : :
27336 : 607 : tree append_args_tree = NULL_TREE;
27337 : 607 : tree append_args_last;
27338 : 607 : vec<tree> adjust_args_list = vNULL;
27339 : 607 : bool has_match = false, has_adjust_args = false;
27340 : 607 : location_t adjust_args_loc = UNKNOWN_LOCATION;
27341 : 607 : location_t append_args_loc = UNKNOWN_LOCATION;
27342 : 607 : location_t match_loc = UNKNOWN_LOCATION;
27343 : 607 : tree need_device_ptr_list = NULL_TREE;
27344 : 607 : tree ctx = error_mark_node;
27345 : :
27346 : 706 : do
27347 : : {
27348 : 706 : if (c_parser_next_token_is (parser, CPP_COMMA)
27349 : 706 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
27350 : 9 : c_parser_consume_token (parser);
27351 : :
27352 : 706 : const char *clause = "";
27353 : 706 : location_t loc = c_parser_peek_token (parser)->location;
27354 : 706 : if (c_parser_next_token_is (parser, CPP_NAME))
27355 : 705 : clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27356 : :
27357 : 706 : enum clause
27358 : : {
27359 : : match,
27360 : : adjust_args,
27361 : : append_args
27362 : : } ccode;
27363 : :
27364 : 706 : if (strcmp (clause, "match") == 0)
27365 : : {
27366 : : ccode = match;
27367 : : match_loc = loc;
27368 : : }
27369 : 102 : else if (strcmp (clause, "adjust_args") == 0)
27370 : : {
27371 : : ccode = adjust_args;
27372 : : adjust_args_loc = loc;
27373 : : }
27374 : 50 : else if (strcmp (clause, "append_args") == 0)
27375 : : {
27376 : : ccode = append_args;
27377 : : append_args_loc = loc;
27378 : : }
27379 : : else
27380 : : {
27381 : 2 : c_parser_error (parser, "expected %<match%>, %<adjust_args%> or "
27382 : : "%<append_args%> clause");
27383 : 2 : goto fail;
27384 : : }
27385 : :
27386 : 704 : c_parser_consume_token (parser);
27387 : :
27388 : 704 : if (!parens.require_open (parser))
27389 : 1 : goto fail;
27390 : :
27391 : 703 : if (parms == NULL_TREE)
27392 : 446 : parms = error_mark_node;
27393 : :
27394 : 703 : if (ccode == match)
27395 : : {
27396 : 603 : if (has_match)
27397 : 1 : error_at (match_loc, "too many %<match%> clauses");
27398 : 603 : has_match = true;
27399 : 603 : ctx = c_parser_omp_context_selector_specification (parser, parms);
27400 : 603 : if (ctx == error_mark_node)
27401 : 32 : goto fail;
27402 : 571 : ctx = omp_check_context_selector (match_loc, ctx,
27403 : : OMP_CTX_DECLARE_VARIANT);
27404 : : }
27405 : 100 : else if (ccode == adjust_args)
27406 : : {
27407 : 52 : has_adjust_args = true;
27408 : 52 : if (c_parser_next_token_is (parser, CPP_NAME)
27409 : 52 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
27410 : : {
27411 : 50 : const char *p
27412 : 50 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27413 : 50 : if (strcmp (p, "need_device_ptr") == 0
27414 : 15 : || strcmp (p, "nothing") == 0)
27415 : : {
27416 : 48 : c_parser_consume_token (parser); // need_device_ptr
27417 : 48 : c_parser_consume_token (parser); // :
27418 : :
27419 : 48 : loc = c_parser_peek_token (parser)->location;
27420 : 48 : tree list
27421 : 48 : = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_ERROR,
27422 : : NULL_TREE);
27423 : :
27424 : 48 : tree arg;
27425 : 48 : if (variant != error_mark_node)
27426 : 103 : for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
27427 : : {
27428 : 61 : tree decl = TREE_PURPOSE (c);
27429 : 61 : location_t arg_loc = EXPR_LOCATION (TREE_VALUE (c));
27430 : 61 : int idx;
27431 : 111 : for (arg = parms, idx = 0; arg != NULL;
27432 : 50 : arg = TREE_CHAIN (arg), idx++)
27433 : 110 : if (arg == decl)
27434 : : break;
27435 : 61 : if (arg == NULL_TREE)
27436 : : {
27437 : 1 : error_at (arg_loc,
27438 : : "%qD is not a function argument",
27439 : : decl);
27440 : 5 : goto fail;
27441 : : }
27442 : 60 : if (adjust_args_list.contains (arg))
27443 : : {
27444 : 3 : error_at (arg_loc,
27445 : : "%qD is specified more than once",
27446 : : decl);
27447 : 3 : goto fail;
27448 : : }
27449 : 57 : if (strcmp (p, "need_device_ptr") == 0
27450 : 57 : && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
27451 : : {
27452 : 1 : error_at (loc, "%qD is not of pointer type", decl);
27453 : 1 : goto fail;
27454 : : }
27455 : 56 : adjust_args_list.safe_push (arg);
27456 : 56 : if (strcmp (p, "need_device_ptr") == 0)
27457 : : {
27458 : 46 : need_device_ptr_list = chainon (
27459 : : need_device_ptr_list,
27460 : : build_tree_list (
27461 : : NULL_TREE,
27462 : : build_int_cst (
27463 : : integer_type_node,
27464 : 46 : idx))); // Store 0-based argument index,
27465 : : // as in gimplify_call_expr
27466 : : }
27467 : : }
27468 : 43 : }
27469 : : else
27470 : : {
27471 : 2 : error_at (c_parser_peek_token (parser)->location,
27472 : : "expected %<nothing%> or %<need_device_ptr%>");
27473 : 2 : if (strcmp (p, "need_device_addr") == 0)
27474 : 1 : inform (c_parser_peek_token (parser)->location,
27475 : : "%<need_device_addr%> is not valid for C");
27476 : 2 : goto fail;
27477 : : }
27478 : : }
27479 : : else
27480 : : {
27481 : 2 : error_at (c_parser_peek_token (parser)->location,
27482 : : "expected %<nothing%> or %<need_device_ptr%> "
27483 : : "followed by %<:%>");
27484 : 2 : goto fail;
27485 : : }
27486 : : }
27487 : 48 : else if (ccode == append_args)
27488 : : {
27489 : 48 : if (append_args_tree)
27490 : : {
27491 : 1 : error_at (append_args_loc, "too many %qs clauses", "append_args");
27492 : 1 : append_args_tree = NULL_TREE;
27493 : : }
27494 : 86 : do
27495 : : {
27496 : 67 : location_t loc = c_parser_peek_token (parser)->location;
27497 : 67 : if (!c_parser_next_token_is (parser, CPP_NAME)
27498 : 67 : || strcmp ("interop",
27499 : 67 : IDENTIFIER_POINTER (
27500 : : c_parser_peek_token (parser)->value)))
27501 : : {
27502 : 0 : error_at (loc, "expected %<interop%>");
27503 : 0 : goto fail;
27504 : : }
27505 : 67 : c_parser_consume_token (parser);
27506 : :
27507 : 67 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
27508 : 0 : goto fail;
27509 : 67 : bool target = false;
27510 : 67 : bool targetsync = false;
27511 : 67 : tree prefer_type_tree = NULL_TREE;
27512 : 67 : if (!c_parser_omp_clause_init_modifiers (parser, &target,
27513 : : &targetsync,
27514 : : &prefer_type_tree)
27515 : 67 : || !c_parser_require (parser, CPP_CLOSE_PAREN,
27516 : : "expected %<)%> or %<,%>"))
27517 : 0 : goto fail;
27518 : 67 : if (!target && !targetsync)
27519 : 3 : error_at (loc,
27520 : : "missing required %<target%> and/or "
27521 : : "%<targetsync%> modifier");
27522 : 67 : tree t = build_tree_list (target ? boolean_true_node
27523 : : : boolean_false_node,
27524 : : targetsync ? boolean_true_node
27525 : : : boolean_false_node);
27526 : 67 : t = build1_loc (loc, NOP_EXPR, void_type_node, t);
27527 : 67 : t = build_tree_list (t, prefer_type_tree);
27528 : 67 : if (append_args_tree)
27529 : : {
27530 : 19 : TREE_CHAIN (append_args_last) = t;
27531 : 19 : append_args_last = t;
27532 : : }
27533 : : else
27534 : : append_args_tree = append_args_last = t;
27535 : 67 : if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
27536 : : break;
27537 : 19 : if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>"))
27538 : 0 : goto fail;
27539 : 19 : }
27540 : : while (true);
27541 : : }
27542 : :
27543 : 662 : parens.require_close (parser);
27544 : 662 : } while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL));
27545 : 563 : if (variant != error_mark_node && !has_match)
27546 : : {
27547 : 1 : c_parser_error (parser, "expected %<match%> clause");
27548 : 1 : variant = error_mark_node;
27549 : : }
27550 : 563 : c_parser_skip_to_pragma_eol (parser);
27551 : :
27552 : : /* At this point, we have completed parsing of the pragma, now it's
27553 : : on to error checking. */
27554 : 563 : if (variant == error_mark_node || ctx == error_mark_node)
27555 : : /* Previously diagnosed error. */
27556 : : return;
27557 : :
27558 : 533 : if ((has_adjust_args || append_args_tree)
27559 : 533 : && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27560 : : OMP_TRAIT_CONSTRUCT_DISPATCH))
27561 : : {
27562 : 1 : error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
27563 : : "an %qs clause can only be specified if the "
27564 : : "%<dispatch%> selector of the %<construct%> selector "
27565 : : "set appears in the %<match%> clause",
27566 : : has_adjust_args ? "adjust_args" : "append_args");
27567 : 1 : return;
27568 : : }
27569 : :
27570 : 532 : if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27571 : : OMP_TRAIT_CONSTRUCT_SIMD))
27572 : : /* Check that the base and variant have compatible types. */
27573 : : {
27574 : 509 : tree base_type = TREE_TYPE (fndecl);
27575 : 509 : tree variant_type = TREE_TYPE (variant);
27576 : 509 : bool unprototyped_variant
27577 : 509 : = (TYPE_ARG_TYPES (variant_type) == NULL_TREE
27578 : 509 : && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type));
27579 : :
27580 : 509 : if (append_args_tree
27581 : 47 : && TYPE_ARG_TYPES (base_type) == NULL_TREE
27582 : 517 : && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type))
27583 : : {
27584 : : /* The base function is a pre-C23 unprototyped function. Without
27585 : : a prototype, we don't know the offset where the append_args go.
27586 : : That offset needs to be stored with the append_args in the
27587 : : variant function attributes, so we cannot presently handle
27588 : : this case. */
27589 : 6 : sorry_at (append_args_loc,
27590 : : "%<append_args%> with unprototyped base function "
27591 : : "is not supported yet");
27592 : 6 : inform (DECL_SOURCE_LOCATION (fndecl),
27593 : : "base function %qD declared here", fndecl);
27594 : 6 : return;
27595 : : }
27596 : 503 : else if (append_args_tree)
27597 : : {
27598 : : /* Find nbase_args, the number of fixed arguments in the base
27599 : : function. */
27600 : 41 : int nappend_args = 0;
27601 : 41 : int nbase_args = 0;
27602 : 41 : for (tree t = TYPE_ARG_TYPES (base_type);
27603 : 183 : t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
27604 : 55 : nbase_args++;
27605 : 101 : for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
27606 : 60 : nappend_args++;
27607 : :
27608 : : /* Store as purpose = arg number after which to append
27609 : : and value = list of interop items. */
27610 : 41 : append_args_tree = build_tree_list (build_int_cst (integer_type_node,
27611 : 41 : nbase_args),
27612 : : append_args_tree);
27613 : :
27614 : : /* Give a specific diagnostic if the append_args parameters
27615 : : of the variant are of the wrong type, or missing. The
27616 : : compatible types test below could fail to detect this if
27617 : : the variant is a varargs function. */
27618 : 41 : if (!unprototyped_variant)
27619 : : {
27620 : 39 : tree args = TYPE_ARG_TYPES (variant_type);
27621 : 90 : for (int i = 0; args && i < nbase_args;
27622 : 51 : i++, args = TREE_CHAIN (args))
27623 : : ;
27624 : 89 : for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args))
27625 : 109 : if (!args || !c_omp_interop_t_p (TREE_VALUE (args)))
27626 : : {
27627 : 5 : error_at (DECL_SOURCE_LOCATION (variant),
27628 : : "argument %d of %qD must be of "
27629 : : "%<omp_interop_t%>",
27630 : 5 : nbase_args + i + 1, variant);
27631 : 5 : inform (append_args_loc,
27632 : : "%<append_args%> specified here");
27633 : 100 : return;
27634 : : }
27635 : : }
27636 : :
27637 : : /* Perform the "implementation defined transformation" on the type
27638 : : of the base function to add the append_args before checking it
27639 : : for compatibility with the function variant's type. */
27640 : 36 : tree args = TYPE_ARG_TYPES (base_type);
27641 : 36 : tree newargs = NULL_TREE;
27642 : 36 : tree lastarg = NULL_TREE;
27643 : 89 : for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args))
27644 : : {
27645 : 53 : tree t = tree_cons (TREE_PURPOSE (args),
27646 : 53 : TREE_VALUE (args), NULL_TREE);
27647 : 53 : if (lastarg)
27648 : 31 : TREE_CHAIN (lastarg) = t;
27649 : : else
27650 : : newargs = t;
27651 : 53 : lastarg = t;
27652 : : }
27653 : 36 : tree type = lookup_name (get_identifier ("omp_interop_t"));
27654 : 36 : type = type ? TREE_TYPE (type) : pointer_sized_int_node;
27655 : 87 : for (int j = 0; j < nappend_args; j++)
27656 : : {
27657 : 51 : tree t = tree_cons (NULL_TREE, type, NULL_TREE);
27658 : 51 : if (lastarg)
27659 : 37 : TREE_CHAIN (lastarg) = t;
27660 : : else
27661 : : newargs = t;
27662 : 51 : lastarg = t;
27663 : : }
27664 : 36 : TREE_CHAIN (lastarg) = args;
27665 : :
27666 : : /* Temporarily stuff newargs into the original base_type. */
27667 : 36 : tree saveargs = TYPE_ARG_TYPES (base_type);
27668 : 36 : TYPE_ARG_TYPES (base_type) = newargs;
27669 : 36 : bool fail = !comptypes (base_type, variant_type);
27670 : 36 : TYPE_ARG_TYPES (base_type) = saveargs;
27671 : :
27672 : 36 : if (fail)
27673 : : {
27674 : 2 : error_at (token->location,
27675 : : "variant %qD and base %qD have incompatible types "
27676 : : "after %<append_args%> adjustment",
27677 : : variant, fndecl);
27678 : 2 : inform (DECL_SOURCE_LOCATION (variant),
27679 : : "%<declare variant%> candidate %qD declared here",
27680 : : variant);
27681 : 2 : return;
27682 : : }
27683 : 34 : else if (unprototyped_variant)
27684 : : /* If we've got an unprototyped variant, copy the transformed
27685 : : base arg types to the variant. This is needed later by
27686 : : modify_call_for_omp_dispatch. */
27687 : 2 : TYPE_ARG_TYPES (variant_type) = newargs;
27688 : : }
27689 : : else /* No append_args present. */
27690 : : {
27691 : 462 : if (!comptypes (base_type, variant_type))
27692 : : {
27693 : 1 : error_at (token->location,
27694 : : "variant %qD and base %qD have incompatible types",
27695 : : variant, fndecl);
27696 : 1 : inform (DECL_SOURCE_LOCATION (variant),
27697 : : "%<declare variant%> candidate %qD declared here",
27698 : : variant);
27699 : 1 : return;
27700 : : }
27701 : 461 : else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE
27702 : 3 : && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)
27703 : 463 : && TYPE_ARG_TYPES (base_type) != NULL_TREE)
27704 : : /* If we've got an unprototyped variant but the base has
27705 : : a prototype, copy the base arg types to the variant. */
27706 : 1 : TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type);
27707 : : }
27708 : : }
27709 : :
27710 : : /* If we made it here, store the parsed information. */
27711 : 518 : C_DECL_USED (variant) = 1;
27712 : 518 : tree construct = omp_get_context_selector_list (ctx,
27713 : : OMP_TRAIT_SET_CONSTRUCT);
27714 : 518 : omp_mark_declare_variant (match_loc, variant, construct);
27715 : 518 : if (omp_context_selector_matches (ctx, NULL_TREE, false))
27716 : : {
27717 : 242 : tree attr = tree_cons (get_identifier ("omp declare variant base"),
27718 : : build_tree_list (variant, ctx),
27719 : 242 : DECL_ATTRIBUTES (fndecl));
27720 : 242 : DECL_ATTRIBUTES (fndecl) = attr;
27721 : : }
27722 : :
27723 : 518 : if (need_device_ptr_list || append_args_tree)
27724 : : {
27725 : 49 : tree variant_decl = tree_strip_nop_conversions (variant);
27726 : 49 : tree t = build_tree_list (need_device_ptr_list,
27727 : : NULL_TREE /* need_device_addr */);
27728 : 49 : TREE_CHAIN (t) = append_args_tree;
27729 : 49 : DECL_ATTRIBUTES (variant_decl)
27730 : 98 : = tree_cons (get_identifier ("omp declare variant variant args"), t,
27731 : 49 : DECL_ATTRIBUTES (variant_decl));
27732 : : }
27733 : : }
27734 : :
27735 : : /* Finalize #pragma omp declare simd or #pragma omp declare variant
27736 : : clauses after FNDECL has been parsed, and put that into "omp declare simd"
27737 : : or "omp declare variant base" attribute. */
27738 : :
27739 : : static void
27740 : 775 : c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
27741 : : vec<c_token> *pclauses)
27742 : : {
27743 : 775 : vec<c_token> &clauses = *pclauses;
27744 : :
27745 : : /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
27746 : : indicates error has been reported and CPP_PRAGMA that
27747 : : c_finish_omp_declare_simd has already processed the tokens. */
27748 : 1550 : if (clauses.exists () && clauses[0].type == CPP_EOF)
27749 : : return;
27750 : 771 : const char *kind = "simd";
27751 : 771 : if (clauses.exists ()
27752 : 1542 : && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
27753 : 771 : kind = IDENTIFIER_POINTER (clauses[0].value);
27754 : 771 : gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
27755 : 771 : if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
27756 : : {
27757 : 15 : error ("%<#pragma omp declare %s%> not immediately followed by "
27758 : : "a function declaration or definition", kind);
27759 : 15 : clauses[0].type = CPP_EOF;
27760 : 15 : return;
27761 : : }
27762 : 1512 : if (clauses.exists () && clauses[0].type != CPP_NAME)
27763 : : {
27764 : 2 : error_at (DECL_SOURCE_LOCATION (fndecl),
27765 : : "%<#pragma omp declare %s%> not immediately followed by "
27766 : : "a single function declaration or definition", kind);
27767 : 2 : clauses[0].type = CPP_EOF;
27768 : 2 : return;
27769 : : }
27770 : :
27771 : 754 : if (parms == NULL_TREE)
27772 : 518 : parms = DECL_ARGUMENTS (fndecl);
27773 : :
27774 : 754 : unsigned int tokens_avail = parser->tokens_avail;
27775 : 754 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27776 : :
27777 : 754 : parser->tokens = clauses.address ();
27778 : 754 : parser->tokens_avail = clauses.length ();
27779 : :
27780 : : /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
27781 : 1730 : while (parser->tokens_avail > 3)
27782 : : {
27783 : 976 : c_token *token = c_parser_peek_token (parser);
27784 : 976 : gcc_assert (token->type == CPP_NAME);
27785 : 976 : kind = IDENTIFIER_POINTER (token->value);
27786 : 976 : c_parser_consume_token (parser);
27787 : 976 : parser->in_pragma = true;
27788 : :
27789 : 976 : if (strcmp (kind, "simd") == 0)
27790 : : {
27791 : 363 : tree c;
27792 : 363 : c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
27793 : : "#pragma omp declare simd");
27794 : 363 : c = c_omp_declare_simd_clauses_to_numbers (parms, c);
27795 : 363 : if (c != NULL_TREE)
27796 : 258 : c = tree_cons (NULL_TREE, c, NULL_TREE);
27797 : 363 : c = build_tree_list (get_identifier ("omp declare simd"), c);
27798 : 363 : TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
27799 : 363 : DECL_ATTRIBUTES (fndecl) = c;
27800 : : }
27801 : : else
27802 : : {
27803 : 613 : gcc_assert (strcmp (kind, "variant") == 0);
27804 : 613 : c_finish_omp_declare_variant (parser, fndecl, parms);
27805 : : }
27806 : : }
27807 : :
27808 : 754 : parser->tokens = &parser->tokens_buf[0];
27809 : 754 : parser->tokens_avail = tokens_avail;
27810 : 754 : if (clauses.exists ())
27811 : 754 : clauses[0].type = CPP_PRAGMA;
27812 : : }
27813 : :
27814 : : /* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
27815 : : a threadprivate, groupprivate, allocate or declare target directive,
27816 : : return true and parse it for DECL. */
27817 : :
27818 : : bool
27819 : 38 : c_maybe_parse_omp_decl (tree decl, tree d)
27820 : : {
27821 : 38 : gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
27822 : 38 : vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
27823 : 38 : c_token *first = toks->address ();
27824 : 38 : c_token *last = first + toks->length ();
27825 : 38 : const char *directive[3] = {};
27826 : 109 : for (int j = 0; j < 3; j++)
27827 : : {
27828 : 97 : tree id = NULL_TREE;
27829 : 97 : if (first + j == last)
27830 : : break;
27831 : 78 : if (first[j].type == CPP_NAME)
27832 : 71 : id = first[j].value;
27833 : 7 : else if (first[j].type == CPP_KEYWORD)
27834 : 0 : id = ridpointers[(int) first[j].keyword];
27835 : : else
27836 : : break;
27837 : 71 : directive[j] = IDENTIFIER_POINTER (id);
27838 : : }
27839 : 38 : const c_omp_directive *dir = NULL;
27840 : 38 : if (directive[0])
27841 : 38 : dir = c_omp_categorize_directive (directive[0], directive[1],
27842 : : directive[2]);
27843 : 38 : if (dir == NULL)
27844 : : {
27845 : 0 : error_at (first->location,
27846 : : "unknown OpenMP directive name in "
27847 : : "%qs attribute argument", "omp::decl");
27848 : 0 : return false;
27849 : : }
27850 : 38 : if (dir->id != PRAGMA_OMP_THREADPRIVATE
27851 : : /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
27852 : 23 : && dir->id != PRAGMA_OMP_ALLOCATE
27853 : 21 : && (dir->id != PRAGMA_OMP_DECLARE
27854 : 21 : || strcmp (directive[1], "target") != 0))
27855 : : return false;
27856 : :
27857 : 38 : if (!flag_openmp && !dir->simd)
27858 : : return true;
27859 : :
27860 : 38 : c_parser *parser = the_parser;
27861 : 38 : unsigned int tokens_avail = parser->tokens_avail;
27862 : 38 : gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27863 : 38 : toks = NULL;
27864 : 38 : vec_safe_reserve (toks, last - first + 2, true);
27865 : 38 : c_token tok = {};
27866 : 38 : tok.type = CPP_PRAGMA;
27867 : 38 : tok.keyword = RID_MAX;
27868 : 38 : tok.pragma_kind = pragma_kind (dir->id);
27869 : 38 : tok.location = first->location;
27870 : 38 : toks->quick_push (tok);
27871 : 176 : while (++first < last)
27872 : 100 : toks->quick_push (*first);
27873 : 38 : tok = {};
27874 : 38 : tok.type = CPP_PRAGMA_EOL;
27875 : 38 : tok.keyword = RID_MAX;
27876 : 38 : tok.location = last[-1].location;
27877 : 38 : toks->quick_push (tok);
27878 : 38 : tok = {};
27879 : 38 : tok.type = CPP_EOF;
27880 : 38 : tok.keyword = RID_MAX;
27881 : 38 : tok.location = last[-1].location;
27882 : 38 : toks->quick_push (tok);
27883 : 38 : parser->in_omp_decl_attribute = decl;
27884 : 38 : gcc_assert (!parser->in_omp_attribute_pragma);
27885 : 38 : parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
27886 : 38 : parser->in_omp_attribute_pragma->token_vec = toks;
27887 : 38 : parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
27888 : 38 : parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
27889 : 38 : parser->tokens = toks->address ();
27890 : 38 : parser->tokens_avail = toks->length ();
27891 : 38 : c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
27892 : 38 : parser->in_omp_decl_attribute = NULL_TREE;
27893 : 38 : return true;
27894 : : }
27895 : :
27896 : : /* OpenMP 4.0:
27897 : : # pragma omp declare target new-line
27898 : : declarations and definitions
27899 : : # pragma omp end declare target new-line
27900 : :
27901 : : OpenMP 4.5:
27902 : : # pragma omp declare target ( extended-list ) new-line
27903 : :
27904 : : # pragma omp declare target declare-target-clauses[seq] new-line */
27905 : :
27906 : : #define OMP_DECLARE_TARGET_CLAUSE_MASK \
27907 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
27908 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
27909 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
27910 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27911 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
27912 : :
27913 : : static void
27914 : 273 : c_parser_omp_declare_target (c_parser *parser)
27915 : : {
27916 : 273 : tree clauses = NULL_TREE;
27917 : 273 : int device_type = 0;
27918 : 273 : bool indirect = false;
27919 : 273 : bool only_device_type_or_indirect = true;
27920 : 273 : if (flag_openmp)
27921 : 273 : omp_requires_mask
27922 : 273 : = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27923 : 273 : if (c_parser_next_token_is (parser, CPP_NAME)
27924 : 407 : || (c_parser_next_token_is (parser, CPP_COMMA)
27925 : 5 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
27926 : 143 : clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
27927 : : "#pragma omp declare target");
27928 : 130 : else if (parser->in_omp_decl_attribute
27929 : 254 : || c_parser_next_token_is (parser, CPP_OPEN_PAREN))
27930 : : {
27931 : 20 : clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
27932 : : clauses);
27933 : 20 : clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
27934 : 20 : c_parser_skip_to_pragma_eol (parser);
27935 : : }
27936 : : else
27937 : : {
27938 : 110 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27939 : 110 : c_parser_skip_to_pragma_eol (parser);
27940 : 110 : c_omp_declare_target_attr attr = { attr_syntax, -1, 0 };
27941 : 110 : vec_safe_push (current_omp_declare_target_attribute, attr);
27942 : 110 : return;
27943 : : }
27944 : 412 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27945 : : {
27946 : 249 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
27947 : 27 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
27948 : 249 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27949 : 16 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
27950 : : }
27951 : 412 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27952 : : {
27953 : 249 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
27954 : 249 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27955 : 249 : continue;
27956 : 206 : tree t = OMP_CLAUSE_DECL (c), id;
27957 : 206 : tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
27958 : 206 : tree at2 = lookup_attribute ("omp declare target link",
27959 : 206 : DECL_ATTRIBUTES (t));
27960 : 206 : only_device_type_or_indirect = false;
27961 : 206 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
27962 : : {
27963 : 34 : id = get_identifier ("omp declare target link");
27964 : 34 : std::swap (at1, at2);
27965 : : }
27966 : : else
27967 : 172 : id = get_identifier ("omp declare target");
27968 : 206 : if (at2)
27969 : : {
27970 : 6 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
27971 : 3 : error_at (OMP_CLAUSE_LOCATION (c),
27972 : : "%qD specified both in declare target %<link%> and %qs"
27973 : 3 : " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
27974 : : else
27975 : 3 : error_at (OMP_CLAUSE_LOCATION (c),
27976 : : "%qD specified both in declare target %<link%> and "
27977 : : "%<to%> or %<enter%> clauses", t);
27978 : 6 : continue;
27979 : : }
27980 : 200 : if (!at1)
27981 : : {
27982 : 171 : DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27983 : 171 : if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
27984 : 1 : continue;
27985 : :
27986 : 170 : symtab_node *node = symtab_node::get (t);
27987 : 170 : if (node != NULL)
27988 : : {
27989 : 123 : node->offloadable = 1;
27990 : 123 : if (ENABLE_OFFLOADING)
27991 : : {
27992 : : g->have_offload = true;
27993 : : if (is_a <varpool_node *> (node))
27994 : : vec_safe_push (offload_vars, t);
27995 : : }
27996 : : }
27997 : : }
27998 : 199 : if (TREE_CODE (t) != FUNCTION_DECL)
27999 : 121 : continue;
28000 : 78 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
28001 : : {
28002 : 13 : tree at3 = lookup_attribute ("omp declare target host",
28003 : 13 : DECL_ATTRIBUTES (t));
28004 : 13 : if (at3 == NULL_TREE)
28005 : : {
28006 : 11 : id = get_identifier ("omp declare target host");
28007 : 11 : DECL_ATTRIBUTES (t)
28008 : 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28009 : : }
28010 : : }
28011 : 78 : if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
28012 : : {
28013 : 13 : tree at3 = lookup_attribute ("omp declare target nohost",
28014 : 13 : DECL_ATTRIBUTES (t));
28015 : 13 : if (at3 == NULL_TREE)
28016 : : {
28017 : 11 : id = get_identifier ("omp declare target nohost");
28018 : 11 : DECL_ATTRIBUTES (t)
28019 : 22 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28020 : : }
28021 : : }
28022 : 78 : if (indirect)
28023 : : {
28024 : 9 : tree at4 = lookup_attribute ("omp declare target indirect",
28025 : 9 : DECL_ATTRIBUTES (t));
28026 : 9 : if (at4 == NULL_TREE)
28027 : : {
28028 : 9 : id = get_identifier ("omp declare target indirect");
28029 : 9 : DECL_ATTRIBUTES (t)
28030 : 18 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
28031 : : }
28032 : : }
28033 : : }
28034 : 163 : if ((device_type || indirect) && only_device_type_or_indirect)
28035 : 3 : error_at (OMP_CLAUSE_LOCATION (clauses),
28036 : : "directive with only %<device_type%> or %<indirect%> clauses");
28037 : 163 : if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
28038 : 1 : error_at (OMP_CLAUSE_LOCATION (clauses),
28039 : : "%<device_type%> clause must specify 'any' when used with "
28040 : : "an %<indirect%> clause");
28041 : : }
28042 : :
28043 : : /* OpenMP 5.1
28044 : : #pragma omp begin assumes clauses[optseq] new-line
28045 : :
28046 : : #pragma omp begin declare target clauses[optseq] new-line */
28047 : :
28048 : : #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
28049 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
28050 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
28051 : :
28052 : : static void
28053 : 91 : c_parser_omp_begin (c_parser *parser)
28054 : : {
28055 : 91 : const char *p = "";
28056 : 91 : c_parser_consume_pragma (parser);
28057 : 91 : if (c_parser_next_token_is (parser, CPP_NAME))
28058 : 91 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28059 : 91 : if (strcmp (p, "declare") == 0)
28060 : : {
28061 : 46 : c_parser_consume_token (parser);
28062 : 46 : p = "";
28063 : 46 : if (c_parser_next_token_is (parser, CPP_NAME))
28064 : 46 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28065 : 46 : if (strcmp (p, "target") == 0)
28066 : : {
28067 : 46 : c_parser_consume_token (parser);
28068 : 46 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28069 : 46 : tree clauses
28070 : 46 : = c_parser_omp_all_clauses (parser,
28071 : 46 : OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
28072 : : "#pragma omp begin declare target");
28073 : 46 : int device_type = 0;
28074 : 46 : int indirect = 0;
28075 : 70 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
28076 : : {
28077 : 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
28078 : 15 : device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
28079 : 24 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
28080 : 9 : indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
28081 : : }
28082 : 46 : c_omp_declare_target_attr attr = { attr_syntax, device_type,
28083 : 46 : indirect };
28084 : 46 : vec_safe_push (current_omp_declare_target_attribute, attr);
28085 : : }
28086 : : else
28087 : : {
28088 : 0 : c_parser_error (parser, "expected %<target%>");
28089 : 0 : c_parser_skip_to_pragma_eol (parser);
28090 : : }
28091 : : }
28092 : 45 : else if (strcmp (p, "assumes") == 0)
28093 : : {
28094 : 45 : c_parser_consume_token (parser);
28095 : 45 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28096 : 45 : c_parser_omp_assumption_clauses (parser, false);
28097 : 45 : struct c_omp_begin_assumes_data a = { attr_syntax };
28098 : 45 : vec_safe_push (current_omp_begin_assumes, a);
28099 : : }
28100 : : else
28101 : : {
28102 : 0 : c_parser_error (parser, "expected %<declare target%> or %<assumes%>");
28103 : 0 : c_parser_skip_to_pragma_eol (parser);
28104 : : }
28105 : 91 : }
28106 : :
28107 : : /* OpenMP 4.0
28108 : : #pragma omp end declare target
28109 : :
28110 : : OpenMP 5.1
28111 : : #pragma omp end assumes */
28112 : :
28113 : : static void
28114 : 199 : c_parser_omp_end (c_parser *parser)
28115 : : {
28116 : 199 : location_t loc = c_parser_peek_token (parser)->location;
28117 : 199 : const char *p = "";
28118 : 199 : c_parser_consume_pragma (parser);
28119 : 199 : if (c_parser_next_token_is (parser, CPP_NAME))
28120 : 199 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28121 : 199 : if (strcmp (p, "declare") == 0)
28122 : : {
28123 : 154 : c_parser_consume_token (parser);
28124 : 154 : if (c_parser_next_token_is (parser, CPP_NAME)
28125 : 154 : && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
28126 : : "target") == 0)
28127 : 154 : c_parser_consume_token (parser);
28128 : : else
28129 : : {
28130 : 0 : c_parser_error (parser, "expected %<target%>");
28131 : 0 : c_parser_skip_to_pragma_eol (parser);
28132 : 0 : return;
28133 : : }
28134 : 154 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28135 : 154 : c_parser_skip_to_pragma_eol (parser);
28136 : 154 : if (!vec_safe_length (current_omp_declare_target_attribute))
28137 : 2 : error_at (loc, "%<#pragma omp end declare target%> without "
28138 : : "corresponding %<#pragma omp declare target%> or "
28139 : : "%<#pragma omp begin declare target%>");
28140 : : else
28141 : : {
28142 : 152 : c_omp_declare_target_attr
28143 : 152 : a = current_omp_declare_target_attribute->pop ();
28144 : 152 : if (a.attr_syntax != attr_syntax)
28145 : : {
28146 : 16 : if (a.attr_syntax)
28147 : 12 : error_at (loc,
28148 : : "%qs in attribute syntax terminated "
28149 : : "with %qs in pragma syntax",
28150 : : a.device_type >= 0 ? "begin declare target"
28151 : : : "declare target",
28152 : : "end declare target");
28153 : : else
28154 : 12 : error_at (loc,
28155 : : "%qs in pragma syntax terminated "
28156 : : "with %qs in attribute syntax",
28157 : : a.device_type >= 0 ? "begin declare target"
28158 : : : "declare target",
28159 : : "end declare target");
28160 : : }
28161 : : }
28162 : : }
28163 : 45 : else if (strcmp (p, "assumes") == 0)
28164 : : {
28165 : 45 : c_parser_consume_token (parser);
28166 : 45 : bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
28167 : 45 : c_parser_skip_to_pragma_eol (parser);
28168 : 45 : if (!vec_safe_length (current_omp_begin_assumes))
28169 : 1 : error_at (loc, "%qs without corresponding %qs",
28170 : : "#pragma omp end assumes", "#pragma omp begin assumes");
28171 : : else
28172 : : {
28173 : 44 : c_omp_begin_assumes_data
28174 : 44 : a = current_omp_begin_assumes->pop ();
28175 : 44 : if (a.attr_syntax != attr_syntax)
28176 : : {
28177 : 8 : if (a.attr_syntax)
28178 : 4 : error_at (loc,
28179 : : "%qs in attribute syntax terminated "
28180 : : "with %qs in pragma syntax",
28181 : : "begin assumes", "end assumes");
28182 : : else
28183 : 4 : error_at (loc,
28184 : : "%qs in pragma syntax terminated "
28185 : : "with %qs in attribute syntax",
28186 : : "begin assumes", "end assumes");
28187 : : }
28188 : : }
28189 : : }
28190 : : else
28191 : : {
28192 : 0 : c_parser_error (parser, "expected %<declare%> or %<assumes%>");
28193 : 0 : c_parser_skip_to_pragma_eol (parser);
28194 : : }
28195 : : }
28196 : :
28197 : : /* OpenMP 5.0
28198 : : #pragma omp declare mapper ([mapper-identifier :] type var) \
28199 : : [clause [ [,] clause ] ... ] new-line */
28200 : :
28201 : : static void
28202 : 65 : c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
28203 : : {
28204 : 65 : tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
28205 : 65 : tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
28206 : 65 : c_token *token;
28207 : :
28208 : 65 : if (context == pragma_struct || context == pragma_param)
28209 : : {
28210 : 2 : error ("%<#pragma omp declare mapper%> not at file or block scope");
28211 : 2 : goto fail;
28212 : : }
28213 : :
28214 : 63 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28215 : 0 : goto fail;
28216 : :
28217 : 63 : token = c_parser_peek_token (parser);
28218 : :
28219 : 63 : if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
28220 : : {
28221 : 22 : switch (token->type)
28222 : : {
28223 : 15 : case CPP_NAME:
28224 : 15 : mapper_name = token->value;
28225 : 15 : c_parser_consume_token (parser);
28226 : 15 : break;
28227 : 7 : case CPP_KEYWORD:
28228 : 7 : if (token->keyword == RID_DEFAULT)
28229 : : {
28230 : 6 : mapper_name = NULL_TREE;
28231 : 6 : c_parser_consume_token (parser);
28232 : 6 : break;
28233 : : }
28234 : : /* Fallthrough. */
28235 : 1 : default:
28236 : 1 : error_at (token->location, "expected identifier or %<default%>");
28237 : 1 : c_parser_skip_to_pragma_eol (parser, false);
28238 : 1 : return;
28239 : : }
28240 : :
28241 : 21 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
28242 : 0 : goto fail;
28243 : : }
28244 : :
28245 : 62 : mapper_id = c_omp_mapper_id (mapper_name);
28246 : 62 : mapper_decl = c_omp_mapper_decl (mapper_id);
28247 : :
28248 : 62 : {
28249 : 62 : location_t loc = c_parser_peek_token (parser)->location;
28250 : 62 : struct c_type_name *ctype = c_parser_type_name (parser);
28251 : 62 : type = groktypename (ctype, NULL, NULL);
28252 : 62 : if (type == error_mark_node)
28253 : 3 : goto fail;
28254 : 59 : if (!RECORD_OR_UNION_TYPE_P (type))
28255 : : {
28256 : 4 : error_at (loc, "%qT is not a struct or union type in "
28257 : : "%<#pragma omp declare mapper%>", type);
28258 : 4 : c_parser_skip_to_pragma_eol (parser, false);
28259 : 4 : return;
28260 : : }
28261 : 65 : for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
28262 : 17 : if (comptypes (TREE_PURPOSE (t), type))
28263 : : {
28264 : 7 : error_at (loc, "redeclaration of %qs %<#pragma omp declare "
28265 : 7 : "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
28266 : : + sizeof ("omp declare mapper ") - 1,
28267 : : type);
28268 : 7 : tree prevmapper = TREE_VALUE (t);
28269 : : /* Hmm, this location might not be very accurate. */
28270 : 7 : location_t ploc
28271 : 7 : = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
28272 : 7 : inform (ploc, "%<#pragma omp declare mapper%> "
28273 : : "previously declared here");
28274 : 7 : c_parser_skip_to_pragma_eol (parser, false);
28275 : 7 : return;
28276 : : }
28277 : : }
28278 : :
28279 : 48 : token = c_parser_peek_token (parser);
28280 : 48 : if (token->type == CPP_NAME)
28281 : : {
28282 : 46 : var = build_decl (token->location, VAR_DECL, token->value, type);
28283 : 46 : c_parser_consume_token (parser);
28284 : 46 : DECL_ARTIFICIAL (var) = 1;
28285 : : }
28286 : : else
28287 : : {
28288 : 2 : error_at (token->location, "expected identifier");
28289 : 2 : goto fail;
28290 : : }
28291 : :
28292 : 46 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28293 : 0 : goto fail;
28294 : :
28295 : 46 : push_scope ();
28296 : 46 : stmtlist = push_stmt_list ();
28297 : 46 : pushdecl (var);
28298 : 46 : DECL_CONTEXT (var) = current_function_decl;
28299 : :
28300 : 115 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28301 : : {
28302 : 70 : location_t here;
28303 : 70 : pragma_omp_clause c_kind;
28304 : 70 : here = c_parser_peek_token (parser)->location;
28305 : 70 : c_kind = c_parser_omp_clause_name (parser);
28306 : 70 : if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
28307 : : {
28308 : 1 : error_at (here, "unexpected clause");
28309 : 1 : goto fail;
28310 : : }
28311 : 69 : maplist = c_parser_omp_clause_map (parser, maplist, true);
28312 : : }
28313 : :
28314 : 45 : if (maplist == NULL_TREE)
28315 : : {
28316 : 1 : error_at (input_location, "missing %<map%> clause");
28317 : 1 : goto fail;
28318 : : }
28319 : :
28320 : 44 : stmt = make_node (OMP_DECLARE_MAPPER);
28321 : 44 : TREE_TYPE (stmt) = type;
28322 : 44 : OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
28323 : 44 : OMP_DECLARE_MAPPER_DECL (stmt) = var;
28324 : 44 : OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
28325 : :
28326 : 44 : add_stmt (stmt);
28327 : :
28328 : 44 : pop_stmt_list (stmtlist);
28329 : 44 : pop_scope ();
28330 : :
28331 : 44 : c_parser_skip_to_pragma_eol (parser);
28332 : :
28333 : 44 : t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
28334 : 44 : DECL_INITIAL (mapper_decl) = t;
28335 : :
28336 : 44 : return;
28337 : :
28338 : 9 : fail:
28339 : 9 : c_parser_skip_to_pragma_eol (parser);
28340 : : }
28341 : :
28342 : : /* OpenMP 4.0
28343 : : #pragma omp declare reduction (reduction-id : typename-list : expression) \
28344 : : initializer-clause[opt] new-line
28345 : :
28346 : : initializer-clause:
28347 : : initializer (omp_priv = initializer)
28348 : : initializer (function-name (argument-list)) */
28349 : :
28350 : : static void
28351 : 164 : c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
28352 : : {
28353 : 164 : unsigned int tokens_avail = 0, i;
28354 : 164 : c_token *saved_tokens = NULL;
28355 : 164 : vec<tree> types = vNULL;
28356 : 164 : vec<c_token> clauses = vNULL;
28357 : 164 : enum tree_code reduc_code = ERROR_MARK;
28358 : 164 : tree reduc_id = NULL_TREE;
28359 : 164 : tree type;
28360 : 164 : location_t rloc = c_parser_peek_token (parser)->location;
28361 : :
28362 : 164 : if (context == pragma_struct || context == pragma_param)
28363 : : {
28364 : 2 : error ("%<#pragma omp declare reduction%> not at file or block scope");
28365 : 2 : goto fail;
28366 : : }
28367 : :
28368 : 162 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28369 : 1 : goto fail;
28370 : :
28371 : 161 : switch (c_parser_peek_token (parser)->type)
28372 : : {
28373 : : case CPP_PLUS:
28374 : : reduc_code = PLUS_EXPR;
28375 : : break;
28376 : 14 : case CPP_MULT:
28377 : 14 : reduc_code = MULT_EXPR;
28378 : 14 : break;
28379 : 0 : case CPP_MINUS:
28380 : 0 : reduc_code = MINUS_EXPR;
28381 : 0 : break;
28382 : 4 : case CPP_AND:
28383 : 4 : reduc_code = BIT_AND_EXPR;
28384 : 4 : break;
28385 : 0 : case CPP_XOR:
28386 : 0 : reduc_code = BIT_XOR_EXPR;
28387 : 0 : break;
28388 : 10 : case CPP_OR:
28389 : 10 : reduc_code = BIT_IOR_EXPR;
28390 : 10 : break;
28391 : 0 : case CPP_AND_AND:
28392 : 0 : reduc_code = TRUTH_ANDIF_EXPR;
28393 : 0 : break;
28394 : 0 : case CPP_OR_OR:
28395 : 0 : reduc_code = TRUTH_ORIF_EXPR;
28396 : 0 : break;
28397 : 89 : case CPP_NAME:
28398 : 89 : const char *p;
28399 : 89 : p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28400 : 89 : if (strcmp (p, "min") == 0)
28401 : : {
28402 : : reduc_code = MIN_EXPR;
28403 : : break;
28404 : : }
28405 : 83 : if (strcmp (p, "max") == 0)
28406 : : {
28407 : : reduc_code = MAX_EXPR;
28408 : : break;
28409 : : }
28410 : 83 : reduc_id = c_parser_peek_token (parser)->value;
28411 : 83 : break;
28412 : 0 : default:
28413 : 0 : c_parser_error (parser,
28414 : : "expected %<+%>, %<*%>, %<-%>, %<&%>, "
28415 : : "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
28416 : 0 : goto fail;
28417 : : }
28418 : :
28419 : 161 : tree orig_reduc_id, reduc_decl;
28420 : 161 : orig_reduc_id = reduc_id;
28421 : 161 : reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
28422 : 161 : reduc_decl = c_omp_reduction_decl (reduc_id);
28423 : 161 : c_parser_consume_token (parser);
28424 : :
28425 : 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
28426 : 0 : goto fail;
28427 : :
28428 : 165 : while (true)
28429 : : {
28430 : 163 : location_t loc = c_parser_peek_token (parser)->location;
28431 : 163 : struct c_type_name *ctype = c_parser_type_name (parser);
28432 : 163 : if (ctype != NULL)
28433 : : {
28434 : 163 : type = groktypename (ctype, NULL, NULL);
28435 : 163 : if (type == error_mark_node)
28436 : : ;
28437 : 163 : else if ((INTEGRAL_TYPE_P (type)
28438 : 163 : || SCALAR_FLOAT_TYPE_P (type)
28439 : 98 : || TREE_CODE (type) == COMPLEX_TYPE)
28440 : 69 : && orig_reduc_id == NULL_TREE)
28441 : 8 : error_at (loc, "predeclared arithmetic type in "
28442 : : "%<#pragma omp declare reduction%>");
28443 : 155 : else if (TREE_CODE (type) == FUNCTION_TYPE
28444 : 150 : || TREE_CODE (type) == ARRAY_TYPE)
28445 : 8 : error_at (loc, "function or array type in "
28446 : : "%<#pragma omp declare reduction%>");
28447 : 147 : else if (TYPE_ATOMIC (type))
28448 : 1 : error_at (loc, "%<_Atomic%> qualified type in "
28449 : : "%<#pragma omp declare reduction%>");
28450 : 146 : else if (TYPE_QUALS_NO_ADDR_SPACE (type))
28451 : 8 : error_at (loc, "const, volatile or restrict qualified type in "
28452 : : "%<#pragma omp declare reduction%>");
28453 : : else
28454 : : {
28455 : 138 : tree t;
28456 : 200 : for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
28457 : 66 : if (comptypes (TREE_PURPOSE (t), type))
28458 : : {
28459 : 4 : error_at (loc, "redeclaration of %qs "
28460 : : "%<#pragma omp declare reduction%> for "
28461 : : "type %qT",
28462 : 4 : IDENTIFIER_POINTER (reduc_id)
28463 : : + sizeof ("omp declare reduction ") - 1,
28464 : : type);
28465 : 4 : location_t ploc
28466 : 4 : = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
28467 : : 0));
28468 : 4 : inform (ploc, "%<#pragma omp declare reduction%> "
28469 : : "previously declared here");
28470 : 4 : break;
28471 : : }
28472 : 4 : if (t == NULL_TREE)
28473 : 134 : types.safe_push (type);
28474 : : }
28475 : 163 : if (c_parser_next_token_is (parser, CPP_COMMA))
28476 : 2 : c_parser_consume_token (parser);
28477 : : else
28478 : : break;
28479 : : }
28480 : : else
28481 : : break;
28482 : 2 : }
28483 : :
28484 : 161 : if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
28485 : 161 : || types.is_empty ())
28486 : : {
28487 : 34 : fail:
28488 : 34 : clauses.release ();
28489 : 34 : types.release ();
28490 : 460 : while (true)
28491 : : {
28492 : 247 : c_token *token = c_parser_peek_token (parser);
28493 : 247 : if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
28494 : : break;
28495 : 213 : c_parser_consume_token (parser);
28496 : 213 : }
28497 : 34 : c_parser_skip_to_pragma_eol (parser);
28498 : 34 : return;
28499 : : }
28500 : :
28501 : 132 : if (types.length () > 1)
28502 : : {
28503 : 13 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28504 : : {
28505 : 12 : c_token *token = c_parser_peek_token (parser);
28506 : 12 : if (token->type == CPP_EOF)
28507 : 0 : goto fail;
28508 : 12 : clauses.safe_push (*token);
28509 : 12 : c_parser_consume_token (parser);
28510 : : }
28511 : 1 : clauses.safe_push (*c_parser_peek_token (parser));
28512 : 1 : c_parser_skip_to_pragma_eol (parser);
28513 : :
28514 : : /* Make sure nothing tries to read past the end of the tokens. */
28515 : 1 : c_token eof_token;
28516 : 1 : memset (&eof_token, 0, sizeof (eof_token));
28517 : 1 : eof_token.type = CPP_EOF;
28518 : 1 : clauses.safe_push (eof_token);
28519 : 1 : clauses.safe_push (eof_token);
28520 : : }
28521 : :
28522 : 132 : int errs = errorcount;
28523 : 238 : FOR_EACH_VEC_ELT (types, i, type)
28524 : : {
28525 : 134 : saved_tokens = parser->tokens;
28526 : 134 : tokens_avail = parser->tokens_avail;
28527 : 134 : if (!clauses.is_empty ())
28528 : : {
28529 : 3 : parser->tokens = clauses.address ();
28530 : 3 : parser->tokens_avail = clauses.length ();
28531 : 3 : parser->in_pragma = true;
28532 : : }
28533 : :
28534 : 134 : bool nested = current_function_decl != NULL_TREE;
28535 : 134 : if (nested)
28536 : 27 : c_push_function_context ();
28537 : 134 : tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
28538 : : reduc_id, default_function_type);
28539 : 134 : current_function_decl = fndecl;
28540 : 134 : allocate_struct_function (fndecl, true);
28541 : 134 : push_scope ();
28542 : 134 : tree stmt = push_stmt_list ();
28543 : : /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
28544 : : warn about these. */
28545 : 134 : tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
28546 : : get_identifier ("omp_out"), type);
28547 : 134 : DECL_ARTIFICIAL (omp_out) = 1;
28548 : 134 : DECL_CONTEXT (omp_out) = fndecl;
28549 : 134 : pushdecl (omp_out);
28550 : 134 : tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
28551 : : get_identifier ("omp_in"), type);
28552 : 134 : DECL_ARTIFICIAL (omp_in) = 1;
28553 : 134 : DECL_CONTEXT (omp_in) = fndecl;
28554 : 134 : pushdecl (omp_in);
28555 : 134 : struct c_expr combiner = c_parser_expression (parser);
28556 : 134 : struct c_expr initializer;
28557 : 134 : tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
28558 : 134 : bool bad = false;
28559 : 134 : initializer.set_error ();
28560 : 134 : if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28561 : : bad = true;
28562 : 134 : else if (c_parser_next_token_is (parser, CPP_COMMA)
28563 : 134 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28564 : 2 : c_parser_consume_token (parser);
28565 : 2 : if (!bad
28566 : 134 : && (c_parser_next_token_is (parser, CPP_NAME)
28567 : 77 : && strcmp (IDENTIFIER_POINTER
28568 : : (c_parser_peek_token (parser)->value),
28569 : : "initializer") == 0))
28570 : : {
28571 : 77 : c_parser_consume_token (parser);
28572 : 77 : pop_scope ();
28573 : 77 : push_scope ();
28574 : 77 : omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
28575 : : get_identifier ("omp_priv"), type);
28576 : 77 : DECL_ARTIFICIAL (omp_priv) = 1;
28577 : 77 : DECL_INITIAL (omp_priv) = error_mark_node;
28578 : 77 : DECL_CONTEXT (omp_priv) = fndecl;
28579 : 77 : pushdecl (omp_priv);
28580 : 77 : omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
28581 : : get_identifier ("omp_orig"), type);
28582 : 77 : DECL_ARTIFICIAL (omp_orig) = 1;
28583 : 77 : DECL_CONTEXT (omp_orig) = fndecl;
28584 : 77 : pushdecl (omp_orig);
28585 : 77 : if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
28586 : : bad = true;
28587 : 77 : else if (!c_parser_next_token_is (parser, CPP_NAME))
28588 : : {
28589 : 0 : c_parser_error (parser, "expected %<omp_priv%> or "
28590 : : "function-name");
28591 : 0 : bad = true;
28592 : : }
28593 : 77 : else if (strcmp (IDENTIFIER_POINTER
28594 : : (c_parser_peek_token (parser)->value),
28595 : : "omp_priv") != 0)
28596 : : {
28597 : 20 : if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
28598 : 20 : || c_parser_peek_token (parser)->id_kind != C_ID_ID)
28599 : : {
28600 : 0 : c_parser_error (parser, "expected function-name %<(%>");
28601 : 0 : bad = true;
28602 : : }
28603 : : else
28604 : 20 : initializer = c_parser_postfix_expression (parser);
28605 : 20 : if (initializer.value
28606 : 20 : && TREE_CODE (initializer.value) == CALL_EXPR)
28607 : : {
28608 : : int j;
28609 : : tree c = initializer.value;
28610 : 21 : for (j = 0; j < call_expr_nargs (c); j++)
28611 : : {
28612 : 20 : tree a = CALL_EXPR_ARG (c, j);
28613 : 20 : STRIP_NOPS (a);
28614 : 20 : if (TREE_CODE (a) == ADDR_EXPR
28615 : 20 : && TREE_OPERAND (a, 0) == omp_priv)
28616 : : break;
28617 : : }
28618 : 20 : if (j == call_expr_nargs (c))
28619 : 1 : error ("one of the initializer call arguments should be "
28620 : : "%<&omp_priv%>");
28621 : : }
28622 : : }
28623 : : else
28624 : : {
28625 : 57 : c_parser_consume_token (parser);
28626 : 57 : if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
28627 : : bad = true;
28628 : : else
28629 : : {
28630 : 55 : tree st = push_stmt_list ();
28631 : 55 : location_t loc = c_parser_peek_token (parser)->location;
28632 : 55 : rich_location richloc (line_table, loc);
28633 : 55 : start_init (omp_priv, NULL_TREE, false, false, &richloc);
28634 : 55 : struct c_expr init = c_parser_initializer (parser, omp_priv);
28635 : 55 : finish_init ();
28636 : 55 : finish_decl (omp_priv, loc, init.value,
28637 : : init.original_type, NULL_TREE);
28638 : 55 : pop_stmt_list (st);
28639 : 55 : }
28640 : : }
28641 : 0 : if (!bad
28642 : 75 : && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
28643 : : bad = true;
28644 : : }
28645 : :
28646 : 134 : if (!bad)
28647 : : {
28648 : 132 : c_parser_skip_to_pragma_eol (parser);
28649 : :
28650 : 189 : tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
28651 : 132 : DECL_INITIAL (reduc_decl));
28652 : 132 : DECL_INITIAL (reduc_decl) = t;
28653 : 132 : DECL_SOURCE_LOCATION (omp_out) = rloc;
28654 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
28655 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
28656 : 132 : TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
28657 : 132 : walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
28658 : : &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
28659 : 132 : if (omp_priv)
28660 : : {
28661 : 75 : DECL_SOURCE_LOCATION (omp_priv) = rloc;
28662 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
28663 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
28664 : 75 : TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
28665 : 75 : walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
28666 : : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28667 : 75 : walk_tree (&DECL_INITIAL (omp_priv),
28668 : : c_check_omp_declare_reduction_r,
28669 : : &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28670 : : }
28671 : : }
28672 : :
28673 : 134 : pop_stmt_list (stmt);
28674 : 134 : pop_scope ();
28675 : 134 : if (cfun->language != NULL)
28676 : : {
28677 : 0 : ggc_free (cfun->language);
28678 : 0 : cfun->language = NULL;
28679 : : }
28680 : 134 : set_cfun (NULL);
28681 : 134 : current_function_decl = NULL_TREE;
28682 : 134 : if (nested)
28683 : 27 : c_pop_function_context ();
28684 : :
28685 : 134 : if (!clauses.is_empty ())
28686 : : {
28687 : 3 : parser->tokens = saved_tokens;
28688 : 3 : parser->tokens_avail = tokens_avail;
28689 : : }
28690 : 134 : if (bad)
28691 : 2 : goto fail;
28692 : 132 : if (errs != errorcount)
28693 : : break;
28694 : : }
28695 : :
28696 : 130 : clauses.release ();
28697 : 130 : types.release ();
28698 : : }
28699 : :
28700 : : /* OpenMP 4.0
28701 : : #pragma omp declare simd declare-simd-clauses[optseq] new-line
28702 : : #pragma omp declare reduction (reduction-id : typename-list : expression) \
28703 : : initializer-clause[opt] new-line
28704 : : #pragma omp declare target new-line
28705 : :
28706 : : OpenMP 5.0
28707 : : #pragma omp declare variant (identifier) match (context-selector)
28708 : :
28709 : : OpenMP 5.1
28710 : : #pragma omp declare variant (identifier) match (context-selector) \
28711 : : adjust_args(adjust-op:argument-list) */
28712 : :
28713 : : static bool
28714 : 1205 : c_parser_omp_declare (c_parser *parser, enum pragma_context context)
28715 : : {
28716 : 1205 : c_parser_consume_pragma (parser);
28717 : 1205 : if (c_parser_next_token_is (parser, CPP_NAME))
28718 : : {
28719 : 1205 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28720 : 1205 : if (strcmp (p, "simd") == 0)
28721 : : {
28722 : : /* c_parser_consume_token (parser); done in
28723 : : c_parser_omp_declare_simd. */
28724 : 268 : c_parser_omp_declare_simd (parser, context);
28725 : 268 : return true;
28726 : : }
28727 : 937 : if (strcmp (p, "reduction") == 0)
28728 : : {
28729 : 164 : c_parser_consume_token (parser);
28730 : 164 : c_parser_omp_declare_reduction (parser, context);
28731 : 164 : return false;
28732 : : }
28733 : 773 : if (strcmp (p, "mapper") == 0)
28734 : : {
28735 : 65 : c_parser_consume_token (parser);
28736 : 65 : c_parser_omp_declare_mapper (parser, context);
28737 : 65 : return false;
28738 : : }
28739 : 708 : if (!flag_openmp) /* flag_openmp_simd */
28740 : : {
28741 : 0 : c_parser_skip_to_pragma_eol (parser, false);
28742 : 0 : return false;
28743 : : }
28744 : 708 : if (strcmp (p, "target") == 0)
28745 : : {
28746 : 273 : c_parser_consume_token (parser);
28747 : 273 : c_parser_omp_declare_target (parser);
28748 : 273 : return false;
28749 : : }
28750 : 435 : if (strcmp (p, "variant") == 0)
28751 : : {
28752 : : /* c_parser_consume_token (parser); done in
28753 : : c_parser_omp_declare_simd. */
28754 : 435 : c_parser_omp_declare_simd (parser, context);
28755 : 435 : return true;
28756 : : }
28757 : : }
28758 : :
28759 : 0 : c_parser_error (parser, "expected %<simd%>, %<reduction%>, "
28760 : : "%<target%> or %<variant%>");
28761 : 0 : c_parser_skip_to_pragma_eol (parser);
28762 : 0 : return false;
28763 : : }
28764 : :
28765 : : /* OpenMP 5.0
28766 : : #pragma omp requires clauses[optseq] new-line */
28767 : :
28768 : : static void
28769 : 62 : c_parser_omp_requires (c_parser *parser)
28770 : : {
28771 : 62 : enum omp_requires new_req = (enum omp_requires) 0;
28772 : :
28773 : 62 : c_parser_consume_pragma (parser);
28774 : :
28775 : 62 : location_t loc = c_parser_peek_token (parser)->location;
28776 : 138 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
28777 : : {
28778 : 80 : if (c_parser_next_token_is (parser, CPP_COMMA)
28779 : 80 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28780 : 14 : c_parser_consume_token (parser);
28781 : :
28782 : 80 : if (c_parser_next_token_is (parser, CPP_NAME))
28783 : : {
28784 : 79 : const char *p
28785 : 79 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28786 : 79 : location_t cloc = c_parser_peek_token (parser)->location;
28787 : 79 : enum omp_requires this_req = (enum omp_requires) 0;
28788 : :
28789 : 79 : if (!strcmp (p, "unified_address"))
28790 : : this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
28791 : 65 : else if (!strcmp (p, "unified_shared_memory"))
28792 : : this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
28793 : 51 : else if (!strcmp (p, "self_maps"))
28794 : : this_req = OMP_REQUIRES_SELF_MAPS;
28795 : 49 : else if (!strcmp (p, "dynamic_allocators"))
28796 : : this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
28797 : 38 : else if (!strcmp (p, "reverse_offload"))
28798 : : this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
28799 : 21 : else if (!strcmp (p, "atomic_default_mem_order"))
28800 : : {
28801 : 20 : c_parser_consume_token (parser);
28802 : :
28803 : 20 : matching_parens parens;
28804 : 20 : if (parens.require_open (parser))
28805 : : {
28806 : 20 : if (c_parser_next_token_is (parser, CPP_NAME))
28807 : : {
28808 : 19 : tree v = c_parser_peek_token (parser)->value;
28809 : 19 : p = IDENTIFIER_POINTER (v);
28810 : :
28811 : 19 : if (!strcmp (p, "seq_cst"))
28812 : : this_req
28813 : : = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
28814 : 10 : else if (!strcmp (p, "relaxed"))
28815 : : this_req
28816 : : = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
28817 : 9 : else if (!strcmp (p, "release"))
28818 : : this_req
28819 : : = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
28820 : 7 : else if (!strcmp (p, "acq_rel"))
28821 : : this_req
28822 : : = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
28823 : 4 : else if (!strcmp (p, "acquire"))
28824 : : this_req
28825 : : = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
28826 : : }
28827 : : if (this_req == 0)
28828 : : {
28829 : 2 : error_at (c_parser_peek_token (parser)->location,
28830 : : "expected %<acq_rel%>, %<acquire%>, "
28831 : : "%<relaxed%>, %<release%> or %<seq_cst%>");
28832 : 2 : switch (c_parser_peek_token (parser)->type)
28833 : : {
28834 : : case CPP_EOF:
28835 : : case CPP_PRAGMA_EOL:
28836 : : case CPP_CLOSE_PAREN:
28837 : : break;
28838 : 1 : default:
28839 : 1 : if (c_parser_peek_2nd_token (parser)->type
28840 : : == CPP_CLOSE_PAREN)
28841 : 1 : c_parser_consume_token (parser);
28842 : : break;
28843 : : }
28844 : : }
28845 : : else
28846 : 18 : c_parser_consume_token (parser);
28847 : :
28848 : 20 : parens.skip_until_found_close (parser);
28849 : 20 : if (this_req == 0)
28850 : : {
28851 : 2 : c_parser_skip_to_pragma_eol (parser, false);
28852 : 2 : return;
28853 : : }
28854 : : }
28855 : 18 : p = NULL;
28856 : : }
28857 : : else
28858 : : {
28859 : 1 : error_at (cloc, "expected %<unified_address%>, "
28860 : : "%<unified_shared_memory%>, "
28861 : : "%<self_maps%>, "
28862 : : "%<dynamic_allocators%>, "
28863 : : "%<reverse_offload%> "
28864 : : "or %<atomic_default_mem_order%> clause");
28865 : 1 : c_parser_skip_to_pragma_eol (parser, false);
28866 : 1 : return;
28867 : : }
28868 : 18 : if (p)
28869 : 58 : c_parser_consume_token (parser);
28870 : 76 : if (this_req)
28871 : : {
28872 : 76 : if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28873 : : {
28874 : 58 : if ((this_req & new_req) != 0)
28875 : 4 : error_at (cloc, "too many %qs clauses", p);
28876 : 58 : if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
28877 : 47 : && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
28878 : 4 : error_at (cloc, "%qs clause used lexically after first "
28879 : : "target construct or offloading API", p);
28880 : : }
28881 : 18 : else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28882 : : {
28883 : 1 : error_at (cloc, "too many %qs clauses",
28884 : : "atomic_default_mem_order");
28885 : 1 : this_req = (enum omp_requires) 0;
28886 : : }
28887 : 17 : else if ((omp_requires_mask
28888 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28889 : : {
28890 : 2 : error_at (cloc, "more than one %<atomic_default_mem_order%>"
28891 : : " clause in a single compilation unit");
28892 : 2 : this_req
28893 : 2 : = (enum omp_requires)
28894 : 2 : (omp_requires_mask
28895 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
28896 : : }
28897 : 15 : else if ((omp_requires_mask
28898 : : & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
28899 : 1 : error_at (cloc, "%<atomic_default_mem_order%> clause used "
28900 : : "lexically after first %<atomic%> construct "
28901 : : "without memory order clause");
28902 : 76 : new_req = (enum omp_requires) (new_req | this_req);
28903 : 76 : omp_requires_mask
28904 : 76 : = (enum omp_requires) (omp_requires_mask | this_req);
28905 : 76 : continue;
28906 : : }
28907 : : }
28908 : : break;
28909 : : }
28910 : 59 : c_parser_skip_to_pragma_eol (parser);
28911 : :
28912 : 59 : if (new_req == 0)
28913 : 1 : error_at (loc, "%<pragma omp requires%> requires at least one clause");
28914 : : }
28915 : :
28916 : : /* Helper function for c_parser_omp_taskloop.
28917 : : Disallow zero sized or potentially zero sized task reductions. */
28918 : :
28919 : : static tree
28920 : 412 : c_finish_taskloop_clauses (tree clauses)
28921 : : {
28922 : 412 : tree *pc = &clauses;
28923 : 2049 : for (tree c = clauses; c; c = *pc)
28924 : : {
28925 : 1637 : bool remove = false;
28926 : 1637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
28927 : : {
28928 : 142 : tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
28929 : 142 : if (integer_zerop (TYPE_SIZE_UNIT (type)))
28930 : : {
28931 : 2 : error_at (OMP_CLAUSE_LOCATION (c),
28932 : : "zero sized type %qT in %<reduction%> clause", type);
28933 : 2 : remove = true;
28934 : : }
28935 : 140 : else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
28936 : : {
28937 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
28938 : : "variable sized type %qT in %<reduction%> clause",
28939 : : type);
28940 : 0 : remove = true;
28941 : : }
28942 : : }
28943 : 2 : if (remove)
28944 : 2 : *pc = OMP_CLAUSE_CHAIN (c);
28945 : : else
28946 : 1635 : pc = &OMP_CLAUSE_CHAIN (c);
28947 : : }
28948 : 412 : return clauses;
28949 : : }
28950 : :
28951 : : /* OpenMP 4.5:
28952 : : #pragma omp taskloop taskloop-clause[optseq] new-line
28953 : : for-loop
28954 : :
28955 : : #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
28956 : : for-loop */
28957 : :
28958 : : #define OMP_TASKLOOP_CLAUSE_MASK \
28959 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
28960 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
28961 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
28962 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
28963 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
28964 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
28965 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
28966 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
28967 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
28968 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
28969 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
28970 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
28971 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
28972 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
28973 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
28974 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
28975 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
28976 : :
28977 : : static tree
28978 : 417 : c_parser_omp_taskloop (location_t loc, c_parser *parser,
28979 : : char *p_name, omp_clause_mask mask, tree *cclauses,
28980 : : bool *if_p)
28981 : : {
28982 : 417 : tree clauses, block, ret;
28983 : :
28984 : 417 : strcat (p_name, " taskloop");
28985 : 417 : mask |= OMP_TASKLOOP_CLAUSE_MASK;
28986 : : /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
28987 : : clause. */
28988 : 417 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
28989 : 94 : mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
28990 : :
28991 : 417 : if (c_parser_next_token_is (parser, CPP_NAME))
28992 : : {
28993 : 341 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28994 : :
28995 : 341 : if (strcmp (p, "simd") == 0)
28996 : : {
28997 : 178 : tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
28998 : 178 : if (cclauses == NULL)
28999 : 84 : cclauses = cclauses_buf;
29000 : 178 : c_parser_consume_token (parser);
29001 : 178 : if (!flag_openmp) /* flag_openmp_simd */
29002 : 3 : return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
29003 : 3 : if_p);
29004 : 175 : block = c_begin_compound_stmt (true);
29005 : 175 : ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
29006 : 175 : block = c_end_compound_stmt (loc, block, true);
29007 : 175 : if (ret == NULL)
29008 : : return ret;
29009 : 175 : ret = make_node (OMP_TASKLOOP);
29010 : 175 : TREE_TYPE (ret) = void_type_node;
29011 : 175 : OMP_FOR_BODY (ret) = block;
29012 : 175 : OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29013 : 175 : OMP_FOR_CLAUSES (ret)
29014 : 175 : = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
29015 : 175 : SET_EXPR_LOCATION (ret, loc);
29016 : 175 : add_stmt (ret);
29017 : 175 : return ret;
29018 : : }
29019 : : }
29020 : 239 : if (!flag_openmp) /* flag_openmp_simd */
29021 : : {
29022 : 2 : c_parser_skip_to_pragma_eol (parser, false);
29023 : 2 : return NULL_TREE;
29024 : : }
29025 : :
29026 : 237 : clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
29027 : 237 : if (cclauses)
29028 : : {
29029 : 65 : omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses);
29030 : 65 : clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
29031 : : }
29032 : :
29033 : 237 : clauses = c_finish_taskloop_clauses (clauses);
29034 : 237 : block = c_begin_compound_stmt (true);
29035 : 237 : ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
29036 : 237 : block = c_end_compound_stmt (loc, block, true);
29037 : 237 : add_stmt (block);
29038 : :
29039 : 237 : return ret;
29040 : : }
29041 : :
29042 : : /* OpenMP 5.1: Parse sizes list for "omp tile sizes"
29043 : : sizes ( size-expr-list ) */
29044 : : static tree
29045 : 476 : c_parser_omp_tile_sizes (c_parser *parser, location_t loc)
29046 : : {
29047 : 476 : tree sizes = NULL_TREE;
29048 : :
29049 : 476 : if (c_parser_next_token_is (parser, CPP_COMMA))
29050 : 2 : c_parser_consume_token (parser);
29051 : :
29052 : 476 : c_token *tok = c_parser_peek_token (parser);
29053 : 476 : if (tok->type != CPP_NAME
29054 : 476 : || strcmp ("sizes", IDENTIFIER_POINTER (tok->value)))
29055 : : {
29056 : 1 : c_parser_error (parser, "expected %<sizes%>");
29057 : 1 : return error_mark_node;
29058 : : }
29059 : 475 : c_parser_consume_token (parser);
29060 : :
29061 : 475 : matching_parens parens;
29062 : 475 : if (!parens.require_open (parser))
29063 : 4 : return error_mark_node;
29064 : :
29065 : 471 : vec<tree, va_gc> *sizes_vec
29066 : 471 : = c_parser_expr_list (parser, true, true, NULL, NULL, NULL, NULL);
29067 : 471 : sizes = build_tree_list_vec (sizes_vec);
29068 : 471 : release_tree_vector (sizes_vec);
29069 : :
29070 : 1198 : for (tree s = sizes; s; s = TREE_CHAIN (s))
29071 : : {
29072 : 734 : tree expr = TREE_VALUE (s);
29073 : 734 : if (expr == error_mark_node)
29074 : : {
29075 : 7 : parens.skip_until_found_close (parser);
29076 : 7 : return error_mark_node;
29077 : : }
29078 : :
29079 : 727 : HOST_WIDE_INT n;
29080 : 1454 : if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
29081 : 724 : || !tree_fits_shwi_p (expr)
29082 : 722 : || (n = tree_to_shwi (expr)) <= 0
29083 : 1440 : || (int) n != n)
29084 : : {
29085 : 14 : c_parser_error (parser, "%<sizes%> argument needs positive"
29086 : : " integral constant");
29087 : 14 : TREE_VALUE (s) = integer_one_node;
29088 : : }
29089 : : }
29090 : 464 : parens.require_close (parser);
29091 : :
29092 : 464 : gcc_assert (sizes);
29093 : 464 : tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES);
29094 : 464 : OMP_CLAUSE_SIZES_LIST (c) = sizes;
29095 : :
29096 : 464 : return c;
29097 : : }
29098 : :
29099 : : /* OpenMP 5.1:
29100 : : #pragma omp tile sizes ( size-expr-list ) new-line
29101 : : for-loop
29102 : :
29103 : : LOC is the location of the #pragma token. */
29104 : :
29105 : : static tree
29106 : 476 : c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p)
29107 : : {
29108 : 476 : tree clauses = c_parser_omp_tile_sizes (parser, loc);
29109 : 476 : c_parser_skip_to_pragma_eol (parser);
29110 : :
29111 : 476 : if (!clauses || clauses == error_mark_node)
29112 : 12 : return error_mark_node;
29113 : :
29114 : 464 : tree block = c_begin_compound_stmt (true);
29115 : 464 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_TILE, clauses,
29116 : : NULL, if_p);
29117 : 464 : block = c_end_compound_stmt (loc, block, true);
29118 : 464 : add_stmt (block);
29119 : :
29120 : 464 : return ret;
29121 : : }
29122 : :
29123 : : #define OMP_UNROLL_CLAUSE_MASK \
29124 : : ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \
29125 : : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL))
29126 : :
29127 : : /* OpenMP 5.1
29128 : : #pragma omp unroll unroll-clause[optseq] new-line
29129 : : for-loop
29130 : :
29131 : : LOC is the location of the #pragma token. */
29132 : :
29133 : : static tree
29134 : 313 : c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p)
29135 : : {
29136 : 313 : tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK,
29137 : : "#pragma omp unroll", true);
29138 : :
29139 : 313 : tree block = c_begin_compound_stmt (true);
29140 : 313 : tree ret = c_parser_omp_for_loop (loc, parser, OMP_UNROLL, clauses,
29141 : : NULL, if_p);
29142 : 313 : block = c_end_compound_stmt (loc, block, true);
29143 : 313 : add_stmt (block);
29144 : :
29145 : 313 : return ret;
29146 : : }
29147 : :
29148 : : /* OpenMP 5.1
29149 : : #pragma omp nothing new-line */
29150 : :
29151 : : static void
29152 : 79 : c_parser_omp_nothing (c_parser *parser)
29153 : : {
29154 : 79 : c_parser_consume_pragma (parser);
29155 : 79 : c_parser_skip_to_pragma_eol (parser);
29156 : 79 : }
29157 : :
29158 : : /* OpenMP 5.1
29159 : : #pragma omp error clauses[optseq] new-line */
29160 : :
29161 : : static bool
29162 : 124 : c_parser_omp_error (c_parser *parser, enum pragma_context context)
29163 : : {
29164 : 124 : int at_compilation = -1;
29165 : 124 : int severity_fatal = -1;
29166 : 124 : tree message = NULL_TREE;
29167 : 124 : bool bad = false;
29168 : 124 : location_t loc = c_parser_peek_token (parser)->location;
29169 : :
29170 : 124 : c_parser_consume_pragma (parser);
29171 : :
29172 : 457 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29173 : : {
29174 : 212 : if (c_parser_next_token_is (parser, CPP_COMMA)
29175 : 212 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29176 : 21 : c_parser_consume_token (parser);
29177 : :
29178 : 212 : if (!c_parser_next_token_is (parser, CPP_NAME))
29179 : : break;
29180 : :
29181 : 211 : const char *p
29182 : 211 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29183 : 211 : location_t cloc = c_parser_peek_token (parser)->location;
29184 : 211 : static const char *args[] = {
29185 : : "execution", "compilation", "warning", "fatal"
29186 : : };
29187 : 211 : int *v = NULL;
29188 : 211 : int idx = 0, n = -1;
29189 : 211 : tree m = NULL_TREE;
29190 : :
29191 : 211 : if (!strcmp (p, "at"))
29192 : : v = &at_compilation;
29193 : 127 : else if (!strcmp (p, "severity"))
29194 : : {
29195 : : v = &severity_fatal;
29196 : : idx += 2;
29197 : : }
29198 : 82 : else if (strcmp (p, "message"))
29199 : : {
29200 : 2 : error_at (cloc,
29201 : : "expected %<at%>, %<severity%> or %<message%> clause");
29202 : 2 : c_parser_skip_to_pragma_eol (parser, false);
29203 : 2 : return false;
29204 : : }
29205 : :
29206 : 209 : c_parser_consume_token (parser);
29207 : :
29208 : 209 : matching_parens parens;
29209 : 209 : if (parens.require_open (parser))
29210 : : {
29211 : 206 : if (v == NULL)
29212 : : {
29213 : 79 : location_t expr_loc = c_parser_peek_token (parser)->location;
29214 : 79 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
29215 : 79 : expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
29216 : 79 : m = convert (const_string_type_node, expr.value);
29217 : 79 : m = c_fully_fold (m, false, NULL);
29218 : : }
29219 : : else
29220 : : {
29221 : 127 : if (c_parser_next_token_is (parser, CPP_NAME))
29222 : : {
29223 : 123 : tree val = c_parser_peek_token (parser)->value;
29224 : 123 : const char *q = IDENTIFIER_POINTER (val);
29225 : :
29226 : 123 : if (!strcmp (q, args[idx]))
29227 : : n = 0;
29228 : 40 : else if (!strcmp (q, args[idx + 1]))
29229 : : n = 1;
29230 : : }
29231 : : if (n == -1)
29232 : : {
29233 : 6 : error_at (c_parser_peek_token (parser)->location,
29234 : 6 : "expected %qs or %qs", args[idx], args[idx + 1]);
29235 : 6 : bad = true;
29236 : 6 : switch (c_parser_peek_token (parser)->type)
29237 : : {
29238 : : case CPP_EOF:
29239 : : case CPP_PRAGMA_EOL:
29240 : : case CPP_CLOSE_PAREN:
29241 : : break;
29242 : 4 : default:
29243 : 4 : if (c_parser_peek_2nd_token (parser)->type
29244 : : == CPP_CLOSE_PAREN)
29245 : 2 : c_parser_consume_token (parser);
29246 : : break;
29247 : : }
29248 : : }
29249 : : else
29250 : 121 : c_parser_consume_token (parser);
29251 : : }
29252 : :
29253 : 206 : parens.skip_until_found_close (parser);
29254 : :
29255 : 206 : if (v == NULL)
29256 : : {
29257 : 79 : if (message)
29258 : : {
29259 : 1 : error_at (cloc, "too many %qs clauses", p);
29260 : 1 : bad = true;
29261 : : }
29262 : : else
29263 : : message = m;
29264 : : }
29265 : 127 : else if (n != -1)
29266 : : {
29267 : 121 : if (*v != -1)
29268 : : {
29269 : 2 : error_at (cloc, "too many %qs clauses", p);
29270 : 2 : bad = true;
29271 : : }
29272 : : else
29273 : 119 : *v = n;
29274 : : }
29275 : : }
29276 : : else
29277 : : bad = true;
29278 : : }
29279 : 122 : c_parser_skip_to_pragma_eol (parser);
29280 : 122 : if (bad)
29281 : : return true;
29282 : :
29283 : 110 : if (at_compilation == -1)
29284 : 33 : at_compilation = 1;
29285 : 110 : if (severity_fatal == -1)
29286 : 72 : severity_fatal = 1;
29287 : 110 : if (!at_compilation)
29288 : : {
29289 : 57 : if (context != pragma_compound)
29290 : : {
29291 : 7 : error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
29292 : : "may only be used in compound statements");
29293 : 7 : return true;
29294 : : }
29295 : 50 : tree fndecl
29296 : 58 : = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
29297 : : : BUILT_IN_GOMP_WARNING);
29298 : 50 : if (!message)
29299 : 4 : message = build_zero_cst (const_string_type_node);
29300 : 50 : tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
29301 : : build_all_ones_cst (size_type_node));
29302 : 50 : add_stmt (stmt);
29303 : 50 : return true;
29304 : : }
29305 : 53 : const char *msg = NULL;
29306 : 53 : if (message)
29307 : : {
29308 : 27 : msg = c_getstr (message);
29309 : 27 : if (msg == NULL)
29310 : 6 : msg = _("<message unknown at compile time>");
29311 : : }
29312 : 15 : const enum diagnostics::kind diag_kind = (severity_fatal
29313 : 53 : ? diagnostics::kind::error
29314 : : : diagnostics::kind::warning);
29315 : 53 : if (msg)
29316 : 27 : emit_diagnostic (diag_kind, loc, 0,
29317 : : "%<pragma omp error%> encountered: %s", msg);
29318 : : else
29319 : 26 : emit_diagnostic (diag_kind, loc, 0,
29320 : : "%<pragma omp error%> encountered");
29321 : : return false;
29322 : : }
29323 : :
29324 : : /* Assumption clauses:
29325 : : OpenMP 5.1
29326 : : absent (directive-name-list)
29327 : : contains (directive-name-list)
29328 : : holds (expression)
29329 : : no_openmp
29330 : : no_openmp_routines
29331 : : no_parallelism */
29332 : :
29333 : : static void
29334 : 124 : c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
29335 : : {
29336 : 124 : bool no_openmp = false;
29337 : 124 : bool no_openmp_routines = false;
29338 : 124 : bool no_parallelism = false;
29339 : 124 : bitmap_head absent_head, contains_head;
29340 : :
29341 : 124 : bitmap_obstack_initialize (NULL);
29342 : 124 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
29343 : 124 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
29344 : :
29345 : 124 : if (c_parser_next_token_is (parser, CPP_PRAGMA_EOL))
29346 : 3 : error_at (c_parser_peek_token (parser)->location,
29347 : : "expected at least one assumption clause");
29348 : :
29349 : 343 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29350 : : {
29351 : 222 : if (c_parser_next_token_is (parser, CPP_COMMA)
29352 : 222 : && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29353 : 53 : c_parser_consume_token (parser);
29354 : :
29355 : 222 : if (!c_parser_next_token_is (parser, CPP_NAME))
29356 : : break;
29357 : :
29358 : 222 : const char *p
29359 : 222 : = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29360 : 222 : location_t cloc = c_parser_peek_token (parser)->location;
29361 : :
29362 : 222 : if (!strcmp (p, "no_openmp"))
29363 : : {
29364 : 16 : c_parser_consume_token (parser);
29365 : 16 : if (no_openmp)
29366 : 3 : error_at (cloc, "too many %qs clauses", "no_openmp");
29367 : : no_openmp = true;
29368 : : }
29369 : 206 : else if (!strcmp (p, "no_openmp_routines"))
29370 : : {
29371 : 16 : c_parser_consume_token (parser);
29372 : 16 : if (no_openmp_routines)
29373 : 3 : error_at (cloc, "too many %qs clauses", "no_openmp_routines");
29374 : : no_openmp_routines = true;
29375 : : }
29376 : 190 : else if (!strcmp (p, "no_parallelism"))
29377 : : {
29378 : 18 : c_parser_consume_token (parser);
29379 : 18 : if (no_parallelism)
29380 : 3 : error_at (cloc, "too many %qs clauses", "no_parallelism");
29381 : : no_parallelism = true;
29382 : : }
29383 : 172 : else if (!strcmp (p, "holds"))
29384 : : {
29385 : 18 : c_parser_consume_token (parser);
29386 : 18 : matching_parens parens;
29387 : 18 : if (parens.require_open (parser))
29388 : : {
29389 : 18 : location_t eloc = c_parser_peek_token (parser)->location;
29390 : 18 : c_expr expr = c_parser_expr_no_commas (parser, NULL);
29391 : 18 : tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
29392 : 18 : t = c_objc_common_truthvalue_conversion (eloc, t);
29393 : 18 : t = c_fully_fold (t, false, NULL);
29394 : 18 : if (is_assume && t != error_mark_node)
29395 : : {
29396 : 10 : tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
29397 : : void_type_node, 1,
29398 : : t);
29399 : 10 : add_stmt (fn);
29400 : : }
29401 : 18 : parens.skip_until_found_close (parser);
29402 : : }
29403 : : }
29404 : 154 : else if (!strcmp (p, "absent") || !strcmp (p, "contains"))
29405 : : {
29406 : 145 : c_parser_consume_token (parser);
29407 : 145 : matching_parens parens;
29408 : 145 : if (parens.require_open (parser))
29409 : : {
29410 : 603 : do
29411 : : {
29412 : 374 : const char *directive[3] = {};
29413 : 374 : int i;
29414 : 374 : location_t dloc = c_parser_peek_token (parser)->location;
29415 : 841 : for (i = 0; i < 3; i++)
29416 : : {
29417 : 808 : tree id;
29418 : 808 : if (c_parser_peek_nth_token (parser, i + 1)->type
29419 : : == CPP_NAME)
29420 : 455 : id = c_parser_peek_nth_token (parser, i + 1)->value;
29421 : 353 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
29422 : : != RID_MAX)
29423 : : {
29424 : 12 : enum rid rid
29425 : 12 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
29426 : 12 : id = ridpointers[rid];
29427 : : }
29428 : : else
29429 : : break;
29430 : 467 : directive[i] = IDENTIFIER_POINTER (id);
29431 : : }
29432 : 374 : if (i == 0)
29433 : 0 : error_at (dloc, "expected directive name");
29434 : : else
29435 : : {
29436 : 374 : const struct c_omp_directive *dir
29437 : 374 : = c_omp_categorize_directive (directive[0],
29438 : : directive[1],
29439 : : directive[2]);
29440 : 374 : if (dir
29441 : 371 : && (dir->kind == C_OMP_DIR_DECLARATIVE
29442 : 368 : || dir->kind == C_OMP_DIR_INFORMATIONAL
29443 : 356 : || dir->kind == C_OMP_DIR_META))
29444 : 15 : error_at (dloc, "invalid OpenMP directive name in "
29445 : : "%qs clause argument: declarative, "
29446 : : "informational, and meta directives "
29447 : : "not permitted", p);
29448 : 356 : else if (dir == NULL
29449 : 356 : || dir->id == PRAGMA_OMP_END
29450 : 356 : || (!dir->second && directive[1])
29451 : 347 : || (!dir->third && directive[2]))
29452 : 12 : error_at (dloc, "unknown OpenMP directive name in "
29453 : : "%qs clause argument", p);
29454 : : else
29455 : : {
29456 : 347 : int id = dir - c_omp_directives;
29457 : 392 : if (bitmap_bit_p (p[0] == 'a' ? &contains_head
29458 : : : &absent_head, id))
29459 : 18 : error_at (dloc, "%<%s%s%s%s%s%> directive "
29460 : : "mentioned in both %<absent%> and "
29461 : : "%<contains%> clauses",
29462 : : directive[0],
29463 : : directive[1] ? " " : "",
29464 : : directive[1] ? directive[1] : "",
29465 : : directive[2] ? " " : "",
29466 : : directive[2] ? directive[2] : "");
29467 : 383 : else if (!bitmap_set_bit (p[0] == 'a'
29468 : : ? &absent_head
29469 : : : &contains_head, id))
29470 : 36 : error_at (dloc, "%<%s%s%s%s%s%> directive "
29471 : : "mentioned multiple times in %qs "
29472 : : "clauses",
29473 : : directive[0],
29474 : : directive[1] ? " " : "",
29475 : : directive[1] ? directive[1] : "",
29476 : : directive[2] ? " " : "",
29477 : : directive[2] ? directive[2] : "", p);
29478 : : }
29479 : 841 : for (; i; --i)
29480 : 467 : c_parser_consume_token (parser);
29481 : : }
29482 : 374 : if (c_parser_next_token_is (parser, CPP_COMMA))
29483 : 229 : c_parser_consume_token (parser);
29484 : : else
29485 : : break;
29486 : 229 : }
29487 : : while (1);
29488 : 145 : parens.skip_until_found_close (parser);
29489 : : }
29490 : 145 : }
29491 : 9 : else if (startswith (p, "ext_"))
29492 : : {
29493 : 6 : warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
29494 : 6 : c_parser_consume_token (parser);
29495 : 6 : if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
29496 : : {
29497 : 3 : matching_parens parens;
29498 : 3 : parens.consume_open (parser);
29499 : 3 : c_parser_balanced_token_sequence (parser);
29500 : 3 : parens.require_close (parser);
29501 : : }
29502 : : }
29503 : : else
29504 : : {
29505 : 3 : c_parser_consume_token (parser);
29506 : 3 : error_at (cloc, "expected assumption clause");
29507 : 3 : break;
29508 : : }
29509 : : }
29510 : 124 : c_parser_skip_to_pragma_eol (parser);
29511 : 124 : }
29512 : :
29513 : : /* OpenMP 5.1
29514 : : #pragma omp assume clauses[optseq] new-line */
29515 : :
29516 : : static void
29517 : 42 : c_parser_omp_assume (c_parser *parser, bool *if_p)
29518 : : {
29519 : 42 : c_parser_omp_assumption_clauses (parser, true);
29520 : 42 : add_stmt (c_parser_omp_structured_block (parser, if_p));
29521 : 42 : }
29522 : :
29523 : : /* OpenMP 5.1
29524 : : #pragma omp assumes clauses[optseq] new-line */
29525 : :
29526 : : static void
29527 : 37 : c_parser_omp_assumes (c_parser *parser)
29528 : : {
29529 : 37 : c_parser_consume_pragma (parser);
29530 : 37 : c_parser_omp_assumption_clauses (parser, false);
29531 : 37 : }
29532 : :
29533 : : /* Helper function for c_parser_omp_metadirective. */
29534 : :
29535 : : static void
29536 : 76 : analyze_metadirective_body (c_parser *parser,
29537 : : vec<c_token> &tokens,
29538 : : vec<tree> &labels)
29539 : : {
29540 : 76 : int nesting_depth = 0;
29541 : 76 : int bracket_depth = 0;
29542 : 76 : bool ignore_label = false;
29543 : :
29544 : : /* Read in the body tokens to the tokens for each candidate directive. */
29545 : 3928 : while (1)
29546 : : {
29547 : 2002 : c_token *token = c_parser_peek_token (parser);
29548 : 2002 : bool stop = false;
29549 : :
29550 : 2002 : if (c_parser_next_token_is_keyword (parser, RID_CASE))
29551 : 0 : ignore_label = true;
29552 : :
29553 : 2002 : switch (token->type)
29554 : : {
29555 : : case CPP_EOF:
29556 : : break;
29557 : 635 : case CPP_NAME:
29558 : 635 : if (!ignore_label
29559 : 635 : && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
29560 : 8 : labels.safe_push (token->value);
29561 : 635 : goto add;
29562 : 27 : case CPP_OPEN_BRACE:
29563 : 27 : ++nesting_depth;
29564 : 27 : goto add;
29565 : 27 : case CPP_CLOSE_BRACE:
29566 : 27 : if (--nesting_depth == 0 && bracket_depth == 0)
29567 : 27 : stop = true;
29568 : 27 : goto add;
29569 : 102 : case CPP_OPEN_PAREN:
29570 : 102 : ++bracket_depth;
29571 : 102 : goto add;
29572 : 102 : case CPP_CLOSE_PAREN:
29573 : 102 : --bracket_depth;
29574 : 102 : goto add;
29575 : 17 : case CPP_COLON:
29576 : 17 : ignore_label = false;
29577 : 17 : goto add;
29578 : 238 : case CPP_SEMICOLON:
29579 : 238 : if (nesting_depth == 0 && bracket_depth == 0)
29580 : 63 : stop = true;
29581 : 238 : goto add;
29582 : 2002 : default:
29583 : 2002 : add:
29584 : 2002 : tokens.safe_push (*token);
29585 : 2002 : if (token->type == CPP_PRAGMA)
29586 : 5 : c_parser_consume_pragma (parser);
29587 : 1997 : else if (token->type == CPP_PRAGMA_EOL)
29588 : 5 : c_parser_skip_to_pragma_eol (parser);
29589 : : else
29590 : 1992 : c_parser_consume_token (parser);
29591 : 2002 : if (stop)
29592 : : break;
29593 : 1926 : continue;
29594 : : }
29595 : 76 : break;
29596 : 1926 : }
29597 : 76 : }
29598 : :
29599 : : /* OpenMP 5.0:
29600 : :
29601 : : # pragma omp metadirective [clause[, clause]]
29602 : : */
29603 : :
29604 : : static void
29605 : 108 : c_parser_omp_metadirective (c_parser *parser, bool *if_p)
29606 : : {
29607 : 108 : static unsigned int metadirective_region_count = 0;
29608 : :
29609 : 108 : tree ret;
29610 : 108 : auto_vec<c_token> directive_tokens;
29611 : 108 : auto_vec<c_token> body_tokens;
29612 : 108 : auto_vec<tree> body_labels;
29613 : 108 : auto_vec<const struct c_omp_directive *> directives;
29614 : 108 : auto_vec<tree> ctxs;
29615 : 108 : vec<struct omp_variant> candidates;
29616 : 108 : bool default_seen = false;
29617 : 108 : int directive_token_idx = 0;
29618 : 108 : tree standalone_body = NULL_TREE;
29619 : 108 : location_t pragma_loc = c_parser_peek_token (parser)->location;
29620 : 108 : bool requires_body = false;
29621 : :
29622 : 108 : ret = make_node (OMP_METADIRECTIVE);
29623 : 108 : SET_EXPR_LOCATION (ret, pragma_loc);
29624 : 108 : TREE_TYPE (ret) = void_type_node;
29625 : 108 : OMP_METADIRECTIVE_VARIANTS (ret) = NULL_TREE;
29626 : :
29627 : 108 : c_parser_consume_pragma (parser);
29628 : 410 : while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
29629 : : {
29630 : 210 : if (c_parser_next_token_is (parser, CPP_COMMA))
29631 : 15 : c_parser_consume_token (parser);
29632 : 210 : if (c_parser_next_token_is_not (parser, CPP_NAME)
29633 : 272 : && c_parser_next_token_is_not (parser, CPP_KEYWORD))
29634 : : {
29635 : 0 : c_parser_error (parser, "expected %<when%>, "
29636 : : "%<otherwise%>, or %<default%> clause");
29637 : 0 : goto error;
29638 : : }
29639 : :
29640 : 210 : location_t match_loc = c_parser_peek_token (parser)->location;
29641 : 210 : const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29642 : 210 : c_parser_consume_token (parser);
29643 : 420 : bool default_p
29644 : 210 : = strcmp (p, "default") == 0 || strcmp (p, "otherwise") == 0;
29645 : 131 : if (default_p)
29646 : : {
29647 : 79 : if (default_seen)
29648 : : {
29649 : 4 : error_at (match_loc, "too many %<otherwise%> or %<default%> "
29650 : : "clauses in %<metadirective%>");
29651 : 4 : goto error;
29652 : : }
29653 : : default_seen = true;
29654 : : }
29655 : 131 : else if (default_seen)
29656 : : {
29657 : 2 : error_at (match_loc, "%<otherwise%> or %<default%> clause "
29658 : : "must appear last in %<metadirective%>");
29659 : 2 : goto error;
29660 : : }
29661 : 204 : if (!default_p && strcmp (p, "when") != 0)
29662 : : {
29663 : 2 : error_at (match_loc, "%qs is not valid for %qs",
29664 : : p, "metadirective");
29665 : 2 : goto error;
29666 : : }
29667 : :
29668 : 202 : matching_parens parens;
29669 : 202 : tree ctx = NULL_TREE;
29670 : 202 : bool skip = false;
29671 : :
29672 : 202 : if (!parens.require_open (parser))
29673 : 0 : goto error;
29674 : :
29675 : 202 : if (!default_p)
29676 : : {
29677 : 127 : ctx = c_parser_omp_context_selector_specification (parser,
29678 : : NULL_TREE);
29679 : 127 : if (ctx == error_mark_node)
29680 : 2 : goto error;
29681 : 125 : ctx = omp_check_context_selector (match_loc, ctx,
29682 : : OMP_CTX_METADIRECTIVE);
29683 : 125 : if (ctx == error_mark_node)
29684 : 0 : goto error;
29685 : :
29686 : : /* Remove the selector from further consideration if it can be
29687 : : evaluated as a non-match at this point. */
29688 : 125 : skip = (omp_context_selector_matches (ctx, NULL_TREE, false) == 0);
29689 : :
29690 : 125 : if (c_parser_next_token_is_not (parser, CPP_COLON))
29691 : : {
29692 : 2 : c_parser_require (parser, CPP_COLON, "expected %<:%>");
29693 : 2 : goto error;
29694 : : }
29695 : 123 : c_parser_consume_token (parser);
29696 : : }
29697 : :
29698 : : /* Read in the directive type and create a dummy pragma token for
29699 : : it. */
29700 : 198 : location_t loc = c_parser_peek_token (parser)->location;
29701 : :
29702 : 198 : const char *directive[3] = {};
29703 : 198 : int i;
29704 : 554 : for (i = 0; i < 3; i++)
29705 : : {
29706 : 534 : tree id;
29707 : 534 : if (c_parser_peek_nth_token (parser, i + 1)->type
29708 : : == CPP_CLOSE_PAREN)
29709 : : {
29710 : 114 : if (i == 0)
29711 : 1 : directive[i++] = "nothing";
29712 : : break;
29713 : : }
29714 : 420 : else if (c_parser_peek_nth_token (parser, i + 1)->type
29715 : : == CPP_NAME)
29716 : 279 : id = c_parser_peek_nth_token (parser, i + 1)->value;
29717 : 141 : else if (c_parser_peek_nth_token (parser, i + 1)->keyword
29718 : : != RID_MAX)
29719 : : {
29720 : 77 : enum rid rid
29721 : 77 : = c_parser_peek_nth_token (parser, i + 1)->keyword;
29722 : 77 : id = ridpointers[rid];
29723 : : }
29724 : : else
29725 : : break;
29726 : :
29727 : 356 : directive[i] = IDENTIFIER_POINTER (id);
29728 : : }
29729 : 85 : if (i == 0)
29730 : : {
29731 : 0 : error_at (loc, "expected directive name");
29732 : 0 : goto error;
29733 : : }
29734 : :
29735 : 198 : const struct c_omp_directive *omp_directive
29736 : 198 : = c_omp_categorize_directive (directive[0],
29737 : : directive[1],
29738 : 198 : directive[2]);
29739 : :
29740 : 198 : if (omp_directive == NULL)
29741 : : {
29742 : 4 : for (int j = 0; j < i; j++)
29743 : 2 : c_parser_consume_token (parser);
29744 : 2 : c_parser_error (parser, "unknown directive name");
29745 : 2 : goto error;
29746 : : }
29747 : : else
29748 : : {
29749 : 196 : int token_count = 0;
29750 : 196 : if (omp_directive->first) token_count++;
29751 : 196 : if (omp_directive->second) token_count++;
29752 : 196 : if (omp_directive->third) token_count++;
29753 : 392 : for (int j = 0; j < token_count; j++)
29754 : 196 : c_parser_consume_token (parser);
29755 : : }
29756 : 196 : if (omp_directive->id == PRAGMA_OMP_METADIRECTIVE)
29757 : : {
29758 : 2 : c_parser_error (parser,
29759 : : "metadirectives cannot be used as variants of a "
29760 : : "%<metadirective%>");
29761 : 2 : goto error;
29762 : : }
29763 : 194 : if (omp_directive->kind == C_OMP_DIR_DECLARATIVE)
29764 : : {
29765 : 0 : sorry_at (loc, "declarative directive variants of a "
29766 : : "%<metadirective%> are not supported");
29767 : 0 : goto error;
29768 : : }
29769 : 194 : if (omp_directive->kind == C_OMP_DIR_CONSTRUCT)
29770 : 116 : requires_body = true;
29771 : :
29772 : 194 : if (!skip)
29773 : : {
29774 : 161 : c_token pragma_token;
29775 : 161 : pragma_token.type = CPP_PRAGMA;
29776 : 161 : pragma_token.location = loc;
29777 : 161 : pragma_token.pragma_kind = (enum pragma_kind) omp_directive->id;
29778 : :
29779 : 161 : directives.safe_push (omp_directive);
29780 : 161 : directive_tokens.safe_push (pragma_token);
29781 : 161 : ctxs.safe_push (ctx);
29782 : : }
29783 : :
29784 : : /* Read in tokens for the directive clauses. */
29785 : : int nesting_depth = 0;
29786 : 1480 : while (1)
29787 : : {
29788 : 837 : c_token *token = c_parser_peek_token (parser);
29789 : 837 : switch (token->type)
29790 : : {
29791 : : case CPP_EOF:
29792 : : case CPP_PRAGMA_EOL:
29793 : : break;
29794 : 117 : case CPP_OPEN_PAREN:
29795 : 117 : ++nesting_depth;
29796 : 117 : goto add;
29797 : 310 : case CPP_CLOSE_PAREN:
29798 : 310 : if (nesting_depth-- == 0)
29799 : : {
29800 : 193 : c_parser_consume_token (parser);
29801 : 193 : break;
29802 : : }
29803 : 117 : goto add;
29804 : 643 : default:
29805 : 643 : add:
29806 : 643 : if (!skip)
29807 : 550 : directive_tokens.safe_push (*token);
29808 : 643 : c_parser_consume_token (parser);
29809 : 643 : continue;
29810 : : }
29811 : 194 : break;
29812 : 643 : }
29813 : :
29814 : 194 : if (!skip)
29815 : : {
29816 : 161 : c_token eol_token;
29817 : 161 : memset (&eol_token, 0, sizeof (eol_token));
29818 : 161 : eol_token.type = CPP_PRAGMA_EOL;
29819 : 161 : directive_tokens.safe_push (eol_token);
29820 : : }
29821 : : }
29822 : 92 : c_parser_skip_to_pragma_eol (parser);
29823 : :
29824 : 92 : if (!default_seen)
29825 : : {
29826 : : /* Add a default clause that evaluates to 'omp nothing'. */
29827 : 27 : const struct c_omp_directive *omp_directive
29828 : 27 : = c_omp_categorize_directive ("nothing", NULL, NULL);
29829 : :
29830 : 27 : c_token pragma_token;
29831 : 27 : pragma_token.type = CPP_PRAGMA;
29832 : 27 : pragma_token.location = UNKNOWN_LOCATION;
29833 : 27 : pragma_token.pragma_kind = PRAGMA_OMP_NOTHING;
29834 : :
29835 : 27 : directives.safe_push (omp_directive);
29836 : 27 : directive_tokens.safe_push (pragma_token);
29837 : 27 : ctxs.safe_push (NULL_TREE);
29838 : :
29839 : 27 : c_token eol_token;
29840 : 27 : memset (&eol_token, 0, sizeof (eol_token));
29841 : 27 : eol_token.type = CPP_PRAGMA_EOL;
29842 : 27 : directive_tokens.safe_push (eol_token);
29843 : : }
29844 : :
29845 : 92 : if (requires_body)
29846 : 76 : analyze_metadirective_body (parser, body_tokens, body_labels);
29847 : :
29848 : : /* Process each candidate directive. */
29849 : : unsigned i;
29850 : : tree ctx;
29851 : :
29852 : 274 : FOR_EACH_VEC_ELT (ctxs, i, ctx)
29853 : : {
29854 : 182 : auto_vec<c_token> tokens;
29855 : :
29856 : : /* Add the directive tokens. */
29857 : 908 : do
29858 : 908 : tokens.safe_push (directive_tokens [directive_token_idx++]);
29859 : 908 : while (tokens.last ().type != CPP_PRAGMA_EOL);
29860 : :
29861 : : /* Add the body tokens. */
29862 : 182 : gcc_assert (requires_body || body_tokens.is_empty ());
29863 : 4042 : for (unsigned j = 0; j < body_tokens.length (); j++)
29864 : 3860 : tokens.safe_push (body_tokens[j]);
29865 : :
29866 : : /* Make sure nothing tries to read past the end of the tokens. */
29867 : 182 : c_token eof_token;
29868 : 182 : memset (&eof_token, 0, sizeof (eof_token));
29869 : 182 : eof_token.type = CPP_EOF;
29870 : 182 : tokens.safe_push (eof_token);
29871 : 182 : tokens.safe_push (eof_token);
29872 : :
29873 : 182 : unsigned int old_tokens_avail = parser->tokens_avail;
29874 : 182 : c_token *old_tokens = parser->tokens;
29875 : 182 : struct omp_attribute_pragma_state *old_in_omp_attribute_pragma
29876 : : = parser->in_omp_attribute_pragma;
29877 : 182 : struct omp_metadirective_parse_data *old_state
29878 : : = parser->omp_metadirective_state;
29879 : :
29880 : 182 : struct omp_metadirective_parse_data new_state;
29881 : 182 : new_state.body_labels = &body_labels;
29882 : 182 : new_state.region_num = ++metadirective_region_count;
29883 : :
29884 : 182 : parser->tokens = tokens.address ();
29885 : 182 : parser->tokens_avail = tokens.length ();
29886 : 182 : parser->in_omp_attribute_pragma = NULL;
29887 : 182 : parser->omp_metadirective_state = &new_state;
29888 : :
29889 : 182 : int prev_errorcount = errorcount;
29890 : 182 : tree directive = c_begin_compound_stmt (true);
29891 : :
29892 : 182 : c_parser_pragma (parser, pragma_compound, if_p, NULL_TREE);
29893 : 182 : directive = c_end_compound_stmt (pragma_loc, directive, true);
29894 : 182 : bool standalone_p
29895 : 182 : = directives[i]->kind == C_OMP_DIR_STANDALONE
29896 : 182 : || directives[i]->kind == C_OMP_DIR_UTILITY;
29897 : 96 : if (standalone_p && requires_body)
29898 : : {
29899 : : /* Parsing standalone directives will not consume the body
29900 : : tokens, so do that here. */
29901 : 58 : if (standalone_body == NULL_TREE)
29902 : : {
29903 : 56 : standalone_body = push_stmt_list ();
29904 : 56 : c_parser_statement (parser, if_p);
29905 : 56 : standalone_body = pop_stmt_list (standalone_body);
29906 : : }
29907 : : else
29908 : 2 : c_parser_skip_to_end_of_block_or_statement (parser, true);
29909 : : }
29910 : :
29911 : 182 : tree body = standalone_p ? standalone_body : NULL_TREE;
29912 : 182 : tree variant = make_omp_metadirective_variant (ctx, directive, body);
29913 : 364 : OMP_METADIRECTIVE_VARIANTS (ret)
29914 : 182 : = chainon (OMP_METADIRECTIVE_VARIANTS (ret), variant);
29915 : :
29916 : : /* Check that all valid tokens have been consumed if no parse errors
29917 : : encountered. */
29918 : 182 : if (errorcount == prev_errorcount)
29919 : : {
29920 : 179 : gcc_assert (parser->tokens_avail == 2);
29921 : 179 : gcc_assert (c_parser_next_token_is (parser, CPP_EOF));
29922 : 179 : gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF);
29923 : : }
29924 : :
29925 : 182 : parser->tokens = old_tokens;
29926 : 182 : parser->tokens_avail = old_tokens_avail;
29927 : 182 : parser->in_omp_attribute_pragma = old_in_omp_attribute_pragma;
29928 : 182 : parser->omp_metadirective_state = old_state;
29929 : 182 : }
29930 : :
29931 : : /* Try to resolve the metadirective early. */
29932 : 92 : candidates = omp_early_resolve_metadirective (ret);
29933 : 92 : if (!candidates.is_empty ())
29934 : 68 : ret = c_omp_expand_variant_construct (candidates);
29935 : :
29936 : 92 : add_stmt (ret);
29937 : 92 : return;
29938 : :
29939 : 16 : error:
29940 : : /* Skip the metadirective pragma. Do not skip the metadirective body. */
29941 : 16 : if (parser->in_pragma)
29942 : 16 : c_parser_skip_to_pragma_eol (parser, false);
29943 : 108 : }
29944 : :
29945 : : /* Main entry point to parsing most OpenMP pragmas. */
29946 : :
29947 : : static void
29948 : 17230 : c_parser_omp_construct (c_parser *parser, bool *if_p)
29949 : : {
29950 : 17230 : enum pragma_kind p_kind;
29951 : 17230 : location_t loc;
29952 : 17230 : tree stmt;
29953 : 17230 : char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
29954 : 17230 : omp_clause_mask mask (0);
29955 : :
29956 : 17230 : loc = c_parser_peek_token (parser)->location;
29957 : 17230 : p_kind = c_parser_peek_token (parser)->pragma_kind;
29958 : 17230 : c_parser_consume_pragma (parser);
29959 : :
29960 : 17230 : switch (p_kind)
29961 : : {
29962 : 309 : case PRAGMA_OACC_ATOMIC:
29963 : 309 : c_parser_omp_atomic (loc, parser, true);
29964 : 2069 : return;
29965 : 137 : case PRAGMA_OACC_CACHE:
29966 : 137 : strcpy (p_name, "#pragma acc");
29967 : 137 : stmt = c_parser_oacc_cache (loc, parser);
29968 : 137 : break;
29969 : 497 : case PRAGMA_OACC_DATA:
29970 : 497 : stmt = c_parser_oacc_data (loc, parser, if_p);
29971 : 497 : break;
29972 : 23 : case PRAGMA_OACC_HOST_DATA:
29973 : 23 : stmt = c_parser_oacc_host_data (loc, parser, if_p);
29974 : 23 : break;
29975 : 2154 : case PRAGMA_OACC_KERNELS:
29976 : 2154 : case PRAGMA_OACC_PARALLEL:
29977 : 2154 : case PRAGMA_OACC_SERIAL:
29978 : 2154 : strcpy (p_name, "#pragma acc");
29979 : 2154 : stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
29980 : 2154 : break;
29981 : 1771 : case PRAGMA_OACC_LOOP:
29982 : 1771 : strcpy (p_name, "#pragma acc");
29983 : 1771 : stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
29984 : 1771 : break;
29985 : 86 : case PRAGMA_OACC_WAIT:
29986 : 86 : strcpy (p_name, "#pragma wait");
29987 : 86 : stmt = c_parser_oacc_wait (loc, parser, p_name);
29988 : 86 : break;
29989 : 1409 : case PRAGMA_OMP_ATOMIC:
29990 : 1409 : c_parser_omp_atomic (loc, parser, false);
29991 : 1409 : return;
29992 : 144 : case PRAGMA_OMP_CRITICAL:
29993 : 144 : stmt = c_parser_omp_critical (loc, parser, if_p);
29994 : 144 : break;
29995 : 1314 : case PRAGMA_OMP_DISTRIBUTE:
29996 : 1314 : strcpy (p_name, "#pragma omp");
29997 : 1314 : stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
29998 : 1314 : break;
29999 : 1806 : case PRAGMA_OMP_FOR:
30000 : 1806 : strcpy (p_name, "#pragma omp");
30001 : 1806 : stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
30002 : 1806 : break;
30003 : 157 : case PRAGMA_OMP_LOOP:
30004 : 157 : strcpy (p_name, "#pragma omp");
30005 : 157 : stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
30006 : 157 : break;
30007 : 60 : case PRAGMA_OMP_MASKED:
30008 : 60 : strcpy (p_name, "#pragma omp");
30009 : 60 : stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
30010 : 60 : break;
30011 : 142 : case PRAGMA_OMP_MASTER:
30012 : 142 : strcpy (p_name, "#pragma omp");
30013 : 142 : stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
30014 : 142 : break;
30015 : 2478 : case PRAGMA_OMP_PARALLEL:
30016 : 2478 : strcpy (p_name, "#pragma omp");
30017 : 2478 : stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
30018 : 2478 : break;
30019 : 61 : case PRAGMA_OMP_SCOPE:
30020 : 61 : stmt = c_parser_omp_scope (loc, parser, if_p);
30021 : 61 : break;
30022 : 106 : case PRAGMA_OMP_SECTIONS:
30023 : 106 : strcpy (p_name, "#pragma omp");
30024 : 106 : stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
30025 : 106 : break;
30026 : 726 : case PRAGMA_OMP_SIMD:
30027 : 726 : strcpy (p_name, "#pragma omp");
30028 : 726 : stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
30029 : 726 : break;
30030 : 222 : case PRAGMA_OMP_SINGLE:
30031 : 222 : stmt = c_parser_omp_single (loc, parser, if_p);
30032 : 222 : break;
30033 : 894 : case PRAGMA_OMP_TASK:
30034 : 894 : stmt = c_parser_omp_task (loc, parser, if_p);
30035 : 894 : break;
30036 : 138 : case PRAGMA_OMP_TASKGROUP:
30037 : 138 : stmt = c_parser_omp_taskgroup (loc, parser, if_p);
30038 : 138 : break;
30039 : 256 : case PRAGMA_OMP_TASKLOOP:
30040 : 256 : strcpy (p_name, "#pragma omp");
30041 : 256 : stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
30042 : 256 : break;
30043 : 1931 : case PRAGMA_OMP_TEAMS:
30044 : 1931 : strcpy (p_name, "#pragma omp");
30045 : 1931 : stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
30046 : 1931 : break;
30047 : 42 : case PRAGMA_OMP_ASSUME:
30048 : 42 : c_parser_omp_assume (parser, if_p);
30049 : 42 : return;
30050 : 110 : case PRAGMA_OMP_TILE:
30051 : 110 : stmt = c_parser_omp_tile (loc, parser, if_p);
30052 : 110 : break;
30053 : 105 : case PRAGMA_OMP_UNROLL:
30054 : 105 : stmt = c_parser_omp_unroll (loc, parser, if_p);
30055 : 105 : break;
30056 : 152 : case PRAGMA_OMP_DISPATCH:
30057 : 152 : stmt = c_parser_omp_dispatch (loc, parser);
30058 : 152 : break;
30059 : 0 : default:
30060 : 0 : gcc_unreachable ();
30061 : : }
30062 : :
30063 : 15470 : if (stmt && stmt != error_mark_node)
30064 : 15162 : gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
30065 : : }
30066 : :
30067 : :
30068 : : /* OpenMP 2.5:
30069 : : # pragma omp threadprivate (variable-list) */
30070 : :
30071 : : static void
30072 : 78 : c_parser_omp_threadprivate (c_parser *parser)
30073 : : {
30074 : 78 : tree vars, t;
30075 : 78 : location_t loc;
30076 : :
30077 : 78 : c_parser_consume_pragma (parser);
30078 : 78 : vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
30079 : :
30080 : : /* Mark every variable in VARS to be assigned thread local storage. */
30081 : 167 : for (t = vars; t; t = TREE_CHAIN (t))
30082 : : {
30083 : 89 : tree v = TREE_PURPOSE (t);
30084 : 89 : loc = EXPR_LOCATION (TREE_VALUE (t));
30085 : :
30086 : : /* If V had already been marked threadprivate, it doesn't matter
30087 : : whether it had been used prior to this point. */
30088 : 89 : if (!VAR_P (v))
30089 : 1 : error_at (loc, "%qD is not a variable", v);
30090 : 88 : else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
30091 : 2 : error_at (loc, "%qE declared %<threadprivate%> after first use", v);
30092 : 86 : else if (! is_global_var (v))
30093 : 2 : error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
30094 : 84 : else if (TREE_TYPE (v) == error_mark_node)
30095 : : ;
30096 : 83 : else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
30097 : 1 : error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
30098 : : else
30099 : : {
30100 : 82 : if (! DECL_THREAD_LOCAL_P (v))
30101 : : {
30102 : 82 : set_decl_tls_model (v, decl_default_tls_model (v));
30103 : : /* If rtl has been already set for this var, call
30104 : : make_decl_rtl once again, so that encode_section_info
30105 : : has a chance to look at the new decl flags. */
30106 : 82 : if (DECL_RTL_SET_P (v))
30107 : 0 : make_decl_rtl (v);
30108 : : }
30109 : 82 : C_DECL_THREADPRIVATE_P (v) = 1;
30110 : : }
30111 : : }
30112 : :
30113 : 78 : c_parser_skip_to_pragma_eol (parser);
30114 : 78 : }
30115 : :
30116 : : /* Parse a transaction attribute (GCC Extension).
30117 : :
30118 : : transaction-attribute:
30119 : : gnu-attributes
30120 : : attribute-specifier
30121 : : */
30122 : :
30123 : : static tree
30124 : 139 : c_parser_transaction_attributes (c_parser *parser)
30125 : : {
30126 : 139 : if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
30127 : 0 : return c_parser_gnu_attributes (parser);
30128 : :
30129 : 139 : if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
30130 : : return NULL_TREE;
30131 : 20 : return c_parser_std_attribute_specifier (parser, true);
30132 : : }
30133 : :
30134 : : /* Parse a __transaction_atomic or __transaction_relaxed statement
30135 : : (GCC Extension).
30136 : :
30137 : : transaction-statement:
30138 : : __transaction_atomic transaction-attribute[opt] compound-statement
30139 : : __transaction_relaxed compound-statement
30140 : :
30141 : : Note that the only valid attribute is: "outer".
30142 : : */
30143 : :
30144 : : static tree
30145 : 137 : c_parser_transaction (c_parser *parser, enum rid keyword)
30146 : : {
30147 : 137 : unsigned int old_in = parser->in_transaction;
30148 : 137 : unsigned int this_in = 1, new_in;
30149 : 137 : location_t loc = c_parser_peek_token (parser)->location;
30150 : 137 : tree stmt, attrs;
30151 : :
30152 : 274 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
30153 : : || keyword == RID_TRANSACTION_RELAXED)
30154 : : && c_parser_next_token_is_keyword (parser, keyword));
30155 : 137 : c_parser_consume_token (parser);
30156 : :
30157 : 137 : if (keyword == RID_TRANSACTION_RELAXED)
30158 : : this_in |= TM_STMT_ATTR_RELAXED;
30159 : : else
30160 : : {
30161 : 106 : attrs = c_parser_transaction_attributes (parser);
30162 : 106 : if (attrs)
30163 : 14 : this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
30164 : : }
30165 : :
30166 : : /* Keep track if we're in the lexical scope of an outer transaction. */
30167 : 137 : new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
30168 : :
30169 : 137 : parser->in_transaction = new_in;
30170 : 137 : stmt = c_parser_compound_statement (parser);
30171 : 137 : parser->in_transaction = old_in;
30172 : :
30173 : 137 : if (flag_tm)
30174 : 135 : stmt = c_finish_transaction (loc, stmt, this_in);
30175 : : else
30176 : 2 : error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
30177 : : "%<__transaction_atomic%> without transactional memory support enabled"
30178 : : : "%<__transaction_relaxed %> "
30179 : : "without transactional memory support enabled"));
30180 : :
30181 : 137 : return stmt;
30182 : : }
30183 : :
30184 : : /* Parse a __transaction_atomic or __transaction_relaxed expression
30185 : : (GCC Extension).
30186 : :
30187 : : transaction-expression:
30188 : : __transaction_atomic ( expression )
30189 : : __transaction_relaxed ( expression )
30190 : : */
30191 : :
30192 : : static struct c_expr
30193 : 7 : c_parser_transaction_expression (c_parser *parser, enum rid keyword)
30194 : : {
30195 : 7 : struct c_expr ret;
30196 : 7 : unsigned int old_in = parser->in_transaction;
30197 : 7 : unsigned int this_in = 1;
30198 : 7 : location_t loc = c_parser_peek_token (parser)->location;
30199 : 7 : tree attrs;
30200 : :
30201 : 14 : gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
30202 : : || keyword == RID_TRANSACTION_RELAXED)
30203 : : && c_parser_next_token_is_keyword (parser, keyword));
30204 : 7 : c_parser_consume_token (parser);
30205 : :
30206 : 7 : if (keyword == RID_TRANSACTION_RELAXED)
30207 : : this_in |= TM_STMT_ATTR_RELAXED;
30208 : : else
30209 : : {
30210 : 5 : attrs = c_parser_transaction_attributes (parser);
30211 : 5 : if (attrs)
30212 : 0 : this_in |= parse_tm_stmt_attr (attrs, 0);
30213 : : }
30214 : :
30215 : 7 : parser->in_transaction = this_in;
30216 : 7 : matching_parens parens;
30217 : 7 : if (parens.require_open (parser))
30218 : : {
30219 : 7 : tree expr = c_parser_expression (parser).value;
30220 : 7 : ret.original_type = TREE_TYPE (expr);
30221 : 7 : ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
30222 : 7 : if (this_in & TM_STMT_ATTR_RELAXED)
30223 : 2 : TRANSACTION_EXPR_RELAXED (ret.value) = 1;
30224 : 7 : SET_EXPR_LOCATION (ret.value, loc);
30225 : 7 : ret.original_code = TRANSACTION_EXPR;
30226 : 7 : ret.m_decimal = 0;
30227 : 7 : if (!parens.require_close (parser))
30228 : : {
30229 : 0 : c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
30230 : 0 : goto error;
30231 : : }
30232 : : }
30233 : : else
30234 : : {
30235 : 0 : error:
30236 : 0 : ret.set_error ();
30237 : 0 : ret.original_code = ERROR_MARK;
30238 : 0 : ret.original_type = NULL;
30239 : : }
30240 : 7 : parser->in_transaction = old_in;
30241 : :
30242 : 7 : if (!flag_tm)
30243 : 6 : error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
30244 : : "%<__transaction_atomic%> without transactional memory support enabled"
30245 : : : "%<__transaction_relaxed %> "
30246 : : "without transactional memory support enabled"));
30247 : :
30248 : 7 : set_c_expr_source_range (&ret, loc, loc);
30249 : :
30250 : 7 : return ret;
30251 : : }
30252 : :
30253 : : /* Parse a __transaction_cancel statement (GCC Extension).
30254 : :
30255 : : transaction-cancel-statement:
30256 : : __transaction_cancel transaction-attribute[opt] ;
30257 : :
30258 : : Note that the only valid attribute is "outer".
30259 : : */
30260 : :
30261 : : static tree
30262 : 28 : c_parser_transaction_cancel (c_parser *parser)
30263 : : {
30264 : 28 : location_t loc = c_parser_peek_token (parser)->location;
30265 : 28 : tree attrs;
30266 : 28 : bool is_outer = false;
30267 : :
30268 : 28 : gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
30269 : 28 : c_parser_consume_token (parser);
30270 : :
30271 : 28 : attrs = c_parser_transaction_attributes (parser);
30272 : 28 : if (attrs)
30273 : 5 : is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
30274 : :
30275 : 28 : if (!flag_tm)
30276 : : {
30277 : 2 : error_at (loc, "%<__transaction_cancel%> without "
30278 : : "transactional memory support enabled");
30279 : 2 : goto ret_error;
30280 : : }
30281 : 26 : else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
30282 : : {
30283 : 0 : error_at (loc, "%<__transaction_cancel%> within a "
30284 : : "%<__transaction_relaxed%>");
30285 : 0 : goto ret_error;
30286 : : }
30287 : 26 : else if (is_outer)
30288 : : {
30289 : 5 : if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
30290 : 5 : && !is_tm_may_cancel_outer (current_function_decl))
30291 : : {
30292 : 0 : error_at (loc, "outer %<__transaction_cancel%> not "
30293 : : "within outer %<__transaction_atomic%> or "
30294 : : "a %<transaction_may_cancel_outer%> function");
30295 : 0 : goto ret_error;
30296 : : }
30297 : : }
30298 : 21 : else if (parser->in_transaction == 0)
30299 : : {
30300 : 0 : error_at (loc, "%<__transaction_cancel%> not within "
30301 : : "%<__transaction_atomic%>");
30302 : 0 : goto ret_error;
30303 : : }
30304 : :
30305 : 26 : return add_stmt (build_tm_abort_call (loc, is_outer));
30306 : :
30307 : 2 : ret_error:
30308 : 2 : return build1 (NOP_EXPR, void_type_node, error_mark_node);
30309 : : }
30310 : :
30311 : : /* Parse a single source file. */
30312 : :
30313 : : void
30314 : 107224 : c_parse_file (void)
30315 : : {
30316 : : /* Use local storage to begin. If the first token is a pragma, parse it.
30317 : : If it is #pragma GCC pch_preprocess, then this will load a PCH file
30318 : : which will cause garbage collection. */
30319 : 107224 : c_parser tparser;
30320 : :
30321 : 107224 : memset (&tparser, 0, sizeof tparser);
30322 : 107224 : tparser.translate_strings_p = true;
30323 : 107224 : tparser.tokens = &tparser.tokens_buf[0];
30324 : 107224 : the_parser = &tparser;
30325 : :
30326 : 107224 : if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
30327 : 12 : c_parser_pragma_pch_preprocess (&tparser);
30328 : : else
30329 : 107145 : c_common_no_more_pch ();
30330 : :
30331 : 107157 : the_parser = ggc_alloc<c_parser> ();
30332 : 107157 : *the_parser = tparser;
30333 : 107157 : if (tparser.tokens == &tparser.tokens_buf[0])
30334 : 107157 : the_parser->tokens = &the_parser->tokens_buf[0];
30335 : :
30336 : : /* Initialize EH, if we've been told to do so. */
30337 : 107157 : if (flag_exceptions)
30338 : 507 : using_eh_for_cleanups ();
30339 : :
30340 : 107157 : c_parser_translation_unit (the_parser);
30341 : 107067 : the_parser = NULL;
30342 : 107067 : }
30343 : :
30344 : : void
30345 : 4849 : c_init_preprocess (void)
30346 : : {
30347 : : /* Create a parser for use by pragma_lex during preprocessing. */
30348 : 4849 : the_parser = ggc_alloc<c_parser> ();
30349 : 4849 : memset (the_parser, 0, sizeof (c_parser));
30350 : 4849 : the_parser->tokens = &the_parser->tokens_buf[0];
30351 : 4849 : }
30352 : :
30353 : : /* Parse the body of a function declaration marked with "__RTL".
30354 : :
30355 : : The RTL parser works on the level of characters read from a
30356 : : FILE *, whereas c_parser works at the level of tokens.
30357 : : Square this circle by consuming all of the tokens up to and
30358 : : including the closing brace, recording the start/end of the RTL
30359 : : fragment, and reopening the file and re-reading the relevant
30360 : : lines within the RTL parser.
30361 : :
30362 : : This requires the opening and closing braces of the C function
30363 : : to be on separate lines from the RTL they wrap.
30364 : :
30365 : : Take ownership of START_WITH_PASS, if non-NULL. */
30366 : :
30367 : : location_t
30368 : 25 : c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
30369 : : {
30370 : 25 : if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
30371 : : {
30372 : 0 : free (start_with_pass);
30373 : 0 : return c_parser_peek_token (parser)->location;
30374 : : }
30375 : :
30376 : 25 : location_t start_loc = c_parser_peek_token (parser)->location;
30377 : :
30378 : : /* Consume all tokens, up to the closing brace, handling
30379 : : matching pairs of braces in the rtl dump. */
30380 : 25 : int num_open_braces = 1;
30381 : 25239 : while (1)
30382 : : {
30383 : 12632 : switch (c_parser_peek_token (parser)->type)
30384 : : {
30385 : 1 : case CPP_OPEN_BRACE:
30386 : 1 : num_open_braces++;
30387 : 1 : break;
30388 : 25 : case CPP_CLOSE_BRACE:
30389 : 25 : if (--num_open_braces == 0)
30390 : 24 : goto found_closing_brace;
30391 : : break;
30392 : 1 : case CPP_EOF:
30393 : 1 : error_at (start_loc, "no closing brace");
30394 : 1 : free (start_with_pass);
30395 : 1 : return c_parser_peek_token (parser)->location;
30396 : : default:
30397 : : break;
30398 : : }
30399 : 12607 : c_parser_consume_token (parser);
30400 : : }
30401 : :
30402 : 24 : found_closing_brace:
30403 : : /* At the closing brace; record its location. */
30404 : 24 : location_t end_loc = c_parser_peek_token (parser)->location;
30405 : :
30406 : : /* Consume the closing brace. */
30407 : 24 : c_parser_consume_token (parser);
30408 : :
30409 : : /* Invoke the RTL parser. */
30410 : 24 : if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
30411 : : {
30412 : 0 : free (start_with_pass);
30413 : 0 : return end_loc;
30414 : : }
30415 : :
30416 : : /* Run the backend on the cfun created above, transferring ownership of
30417 : : START_WITH_PASS. */
30418 : 23 : run_rtl_passes (start_with_pass);
30419 : 23 : return end_loc;
30420 : : }
30421 : :
30422 : : #include "gt-c-c-parser.h"
|