]>
Commit | Line | Data |
---|---|---|
27bf414c | 1 | /* Parser for C and Objective-C. |
cbe34bb5 | 2 | Copyright (C) 1987-2017 Free Software Foundation, Inc. |
27bf414c JM |
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 | |
9dcd6f09 | 11 | Software Foundation; either version 3, or (at your option) any later |
27bf414c JM |
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 | |
9dcd6f09 NC |
20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
27bf414c JM |
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" | |
6c7a259b | 39 | #define INCLUDE_UNIQUE_PTR |
27bf414c JM |
40 | #include "system.h" |
41 | #include "coretypes.h" | |
2adfab87 AM |
42 | #include "target.h" |
43 | #include "function.h" | |
2adfab87 AM |
44 | #include "c-tree.h" |
45 | #include "timevar.h" | |
d8a2d370 | 46 | #include "stringpool.h" |
2adfab87 | 47 | #include "cgraph.h" |
d8a2d370 DN |
48 | #include "attribs.h" |
49 | #include "stor-layout.h" | |
50 | #include "varasm.h" | |
51 | #include "trans-mem.h" | |
39dabefd | 52 | #include "c-family/c-pragma.h" |
acf0174b | 53 | #include "c-lang.h" |
61d3ce20 | 54 | #include "c-family/c-objc.h" |
68a607d8 | 55 | #include "plugin.h" |
629b3d75 MJ |
56 | #include "omp-general.h" |
57 | #include "omp-offload.h" | |
9b2b7279 | 58 | #include "builtins.h" |
41dbbb37 | 59 | #include "gomp-constants.h" |
992118a1 | 60 | #include "c-family/c-indentation.h" |
e01d41e5 JJ |
61 | #include "gimple-expr.h" |
62 | #include "context.h" | |
1a4f11c8 | 63 | #include "gcc-rich-location.h" |
1ee62b92 PG |
64 | #include "c-parser.h" |
65 | #include "gimple-parser.h" | |
c2e84327 DM |
66 | #include "read-rtl-function.h" |
67 | #include "run-rtl-passes.h" | |
324ff1a0 | 68 | #include "intl.h" |
6c7a259b | 69 | #include "c-family/name-hint.h" |
27bf414c | 70 | |
d25c7690 PK |
71 | /* We need to walk over decls with incomplete struct/union/enum types |
72 | after parsing the whole translation unit. | |
73 | In finish_decl(), if the decl is static, has incomplete | |
74 | struct/union/enum type, it is appeneded to incomplete_record_decls. | |
75 | In c_parser_translation_unit(), we iterate over incomplete_record_decls | |
76 | and report error if any of the decls are still incomplete. */ | |
77 | ||
7de76362 | 78 | vec<tree> incomplete_record_decls; |
d25c7690 | 79 | |
ebedc9a3 DM |
80 | void |
81 | set_c_expr_source_range (c_expr *expr, | |
82 | location_t start, location_t finish) | |
83 | { | |
84 | expr->src_range.m_start = start; | |
85 | expr->src_range.m_finish = finish; | |
bef08b71 DM |
86 | if (expr->value) |
87 | set_source_range (expr->value, start, finish); | |
ebedc9a3 DM |
88 | } |
89 | ||
90 | void | |
91 | set_c_expr_source_range (c_expr *expr, | |
92 | source_range src_range) | |
93 | { | |
94 | expr->src_range = src_range; | |
bef08b71 DM |
95 | if (expr->value) |
96 | set_source_range (expr->value, src_range); | |
ebedc9a3 DM |
97 | } |
98 | ||
27bf414c | 99 | \f |
27bf414c JM |
100 | /* Initialization routine for this file. */ |
101 | ||
102 | void | |
103 | c_parse_init (void) | |
104 | { | |
105 | /* The only initialization required is of the reserved word | |
106 | identifiers. */ | |
107 | unsigned int i; | |
108 | tree id; | |
eea1139b | 109 | int mask = 0; |
27bf414c | 110 | |
36c5e70a BE |
111 | /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in |
112 | the c_token structure. */ | |
113 | gcc_assert (RID_MAX <= 255); | |
114 | ||
eea1139b ILT |
115 | mask |= D_CXXONLY; |
116 | if (!flag_isoc99) | |
117 | mask |= D_C99; | |
118 | if (flag_no_asm) | |
119 | { | |
120 | mask |= D_ASM | D_EXT; | |
121 | if (!flag_isoc99) | |
122 | mask |= D_EXT89; | |
123 | } | |
27bf414c | 124 | if (!c_dialect_objc ()) |
eea1139b | 125 | mask |= D_OBJC | D_CXX_OBJC; |
27bf414c | 126 | |
766090c2 | 127 | ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX); |
eea1139b | 128 | for (i = 0; i < num_c_common_reswords; i++) |
27bf414c JM |
129 | { |
130 | /* If a keyword is disabled, do not enter it into the table | |
131 | and so create a canonical spelling that isn't a keyword. */ | |
eea1139b ILT |
132 | if (c_common_reswords[i].disable & mask) |
133 | { | |
134 | if (warn_cxx_compat | |
135 | && (c_common_reswords[i].disable & D_CXXWARN)) | |
136 | { | |
137 | id = get_identifier (c_common_reswords[i].word); | |
138 | C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN); | |
139 | C_IS_RESERVED_WORD (id) = 1; | |
140 | } | |
141 | continue; | |
142 | } | |
27bf414c | 143 | |
eea1139b ILT |
144 | id = get_identifier (c_common_reswords[i].word); |
145 | C_SET_RID_CODE (id, c_common_reswords[i].rid); | |
27bf414c | 146 | C_IS_RESERVED_WORD (id) = 1; |
eea1139b | 147 | ridpointers [(int) c_common_reswords[i].rid] = id; |
27bf414c | 148 | } |
78a7c317 DD |
149 | |
150 | for (i = 0; i < NUM_INT_N_ENTS; i++) | |
151 | { | |
152 | /* We always create the symbols but they aren't always supported. */ | |
153 | char name[50]; | |
154 | sprintf (name, "__int%d", int_n_data[i].bitsize); | |
17958621 | 155 | id = get_identifier (name); |
78a7c317 DD |
156 | C_SET_RID_CODE (id, RID_FIRST_INT_N + i); |
157 | C_IS_RESERVED_WORD (id) = 1; | |
158 | } | |
27bf414c JM |
159 | } |
160 | \f | |
27bf414c JM |
161 | /* A parser structure recording information about the state and |
162 | context of parsing. Includes lexer information with up to two | |
163 | tokens of look-ahead; more are not needed for C. */ | |
a79683d5 | 164 | struct GTY(()) c_parser { |
27bf414c | 165 | /* The look-ahead tokens. */ |
acf0174b JJ |
166 | c_token * GTY((skip)) tokens; |
167 | /* Buffer for look-ahead tokens. */ | |
de67c4c3 DM |
168 | c_token tokens_buf[4]; |
169 | /* How many look-ahead tokens are available (0 - 4, or | |
acf0174b JJ |
170 | more if parsing from pre-lexed tokens). */ |
171 | unsigned int tokens_avail; | |
27bf414c JM |
172 | /* True if a syntax error is being recovered from; false otherwise. |
173 | c_parser_error sets this flag. It should clear this flag when | |
174 | enough tokens have been consumed to recover from the error. */ | |
175 | BOOL_BITFIELD error : 1; | |
bc4071dd RH |
176 | /* True if we're processing a pragma, and shouldn't automatically |
177 | consume CPP_PRAGMA_EOL. */ | |
178 | BOOL_BITFIELD in_pragma : 1; | |
b4b56033 MLI |
179 | /* True if we're parsing the outermost block of an if statement. */ |
180 | BOOL_BITFIELD in_if_block : 1; | |
46c2514e TT |
181 | /* True if we want to lex an untranslated string. */ |
182 | BOOL_BITFIELD lex_untranslated_string : 1; | |
1973201f | 183 | |
0bacb8c7 | 184 | /* Objective-C specific parser/lexer information. */ |
1973201f NP |
185 | |
186 | /* True if we are in a context where the Objective-C "PQ" keywords | |
187 | are considered keywords. */ | |
0bacb8c7 | 188 | BOOL_BITFIELD objc_pq_context : 1; |
f05b9d93 NP |
189 | /* True if we are parsing a (potential) Objective-C foreach |
190 | statement. This is set to true after we parsed 'for (' and while | |
191 | we wait for 'in' or ';' to decide if it's a standard C for loop or an | |
192 | Objective-C foreach loop. */ | |
193 | BOOL_BITFIELD objc_could_be_foreach_context : 1; | |
0bacb8c7 TT |
194 | /* The following flag is needed to contextualize Objective-C lexical |
195 | analysis. In some cases (e.g., 'int NSObject;'), it is | |
196 | undesirable to bind an identifier to an Objective-C class, even | |
197 | if a class with that name exists. */ | |
198 | BOOL_BITFIELD objc_need_raw_identifier : 1; | |
0a35513e AH |
199 | /* Nonzero if we're processing a __transaction statement. The value |
200 | is 1 | TM_STMT_ATTR_*. */ | |
201 | unsigned int in_transaction : 4; | |
668ea4b1 IS |
202 | /* True if we are in a context where the Objective-C "Property attribute" |
203 | keywords are valid. */ | |
204 | BOOL_BITFIELD objc_property_attr_context : 1; | |
41958c28 BI |
205 | |
206 | /* Cilk Plus specific parser/lexer information. */ | |
207 | ||
208 | /* Buffer to hold all the tokens from parsing the vector attribute for the | |
209 | SIMD-enabled functions (formerly known as elemental functions). */ | |
210 | vec <c_token, va_gc> *cilk_simd_fn_tokens; | |
8139a48e DM |
211 | |
212 | /* Location of the last consumed token. */ | |
213 | location_t last_token_location; | |
a79683d5 | 214 | }; |
27bf414c | 215 | |
1ee62b92 PG |
216 | /* Return a pointer to the Nth token in PARSERs tokens_buf. */ |
217 | ||
218 | c_token * | |
219 | c_parser_tokens_buf (c_parser *parser, unsigned n) | |
220 | { | |
221 | return &parser->tokens_buf[n]; | |
222 | } | |
223 | ||
224 | /* Return the error state of PARSER. */ | |
225 | ||
226 | bool | |
227 | c_parser_error (c_parser *parser) | |
228 | { | |
229 | return parser->error; | |
230 | } | |
231 | ||
232 | /* Set the error state of PARSER to ERR. */ | |
233 | ||
234 | void | |
235 | c_parser_set_error (c_parser *parser, bool err) | |
236 | { | |
237 | parser->error = err; | |
238 | } | |
239 | ||
bc4071dd RH |
240 | |
241 | /* The actual parser and external interface. ??? Does this need to be | |
242 | garbage-collected? */ | |
243 | ||
244 | static GTY (()) c_parser *the_parser; | |
245 | ||
27bf414c JM |
246 | /* Read in and lex a single token, storing it in *TOKEN. */ |
247 | ||
248 | static void | |
0bacb8c7 | 249 | c_lex_one_token (c_parser *parser, c_token *token) |
27bf414c JM |
250 | { |
251 | timevar_push (TV_LEX); | |
bc4071dd | 252 | |
81fea426 MP |
253 | token->type = c_lex_with_flags (&token->value, &token->location, |
254 | &token->flags, | |
46c2514e TT |
255 | (parser->lex_untranslated_string |
256 | ? C_LEX_STRING_NO_TRANSLATE : 0)); | |
bc4071dd RH |
257 | token->id_kind = C_ID_NONE; |
258 | token->keyword = RID_MAX; | |
259 | token->pragma_kind = PRAGMA_NONE; | |
bc4071dd | 260 | |
27bf414c JM |
261 | switch (token->type) |
262 | { | |
263 | case CPP_NAME: | |
27bf414c JM |
264 | { |
265 | tree decl; | |
266 | ||
0bacb8c7 TT |
267 | bool objc_force_identifier = parser->objc_need_raw_identifier; |
268 | if (c_dialect_objc ()) | |
269 | parser->objc_need_raw_identifier = false; | |
27bf414c JM |
270 | |
271 | if (C_IS_RESERVED_WORD (token->value)) | |
272 | { | |
273 | enum rid rid_code = C_RID_CODE (token->value); | |
274 | ||
eea1139b ILT |
275 | if (rid_code == RID_CXX_COMPAT_WARN) |
276 | { | |
3ba09659 AH |
277 | warning_at (token->location, |
278 | OPT_Wc___compat, | |
88388a52 JM |
279 | "identifier %qE conflicts with C++ keyword", |
280 | token->value); | |
eea1139b | 281 | } |
36c5e70a BE |
282 | else if (rid_code >= RID_FIRST_ADDR_SPACE |
283 | && rid_code <= RID_LAST_ADDR_SPACE) | |
284 | { | |
ffc22840 GJL |
285 | addr_space_t as; |
286 | as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE); | |
287 | targetm.addr_space.diagnose_usage (as, token->location); | |
36c5e70a BE |
288 | token->id_kind = C_ID_ADDRSPACE; |
289 | token->keyword = rid_code; | |
290 | break; | |
291 | } | |
1973201f | 292 | else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code)) |
27bf414c | 293 | { |
1973201f NP |
294 | /* We found an Objective-C "pq" keyword (in, out, |
295 | inout, bycopy, byref, oneway). They need special | |
296 | care because the interpretation depends on the | |
d853ee42 | 297 | context. */ |
1973201f | 298 | if (parser->objc_pq_context) |
27bf414c | 299 | { |
27bf414c JM |
300 | token->type = CPP_KEYWORD; |
301 | token->keyword = rid_code; | |
302 | break; | |
303 | } | |
f05b9d93 NP |
304 | else if (parser->objc_could_be_foreach_context |
305 | && rid_code == RID_IN) | |
306 | { | |
307 | /* We are in Objective-C, inside a (potential) | |
308 | foreach context (which means after having | |
309 | parsed 'for (', but before having parsed ';'), | |
310 | and we found 'in'. We consider it the keyword | |
311 | which terminates the declaration at the | |
312 | beginning of a foreach-statement. Note that | |
313 | this means you can't use 'in' for anything else | |
314 | in that context; in particular, in Objective-C | |
315 | you can't use 'in' as the name of the running | |
316 | variable in a C for loop. We could potentially | |
317 | try to add code here to disambiguate, but it | |
d853ee42 | 318 | seems a reasonable limitation. */ |
f05b9d93 NP |
319 | token->type = CPP_KEYWORD; |
320 | token->keyword = rid_code; | |
321 | break; | |
322 | } | |
1973201f NP |
323 | /* Else, "pq" keywords outside of the "pq" context are |
324 | not keywords, and we fall through to the code for | |
d853ee42 | 325 | normal tokens. */ |
1973201f | 326 | } |
668ea4b1 IS |
327 | else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code)) |
328 | { | |
d853ee42 NP |
329 | /* We found an Objective-C "property attribute" |
330 | keyword (getter, setter, readonly, etc). These are | |
668ea4b1 IS |
331 | only valid in the property context. */ |
332 | if (parser->objc_property_attr_context) | |
333 | { | |
334 | token->type = CPP_KEYWORD; | |
335 | token->keyword = rid_code; | |
336 | break; | |
337 | } | |
338 | /* Else they are not special keywords. | |
339 | */ | |
340 | } | |
1973201f NP |
341 | else if (c_dialect_objc () |
342 | && (OBJC_IS_AT_KEYWORD (rid_code) | |
343 | || OBJC_IS_CXX_KEYWORD (rid_code))) | |
344 | { | |
345 | /* We found one of the Objective-C "@" keywords (defs, | |
346 | selector, synchronized, etc) or one of the | |
347 | Objective-C "cxx" keywords (class, private, | |
348 | protected, public, try, catch, throw) without a | |
349 | preceding '@' sign. Do nothing and fall through to | |
350 | the code for normal tokens (in C++ we would still | |
d853ee42 | 351 | consider the CXX ones keywords, but not in C). */ |
1973201f | 352 | ; |
27bf414c JM |
353 | } |
354 | else | |
355 | { | |
27bf414c JM |
356 | token->type = CPP_KEYWORD; |
357 | token->keyword = rid_code; | |
358 | break; | |
359 | } | |
360 | } | |
361 | ||
362 | decl = lookup_name (token->value); | |
363 | if (decl) | |
364 | { | |
365 | if (TREE_CODE (decl) == TYPE_DECL) | |
366 | { | |
367 | token->id_kind = C_ID_TYPENAME; | |
368 | break; | |
369 | } | |
370 | } | |
371 | else if (c_dialect_objc ()) | |
372 | { | |
373 | tree objc_interface_decl = objc_is_class_name (token->value); | |
374 | /* Objective-C class names are in the same namespace as | |
375 | variables and typedefs, and hence are shadowed by local | |
376 | declarations. */ | |
377 | if (objc_interface_decl | |
0d8a2528 | 378 | && (!objc_force_identifier || global_bindings_p ())) |
27bf414c JM |
379 | { |
380 | token->value = objc_interface_decl; | |
381 | token->id_kind = C_ID_CLASSNAME; | |
382 | break; | |
383 | } | |
384 | } | |
bc4071dd | 385 | token->id_kind = C_ID_ID; |
27bf414c | 386 | } |
27bf414c JM |
387 | break; |
388 | case CPP_AT_NAME: | |
389 | /* This only happens in Objective-C; it must be a keyword. */ | |
390 | token->type = CPP_KEYWORD; | |
49b91f05 NP |
391 | switch (C_RID_CODE (token->value)) |
392 | { | |
393 | /* Replace 'class' with '@class', 'private' with '@private', | |
394 | etc. This prevents confusion with the C++ keyword | |
395 | 'class', and makes the tokens consistent with other | |
396 | Objective-C 'AT' keywords. For example '@class' is | |
397 | reported as RID_AT_CLASS which is consistent with | |
398 | '@synchronized', which is reported as | |
399 | RID_AT_SYNCHRONIZED. | |
400 | */ | |
401 | case RID_CLASS: token->keyword = RID_AT_CLASS; break; | |
402 | case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break; | |
403 | case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break; | |
404 | case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break; | |
405 | case RID_THROW: token->keyword = RID_AT_THROW; break; | |
406 | case RID_TRY: token->keyword = RID_AT_TRY; break; | |
407 | case RID_CATCH: token->keyword = RID_AT_CATCH; break; | |
b8fd7909 | 408 | case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break; |
49b91f05 NP |
409 | default: token->keyword = C_RID_CODE (token->value); |
410 | } | |
27bf414c JM |
411 | break; |
412 | case CPP_COLON: | |
413 | case CPP_COMMA: | |
414 | case CPP_CLOSE_PAREN: | |
415 | case CPP_SEMICOLON: | |
416 | /* These tokens may affect the interpretation of any identifiers | |
417 | following, if doing Objective-C. */ | |
0bacb8c7 TT |
418 | if (c_dialect_objc ()) |
419 | parser->objc_need_raw_identifier = false; | |
bc4071dd RH |
420 | break; |
421 | case CPP_PRAGMA: | |
422 | /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ | |
d75d71e0 | 423 | token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value); |
bc4071dd | 424 | token->value = NULL; |
27bf414c JM |
425 | break; |
426 | default: | |
27bf414c JM |
427 | break; |
428 | } | |
429 | timevar_pop (TV_LEX); | |
430 | } | |
431 | ||
432 | /* Return a pointer to the next token from PARSER, reading it in if | |
433 | necessary. */ | |
434 | ||
1ee62b92 | 435 | c_token * |
27bf414c JM |
436 | c_parser_peek_token (c_parser *parser) |
437 | { | |
438 | if (parser->tokens_avail == 0) | |
439 | { | |
0bacb8c7 | 440 | c_lex_one_token (parser, &parser->tokens[0]); |
27bf414c JM |
441 | parser->tokens_avail = 1; |
442 | } | |
443 | return &parser->tokens[0]; | |
444 | } | |
445 | ||
29ce73cb PB |
446 | /* Return a pointer to the next-but-one token from PARSER, reading it |
447 | in if necessary. The next token is already read in. */ | |
448 | ||
1ee62b92 | 449 | c_token * |
29ce73cb PB |
450 | c_parser_peek_2nd_token (c_parser *parser) |
451 | { | |
452 | if (parser->tokens_avail >= 2) | |
453 | return &parser->tokens[1]; | |
454 | gcc_assert (parser->tokens_avail == 1); | |
455 | gcc_assert (parser->tokens[0].type != CPP_EOF); | |
456 | gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL); | |
457 | c_lex_one_token (parser, &parser->tokens[1]); | |
458 | parser->tokens_avail = 2; | |
459 | return &parser->tokens[1]; | |
460 | } | |
461 | ||
de67c4c3 DM |
462 | /* Return a pointer to the Nth token from PARSER, reading it |
463 | in if necessary. The N-1th token is already read in. */ | |
464 | ||
1ee62b92 | 465 | c_token * |
de67c4c3 DM |
466 | c_parser_peek_nth_token (c_parser *parser, unsigned int n) |
467 | { | |
468 | /* N is 1-based, not zero-based. */ | |
469 | gcc_assert (n > 0); | |
470 | ||
471 | if (parser->tokens_avail >= n) | |
472 | return &parser->tokens[n - 1]; | |
473 | gcc_assert (parser->tokens_avail == n - 1); | |
474 | c_lex_one_token (parser, &parser->tokens[n - 1]); | |
475 | parser->tokens_avail = n; | |
476 | return &parser->tokens[n - 1]; | |
477 | } | |
478 | ||
1a4f11c8 DM |
479 | bool |
480 | c_keyword_starts_typename (enum rid keyword) | |
481 | { | |
482 | switch (keyword) | |
483 | { | |
484 | case RID_UNSIGNED: | |
485 | case RID_LONG: | |
486 | case RID_SHORT: | |
487 | case RID_SIGNED: | |
488 | case RID_COMPLEX: | |
489 | case RID_INT: | |
490 | case RID_CHAR: | |
491 | case RID_FLOAT: | |
492 | case RID_DOUBLE: | |
493 | case RID_VOID: | |
494 | case RID_DFLOAT32: | |
495 | case RID_DFLOAT64: | |
496 | case RID_DFLOAT128: | |
c65699ef | 497 | CASE_RID_FLOATN_NX: |
1a4f11c8 DM |
498 | case RID_BOOL: |
499 | case RID_ENUM: | |
500 | case RID_STRUCT: | |
501 | case RID_UNION: | |
502 | case RID_TYPEOF: | |
503 | case RID_CONST: | |
504 | case RID_ATOMIC: | |
505 | case RID_VOLATILE: | |
506 | case RID_RESTRICT: | |
507 | case RID_ATTRIBUTE: | |
508 | case RID_FRACT: | |
509 | case RID_ACCUM: | |
510 | case RID_SAT: | |
511 | case RID_AUTO_TYPE: | |
512 | return true; | |
513 | default: | |
514 | if (keyword >= RID_FIRST_INT_N | |
515 | && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS | |
516 | && int_n_enabled_p[keyword - RID_FIRST_INT_N]) | |
517 | return true; | |
518 | return false; | |
519 | } | |
520 | } | |
521 | ||
27bf414c JM |
522 | /* Return true if TOKEN can start a type name, |
523 | false otherwise. */ | |
1ee62b92 | 524 | bool |
27bf414c JM |
525 | c_token_starts_typename (c_token *token) |
526 | { | |
527 | switch (token->type) | |
528 | { | |
529 | case CPP_NAME: | |
530 | switch (token->id_kind) | |
531 | { | |
532 | case C_ID_ID: | |
533 | return false; | |
36c5e70a BE |
534 | case C_ID_ADDRSPACE: |
535 | return true; | |
27bf414c JM |
536 | case C_ID_TYPENAME: |
537 | return true; | |
538 | case C_ID_CLASSNAME: | |
539 | gcc_assert (c_dialect_objc ()); | |
540 | return true; | |
541 | default: | |
542 | gcc_unreachable (); | |
543 | } | |
544 | case CPP_KEYWORD: | |
1a4f11c8 | 545 | return c_keyword_starts_typename (token->keyword); |
27bf414c JM |
546 | case CPP_LESS: |
547 | if (c_dialect_objc ()) | |
548 | return true; | |
549 | return false; | |
550 | default: | |
551 | return false; | |
552 | } | |
553 | } | |
554 | ||
555 | /* Return true if the next token from PARSER can start a type name, | |
29ce73cb PB |
556 | false otherwise. LA specifies how to do lookahead in order to |
557 | detect unknown type names. If unsure, pick CLA_PREFER_ID. */ | |
558 | ||
27bf414c | 559 | static inline bool |
29ce73cb | 560 | c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la) |
27bf414c JM |
561 | { |
562 | c_token *token = c_parser_peek_token (parser); | |
29ce73cb PB |
563 | if (c_token_starts_typename (token)) |
564 | return true; | |
565 | ||
566 | /* Try a bit harder to detect an unknown typename. */ | |
567 | if (la != cla_prefer_id | |
568 | && token->type == CPP_NAME | |
569 | && token->id_kind == C_ID_ID | |
570 | ||
571 | /* Do not try too hard when we could have "object in array". */ | |
572 | && !parser->objc_could_be_foreach_context | |
573 | ||
574 | && (la == cla_prefer_type | |
575 | || c_parser_peek_2nd_token (parser)->type == CPP_NAME | |
576 | || c_parser_peek_2nd_token (parser)->type == CPP_MULT) | |
577 | ||
578 | /* Only unknown identifiers. */ | |
579 | && !lookup_name (token->value)) | |
580 | return true; | |
581 | ||
582 | return false; | |
27bf414c JM |
583 | } |
584 | ||
f725e721 PB |
585 | /* Return true if TOKEN is a type qualifier, false otherwise. */ |
586 | static bool | |
587 | c_token_is_qualifier (c_token *token) | |
588 | { | |
589 | switch (token->type) | |
590 | { | |
591 | case CPP_NAME: | |
592 | switch (token->id_kind) | |
593 | { | |
594 | case C_ID_ADDRSPACE: | |
595 | return true; | |
596 | default: | |
597 | return false; | |
598 | } | |
599 | case CPP_KEYWORD: | |
600 | switch (token->keyword) | |
601 | { | |
602 | case RID_CONST: | |
603 | case RID_VOLATILE: | |
604 | case RID_RESTRICT: | |
605 | case RID_ATTRIBUTE: | |
267bac10 | 606 | case RID_ATOMIC: |
f725e721 PB |
607 | return true; |
608 | default: | |
609 | return false; | |
610 | } | |
611 | case CPP_LESS: | |
612 | return false; | |
613 | default: | |
614 | gcc_unreachable (); | |
615 | } | |
616 | } | |
617 | ||
618 | /* Return true if the next token from PARSER is a type qualifier, | |
619 | false otherwise. */ | |
620 | static inline bool | |
621 | c_parser_next_token_is_qualifier (c_parser *parser) | |
622 | { | |
623 | c_token *token = c_parser_peek_token (parser); | |
624 | return c_token_is_qualifier (token); | |
625 | } | |
626 | ||
27bf414c JM |
627 | /* Return true if TOKEN can start declaration specifiers, false |
628 | otherwise. */ | |
629 | static bool | |
630 | c_token_starts_declspecs (c_token *token) | |
631 | { | |
632 | switch (token->type) | |
633 | { | |
634 | case CPP_NAME: | |
635 | switch (token->id_kind) | |
636 | { | |
637 | case C_ID_ID: | |
638 | return false; | |
36c5e70a BE |
639 | case C_ID_ADDRSPACE: |
640 | return true; | |
27bf414c JM |
641 | case C_ID_TYPENAME: |
642 | return true; | |
643 | case C_ID_CLASSNAME: | |
644 | gcc_assert (c_dialect_objc ()); | |
645 | return true; | |
646 | default: | |
647 | gcc_unreachable (); | |
648 | } | |
649 | case CPP_KEYWORD: | |
650 | switch (token->keyword) | |
651 | { | |
652 | case RID_STATIC: | |
653 | case RID_EXTERN: | |
654 | case RID_REGISTER: | |
655 | case RID_TYPEDEF: | |
656 | case RID_INLINE: | |
bbceee64 | 657 | case RID_NORETURN: |
27bf414c JM |
658 | case RID_AUTO: |
659 | case RID_THREAD: | |
660 | case RID_UNSIGNED: | |
661 | case RID_LONG: | |
662 | case RID_SHORT: | |
663 | case RID_SIGNED: | |
664 | case RID_COMPLEX: | |
665 | case RID_INT: | |
666 | case RID_CHAR: | |
667 | case RID_FLOAT: | |
668 | case RID_DOUBLE: | |
669 | case RID_VOID: | |
9a8ce21f JG |
670 | case RID_DFLOAT32: |
671 | case RID_DFLOAT64: | |
672 | case RID_DFLOAT128: | |
c65699ef | 673 | CASE_RID_FLOATN_NX: |
27bf414c JM |
674 | case RID_BOOL: |
675 | case RID_ENUM: | |
676 | case RID_STRUCT: | |
677 | case RID_UNION: | |
678 | case RID_TYPEOF: | |
679 | case RID_CONST: | |
680 | case RID_VOLATILE: | |
681 | case RID_RESTRICT: | |
682 | case RID_ATTRIBUTE: | |
ab22c1fa CF |
683 | case RID_FRACT: |
684 | case RID_ACCUM: | |
685 | case RID_SAT: | |
d19fa6b5 | 686 | case RID_ALIGNAS: |
267bac10 | 687 | case RID_ATOMIC: |
38b7bc7f | 688 | case RID_AUTO_TYPE: |
27bf414c JM |
689 | return true; |
690 | default: | |
78a7c317 DD |
691 | if (token->keyword >= RID_FIRST_INT_N |
692 | && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS | |
693 | && int_n_enabled_p[token->keyword - RID_FIRST_INT_N]) | |
694 | return true; | |
27bf414c JM |
695 | return false; |
696 | } | |
697 | case CPP_LESS: | |
698 | if (c_dialect_objc ()) | |
699 | return true; | |
700 | return false; | |
701 | default: | |
702 | return false; | |
703 | } | |
704 | } | |
705 | ||
32912286 JM |
706 | |
707 | /* Return true if TOKEN can start declaration specifiers or a static | |
708 | assertion, false otherwise. */ | |
709 | static bool | |
710 | c_token_starts_declaration (c_token *token) | |
711 | { | |
712 | if (c_token_starts_declspecs (token) | |
713 | || token->keyword == RID_STATIC_ASSERT) | |
714 | return true; | |
715 | else | |
716 | return false; | |
717 | } | |
718 | ||
27bf414c JM |
719 | /* Return true if the next token from PARSER can start declaration |
720 | specifiers, false otherwise. */ | |
1ee62b92 | 721 | bool |
27bf414c JM |
722 | c_parser_next_token_starts_declspecs (c_parser *parser) |
723 | { | |
724 | c_token *token = c_parser_peek_token (parser); | |
bede2adc NP |
725 | |
726 | /* In Objective-C, a classname normally starts a declspecs unless it | |
727 | is immediately followed by a dot. In that case, it is the | |
728 | Objective-C 2.0 "dot-syntax" for class objects, ie, calls the | |
729 | setter/getter on the class. c_token_starts_declspecs() can't | |
730 | differentiate between the two cases because it only checks the | |
731 | current token, so we have a special check here. */ | |
732 | if (c_dialect_objc () | |
733 | && token->type == CPP_NAME | |
734 | && token->id_kind == C_ID_CLASSNAME | |
735 | && c_parser_peek_2nd_token (parser)->type == CPP_DOT) | |
736 | return false; | |
737 | ||
27bf414c JM |
738 | return c_token_starts_declspecs (token); |
739 | } | |
740 | ||
2f413185 | 741 | /* Return true if the next tokens from PARSER can start declaration |
32912286 | 742 | specifiers or a static assertion, false otherwise. */ |
1ee62b92 | 743 | bool |
2f413185 | 744 | c_parser_next_tokens_start_declaration (c_parser *parser) |
32912286 JM |
745 | { |
746 | c_token *token = c_parser_peek_token (parser); | |
bede2adc NP |
747 | |
748 | /* Same as above. */ | |
749 | if (c_dialect_objc () | |
750 | && token->type == CPP_NAME | |
751 | && token->id_kind == C_ID_CLASSNAME | |
752 | && c_parser_peek_2nd_token (parser)->type == CPP_DOT) | |
753 | return false; | |
754 | ||
2f413185 PB |
755 | /* Labels do not start declarations. */ |
756 | if (token->type == CPP_NAME | |
757 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
758 | return false; | |
759 | ||
760 | if (c_token_starts_declaration (token)) | |
761 | return true; | |
762 | ||
29ce73cb | 763 | if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl)) |
2f413185 PB |
764 | return true; |
765 | ||
766 | return false; | |
32912286 JM |
767 | } |
768 | ||
27bf414c JM |
769 | /* Consume the next token from PARSER. */ |
770 | ||
1ee62b92 | 771 | void |
27bf414c JM |
772 | c_parser_consume_token (c_parser *parser) |
773 | { | |
bc4071dd RH |
774 | gcc_assert (parser->tokens_avail >= 1); |
775 | gcc_assert (parser->tokens[0].type != CPP_EOF); | |
776 | gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL); | |
777 | gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA); | |
8139a48e | 778 | parser->last_token_location = parser->tokens[0].location; |
acf0174b JJ |
779 | if (parser->tokens != &parser->tokens_buf[0]) |
780 | parser->tokens++; | |
781 | else if (parser->tokens_avail == 2) | |
27bf414c | 782 | parser->tokens[0] = parser->tokens[1]; |
27bf414c JM |
783 | parser->tokens_avail--; |
784 | } | |
785 | ||
bc4071dd RH |
786 | /* Expect the current token to be a #pragma. Consume it and remember |
787 | that we've begun parsing a pragma. */ | |
788 | ||
789 | static void | |
790 | c_parser_consume_pragma (c_parser *parser) | |
791 | { | |
792 | gcc_assert (!parser->in_pragma); | |
793 | gcc_assert (parser->tokens_avail >= 1); | |
794 | gcc_assert (parser->tokens[0].type == CPP_PRAGMA); | |
acf0174b JJ |
795 | if (parser->tokens != &parser->tokens_buf[0]) |
796 | parser->tokens++; | |
797 | else if (parser->tokens_avail == 2) | |
bc4071dd RH |
798 | parser->tokens[0] = parser->tokens[1]; |
799 | parser->tokens_avail--; | |
800 | parser->in_pragma = true; | |
801 | } | |
802 | ||
8400e75e | 803 | /* Update the global input_location from TOKEN. */ |
27bf414c JM |
804 | static inline void |
805 | c_parser_set_source_position_from_token (c_token *token) | |
806 | { | |
807 | if (token->type != CPP_EOF) | |
808 | { | |
809 | input_location = token->location; | |
27bf414c JM |
810 | } |
811 | } | |
812 | ||
de67c4c3 DM |
813 | /* Helper function for c_parser_error. |
814 | Having peeked a token of kind TOK1_KIND that might signify | |
815 | a conflict marker, peek successor tokens to determine | |
816 | if we actually do have a conflict marker. | |
817 | Specifically, we consider a run of 7 '<', '=' or '>' characters | |
818 | at the start of a line as a conflict marker. | |
819 | These come through the lexer as three pairs and a single, | |
820 | e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<'). | |
821 | If it returns true, *OUT_LOC is written to with the location/range | |
822 | of the marker. */ | |
823 | ||
824 | static bool | |
825 | c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind, | |
826 | location_t *out_loc) | |
827 | { | |
828 | c_token *token2 = c_parser_peek_2nd_token (parser); | |
829 | if (token2->type != tok1_kind) | |
830 | return false; | |
831 | c_token *token3 = c_parser_peek_nth_token (parser, 3); | |
832 | if (token3->type != tok1_kind) | |
833 | return false; | |
834 | c_token *token4 = c_parser_peek_nth_token (parser, 4); | |
835 | if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind)) | |
836 | return false; | |
837 | ||
838 | /* It must be at the start of the line. */ | |
839 | location_t start_loc = c_parser_peek_token (parser)->location; | |
840 | if (LOCATION_COLUMN (start_loc) != 1) | |
841 | return false; | |
842 | ||
843 | /* We have a conflict marker. Construct a location of the form: | |
844 | <<<<<<< | |
845 | ^~~~~~~ | |
846 | with start == caret, finishing at the end of the marker. */ | |
847 | location_t finish_loc = get_finish (token4->location); | |
848 | *out_loc = make_location (start_loc, start_loc, finish_loc); | |
849 | ||
850 | return true; | |
851 | } | |
852 | ||
27bf414c JM |
853 | /* Issue a diagnostic of the form |
854 | FILE:LINE: MESSAGE before TOKEN | |
855 | where TOKEN is the next token in the input stream of PARSER. | |
856 | MESSAGE (specified by the caller) is usually of the form "expected | |
857 | OTHER-TOKEN". | |
858 | ||
32129a17 DM |
859 | Use RICHLOC as the location of the diagnostic. |
860 | ||
27bf414c JM |
861 | Do not issue a diagnostic if still recovering from an error. |
862 | ||
32129a17 DM |
863 | Return true iff an error was actually emitted. |
864 | ||
27bf414c JM |
865 | ??? This is taken from the C++ parser, but building up messages in |
866 | this way is not i18n-friendly and some other approach should be | |
867 | used. */ | |
868 | ||
32129a17 DM |
869 | static bool |
870 | c_parser_error_richloc (c_parser *parser, const char *gmsgid, | |
871 | rich_location *richloc) | |
27bf414c JM |
872 | { |
873 | c_token *token = c_parser_peek_token (parser); | |
874 | if (parser->error) | |
32129a17 | 875 | return false; |
27bf414c | 876 | parser->error = true; |
4b794eaf | 877 | if (!gmsgid) |
32129a17 | 878 | return false; |
de67c4c3 DM |
879 | |
880 | /* If this is actually a conflict marker, report it as such. */ | |
881 | if (token->type == CPP_LSHIFT | |
882 | || token->type == CPP_RSHIFT | |
883 | || token->type == CPP_EQ_EQ) | |
884 | { | |
885 | location_t loc; | |
886 | if (c_parser_peek_conflict_marker (parser, token->type, &loc)) | |
887 | { | |
888 | error_at (loc, "version control conflict marker in file"); | |
32129a17 | 889 | return true; |
de67c4c3 DM |
890 | } |
891 | } | |
892 | ||
4b794eaf | 893 | c_parse_error (gmsgid, |
27bf414c JM |
894 | /* Because c_parse_error does not understand |
895 | CPP_KEYWORD, keywords are treated like | |
896 | identifiers. */ | |
897 | (token->type == CPP_KEYWORD ? CPP_NAME : token->type), | |
cfc93532 MLI |
898 | /* ??? The C parser does not save the cpp flags of a |
899 | token, we need to pass 0 here and we will not get | |
900 | the source spelling of some tokens but rather the | |
901 | canonical spelling. */ | |
32129a17 DM |
902 | token->value, /*flags=*/0, richloc); |
903 | return true; | |
904 | } | |
905 | ||
906 | /* As c_parser_error_richloc, but issue the message at the | |
907 | location of PARSER's next token, or at input_location | |
908 | if the next token is EOF. */ | |
909 | ||
910 | bool | |
911 | c_parser_error (c_parser *parser, const char *gmsgid) | |
912 | { | |
913 | c_token *token = c_parser_peek_token (parser); | |
914 | c_parser_set_source_position_from_token (token); | |
915 | rich_location richloc (line_table, input_location); | |
916 | return c_parser_error_richloc (parser, gmsgid, &richloc); | |
917 | } | |
918 | ||
919 | /* Some tokens naturally come in pairs e.g.'(' and ')'. | |
920 | This class is for tracking such a matching pair of symbols. | |
921 | In particular, it tracks the location of the first token, | |
922 | so that if the second token is missing, we can highlight the | |
923 | location of the first token when notifying the user about the | |
924 | problem. */ | |
925 | ||
926 | template <typename traits_t> | |
927 | class token_pair | |
928 | { | |
929 | public: | |
930 | /* token_pair's ctor. */ | |
931 | token_pair () : m_open_loc (UNKNOWN_LOCATION) {} | |
932 | ||
933 | /* If the next token is the opening symbol for this pair, consume it and | |
934 | return true. | |
935 | Otherwise, issue an error and return false. | |
936 | In either case, record the location of the opening token. */ | |
937 | ||
938 | bool require_open (c_parser *parser) | |
939 | { | |
940 | c_token *token = c_parser_peek_token (parser); | |
941 | if (token) | |
942 | m_open_loc = token->location; | |
943 | ||
944 | return c_parser_require (parser, traits_t::open_token_type, | |
945 | traits_t::open_gmsgid); | |
946 | } | |
947 | ||
948 | /* Consume the next token from PARSER, recording its location as | |
949 | that of the opening token within the pair. */ | |
950 | ||
951 | void consume_open (c_parser *parser) | |
952 | { | |
953 | c_token *token = c_parser_peek_token (parser); | |
954 | gcc_assert (token->type == traits_t::open_token_type); | |
955 | m_open_loc = token->location; | |
956 | c_parser_consume_token (parser); | |
957 | } | |
958 | ||
959 | /* If the next token is the closing symbol for this pair, consume it | |
960 | and return true. | |
961 | Otherwise, issue an error, highlighting the location of the | |
962 | corresponding opening token, and return false. */ | |
963 | ||
964 | bool require_close (c_parser *parser) const | |
965 | { | |
966 | return c_parser_require (parser, traits_t::close_token_type, | |
967 | traits_t::close_gmsgid, m_open_loc); | |
968 | } | |
969 | ||
970 | /* Like token_pair::require_close, except that tokens will be skipped | |
971 | until the desired token is found. An error message is still produced | |
972 | if the next token is not as expected. */ | |
973 | ||
974 | void skip_until_found_close (c_parser *parser) const | |
975 | { | |
976 | c_parser_skip_until_found (parser, traits_t::close_token_type, | |
977 | traits_t::close_gmsgid, m_open_loc); | |
978 | } | |
979 | ||
980 | private: | |
981 | location_t m_open_loc; | |
982 | }; | |
983 | ||
984 | /* Traits for token_pair<T> for tracking matching pairs of parentheses. */ | |
985 | ||
986 | struct matching_paren_traits | |
987 | { | |
988 | static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; | |
989 | static const char * const open_gmsgid; | |
990 | static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; | |
991 | static const char * const close_gmsgid; | |
992 | }; | |
993 | ||
994 | const char * const matching_paren_traits::open_gmsgid = "expected %<(%>"; | |
995 | const char * const matching_paren_traits::close_gmsgid = "expected %<)%>"; | |
996 | ||
997 | /* "matching_parens" is a token_pair<T> class for tracking matching | |
998 | pairs of parentheses. */ | |
999 | ||
1000 | typedef token_pair<matching_paren_traits> matching_parens; | |
1001 | ||
1002 | /* Traits for token_pair<T> for tracking matching pairs of braces. */ | |
1003 | ||
1004 | struct matching_brace_traits | |
1005 | { | |
1006 | static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; | |
1007 | static const char * const open_gmsgid; | |
1008 | static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; | |
1009 | static const char * const close_gmsgid; | |
1010 | }; | |
1011 | ||
1012 | const char * const matching_brace_traits::open_gmsgid = "expected %<{%>"; | |
1013 | const char * const matching_brace_traits::close_gmsgid = "expected %<}%>"; | |
1014 | ||
1015 | /* "matching_braces" is a token_pair<T> class for tracking matching | |
1016 | pairs of braces. */ | |
1017 | ||
1018 | typedef token_pair<matching_brace_traits> matching_braces; | |
1019 | ||
1020 | /* Get a description of the matching symbol to TYPE e.g. "(" for | |
1021 | CPP_CLOSE_PAREN. */ | |
1022 | ||
1023 | static const char * | |
1024 | get_matching_symbol (enum cpp_ttype type) | |
1025 | { | |
1026 | switch (type) | |
1027 | { | |
1028 | default: | |
1029 | gcc_unreachable (); | |
1030 | return ""; | |
1031 | case CPP_CLOSE_PAREN: | |
1032 | return "("; | |
1033 | case CPP_CLOSE_BRACE: | |
1034 | return "{"; | |
1035 | } | |
27bf414c JM |
1036 | } |
1037 | ||
1038 | /* If the next token is of the indicated TYPE, consume it. Otherwise, | |
1039 | issue the error MSGID. If MSGID is NULL then a message has already | |
1040 | been produced and no message will be produced this time. Returns | |
32129a17 DM |
1041 | true if found, false otherwise. |
1042 | ||
1043 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it | |
1044 | within any error as the location of an "opening" token matching | |
1045 | the close token TYPE (e.g. the location of the '(' when TYPE is | |
62e1c678 DM |
1046 | CPP_CLOSE_PAREN). |
1047 | ||
1048 | If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly | |
1049 | one type (e.g. "expected %<)%>") and thus it may be reasonable to | |
1050 | attempt to generate a fix-it hint for the problem. | |
1051 | Otherwise msgid describes multiple token types (e.g. | |
1052 | "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to | |
1053 | generate a fix-it hint. */ | |
27bf414c | 1054 | |
1ee62b92 | 1055 | bool |
27bf414c JM |
1056 | c_parser_require (c_parser *parser, |
1057 | enum cpp_ttype type, | |
32129a17 | 1058 | const char *msgid, |
62e1c678 DM |
1059 | location_t matching_location, |
1060 | bool type_is_unique) | |
27bf414c JM |
1061 | { |
1062 | if (c_parser_next_token_is (parser, type)) | |
1063 | { | |
1064 | c_parser_consume_token (parser); | |
1065 | return true; | |
1066 | } | |
1067 | else | |
1068 | { | |
32129a17 DM |
1069 | location_t next_token_loc = c_parser_peek_token (parser)->location; |
1070 | gcc_rich_location richloc (next_token_loc); | |
1071 | ||
62e1c678 DM |
1072 | /* Potentially supply a fix-it hint, suggesting to add the |
1073 | missing token immediately after the *previous* token. | |
1074 | This may move the primary location within richloc. */ | |
1075 | if (!parser->error && type_is_unique) | |
1076 | maybe_suggest_missing_token_insertion (&richloc, type, | |
1077 | parser->last_token_location); | |
1078 | ||
32129a17 DM |
1079 | /* If matching_location != UNKNOWN_LOCATION, highlight it. |
1080 | Attempt to consolidate diagnostics by printing it as a | |
1081 | secondary range within the main diagnostic. */ | |
1082 | bool added_matching_location = false; | |
1083 | if (matching_location != UNKNOWN_LOCATION) | |
1084 | added_matching_location | |
1085 | = richloc.add_location_if_nearby (matching_location); | |
1086 | ||
1087 | if (c_parser_error_richloc (parser, msgid, &richloc)) | |
1088 | /* If we weren't able to consolidate matching_location, then | |
1089 | print it as a secondary diagnostic. */ | |
1090 | if (matching_location != UNKNOWN_LOCATION && !added_matching_location) | |
1091 | inform (matching_location, "to match this %qs", | |
1092 | get_matching_symbol (type)); | |
1093 | ||
27bf414c JM |
1094 | return false; |
1095 | } | |
1096 | } | |
1097 | ||
1098 | /* If the next token is the indicated keyword, consume it. Otherwise, | |
1099 | issue the error MSGID. Returns true if found, false otherwise. */ | |
1100 | ||
1101 | static bool | |
1102 | c_parser_require_keyword (c_parser *parser, | |
1103 | enum rid keyword, | |
1104 | const char *msgid) | |
1105 | { | |
1106 | if (c_parser_next_token_is_keyword (parser, keyword)) | |
1107 | { | |
1108 | c_parser_consume_token (parser); | |
1109 | return true; | |
1110 | } | |
1111 | else | |
1112 | { | |
1113 | c_parser_error (parser, msgid); | |
1114 | return false; | |
1115 | } | |
1116 | } | |
1117 | ||
1118 | /* Like c_parser_require, except that tokens will be skipped until the | |
1119 | desired token is found. An error message is still produced if the | |
1120 | next token is not as expected. If MSGID is NULL then a message has | |
1121 | already been produced and no message will be produced this | |
32129a17 DM |
1122 | time. |
1123 | ||
1124 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it | |
1125 | within any error as the location of an "opening" token matching | |
1126 | the close token TYPE (e.g. the location of the '(' when TYPE is | |
1127 | CPP_CLOSE_PAREN). */ | |
27bf414c | 1128 | |
1ee62b92 | 1129 | void |
27bf414c JM |
1130 | c_parser_skip_until_found (c_parser *parser, |
1131 | enum cpp_ttype type, | |
32129a17 DM |
1132 | const char *msgid, |
1133 | location_t matching_location) | |
27bf414c JM |
1134 | { |
1135 | unsigned nesting_depth = 0; | |
1136 | ||
32129a17 | 1137 | if (c_parser_require (parser, type, msgid, matching_location)) |
27bf414c JM |
1138 | return; |
1139 | ||
1140 | /* Skip tokens until the desired token is found. */ | |
1141 | while (true) | |
1142 | { | |
1143 | /* Peek at the next token. */ | |
1144 | c_token *token = c_parser_peek_token (parser); | |
1145 | /* If we've reached the token we want, consume it and stop. */ | |
1146 | if (token->type == type && !nesting_depth) | |
1147 | { | |
1148 | c_parser_consume_token (parser); | |
1149 | break; | |
1150 | } | |
bc4071dd | 1151 | |
27bf414c JM |
1152 | /* If we've run out of tokens, stop. */ |
1153 | if (token->type == CPP_EOF) | |
1154 | return; | |
bc4071dd RH |
1155 | if (token->type == CPP_PRAGMA_EOL && parser->in_pragma) |
1156 | return; | |
27bf414c JM |
1157 | if (token->type == CPP_OPEN_BRACE |
1158 | || token->type == CPP_OPEN_PAREN | |
1159 | || token->type == CPP_OPEN_SQUARE) | |
1160 | ++nesting_depth; | |
1161 | else if (token->type == CPP_CLOSE_BRACE | |
1162 | || token->type == CPP_CLOSE_PAREN | |
1163 | || token->type == CPP_CLOSE_SQUARE) | |
1164 | { | |
1165 | if (nesting_depth-- == 0) | |
1166 | break; | |
1167 | } | |
1168 | /* Consume this token. */ | |
1169 | c_parser_consume_token (parser); | |
1170 | } | |
1171 | parser->error = false; | |
1172 | } | |
1173 | ||
1174 | /* Skip tokens until the end of a parameter is found, but do not | |
1175 | consume the comma, semicolon or closing delimiter. */ | |
1176 | ||
1177 | static void | |
1178 | c_parser_skip_to_end_of_parameter (c_parser *parser) | |
1179 | { | |
1180 | unsigned nesting_depth = 0; | |
1181 | ||
1182 | while (true) | |
1183 | { | |
1184 | c_token *token = c_parser_peek_token (parser); | |
1185 | if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON) | |
1186 | && !nesting_depth) | |
1187 | break; | |
1188 | /* If we've run out of tokens, stop. */ | |
1189 | if (token->type == CPP_EOF) | |
1190 | return; | |
bc4071dd RH |
1191 | if (token->type == CPP_PRAGMA_EOL && parser->in_pragma) |
1192 | return; | |
27bf414c JM |
1193 | if (token->type == CPP_OPEN_BRACE |
1194 | || token->type == CPP_OPEN_PAREN | |
1195 | || token->type == CPP_OPEN_SQUARE) | |
1196 | ++nesting_depth; | |
1197 | else if (token->type == CPP_CLOSE_BRACE | |
1198 | || token->type == CPP_CLOSE_PAREN | |
1199 | || token->type == CPP_CLOSE_SQUARE) | |
1200 | { | |
1201 | if (nesting_depth-- == 0) | |
1202 | break; | |
1203 | } | |
1204 | /* Consume this token. */ | |
1205 | c_parser_consume_token (parser); | |
1206 | } | |
1207 | parser->error = false; | |
1208 | } | |
1209 | ||
bc4071dd RH |
1210 | /* Expect to be at the end of the pragma directive and consume an |
1211 | end of line marker. */ | |
1212 | ||
1213 | static void | |
62021f64 | 1214 | c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true) |
bc4071dd RH |
1215 | { |
1216 | gcc_assert (parser->in_pragma); | |
1217 | parser->in_pragma = false; | |
1218 | ||
62021f64 TB |
1219 | if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL) |
1220 | c_parser_error (parser, "expected end of line"); | |
1221 | ||
1222 | cpp_ttype token_type; | |
1223 | do | |
1224 | { | |
1225 | c_token *token = c_parser_peek_token (parser); | |
1226 | token_type = token->type; | |
1227 | if (token_type == CPP_EOF) | |
1228 | break; | |
1229 | c_parser_consume_token (parser); | |
1230 | } | |
1231 | while (token_type != CPP_PRAGMA_EOL); | |
bc4071dd RH |
1232 | |
1233 | parser->error = false; | |
1234 | } | |
27bf414c | 1235 | |
2a83cc52 RH |
1236 | /* Skip tokens until we have consumed an entire block, or until we |
1237 | have consumed a non-nested ';'. */ | |
1238 | ||
1239 | static void | |
1240 | c_parser_skip_to_end_of_block_or_statement (c_parser *parser) | |
1241 | { | |
1242 | unsigned nesting_depth = 0; | |
1243 | bool save_error = parser->error; | |
1244 | ||
1245 | while (true) | |
1246 | { | |
1247 | c_token *token; | |
1248 | ||
1249 | /* Peek at the next token. */ | |
1250 | token = c_parser_peek_token (parser); | |
1251 | ||
1252 | switch (token->type) | |
1253 | { | |
1254 | case CPP_EOF: | |
1255 | return; | |
1256 | ||
1257 | case CPP_PRAGMA_EOL: | |
1258 | if (parser->in_pragma) | |
1259 | return; | |
1260 | break; | |
1261 | ||
1262 | case CPP_SEMICOLON: | |
1263 | /* If the next token is a ';', we have reached the | |
1264 | end of the statement. */ | |
1265 | if (!nesting_depth) | |
1266 | { | |
1267 | /* Consume the ';'. */ | |
1268 | c_parser_consume_token (parser); | |
1269 | goto finished; | |
1270 | } | |
1271 | break; | |
1272 | ||
1273 | case CPP_CLOSE_BRACE: | |
1274 | /* If the next token is a non-nested '}', then we have | |
1275 | reached the end of the current block. */ | |
1276 | if (nesting_depth == 0 || --nesting_depth == 0) | |
1277 | { | |
1278 | c_parser_consume_token (parser); | |
1279 | goto finished; | |
1280 | } | |
1281 | break; | |
1282 | ||
1283 | case CPP_OPEN_BRACE: | |
1284 | /* If it the next token is a '{', then we are entering a new | |
1285 | block. Consume the entire block. */ | |
1286 | ++nesting_depth; | |
1287 | break; | |
1288 | ||
1289 | case CPP_PRAGMA: | |
1290 | /* If we see a pragma, consume the whole thing at once. We | |
1291 | have some safeguards against consuming pragmas willy-nilly. | |
1292 | Normally, we'd expect to be here with parser->error set, | |
1293 | which disables these safeguards. But it's possible to get | |
1294 | here for secondary error recovery, after parser->error has | |
1295 | been cleared. */ | |
1296 | c_parser_consume_pragma (parser); | |
1297 | c_parser_skip_to_pragma_eol (parser); | |
1298 | parser->error = save_error; | |
1299 | continue; | |
9e33de05 RS |
1300 | |
1301 | default: | |
1302 | break; | |
2a83cc52 RH |
1303 | } |
1304 | ||
1305 | c_parser_consume_token (parser); | |
1306 | } | |
1307 | ||
1308 | finished: | |
1309 | parser->error = false; | |
1310 | } | |
1311 | ||
d2e796ad MLI |
1312 | /* CPP's options (initialized by c-opts.c). */ |
1313 | extern cpp_options *cpp_opts; | |
1314 | ||
27bf414c JM |
1315 | /* Save the warning flags which are controlled by __extension__. */ |
1316 | ||
1317 | static inline int | |
1318 | disable_extension_diagnostics (void) | |
1319 | { | |
1320 | int ret = (pedantic | |
1321 | | (warn_pointer_arith << 1) | |
1322 | | (warn_traditional << 2) | |
d2e796ad | 1323 | | (flag_iso << 3) |
24b97832 | 1324 | | (warn_long_long << 4) |
b3ab9ea2 | 1325 | | (warn_cxx_compat << 5) |
f3bede71 | 1326 | | (warn_overlength_strings << 6) |
177cce46 MP |
1327 | /* warn_c90_c99_compat has three states: -1/0/1, so we must |
1328 | play tricks to properly restore it. */ | |
1329 | | ((warn_c90_c99_compat == 1) << 7) | |
35aff4fb MP |
1330 | | ((warn_c90_c99_compat == -1) << 8) |
1331 | /* Similarly for warn_c99_c11_compat. */ | |
1332 | | ((warn_c99_c11_compat == 1) << 9) | |
1333 | | ((warn_c99_c11_compat == -1) << 10) | |
1334 | ); | |
e3339d0f | 1335 | cpp_opts->cpp_pedantic = pedantic = 0; |
27bf414c | 1336 | warn_pointer_arith = 0; |
e3339d0f | 1337 | cpp_opts->cpp_warn_traditional = warn_traditional = 0; |
27bf414c | 1338 | flag_iso = 0; |
e3339d0f | 1339 | cpp_opts->cpp_warn_long_long = warn_long_long = 0; |
24b97832 | 1340 | warn_cxx_compat = 0; |
b3ab9ea2 | 1341 | warn_overlength_strings = 0; |
f3bede71 | 1342 | warn_c90_c99_compat = 0; |
35aff4fb | 1343 | warn_c99_c11_compat = 0; |
27bf414c JM |
1344 | return ret; |
1345 | } | |
1346 | ||
1347 | /* Restore the warning flags which are controlled by __extension__. | |
1348 | FLAGS is the return value from disable_extension_diagnostics. */ | |
1349 | ||
1350 | static inline void | |
1351 | restore_extension_diagnostics (int flags) | |
1352 | { | |
e3339d0f | 1353 | cpp_opts->cpp_pedantic = pedantic = flags & 1; |
27bf414c | 1354 | warn_pointer_arith = (flags >> 1) & 1; |
e3339d0f | 1355 | cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1; |
27bf414c | 1356 | flag_iso = (flags >> 3) & 1; |
e3339d0f | 1357 | cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1; |
24b97832 | 1358 | warn_cxx_compat = (flags >> 5) & 1; |
b3ab9ea2 | 1359 | warn_overlength_strings = (flags >> 6) & 1; |
177cce46 MP |
1360 | /* See above for why is this needed. */ |
1361 | warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0); | |
35aff4fb | 1362 | warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0); |
27bf414c JM |
1363 | } |
1364 | ||
0b212d8c TS |
1365 | /* Helper data structure for parsing #pragma acc routine. */ |
1366 | struct oacc_routine_data { | |
ae9281fc TS |
1367 | bool error_seen; /* Set if error has been reported. */ |
1368 | bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */ | |
0b212d8c TS |
1369 | tree clauses; |
1370 | location_t loc; | |
1371 | }; | |
1372 | ||
27bf414c JM |
1373 | static void c_parser_external_declaration (c_parser *); |
1374 | static void c_parser_asm_definition (c_parser *); | |
32912286 | 1375 | static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, |
3a40d81d | 1376 | bool, bool, tree *, vec<c_token>, |
81fea426 MP |
1377 | struct oacc_routine_data * = NULL, |
1378 | bool * = NULL); | |
32912286 JM |
1379 | static void c_parser_static_assert_declaration_no_semi (c_parser *); |
1380 | static void c_parser_static_assert_declaration (c_parser *); | |
27bf414c JM |
1381 | static struct c_typespec c_parser_enum_specifier (c_parser *); |
1382 | static struct c_typespec c_parser_struct_or_union_specifier (c_parser *); | |
1383 | static tree c_parser_struct_declaration (c_parser *); | |
1384 | static struct c_typespec c_parser_typeof_specifier (c_parser *); | |
d19fa6b5 | 1385 | static tree c_parser_alignas_specifier (c_parser *); |
27bf414c JM |
1386 | static struct c_declarator *c_parser_direct_declarator (c_parser *, bool, |
1387 | c_dtr_syn, bool *); | |
1388 | static struct c_declarator *c_parser_direct_declarator_inner (c_parser *, | |
1389 | bool, | |
1390 | struct c_declarator *); | |
1391 | static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree); | |
a04a722b JM |
1392 | static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree, |
1393 | tree); | |
27bf414c JM |
1394 | static struct c_parm *c_parser_parameter_declaration (c_parser *, tree); |
1395 | static tree c_parser_simple_asm_expr (c_parser *); | |
1396 | static tree c_parser_attributes (c_parser *); | |
27bf414c | 1397 | static struct c_expr c_parser_initializer (c_parser *); |
16595a1f BS |
1398 | static struct c_expr c_parser_braced_init (c_parser *, tree, bool, |
1399 | struct obstack *); | |
a1e3b3d9 LB |
1400 | static void c_parser_initelt (c_parser *, struct obstack *); |
1401 | static void c_parser_initval (c_parser *, struct c_expr *, | |
1402 | struct obstack *); | |
27bf414c JM |
1403 | static tree c_parser_compound_statement (c_parser *); |
1404 | static void c_parser_compound_statement_nostart (c_parser *); | |
1405 | static void c_parser_label (c_parser *); | |
3e2becc4 | 1406 | static void c_parser_statement (c_parser *, bool *, location_t * = NULL); |
99cd9857 MP |
1407 | static void c_parser_statement_after_labels (c_parser *, bool *, |
1408 | vec<tree> * = NULL); | |
3e2becc4 MP |
1409 | static tree c_parser_c99_block_statement (c_parser *, bool *, |
1410 | location_t * = NULL); | |
99cd9857 | 1411 | static void c_parser_if_statement (c_parser *, bool *, vec<tree> *); |
351f85c5 | 1412 | static void c_parser_switch_statement (c_parser *, bool *); |
99cd9857 | 1413 | static void c_parser_while_statement (c_parser *, bool, bool *); |
d4af74d4 | 1414 | static void c_parser_do_statement (c_parser *, bool); |
99cd9857 | 1415 | static void c_parser_for_statement (c_parser *, bool, bool *); |
27bf414c | 1416 | static tree c_parser_asm_statement (c_parser *); |
eadd3d0d | 1417 | static tree c_parser_asm_operands (c_parser *); |
1c384bf1 | 1418 | static tree c_parser_asm_goto_operands (c_parser *); |
27bf414c | 1419 | static tree c_parser_asm_clobbers (c_parser *); |
acf0174b JJ |
1420 | static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *, |
1421 | tree = NULL_TREE); | |
27bf414c | 1422 | static struct c_expr c_parser_conditional_expression (c_parser *, |
acf0174b | 1423 | struct c_expr *, tree); |
20906c66 | 1424 | static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *, |
acf0174b | 1425 | tree); |
27bf414c JM |
1426 | static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *); |
1427 | static struct c_expr c_parser_unary_expression (c_parser *); | |
1428 | static struct c_expr c_parser_sizeof_expression (c_parser *); | |
1429 | static struct c_expr c_parser_alignof_expression (c_parser *); | |
1430 | static struct c_expr c_parser_postfix_expression (c_parser *); | |
1431 | static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *, | |
24b97832 ILT |
1432 | struct c_type_name *, |
1433 | location_t); | |
27bf414c | 1434 | static struct c_expr c_parser_postfix_expression_after_primary (c_parser *, |
c2255bc4 | 1435 | location_t loc, |
27bf414c | 1436 | struct c_expr); |
0a35513e AH |
1437 | static tree c_parser_transaction (c_parser *, enum rid); |
1438 | static struct c_expr c_parser_transaction_expression (c_parser *, enum rid); | |
1439 | static tree c_parser_transaction_cancel (c_parser *); | |
27bf414c | 1440 | static struct c_expr c_parser_expression (c_parser *); |
46bdb9cf | 1441 | static struct c_expr c_parser_expression_conv (c_parser *); |
9771b263 DN |
1442 | static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool, |
1443 | vec<tree, va_gc> **, location_t *, | |
b108f48f JJ |
1444 | tree *, vec<location_t> *, |
1445 | unsigned int * = NULL); | |
6e232ba4 | 1446 | static void c_parser_oacc_declare (c_parser *); |
41dbbb37 TS |
1447 | static void c_parser_oacc_enter_exit_data (c_parser *, bool); |
1448 | static void c_parser_oacc_update (c_parser *); | |
dda1bf61 | 1449 | static void c_parser_omp_construct (c_parser *, bool *); |
953ff289 DN |
1450 | static void c_parser_omp_threadprivate (c_parser *); |
1451 | static void c_parser_omp_barrier (c_parser *); | |
1452 | static void c_parser_omp_flush (c_parser *); | |
41dbbb37 | 1453 | static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code, |
dda1bf61 | 1454 | tree, tree *, bool *); |
a68ab351 | 1455 | static void c_parser_omp_taskwait (c_parser *); |
20906c66 | 1456 | static void c_parser_omp_taskyield (c_parser *); |
acf0174b | 1457 | static void c_parser_omp_cancel (c_parser *); |
27bf414c | 1458 | |
acf0174b JJ |
1459 | enum pragma_context { pragma_external, pragma_struct, pragma_param, |
1460 | pragma_stmt, pragma_compound }; | |
dda1bf61 | 1461 | static bool c_parser_pragma (c_parser *, enum pragma_context, bool *); |
54d19c3b | 1462 | static void c_parser_omp_cancellation_point (c_parser *, enum pragma_context); |
dda1bf61 | 1463 | static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *); |
acf0174b JJ |
1464 | static void c_parser_omp_end_declare_target (c_parser *); |
1465 | static void c_parser_omp_declare (c_parser *, enum pragma_context); | |
dda1bf61 | 1466 | static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *); |
0b212d8c | 1467 | static void c_parser_oacc_routine (c_parser *, enum pragma_context); |
bc4071dd | 1468 | |
27bf414c JM |
1469 | /* These Objective-C parser functions are only ever called when |
1470 | compiling Objective-C. */ | |
c165dca7 | 1471 | static void c_parser_objc_class_definition (c_parser *, tree); |
27bf414c JM |
1472 | static void c_parser_objc_class_instance_variables (c_parser *); |
1473 | static void c_parser_objc_class_declaration (c_parser *); | |
1474 | static void c_parser_objc_alias_declaration (c_parser *); | |
c165dca7 | 1475 | static void c_parser_objc_protocol_definition (c_parser *, tree); |
249a82c4 | 1476 | static bool c_parser_objc_method_type (c_parser *); |
27bf414c JM |
1477 | static void c_parser_objc_method_definition (c_parser *); |
1478 | static void c_parser_objc_methodprotolist (c_parser *); | |
1479 | static void c_parser_objc_methodproto (c_parser *); | |
a04a722b | 1480 | static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *); |
27bf414c JM |
1481 | static tree c_parser_objc_type_name (c_parser *); |
1482 | static tree c_parser_objc_protocol_refs (c_parser *); | |
437c2322 | 1483 | static void c_parser_objc_try_catch_finally_statement (c_parser *); |
27bf414c JM |
1484 | static void c_parser_objc_synchronized_statement (c_parser *); |
1485 | static tree c_parser_objc_selector (c_parser *); | |
1486 | static tree c_parser_objc_selector_arg (c_parser *); | |
1487 | static tree c_parser_objc_receiver (c_parser *); | |
1488 | static tree c_parser_objc_message_args (c_parser *); | |
1489 | static tree c_parser_objc_keywordexpr (c_parser *); | |
f614132b | 1490 | static void c_parser_objc_at_property_declaration (c_parser *); |
da57d1b9 NP |
1491 | static void c_parser_objc_at_synthesize_declaration (c_parser *); |
1492 | static void c_parser_objc_at_dynamic_declaration (c_parser *); | |
668ea4b1 | 1493 | static bool c_parser_objc_diagnose_bad_element_prefix |
c165dca7 | 1494 | (c_parser *, struct c_declspecs *); |
27bf414c | 1495 | |
c02065fc | 1496 | /* Cilk Plus supporting routines. */ |
dda1bf61 JJ |
1497 | static void c_parser_cilk_simd (c_parser *, bool *); |
1498 | static void c_parser_cilk_for (c_parser *, tree, bool *); | |
c02065fc | 1499 | static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context); |
36536d79 | 1500 | static tree c_parser_array_notation (location_t, c_parser *, tree, tree); |
41958c28 | 1501 | static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); |
dda1bf61 | 1502 | static void c_parser_cilk_grainsize (c_parser *, bool *); |
36536d79 | 1503 | |
c2e84327 DM |
1504 | static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass); |
1505 | ||
31dc71a8 | 1506 | /* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9). |
27bf414c JM |
1507 | |
1508 | translation-unit: | |
1509 | external-declarations | |
1510 | ||
1511 | external-declarations: | |
1512 | external-declaration | |
1513 | external-declarations external-declaration | |
1514 | ||
1515 | GNU extensions: | |
1516 | ||
1517 | translation-unit: | |
1518 | empty | |
1519 | */ | |
1520 | ||
1521 | static void | |
1522 | c_parser_translation_unit (c_parser *parser) | |
1523 | { | |
1524 | if (c_parser_next_token_is (parser, CPP_EOF)) | |
1525 | { | |
c1771a20 | 1526 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 1527 | "ISO C forbids an empty translation unit"); |
27bf414c JM |
1528 | } |
1529 | else | |
1530 | { | |
1531 | void *obstack_position = obstack_alloc (&parser_obstack, 0); | |
6ec637a4 | 1532 | mark_valid_location_for_stdc_pragma (false); |
27bf414c JM |
1533 | do |
1534 | { | |
1535 | ggc_collect (); | |
1536 | c_parser_external_declaration (parser); | |
1537 | obstack_free (&parser_obstack, obstack_position); | |
1538 | } | |
1539 | while (c_parser_next_token_is_not (parser, CPP_EOF)); | |
1540 | } | |
d25c7690 | 1541 | |
13f92e8d JJ |
1542 | unsigned int i; |
1543 | tree decl; | |
1544 | FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl) | |
1545 | if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node) | |
686e2237 | 1546 | error ("storage size of %q+D isn%'t known", decl); |
27bf414c JM |
1547 | } |
1548 | ||
31dc71a8 | 1549 | /* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9). |
27bf414c JM |
1550 | |
1551 | external-declaration: | |
1552 | function-definition | |
1553 | declaration | |
1554 | ||
1555 | GNU extensions: | |
1556 | ||
1557 | external-declaration: | |
1558 | asm-definition | |
1559 | ; | |
1560 | __extension__ external-declaration | |
1561 | ||
1562 | Objective-C: | |
1563 | ||
1564 | external-declaration: | |
1565 | objc-class-definition | |
1566 | objc-class-declaration | |
1567 | objc-alias-declaration | |
1568 | objc-protocol-definition | |
1569 | objc-method-definition | |
1570 | @end | |
1571 | */ | |
1572 | ||
1573 | static void | |
1574 | c_parser_external_declaration (c_parser *parser) | |
1575 | { | |
1576 | int ext; | |
1577 | switch (c_parser_peek_token (parser)->type) | |
1578 | { | |
1579 | case CPP_KEYWORD: | |
1580 | switch (c_parser_peek_token (parser)->keyword) | |
1581 | { | |
1582 | case RID_EXTENSION: | |
1583 | ext = disable_extension_diagnostics (); | |
1584 | c_parser_consume_token (parser); | |
1585 | c_parser_external_declaration (parser); | |
1586 | restore_extension_diagnostics (ext); | |
1587 | break; | |
1588 | case RID_ASM: | |
1589 | c_parser_asm_definition (parser); | |
1590 | break; | |
1591 | case RID_AT_INTERFACE: | |
1592 | case RID_AT_IMPLEMENTATION: | |
1593 | gcc_assert (c_dialect_objc ()); | |
c165dca7 | 1594 | c_parser_objc_class_definition (parser, NULL_TREE); |
27bf414c | 1595 | break; |
49b91f05 | 1596 | case RID_AT_CLASS: |
27bf414c JM |
1597 | gcc_assert (c_dialect_objc ()); |
1598 | c_parser_objc_class_declaration (parser); | |
1599 | break; | |
1600 | case RID_AT_ALIAS: | |
1601 | gcc_assert (c_dialect_objc ()); | |
1602 | c_parser_objc_alias_declaration (parser); | |
1603 | break; | |
1604 | case RID_AT_PROTOCOL: | |
1605 | gcc_assert (c_dialect_objc ()); | |
c165dca7 | 1606 | c_parser_objc_protocol_definition (parser, NULL_TREE); |
27bf414c | 1607 | break; |
668ea4b1 IS |
1608 | case RID_AT_PROPERTY: |
1609 | gcc_assert (c_dialect_objc ()); | |
f614132b | 1610 | c_parser_objc_at_property_declaration (parser); |
668ea4b1 | 1611 | break; |
da57d1b9 NP |
1612 | case RID_AT_SYNTHESIZE: |
1613 | gcc_assert (c_dialect_objc ()); | |
1614 | c_parser_objc_at_synthesize_declaration (parser); | |
1615 | break; | |
1616 | case RID_AT_DYNAMIC: | |
1617 | gcc_assert (c_dialect_objc ()); | |
1618 | c_parser_objc_at_dynamic_declaration (parser); | |
1619 | break; | |
27bf414c JM |
1620 | case RID_AT_END: |
1621 | gcc_assert (c_dialect_objc ()); | |
1622 | c_parser_consume_token (parser); | |
1623 | objc_finish_implementation (); | |
1624 | break; | |
1625 | default: | |
1626 | goto decl_or_fndef; | |
1627 | } | |
1628 | break; | |
1629 | case CPP_SEMICOLON: | |
c1771a20 | 1630 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 1631 | "ISO C does not allow extra %<;%> outside of a function"); |
27bf414c JM |
1632 | c_parser_consume_token (parser); |
1633 | break; | |
bc4071dd | 1634 | case CPP_PRAGMA: |
6ec637a4 | 1635 | mark_valid_location_for_stdc_pragma (true); |
dda1bf61 | 1636 | c_parser_pragma (parser, pragma_external, NULL); |
6ec637a4 | 1637 | mark_valid_location_for_stdc_pragma (false); |
bc4071dd | 1638 | break; |
27bf414c JM |
1639 | case CPP_PLUS: |
1640 | case CPP_MINUS: | |
1641 | if (c_dialect_objc ()) | |
1642 | { | |
1643 | c_parser_objc_method_definition (parser); | |
1644 | break; | |
1645 | } | |
1646 | /* Else fall through, and yield a syntax error trying to parse | |
1647 | as a declaration or function definition. */ | |
191816a3 | 1648 | /* FALLTHRU */ |
27bf414c JM |
1649 | default: |
1650 | decl_or_fndef: | |
c165dca7 IS |
1651 | /* A declaration or a function definition (or, in Objective-C, |
1652 | an @interface or @protocol with prefix attributes). We can | |
1653 | only tell which after parsing the declaration specifiers, if | |
1654 | any, and the first declarator. */ | |
acf0174b JJ |
1655 | c_parser_declaration_or_fndef (parser, true, true, true, false, true, |
1656 | NULL, vNULL); | |
27bf414c JM |
1657 | break; |
1658 | } | |
1659 | } | |
1660 | ||
acf0174b | 1661 | static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>); |
ae9281fc | 1662 | static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); |
acf0174b | 1663 | |
27bf414c | 1664 | /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 |
31dc71a8 MP |
1665 | 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition |
1666 | is accepted; otherwise (old-style parameter declarations) only other | |
32912286 JM |
1667 | declarations are accepted. If STATIC_ASSERT_OK is true, a static |
1668 | assertion is accepted; otherwise (old-style parameter declarations) | |
1669 | it is not. If NESTED is true, we are inside a function or parsing | |
1670 | old-style parameter declarations; any functions encountered are | |
1671 | nested functions and declaration specifiers are required; otherwise | |
1672 | we are at top level and functions are normal functions and | |
1673 | declaration specifiers may be optional. If EMPTY_OK is true, empty | |
1674 | declarations are OK (subject to all other constraints); otherwise | |
1675 | (old-style parameter declarations) they are diagnosed. If | |
1676 | START_ATTR_OK is true, the declaration specifiers may start with | |
1677 | attributes; otherwise they may not. | |
f05b9d93 NP |
1678 | OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed |
1679 | declaration when parsing an Objective-C foreach statement. | |
81fea426 MP |
1680 | FALLTHRU_ATTR_P is used to signal whether this function parsed |
1681 | "__attribute__((fallthrough));". | |
27bf414c JM |
1682 | |
1683 | declaration: | |
1684 | declaration-specifiers init-declarator-list[opt] ; | |
32912286 | 1685 | static_assert-declaration |
27bf414c JM |
1686 | |
1687 | function-definition: | |
1688 | declaration-specifiers[opt] declarator declaration-list[opt] | |
1689 | compound-statement | |
1690 | ||
1691 | declaration-list: | |
1692 | declaration | |
1693 | declaration-list declaration | |
1694 | ||
1695 | init-declarator-list: | |
1696 | init-declarator | |
1697 | init-declarator-list , init-declarator | |
1698 | ||
1699 | init-declarator: | |
1700 | declarator simple-asm-expr[opt] attributes[opt] | |
1701 | declarator simple-asm-expr[opt] attributes[opt] = initializer | |
1702 | ||
1703 | GNU extensions: | |
1704 | ||
1705 | nested-function-definition: | |
1706 | declaration-specifiers declarator declaration-list[opt] | |
1707 | compound-statement | |
1708 | ||
81fea426 MP |
1709 | attribute ; |
1710 | ||
c165dca7 IS |
1711 | Objective-C: |
1712 | attributes objc-class-definition | |
1713 | attributes objc-category-definition | |
1714 | attributes objc-protocol-definition | |
1715 | ||
27bf414c JM |
1716 | The simple-asm-expr and attributes are GNU extensions. |
1717 | ||
1718 | This function does not handle __extension__; that is handled in its | |
1719 | callers. ??? Following the old parser, __extension__ may start | |
1720 | external declarations, declarations in functions and declarations | |
1721 | at the start of "for" loops, but not old-style parameter | |
1722 | declarations. | |
1723 | ||
1724 | C99 requires declaration specifiers in a function definition; the | |
1725 | absence is diagnosed through the diagnosis of implicit int. In GNU | |
1726 | C we also allow but diagnose declarations without declaration | |
1727 | specifiers, but only at top level (elsewhere they conflict with | |
953ff289 | 1728 | other syntax). |
b8698a0f | 1729 | |
f05b9d93 NP |
1730 | In Objective-C, declarations of the looping variable in a foreach |
1731 | statement are exceptionally terminated by 'in' (for example, 'for | |
1732 | (NSObject *object in array) { ... }'). | |
1733 | ||
953ff289 | 1734 | OpenMP: |
b8698a0f | 1735 | |
953ff289 | 1736 | declaration: |
1ee62b92 PG |
1737 | threadprivate-directive |
1738 | ||
1739 | GIMPLE: | |
1740 | ||
1741 | gimple-function-definition: | |
c2e84327 DM |
1742 | declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator |
1743 | declaration-list[opt] compound-statement | |
1744 | ||
1745 | rtl-function-definition: | |
1746 | declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator | |
1ee62b92 | 1747 | declaration-list[opt] compound-statement */ |
27bf414c JM |
1748 | |
1749 | static void | |
32912286 JM |
1750 | c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, |
1751 | bool static_assert_ok, bool empty_ok, | |
f05b9d93 | 1752 | bool nested, bool start_attr_ok, |
acf0174b | 1753 | tree *objc_foreach_object_declaration, |
3a40d81d | 1754 | vec<c_token> omp_declare_simd_clauses, |
81fea426 MP |
1755 | struct oacc_routine_data *oacc_routine_data, |
1756 | bool *fallthru_attr_p) | |
27bf414c JM |
1757 | { |
1758 | struct c_declspecs *specs; | |
1759 | tree prefix_attrs; | |
1760 | tree all_prefix_attrs; | |
1761 | bool diagnosed_no_specs = false; | |
c7412148 | 1762 | location_t here = c_parser_peek_token (parser)->location; |
bc4071dd | 1763 | |
32912286 JM |
1764 | if (static_assert_ok |
1765 | && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) | |
1766 | { | |
1767 | c_parser_static_assert_declaration (parser); | |
1768 | return; | |
1769 | } | |
27bf414c | 1770 | specs = build_null_declspecs (); |
2f413185 PB |
1771 | |
1772 | /* Try to detect an unknown type name when we have "A B" or "A *B". */ | |
1773 | if (c_parser_peek_token (parser)->type == CPP_NAME | |
1774 | && c_parser_peek_token (parser)->id_kind == C_ID_ID | |
1775 | && (c_parser_peek_2nd_token (parser)->type == CPP_NAME | |
1776 | || c_parser_peek_2nd_token (parser)->type == CPP_MULT) | |
1777 | && (!nested || !lookup_name (c_parser_peek_token (parser)->value))) | |
1778 | { | |
0e36f5c7 | 1779 | tree name = c_parser_peek_token (parser)->value; |
1a4f11c8 DM |
1780 | |
1781 | /* Issue a warning about NAME being an unknown type name, perhaps | |
1782 | with some kind of hint. | |
1783 | If the user forgot a "struct" etc, suggest inserting | |
1784 | it. Otherwise, attempt to look for misspellings. */ | |
1785 | gcc_rich_location richloc (here); | |
0e36f5c7 | 1786 | if (tag_exists_p (RECORD_TYPE, name)) |
1a4f11c8 DM |
1787 | { |
1788 | /* This is not C++ with its implicit typedef. */ | |
254830ba | 1789 | richloc.add_fixit_insert_before ("struct "); |
64a5912c DM |
1790 | error_at (&richloc, |
1791 | "unknown type name %qE;" | |
1792 | " use %<struct%> keyword to refer to the type", | |
1793 | name); | |
1a4f11c8 | 1794 | } |
0e36f5c7 | 1795 | else if (tag_exists_p (UNION_TYPE, name)) |
1a4f11c8 | 1796 | { |
254830ba | 1797 | richloc.add_fixit_insert_before ("union "); |
64a5912c DM |
1798 | error_at (&richloc, |
1799 | "unknown type name %qE;" | |
1800 | " use %<union%> keyword to refer to the type", | |
1801 | name); | |
1a4f11c8 | 1802 | } |
0e36f5c7 | 1803 | else if (tag_exists_p (ENUMERAL_TYPE, name)) |
1a4f11c8 | 1804 | { |
254830ba | 1805 | richloc.add_fixit_insert_before ("enum "); |
64a5912c DM |
1806 | error_at (&richloc, |
1807 | "unknown type name %qE;" | |
1808 | " use %<enum%> keyword to refer to the type", | |
1809 | name); | |
1a4f11c8 DM |
1810 | } |
1811 | else | |
1812 | { | |
6c7a259b DM |
1813 | name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME, |
1814 | here); | |
1a4f11c8 DM |
1815 | if (hint) |
1816 | { | |
6c7a259b | 1817 | richloc.add_fixit_replace (hint.suggestion ()); |
64a5912c DM |
1818 | error_at (&richloc, |
1819 | "unknown type name %qE; did you mean %qs?", | |
6c7a259b | 1820 | name, hint.suggestion ()); |
1a4f11c8 DM |
1821 | } |
1822 | else | |
1823 | error_at (here, "unknown type name %qE", name); | |
1824 | } | |
2f413185 PB |
1825 | |
1826 | /* Parse declspecs normally to get a correct pointer type, but avoid | |
a5812bdc PB |
1827 | a further "fails to be a type name" error. Refuse nested functions |
1828 | since it is not how the user likely wants us to recover. */ | |
2f413185 PB |
1829 | c_parser_peek_token (parser)->type = CPP_KEYWORD; |
1830 | c_parser_peek_token (parser)->keyword = RID_VOID; | |
1831 | c_parser_peek_token (parser)->value = error_mark_node; | |
a5812bdc | 1832 | fndef_ok = !nested; |
2f413185 PB |
1833 | } |
1834 | ||
568a31f2 | 1835 | c_parser_declspecs (parser, specs, true, true, start_attr_ok, |
38b7bc7f | 1836 | true, true, cla_nonabstract_decl); |
27bf414c JM |
1837 | if (parser->error) |
1838 | { | |
1839 | c_parser_skip_to_end_of_block_or_statement (parser); | |
1840 | return; | |
1841 | } | |
1842 | if (nested && !specs->declspecs_seen_p) | |
1843 | { | |
1844 | c_parser_error (parser, "expected declaration specifiers"); | |
1845 | c_parser_skip_to_end_of_block_or_statement (parser); | |
1846 | return; | |
1847 | } | |
1ee62b92 | 1848 | |
27bf414c | 1849 | finish_declspecs (specs); |
38b7bc7f | 1850 | bool auto_type_p = specs->typespec_word == cts_auto_type; |
27bf414c JM |
1851 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
1852 | { | |
38b7bc7f JM |
1853 | if (auto_type_p) |
1854 | error_at (here, "%<__auto_type%> in empty declaration"); | |
81fea426 MP |
1855 | else if (specs->typespec_kind == ctsk_none |
1856 | && attribute_fallthrough_p (specs->attrs)) | |
1857 | { | |
1858 | if (fallthru_attr_p != NULL) | |
1859 | *fallthru_attr_p = true; | |
1860 | tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH, | |
1861 | void_type_node, 0); | |
1862 | add_stmt (fn); | |
1863 | } | |
38b7bc7f | 1864 | else if (empty_ok) |
27bf414c JM |
1865 | shadow_tag (specs); |
1866 | else | |
1867 | { | |
1868 | shadow_tag_warned (specs, 1); | |
509c9d60 | 1869 | pedwarn (here, 0, "empty declaration"); |
27bf414c JM |
1870 | } |
1871 | c_parser_consume_token (parser); | |
0b212d8c | 1872 | if (oacc_routine_data) |
ae9281fc | 1873 | c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false); |
27bf414c JM |
1874 | return; |
1875 | } | |
f725e721 PB |
1876 | |
1877 | /* Provide better error recovery. Note that a type name here is usually | |
1878 | better diagnosed as a redeclaration. */ | |
1879 | if (empty_ok | |
1880 | && specs->typespec_kind == ctsk_tagdef | |
1881 | && c_parser_next_token_starts_declspecs (parser) | |
1882 | && !c_parser_next_token_is (parser, CPP_NAME)) | |
1883 | { | |
1884 | c_parser_error (parser, "expected %<;%>, identifier or %<(%>"); | |
1885 | parser->error = false; | |
1886 | shadow_tag_warned (specs, 1); | |
1887 | return; | |
1888 | } | |
38b7bc7f | 1889 | else if (c_dialect_objc () && !auto_type_p) |
c165dca7 | 1890 | { |
f7e71da5 IS |
1891 | /* Prefix attributes are an error on method decls. */ |
1892 | switch (c_parser_peek_token (parser)->type) | |
1893 | { | |
1894 | case CPP_PLUS: | |
1895 | case CPP_MINUS: | |
1896 | if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) | |
1897 | return; | |
1898 | if (specs->attrs) | |
1899 | { | |
1900 | warning_at (c_parser_peek_token (parser)->location, | |
1901 | OPT_Wattributes, | |
1902 | "prefix attributes are ignored for methods"); | |
1903 | specs->attrs = NULL_TREE; | |
1904 | } | |
1905 | if (fndef_ok) | |
1906 | c_parser_objc_method_definition (parser); | |
1907 | else | |
1908 | c_parser_objc_methodproto (parser); | |
1909 | return; | |
1910 | break; | |
1911 | default: | |
1912 | break; | |
1913 | } | |
c165dca7 IS |
1914 | /* This is where we parse 'attributes @interface ...', |
1915 | 'attributes @implementation ...', 'attributes @protocol ...' | |
1916 | (where attributes could be, for example, __attribute__ | |
1917 | ((deprecated)). | |
1918 | */ | |
1919 | switch (c_parser_peek_token (parser)->keyword) | |
1920 | { | |
1921 | case RID_AT_INTERFACE: | |
1922 | { | |
1923 | if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) | |
1924 | return; | |
1925 | c_parser_objc_class_definition (parser, specs->attrs); | |
1926 | return; | |
1927 | } | |
1928 | break; | |
1929 | case RID_AT_IMPLEMENTATION: | |
1930 | { | |
1931 | if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) | |
1932 | return; | |
1933 | if (specs->attrs) | |
1934 | { | |
1935 | warning_at (c_parser_peek_token (parser)->location, | |
1936 | OPT_Wattributes, | |
1937 | "prefix attributes are ignored for implementations"); | |
1938 | specs->attrs = NULL_TREE; | |
1939 | } | |
1940 | c_parser_objc_class_definition (parser, NULL_TREE); | |
1941 | return; | |
1942 | } | |
1943 | break; | |
1944 | case RID_AT_PROTOCOL: | |
1945 | { | |
1946 | if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) | |
1947 | return; | |
1948 | c_parser_objc_protocol_definition (parser, specs->attrs); | |
1949 | return; | |
1950 | } | |
1951 | break; | |
668ea4b1 IS |
1952 | case RID_AT_ALIAS: |
1953 | case RID_AT_CLASS: | |
1954 | case RID_AT_END: | |
1955 | case RID_AT_PROPERTY: | |
1956 | if (specs->attrs) | |
1957 | { | |
96bbfbac | 1958 | c_parser_error (parser, "unexpected attribute"); |
668ea4b1 IS |
1959 | specs->attrs = NULL; |
1960 | } | |
1961 | break; | |
c165dca7 IS |
1962 | default: |
1963 | break; | |
1964 | } | |
1965 | } | |
81fea426 MP |
1966 | else if (attribute_fallthrough_p (specs->attrs)) |
1967 | warning_at (here, OPT_Wattributes, | |
1968 | "%<fallthrough%> attribute not followed by %<;%>"); | |
1969 | ||
27bf414c JM |
1970 | pending_xref_error (); |
1971 | prefix_attrs = specs->attrs; | |
1972 | all_prefix_attrs = prefix_attrs; | |
1973 | specs->attrs = NULL_TREE; | |
ae9281fc | 1974 | while (true) |
27bf414c JM |
1975 | { |
1976 | struct c_declarator *declarator; | |
1977 | bool dummy = false; | |
575bfb00 | 1978 | timevar_id_t tv; |
1ee62b92 | 1979 | tree fnbody = NULL_TREE; |
27bf414c JM |
1980 | /* Declaring either one or more declarators (in which case we |
1981 | should diagnose if there were no declaration specifiers) or a | |
1982 | function definition (in which case the diagnostic for | |
1983 | implicit int suffices). */ | |
9e5b2115 PB |
1984 | declarator = c_parser_declarator (parser, |
1985 | specs->typespec_kind != ctsk_none, | |
27bf414c JM |
1986 | C_DTR_NORMAL, &dummy); |
1987 | if (declarator == NULL) | |
1988 | { | |
41958c28 BI |
1989 | if (omp_declare_simd_clauses.exists () |
1990 | || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
acf0174b JJ |
1991 | c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, |
1992 | omp_declare_simd_clauses); | |
0b212d8c | 1993 | if (oacc_routine_data) |
ae9281fc | 1994 | c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false); |
27bf414c JM |
1995 | c_parser_skip_to_end_of_block_or_statement (parser); |
1996 | return; | |
1997 | } | |
38b7bc7f JM |
1998 | if (auto_type_p && declarator->kind != cdk_id) |
1999 | { | |
2000 | error_at (here, | |
2001 | "%<__auto_type%> requires a plain identifier" | |
2002 | " as declarator"); | |
2003 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2004 | return; | |
2005 | } | |
27bf414c JM |
2006 | if (c_parser_next_token_is (parser, CPP_EQ) |
2007 | || c_parser_next_token_is (parser, CPP_COMMA) | |
2008 | || c_parser_next_token_is (parser, CPP_SEMICOLON) | |
2009 | || c_parser_next_token_is_keyword (parser, RID_ASM) | |
f05b9d93 NP |
2010 | || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE) |
2011 | || c_parser_next_token_is_keyword (parser, RID_IN)) | |
27bf414c JM |
2012 | { |
2013 | tree asm_name = NULL_TREE; | |
2014 | tree postfix_attrs = NULL_TREE; | |
2015 | if (!diagnosed_no_specs && !specs->declspecs_seen_p) | |
2016 | { | |
2017 | diagnosed_no_specs = true; | |
509c9d60 | 2018 | pedwarn (here, 0, "data definition has no type or storage class"); |
27bf414c JM |
2019 | } |
2020 | /* Having seen a data definition, there cannot now be a | |
2021 | function definition. */ | |
2022 | fndef_ok = false; | |
2023 | if (c_parser_next_token_is_keyword (parser, RID_ASM)) | |
2024 | asm_name = c_parser_simple_asm_expr (parser); | |
2025 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
ae5ebda4 MP |
2026 | { |
2027 | postfix_attrs = c_parser_attributes (parser); | |
2028 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
2029 | { | |
2030 | /* This means there is an attribute specifier after | |
2031 | the declarator in a function definition. Provide | |
2032 | some more information for the user. */ | |
2033 | error_at (here, "attributes should be specified before the " | |
2034 | "declarator in a function definition"); | |
2035 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2036 | return; | |
2037 | } | |
2038 | } | |
27bf414c JM |
2039 | if (c_parser_next_token_is (parser, CPP_EQ)) |
2040 | { | |
2041 | tree d; | |
2042 | struct c_expr init; | |
c2255bc4 | 2043 | location_t init_loc; |
27bf414c | 2044 | c_parser_consume_token (parser); |
38b7bc7f JM |
2045 | if (auto_type_p) |
2046 | { | |
38b7bc7f | 2047 | init_loc = c_parser_peek_token (parser)->location; |
5dd9a9d0 DM |
2048 | rich_location richloc (line_table, init_loc); |
2049 | start_init (NULL_TREE, asm_name, global_bindings_p (), &richloc); | |
36618428 MP |
2050 | /* A parameter is initialized, which is invalid. Don't |
2051 | attempt to instrument the initializer. */ | |
2052 | int flag_sanitize_save = flag_sanitize; | |
2053 | if (nested && !empty_ok) | |
2054 | flag_sanitize = 0; | |
38b7bc7f | 2055 | init = c_parser_expr_no_commas (parser, NULL); |
36618428 | 2056 | flag_sanitize = flag_sanitize_save; |
38b7bc7f JM |
2057 | if (TREE_CODE (init.value) == COMPONENT_REF |
2058 | && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1))) | |
2059 | error_at (here, | |
2060 | "%<__auto_type%> used with a bit-field" | |
2061 | " initializer"); | |
2062 | init = convert_lvalue_to_rvalue (init_loc, init, true, true); | |
2063 | tree init_type = TREE_TYPE (init.value); | |
9698b078 | 2064 | /* As with typeof, remove all qualifiers from atomic types. */ |
38b7bc7f JM |
2065 | if (init_type != error_mark_node && TYPE_ATOMIC (init_type)) |
2066 | init_type | |
9698b078 | 2067 | = c_build_qualified_type (init_type, TYPE_UNQUALIFIED); |
38b7bc7f JM |
2068 | bool vm_type = variably_modified_type_p (init_type, |
2069 | NULL_TREE); | |
2070 | if (vm_type) | |
b2fa0a8b | 2071 | init.value = save_expr (init.value); |
38b7bc7f JM |
2072 | finish_init (); |
2073 | specs->typespec_kind = ctsk_typeof; | |
2074 | specs->locations[cdw_typedef] = init_loc; | |
2075 | specs->typedef_p = true; | |
2076 | specs->type = init_type; | |
2077 | if (vm_type) | |
2078 | { | |
2079 | bool maybe_const = true; | |
2080 | tree type_expr = c_fully_fold (init.value, false, | |
2081 | &maybe_const); | |
2082 | specs->expr_const_operands &= maybe_const; | |
2083 | if (specs->expr) | |
2084 | specs->expr = build2 (COMPOUND_EXPR, | |
2085 | TREE_TYPE (type_expr), | |
2086 | specs->expr, type_expr); | |
2087 | else | |
2088 | specs->expr = type_expr; | |
2089 | } | |
2090 | d = start_decl (declarator, specs, true, | |
2091 | chainon (postfix_attrs, all_prefix_attrs)); | |
2092 | if (!d) | |
2093 | d = error_mark_node; | |
41958c28 BI |
2094 | if (omp_declare_simd_clauses.exists () |
2095 | || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
38b7bc7f JM |
2096 | c_finish_omp_declare_simd (parser, d, NULL_TREE, |
2097 | omp_declare_simd_clauses); | |
2098 | } | |
2099 | else | |
2100 | { | |
2101 | /* The declaration of the variable is in effect while | |
2102 | its initializer is parsed. */ | |
2103 | d = start_decl (declarator, specs, true, | |
2104 | chainon (postfix_attrs, all_prefix_attrs)); | |
2105 | if (!d) | |
2106 | d = error_mark_node; | |
41958c28 BI |
2107 | if (omp_declare_simd_clauses.exists () |
2108 | || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
38b7bc7f JM |
2109 | c_finish_omp_declare_simd (parser, d, NULL_TREE, |
2110 | omp_declare_simd_clauses); | |
38b7bc7f | 2111 | init_loc = c_parser_peek_token (parser)->location; |
5dd9a9d0 DM |
2112 | rich_location richloc (line_table, init_loc); |
2113 | start_init (d, asm_name, global_bindings_p (), &richloc); | |
36618428 MP |
2114 | /* A parameter is initialized, which is invalid. Don't |
2115 | attempt to instrument the initializer. */ | |
2116 | int flag_sanitize_save = flag_sanitize; | |
2117 | if (TREE_CODE (d) == PARM_DECL) | |
2118 | flag_sanitize = 0; | |
38b7bc7f | 2119 | init = c_parser_initializer (parser); |
36618428 | 2120 | flag_sanitize = flag_sanitize_save; |
38b7bc7f JM |
2121 | finish_init (); |
2122 | } | |
0b212d8c | 2123 | if (oacc_routine_data) |
ae9281fc | 2124 | c_finish_oacc_routine (oacc_routine_data, d, false); |
27bf414c JM |
2125 | if (d != error_mark_node) |
2126 | { | |
d033409e | 2127 | maybe_warn_string_init (init_loc, TREE_TYPE (d), init); |
c2255bc4 | 2128 | finish_decl (d, init_loc, init.value, |
d033409e | 2129 | init.original_type, asm_name); |
27bf414c JM |
2130 | } |
2131 | } | |
2132 | else | |
2133 | { | |
38b7bc7f JM |
2134 | if (auto_type_p) |
2135 | { | |
2136 | error_at (here, | |
2137 | "%<__auto_type%> requires an initialized " | |
2138 | "data declaration"); | |
2139 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2140 | return; | |
2141 | } | |
27bf414c JM |
2142 | tree d = start_decl (declarator, specs, false, |
2143 | chainon (postfix_attrs, | |
2144 | all_prefix_attrs)); | |
8139a48e DM |
2145 | if (d && TREE_CODE (d) == FUNCTION_DECL) |
2146 | if (declarator->kind == cdk_function) | |
2147 | if (DECL_ARGUMENTS (d) == NULL_TREE) | |
2148 | DECL_ARGUMENTS (d) = declarator->u.arg_info->parms; | |
41958c28 BI |
2149 | if (omp_declare_simd_clauses.exists () |
2150 | || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
acf0174b JJ |
2151 | { |
2152 | tree parms = NULL_TREE; | |
2153 | if (d && TREE_CODE (d) == FUNCTION_DECL) | |
2154 | { | |
2155 | struct c_declarator *ce = declarator; | |
2156 | while (ce != NULL) | |
2157 | if (ce->kind == cdk_function) | |
2158 | { | |
2159 | parms = ce->u.arg_info->parms; | |
2160 | break; | |
2161 | } | |
2162 | else | |
2163 | ce = ce->declarator; | |
2164 | } | |
2165 | if (parms) | |
2166 | temp_store_parm_decls (d, parms); | |
2167 | c_finish_omp_declare_simd (parser, d, parms, | |
2168 | omp_declare_simd_clauses); | |
2169 | if (parms) | |
2170 | temp_pop_parm_decls (); | |
2171 | } | |
0b212d8c | 2172 | if (oacc_routine_data) |
ae9281fc | 2173 | c_finish_oacc_routine (oacc_routine_data, d, false); |
27bf414c | 2174 | if (d) |
c2255bc4 | 2175 | finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, |
f05b9d93 NP |
2176 | NULL_TREE, asm_name); |
2177 | ||
2178 | if (c_parser_next_token_is_keyword (parser, RID_IN)) | |
2179 | { | |
2180 | if (d) | |
2181 | *objc_foreach_object_declaration = d; | |
2182 | else | |
2183 | *objc_foreach_object_declaration = error_mark_node; | |
2184 | } | |
27bf414c JM |
2185 | } |
2186 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
2187 | { | |
38b7bc7f JM |
2188 | if (auto_type_p) |
2189 | { | |
2190 | error_at (here, | |
2191 | "%<__auto_type%> may only be used with" | |
2192 | " a single declarator"); | |
2193 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2194 | return; | |
2195 | } | |
27bf414c JM |
2196 | c_parser_consume_token (parser); |
2197 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
2198 | all_prefix_attrs = chainon (c_parser_attributes (parser), | |
2199 | prefix_attrs); | |
2200 | else | |
2201 | all_prefix_attrs = prefix_attrs; | |
2202 | continue; | |
2203 | } | |
2204 | else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
2205 | { | |
2206 | c_parser_consume_token (parser); | |
2207 | return; | |
2208 | } | |
f05b9d93 NP |
2209 | else if (c_parser_next_token_is_keyword (parser, RID_IN)) |
2210 | { | |
2211 | /* This can only happen in Objective-C: we found the | |
2212 | 'in' that terminates the declaration inside an | |
2213 | Objective-C foreach statement. Do not consume the | |
2214 | token, so that the caller can use it to determine | |
2215 | that this indeed is a foreach context. */ | |
2216 | return; | |
2217 | } | |
27bf414c JM |
2218 | else |
2219 | { | |
2220 | c_parser_error (parser, "expected %<,%> or %<;%>"); | |
2221 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2222 | return; | |
2223 | } | |
2224 | } | |
38b7bc7f JM |
2225 | else if (auto_type_p) |
2226 | { | |
2227 | error_at (here, | |
2228 | "%<__auto_type%> requires an initialized data declaration"); | |
2229 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2230 | return; | |
2231 | } | |
27bf414c JM |
2232 | else if (!fndef_ok) |
2233 | { | |
2234 | c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, " | |
2235 | "%<asm%> or %<__attribute__%>"); | |
2236 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2237 | return; | |
2238 | } | |
2239 | /* Function definition (nested or otherwise). */ | |
2240 | if (nested) | |
2241 | { | |
c1771a20 | 2242 | pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions"); |
d2784db4 | 2243 | c_push_function_context (); |
27bf414c JM |
2244 | } |
2245 | if (!start_function (specs, declarator, all_prefix_attrs)) | |
2246 | { | |
1a59ccf2 DM |
2247 | /* At this point we've consumed: |
2248 | declaration-specifiers declarator | |
2249 | and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON, | |
2250 | RID_ASM, RID_ATTRIBUTE, or RID_IN, | |
2251 | but the | |
2252 | declaration-specifiers declarator | |
2253 | aren't grokkable as a function definition, so we have | |
2254 | an error. */ | |
2255 | gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON)); | |
2256 | if (c_parser_next_token_starts_declspecs (parser)) | |
2257 | { | |
2258 | /* If we have | |
2259 | declaration-specifiers declarator decl-specs | |
2260 | then assume we have a missing semicolon, which would | |
2261 | give us: | |
2262 | declaration-specifiers declarator decl-specs | |
2263 | ^ | |
2264 | ; | |
2265 | <~~~~~~~~~ declaration ~~~~~~~~~~> | |
2266 | Use c_parser_require to get an error with a fix-it hint. */ | |
2267 | c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"); | |
2268 | parser->error = false; | |
2269 | } | |
2270 | else | |
2271 | { | |
2272 | /* This can appear in many cases looking nothing like a | |
2273 | function definition, so we don't give a more specific | |
2274 | error suggesting there was one. */ | |
2275 | c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> " | |
2276 | "or %<__attribute__%>"); | |
2277 | } | |
27bf414c | 2278 | if (nested) |
d2784db4 | 2279 | c_pop_function_context (); |
27bf414c JM |
2280 | break; |
2281 | } | |
575bfb00 LC |
2282 | |
2283 | if (DECL_DECLARED_INLINE_P (current_function_decl)) | |
2284 | tv = TV_PARSE_INLINE; | |
2285 | else | |
2286 | tv = TV_PARSE_FUNC; | |
c2e84327 | 2287 | auto_timevar at (g_timer, tv); |
575bfb00 | 2288 | |
27bf414c JM |
2289 | /* Parse old-style parameter declarations. ??? Attributes are |
2290 | not allowed to start declaration specifiers here because of a | |
2291 | syntax conflict between a function declaration with attribute | |
2292 | suffix and a function definition with an attribute prefix on | |
2293 | first old-style parameter declaration. Following the old | |
2294 | parser, they are not accepted on subsequent old-style | |
2295 | parameter declarations either. However, there is no | |
2296 | ambiguity after the first declaration, nor indeed on the | |
2297 | first as long as we don't allow postfix attributes after a | |
2298 | declarator with a nonempty identifier list in a definition; | |
2299 | and postfix attributes have never been accepted here in | |
2300 | function definitions either. */ | |
2301 | while (c_parser_next_token_is_not (parser, CPP_EOF) | |
2302 | && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) | |
32912286 | 2303 | c_parser_declaration_or_fndef (parser, false, false, false, |
acf0174b | 2304 | true, false, NULL, vNULL); |
27bf414c | 2305 | store_parm_decls (); |
41958c28 BI |
2306 | if (omp_declare_simd_clauses.exists () |
2307 | || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
acf0174b JJ |
2308 | c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, |
2309 | omp_declare_simd_clauses); | |
0b212d8c | 2310 | if (oacc_routine_data) |
ae9281fc | 2311 | c_finish_oacc_routine (oacc_routine_data, current_function_decl, true); |
1751ecd6 AH |
2312 | DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus |
2313 | = c_parser_peek_token (parser)->location; | |
1ee62b92 PG |
2314 | |
2315 | /* If the definition was marked with __GIMPLE then parse the | |
2316 | function body as GIMPLE. */ | |
2317 | if (specs->gimple_p) | |
2318 | { | |
c2e84327 | 2319 | cfun->pass_startwith = specs->gimple_or_rtl_pass; |
1ee62b92 PG |
2320 | bool saved = in_late_binary_op; |
2321 | in_late_binary_op = true; | |
2322 | c_parser_parse_gimple_body (parser); | |
2323 | in_late_binary_op = saved; | |
2324 | } | |
c2e84327 DM |
2325 | /* Similarly, if it was marked with __RTL, use the RTL parser now, |
2326 | consuming the function body. */ | |
2327 | else if (specs->rtl_p) | |
2328 | { | |
2329 | c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass); | |
2330 | ||
2331 | /* Normally, store_parm_decls sets next_is_function_body, | |
2332 | anticipating a function body. We need a push_scope/pop_scope | |
2333 | pair to flush out this state, or subsequent function parsing | |
2334 | will go wrong. */ | |
2335 | push_scope (); | |
2336 | pop_scope (); | |
2337 | ||
2338 | finish_function (); | |
2339 | return; | |
2340 | } | |
1ee62b92 PG |
2341 | else |
2342 | { | |
2343 | fnbody = c_parser_compound_statement (parser); | |
2344 | if (flag_cilkplus && contains_array_notation_expr (fnbody)) | |
2345 | fnbody = expand_array_notation_exprs (fnbody); | |
2346 | } | |
2347 | tree fndecl = current_function_decl; | |
27bf414c JM |
2348 | if (nested) |
2349 | { | |
2350 | tree decl = current_function_decl; | |
9f62cb92 JJ |
2351 | /* Mark nested functions as needing static-chain initially. |
2352 | lower_nested_functions will recompute it but the | |
2353 | DECL_STATIC_CHAIN flag is also used before that happens, | |
2354 | by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */ | |
2355 | DECL_STATIC_CHAIN (decl) = 1; | |
27bf414c JM |
2356 | add_stmt (fnbody); |
2357 | finish_function (); | |
d2784db4 | 2358 | c_pop_function_context (); |
c2255bc4 | 2359 | add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); |
27bf414c JM |
2360 | } |
2361 | else | |
2362 | { | |
1ee62b92 PG |
2363 | if (fnbody) |
2364 | add_stmt (fnbody); | |
27bf414c JM |
2365 | finish_function (); |
2366 | } | |
1ee62b92 PG |
2367 | /* Get rid of the empty stmt list for GIMPLE. */ |
2368 | if (specs->gimple_p) | |
2369 | DECL_SAVED_TREE (fndecl) = NULL_TREE; | |
575bfb00 | 2370 | |
27bf414c JM |
2371 | break; |
2372 | } | |
2373 | } | |
2374 | ||
2375 | /* Parse an asm-definition (asm() outside a function body). This is a | |
2376 | GNU extension. | |
2377 | ||
2378 | asm-definition: | |
2379 | simple-asm-expr ; | |
2380 | */ | |
2381 | ||
2382 | static void | |
2383 | c_parser_asm_definition (c_parser *parser) | |
2384 | { | |
2385 | tree asm_str = c_parser_simple_asm_expr (parser); | |
27bf414c | 2386 | if (asm_str) |
3dafb85c | 2387 | symtab->finalize_toplevel_asm (asm_str); |
27bf414c JM |
2388 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
2389 | } | |
2390 | ||
48b0b196 | 2391 | /* Parse a static assertion (C11 6.7.10). |
32912286 JM |
2392 | |
2393 | static_assert-declaration: | |
2394 | static_assert-declaration-no-semi ; | |
2395 | */ | |
2396 | ||
2397 | static void | |
2398 | c_parser_static_assert_declaration (c_parser *parser) | |
2399 | { | |
2400 | c_parser_static_assert_declaration_no_semi (parser); | |
2401 | if (parser->error | |
2402 | || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |
2403 | c_parser_skip_to_end_of_block_or_statement (parser); | |
2404 | } | |
2405 | ||
48b0b196 | 2406 | /* Parse a static assertion (C11 6.7.10), without the trailing |
32912286 JM |
2407 | semicolon. |
2408 | ||
2409 | static_assert-declaration-no-semi: | |
2410 | _Static_assert ( constant-expression , string-literal ) | |
2411 | */ | |
2412 | ||
2413 | static void | |
2414 | c_parser_static_assert_declaration_no_semi (c_parser *parser) | |
2415 | { | |
2416 | location_t assert_loc, value_loc; | |
2417 | tree value; | |
2418 | tree string; | |
2419 | ||
2420 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)); | |
2421 | assert_loc = c_parser_peek_token (parser)->location; | |
35aff4fb MP |
2422 | if (flag_isoc99) |
2423 | pedwarn_c99 (assert_loc, OPT_Wpedantic, | |
32912286 | 2424 | "ISO C99 does not support %<_Static_assert%>"); |
35aff4fb MP |
2425 | else |
2426 | pedwarn_c99 (assert_loc, OPT_Wpedantic, | |
32912286 | 2427 | "ISO C90 does not support %<_Static_assert%>"); |
32912286 | 2428 | c_parser_consume_token (parser); |
32129a17 DM |
2429 | matching_parens parens; |
2430 | if (!parens.require_open (parser)) | |
32912286 | 2431 | return; |
8062bca6 | 2432 | location_t value_tok_loc = c_parser_peek_token (parser)->location; |
32912286 | 2433 | value = c_parser_expr_no_commas (parser, NULL).value; |
8062bca6 | 2434 | value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc); |
32912286 JM |
2435 | parser->lex_untranslated_string = true; |
2436 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |
2437 | { | |
2438 | parser->lex_untranslated_string = false; | |
2439 | return; | |
2440 | } | |
2441 | switch (c_parser_peek_token (parser)->type) | |
2442 | { | |
2443 | case CPP_STRING: | |
2444 | case CPP_STRING16: | |
2445 | case CPP_STRING32: | |
2446 | case CPP_WSTRING: | |
2447 | case CPP_UTF8STRING: | |
2448 | string = c_parser_peek_token (parser)->value; | |
2449 | c_parser_consume_token (parser); | |
2450 | parser->lex_untranslated_string = false; | |
2451 | break; | |
2452 | default: | |
2453 | c_parser_error (parser, "expected string literal"); | |
2454 | parser->lex_untranslated_string = false; | |
2455 | return; | |
2456 | } | |
32129a17 | 2457 | parens.require_close (parser); |
32912286 JM |
2458 | |
2459 | if (!INTEGRAL_TYPE_P (TREE_TYPE (value))) | |
2460 | { | |
2461 | error_at (value_loc, "expression in static assertion is not an integer"); | |
2462 | return; | |
2463 | } | |
2464 | if (TREE_CODE (value) != INTEGER_CST) | |
2465 | { | |
2466 | value = c_fully_fold (value, false, NULL); | |
8d95fe25 MP |
2467 | /* Strip no-op conversions. */ |
2468 | STRIP_TYPE_NOPS (value); | |
32912286 | 2469 | if (TREE_CODE (value) == INTEGER_CST) |
c1771a20 | 2470 | pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion " |
32912286 JM |
2471 | "is not an integer constant expression"); |
2472 | } | |
2473 | if (TREE_CODE (value) != INTEGER_CST) | |
2474 | { | |
2475 | error_at (value_loc, "expression in static assertion is not constant"); | |
2476 | return; | |
2477 | } | |
2478 | constant_expression_warning (value); | |
2479 | if (integer_zerop (value)) | |
2480 | error_at (assert_loc, "static assertion failed: %E", string); | |
2481 | } | |
2482 | ||
27bf414c | 2483 | /* Parse some declaration specifiers (possibly none) (C90 6.5, C99 |
31dc71a8 | 2484 | 6.7, C11 6.7), adding them to SPECS (which may already include some). |
27bf414c | 2485 | Storage class specifiers are accepted iff SCSPEC_OK; type |
568a31f2 MP |
2486 | specifiers are accepted iff TYPESPEC_OK; alignment specifiers are |
2487 | accepted iff ALIGNSPEC_OK; attributes are accepted at the start | |
38b7bc7f | 2488 | iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. |
27bf414c JM |
2489 | |
2490 | declaration-specifiers: | |
2491 | storage-class-specifier declaration-specifiers[opt] | |
2492 | type-specifier declaration-specifiers[opt] | |
2493 | type-qualifier declaration-specifiers[opt] | |
2494 | function-specifier declaration-specifiers[opt] | |
d19fa6b5 | 2495 | alignment-specifier declaration-specifiers[opt] |
27bf414c JM |
2496 | |
2497 | Function specifiers (inline) are from C99, and are currently | |
d19fa6b5 | 2498 | handled as storage class specifiers, as is __thread. Alignment |
48b0b196 | 2499 | specifiers are from C11. |
27bf414c | 2500 | |
31dc71a8 | 2501 | C90 6.5.1, C99 6.7.1, C11 6.7.1: |
27bf414c JM |
2502 | storage-class-specifier: |
2503 | typedef | |
2504 | extern | |
2505 | static | |
2506 | auto | |
2507 | register | |
582d9b50 JM |
2508 | _Thread_local |
2509 | ||
2510 | (_Thread_local is new in C11.) | |
27bf414c | 2511 | |
31dc71a8 | 2512 | C99 6.7.4, C11 6.7.4: |
27bf414c JM |
2513 | function-specifier: |
2514 | inline | |
c4b3a0a0 JM |
2515 | _Noreturn |
2516 | ||
48b0b196 | 2517 | (_Noreturn is new in C11.) |
27bf414c | 2518 | |
31dc71a8 | 2519 | C90 6.5.2, C99 6.7.2, C11 6.7.2: |
27bf414c JM |
2520 | type-specifier: |
2521 | void | |
2522 | char | |
2523 | short | |
2524 | int | |
2525 | long | |
2526 | float | |
2527 | double | |
2528 | signed | |
2529 | unsigned | |
2530 | _Bool | |
2531 | _Complex | |
2532 | [_Imaginary removed in C99 TC2] | |
2533 | struct-or-union-specifier | |
2534 | enum-specifier | |
2535 | typedef-name | |
267bac10 | 2536 | atomic-type-specifier |
27bf414c JM |
2537 | |
2538 | (_Bool and _Complex are new in C99.) | |
267bac10 | 2539 | (atomic-type-specifier is new in C11.) |
27bf414c | 2540 | |
31dc71a8 | 2541 | C90 6.5.3, C99 6.7.3, C11 6.7.3: |
27bf414c JM |
2542 | |
2543 | type-qualifier: | |
2544 | const | |
2545 | restrict | |
2546 | volatile | |
36c5e70a | 2547 | address-space-qualifier |
267bac10 | 2548 | _Atomic |
27bf414c JM |
2549 | |
2550 | (restrict is new in C99.) | |
267bac10 | 2551 | (_Atomic is new in C11.) |
27bf414c JM |
2552 | |
2553 | GNU extensions: | |
2554 | ||
2555 | declaration-specifiers: | |
2556 | attributes declaration-specifiers[opt] | |
2557 | ||
36c5e70a BE |
2558 | type-qualifier: |
2559 | address-space | |
2560 | ||
2561 | address-space: | |
2562 | identifier recognized by the target | |
2563 | ||
27bf414c JM |
2564 | storage-class-specifier: |
2565 | __thread | |
2566 | ||
2567 | type-specifier: | |
2568 | typeof-specifier | |
38b7bc7f | 2569 | __auto_type |
78a7c317 | 2570 | __intN |
9a8ce21f JG |
2571 | _Decimal32 |
2572 | _Decimal64 | |
2573 | _Decimal128 | |
ab22c1fa CF |
2574 | _Fract |
2575 | _Accum | |
2576 | _Sat | |
2577 | ||
2578 | (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037: | |
2579 | http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf) | |
27bf414c | 2580 | |
267bac10 JM |
2581 | atomic-type-specifier |
2582 | _Atomic ( type-name ) | |
2583 | ||
27bf414c JM |
2584 | Objective-C: |
2585 | ||
2586 | type-specifier: | |
2587 | class-name objc-protocol-refs[opt] | |
2588 | typedef-name objc-protocol-refs | |
2589 | objc-protocol-refs | |
2590 | */ | |
2591 | ||
1ee62b92 | 2592 | void |
27bf414c | 2593 | c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
29ce73cb | 2594 | bool scspec_ok, bool typespec_ok, bool start_attr_ok, |
38b7bc7f JM |
2595 | bool alignspec_ok, bool auto_type_ok, |
2596 | enum c_lookahead_kind la) | |
27bf414c JM |
2597 | { |
2598 | bool attrs_ok = start_attr_ok; | |
9e5b2115 | 2599 | bool seen_type = specs->typespec_kind != ctsk_none; |
29ce73cb PB |
2600 | |
2601 | if (!typespec_ok) | |
2602 | gcc_assert (la == cla_prefer_id); | |
2603 | ||
2604 | while (c_parser_next_token_is (parser, CPP_NAME) | |
27bf414c JM |
2605 | || c_parser_next_token_is (parser, CPP_KEYWORD) |
2606 | || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS))) | |
2607 | { | |
2608 | struct c_typespec t; | |
2609 | tree attrs; | |
d19fa6b5 | 2610 | tree align; |
dc491a25 | 2611 | location_t loc = c_parser_peek_token (parser)->location; |
f725e721 | 2612 | |
29ce73cb PB |
2613 | /* If we cannot accept a type, exit if the next token must start |
2614 | one. Also, if we already have seen a tagged definition, | |
2615 | a typename would be an error anyway and likely the user | |
2616 | has simply forgotten a semicolon, so we exit. */ | |
2617 | if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef) | |
2618 | && c_parser_next_tokens_start_typename (parser, la) | |
2619 | && !c_parser_next_token_is_qualifier (parser)) | |
2620 | break; | |
f725e721 | 2621 | |
27bf414c JM |
2622 | if (c_parser_next_token_is (parser, CPP_NAME)) |
2623 | { | |
0b2c4be5 DS |
2624 | c_token *name_token = c_parser_peek_token (parser); |
2625 | tree value = name_token->value; | |
2626 | c_id_kind kind = name_token->id_kind; | |
36c5e70a BE |
2627 | |
2628 | if (kind == C_ID_ADDRSPACE) | |
2629 | { | |
2630 | addr_space_t as | |
0b2c4be5 DS |
2631 | = name_token->keyword - RID_FIRST_ADDR_SPACE; |
2632 | declspecs_add_addrspace (name_token->location, specs, as); | |
36c5e70a BE |
2633 | c_parser_consume_token (parser); |
2634 | attrs_ok = true; | |
2635 | continue; | |
2636 | } | |
2637 | ||
29ce73cb PB |
2638 | gcc_assert (!c_parser_next_token_is_qualifier (parser)); |
2639 | ||
2640 | /* If we cannot accept a type, and the next token must start one, | |
2641 | exit. Do the same if we already have seen a tagged definition, | |
2642 | since it would be an error anyway and likely the user has simply | |
2643 | forgotten a semicolon. */ | |
2644 | if (seen_type || !c_parser_next_tokens_start_typename (parser, la)) | |
2645 | break; | |
2646 | ||
2647 | /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or | |
2648 | a C_ID_CLASSNAME. */ | |
27bf414c JM |
2649 | c_parser_consume_token (parser); |
2650 | seen_type = true; | |
2651 | attrs_ok = true; | |
29ce73cb PB |
2652 | if (kind == C_ID_ID) |
2653 | { | |
1c9f5f33 | 2654 | error_at (loc, "unknown type name %qE", value); |
29ce73cb PB |
2655 | t.kind = ctsk_typedef; |
2656 | t.spec = error_mark_node; | |
2657 | } | |
2658 | else if (kind == C_ID_TYPENAME | |
2659 | && (!c_dialect_objc () | |
2660 | || c_parser_next_token_is_not (parser, CPP_LESS))) | |
27bf414c JM |
2661 | { |
2662 | t.kind = ctsk_typedef; | |
2663 | /* For a typedef name, record the meaning, not the name. | |
2664 | In case of 'foo foo, bar;'. */ | |
2665 | t.spec = lookup_name (value); | |
2666 | } | |
2667 | else | |
2668 | { | |
2669 | tree proto = NULL_TREE; | |
2670 | gcc_assert (c_dialect_objc ()); | |
2671 | t.kind = ctsk_objc; | |
2672 | if (c_parser_next_token_is (parser, CPP_LESS)) | |
2673 | proto = c_parser_objc_protocol_refs (parser); | |
2674 | t.spec = objc_get_protocol_qualified_type (value, proto); | |
2675 | } | |
29ce73cb PB |
2676 | t.expr = NULL_TREE; |
2677 | t.expr_const_operands = true; | |
0b2c4be5 | 2678 | declspecs_add_type (name_token->location, specs, t); |
27bf414c JM |
2679 | continue; |
2680 | } | |
2681 | if (c_parser_next_token_is (parser, CPP_LESS)) | |
2682 | { | |
2683 | /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" - | |
2684 | nisse@lysator.liu.se. */ | |
2685 | tree proto; | |
2686 | gcc_assert (c_dialect_objc ()); | |
2687 | if (!typespec_ok || seen_type) | |
2688 | break; | |
2689 | proto = c_parser_objc_protocol_refs (parser); | |
2690 | t.kind = ctsk_objc; | |
2691 | t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto); | |
928c19bb JM |
2692 | t.expr = NULL_TREE; |
2693 | t.expr_const_operands = true; | |
dc491a25 | 2694 | declspecs_add_type (loc, specs, t); |
27bf414c JM |
2695 | continue; |
2696 | } | |
2697 | gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD)); | |
2698 | switch (c_parser_peek_token (parser)->keyword) | |
2699 | { | |
2700 | case RID_STATIC: | |
2701 | case RID_EXTERN: | |
2702 | case RID_REGISTER: | |
2703 | case RID_TYPEDEF: | |
2704 | case RID_INLINE: | |
bbceee64 | 2705 | case RID_NORETURN: |
27bf414c JM |
2706 | case RID_AUTO: |
2707 | case RID_THREAD: | |
2708 | if (!scspec_ok) | |
2709 | goto out; | |
2710 | attrs_ok = true; | |
bbceee64 | 2711 | /* TODO: Distinguish between function specifiers (inline, noreturn) |
27bf414c JM |
2712 | and storage class specifiers, either here or in |
2713 | declspecs_add_scspec. */ | |
0b2c4be5 DS |
2714 | declspecs_add_scspec (loc, specs, |
2715 | c_parser_peek_token (parser)->value); | |
27bf414c JM |
2716 | c_parser_consume_token (parser); |
2717 | break; | |
38b7bc7f JM |
2718 | case RID_AUTO_TYPE: |
2719 | if (!auto_type_ok) | |
2720 | goto out; | |
2721 | /* Fall through. */ | |
27bf414c JM |
2722 | case RID_UNSIGNED: |
2723 | case RID_LONG: | |
2724 | case RID_SHORT: | |
2725 | case RID_SIGNED: | |
2726 | case RID_COMPLEX: | |
2727 | case RID_INT: | |
2728 | case RID_CHAR: | |
2729 | case RID_FLOAT: | |
2730 | case RID_DOUBLE: | |
2731 | case RID_VOID: | |
9a8ce21f JG |
2732 | case RID_DFLOAT32: |
2733 | case RID_DFLOAT64: | |
2734 | case RID_DFLOAT128: | |
c65699ef | 2735 | CASE_RID_FLOATN_NX: |
27bf414c | 2736 | case RID_BOOL: |
ab22c1fa CF |
2737 | case RID_FRACT: |
2738 | case RID_ACCUM: | |
2739 | case RID_SAT: | |
78a7c317 DD |
2740 | case RID_INT_N_0: |
2741 | case RID_INT_N_1: | |
2742 | case RID_INT_N_2: | |
2743 | case RID_INT_N_3: | |
27bf414c JM |
2744 | if (!typespec_ok) |
2745 | goto out; | |
2746 | attrs_ok = true; | |
2747 | seen_type = true; | |
0bacb8c7 TT |
2748 | if (c_dialect_objc ()) |
2749 | parser->objc_need_raw_identifier = true; | |
27bf414c JM |
2750 | t.kind = ctsk_resword; |
2751 | t.spec = c_parser_peek_token (parser)->value; | |
928c19bb JM |
2752 | t.expr = NULL_TREE; |
2753 | t.expr_const_operands = true; | |
dc491a25 | 2754 | declspecs_add_type (loc, specs, t); |
27bf414c JM |
2755 | c_parser_consume_token (parser); |
2756 | break; | |
2757 | case RID_ENUM: | |
2758 | if (!typespec_ok) | |
2759 | goto out; | |
2760 | attrs_ok = true; | |
2761 | seen_type = true; | |
2762 | t = c_parser_enum_specifier (parser); | |
a4bb6959 | 2763 | invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec); |
dc491a25 | 2764 | declspecs_add_type (loc, specs, t); |
27bf414c JM |
2765 | break; |
2766 | case RID_STRUCT: | |
2767 | case RID_UNION: | |
2768 | if (!typespec_ok) | |
2769 | goto out; | |
2770 | attrs_ok = true; | |
2771 | seen_type = true; | |
2772 | t = c_parser_struct_or_union_specifier (parser); | |
dab71827 | 2773 | invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec); |
dc491a25 | 2774 | declspecs_add_type (loc, specs, t); |
27bf414c JM |
2775 | break; |
2776 | case RID_TYPEOF: | |
2777 | /* ??? The old parser rejected typeof after other type | |
2778 | specifiers, but is a syntax error the best way of | |
2779 | handling this? */ | |
2780 | if (!typespec_ok || seen_type) | |
2781 | goto out; | |
2782 | attrs_ok = true; | |
2783 | seen_type = true; | |
2784 | t = c_parser_typeof_specifier (parser); | |
dc491a25 | 2785 | declspecs_add_type (loc, specs, t); |
27bf414c | 2786 | break; |
267bac10 JM |
2787 | case RID_ATOMIC: |
2788 | /* C parser handling of Objective-C constructs needs | |
2789 | checking for correct lvalue-to-rvalue conversions, and | |
2790 | the code in build_modify_expr handling various | |
2791 | Objective-C cases, and that in build_unary_op handling | |
2792 | Objective-C cases for increment / decrement, also needs | |
2793 | updating; uses of TYPE_MAIN_VARIANT in objc_compare_types | |
2794 | and objc_types_are_equivalent may also need updates. */ | |
2795 | if (c_dialect_objc ()) | |
2796 | sorry ("%<_Atomic%> in Objective-C"); | |
35aff4fb MP |
2797 | if (flag_isoc99) |
2798 | pedwarn_c99 (loc, OPT_Wpedantic, | |
267bac10 | 2799 | "ISO C99 does not support the %<_Atomic%> qualifier"); |
35aff4fb MP |
2800 | else |
2801 | pedwarn_c99 (loc, OPT_Wpedantic, | |
267bac10 | 2802 | "ISO C90 does not support the %<_Atomic%> qualifier"); |
267bac10 JM |
2803 | attrs_ok = true; |
2804 | tree value; | |
2805 | value = c_parser_peek_token (parser)->value; | |
2806 | c_parser_consume_token (parser); | |
2807 | if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
2808 | { | |
2809 | /* _Atomic ( type-name ). */ | |
2810 | seen_type = true; | |
2811 | c_parser_consume_token (parser); | |
2812 | struct c_type_name *type = c_parser_type_name (parser); | |
2813 | t.kind = ctsk_typeof; | |
2814 | t.spec = error_mark_node; | |
2815 | t.expr = NULL_TREE; | |
2816 | t.expr_const_operands = true; | |
2817 | if (type != NULL) | |
2818 | t.spec = groktypename (type, &t.expr, | |
2819 | &t.expr_const_operands); | |
2820 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
2821 | "expected %<)%>"); | |
2822 | if (t.spec != error_mark_node) | |
2823 | { | |
2824 | if (TREE_CODE (t.spec) == ARRAY_TYPE) | |
2825 | error_at (loc, "%<_Atomic%>-qualified array type"); | |
2826 | else if (TREE_CODE (t.spec) == FUNCTION_TYPE) | |
2827 | error_at (loc, "%<_Atomic%>-qualified function type"); | |
2828 | else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED) | |
2829 | error_at (loc, "%<_Atomic%> applied to a qualified type"); | |
2830 | else | |
2831 | t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC); | |
2832 | } | |
2833 | declspecs_add_type (loc, specs, t); | |
2834 | } | |
2835 | else | |
2836 | declspecs_add_qual (loc, specs, value); | |
2837 | break; | |
27bf414c JM |
2838 | case RID_CONST: |
2839 | case RID_VOLATILE: | |
2840 | case RID_RESTRICT: | |
2841 | attrs_ok = true; | |
0b2c4be5 | 2842 | declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value); |
27bf414c JM |
2843 | c_parser_consume_token (parser); |
2844 | break; | |
2845 | case RID_ATTRIBUTE: | |
2846 | if (!attrs_ok) | |
2847 | goto out; | |
2848 | attrs = c_parser_attributes (parser); | |
0b2c4be5 | 2849 | declspecs_add_attrs (loc, specs, attrs); |
27bf414c | 2850 | break; |
d19fa6b5 | 2851 | case RID_ALIGNAS: |
568a31f2 MP |
2852 | if (!alignspec_ok) |
2853 | goto out; | |
d19fa6b5 | 2854 | align = c_parser_alignas_specifier (parser); |
0b2c4be5 | 2855 | declspecs_add_alignas (loc, specs, align); |
d19fa6b5 | 2856 | break; |
1ee62b92 PG |
2857 | case RID_GIMPLE: |
2858 | if (! flag_gimple) | |
2859 | error_at (loc, "%<__GIMPLE%> only valid with -fgimple"); | |
2860 | c_parser_consume_token (parser); | |
2861 | specs->gimple_p = true; | |
2862 | specs->locations[cdw_gimple] = loc; | |
c2e84327 DM |
2863 | specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser); |
2864 | break; | |
2865 | case RID_RTL: | |
2866 | c_parser_consume_token (parser); | |
2867 | specs->rtl_p = true; | |
2868 | specs->locations[cdw_rtl] = loc; | |
2869 | specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser); | |
1ee62b92 | 2870 | break; |
27bf414c JM |
2871 | default: |
2872 | goto out; | |
2873 | } | |
2874 | } | |
2875 | out: ; | |
2876 | } | |
2877 | ||
31dc71a8 | 2878 | /* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2). |
27bf414c JM |
2879 | |
2880 | enum-specifier: | |
2881 | enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt] | |
2882 | enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt] | |
2883 | enum attributes[opt] identifier | |
2884 | ||
2885 | The form with trailing comma is new in C99. The forms with | |
2886 | attributes are GNU extensions. In GNU C, we accept any expression | |
2887 | without commas in the syntax (assignment expressions, not just | |
2888 | conditional expressions); assignment expressions will be diagnosed | |
2889 | as non-constant. | |
2890 | ||
2891 | enumerator-list: | |
2892 | enumerator | |
2893 | enumerator-list , enumerator | |
2894 | ||
2895 | enumerator: | |
2896 | enumeration-constant | |
2897 | enumeration-constant = constant-expression | |
fd5c817a MP |
2898 | |
2899 | GNU Extensions: | |
2900 | ||
2901 | enumerator: | |
2902 | enumeration-constant attributes[opt] | |
2903 | enumeration-constant attributes[opt] = constant-expression | |
2904 | ||
27bf414c JM |
2905 | */ |
2906 | ||
2907 | static struct c_typespec | |
2908 | c_parser_enum_specifier (c_parser *parser) | |
2909 | { | |
2910 | struct c_typespec ret; | |
2911 | tree attrs; | |
2912 | tree ident = NULL_TREE; | |
24b97832 | 2913 | location_t enum_loc; |
922f2908 | 2914 | location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
27bf414c JM |
2915 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM)); |
2916 | c_parser_consume_token (parser); | |
2917 | attrs = c_parser_attributes (parser); | |
c2255bc4 | 2918 | enum_loc = c_parser_peek_token (parser)->location; |
5af28c74 TT |
2919 | /* Set the location in case we create a decl now. */ |
2920 | c_parser_set_source_position_from_token (c_parser_peek_token (parser)); | |
27bf414c JM |
2921 | if (c_parser_next_token_is (parser, CPP_NAME)) |
2922 | { | |
2923 | ident = c_parser_peek_token (parser)->value; | |
c7412148 | 2924 | ident_loc = c_parser_peek_token (parser)->location; |
24b97832 | 2925 | enum_loc = ident_loc; |
27bf414c JM |
2926 | c_parser_consume_token (parser); |
2927 | } | |
2928 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
2929 | { | |
2930 | /* Parse an enum definition. */ | |
7114359f | 2931 | struct c_enum_contents the_enum; |
575bfb00 | 2932 | tree type; |
27bf414c JM |
2933 | tree postfix_attrs; |
2934 | /* We chain the enumerators in reverse order, then put them in | |
2935 | forward order at the end. */ | |
575bfb00 LC |
2936 | tree values; |
2937 | timevar_push (TV_PARSE_ENUM); | |
2938 | type = start_enum (enum_loc, &the_enum, ident); | |
2939 | values = NULL_TREE; | |
27bf414c JM |
2940 | c_parser_consume_token (parser); |
2941 | while (true) | |
2942 | { | |
2943 | tree enum_id; | |
2944 | tree enum_value; | |
2945 | tree enum_decl; | |
2946 | bool seen_comma; | |
5af28c74 | 2947 | c_token *token; |
922f2908 | 2948 | location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
7370e0da | 2949 | location_t decl_loc, value_loc; |
27bf414c JM |
2950 | if (c_parser_next_token_is_not (parser, CPP_NAME)) |
2951 | { | |
d04ff417 MP |
2952 | /* Give a nicer error for "enum {}". */ |
2953 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE) | |
2954 | && !parser->error) | |
2955 | { | |
2956 | error_at (c_parser_peek_token (parser)->location, | |
2957 | "empty enum is invalid"); | |
2958 | parser->error = true; | |
2959 | } | |
2960 | else | |
2961 | c_parser_error (parser, "expected identifier"); | |
27bf414c JM |
2962 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); |
2963 | values = error_mark_node; | |
2964 | break; | |
2965 | } | |
5af28c74 TT |
2966 | token = c_parser_peek_token (parser); |
2967 | enum_id = token->value; | |
2968 | /* Set the location in case we create a decl now. */ | |
2969 | c_parser_set_source_position_from_token (token); | |
7370e0da | 2970 | decl_loc = value_loc = token->location; |
27bf414c | 2971 | c_parser_consume_token (parser); |
fd5c817a MP |
2972 | /* Parse any specified attributes. */ |
2973 | tree enum_attrs = c_parser_attributes (parser); | |
27bf414c JM |
2974 | if (c_parser_next_token_is (parser, CPP_EQ)) |
2975 | { | |
2976 | c_parser_consume_token (parser); | |
85790e66 | 2977 | value_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
2978 | enum_value = c_parser_expr_no_commas (parser, NULL).value; |
2979 | } | |
2980 | else | |
2981 | enum_value = NULL_TREE; | |
7370e0da | 2982 | enum_decl = build_enumerator (decl_loc, value_loc, |
fd5c817a MP |
2983 | &the_enum, enum_id, enum_value); |
2984 | if (enum_attrs) | |
2985 | decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0); | |
27bf414c JM |
2986 | TREE_CHAIN (enum_decl) = values; |
2987 | values = enum_decl; | |
2988 | seen_comma = false; | |
2989 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
2990 | { | |
c7412148 | 2991 | comma_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
2992 | seen_comma = true; |
2993 | c_parser_consume_token (parser); | |
2994 | } | |
2995 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
2996 | { | |
f3bede71 MP |
2997 | if (seen_comma) |
2998 | pedwarn_c90 (comma_loc, OPT_Wpedantic, | |
2999 | "comma at end of enumerator list"); | |
27bf414c JM |
3000 | c_parser_consume_token (parser); |
3001 | break; | |
3002 | } | |
3003 | if (!seen_comma) | |
3004 | { | |
3005 | c_parser_error (parser, "expected %<,%> or %<}%>"); | |
3006 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); | |
3007 | values = error_mark_node; | |
3008 | break; | |
3009 | } | |
3010 | } | |
3011 | postfix_attrs = c_parser_attributes (parser); | |
3012 | ret.spec = finish_enum (type, nreverse (values), | |
3013 | chainon (attrs, postfix_attrs)); | |
3014 | ret.kind = ctsk_tagdef; | |
928c19bb JM |
3015 | ret.expr = NULL_TREE; |
3016 | ret.expr_const_operands = true; | |
575bfb00 | 3017 | timevar_pop (TV_PARSE_ENUM); |
27bf414c JM |
3018 | return ret; |
3019 | } | |
3020 | else if (!ident) | |
3021 | { | |
3022 | c_parser_error (parser, "expected %<{%>"); | |
3023 | ret.spec = error_mark_node; | |
3024 | ret.kind = ctsk_tagref; | |
928c19bb JM |
3025 | ret.expr = NULL_TREE; |
3026 | ret.expr_const_operands = true; | |
27bf414c JM |
3027 | return ret; |
3028 | } | |
c2255bc4 | 3029 | ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident); |
27bf414c JM |
3030 | /* In ISO C, enumerated types can be referred to only if already |
3031 | defined. */ | |
3032 | if (pedantic && !COMPLETE_TYPE_P (ret.spec)) | |
c7412148 TT |
3033 | { |
3034 | gcc_assert (ident); | |
c1771a20 | 3035 | pedwarn (enum_loc, OPT_Wpedantic, |
509c9d60 | 3036 | "ISO C forbids forward references to %<enum%> types"); |
c7412148 | 3037 | } |
27bf414c JM |
3038 | return ret; |
3039 | } | |
3040 | ||
31dc71a8 | 3041 | /* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1). |
27bf414c JM |
3042 | |
3043 | struct-or-union-specifier: | |
3044 | struct-or-union attributes[opt] identifier[opt] | |
3045 | { struct-contents } attributes[opt] | |
3046 | struct-or-union attributes[opt] identifier | |
3047 | ||
3048 | struct-contents: | |
3049 | struct-declaration-list | |
3050 | ||
3051 | struct-declaration-list: | |
3052 | struct-declaration ; | |
3053 | struct-declaration-list struct-declaration ; | |
3054 | ||
3055 | GNU extensions: | |
3056 | ||
3057 | struct-contents: | |
3058 | empty | |
3059 | struct-declaration | |
3060 | struct-declaration-list struct-declaration | |
3061 | ||
3062 | struct-declaration-list: | |
3063 | struct-declaration-list ; | |
3064 | ; | |
3065 | ||
3066 | (Note that in the syntax here, unlike that in ISO C, the semicolons | |
3067 | are included here rather than in struct-declaration, in order to | |
3068 | describe the syntax with extra semicolons and missing semicolon at | |
3069 | end.) | |
3070 | ||
3071 | Objective-C: | |
3072 | ||
3073 | struct-declaration-list: | |
3074 | @defs ( class-name ) | |
3075 | ||
3076 | (Note this does not include a trailing semicolon, but can be | |
3077 | followed by further declarations, and gets a pedwarn-if-pedantic | |
3078 | when followed by a semicolon.) */ | |
3079 | ||
3080 | static struct c_typespec | |
3081 | c_parser_struct_or_union_specifier (c_parser *parser) | |
3082 | { | |
3083 | struct c_typespec ret; | |
3084 | tree attrs; | |
3085 | tree ident = NULL_TREE; | |
24b97832 ILT |
3086 | location_t struct_loc; |
3087 | location_t ident_loc = UNKNOWN_LOCATION; | |
27bf414c JM |
3088 | enum tree_code code; |
3089 | switch (c_parser_peek_token (parser)->keyword) | |
3090 | { | |
3091 | case RID_STRUCT: | |
3092 | code = RECORD_TYPE; | |
3093 | break; | |
3094 | case RID_UNION: | |
3095 | code = UNION_TYPE; | |
3096 | break; | |
3097 | default: | |
3098 | gcc_unreachable (); | |
3099 | } | |
24b97832 | 3100 | struct_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
3101 | c_parser_consume_token (parser); |
3102 | attrs = c_parser_attributes (parser); | |
c2255bc4 | 3103 | |
5af28c74 TT |
3104 | /* Set the location in case we create a decl now. */ |
3105 | c_parser_set_source_position_from_token (c_parser_peek_token (parser)); | |
c2255bc4 | 3106 | |
27bf414c JM |
3107 | if (c_parser_next_token_is (parser, CPP_NAME)) |
3108 | { | |
3109 | ident = c_parser_peek_token (parser)->value; | |
24b97832 ILT |
3110 | ident_loc = c_parser_peek_token (parser)->location; |
3111 | struct_loc = ident_loc; | |
27bf414c JM |
3112 | c_parser_consume_token (parser); |
3113 | } | |
3114 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
3115 | { | |
3116 | /* Parse a struct or union definition. Start the scope of the | |
3117 | tag before parsing components. */ | |
dc491a25 ILT |
3118 | struct c_struct_parse_info *struct_info; |
3119 | tree type = start_struct (struct_loc, code, ident, &struct_info); | |
27bf414c JM |
3120 | tree postfix_attrs; |
3121 | /* We chain the components in reverse order, then put them in | |
3122 | forward order at the end. Each struct-declaration may | |
3123 | declare multiple components (comma-separated), so we must use | |
3124 | chainon to join them, although when parsing each | |
3125 | struct-declaration we can use TREE_CHAIN directly. | |
3126 | ||
3127 | The theory behind all this is that there will be more | |
3128 | semicolon separated fields than comma separated fields, and | |
3129 | so we'll be minimizing the number of node traversals required | |
3130 | by chainon. */ | |
575bfb00 LC |
3131 | tree contents; |
3132 | timevar_push (TV_PARSE_STRUCT); | |
3133 | contents = NULL_TREE; | |
27bf414c JM |
3134 | c_parser_consume_token (parser); |
3135 | /* Handle the Objective-C @defs construct, | |
3136 | e.g. foo(sizeof(struct{ @defs(ClassName) }));. */ | |
3137 | if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS)) | |
3138 | { | |
3139 | tree name; | |
3140 | gcc_assert (c_dialect_objc ()); | |
3141 | c_parser_consume_token (parser); | |
32129a17 DM |
3142 | matching_parens parens; |
3143 | if (!parens.require_open (parser)) | |
27bf414c JM |
3144 | goto end_at_defs; |
3145 | if (c_parser_next_token_is (parser, CPP_NAME) | |
3146 | && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME) | |
3147 | { | |
3148 | name = c_parser_peek_token (parser)->value; | |
3149 | c_parser_consume_token (parser); | |
3150 | } | |
3151 | else | |
3152 | { | |
3153 | c_parser_error (parser, "expected class name"); | |
3154 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
3155 | goto end_at_defs; | |
3156 | } | |
32129a17 | 3157 | parens.skip_until_found_close (parser); |
27bf414c JM |
3158 | contents = nreverse (objc_get_class_ivars (name)); |
3159 | } | |
3160 | end_at_defs: | |
3161 | /* Parse the struct-declarations and semicolons. Problems with | |
3162 | semicolons are diagnosed here; empty structures are diagnosed | |
3163 | elsewhere. */ | |
3164 | while (true) | |
3165 | { | |
3166 | tree decls; | |
3167 | /* Parse any stray semicolon. */ | |
3168 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
3169 | { | |
1c4ea66f DM |
3170 | location_t semicolon_loc |
3171 | = c_parser_peek_token (parser)->location; | |
3172 | gcc_rich_location richloc (semicolon_loc); | |
3173 | richloc.add_fixit_remove (); | |
64a5912c DM |
3174 | pedwarn (&richloc, OPT_Wpedantic, |
3175 | "extra semicolon in struct or union specified"); | |
27bf414c JM |
3176 | c_parser_consume_token (parser); |
3177 | continue; | |
3178 | } | |
3179 | /* Stop if at the end of the struct or union contents. */ | |
3180 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
3181 | { | |
3182 | c_parser_consume_token (parser); | |
3183 | break; | |
3184 | } | |
bc4071dd RH |
3185 | /* Accept #pragmas at struct scope. */ |
3186 | if (c_parser_next_token_is (parser, CPP_PRAGMA)) | |
3187 | { | |
dda1bf61 | 3188 | c_parser_pragma (parser, pragma_struct, NULL); |
bc4071dd RH |
3189 | continue; |
3190 | } | |
27bf414c JM |
3191 | /* Parse some comma-separated declarations, but not the |
3192 | trailing semicolon if any. */ | |
3193 | decls = c_parser_struct_declaration (parser); | |
3194 | contents = chainon (decls, contents); | |
3195 | /* If no semicolon follows, either we have a parse error or | |
3196 | are at the end of the struct or union and should | |
3197 | pedwarn. */ | |
3198 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
3199 | c_parser_consume_token (parser); | |
3200 | else | |
3201 | { | |
3202 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
b8698a0f | 3203 | pedwarn (c_parser_peek_token (parser)->location, 0, |
509c9d60 | 3204 | "no semicolon at end of struct or union"); |
f725e721 PB |
3205 | else if (parser->error |
3206 | || !c_parser_next_token_starts_declspecs (parser)) | |
27bf414c JM |
3207 | { |
3208 | c_parser_error (parser, "expected %<;%>"); | |
3209 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); | |
3210 | break; | |
3211 | } | |
f725e721 PB |
3212 | |
3213 | /* If we come here, we have already emitted an error | |
3214 | for an expected `;', identifier or `(', and we also | |
3215 | recovered already. Go on with the next field. */ | |
27bf414c JM |
3216 | } |
3217 | } | |
3218 | postfix_attrs = c_parser_attributes (parser); | |
c2255bc4 | 3219 | ret.spec = finish_struct (struct_loc, type, nreverse (contents), |
dc491a25 | 3220 | chainon (attrs, postfix_attrs), struct_info); |
27bf414c | 3221 | ret.kind = ctsk_tagdef; |
928c19bb JM |
3222 | ret.expr = NULL_TREE; |
3223 | ret.expr_const_operands = true; | |
575bfb00 | 3224 | timevar_pop (TV_PARSE_STRUCT); |
27bf414c JM |
3225 | return ret; |
3226 | } | |
3227 | else if (!ident) | |
3228 | { | |
3229 | c_parser_error (parser, "expected %<{%>"); | |
3230 | ret.spec = error_mark_node; | |
3231 | ret.kind = ctsk_tagref; | |
928c19bb JM |
3232 | ret.expr = NULL_TREE; |
3233 | ret.expr_const_operands = true; | |
67c2939d | 3234 | return ret; |
27bf414c | 3235 | } |
c2255bc4 | 3236 | ret = parser_xref_tag (ident_loc, code, ident); |
27bf414c JM |
3237 | return ret; |
3238 | } | |
3239 | ||
31dc71a8 MP |
3240 | /* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1), |
3241 | *without* the trailing semicolon. | |
27bf414c JM |
3242 | |
3243 | struct-declaration: | |
3244 | specifier-qualifier-list struct-declarator-list | |
32912286 | 3245 | static_assert-declaration-no-semi |
27bf414c JM |
3246 | |
3247 | specifier-qualifier-list: | |
3248 | type-specifier specifier-qualifier-list[opt] | |
3249 | type-qualifier specifier-qualifier-list[opt] | |
3250 | attributes specifier-qualifier-list[opt] | |
3251 | ||
3252 | struct-declarator-list: | |
3253 | struct-declarator | |
3254 | struct-declarator-list , attributes[opt] struct-declarator | |
3255 | ||
3256 | struct-declarator: | |
3257 | declarator attributes[opt] | |
3258 | declarator[opt] : constant-expression attributes[opt] | |
3259 | ||
3260 | GNU extensions: | |
3261 | ||
3262 | struct-declaration: | |
3263 | __extension__ struct-declaration | |
3264 | specifier-qualifier-list | |
3265 | ||
3266 | Unlike the ISO C syntax, semicolons are handled elsewhere. The use | |
3267 | of attributes where shown is a GNU extension. In GNU C, we accept | |
3268 | any expression without commas in the syntax (assignment | |
3269 | expressions, not just conditional expressions); assignment | |
3270 | expressions will be diagnosed as non-constant. */ | |
3271 | ||
3272 | static tree | |
3273 | c_parser_struct_declaration (c_parser *parser) | |
3274 | { | |
3275 | struct c_declspecs *specs; | |
3276 | tree prefix_attrs; | |
3277 | tree all_prefix_attrs; | |
3278 | tree decls; | |
c7412148 | 3279 | location_t decl_loc; |
27bf414c JM |
3280 | if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) |
3281 | { | |
3282 | int ext; | |
3283 | tree decl; | |
3284 | ext = disable_extension_diagnostics (); | |
3285 | c_parser_consume_token (parser); | |
3286 | decl = c_parser_struct_declaration (parser); | |
3287 | restore_extension_diagnostics (ext); | |
3288 | return decl; | |
3289 | } | |
32912286 JM |
3290 | if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) |
3291 | { | |
3292 | c_parser_static_assert_declaration_no_semi (parser); | |
3293 | return NULL_TREE; | |
3294 | } | |
27bf414c | 3295 | specs = build_null_declspecs (); |
c7412148 | 3296 | decl_loc = c_parser_peek_token (parser)->location; |
f28aa681 MP |
3297 | /* Strictly by the standard, we shouldn't allow _Alignas here, |
3298 | but it appears to have been intended to allow it there, so | |
3299 | we're keeping it as it is until WG14 reaches a conclusion | |
3300 | of N1731. | |
3301 | <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */ | |
568a31f2 | 3302 | c_parser_declspecs (parser, specs, false, true, true, |
38b7bc7f | 3303 | true, false, cla_nonabstract_decl); |
27bf414c | 3304 | if (parser->error) |
67c2939d | 3305 | return NULL_TREE; |
27bf414c JM |
3306 | if (!specs->declspecs_seen_p) |
3307 | { | |
3308 | c_parser_error (parser, "expected specifier-qualifier-list"); | |
3309 | return NULL_TREE; | |
3310 | } | |
3311 | finish_declspecs (specs); | |
b8cbdff5 JM |
3312 | if (c_parser_next_token_is (parser, CPP_SEMICOLON) |
3313 | || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
27bf414c JM |
3314 | { |
3315 | tree ret; | |
9e5b2115 | 3316 | if (specs->typespec_kind == ctsk_none) |
27bf414c | 3317 | { |
c1771a20 | 3318 | pedwarn (decl_loc, OPT_Wpedantic, |
509c9d60 | 3319 | "ISO C forbids member declarations with no members"); |
27bf414c JM |
3320 | shadow_tag_warned (specs, pedantic); |
3321 | ret = NULL_TREE; | |
3322 | } | |
3323 | else | |
3324 | { | |
3325 | /* Support for unnamed structs or unions as members of | |
3326 | structs or unions (which is [a] useful and [b] supports | |
3327 | MS P-SDK). */ | |
b9baeecd | 3328 | tree attrs = NULL; |
3d10ed6c AH |
3329 | |
3330 | ret = grokfield (c_parser_peek_token (parser)->location, | |
3331 | build_id_declarator (NULL_TREE), specs, | |
b9baeecd | 3332 | NULL_TREE, &attrs); |
0ad7e054 RS |
3333 | if (ret) |
3334 | decl_attributes (&ret, attrs, 0); | |
27bf414c JM |
3335 | } |
3336 | return ret; | |
3337 | } | |
f725e721 PB |
3338 | |
3339 | /* Provide better error recovery. Note that a type name here is valid, | |
3340 | and will be treated as a field name. */ | |
3341 | if (specs->typespec_kind == ctsk_tagdef | |
3342 | && TREE_CODE (specs->type) != ENUMERAL_TYPE | |
3343 | && c_parser_next_token_starts_declspecs (parser) | |
3344 | && !c_parser_next_token_is (parser, CPP_NAME)) | |
3345 | { | |
3346 | c_parser_error (parser, "expected %<;%>, identifier or %<(%>"); | |
3347 | parser->error = false; | |
3348 | return NULL_TREE; | |
3349 | } | |
3350 | ||
27bf414c JM |
3351 | pending_xref_error (); |
3352 | prefix_attrs = specs->attrs; | |
3353 | all_prefix_attrs = prefix_attrs; | |
3354 | specs->attrs = NULL_TREE; | |
3355 | decls = NULL_TREE; | |
3356 | while (true) | |
3357 | { | |
3358 | /* Declaring one or more declarators or un-named bit-fields. */ | |
3359 | struct c_declarator *declarator; | |
3360 | bool dummy = false; | |
3361 | if (c_parser_next_token_is (parser, CPP_COLON)) | |
3362 | declarator = build_id_declarator (NULL_TREE); | |
3363 | else | |
9e5b2115 PB |
3364 | declarator = c_parser_declarator (parser, |
3365 | specs->typespec_kind != ctsk_none, | |
27bf414c JM |
3366 | C_DTR_NORMAL, &dummy); |
3367 | if (declarator == NULL) | |
3368 | { | |
3369 | c_parser_skip_to_end_of_block_or_statement (parser); | |
3370 | break; | |
3371 | } | |
3372 | if (c_parser_next_token_is (parser, CPP_COLON) | |
3373 | || c_parser_next_token_is (parser, CPP_COMMA) | |
3374 | || c_parser_next_token_is (parser, CPP_SEMICOLON) | |
3375 | || c_parser_next_token_is (parser, CPP_CLOSE_BRACE) | |
3376 | || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
3377 | { | |
3378 | tree postfix_attrs = NULL_TREE; | |
3379 | tree width = NULL_TREE; | |
3380 | tree d; | |
3381 | if (c_parser_next_token_is (parser, CPP_COLON)) | |
3382 | { | |
3383 | c_parser_consume_token (parser); | |
3384 | width = c_parser_expr_no_commas (parser, NULL).value; | |
3385 | } | |
3386 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
3387 | postfix_attrs = c_parser_attributes (parser); | |
3d10ed6c AH |
3388 | d = grokfield (c_parser_peek_token (parser)->location, |
3389 | declarator, specs, width, &all_prefix_attrs); | |
27bf414c JM |
3390 | decl_attributes (&d, chainon (postfix_attrs, |
3391 | all_prefix_attrs), 0); | |
910ad8de | 3392 | DECL_CHAIN (d) = decls; |
27bf414c JM |
3393 | decls = d; |
3394 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
3395 | all_prefix_attrs = chainon (c_parser_attributes (parser), | |
3396 | prefix_attrs); | |
3397 | else | |
3398 | all_prefix_attrs = prefix_attrs; | |
3399 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
3400 | c_parser_consume_token (parser); | |
3401 | else if (c_parser_next_token_is (parser, CPP_SEMICOLON) | |
3402 | || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
3403 | { | |
3404 | /* Semicolon consumed in caller. */ | |
3405 | break; | |
3406 | } | |
3407 | else | |
3408 | { | |
3409 | c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>"); | |
3410 | break; | |
3411 | } | |
3412 | } | |
3413 | else | |
3414 | { | |
3415 | c_parser_error (parser, | |
3416 | "expected %<:%>, %<,%>, %<;%>, %<}%> or " | |
3417 | "%<__attribute__%>"); | |
3418 | break; | |
3419 | } | |
3420 | } | |
3421 | return decls; | |
3422 | } | |
3423 | ||
3424 | /* Parse a typeof specifier (a GNU extension). | |
3425 | ||
3426 | typeof-specifier: | |
3427 | typeof ( expression ) | |
3428 | typeof ( type-name ) | |
3429 | */ | |
3430 | ||
3431 | static struct c_typespec | |
3432 | c_parser_typeof_specifier (c_parser *parser) | |
3433 | { | |
3434 | struct c_typespec ret; | |
3435 | ret.kind = ctsk_typeof; | |
3436 | ret.spec = error_mark_node; | |
928c19bb JM |
3437 | ret.expr = NULL_TREE; |
3438 | ret.expr_const_operands = true; | |
27bf414c JM |
3439 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); |
3440 | c_parser_consume_token (parser); | |
7d882b83 | 3441 | c_inhibit_evaluation_warnings++; |
27bf414c | 3442 | in_typeof++; |
32129a17 DM |
3443 | matching_parens parens; |
3444 | if (!parens.require_open (parser)) | |
27bf414c | 3445 | { |
7d882b83 | 3446 | c_inhibit_evaluation_warnings--; |
27bf414c JM |
3447 | in_typeof--; |
3448 | return ret; | |
3449 | } | |
29ce73cb | 3450 | if (c_parser_next_tokens_start_typename (parser, cla_prefer_id)) |
27bf414c JM |
3451 | { |
3452 | struct c_type_name *type = c_parser_type_name (parser); | |
7d882b83 | 3453 | c_inhibit_evaluation_warnings--; |
27bf414c JM |
3454 | in_typeof--; |
3455 | if (type != NULL) | |
3456 | { | |
928c19bb | 3457 | ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands); |
27bf414c JM |
3458 | pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); |
3459 | } | |
3460 | } | |
3461 | else | |
3462 | { | |
52ffd86e | 3463 | bool was_vm; |
c7412148 | 3464 | location_t here = c_parser_peek_token (parser)->location; |
27bf414c | 3465 | struct c_expr expr = c_parser_expression (parser); |
7d882b83 | 3466 | c_inhibit_evaluation_warnings--; |
27bf414c JM |
3467 | in_typeof--; |
3468 | if (TREE_CODE (expr.value) == COMPONENT_REF | |
3469 | && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) | |
3ba09659 | 3470 | error_at (here, "%<typeof%> applied to a bit-field"); |
ebfbbdc5 | 3471 | mark_exp_read (expr.value); |
27bf414c | 3472 | ret.spec = TREE_TYPE (expr.value); |
52ffd86e | 3473 | was_vm = variably_modified_type_p (ret.spec, NULL_TREE); |
928c19bb JM |
3474 | /* This is returned with the type so that when the type is |
3475 | evaluated, this can be evaluated. */ | |
3476 | if (was_vm) | |
3477 | ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); | |
52ffd86e | 3478 | pop_maybe_used (was_vm); |
9698b078 SH |
3479 | /* For use in macros such as those in <stdatomic.h>, remove all |
3480 | qualifiers from atomic types. (const can be an issue for more macros | |
3481 | using typeof than just the <stdatomic.h> ones.) */ | |
267bac10 | 3482 | if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) |
9698b078 | 3483 | ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED); |
27bf414c | 3484 | } |
32129a17 | 3485 | parens.skip_until_found_close (parser); |
27bf414c JM |
3486 | return ret; |
3487 | } | |
3488 | ||
d19fa6b5 JM |
3489 | /* Parse an alignment-specifier. |
3490 | ||
48b0b196 | 3491 | C11 6.7.5: |
d19fa6b5 JM |
3492 | |
3493 | alignment-specifier: | |
3494 | _Alignas ( type-name ) | |
3495 | _Alignas ( constant-expression ) | |
3496 | */ | |
3497 | ||
3498 | static tree | |
3499 | c_parser_alignas_specifier (c_parser * parser) | |
3500 | { | |
3501 | tree ret = error_mark_node; | |
3502 | location_t loc = c_parser_peek_token (parser)->location; | |
3503 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS)); | |
3504 | c_parser_consume_token (parser); | |
35aff4fb MP |
3505 | if (flag_isoc99) |
3506 | pedwarn_c99 (loc, OPT_Wpedantic, | |
d19fa6b5 | 3507 | "ISO C99 does not support %<_Alignas%>"); |
35aff4fb MP |
3508 | else |
3509 | pedwarn_c99 (loc, OPT_Wpedantic, | |
d19fa6b5 | 3510 | "ISO C90 does not support %<_Alignas%>"); |
32129a17 DM |
3511 | matching_parens parens; |
3512 | if (!parens.require_open (parser)) | |
d19fa6b5 JM |
3513 | return ret; |
3514 | if (c_parser_next_tokens_start_typename (parser, cla_prefer_id)) | |
3515 | { | |
3516 | struct c_type_name *type = c_parser_type_name (parser); | |
3517 | if (type != NULL) | |
296674db JM |
3518 | ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL), |
3519 | false, true, 1); | |
d19fa6b5 JM |
3520 | } |
3521 | else | |
3522 | ret = c_parser_expr_no_commas (parser, NULL).value; | |
32129a17 | 3523 | parens.skip_until_found_close (parser); |
d19fa6b5 JM |
3524 | return ret; |
3525 | } | |
3526 | ||
27bf414c | 3527 | /* Parse a declarator, possibly an abstract declarator (C90 6.5.4, |
31dc71a8 MP |
3528 | 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then |
3529 | a typedef name may be redeclared; otherwise it may not. KIND | |
3530 | indicates which kind of declarator is wanted. Returns a valid | |
3531 | declarator except in the case of a syntax error in which case NULL is | |
3532 | returned. *SEEN_ID is set to true if an identifier being declared is | |
3533 | seen; this is used to diagnose bad forms of abstract array declarators | |
3534 | and to determine whether an identifier list is syntactically permitted. | |
27bf414c JM |
3535 | |
3536 | declarator: | |
3537 | pointer[opt] direct-declarator | |
3538 | ||
3539 | direct-declarator: | |
3540 | identifier | |
3541 | ( attributes[opt] declarator ) | |
3542 | direct-declarator array-declarator | |
3543 | direct-declarator ( parameter-type-list ) | |
3544 | direct-declarator ( identifier-list[opt] ) | |
3545 | ||
3546 | pointer: | |
3547 | * type-qualifier-list[opt] | |
3548 | * type-qualifier-list[opt] pointer | |
3549 | ||
3550 | type-qualifier-list: | |
3551 | type-qualifier | |
3552 | attributes | |
3553 | type-qualifier-list type-qualifier | |
3554 | type-qualifier-list attributes | |
3555 | ||
568a31f2 MP |
3556 | array-declarator: |
3557 | [ type-qualifier-list[opt] assignment-expression[opt] ] | |
3558 | [ static type-qualifier-list[opt] assignment-expression ] | |
3559 | [ type-qualifier-list static assignment-expression ] | |
3560 | [ type-qualifier-list[opt] * ] | |
3561 | ||
27bf414c JM |
3562 | parameter-type-list: |
3563 | parameter-list | |
3564 | parameter-list , ... | |
3565 | ||
3566 | parameter-list: | |
3567 | parameter-declaration | |
3568 | parameter-list , parameter-declaration | |
3569 | ||
3570 | parameter-declaration: | |
3571 | declaration-specifiers declarator attributes[opt] | |
3572 | declaration-specifiers abstract-declarator[opt] attributes[opt] | |
3573 | ||
3574 | identifier-list: | |
3575 | identifier | |
3576 | identifier-list , identifier | |
3577 | ||
3578 | abstract-declarator: | |
3579 | pointer | |
3580 | pointer[opt] direct-abstract-declarator | |
3581 | ||
3582 | direct-abstract-declarator: | |
3583 | ( attributes[opt] abstract-declarator ) | |
3584 | direct-abstract-declarator[opt] array-declarator | |
3585 | direct-abstract-declarator[opt] ( parameter-type-list[opt] ) | |
3586 | ||
3587 | GNU extensions: | |
3588 | ||
3589 | direct-declarator: | |
3590 | direct-declarator ( parameter-forward-declarations | |
3591 | parameter-type-list[opt] ) | |
3592 | ||
3593 | direct-abstract-declarator: | |
c22cacf3 | 3594 | direct-abstract-declarator[opt] ( parameter-forward-declarations |
27bf414c JM |
3595 | parameter-type-list[opt] ) |
3596 | ||
3597 | parameter-forward-declarations: | |
3598 | parameter-list ; | |
3599 | parameter-forward-declarations parameter-list ; | |
3600 | ||
3601 | The uses of attributes shown above are GNU extensions. | |
3602 | ||
3603 | Some forms of array declarator are not included in C99 in the | |
3604 | syntax for abstract declarators; these are disallowed elsewhere. | |
3605 | This may be a defect (DR#289). | |
3606 | ||
3607 | This function also accepts an omitted abstract declarator as being | |
3608 | an abstract declarator, although not part of the formal syntax. */ | |
3609 | ||
1ee62b92 | 3610 | struct c_declarator * |
27bf414c JM |
3611 | c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, |
3612 | bool *seen_id) | |
3613 | { | |
3614 | /* Parse any initial pointer part. */ | |
3615 | if (c_parser_next_token_is (parser, CPP_MULT)) | |
3616 | { | |
3617 | struct c_declspecs *quals_attrs = build_null_declspecs (); | |
3618 | struct c_declarator *inner; | |
3619 | c_parser_consume_token (parser); | |
568a31f2 | 3620 | c_parser_declspecs (parser, quals_attrs, false, false, true, |
38b7bc7f | 3621 | false, false, cla_prefer_id); |
27bf414c JM |
3622 | inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); |
3623 | if (inner == NULL) | |
3624 | return NULL; | |
3625 | else | |
3626 | return make_pointer_declarator (quals_attrs, inner); | |
3627 | } | |
3628 | /* Now we have a direct declarator, direct abstract declarator or | |
3629 | nothing (which counts as a direct abstract declarator here). */ | |
3630 | return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id); | |
3631 | } | |
3632 | ||
3633 | /* Parse a direct declarator or direct abstract declarator; arguments | |
3634 | as c_parser_declarator. */ | |
3635 | ||
3636 | static struct c_declarator * | |
3637 | c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, | |
3638 | bool *seen_id) | |
3639 | { | |
3640 | /* The direct declarator must start with an identifier (possibly | |
3641 | omitted) or a parenthesized declarator (possibly abstract). In | |
3642 | an ordinary declarator, initial parentheses must start a | |
3643 | parenthesized declarator. In an abstract declarator or parameter | |
3644 | declarator, they could start a parenthesized declarator or a | |
3645 | parameter list. To tell which, the open parenthesis and any | |
3646 | following attributes must be read. If a declaration specifier | |
3647 | follows, then it is a parameter list; if the specifier is a | |
3648 | typedef name, there might be an ambiguity about redeclaring it, | |
3649 | which is resolved in the direction of treating it as a typedef | |
3650 | name. If a close parenthesis follows, it is also an empty | |
3651 | parameter list, as the syntax does not permit empty abstract | |
0fa2e4df | 3652 | declarators. Otherwise, it is a parenthesized declarator (in |
27bf414c JM |
3653 | which case the analysis may be repeated inside it, recursively). |
3654 | ||
3655 | ??? There is an ambiguity in a parameter declaration "int | |
3656 | (__attribute__((foo)) x)", where x is not a typedef name: it | |
3657 | could be an abstract declarator for a function, or declare x with | |
3658 | parentheses. The proper resolution of this ambiguity needs | |
3659 | documenting. At present we follow an accident of the old | |
3660 | parser's implementation, whereby the first parameter must have | |
3661 | some declaration specifiers other than just attributes. Thus as | |
0fa2e4df | 3662 | a parameter declaration it is treated as a parenthesized |
27bf414c JM |
3663 | parameter named x, and as an abstract declarator it is |
3664 | rejected. | |
3665 | ||
3666 | ??? Also following the old parser, attributes inside an empty | |
3667 | parameter list are ignored, making it a list not yielding a | |
3668 | prototype, rather than giving an error or making it have one | |
3669 | parameter with implicit type int. | |
3670 | ||
3671 | ??? Also following the old parser, typedef names may be | |
3672 | redeclared in declarators, but not Objective-C class names. */ | |
3673 | ||
3674 | if (kind != C_DTR_ABSTRACT | |
3675 | && c_parser_next_token_is (parser, CPP_NAME) | |
3676 | && ((type_seen_p | |
a6341d57 NP |
3677 | && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME |
3678 | || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) | |
27bf414c JM |
3679 | || c_parser_peek_token (parser)->id_kind == C_ID_ID)) |
3680 | { | |
3681 | struct c_declarator *inner | |
3682 | = build_id_declarator (c_parser_peek_token (parser)->value); | |
3683 | *seen_id = true; | |
6037d88d | 3684 | inner->id_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
3685 | c_parser_consume_token (parser); |
3686 | return c_parser_direct_declarator_inner (parser, *seen_id, inner); | |
3687 | } | |
3688 | ||
3689 | if (kind != C_DTR_NORMAL | |
3690 | && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) | |
3691 | { | |
3692 | struct c_declarator *inner = build_id_declarator (NULL_TREE); | |
1f40cff3 | 3693 | inner->id_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
3694 | return c_parser_direct_declarator_inner (parser, *seen_id, inner); |
3695 | } | |
3696 | ||
3697 | /* Either we are at the end of an abstract declarator, or we have | |
3698 | parentheses. */ | |
3699 | ||
3700 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
3701 | { | |
3702 | tree attrs; | |
3703 | struct c_declarator *inner; | |
3704 | c_parser_consume_token (parser); | |
3705 | attrs = c_parser_attributes (parser); | |
3706 | if (kind != C_DTR_NORMAL | |
3707 | && (c_parser_next_token_starts_declspecs (parser) | |
3708 | || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) | |
3709 | { | |
3710 | struct c_arg_info *args | |
3711 | = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL, | |
3712 | attrs); | |
3713 | if (args == NULL) | |
3714 | return NULL; | |
3715 | else | |
3716 | { | |
3717 | inner | |
3718 | = build_function_declarator (args, | |
3719 | build_id_declarator (NULL_TREE)); | |
3720 | return c_parser_direct_declarator_inner (parser, *seen_id, | |
3721 | inner); | |
3722 | } | |
3723 | } | |
3724 | /* A parenthesized declarator. */ | |
3725 | inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); | |
3726 | if (inner != NULL && attrs != NULL) | |
3727 | inner = build_attrs_declarator (attrs, inner); | |
3728 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
3729 | { | |
3730 | c_parser_consume_token (parser); | |
3731 | if (inner == NULL) | |
3732 | return NULL; | |
3733 | else | |
3734 | return c_parser_direct_declarator_inner (parser, *seen_id, inner); | |
3735 | } | |
3736 | else | |
3737 | { | |
3738 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
3739 | "expected %<)%>"); | |
3740 | return NULL; | |
3741 | } | |
3742 | } | |
3743 | else | |
3744 | { | |
3745 | if (kind == C_DTR_NORMAL) | |
3746 | { | |
3747 | c_parser_error (parser, "expected identifier or %<(%>"); | |
3748 | return NULL; | |
3749 | } | |
3750 | else | |
3751 | return build_id_declarator (NULL_TREE); | |
3752 | } | |
3753 | } | |
3754 | ||
3755 | /* Parse part of a direct declarator or direct abstract declarator, | |
3756 | given that some (in INNER) has already been parsed; ID_PRESENT is | |
3757 | true if an identifier is present, false for an abstract | |
3758 | declarator. */ | |
3759 | ||
3760 | static struct c_declarator * | |
3761 | c_parser_direct_declarator_inner (c_parser *parser, bool id_present, | |
3762 | struct c_declarator *inner) | |
3763 | { | |
3764 | /* Parse a sequence of array declarators and parameter lists. */ | |
3765 | if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) | |
3766 | { | |
b8698a0f | 3767 | location_t brace_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
3768 | struct c_declarator *declarator; |
3769 | struct c_declspecs *quals_attrs = build_null_declspecs (); | |
3770 | bool static_seen; | |
3771 | bool star_seen; | |
267bac10 JM |
3772 | struct c_expr dimen; |
3773 | dimen.value = NULL_TREE; | |
3774 | dimen.original_code = ERROR_MARK; | |
3775 | dimen.original_type = NULL_TREE; | |
27bf414c | 3776 | c_parser_consume_token (parser); |
568a31f2 | 3777 | c_parser_declspecs (parser, quals_attrs, false, false, true, |
38b7bc7f | 3778 | false, false, cla_prefer_id); |
27bf414c JM |
3779 | static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC); |
3780 | if (static_seen) | |
3781 | c_parser_consume_token (parser); | |
3782 | if (static_seen && !quals_attrs->declspecs_seen_p) | |
568a31f2 | 3783 | c_parser_declspecs (parser, quals_attrs, false, false, true, |
38b7bc7f | 3784 | false, false, cla_prefer_id); |
27bf414c JM |
3785 | if (!quals_attrs->declspecs_seen_p) |
3786 | quals_attrs = NULL; | |
3787 | /* If "static" is present, there must be an array dimension. | |
3788 | Otherwise, there may be a dimension, "*", or no | |
3789 | dimension. */ | |
3790 | if (static_seen) | |
3791 | { | |
3792 | star_seen = false; | |
267bac10 | 3793 | dimen = c_parser_expr_no_commas (parser, NULL); |
27bf414c JM |
3794 | } |
3795 | else | |
3796 | { | |
3797 | if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) | |
3798 | { | |
267bac10 | 3799 | dimen.value = NULL_TREE; |
27bf414c JM |
3800 | star_seen = false; |
3801 | } | |
b72271b9 | 3802 | else if (flag_cilkplus |
36536d79 BI |
3803 | && c_parser_next_token_is (parser, CPP_COLON)) |
3804 | { | |
267bac10 | 3805 | dimen.value = error_mark_node; |
36536d79 BI |
3806 | star_seen = false; |
3807 | error_at (c_parser_peek_token (parser)->location, | |
3808 | "array notations cannot be used in declaration"); | |
3809 | c_parser_consume_token (parser); | |
3810 | } | |
27bf414c JM |
3811 | else if (c_parser_next_token_is (parser, CPP_MULT)) |
3812 | { | |
3813 | if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE) | |
3814 | { | |
267bac10 | 3815 | dimen.value = NULL_TREE; |
27bf414c JM |
3816 | star_seen = true; |
3817 | c_parser_consume_token (parser); | |
3818 | } | |
3819 | else | |
3820 | { | |
3821 | star_seen = false; | |
267bac10 | 3822 | dimen = c_parser_expr_no_commas (parser, NULL); |
27bf414c JM |
3823 | } |
3824 | } | |
3825 | else | |
3826 | { | |
3827 | star_seen = false; | |
267bac10 | 3828 | dimen = c_parser_expr_no_commas (parser, NULL); |
27bf414c JM |
3829 | } |
3830 | } | |
3831 | if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) | |
3832 | c_parser_consume_token (parser); | |
b72271b9 | 3833 | else if (flag_cilkplus |
36536d79 BI |
3834 | && c_parser_next_token_is (parser, CPP_COLON)) |
3835 | { | |
3836 | error_at (c_parser_peek_token (parser)->location, | |
3837 | "array notations cannot be used in declaration"); | |
3838 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
3839 | return NULL; | |
3840 | } | |
27bf414c JM |
3841 | else |
3842 | { | |
3843 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, | |
3844 | "expected %<]%>"); | |
3845 | return NULL; | |
3846 | } | |
267bac10 JM |
3847 | if (dimen.value) |
3848 | dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true); | |
3849 | declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs, | |
c2255bc4 | 3850 | static_seen, star_seen); |
52ffd86e MS |
3851 | if (declarator == NULL) |
3852 | return NULL; | |
6ac0194d | 3853 | inner = set_array_declarator_inner (declarator, inner); |
27bf414c JM |
3854 | return c_parser_direct_declarator_inner (parser, id_present, inner); |
3855 | } | |
3856 | else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
3857 | { | |
3858 | tree attrs; | |
3859 | struct c_arg_info *args; | |
3860 | c_parser_consume_token (parser); | |
3861 | attrs = c_parser_attributes (parser); | |
3862 | args = c_parser_parms_declarator (parser, id_present, attrs); | |
3863 | if (args == NULL) | |
3864 | return NULL; | |
3865 | else | |
3866 | { | |
3867 | inner = build_function_declarator (args, inner); | |
3868 | return c_parser_direct_declarator_inner (parser, id_present, inner); | |
3869 | } | |
3870 | } | |
3871 | return inner; | |
3872 | } | |
3873 | ||
3874 | /* Parse a parameter list or identifier list, including the closing | |
3875 | parenthesis but not the opening one. ATTRS are the attributes at | |
3876 | the start of the list. ID_LIST_OK is true if an identifier list is | |
3877 | acceptable; such a list must not have attributes at the start. */ | |
3878 | ||
3879 | static struct c_arg_info * | |
3880 | c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs) | |
3881 | { | |
3882 | push_scope (); | |
3883 | declare_parm_level (); | |
3884 | /* If the list starts with an identifier, it is an identifier list. | |
3885 | Otherwise, it is either a prototype list or an empty list. */ | |
3886 | if (id_list_ok | |
3887 | && !attrs | |
3888 | && c_parser_next_token_is (parser, CPP_NAME) | |
29ce73cb PB |
3889 | && c_parser_peek_token (parser)->id_kind == C_ID_ID |
3890 | ||
3891 | /* Look ahead to detect typos in type names. */ | |
3892 | && c_parser_peek_2nd_token (parser)->type != CPP_NAME | |
3893 | && c_parser_peek_2nd_token (parser)->type != CPP_MULT | |
3894 | && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN | |
1a4f11c8 DM |
3895 | && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE |
3896 | && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD) | |
27bf414c | 3897 | { |
7fa3585c | 3898 | tree list = NULL_TREE, *nextp = &list; |
27bf414c JM |
3899 | while (c_parser_next_token_is (parser, CPP_NAME) |
3900 | && c_parser_peek_token (parser)->id_kind == C_ID_ID) | |
3901 | { | |
7fa3585c GK |
3902 | *nextp = build_tree_list (NULL_TREE, |
3903 | c_parser_peek_token (parser)->value); | |
3904 | nextp = & TREE_CHAIN (*nextp); | |
27bf414c JM |
3905 | c_parser_consume_token (parser); |
3906 | if (c_parser_next_token_is_not (parser, CPP_COMMA)) | |
3907 | break; | |
3908 | c_parser_consume_token (parser); | |
3909 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
3910 | { | |
3911 | c_parser_error (parser, "expected identifier"); | |
3912 | break; | |
3913 | } | |
3914 | } | |
3915 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
3916 | { | |
b3399d18 | 3917 | struct c_arg_info *ret = build_arg_info (); |
27bf414c | 3918 | ret->types = list; |
27bf414c JM |
3919 | c_parser_consume_token (parser); |
3920 | pop_scope (); | |
3921 | return ret; | |
3922 | } | |
3923 | else | |
3924 | { | |
3925 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
3926 | "expected %<)%>"); | |
3927 | pop_scope (); | |
3928 | return NULL; | |
3929 | } | |
3930 | } | |
3931 | else | |
3932 | { | |
a04a722b JM |
3933 | struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs, |
3934 | NULL); | |
27bf414c JM |
3935 | pop_scope (); |
3936 | return ret; | |
3937 | } | |
3938 | } | |
3939 | ||
3940 | /* Parse a parameter list (possibly empty), including the closing | |
3941 | parenthesis but not the opening one. ATTRS are the attributes at | |
a04a722b JM |
3942 | the start of the list. EXPR is NULL or an expression that needs to |
3943 | be evaluated for the side effects of array size expressions in the | |
3944 | parameters. */ | |
27bf414c JM |
3945 | |
3946 | static struct c_arg_info * | |
a04a722b | 3947 | c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr) |
27bf414c | 3948 | { |
09a1e889 | 3949 | bool bad_parm = false; |
a04a722b | 3950 | |
27bf414c JM |
3951 | /* ??? Following the old parser, forward parameter declarations may |
3952 | use abstract declarators, and if no real parameter declarations | |
3953 | follow the forward declarations then this is not diagnosed. Also | |
3954 | note as above that attributes are ignored as the only contents of | |
3955 | the parentheses, or as the only contents after forward | |
3956 | declarations. */ | |
3957 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
3958 | { | |
b3399d18 | 3959 | struct c_arg_info *ret = build_arg_info (); |
27bf414c JM |
3960 | c_parser_consume_token (parser); |
3961 | return ret; | |
3962 | } | |
3963 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
3964 | { | |
b3399d18 | 3965 | struct c_arg_info *ret = build_arg_info (); |
6637388f TG |
3966 | |
3967 | if (flag_allow_parameterless_variadic_functions) | |
3968 | { | |
3969 | /* F (...) is allowed. */ | |
3970 | ret->types = NULL_TREE; | |
3971 | } | |
3972 | else | |
3973 | { | |
3974 | /* Suppress -Wold-style-definition for this case. */ | |
3975 | ret->types = error_mark_node; | |
3976 | error_at (c_parser_peek_token (parser)->location, | |
3977 | "ISO C requires a named argument before %<...%>"); | |
3978 | } | |
27bf414c JM |
3979 | c_parser_consume_token (parser); |
3980 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
3981 | { | |
3982 | c_parser_consume_token (parser); | |
3983 | return ret; | |
3984 | } | |
3985 | else | |
3986 | { | |
3987 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
3988 | "expected %<)%>"); | |
3989 | return NULL; | |
3990 | } | |
3991 | } | |
3992 | /* Nonempty list of parameters, either terminated with semicolon | |
3993 | (forward declarations; recurse) or with close parenthesis (normal | |
3994 | function) or with ", ... )" (variadic function). */ | |
3995 | while (true) | |
3996 | { | |
3997 | /* Parse a parameter. */ | |
3998 | struct c_parm *parm = c_parser_parameter_declaration (parser, attrs); | |
3999 | attrs = NULL_TREE; | |
09a1e889 SZ |
4000 | if (parm == NULL) |
4001 | bad_parm = true; | |
4002 | else | |
a04a722b | 4003 | push_parm_decl (parm, &expr); |
27bf414c JM |
4004 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
4005 | { | |
4006 | tree new_attrs; | |
4007 | c_parser_consume_token (parser); | |
91d975b8 | 4008 | mark_forward_parm_decls (); |
27bf414c | 4009 | new_attrs = c_parser_attributes (parser); |
a04a722b | 4010 | return c_parser_parms_list_declarator (parser, new_attrs, expr); |
27bf414c JM |
4011 | } |
4012 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4013 | { | |
4014 | c_parser_consume_token (parser); | |
09a1e889 | 4015 | if (bad_parm) |
a04a722b | 4016 | return NULL; |
09a1e889 | 4017 | else |
a04a722b | 4018 | return get_parm_info (false, expr); |
27bf414c JM |
4019 | } |
4020 | if (!c_parser_require (parser, CPP_COMMA, | |
62e1c678 DM |
4021 | "expected %<;%>, %<,%> or %<)%>", |
4022 | UNKNOWN_LOCATION, false)) | |
27bf414c JM |
4023 | { |
4024 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
4025 | return NULL; | |
4026 | } | |
4027 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
4028 | { | |
4029 | c_parser_consume_token (parser); | |
4030 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4031 | { | |
4032 | c_parser_consume_token (parser); | |
09a1e889 | 4033 | if (bad_parm) |
a04a722b | 4034 | return NULL; |
09a1e889 | 4035 | else |
a04a722b | 4036 | return get_parm_info (true, expr); |
27bf414c JM |
4037 | } |
4038 | else | |
4039 | { | |
4040 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
4041 | "expected %<)%>"); | |
4042 | return NULL; | |
4043 | } | |
4044 | } | |
4045 | } | |
4046 | } | |
4047 | ||
4048 | /* Parse a parameter declaration. ATTRS are the attributes at the | |
4049 | start of the declaration if it is the first parameter. */ | |
4050 | ||
4051 | static struct c_parm * | |
4052 | c_parser_parameter_declaration (c_parser *parser, tree attrs) | |
4053 | { | |
4054 | struct c_declspecs *specs; | |
4055 | struct c_declarator *declarator; | |
4056 | tree prefix_attrs; | |
4057 | tree postfix_attrs = NULL_TREE; | |
4058 | bool dummy = false; | |
51a1aacf TG |
4059 | |
4060 | /* Accept #pragmas between parameter declarations. */ | |
4061 | while (c_parser_next_token_is (parser, CPP_PRAGMA)) | |
dda1bf61 | 4062 | c_parser_pragma (parser, pragma_param, NULL); |
51a1aacf | 4063 | |
27bf414c JM |
4064 | if (!c_parser_next_token_starts_declspecs (parser)) |
4065 | { | |
09a1e889 SZ |
4066 | c_token *token = c_parser_peek_token (parser); |
4067 | if (parser->error) | |
4068 | return NULL; | |
4069 | c_parser_set_source_position_from_token (token); | |
29ce73cb | 4070 | if (c_parser_next_tokens_start_typename (parser, cla_prefer_type)) |
09a1e889 | 4071 | { |
6c7a259b DM |
4072 | name_hint hint = lookup_name_fuzzy (token->value, |
4073 | FUZZY_LOOKUP_TYPENAME, | |
4074 | token->location); | |
1a4f11c8 DM |
4075 | if (hint) |
4076 | { | |
1a4f11c8 | 4077 | gcc_rich_location richloc (token->location); |
6c7a259b | 4078 | richloc.add_fixit_replace (hint.suggestion ()); |
64a5912c DM |
4079 | error_at (&richloc, |
4080 | "unknown type name %qE; did you mean %qs?", | |
6c7a259b | 4081 | token->value, hint.suggestion ()); |
1a4f11c8 DM |
4082 | } |
4083 | else | |
4084 | error_at (token->location, "unknown type name %qE", token->value); | |
09a1e889 SZ |
4085 | parser->error = true; |
4086 | } | |
27bf414c JM |
4087 | /* ??? In some Objective-C cases '...' isn't applicable so there |
4088 | should be a different message. */ | |
09a1e889 SZ |
4089 | else |
4090 | c_parser_error (parser, | |
4091 | "expected declaration specifiers or %<...%>"); | |
27bf414c JM |
4092 | c_parser_skip_to_end_of_parameter (parser); |
4093 | return NULL; | |
4094 | } | |
8139a48e DM |
4095 | |
4096 | location_t start_loc = c_parser_peek_token (parser)->location; | |
4097 | ||
27bf414c JM |
4098 | specs = build_null_declspecs (); |
4099 | if (attrs) | |
4100 | { | |
0b2c4be5 | 4101 | declspecs_add_attrs (input_location, specs, attrs); |
27bf414c JM |
4102 | attrs = NULL_TREE; |
4103 | } | |
38b7bc7f | 4104 | c_parser_declspecs (parser, specs, true, true, true, true, false, |
568a31f2 | 4105 | cla_nonabstract_decl); |
27bf414c JM |
4106 | finish_declspecs (specs); |
4107 | pending_xref_error (); | |
4108 | prefix_attrs = specs->attrs; | |
4109 | specs->attrs = NULL_TREE; | |
9e5b2115 PB |
4110 | declarator = c_parser_declarator (parser, |
4111 | specs->typespec_kind != ctsk_none, | |
27bf414c JM |
4112 | C_DTR_PARM, &dummy); |
4113 | if (declarator == NULL) | |
4114 | { | |
4115 | c_parser_skip_until_found (parser, CPP_COMMA, NULL); | |
4116 | return NULL; | |
4117 | } | |
4118 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
4119 | postfix_attrs = c_parser_attributes (parser); | |
8139a48e DM |
4120 | |
4121 | /* Generate a location for the parameter, ranging from the start of the | |
4122 | initial token to the end of the final token. | |
4123 | ||
4124 | If we have a identifier, then use it for the caret location, e.g. | |
4125 | ||
4126 | extern int callee (int one, int (*two)(int, int), float three); | |
4127 | ~~~~~~^~~~~~~~~~~~~~ | |
4128 | ||
4129 | otherwise, reuse the start location for the caret location e.g.: | |
4130 | ||
4131 | extern int callee (int one, int (*)(int, int), float three); | |
4132 | ^~~~~~~~~~~~~~~~~ | |
4133 | */ | |
4134 | location_t end_loc = parser->last_token_location; | |
4135 | ||
4136 | /* Find any cdk_id declarator; determine if we have an identifier. */ | |
4137 | c_declarator *id_declarator = declarator; | |
4138 | while (id_declarator && id_declarator->kind != cdk_id) | |
4139 | id_declarator = id_declarator->declarator; | |
4140 | location_t caret_loc = (id_declarator->u.id | |
4141 | ? id_declarator->id_loc | |
4142 | : start_loc); | |
4143 | location_t param_loc = make_location (caret_loc, start_loc, end_loc); | |
4144 | ||
27bf414c | 4145 | return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs), |
8139a48e | 4146 | declarator, param_loc); |
27bf414c JM |
4147 | } |
4148 | ||
4149 | /* Parse a string literal in an asm expression. It should not be | |
4150 | translated, and wide string literals are an error although | |
4151 | permitted by the syntax. This is a GNU extension. | |
4152 | ||
4153 | asm-string-literal: | |
4154 | string-literal | |
4155 | ||
4156 | ??? At present, following the old parser, the caller needs to have | |
46c2514e TT |
4157 | set lex_untranslated_string to 1. It would be better to follow the |
4158 | C++ parser rather than using this kludge. */ | |
27bf414c JM |
4159 | |
4160 | static tree | |
4161 | c_parser_asm_string_literal (c_parser *parser) | |
4162 | { | |
4163 | tree str; | |
87f9e23d TT |
4164 | int save_flag = warn_overlength_strings; |
4165 | warn_overlength_strings = 0; | |
27bf414c JM |
4166 | if (c_parser_next_token_is (parser, CPP_STRING)) |
4167 | { | |
4168 | str = c_parser_peek_token (parser)->value; | |
4169 | c_parser_consume_token (parser); | |
4170 | } | |
4171 | else if (c_parser_next_token_is (parser, CPP_WSTRING)) | |
4172 | { | |
3ba09659 AH |
4173 | error_at (c_parser_peek_token (parser)->location, |
4174 | "wide string literal in %<asm%>"); | |
27bf414c JM |
4175 | str = build_string (1, ""); |
4176 | c_parser_consume_token (parser); | |
4177 | } | |
4178 | else | |
4179 | { | |
4180 | c_parser_error (parser, "expected string literal"); | |
4181 | str = NULL_TREE; | |
4182 | } | |
87f9e23d | 4183 | warn_overlength_strings = save_flag; |
27bf414c JM |
4184 | return str; |
4185 | } | |
4186 | ||
4187 | /* Parse a simple asm expression. This is used in restricted | |
4188 | contexts, where a full expression with inputs and outputs does not | |
4189 | make sense. This is a GNU extension. | |
4190 | ||
4191 | simple-asm-expr: | |
4192 | asm ( asm-string-literal ) | |
4193 | */ | |
4194 | ||
4195 | static tree | |
4196 | c_parser_simple_asm_expr (c_parser *parser) | |
4197 | { | |
4198 | tree str; | |
4199 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); | |
4200 | /* ??? Follow the C++ parser rather than using the | |
46c2514e TT |
4201 | lex_untranslated_string kludge. */ |
4202 | parser->lex_untranslated_string = true; | |
27bf414c | 4203 | c_parser_consume_token (parser); |
32129a17 DM |
4204 | matching_parens parens; |
4205 | if (!parens.require_open (parser)) | |
27bf414c | 4206 | { |
46c2514e | 4207 | parser->lex_untranslated_string = false; |
27bf414c JM |
4208 | return NULL_TREE; |
4209 | } | |
4210 | str = c_parser_asm_string_literal (parser); | |
46c2514e | 4211 | parser->lex_untranslated_string = false; |
32129a17 | 4212 | if (!parens.require_close (parser)) |
27bf414c JM |
4213 | { |
4214 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
4215 | return NULL_TREE; | |
4216 | } | |
4217 | return str; | |
4218 | } | |
4219 | ||
0a35513e AH |
4220 | static tree |
4221 | c_parser_attribute_any_word (c_parser *parser) | |
4222 | { | |
4223 | tree attr_name = NULL_TREE; | |
4224 | ||
4225 | if (c_parser_next_token_is (parser, CPP_KEYWORD)) | |
4226 | { | |
4227 | /* ??? See comment above about what keywords are accepted here. */ | |
4228 | bool ok; | |
4229 | switch (c_parser_peek_token (parser)->keyword) | |
4230 | { | |
4231 | case RID_STATIC: | |
4232 | case RID_UNSIGNED: | |
4233 | case RID_LONG: | |
0a35513e AH |
4234 | case RID_CONST: |
4235 | case RID_EXTERN: | |
4236 | case RID_REGISTER: | |
4237 | case RID_TYPEDEF: | |
4238 | case RID_SHORT: | |
4239 | case RID_INLINE: | |
4240 | case RID_NORETURN: | |
4241 | case RID_VOLATILE: | |
4242 | case RID_SIGNED: | |
4243 | case RID_AUTO: | |
4244 | case RID_RESTRICT: | |
4245 | case RID_COMPLEX: | |
4246 | case RID_THREAD: | |
4247 | case RID_INT: | |
4248 | case RID_CHAR: | |
4249 | case RID_FLOAT: | |
4250 | case RID_DOUBLE: | |
4251 | case RID_VOID: | |
4252 | case RID_DFLOAT32: | |
4253 | case RID_DFLOAT64: | |
4254 | case RID_DFLOAT128: | |
c65699ef | 4255 | CASE_RID_FLOATN_NX: |
0a35513e AH |
4256 | case RID_BOOL: |
4257 | case RID_FRACT: | |
4258 | case RID_ACCUM: | |
4259 | case RID_SAT: | |
4260 | case RID_TRANSACTION_ATOMIC: | |
4261 | case RID_TRANSACTION_CANCEL: | |
267bac10 | 4262 | case RID_ATOMIC: |
38b7bc7f | 4263 | case RID_AUTO_TYPE: |
78a7c317 DD |
4264 | case RID_INT_N_0: |
4265 | case RID_INT_N_1: | |
4266 | case RID_INT_N_2: | |
4267 | case RID_INT_N_3: | |
0a35513e AH |
4268 | ok = true; |
4269 | break; | |
4270 | default: | |
4271 | ok = false; | |
4272 | break; | |
4273 | } | |
4274 | if (!ok) | |
4275 | return NULL_TREE; | |
4276 | ||
4277 | /* Accept __attribute__((__const)) as __attribute__((const)) etc. */ | |
4278 | attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword]; | |
4279 | } | |
4280 | else if (c_parser_next_token_is (parser, CPP_NAME)) | |
4281 | attr_name = c_parser_peek_token (parser)->value; | |
4282 | ||
4283 | return attr_name; | |
4284 | } | |
4285 | ||
41958c28 BI |
4286 | #define CILK_SIMD_FN_CLAUSE_MASK \ |
4287 | ((OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_VECTORLENGTH) \ | |
4288 | | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_LINEAR) \ | |
4289 | | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNIFORM) \ | |
4290 | | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_MASK) \ | |
4291 | | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_NOMASK)) | |
4292 | ||
4293 | /* Parses the vector attribute of SIMD enabled functions in Cilk Plus. | |
4294 | VEC_TOKEN is the "vector" token that is replaced with "simd" and | |
4295 | pushed into the token list. | |
4296 | Syntax: | |
4297 | vector | |
4298 | vector (<vector attributes>). */ | |
4299 | ||
4300 | static void | |
4301 | c_parser_cilk_simd_fn_vector_attrs (c_parser *parser, c_token vec_token) | |
4302 | { | |
4303 | gcc_assert (is_cilkplus_vector_p (vec_token.value)); | |
4304 | ||
4305 | int paren_scope = 0; | |
4306 | vec_safe_push (parser->cilk_simd_fn_tokens, vec_token); | |
4307 | /* Consume the "vector" token. */ | |
4308 | c_parser_consume_token (parser); | |
4309 | ||
4310 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
4311 | { | |
4312 | c_parser_consume_token (parser); | |
4313 | paren_scope++; | |
4314 | } | |
4315 | while (paren_scope > 0) | |
4316 | { | |
4317 | c_token *token = c_parser_peek_token (parser); | |
4318 | if (token->type == CPP_OPEN_PAREN) | |
4319 | paren_scope++; | |
4320 | else if (token->type == CPP_CLOSE_PAREN) | |
4321 | paren_scope--; | |
4322 | /* Do not push the last ')' since we are not pushing the '('. */ | |
4323 | if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0)) | |
4324 | vec_safe_push (parser->cilk_simd_fn_tokens, *token); | |
4325 | c_parser_consume_token (parser); | |
4326 | } | |
4327 | ||
4328 | /* Since we are converting an attribute to a pragma, we need to end the | |
4329 | attribute with PRAGMA_EOL. */ | |
4330 | c_token eol_token; | |
4331 | memset (&eol_token, 0, sizeof (eol_token)); | |
4332 | eol_token.type = CPP_PRAGMA_EOL; | |
4333 | vec_safe_push (parser->cilk_simd_fn_tokens, eol_token); | |
4334 | } | |
4335 | ||
4336 | /* Add 2 CPP_EOF at the end of PARSER->ELEM_FN_TOKENS vector. */ | |
4337 | ||
4338 | static void | |
4339 | c_finish_cilk_simd_fn_tokens (c_parser *parser) | |
4340 | { | |
4341 | c_token last_token = parser->cilk_simd_fn_tokens->last (); | |
4342 | ||
4343 | /* c_parser_attributes is called in several places, so if these EOF | |
4344 | tokens are already inserted, then don't do them again. */ | |
4345 | if (last_token.type == CPP_EOF) | |
4346 | return; | |
4347 | ||
4348 | /* Two CPP_EOF token are added as a safety net since the normal C | |
4349 | front-end has two token look-ahead. */ | |
4350 | c_token eof_token; | |
4351 | eof_token.type = CPP_EOF; | |
4352 | vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); | |
4353 | vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); | |
4354 | } | |
4355 | ||
27bf414c JM |
4356 | /* Parse (possibly empty) attributes. This is a GNU extension. |
4357 | ||
4358 | attributes: | |
4359 | empty | |
4360 | attributes attribute | |
4361 | ||
4362 | attribute: | |
4363 | __attribute__ ( ( attribute-list ) ) | |
4364 | ||
4365 | attribute-list: | |
4366 | attrib | |
4367 | attribute_list , attrib | |
4368 | ||
4369 | attrib: | |
4370 | empty | |
4371 | any-word | |
4372 | any-word ( identifier ) | |
4373 | any-word ( identifier , nonempty-expr-list ) | |
4374 | any-word ( expr-list ) | |
4375 | ||
4376 | where the "identifier" must not be declared as a type, and | |
4377 | "any-word" may be any identifier (including one declared as a | |
4378 | type), a reserved word storage class specifier, type specifier or | |
4379 | type qualifier. ??? This still leaves out most reserved keywords | |
4380 | (following the old parser), shouldn't we include them, and why not | |
4381 | allow identifiers declared as types to start the arguments? */ | |
4382 | ||
4383 | static tree | |
4384 | c_parser_attributes (c_parser *parser) | |
4385 | { | |
4386 | tree attrs = NULL_TREE; | |
4387 | while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
4388 | { | |
4389 | /* ??? Follow the C++ parser rather than using the | |
46c2514e TT |
4390 | lex_untranslated_string kludge. */ |
4391 | parser->lex_untranslated_string = true; | |
2c7020eb | 4392 | /* Consume the `__attribute__' keyword. */ |
27bf414c | 4393 | c_parser_consume_token (parser); |
2c7020eb | 4394 | /* Look for the two `(' tokens. */ |
27bf414c JM |
4395 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
4396 | { | |
46c2514e | 4397 | parser->lex_untranslated_string = false; |
27bf414c JM |
4398 | return attrs; |
4399 | } | |
4400 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |
4401 | { | |
46c2514e | 4402 | parser->lex_untranslated_string = false; |
27bf414c JM |
4403 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
4404 | return attrs; | |
4405 | } | |
4406 | /* Parse the attribute list. */ | |
4407 | while (c_parser_next_token_is (parser, CPP_COMMA) | |
4408 | || c_parser_next_token_is (parser, CPP_NAME) | |
4409 | || c_parser_next_token_is (parser, CPP_KEYWORD)) | |
4410 | { | |
4411 | tree attr, attr_name, attr_args; | |
9771b263 | 4412 | vec<tree, va_gc> *expr_list; |
27bf414c JM |
4413 | if (c_parser_next_token_is (parser, CPP_COMMA)) |
4414 | { | |
4415 | c_parser_consume_token (parser); | |
4416 | continue; | |
4417 | } | |
0a35513e AH |
4418 | |
4419 | attr_name = c_parser_attribute_any_word (parser); | |
4420 | if (attr_name == NULL) | |
4421 | break; | |
577eec56 | 4422 | attr_name = canonicalize_attr_name (attr_name); |
2c7020eb | 4423 | if (is_cilkplus_vector_p (attr_name)) |
41958c28 BI |
4424 | { |
4425 | c_token *v_token = c_parser_peek_token (parser); | |
577eec56 | 4426 | v_token->value = canonicalize_attr_name (v_token->value); |
41958c28 | 4427 | c_parser_cilk_simd_fn_vector_attrs (parser, *v_token); |
2c7020eb MP |
4428 | /* If the next token isn't a comma, we're done. */ |
4429 | if (!c_parser_next_token_is (parser, CPP_COMMA)) | |
4430 | break; | |
41958c28 BI |
4431 | continue; |
4432 | } | |
27bf414c JM |
4433 | c_parser_consume_token (parser); |
4434 | if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) | |
4435 | { | |
4436 | attr = build_tree_list (attr_name, NULL_TREE); | |
2c7020eb | 4437 | /* Add this attribute to the list. */ |
27bf414c | 4438 | attrs = chainon (attrs, attr); |
2c7020eb MP |
4439 | /* If the next token isn't a comma, we're done. */ |
4440 | if (!c_parser_next_token_is (parser, CPP_COMMA)) | |
4441 | break; | |
27bf414c JM |
4442 | continue; |
4443 | } | |
4444 | c_parser_consume_token (parser); | |
4445 | /* Parse the attribute contents. If they start with an | |
4446 | identifier which is followed by a comma or close | |
4447 | parenthesis, then the arguments start with that | |
91ebb981 IS |
4448 | identifier; otherwise they are an expression list. |
4449 | In objective-c the identifier may be a classname. */ | |
27bf414c | 4450 | if (c_parser_next_token_is (parser, CPP_NAME) |
91ebb981 | 4451 | && (c_parser_peek_token (parser)->id_kind == C_ID_ID |
661a0813 MP |
4452 | || (c_dialect_objc () |
4453 | && c_parser_peek_token (parser)->id_kind | |
4454 | == C_ID_CLASSNAME)) | |
27bf414c JM |
4455 | && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA) |
4456 | || (c_parser_peek_2nd_token (parser)->type | |
661a0813 MP |
4457 | == CPP_CLOSE_PAREN)) |
4458 | && (attribute_takes_identifier_p (attr_name) | |
4459 | || (c_dialect_objc () | |
4460 | && c_parser_peek_token (parser)->id_kind | |
4461 | == C_ID_CLASSNAME))) | |
27bf414c JM |
4462 | { |
4463 | tree arg1 = c_parser_peek_token (parser)->value; | |
4464 | c_parser_consume_token (parser); | |
4465 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4466 | attr_args = build_tree_list (NULL_TREE, arg1); | |
4467 | else | |
4468 | { | |
bbbbb16a | 4469 | tree tree_list; |
27bf414c | 4470 | c_parser_consume_token (parser); |
1a4049e7 | 4471 | expr_list = c_parser_expr_list (parser, false, true, |
81e5eca8 | 4472 | NULL, NULL, NULL, NULL); |
c166b898 | 4473 | tree_list = build_tree_list_vec (expr_list); |
bbbbb16a | 4474 | attr_args = tree_cons (NULL_TREE, arg1, tree_list); |
c166b898 | 4475 | release_tree_vector (expr_list); |
27bf414c JM |
4476 | } |
4477 | } | |
4478 | else | |
4479 | { | |
4480 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4481 | attr_args = NULL_TREE; | |
4482 | else | |
bbbbb16a | 4483 | { |
1a4049e7 | 4484 | expr_list = c_parser_expr_list (parser, false, true, |
81e5eca8 | 4485 | NULL, NULL, NULL, NULL); |
c166b898 ILT |
4486 | attr_args = build_tree_list_vec (expr_list); |
4487 | release_tree_vector (expr_list); | |
bbbbb16a | 4488 | } |
27bf414c | 4489 | } |
577eec56 | 4490 | |
27bf414c JM |
4491 | attr = build_tree_list (attr_name, attr_args); |
4492 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4493 | c_parser_consume_token (parser); | |
4494 | else | |
4495 | { | |
46c2514e | 4496 | parser->lex_untranslated_string = false; |
27bf414c JM |
4497 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
4498 | "expected %<)%>"); | |
4499 | return attrs; | |
4500 | } | |
2c7020eb | 4501 | /* Add this attribute to the list. */ |
27bf414c | 4502 | attrs = chainon (attrs, attr); |
2c7020eb MP |
4503 | /* If the next token isn't a comma, we're done. */ |
4504 | if (!c_parser_next_token_is (parser, CPP_COMMA)) | |
4505 | break; | |
27bf414c | 4506 | } |
2c7020eb | 4507 | /* Look for the two `)' tokens. */ |
27bf414c JM |
4508 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
4509 | c_parser_consume_token (parser); | |
4510 | else | |
4511 | { | |
46c2514e | 4512 | parser->lex_untranslated_string = false; |
27bf414c JM |
4513 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
4514 | "expected %<)%>"); | |
4515 | return attrs; | |
4516 | } | |
4517 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
4518 | c_parser_consume_token (parser); | |
4519 | else | |
4520 | { | |
46c2514e | 4521 | parser->lex_untranslated_string = false; |
27bf414c JM |
4522 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
4523 | "expected %<)%>"); | |
4524 | return attrs; | |
4525 | } | |
46c2514e | 4526 | parser->lex_untranslated_string = false; |
27bf414c | 4527 | } |
41958c28 | 4528 | |
b72271b9 | 4529 | if (flag_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) |
41958c28 | 4530 | c_finish_cilk_simd_fn_tokens (parser); |
27bf414c JM |
4531 | return attrs; |
4532 | } | |
4533 | ||
31dc71a8 | 4534 | /* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). |
27bf414c JM |
4535 | |
4536 | type-name: | |
4537 | specifier-qualifier-list abstract-declarator[opt] | |
4538 | */ | |
4539 | ||
1ee62b92 | 4540 | struct c_type_name * |
27bf414c JM |
4541 | c_parser_type_name (c_parser *parser) |
4542 | { | |
4543 | struct c_declspecs *specs = build_null_declspecs (); | |
4544 | struct c_declarator *declarator; | |
4545 | struct c_type_name *ret; | |
4546 | bool dummy = false; | |
38b7bc7f | 4547 | c_parser_declspecs (parser, specs, false, true, true, false, false, |
568a31f2 | 4548 | cla_prefer_type); |
27bf414c JM |
4549 | if (!specs->declspecs_seen_p) |
4550 | { | |
4551 | c_parser_error (parser, "expected specifier-qualifier-list"); | |
4552 | return NULL; | |
4553 | } | |
29ce73cb PB |
4554 | if (specs->type != error_mark_node) |
4555 | { | |
4556 | pending_xref_error (); | |
4557 | finish_declspecs (specs); | |
4558 | } | |
9e5b2115 PB |
4559 | declarator = c_parser_declarator (parser, |
4560 | specs->typespec_kind != ctsk_none, | |
27bf414c JM |
4561 | C_DTR_ABSTRACT, &dummy); |
4562 | if (declarator == NULL) | |
4563 | return NULL; | |
4564 | ret = XOBNEW (&parser_obstack, struct c_type_name); | |
4565 | ret->specs = specs; | |
4566 | ret->declarator = declarator; | |
4567 | return ret; | |
4568 | } | |
4569 | ||
31dc71a8 | 4570 | /* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9). |
27bf414c JM |
4571 | |
4572 | initializer: | |
4573 | assignment-expression | |
4574 | { initializer-list } | |
4575 | { initializer-list , } | |
4576 | ||
4577 | initializer-list: | |
4578 | designation[opt] initializer | |
4579 | initializer-list , designation[opt] initializer | |
4580 | ||
4581 | designation: | |
4582 | designator-list = | |
4583 | ||
4584 | designator-list: | |
4585 | designator | |
4586 | designator-list designator | |
4587 | ||
4588 | designator: | |
4589 | array-designator | |
4590 | . identifier | |
4591 | ||
4592 | array-designator: | |
4593 | [ constant-expression ] | |
4594 | ||
4595 | GNU extensions: | |
4596 | ||
4597 | initializer: | |
4598 | { } | |
4599 | ||
4600 | designation: | |
4601 | array-designator | |
4602 | identifier : | |
4603 | ||
4604 | array-designator: | |
4605 | [ constant-expression ... constant-expression ] | |
4606 | ||
4607 | Any expression without commas is accepted in the syntax for the | |
4608 | constant-expressions, with non-constant expressions rejected later. | |
4609 | ||
4610 | This function is only used for top-level initializers; for nested | |
4611 | ones, see c_parser_initval. */ | |
4612 | ||
4613 | static struct c_expr | |
4614 | c_parser_initializer (c_parser *parser) | |
4615 | { | |
4616 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
16595a1f | 4617 | return c_parser_braced_init (parser, NULL_TREE, false, NULL); |
27bf414c | 4618 | else |
46bdb9cf JM |
4619 | { |
4620 | struct c_expr ret; | |
c2255bc4 | 4621 | location_t loc = c_parser_peek_token (parser)->location; |
46bdb9cf JM |
4622 | ret = c_parser_expr_no_commas (parser, NULL); |
4623 | if (TREE_CODE (ret.value) != STRING_CST | |
4624 | && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR) | |
267bac10 | 4625 | ret = convert_lvalue_to_rvalue (loc, ret, true, true); |
46bdb9cf JM |
4626 | return ret; |
4627 | } | |
27bf414c JM |
4628 | } |
4629 | ||
5dd9a9d0 DM |
4630 | /* The location of the last comma within the current initializer list, |
4631 | or UNKNOWN_LOCATION if not within one. */ | |
4632 | ||
4633 | location_t last_init_list_comma; | |
4634 | ||
27bf414c JM |
4635 | /* Parse a braced initializer list. TYPE is the type specified for a |
4636 | compound literal, and NULL_TREE for other initializers and for | |
4637 | nested braced lists. NESTED_P is true for nested braced lists, | |
4638 | false for the list of a compound literal or the list that is the | |
4639 | top-level initializer in a declaration. */ | |
4640 | ||
4641 | static struct c_expr | |
16595a1f BS |
4642 | c_parser_braced_init (c_parser *parser, tree type, bool nested_p, |
4643 | struct obstack *outer_obstack) | |
27bf414c | 4644 | { |
a1e3b3d9 LB |
4645 | struct c_expr ret; |
4646 | struct obstack braced_init_obstack; | |
c7412148 | 4647 | location_t brace_loc = c_parser_peek_token (parser)->location; |
a1e3b3d9 | 4648 | gcc_obstack_init (&braced_init_obstack); |
27bf414c | 4649 | gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); |
32129a17 DM |
4650 | matching_braces braces; |
4651 | braces.consume_open (parser); | |
27bf414c | 4652 | if (nested_p) |
16595a1f BS |
4653 | { |
4654 | finish_implicit_inits (brace_loc, outer_obstack); | |
4655 | push_init_level (brace_loc, 0, &braced_init_obstack); | |
4656 | } | |
27bf414c JM |
4657 | else |
4658 | really_start_incremental_init (type); | |
4659 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
4660 | { | |
c1771a20 | 4661 | pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces"); |
27bf414c JM |
4662 | } |
4663 | else | |
4664 | { | |
4665 | /* Parse a non-empty initializer list, possibly with a trailing | |
4666 | comma. */ | |
4667 | while (true) | |
4668 | { | |
a1e3b3d9 | 4669 | c_parser_initelt (parser, &braced_init_obstack); |
27bf414c JM |
4670 | if (parser->error) |
4671 | break; | |
4672 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
5dd9a9d0 DM |
4673 | { |
4674 | last_init_list_comma = c_parser_peek_token (parser)->location; | |
4675 | c_parser_consume_token (parser); | |
4676 | } | |
27bf414c JM |
4677 | else |
4678 | break; | |
4679 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
4680 | break; | |
4681 | } | |
4682 | } | |
bef08b71 DM |
4683 | c_token *next_tok = c_parser_peek_token (parser); |
4684 | if (next_tok->type != CPP_CLOSE_BRACE) | |
27bf414c | 4685 | { |
27bf414c JM |
4686 | ret.value = error_mark_node; |
4687 | ret.original_code = ERROR_MARK; | |
6866c6e8 | 4688 | ret.original_type = NULL; |
32129a17 | 4689 | braces.skip_until_found_close (parser); |
5dd9a9d0 | 4690 | pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma); |
a1e3b3d9 | 4691 | obstack_free (&braced_init_obstack, NULL); |
27bf414c JM |
4692 | return ret; |
4693 | } | |
bef08b71 | 4694 | location_t close_loc = next_tok->location; |
27bf414c | 4695 | c_parser_consume_token (parser); |
5dd9a9d0 | 4696 | ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc); |
a1e3b3d9 | 4697 | obstack_free (&braced_init_obstack, NULL); |
bef08b71 | 4698 | set_c_expr_source_range (&ret, brace_loc, close_loc); |
a1e3b3d9 | 4699 | return ret; |
27bf414c JM |
4700 | } |
4701 | ||
4702 | /* Parse a nested initializer, including designators. */ | |
4703 | ||
4704 | static void | |
a1e3b3d9 | 4705 | c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) |
27bf414c JM |
4706 | { |
4707 | /* Parse any designator or designator list. A single array | |
4708 | designator may have the subsequent "=" omitted in GNU C, but a | |
4709 | longer list or a structure member designator may not. */ | |
4710 | if (c_parser_next_token_is (parser, CPP_NAME) | |
4711 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
4712 | { | |
4713 | /* Old-style structure member designator. */ | |
ea58ef42 MP |
4714 | set_init_label (c_parser_peek_token (parser)->location, |
4715 | c_parser_peek_token (parser)->value, | |
f7e4f2e3 | 4716 | c_parser_peek_token (parser)->location, |
a1e3b3d9 | 4717 | braced_init_obstack); |
fcf73884 | 4718 | /* Use the colon as the error location. */ |
c1771a20 | 4719 | pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 4720 | "obsolete use of designated initializer with %<:%>"); |
27bf414c JM |
4721 | c_parser_consume_token (parser); |
4722 | c_parser_consume_token (parser); | |
4723 | } | |
4724 | else | |
4725 | { | |
4726 | /* des_seen is 0 if there have been no designators, 1 if there | |
4727 | has been a single array designator and 2 otherwise. */ | |
4728 | int des_seen = 0; | |
c7412148 | 4729 | /* Location of a designator. */ |
922f2908 | 4730 | location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
27bf414c JM |
4731 | while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE) |
4732 | || c_parser_next_token_is (parser, CPP_DOT)) | |
4733 | { | |
4734 | int des_prev = des_seen; | |
c7412148 TT |
4735 | if (!des_seen) |
4736 | des_loc = c_parser_peek_token (parser)->location; | |
27bf414c JM |
4737 | if (des_seen < 2) |
4738 | des_seen++; | |
4739 | if (c_parser_next_token_is (parser, CPP_DOT)) | |
4740 | { | |
4741 | des_seen = 2; | |
4742 | c_parser_consume_token (parser); | |
4743 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
4744 | { | |
ea58ef42 | 4745 | set_init_label (des_loc, c_parser_peek_token (parser)->value, |
f7e4f2e3 | 4746 | c_parser_peek_token (parser)->location, |
a1e3b3d9 | 4747 | braced_init_obstack); |
27bf414c JM |
4748 | c_parser_consume_token (parser); |
4749 | } | |
4750 | else | |
4751 | { | |
4752 | struct c_expr init; | |
4753 | init.value = error_mark_node; | |
4754 | init.original_code = ERROR_MARK; | |
6866c6e8 | 4755 | init.original_type = NULL; |
27bf414c JM |
4756 | c_parser_error (parser, "expected identifier"); |
4757 | c_parser_skip_until_found (parser, CPP_COMMA, NULL); | |
34cf811f MP |
4758 | process_init_element (input_location, init, false, |
4759 | braced_init_obstack); | |
27bf414c JM |
4760 | return; |
4761 | } | |
4762 | } | |
4763 | else | |
4764 | { | |
4765 | tree first, second; | |
922f2908 | 4766 | location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
ea58ef42 | 4767 | location_t array_index_loc = UNKNOWN_LOCATION; |
27bf414c JM |
4768 | /* ??? Following the old parser, [ objc-receiver |
4769 | objc-message-args ] is accepted as an initializer, | |
4770 | being distinguished from a designator by what follows | |
4771 | the first assignment expression inside the square | |
4772 | brackets, but after a first array designator a | |
4773 | subsequent square bracket is for Objective-C taken to | |
4774 | start an expression, using the obsolete form of | |
4775 | designated initializer without '=', rather than | |
4776 | possibly being a second level of designation: in LALR | |
4777 | terms, the '[' is shifted rather than reducing | |
4778 | designator to designator-list. */ | |
4779 | if (des_prev == 1 && c_dialect_objc ()) | |
4780 | { | |
4781 | des_seen = des_prev; | |
4782 | break; | |
4783 | } | |
4784 | if (des_prev == 0 && c_dialect_objc ()) | |
4785 | { | |
4786 | /* This might be an array designator or an | |
4787 | Objective-C message expression. If the former, | |
4788 | continue parsing here; if the latter, parse the | |
4789 | remainder of the initializer given the starting | |
4790 | primary-expression. ??? It might make sense to | |
4791 | distinguish when des_prev == 1 as well; see | |
4792 | previous comment. */ | |
4793 | tree rec, args; | |
4794 | struct c_expr mexpr; | |
4795 | c_parser_consume_token (parser); | |
4796 | if (c_parser_peek_token (parser)->type == CPP_NAME | |
4797 | && ((c_parser_peek_token (parser)->id_kind | |
4798 | == C_ID_TYPENAME) | |
4799 | || (c_parser_peek_token (parser)->id_kind | |
4800 | == C_ID_CLASSNAME))) | |
4801 | { | |
4802 | /* Type name receiver. */ | |
4803 | tree id = c_parser_peek_token (parser)->value; | |
4804 | c_parser_consume_token (parser); | |
4805 | rec = objc_get_class_reference (id); | |
4806 | goto parse_message_args; | |
4807 | } | |
4808 | first = c_parser_expr_no_commas (parser, NULL).value; | |
ebfbbdc5 | 4809 | mark_exp_read (first); |
27bf414c JM |
4810 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS) |
4811 | || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) | |
4812 | goto array_desig_after_first; | |
4813 | /* Expression receiver. So far only one part | |
4814 | without commas has been parsed; there might be | |
4815 | more of the expression. */ | |
4816 | rec = first; | |
4817 | while (c_parser_next_token_is (parser, CPP_COMMA)) | |
4818 | { | |
f2a71bbc | 4819 | struct c_expr next; |
c2255bc4 AH |
4820 | location_t comma_loc, exp_loc; |
4821 | comma_loc = c_parser_peek_token (parser)->location; | |
27bf414c | 4822 | c_parser_consume_token (parser); |
c2255bc4 | 4823 | exp_loc = c_parser_peek_token (parser)->location; |
f2a71bbc | 4824 | next = c_parser_expr_no_commas (parser, NULL); |
267bac10 JM |
4825 | next = convert_lvalue_to_rvalue (exp_loc, next, |
4826 | true, true); | |
c2255bc4 | 4827 | rec = build_compound_expr (comma_loc, rec, next.value); |
27bf414c JM |
4828 | } |
4829 | parse_message_args: | |
4830 | /* Now parse the objc-message-args. */ | |
4831 | args = c_parser_objc_message_args (parser); | |
4832 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, | |
4833 | "expected %<]%>"); | |
4834 | mexpr.value | |
eb345401 | 4835 | = objc_build_message_expr (rec, args); |
27bf414c | 4836 | mexpr.original_code = ERROR_MARK; |
6866c6e8 | 4837 | mexpr.original_type = NULL; |
27bf414c JM |
4838 | /* Now parse and process the remainder of the |
4839 | initializer, starting with this message | |
4840 | expression as a primary-expression. */ | |
a1e3b3d9 | 4841 | c_parser_initval (parser, &mexpr, braced_init_obstack); |
27bf414c JM |
4842 | return; |
4843 | } | |
4844 | c_parser_consume_token (parser); | |
ea58ef42 | 4845 | array_index_loc = c_parser_peek_token (parser)->location; |
27bf414c | 4846 | first = c_parser_expr_no_commas (parser, NULL).value; |
ebfbbdc5 | 4847 | mark_exp_read (first); |
27bf414c JM |
4848 | array_desig_after_first: |
4849 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
4850 | { | |
c7412148 | 4851 | ellipsis_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
4852 | c_parser_consume_token (parser); |
4853 | second = c_parser_expr_no_commas (parser, NULL).value; | |
ebfbbdc5 | 4854 | mark_exp_read (second); |
27bf414c JM |
4855 | } |
4856 | else | |
4857 | second = NULL_TREE; | |
4858 | if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) | |
4859 | { | |
4860 | c_parser_consume_token (parser); | |
ea58ef42 MP |
4861 | set_init_index (array_index_loc, first, second, |
4862 | braced_init_obstack); | |
fcf73884 | 4863 | if (second) |
c1771a20 | 4864 | pedwarn (ellipsis_loc, OPT_Wpedantic, |
509c9d60 | 4865 | "ISO C forbids specifying range of elements to initialize"); |
27bf414c JM |
4866 | } |
4867 | else | |
4868 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, | |
4869 | "expected %<]%>"); | |
4870 | } | |
4871 | } | |
4872 | if (des_seen >= 1) | |
4873 | { | |
4874 | if (c_parser_next_token_is (parser, CPP_EQ)) | |
4875 | { | |
f3bede71 MP |
4876 | pedwarn_c90 (des_loc, OPT_Wpedantic, |
4877 | "ISO C90 forbids specifying subobject " | |
4878 | "to initialize"); | |
27bf414c JM |
4879 | c_parser_consume_token (parser); |
4880 | } | |
4881 | else | |
4882 | { | |
4883 | if (des_seen == 1) | |
c1771a20 | 4884 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 4885 | "obsolete use of designated initializer without %<=%>"); |
27bf414c JM |
4886 | else |
4887 | { | |
4888 | struct c_expr init; | |
4889 | init.value = error_mark_node; | |
4890 | init.original_code = ERROR_MARK; | |
6866c6e8 | 4891 | init.original_type = NULL; |
27bf414c JM |
4892 | c_parser_error (parser, "expected %<=%>"); |
4893 | c_parser_skip_until_found (parser, CPP_COMMA, NULL); | |
34cf811f MP |
4894 | process_init_element (input_location, init, false, |
4895 | braced_init_obstack); | |
27bf414c JM |
4896 | return; |
4897 | } | |
4898 | } | |
4899 | } | |
4900 | } | |
a1e3b3d9 | 4901 | c_parser_initval (parser, NULL, braced_init_obstack); |
27bf414c JM |
4902 | } |
4903 | ||
4904 | /* Parse a nested initializer; as c_parser_initializer but parses | |
4905 | initializers within braced lists, after any designators have been | |
4906 | applied. If AFTER is not NULL then it is an Objective-C message | |
4907 | expression which is the primary-expression starting the | |
4908 | initializer. */ | |
4909 | ||
4910 | static void | |
a1e3b3d9 LB |
4911 | c_parser_initval (c_parser *parser, struct c_expr *after, |
4912 | struct obstack * braced_init_obstack) | |
27bf414c JM |
4913 | { |
4914 | struct c_expr init; | |
4915 | gcc_assert (!after || c_dialect_objc ()); | |
34cf811f MP |
4916 | location_t loc = c_parser_peek_token (parser)->location; |
4917 | ||
27bf414c | 4918 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) |
16595a1f BS |
4919 | init = c_parser_braced_init (parser, NULL_TREE, true, |
4920 | braced_init_obstack); | |
27bf414c | 4921 | else |
46bdb9cf JM |
4922 | { |
4923 | init = c_parser_expr_no_commas (parser, after); | |
4924 | if (init.value != NULL_TREE | |
4925 | && TREE_CODE (init.value) != STRING_CST | |
4926 | && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) | |
267bac10 | 4927 | init = convert_lvalue_to_rvalue (loc, init, true, true); |
46bdb9cf | 4928 | } |
34cf811f | 4929 | process_init_element (loc, init, false, braced_init_obstack); |
27bf414c JM |
4930 | } |
4931 | ||
4932 | /* Parse a compound statement (possibly a function body) (C90 6.6.2, | |
31dc71a8 | 4933 | C99 6.8.2, C11 6.8.2). |
27bf414c JM |
4934 | |
4935 | compound-statement: | |
4936 | { block-item-list[opt] } | |
4937 | { label-declarations block-item-list } | |
4938 | ||
4939 | block-item-list: | |
4940 | block-item | |
4941 | block-item-list block-item | |
4942 | ||
4943 | block-item: | |
4944 | nested-declaration | |
4945 | statement | |
4946 | ||
4947 | nested-declaration: | |
4948 | declaration | |
4949 | ||
4950 | GNU extensions: | |
4951 | ||
4952 | compound-statement: | |
4953 | { label-declarations block-item-list } | |
4954 | ||
4955 | nested-declaration: | |
4956 | __extension__ nested-declaration | |
4957 | nested-function-definition | |
4958 | ||
4959 | label-declarations: | |
4960 | label-declaration | |
4961 | label-declarations label-declaration | |
4962 | ||
4963 | label-declaration: | |
4964 | __label__ identifier-list ; | |
4965 | ||
4966 | Allowing the mixing of declarations and code is new in C99. The | |
4967 | GNU syntax also permits (not shown above) labels at the end of | |
4968 | compound statements, which yield an error. We don't allow labels | |
4969 | on declarations; this might seem like a natural extension, but | |
4970 | there would be a conflict between attributes on the label and | |
4971 | prefix attributes on the declaration. ??? The syntax follows the | |
4972 | old parser in requiring something after label declarations. | |
4973 | Although they are erroneous if the labels declared aren't defined, | |
953ff289 | 4974 | is it useful for the syntax to be this way? |
b8698a0f | 4975 | |
41dbbb37 TS |
4976 | OpenACC: |
4977 | ||
4978 | block-item: | |
4979 | openacc-directive | |
4980 | ||
4981 | openacc-directive: | |
4982 | update-directive | |
4983 | ||
953ff289 | 4984 | OpenMP: |
b8698a0f | 4985 | |
953ff289 DN |
4986 | block-item: |
4987 | openmp-directive | |
4988 | ||
4989 | openmp-directive: | |
4990 | barrier-directive | |
acf0174b JJ |
4991 | flush-directive |
4992 | taskwait-directive | |
4993 | taskyield-directive | |
4994 | cancel-directive | |
4995 | cancellation-point-directive */ | |
27bf414c JM |
4996 | |
4997 | static tree | |
4998 | c_parser_compound_statement (c_parser *parser) | |
4999 | { | |
5000 | tree stmt; | |
c2255bc4 AH |
5001 | location_t brace_loc; |
5002 | brace_loc = c_parser_peek_token (parser)->location; | |
27bf414c | 5003 | if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) |
5600f233 JM |
5004 | { |
5005 | /* Ensure a scope is entered and left anyway to avoid confusion | |
5006 | if we have just prepared to enter a function body. */ | |
5007 | stmt = c_begin_compound_stmt (true); | |
c2255bc4 | 5008 | c_end_compound_stmt (brace_loc, stmt, true); |
5600f233 JM |
5009 | return error_mark_node; |
5010 | } | |
27bf414c JM |
5011 | stmt = c_begin_compound_stmt (true); |
5012 | c_parser_compound_statement_nostart (parser); | |
36536d79 BI |
5013 | |
5014 | /* If the compound stmt contains array notations, then we expand them. */ | |
b72271b9 | 5015 | if (flag_cilkplus && contains_array_notation_expr (stmt)) |
36536d79 | 5016 | stmt = expand_array_notation_exprs (stmt); |
c2255bc4 | 5017 | return c_end_compound_stmt (brace_loc, stmt, true); |
27bf414c JM |
5018 | } |
5019 | ||
5020 | /* Parse a compound statement except for the opening brace. This is | |
5021 | used for parsing both compound statements and statement expressions | |
5022 | (which follow different paths to handling the opening). */ | |
5023 | ||
5024 | static void | |
5025 | c_parser_compound_statement_nostart (c_parser *parser) | |
5026 | { | |
5027 | bool last_stmt = false; | |
5028 | bool last_label = false; | |
6ec637a4 | 5029 | bool save_valid_for_pragma = valid_location_for_stdc_pragma_p (); |
3ba09659 | 5030 | location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
27bf414c JM |
5031 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) |
5032 | { | |
5033 | c_parser_consume_token (parser); | |
5034 | return; | |
5035 | } | |
6ec637a4 | 5036 | mark_valid_location_for_stdc_pragma (true); |
27bf414c JM |
5037 | if (c_parser_next_token_is_keyword (parser, RID_LABEL)) |
5038 | { | |
5039 | /* Read zero or more forward-declarations for labels that nested | |
5040 | functions can jump to. */ | |
6ec637a4 | 5041 | mark_valid_location_for_stdc_pragma (false); |
27bf414c JM |
5042 | while (c_parser_next_token_is_keyword (parser, RID_LABEL)) |
5043 | { | |
c2255bc4 | 5044 | label_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
5045 | c_parser_consume_token (parser); |
5046 | /* Any identifiers, including those declared as type names, | |
5047 | are OK here. */ | |
5048 | while (true) | |
5049 | { | |
5050 | tree label; | |
5051 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
5052 | { | |
5053 | c_parser_error (parser, "expected identifier"); | |
5054 | break; | |
5055 | } | |
5056 | label | |
5057 | = declare_label (c_parser_peek_token (parser)->value); | |
5058 | C_DECLARED_LABEL_FLAG (label) = 1; | |
c2255bc4 | 5059 | add_stmt (build_stmt (label_loc, DECL_EXPR, label)); |
27bf414c JM |
5060 | c_parser_consume_token (parser); |
5061 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
5062 | c_parser_consume_token (parser); | |
5063 | else | |
5064 | break; | |
5065 | } | |
5066 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
5067 | } | |
c1771a20 | 5068 | pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations"); |
27bf414c JM |
5069 | } |
5070 | /* We must now have at least one statement, label or declaration. */ | |
5071 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
5072 | { | |
6ec637a4 | 5073 | mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
27bf414c JM |
5074 | c_parser_error (parser, "expected declaration or statement"); |
5075 | c_parser_consume_token (parser); | |
5076 | return; | |
5077 | } | |
5078 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) | |
5079 | { | |
5080 | location_t loc = c_parser_peek_token (parser)->location; | |
27bf414c JM |
5081 | if (c_parser_next_token_is_keyword (parser, RID_CASE) |
5082 | || c_parser_next_token_is_keyword (parser, RID_DEFAULT) | |
5083 | || (c_parser_next_token_is (parser, CPP_NAME) | |
5084 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) | |
5085 | { | |
c7412148 TT |
5086 | if (c_parser_next_token_is_keyword (parser, RID_CASE)) |
5087 | label_loc = c_parser_peek_2nd_token (parser)->location; | |
5088 | else | |
5089 | label_loc = c_parser_peek_token (parser)->location; | |
27bf414c JM |
5090 | last_label = true; |
5091 | last_stmt = false; | |
6ec637a4 | 5092 | mark_valid_location_for_stdc_pragma (false); |
27bf414c JM |
5093 | c_parser_label (parser); |
5094 | } | |
5095 | else if (!last_label | |
2f413185 | 5096 | && c_parser_next_tokens_start_declaration (parser)) |
27bf414c JM |
5097 | { |
5098 | last_label = false; | |
6ec637a4 | 5099 | mark_valid_location_for_stdc_pragma (false); |
81fea426 | 5100 | bool fallthru_attr_p = false; |
acf0174b | 5101 | c_parser_declaration_or_fndef (parser, true, true, true, true, |
81fea426 MP |
5102 | true, NULL, vNULL, NULL, |
5103 | &fallthru_attr_p); | |
5104 | if (last_stmt && !fallthru_attr_p) | |
177cce46 | 5105 | pedwarn_c90 (loc, OPT_Wdeclaration_after_statement, |
509c9d60 | 5106 | "ISO C90 forbids mixed declarations and code"); |
81fea426 | 5107 | last_stmt = fallthru_attr_p; |
27bf414c JM |
5108 | } |
5109 | else if (!last_label | |
5110 | && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) | |
5111 | { | |
5112 | /* __extension__ can start a declaration, but is also an | |
5113 | unary operator that can start an expression. Consume all | |
5114 | but the last of a possible series of __extension__ to | |
5115 | determine which. */ | |
5116 | while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD | |
5117 | && (c_parser_peek_2nd_token (parser)->keyword | |
5118 | == RID_EXTENSION)) | |
5119 | c_parser_consume_token (parser); | |
32912286 | 5120 | if (c_token_starts_declaration (c_parser_peek_2nd_token (parser))) |
27bf414c JM |
5121 | { |
5122 | int ext; | |
5123 | ext = disable_extension_diagnostics (); | |
5124 | c_parser_consume_token (parser); | |
5125 | last_label = false; | |
6ec637a4 | 5126 | mark_valid_location_for_stdc_pragma (false); |
32912286 | 5127 | c_parser_declaration_or_fndef (parser, true, true, true, true, |
acf0174b | 5128 | true, NULL, vNULL); |
27bf414c JM |
5129 | /* Following the old parser, __extension__ does not |
5130 | disable this diagnostic. */ | |
5131 | restore_extension_diagnostics (ext); | |
fcf73884 | 5132 | if (last_stmt) |
177cce46 | 5133 | pedwarn_c90 (loc, OPT_Wdeclaration_after_statement, |
509c9d60 | 5134 | "ISO C90 forbids mixed declarations and code"); |
27bf414c JM |
5135 | last_stmt = false; |
5136 | } | |
5137 | else | |
5138 | goto statement; | |
5139 | } | |
bc4071dd RH |
5140 | else if (c_parser_next_token_is (parser, CPP_PRAGMA)) |
5141 | { | |
5142 | /* External pragmas, and some omp pragmas, are not associated | |
5143 | with regular c code, and so are not to be considered statements | |
5144 | syntactically. This ensures that the user doesn't put them | |
5145 | places that would turn into syntax errors if the directive | |
5146 | were ignored. */ | |
aec17bfe | 5147 | if (c_parser_pragma (parser, |
dda1bf61 JJ |
5148 | last_label ? pragma_stmt : pragma_compound, |
5149 | NULL)) | |
bc4071dd RH |
5150 | last_label = false, last_stmt = true; |
5151 | } | |
5152 | else if (c_parser_next_token_is (parser, CPP_EOF)) | |
5153 | { | |
6ec637a4 | 5154 | mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
bc4071dd RH |
5155 | c_parser_error (parser, "expected declaration or statement"); |
5156 | return; | |
5157 | } | |
b4b56033 MLI |
5158 | else if (c_parser_next_token_is_keyword (parser, RID_ELSE)) |
5159 | { | |
b8698a0f | 5160 | if (parser->in_if_block) |
b4b56033 | 5161 | { |
6ec637a4 | 5162 | mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
92fa0f9e | 5163 | error_at (loc, "expected %<}%> before %<else%>"); |
b4b56033 MLI |
5164 | return; |
5165 | } | |
b8698a0f | 5166 | else |
b4b56033 | 5167 | { |
3ba09659 | 5168 | error_at (loc, "%<else%> without a previous %<if%>"); |
b4b56033 MLI |
5169 | c_parser_consume_token (parser); |
5170 | continue; | |
5171 | } | |
5172 | } | |
27bf414c JM |
5173 | else |
5174 | { | |
5175 | statement: | |
5176 | last_label = false; | |
5177 | last_stmt = true; | |
6ec637a4 | 5178 | mark_valid_location_for_stdc_pragma (false); |
99cd9857 | 5179 | c_parser_statement_after_labels (parser, NULL); |
27bf414c | 5180 | } |
2c14ae9a VR |
5181 | |
5182 | parser->error = false; | |
27bf414c JM |
5183 | } |
5184 | if (last_label) | |
3ba09659 | 5185 | error_at (label_loc, "label at end of compound statement"); |
27bf414c | 5186 | c_parser_consume_token (parser); |
6ec637a4 JJ |
5187 | /* Restore the value we started with. */ |
5188 | mark_valid_location_for_stdc_pragma (save_valid_for_pragma); | |
27bf414c JM |
5189 | } |
5190 | ||
74d98c1e AB |
5191 | /* Parse all consecutive labels. */ |
5192 | ||
5193 | static void | |
5194 | c_parser_all_labels (c_parser *parser) | |
5195 | { | |
5196 | while (c_parser_next_token_is_keyword (parser, RID_CASE) | |
5197 | || c_parser_next_token_is_keyword (parser, RID_DEFAULT) | |
5198 | || (c_parser_next_token_is (parser, CPP_NAME) | |
5199 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) | |
5200 | c_parser_label (parser); | |
5201 | } | |
5202 | ||
31dc71a8 | 5203 | /* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1). |
27bf414c JM |
5204 | |
5205 | label: | |
5206 | identifier : attributes[opt] | |
5207 | case constant-expression : | |
5208 | default : | |
5209 | ||
5210 | GNU extensions: | |
5211 | ||
5212 | label: | |
5213 | case constant-expression ... constant-expression : | |
5214 | ||
5215 | The use of attributes on labels is a GNU extension. The syntax in | |
5216 | GNU C accepts any expressions without commas, non-constant | |
5217 | expressions being rejected later. */ | |
5218 | ||
5219 | static void | |
5220 | c_parser_label (c_parser *parser) | |
5221 | { | |
5222 | location_t loc1 = c_parser_peek_token (parser)->location; | |
5223 | tree label = NULL_TREE; | |
81fea426 MP |
5224 | |
5225 | /* Remember whether this case or a user-defined label is allowed to fall | |
5226 | through to. */ | |
5227 | bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH; | |
5228 | ||
27bf414c JM |
5229 | if (c_parser_next_token_is_keyword (parser, RID_CASE)) |
5230 | { | |
5231 | tree exp1, exp2; | |
5232 | c_parser_consume_token (parser); | |
5233 | exp1 = c_parser_expr_no_commas (parser, NULL).value; | |
5234 | if (c_parser_next_token_is (parser, CPP_COLON)) | |
5235 | { | |
5236 | c_parser_consume_token (parser); | |
c2255bc4 | 5237 | label = do_case (loc1, exp1, NULL_TREE); |
27bf414c JM |
5238 | } |
5239 | else if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
5240 | { | |
5241 | c_parser_consume_token (parser); | |
5242 | exp2 = c_parser_expr_no_commas (parser, NULL).value; | |
5243 | if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
c2255bc4 | 5244 | label = do_case (loc1, exp1, exp2); |
27bf414c JM |
5245 | } |
5246 | else | |
5247 | c_parser_error (parser, "expected %<:%> or %<...%>"); | |
5248 | } | |
5249 | else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)) | |
5250 | { | |
5251 | c_parser_consume_token (parser); | |
5252 | if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
c2255bc4 | 5253 | label = do_case (loc1, NULL_TREE, NULL_TREE); |
27bf414c JM |
5254 | } |
5255 | else | |
5256 | { | |
5257 | tree name = c_parser_peek_token (parser)->value; | |
5258 | tree tlab; | |
27bf414c | 5259 | tree attrs; |
c7412148 | 5260 | location_t loc2 = c_parser_peek_token (parser)->location; |
27bf414c JM |
5261 | gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); |
5262 | c_parser_consume_token (parser); | |
5263 | gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); | |
27bf414c JM |
5264 | c_parser_consume_token (parser); |
5265 | attrs = c_parser_attributes (parser); | |
5266 | tlab = define_label (loc2, name); | |
5267 | if (tlab) | |
5268 | { | |
5269 | decl_attributes (&tlab, attrs, 0); | |
c2255bc4 | 5270 | label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab)); |
27bf414c JM |
5271 | } |
5272 | } | |
5273 | if (label) | |
3d57f0f0 | 5274 | { |
81fea426 MP |
5275 | if (TREE_CODE (label) == LABEL_EXPR) |
5276 | FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p; | |
5277 | else | |
5278 | FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p; | |
5279 | ||
5280 | /* Allow '__attribute__((fallthrough));'. */ | |
5281 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
5282 | { | |
5283 | location_t loc = c_parser_peek_token (parser)->location; | |
5284 | tree attrs = c_parser_attributes (parser); | |
5285 | if (attribute_fallthrough_p (attrs)) | |
5286 | { | |
5287 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
5288 | { | |
5289 | tree fn = build_call_expr_internal_loc (loc, | |
5290 | IFN_FALLTHROUGH, | |
5291 | void_type_node, 0); | |
5292 | add_stmt (fn); | |
5293 | } | |
5294 | else | |
5295 | warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute " | |
5296 | "not followed by %<;%>"); | |
5297 | } | |
5298 | else if (attrs != NULL_TREE) | |
5299 | warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>" | |
5300 | " can be applied to a null statement"); | |
5301 | } | |
2f413185 | 5302 | if (c_parser_next_tokens_start_declaration (parser)) |
3d57f0f0 | 5303 | { |
3ba09659 AH |
5304 | error_at (c_parser_peek_token (parser)->location, |
5305 | "a label can only be part of a statement and " | |
5306 | "a declaration is not a statement"); | |
b8698a0f | 5307 | c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, |
32912286 | 5308 | /*static_assert_ok*/ true, |
6265d07c | 5309 | /*empty_ok*/ true, /*nested*/ true, |
acf0174b JJ |
5310 | /*start_attr_ok*/ true, NULL, |
5311 | vNULL); | |
3d57f0f0 MLI |
5312 | } |
5313 | } | |
27bf414c JM |
5314 | } |
5315 | ||
31dc71a8 | 5316 | /* Parse a statement (C90 6.6, C99 6.8, C11 6.8). |
27bf414c JM |
5317 | |
5318 | statement: | |
5319 | labeled-statement | |
5320 | compound-statement | |
5321 | expression-statement | |
5322 | selection-statement | |
5323 | iteration-statement | |
5324 | jump-statement | |
5325 | ||
5326 | labeled-statement: | |
5327 | label statement | |
5328 | ||
5329 | expression-statement: | |
5330 | expression[opt] ; | |
5331 | ||
5332 | selection-statement: | |
5333 | if-statement | |
5334 | switch-statement | |
5335 | ||
5336 | iteration-statement: | |
5337 | while-statement | |
5338 | do-statement | |
5339 | for-statement | |
5340 | ||
5341 | jump-statement: | |
5342 | goto identifier ; | |
5343 | continue ; | |
5344 | break ; | |
5345 | return expression[opt] ; | |
5346 | ||
5347 | GNU extensions: | |
5348 | ||
5349 | statement: | |
5350 | asm-statement | |
5351 | ||
5352 | jump-statement: | |
5353 | goto * expression ; | |
5354 | ||
81fea426 MP |
5355 | expression-statement: |
5356 | attributes ; | |
5357 | ||
27bf414c JM |
5358 | Objective-C: |
5359 | ||
5360 | statement: | |
5361 | objc-throw-statement | |
5362 | objc-try-catch-statement | |
5363 | objc-synchronized-statement | |
5364 | ||
5365 | objc-throw-statement: | |
5366 | @throw expression ; | |
5367 | @throw ; | |
953ff289 | 5368 | |
41dbbb37 TS |
5369 | OpenACC: |
5370 | ||
5371 | statement: | |
5372 | openacc-construct | |
5373 | ||
5374 | openacc-construct: | |
5375 | parallel-construct | |
5376 | kernels-construct | |
5377 | data-construct | |
5378 | loop-construct | |
5379 | ||
5380 | parallel-construct: | |
5381 | parallel-directive structured-block | |
5382 | ||
5383 | kernels-construct: | |
5384 | kernels-directive structured-block | |
5385 | ||
5386 | data-construct: | |
5387 | data-directive structured-block | |
5388 | ||
5389 | loop-construct: | |
5390 | loop-directive structured-block | |
5391 | ||
953ff289 DN |
5392 | OpenMP: |
5393 | ||
5394 | statement: | |
5395 | openmp-construct | |
5396 | ||
5397 | openmp-construct: | |
5398 | parallel-construct | |
5399 | for-construct | |
acf0174b JJ |
5400 | simd-construct |
5401 | for-simd-construct | |
953ff289 DN |
5402 | sections-construct |
5403 | single-construct | |
5404 | parallel-for-construct | |
acf0174b | 5405 | parallel-for-simd-construct |
953ff289 DN |
5406 | parallel-sections-construct |
5407 | master-construct | |
5408 | critical-construct | |
5409 | atomic-construct | |
5410 | ordered-construct | |
5411 | ||
5412 | parallel-construct: | |
5413 | parallel-directive structured-block | |
5414 | ||
5415 | for-construct: | |
5416 | for-directive iteration-statement | |
5417 | ||
acf0174b JJ |
5418 | simd-construct: |
5419 | simd-directive iteration-statements | |
5420 | ||
5421 | for-simd-construct: | |
5422 | for-simd-directive iteration-statements | |
5423 | ||
953ff289 DN |
5424 | sections-construct: |
5425 | sections-directive section-scope | |
5426 | ||
5427 | single-construct: | |
5428 | single-directive structured-block | |
5429 | ||
5430 | parallel-for-construct: | |
5431 | parallel-for-directive iteration-statement | |
5432 | ||
acf0174b JJ |
5433 | parallel-for-simd-construct: |
5434 | parallel-for-simd-directive iteration-statement | |
5435 | ||
953ff289 DN |
5436 | parallel-sections-construct: |
5437 | parallel-sections-directive section-scope | |
5438 | ||
5439 | master-construct: | |
5440 | master-directive structured-block | |
5441 | ||
5442 | critical-construct: | |
5443 | critical-directive structured-block | |
5444 | ||
5445 | atomic-construct: | |
5446 | atomic-directive expression-statement | |
5447 | ||
5448 | ordered-construct: | |
0a35513e AH |
5449 | ordered-directive structured-block |
5450 | ||
5451 | Transactional Memory: | |
5452 | ||
5453 | statement: | |
5454 | transaction-statement | |
5455 | transaction-cancel-statement | |
99cd9857 MP |
5456 | |
5457 | IF_P is used to track whether there's a (possibly labeled) if statement | |
5458 | which is not enclosed in braces and has an else clause. This is used to | |
5459 | implement -Wparentheses. */ | |
27bf414c JM |
5460 | |
5461 | static void | |
3e2becc4 | 5462 | c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels) |
27bf414c | 5463 | { |
74d98c1e | 5464 | c_parser_all_labels (parser); |
3e2becc4 MP |
5465 | if (loc_after_labels) |
5466 | *loc_after_labels = c_parser_peek_token (parser)->location; | |
99cd9857 | 5467 | c_parser_statement_after_labels (parser, if_p, NULL); |
27bf414c JM |
5468 | } |
5469 | ||
3e3b8d63 | 5470 | /* Parse a statement, other than a labeled statement. CHAIN is a vector |
99cd9857 MP |
5471 | of if-else-if conditions. |
5472 | ||
5473 | IF_P is used to track whether there's a (possibly labeled) if statement | |
5474 | which is not enclosed in braces and has an else clause. This is used to | |
5475 | implement -Wparentheses. */ | |
27bf414c JM |
5476 | |
5477 | static void | |
99cd9857 MP |
5478 | c_parser_statement_after_labels (c_parser *parser, bool *if_p, |
5479 | vec<tree> *chain) | |
27bf414c JM |
5480 | { |
5481 | location_t loc = c_parser_peek_token (parser)->location; | |
5482 | tree stmt = NULL_TREE; | |
b4b56033 MLI |
5483 | bool in_if_block = parser->in_if_block; |
5484 | parser->in_if_block = false; | |
99cd9857 MP |
5485 | if (if_p != NULL) |
5486 | *if_p = false; | |
27bf414c JM |
5487 | switch (c_parser_peek_token (parser)->type) |
5488 | { | |
5489 | case CPP_OPEN_BRACE: | |
5490 | add_stmt (c_parser_compound_statement (parser)); | |
5491 | break; | |
5492 | case CPP_KEYWORD: | |
5493 | switch (c_parser_peek_token (parser)->keyword) | |
5494 | { | |
5495 | case RID_IF: | |
99cd9857 | 5496 | c_parser_if_statement (parser, if_p, chain); |
27bf414c JM |
5497 | break; |
5498 | case RID_SWITCH: | |
351f85c5 | 5499 | c_parser_switch_statement (parser, if_p); |
27bf414c JM |
5500 | break; |
5501 | case RID_WHILE: | |
99cd9857 | 5502 | c_parser_while_statement (parser, false, if_p); |
27bf414c JM |
5503 | break; |
5504 | case RID_DO: | |
d4af74d4 | 5505 | c_parser_do_statement (parser, false); |
27bf414c JM |
5506 | break; |
5507 | case RID_FOR: | |
99cd9857 | 5508 | c_parser_for_statement (parser, false, if_p); |
27bf414c | 5509 | break; |
9a771876 JJ |
5510 | case RID_CILK_FOR: |
5511 | if (!flag_cilkplus) | |
5512 | { | |
5513 | error_at (c_parser_peek_token (parser)->location, | |
5514 | "-fcilkplus must be enabled to use %<_Cilk_for%>"); | |
5515 | c_parser_skip_to_end_of_block_or_statement (parser); | |
5516 | } | |
5517 | else | |
dda1bf61 | 5518 | c_parser_cilk_for (parser, integer_zero_node, if_p); |
9a771876 | 5519 | break; |
939b37da BI |
5520 | case RID_CILK_SYNC: |
5521 | c_parser_consume_token (parser); | |
5522 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
b72271b9 | 5523 | if (!flag_cilkplus) |
939b37da BI |
5524 | error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>"); |
5525 | else | |
5526 | add_stmt (build_cilk_sync ()); | |
5527 | break; | |
27bf414c JM |
5528 | case RID_GOTO: |
5529 | c_parser_consume_token (parser); | |
5530 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
5531 | { | |
c2255bc4 AH |
5532 | stmt = c_finish_goto_label (loc, |
5533 | c_parser_peek_token (parser)->value); | |
27bf414c JM |
5534 | c_parser_consume_token (parser); |
5535 | } | |
5536 | else if (c_parser_next_token_is (parser, CPP_MULT)) | |
5537 | { | |
267bac10 | 5538 | struct c_expr val; |
84628aa8 | 5539 | |
27bf414c | 5540 | c_parser_consume_token (parser); |
267bac10 | 5541 | val = c_parser_expression (parser); |
e5e44252 AK |
5542 | if (check_no_cilk (val.value, |
5543 | "Cilk array notation cannot be used as a computed goto expression", | |
5544 | "%<_Cilk_spawn%> statement cannot be used as a computed goto expression", | |
5545 | loc)) | |
5546 | val.value = error_mark_node; | |
267bac10 JM |
5547 | val = convert_lvalue_to_rvalue (loc, val, false, true); |
5548 | stmt = c_finish_goto_ptr (loc, val.value); | |
27bf414c JM |
5549 | } |
5550 | else | |
5551 | c_parser_error (parser, "expected identifier or %<*%>"); | |
5552 | goto expect_semicolon; | |
5553 | case RID_CONTINUE: | |
5554 | c_parser_consume_token (parser); | |
c2255bc4 | 5555 | stmt = c_finish_bc_stmt (loc, &c_cont_label, false); |
27bf414c JM |
5556 | goto expect_semicolon; |
5557 | case RID_BREAK: | |
5558 | c_parser_consume_token (parser); | |
c2255bc4 | 5559 | stmt = c_finish_bc_stmt (loc, &c_break_label, true); |
27bf414c JM |
5560 | goto expect_semicolon; |
5561 | case RID_RETURN: | |
5562 | c_parser_consume_token (parser); | |
5563 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
5564 | { | |
c2255bc4 | 5565 | stmt = c_finish_return (loc, NULL_TREE, NULL_TREE); |
27bf414c JM |
5566 | c_parser_consume_token (parser); |
5567 | } | |
5568 | else | |
5569 | { | |
6e07c515 | 5570 | location_t xloc = c_parser_peek_token (parser)->location; |
bbbbb16a | 5571 | struct c_expr expr = c_parser_expression_conv (parser); |
ebfbbdc5 | 5572 | mark_exp_read (expr.value); |
94c40e19 DM |
5573 | stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc), |
5574 | expr.value, expr.original_type); | |
27bf414c JM |
5575 | goto expect_semicolon; |
5576 | } | |
5577 | break; | |
5578 | case RID_ASM: | |
5579 | stmt = c_parser_asm_statement (parser); | |
5580 | break; | |
0a35513e AH |
5581 | case RID_TRANSACTION_ATOMIC: |
5582 | case RID_TRANSACTION_RELAXED: | |
5583 | stmt = c_parser_transaction (parser, | |
5584 | c_parser_peek_token (parser)->keyword); | |
5585 | break; | |
5586 | case RID_TRANSACTION_CANCEL: | |
5587 | stmt = c_parser_transaction_cancel (parser); | |
5588 | goto expect_semicolon; | |
49b91f05 | 5589 | case RID_AT_THROW: |
27bf414c JM |
5590 | gcc_assert (c_dialect_objc ()); |
5591 | c_parser_consume_token (parser); | |
5592 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
5593 | { | |
c2255bc4 | 5594 | stmt = objc_build_throw_stmt (loc, NULL_TREE); |
27bf414c JM |
5595 | c_parser_consume_token (parser); |
5596 | } | |
5597 | else | |
5598 | { | |
267bac10 JM |
5599 | struct c_expr expr = c_parser_expression (parser); |
5600 | expr = convert_lvalue_to_rvalue (loc, expr, false, false); | |
e5e44252 AK |
5601 | if (check_no_cilk (expr.value, |
5602 | "Cilk array notation cannot be used for a throw expression", | |
5603 | "%<_Cilk_spawn%> statement cannot be used for a throw expression")) | |
5604 | expr.value = error_mark_node; | |
5605 | else | |
5606 | { | |
5607 | expr.value = c_fully_fold (expr.value, false, NULL); | |
5608 | stmt = objc_build_throw_stmt (loc, expr.value); | |
5609 | } | |
27bf414c JM |
5610 | goto expect_semicolon; |
5611 | } | |
5612 | break; | |
49b91f05 | 5613 | case RID_AT_TRY: |
27bf414c | 5614 | gcc_assert (c_dialect_objc ()); |
437c2322 | 5615 | c_parser_objc_try_catch_finally_statement (parser); |
27bf414c JM |
5616 | break; |
5617 | case RID_AT_SYNCHRONIZED: | |
5618 | gcc_assert (c_dialect_objc ()); | |
5619 | c_parser_objc_synchronized_statement (parser); | |
5620 | break; | |
81fea426 MP |
5621 | case RID_ATTRIBUTE: |
5622 | { | |
5623 | /* Allow '__attribute__((fallthrough));'. */ | |
5624 | tree attrs = c_parser_attributes (parser); | |
5625 | if (attribute_fallthrough_p (attrs)) | |
5626 | { | |
5627 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
5628 | { | |
5629 | tree fn = build_call_expr_internal_loc (loc, | |
5630 | IFN_FALLTHROUGH, | |
5631 | void_type_node, 0); | |
5632 | add_stmt (fn); | |
5633 | /* Eat the ';'. */ | |
5634 | c_parser_consume_token (parser); | |
5635 | } | |
5636 | else | |
5637 | warning_at (loc, OPT_Wattributes, | |
5638 | "%<fallthrough%> attribute not followed " | |
5639 | "by %<;%>"); | |
5640 | } | |
5641 | else if (attrs != NULL_TREE) | |
5642 | warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>" | |
5643 | " can be applied to a null statement"); | |
5644 | break; | |
5645 | } | |
27bf414c JM |
5646 | default: |
5647 | goto expr_stmt; | |
5648 | } | |
5649 | break; | |
5650 | case CPP_SEMICOLON: | |
5651 | c_parser_consume_token (parser); | |
5652 | break; | |
5653 | case CPP_CLOSE_PAREN: | |
5654 | case CPP_CLOSE_SQUARE: | |
5655 | /* Avoid infinite loop in error recovery: | |
5656 | c_parser_skip_until_found stops at a closing nesting | |
5657 | delimiter without consuming it, but here we need to consume | |
5658 | it to proceed further. */ | |
5659 | c_parser_error (parser, "expected statement"); | |
5660 | c_parser_consume_token (parser); | |
5661 | break; | |
bc4071dd | 5662 | case CPP_PRAGMA: |
dda1bf61 | 5663 | c_parser_pragma (parser, pragma_stmt, if_p); |
bc4071dd | 5664 | break; |
27bf414c JM |
5665 | default: |
5666 | expr_stmt: | |
c2255bc4 | 5667 | stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value); |
27bf414c JM |
5668 | expect_semicolon: |
5669 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
5670 | break; | |
5671 | } | |
5672 | /* Two cases cannot and do not have line numbers associated: If stmt | |
5673 | is degenerate, such as "2;", then stmt is an INTEGER_CST, which | |
5674 | cannot hold line numbers. But that's OK because the statement | |
5675 | will either be changed to a MODIFY_EXPR during gimplification of | |
5676 | the statement expr, or discarded. If stmt was compound, but | |
5677 | without new variables, we will have skipped the creation of a | |
5678 | BIND and will have a bare STATEMENT_LIST. But that's OK because | |
5679 | (recursively) all of the component statements should already have | |
5680 | line numbers assigned. ??? Can we discard no-op statements | |
5681 | earlier? */ | |
21ba0cea MP |
5682 | if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION) |
5683 | protected_set_expr_location (stmt, loc); | |
b4b56033 MLI |
5684 | |
5685 | parser->in_if_block = in_if_block; | |
27bf414c JM |
5686 | } |
5687 | ||
ca085fd7 MLI |
5688 | /* Parse the condition from an if, do, while or for statements. */ |
5689 | ||
5690 | static tree | |
5691 | c_parser_condition (c_parser *parser) | |
5692 | { | |
c2255bc4 | 5693 | location_t loc = c_parser_peek_token (parser)->location; |
ca085fd7 | 5694 | tree cond; |
928c19bb JM |
5695 | cond = c_parser_expression_conv (parser).value; |
5696 | cond = c_objc_common_truthvalue_conversion (loc, cond); | |
5697 | cond = c_fully_fold (cond, false, NULL); | |
ca085fd7 MLI |
5698 | if (warn_sequence_point) |
5699 | verify_sequence_points (cond); | |
5700 | return cond; | |
5701 | } | |
5702 | ||
27bf414c JM |
5703 | /* Parse a parenthesized condition from an if, do or while statement. |
5704 | ||
5705 | condition: | |
5706 | ( expression ) | |
5707 | */ | |
5708 | static tree | |
5709 | c_parser_paren_condition (c_parser *parser) | |
5710 | { | |
27bf414c | 5711 | tree cond; |
32129a17 DM |
5712 | matching_parens parens; |
5713 | if (!parens.require_open (parser)) | |
27bf414c | 5714 | return error_mark_node; |
ca085fd7 | 5715 | cond = c_parser_condition (parser); |
32129a17 | 5716 | parens.skip_until_found_close (parser); |
27bf414c JM |
5717 | return cond; |
5718 | } | |
5719 | ||
99cd9857 MP |
5720 | /* Parse a statement which is a block in C99. |
5721 | ||
5722 | IF_P is used to track whether there's a (possibly labeled) if statement | |
5723 | which is not enclosed in braces and has an else clause. This is used to | |
5724 | implement -Wparentheses. */ | |
27bf414c JM |
5725 | |
5726 | static tree | |
3e2becc4 MP |
5727 | c_parser_c99_block_statement (c_parser *parser, bool *if_p, |
5728 | location_t *loc_after_labels) | |
27bf414c JM |
5729 | { |
5730 | tree block = c_begin_compound_stmt (flag_isoc99); | |
c2255bc4 | 5731 | location_t loc = c_parser_peek_token (parser)->location; |
3e2becc4 | 5732 | c_parser_statement (parser, if_p, loc_after_labels); |
c2255bc4 | 5733 | return c_end_compound_stmt (loc, block, flag_isoc99); |
27bf414c JM |
5734 | } |
5735 | ||
b4b56033 MLI |
5736 | /* Parse the body of an if statement. This is just parsing a |
5737 | statement but (a) it is a block in C99, (b) we track whether the | |
5738 | body is an if statement for the sake of -Wparentheses warnings, (c) | |
5739 | we handle an empty body specially for the sake of -Wempty-body | |
5740 | warnings, and (d) we call parser_compound_statement directly | |
5741 | because c_parser_statement_after_labels resets | |
99cd9857 MP |
5742 | parser->in_if_block. |
5743 | ||
5744 | IF_P is used to track whether there's a (possibly labeled) if statement | |
5745 | which is not enclosed in braces and has an else clause. This is used to | |
5746 | implement -Wparentheses. */ | |
27bf414c JM |
5747 | |
5748 | static tree | |
992118a1 PP |
5749 | c_parser_if_body (c_parser *parser, bool *if_p, |
5750 | const token_indent_info &if_tinfo) | |
27bf414c JM |
5751 | { |
5752 | tree block = c_begin_compound_stmt (flag_isoc99); | |
c2255bc4 | 5753 | location_t body_loc = c_parser_peek_token (parser)->location; |
3e2becc4 | 5754 | location_t body_loc_after_labels = UNKNOWN_LOCATION; |
992118a1 PP |
5755 | token_indent_info body_tinfo |
5756 | = get_token_indent_info (c_parser_peek_token (parser)); | |
5757 | ||
74d98c1e | 5758 | c_parser_all_labels (parser); |
62e00e94 | 5759 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
b4b56033 | 5760 | { |
626c34b5 | 5761 | location_t loc = c_parser_peek_token (parser)->location; |
c2255bc4 | 5762 | add_stmt (build_empty_stmt (loc)); |
b4b56033 | 5763 | c_parser_consume_token (parser); |
626c34b5 PB |
5764 | if (!c_parser_next_token_is_keyword (parser, RID_ELSE)) |
5765 | warning_at (loc, OPT_Wempty_body, | |
5766 | "suggest braces around empty body in an %<if%> statement"); | |
b4b56033 MLI |
5767 | } |
5768 | else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
5769 | add_stmt (c_parser_compound_statement (parser)); | |
5770 | else | |
3e2becc4 MP |
5771 | { |
5772 | body_loc_after_labels = c_parser_peek_token (parser)->location; | |
5773 | c_parser_statement_after_labels (parser, if_p); | |
5774 | } | |
992118a1 PP |
5775 | |
5776 | token_indent_info next_tinfo | |
5777 | = get_token_indent_info (c_parser_peek_token (parser)); | |
5778 | warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo); | |
3e2becc4 MP |
5779 | if (body_loc_after_labels != UNKNOWN_LOCATION |
5780 | && next_tinfo.type != CPP_SEMICOLON) | |
5781 | warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location, | |
5782 | if_tinfo.location, RID_IF); | |
c3388e62 | 5783 | |
c2255bc4 | 5784 | return c_end_compound_stmt (body_loc, block, flag_isoc99); |
b4b56033 MLI |
5785 | } |
5786 | ||
5787 | /* Parse the else body of an if statement. This is just parsing a | |
5788 | statement but (a) it is a block in C99, (b) we handle an empty body | |
3e3b8d63 MP |
5789 | specially for the sake of -Wempty-body warnings. CHAIN is a vector |
5790 | of if-else-if conditions. */ | |
b4b56033 MLI |
5791 | |
5792 | static tree | |
3e3b8d63 MP |
5793 | c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo, |
5794 | vec<tree> *chain) | |
b4b56033 | 5795 | { |
c3388e62 | 5796 | location_t body_loc = c_parser_peek_token (parser)->location; |
b4b56033 | 5797 | tree block = c_begin_compound_stmt (flag_isoc99); |
992118a1 PP |
5798 | token_indent_info body_tinfo |
5799 | = get_token_indent_info (c_parser_peek_token (parser)); | |
3e2becc4 | 5800 | location_t body_loc_after_labels = UNKNOWN_LOCATION; |
992118a1 | 5801 | |
74d98c1e | 5802 | c_parser_all_labels (parser); |
b4b56033 MLI |
5803 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
5804 | { | |
c2255bc4 AH |
5805 | location_t loc = c_parser_peek_token (parser)->location; |
5806 | warning_at (loc, | |
626c34b5 PB |
5807 | OPT_Wempty_body, |
5808 | "suggest braces around empty body in an %<else%> statement"); | |
c2255bc4 | 5809 | add_stmt (build_empty_stmt (loc)); |
b4b56033 MLI |
5810 | c_parser_consume_token (parser); |
5811 | } | |
b8698a0f | 5812 | else |
3e2becc4 | 5813 | { |
d49718d6 MP |
5814 | if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
5815 | body_loc_after_labels = c_parser_peek_token (parser)->location; | |
3e2becc4 MP |
5816 | c_parser_statement_after_labels (parser, NULL, chain); |
5817 | } | |
992118a1 PP |
5818 | |
5819 | token_indent_info next_tinfo | |
5820 | = get_token_indent_info (c_parser_peek_token (parser)); | |
5821 | warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo); | |
3e2becc4 MP |
5822 | if (body_loc_after_labels != UNKNOWN_LOCATION |
5823 | && next_tinfo.type != CPP_SEMICOLON) | |
5824 | warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location, | |
5825 | else_tinfo.location, RID_ELSE); | |
992118a1 | 5826 | |
c3388e62 | 5827 | return c_end_compound_stmt (body_loc, block, flag_isoc99); |
27bf414c JM |
5828 | } |
5829 | ||
2448a956 MP |
5830 | /* We might need to reclassify any previously-lexed identifier, e.g. |
5831 | when we've left a for loop with an if-statement without else in the | |
5832 | body - we might have used a wrong scope for the token. See PR67784. */ | |
5833 | ||
5834 | static void | |
5835 | c_parser_maybe_reclassify_token (c_parser *parser) | |
5836 | { | |
5837 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
5838 | { | |
5839 | c_token *token = c_parser_peek_token (parser); | |
5840 | ||
5841 | if (token->id_kind != C_ID_CLASSNAME) | |
5842 | { | |
5843 | tree decl = lookup_name (token->value); | |
5844 | ||
5845 | token->id_kind = C_ID_ID; | |
5846 | if (decl) | |
5847 | { | |
5848 | if (TREE_CODE (decl) == TYPE_DECL) | |
5849 | token->id_kind = C_ID_TYPENAME; | |
5850 | } | |
5851 | else if (c_dialect_objc ()) | |
5852 | { | |
5853 | tree objc_interface_decl = objc_is_class_name (token->value); | |
5854 | /* Objective-C class names are in the same namespace as | |
5855 | variables and typedefs, and hence are shadowed by local | |
5856 | declarations. */ | |
5857 | if (objc_interface_decl) | |
5858 | { | |
5859 | token->value = objc_interface_decl; | |
5860 | token->id_kind = C_ID_CLASSNAME; | |
5861 | } | |
5862 | } | |
5863 | } | |
5864 | } | |
5865 | } | |
5866 | ||
31dc71a8 | 5867 | /* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4). |
27bf414c JM |
5868 | |
5869 | if-statement: | |
5870 | if ( expression ) statement | |
5871 | if ( expression ) statement else statement | |
3e3b8d63 | 5872 | |
99cd9857 MP |
5873 | CHAIN is a vector of if-else-if conditions. |
5874 | IF_P is used to track whether there's a (possibly labeled) if statement | |
5875 | which is not enclosed in braces and has an else clause. This is used to | |
5876 | implement -Wparentheses. */ | |
27bf414c JM |
5877 | |
5878 | static void | |
99cd9857 | 5879 | c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain) |
27bf414c JM |
5880 | { |
5881 | tree block; | |
5882 | location_t loc; | |
5883 | tree cond; | |
99cd9857 | 5884 | bool nested_if = false; |
27bf414c | 5885 | tree first_body, second_body; |
b4b56033 | 5886 | bool in_if_block; |
36536d79 | 5887 | tree if_stmt; |
b4b56033 | 5888 | |
27bf414c | 5889 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF)); |
992118a1 PP |
5890 | token_indent_info if_tinfo |
5891 | = get_token_indent_info (c_parser_peek_token (parser)); | |
27bf414c JM |
5892 | c_parser_consume_token (parser); |
5893 | block = c_begin_compound_stmt (flag_isoc99); | |
5894 | loc = c_parser_peek_token (parser)->location; | |
5895 | cond = c_parser_paren_condition (parser); | |
e5e44252 AK |
5896 | if (flag_cilkplus && contains_cilk_spawn_stmt (cond)) |
5897 | { | |
5898 | error_at (loc, "if statement cannot contain %<Cilk_spawn%>"); | |
5899 | cond = error_mark_node; | |
5900 | } | |
b4b56033 MLI |
5901 | in_if_block = parser->in_if_block; |
5902 | parser->in_if_block = true; | |
99cd9857 | 5903 | first_body = c_parser_if_body (parser, &nested_if, if_tinfo); |
b4b56033 | 5904 | parser->in_if_block = in_if_block; |
3e3b8d63 MP |
5905 | |
5906 | if (warn_duplicated_cond) | |
5907 | warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain); | |
5908 | ||
27bf414c JM |
5909 | if (c_parser_next_token_is_keyword (parser, RID_ELSE)) |
5910 | { | |
992118a1 PP |
5911 | token_indent_info else_tinfo |
5912 | = get_token_indent_info (c_parser_peek_token (parser)); | |
27bf414c | 5913 | c_parser_consume_token (parser); |
3e3b8d63 MP |
5914 | if (warn_duplicated_cond) |
5915 | { | |
5916 | if (c_parser_next_token_is_keyword (parser, RID_IF) | |
5917 | && chain == NULL) | |
5918 | { | |
5919 | /* We've got "if (COND) else if (COND2)". Start the | |
5920 | condition chain and add COND as the first element. */ | |
5921 | chain = new vec<tree> (); | |
5922 | if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond)) | |
5923 | chain->safe_push (cond); | |
5924 | } | |
5925 | else if (!c_parser_next_token_is_keyword (parser, RID_IF)) | |
5926 | { | |
5927 | /* This is if-else without subsequent if. Zap the condition | |
5928 | chain; we would have already warned at this point. */ | |
5929 | delete chain; | |
5930 | chain = NULL; | |
5931 | } | |
5932 | } | |
5933 | second_body = c_parser_else_body (parser, else_tinfo, chain); | |
99cd9857 MP |
5934 | /* Set IF_P to true to indicate that this if statement has an |
5935 | else clause. This may trigger the Wparentheses warning | |
5936 | below when we get back up to the parent if statement. */ | |
5937 | if (if_p != NULL) | |
5938 | *if_p = true; | |
27bf414c JM |
5939 | } |
5940 | else | |
3e3b8d63 MP |
5941 | { |
5942 | second_body = NULL_TREE; | |
99cd9857 MP |
5943 | |
5944 | /* Diagnose an ambiguous else if if-then-else is nested inside | |
5945 | if-then. */ | |
5946 | if (nested_if) | |
deef7113 | 5947 | warning_at (loc, OPT_Wdangling_else, |
99cd9857 MP |
5948 | "suggest explicit braces to avoid ambiguous %<else%>"); |
5949 | ||
3e3b8d63 MP |
5950 | if (warn_duplicated_cond) |
5951 | { | |
5952 | /* This if statement does not have an else clause. We don't | |
5953 | need the condition chain anymore. */ | |
5954 | delete chain; | |
5955 | chain = NULL; | |
5956 | } | |
5957 | } | |
99cd9857 | 5958 | c_finish_if_stmt (loc, cond, first_body, second_body); |
36536d79 BI |
5959 | if_stmt = c_end_compound_stmt (loc, block, flag_isoc99); |
5960 | ||
5961 | /* If the if statement contains array notations, then we expand them. */ | |
b72271b9 | 5962 | if (flag_cilkplus && contains_array_notation_expr (if_stmt)) |
36536d79 BI |
5963 | if_stmt = fix_conditional_array_notations (if_stmt); |
5964 | add_stmt (if_stmt); | |
2448a956 | 5965 | c_parser_maybe_reclassify_token (parser); |
27bf414c JM |
5966 | } |
5967 | ||
31dc71a8 | 5968 | /* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4). |
27bf414c JM |
5969 | |
5970 | switch-statement: | |
5971 | switch (expression) statement | |
5972 | */ | |
5973 | ||
5974 | static void | |
351f85c5 | 5975 | c_parser_switch_statement (c_parser *parser, bool *if_p) |
27bf414c | 5976 | { |
267bac10 | 5977 | struct c_expr ce; |
27bf414c | 5978 | tree block, expr, body, save_break; |
c2255bc4 AH |
5979 | location_t switch_loc = c_parser_peek_token (parser)->location; |
5980 | location_t switch_cond_loc; | |
27bf414c JM |
5981 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH)); |
5982 | c_parser_consume_token (parser); | |
5983 | block = c_begin_compound_stmt (flag_isoc99); | |
fedfecef | 5984 | bool explicit_cast_p = false; |
32129a17 DM |
5985 | matching_parens parens; |
5986 | if (parens.require_open (parser)) | |
27bf414c | 5987 | { |
c2255bc4 | 5988 | switch_cond_loc = c_parser_peek_token (parser)->location; |
fedfecef MP |
5989 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
5990 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) | |
5991 | explicit_cast_p = true; | |
267bac10 JM |
5992 | ce = c_parser_expression (parser); |
5993 | ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false); | |
5994 | expr = ce.value; | |
e5e44252 AK |
5995 | /* ??? expr has no valid location? */ |
5996 | if (check_no_cilk (expr, | |
5997 | "Cilk array notation cannot be used as a condition for switch statement", | |
5998 | "%<_Cilk_spawn%> statement cannot be used as a condition for switch statement", | |
5999 | switch_cond_loc)) | |
6000 | expr = error_mark_node; | |
32129a17 | 6001 | parens.skip_until_found_close (parser); |
27bf414c JM |
6002 | } |
6003 | else | |
c2255bc4 AH |
6004 | { |
6005 | switch_cond_loc = UNKNOWN_LOCATION; | |
6006 | expr = error_mark_node; | |
efd0786f | 6007 | ce.original_type = error_mark_node; |
c2255bc4 | 6008 | } |
fedfecef | 6009 | c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p); |
27bf414c JM |
6010 | save_break = c_break_label; |
6011 | c_break_label = NULL_TREE; | |
3e2becc4 MP |
6012 | location_t loc_after_labels; |
6013 | bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE; | |
6014 | body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels); | |
6015 | location_t next_loc = c_parser_peek_token (parser)->location; | |
6016 | if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON) | |
6017 | warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc, | |
6018 | RID_SWITCH); | |
083e891e | 6019 | c_finish_case (body, ce.original_type); |
27bf414c | 6020 | if (c_break_label) |
c2255bc4 AH |
6021 | { |
6022 | location_t here = c_parser_peek_token (parser)->location; | |
6023 | tree t = build1 (LABEL_EXPR, void_type_node, c_break_label); | |
6024 | SET_EXPR_LOCATION (t, here); | |
6025 | add_stmt (t); | |
6026 | } | |
27bf414c | 6027 | c_break_label = save_break; |
c2255bc4 | 6028 | add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); |
2448a956 | 6029 | c_parser_maybe_reclassify_token (parser); |
27bf414c JM |
6030 | } |
6031 | ||
31dc71a8 | 6032 | /* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5). |
27bf414c JM |
6033 | |
6034 | while-statement: | |
6035 | while (expression) statement | |
99cd9857 MP |
6036 | |
6037 | IF_P is used to track whether there's a (possibly labeled) if statement | |
6038 | which is not enclosed in braces and has an else clause. This is used to | |
6039 | implement -Wparentheses. */ | |
27bf414c JM |
6040 | |
6041 | static void | |
99cd9857 | 6042 | c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) |
27bf414c JM |
6043 | { |
6044 | tree block, cond, body, save_break, save_cont; | |
6045 | location_t loc; | |
6046 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE)); | |
992118a1 PP |
6047 | token_indent_info while_tinfo |
6048 | = get_token_indent_info (c_parser_peek_token (parser)); | |
27bf414c JM |
6049 | c_parser_consume_token (parser); |
6050 | block = c_begin_compound_stmt (flag_isoc99); | |
6051 | loc = c_parser_peek_token (parser)->location; | |
6052 | cond = c_parser_paren_condition (parser); | |
e5e44252 AK |
6053 | if (check_no_cilk (cond, |
6054 | "Cilk array notation cannot be used as a condition for while statement", | |
6055 | "%<_Cilk_spawn%> statement cannot be used as a condition for while statement")) | |
6056 | cond = error_mark_node; | |
d4af74d4 | 6057 | if (ivdep && cond != error_mark_node) |
ac9effed | 6058 | cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, |
d4af74d4 | 6059 | build_int_cst (integer_type_node, |
ac9effed EB |
6060 | annot_expr_ivdep_kind), |
6061 | integer_zero_node); | |
27bf414c JM |
6062 | save_break = c_break_label; |
6063 | c_break_label = NULL_TREE; | |
6064 | save_cont = c_cont_label; | |
6065 | c_cont_label = NULL_TREE; | |
c3388e62 | 6066 | |
992118a1 PP |
6067 | token_indent_info body_tinfo |
6068 | = get_token_indent_info (c_parser_peek_token (parser)); | |
6069 | ||
3e2becc4 | 6070 | location_t loc_after_labels; |
d49718d6 | 6071 | bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE); |
3e2becc4 | 6072 | body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels); |
f6b0b3db AA |
6073 | c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true); |
6074 | add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); | |
2448a956 | 6075 | c_parser_maybe_reclassify_token (parser); |
992118a1 PP |
6076 | |
6077 | token_indent_info next_tinfo | |
6078 | = get_token_indent_info (c_parser_peek_token (parser)); | |
6079 | warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo); | |
c3388e62 | 6080 | |
d49718d6 | 6081 | if (next_tinfo.type != CPP_SEMICOLON && !open_brace) |
3e2becc4 MP |
6082 | warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, |
6083 | while_tinfo.location, RID_WHILE); | |
6084 | ||
27bf414c JM |
6085 | c_break_label = save_break; |
6086 | c_cont_label = save_cont; | |
6087 | } | |
6088 | ||
31dc71a8 | 6089 | /* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5). |
27bf414c JM |
6090 | |
6091 | do-statement: | |
6092 | do statement while ( expression ) ; | |
6093 | */ | |
6094 | ||
6095 | static void | |
d4af74d4 | 6096 | c_parser_do_statement (c_parser *parser, bool ivdep) |
27bf414c JM |
6097 | { |
6098 | tree block, cond, body, save_break, save_cont, new_break, new_cont; | |
6099 | location_t loc; | |
6100 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO)); | |
6101 | c_parser_consume_token (parser); | |
62e00e94 | 6102 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
3ba09659 AH |
6103 | warning_at (c_parser_peek_token (parser)->location, |
6104 | OPT_Wempty_body, | |
6105 | "suggest braces around empty body in %<do%> statement"); | |
27bf414c JM |
6106 | block = c_begin_compound_stmt (flag_isoc99); |
6107 | loc = c_parser_peek_token (parser)->location; | |
6108 | save_break = c_break_label; | |
6109 | c_break_label = NULL_TREE; | |
6110 | save_cont = c_cont_label; | |
6111 | c_cont_label = NULL_TREE; | |
99cd9857 | 6112 | body = c_parser_c99_block_statement (parser, NULL); |
27bf414c JM |
6113 | c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>"); |
6114 | new_break = c_break_label; | |
6115 | c_break_label = save_break; | |
6116 | new_cont = c_cont_label; | |
6117 | c_cont_label = save_cont; | |
6118 | cond = c_parser_paren_condition (parser); | |
e5e44252 AK |
6119 | if (check_no_cilk (cond, |
6120 | "Cilk array notation cannot be used as a condition for a do-while statement", | |
6121 | "%<_Cilk_spawn%> statement cannot be used as a condition for a do-while statement")) | |
6122 | cond = error_mark_node; | |
d4af74d4 | 6123 | if (ivdep && cond != error_mark_node) |
ac9effed | 6124 | cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, |
d4af74d4 | 6125 | build_int_cst (integer_type_node, |
ac9effed EB |
6126 | annot_expr_ivdep_kind), |
6127 | integer_zero_node); | |
27bf414c JM |
6128 | if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) |
6129 | c_parser_skip_to_end_of_block_or_statement (parser); | |
6130 | c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); | |
c2255bc4 | 6131 | add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); |
27bf414c JM |
6132 | } |
6133 | ||
31dc71a8 | 6134 | /* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5). |
27bf414c JM |
6135 | |
6136 | for-statement: | |
6137 | for ( expression[opt] ; expression[opt] ; expression[opt] ) statement | |
6138 | for ( nested-declaration expression[opt] ; expression[opt] ) statement | |
6139 | ||
6140 | The form with a declaration is new in C99. | |
6141 | ||
6142 | ??? In accordance with the old parser, the declaration may be a | |
6143 | nested function, which is then rejected in check_for_loop_decls, | |
6144 | but does it make any sense for this to be included in the grammar? | |
6145 | Note in particular that the nested function does not include a | |
6146 | trailing ';', whereas the "declaration" production includes one. | |
6147 | Also, can we reject bad declarations earlier and cheaper than | |
f05b9d93 NP |
6148 | check_for_loop_decls? |
6149 | ||
6150 | In Objective-C, there are two additional variants: | |
6151 | ||
6152 | foreach-statement: | |
6153 | for ( expression in expresssion ) statement | |
6154 | for ( declaration in expression ) statement | |
6155 | ||
6156 | This is inconsistent with C, because the second variant is allowed | |
6157 | even if c99 is not enabled. | |
6158 | ||
6159 | The rest of the comment documents these Objective-C foreach-statement. | |
6160 | ||
6161 | Here is the canonical example of the first variant: | |
6162 | for (object in array) { do something with object } | |
6163 | we call the first expression ("object") the "object_expression" and | |
6164 | the second expression ("array") the "collection_expression". | |
6165 | object_expression must be an lvalue of type "id" (a generic Objective-C | |
6166 | object) because the loop works by assigning to object_expression the | |
6167 | various objects from the collection_expression. collection_expression | |
6168 | must evaluate to something of type "id" which responds to the method | |
6169 | countByEnumeratingWithState:objects:count:. | |
6170 | ||
6171 | The canonical example of the second variant is: | |
6172 | for (id object in array) { do something with object } | |
6173 | which is completely equivalent to | |
6174 | { | |
6175 | id object; | |
6176 | for (object in array) { do something with object } | |
6177 | } | |
6178 | Note that initizializing 'object' in some way (eg, "for ((object = | |
6179 | xxx) in array) { do something with object }") is possibly | |
6180 | technically valid, but completely pointless as 'object' will be | |
6181 | assigned to something else as soon as the loop starts. We should | |
6182 | most likely reject it (TODO). | |
6183 | ||
6184 | The beginning of the Objective-C foreach-statement looks exactly | |
6185 | like the beginning of the for-statement, and we can tell it is a | |
6186 | foreach-statement only because the initial declaration or | |
6187 | expression is terminated by 'in' instead of ';'. | |
99cd9857 MP |
6188 | |
6189 | IF_P is used to track whether there's a (possibly labeled) if statement | |
6190 | which is not enclosed in braces and has an else clause. This is used to | |
6191 | implement -Wparentheses. */ | |
27bf414c JM |
6192 | |
6193 | static void | |
99cd9857 | 6194 | c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) |
27bf414c JM |
6195 | { |
6196 | tree block, cond, incr, save_break, save_cont, body; | |
f05b9d93 | 6197 | /* The following are only used when parsing an ObjC foreach statement. */ |
689f2c82 AO |
6198 | tree object_expression; |
6199 | /* Silence the bogus uninitialized warning. */ | |
6200 | tree collection_expression = NULL; | |
c2255bc4 AH |
6201 | location_t loc = c_parser_peek_token (parser)->location; |
6202 | location_t for_loc = c_parser_peek_token (parser)->location; | |
f05b9d93 | 6203 | bool is_foreach_statement = false; |
27bf414c | 6204 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); |
992118a1 PP |
6205 | token_indent_info for_tinfo |
6206 | = get_token_indent_info (c_parser_peek_token (parser)); | |
27bf414c | 6207 | c_parser_consume_token (parser); |
f05b9d93 NP |
6208 | /* Open a compound statement in Objective-C as well, just in case this is |
6209 | as foreach expression. */ | |
6210 | block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ()); | |
91b90ead UB |
6211 | cond = error_mark_node; |
6212 | incr = error_mark_node; | |
32129a17 DM |
6213 | matching_parens parens; |
6214 | if (parens.require_open (parser)) | |
27bf414c JM |
6215 | { |
6216 | /* Parse the initialization declaration or expression. */ | |
f05b9d93 | 6217 | object_expression = error_mark_node; |
a5812bdc | 6218 | parser->objc_could_be_foreach_context = c_dialect_objc (); |
27bf414c JM |
6219 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
6220 | { | |
a5812bdc | 6221 | parser->objc_could_be_foreach_context = false; |
27bf414c | 6222 | c_parser_consume_token (parser); |
c2255bc4 | 6223 | c_finish_expr_stmt (loc, NULL_TREE); |
27bf414c | 6224 | } |
2f413185 | 6225 | else if (c_parser_next_tokens_start_declaration (parser)) |
27bf414c | 6226 | { |
f05b9d93 | 6227 | c_parser_declaration_or_fndef (parser, true, true, true, true, true, |
acf0174b | 6228 | &object_expression, vNULL); |
f05b9d93 NP |
6229 | parser->objc_could_be_foreach_context = false; |
6230 | ||
6231 | if (c_parser_next_token_is_keyword (parser, RID_IN)) | |
6232 | { | |
6233 | c_parser_consume_token (parser); | |
6234 | is_foreach_statement = true; | |
6235 | if (check_for_loop_decls (for_loc, true) == NULL_TREE) | |
6236 | c_parser_error (parser, "multiple iterating variables in fast enumeration"); | |
6237 | } | |
6238 | else | |
6239 | check_for_loop_decls (for_loc, flag_isoc99); | |
27bf414c JM |
6240 | } |
6241 | else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) | |
6242 | { | |
6243 | /* __extension__ can start a declaration, but is also an | |
6244 | unary operator that can start an expression. Consume all | |
6245 | but the last of a possible series of __extension__ to | |
6246 | determine which. */ | |
6247 | while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD | |
6248 | && (c_parser_peek_2nd_token (parser)->keyword | |
6249 | == RID_EXTENSION)) | |
6250 | c_parser_consume_token (parser); | |
32912286 | 6251 | if (c_token_starts_declaration (c_parser_peek_2nd_token (parser))) |
27bf414c JM |
6252 | { |
6253 | int ext; | |
6254 | ext = disable_extension_diagnostics (); | |
6255 | c_parser_consume_token (parser); | |
32912286 | 6256 | c_parser_declaration_or_fndef (parser, true, true, true, true, |
acf0174b | 6257 | true, &object_expression, vNULL); |
f05b9d93 NP |
6258 | parser->objc_could_be_foreach_context = false; |
6259 | ||
27bf414c | 6260 | restore_extension_diagnostics (ext); |
f05b9d93 NP |
6261 | if (c_parser_next_token_is_keyword (parser, RID_IN)) |
6262 | { | |
6263 | c_parser_consume_token (parser); | |
6264 | is_foreach_statement = true; | |
6265 | if (check_for_loop_decls (for_loc, true) == NULL_TREE) | |
6266 | c_parser_error (parser, "multiple iterating variables in fast enumeration"); | |
6267 | } | |
6268 | else | |
6269 | check_for_loop_decls (for_loc, flag_isoc99); | |
27bf414c JM |
6270 | } |
6271 | else | |
6272 | goto init_expr; | |
6273 | } | |
6274 | else | |
6275 | { | |
6276 | init_expr: | |
f05b9d93 | 6277 | { |
267bac10 | 6278 | struct c_expr ce; |
f05b9d93 | 6279 | tree init_expression; |
267bac10 | 6280 | ce = c_parser_expression (parser); |
e5e44252 AK |
6281 | /* In theory we could forbid _Cilk_spawn here, as the spec says "only in top |
6282 | level statement", but it works just fine, so allow it. */ | |
267bac10 | 6283 | init_expression = ce.value; |
f05b9d93 NP |
6284 | parser->objc_could_be_foreach_context = false; |
6285 | if (c_parser_next_token_is_keyword (parser, RID_IN)) | |
6286 | { | |
6287 | c_parser_consume_token (parser); | |
6288 | is_foreach_statement = true; | |
6289 | if (! lvalue_p (init_expression)) | |
6290 | c_parser_error (parser, "invalid iterating variable in fast enumeration"); | |
69a97201 | 6291 | object_expression = c_fully_fold (init_expression, false, NULL); |
f05b9d93 NP |
6292 | } |
6293 | else | |
6294 | { | |
267bac10 JM |
6295 | ce = convert_lvalue_to_rvalue (loc, ce, true, false); |
6296 | init_expression = ce.value; | |
f05b9d93 NP |
6297 | c_finish_expr_stmt (loc, init_expression); |
6298 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
6299 | } | |
6300 | } | |
27bf414c | 6301 | } |
f05b9d93 NP |
6302 | /* Parse the loop condition. In the case of a foreach |
6303 | statement, there is no loop condition. */ | |
a5812bdc | 6304 | gcc_assert (!parser->objc_could_be_foreach_context); |
f05b9d93 | 6305 | if (!is_foreach_statement) |
27bf414c | 6306 | { |
f05b9d93 NP |
6307 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
6308 | { | |
8170608b TB |
6309 | if (ivdep) |
6310 | { | |
6311 | c_parser_error (parser, "missing loop condition in loop with " | |
6312 | "%<GCC ivdep%> pragma"); | |
6313 | cond = error_mark_node; | |
6314 | } | |
6315 | else | |
6316 | { | |
6317 | c_parser_consume_token (parser); | |
6318 | cond = NULL_TREE; | |
6319 | } | |
f05b9d93 NP |
6320 | } |
6321 | else | |
6322 | { | |
6323 | cond = c_parser_condition (parser); | |
e5e44252 AK |
6324 | if (check_no_cilk (cond, |
6325 | "Cilk array notation cannot be used in a condition for a for-loop", | |
6326 | "%<_Cilk_spawn%> statement cannot be used in a condition for a for-loop")) | |
6327 | cond = error_mark_node; | |
36536d79 BI |
6328 | c_parser_skip_until_found (parser, CPP_SEMICOLON, |
6329 | "expected %<;%>"); | |
f05b9d93 | 6330 | } |
8170608b | 6331 | if (ivdep && cond != error_mark_node) |
ac9effed | 6332 | cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, |
8170608b | 6333 | build_int_cst (integer_type_node, |
ac9effed EB |
6334 | annot_expr_ivdep_kind), |
6335 | integer_zero_node); | |
27bf414c | 6336 | } |
f05b9d93 NP |
6337 | /* Parse the increment expression (the third expression in a |
6338 | for-statement). In the case of a foreach-statement, this is | |
6339 | the expression that follows the 'in'. */ | |
6340 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
27bf414c | 6341 | { |
f05b9d93 NP |
6342 | if (is_foreach_statement) |
6343 | { | |
6344 | c_parser_error (parser, "missing collection in fast enumeration"); | |
6345 | collection_expression = error_mark_node; | |
6346 | } | |
6347 | else | |
6348 | incr = c_process_expr_stmt (loc, NULL_TREE); | |
27bf414c | 6349 | } |
27bf414c | 6350 | else |
f05b9d93 NP |
6351 | { |
6352 | if (is_foreach_statement) | |
69a97201 NP |
6353 | collection_expression = c_fully_fold (c_parser_expression (parser).value, |
6354 | false, NULL); | |
f05b9d93 | 6355 | else |
267bac10 JM |
6356 | { |
6357 | struct c_expr ce = c_parser_expression (parser); | |
6358 | ce = convert_lvalue_to_rvalue (loc, ce, true, false); | |
6359 | incr = c_process_expr_stmt (loc, ce.value); | |
6360 | } | |
f05b9d93 | 6361 | } |
32129a17 | 6362 | parens.skip_until_found_close (parser); |
27bf414c | 6363 | } |
27bf414c JM |
6364 | save_break = c_break_label; |
6365 | c_break_label = NULL_TREE; | |
6366 | save_cont = c_cont_label; | |
6367 | c_cont_label = NULL_TREE; | |
c3388e62 | 6368 | |
992118a1 PP |
6369 | token_indent_info body_tinfo |
6370 | = get_token_indent_info (c_parser_peek_token (parser)); | |
6371 | ||
3e2becc4 | 6372 | location_t loc_after_labels; |
d49718d6 | 6373 | bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE); |
3e2becc4 | 6374 | body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels); |
992118a1 | 6375 | |
f05b9d93 NP |
6376 | if (is_foreach_statement) |
6377 | objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label); | |
6378 | else | |
6379 | c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true); | |
6380 | add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ())); | |
2448a956 | 6381 | c_parser_maybe_reclassify_token (parser); |
9be4f715 | 6382 | |
f6b0b3db AA |
6383 | token_indent_info next_tinfo |
6384 | = get_token_indent_info (c_parser_peek_token (parser)); | |
6385 | warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo); | |
6386 | ||
d49718d6 | 6387 | if (next_tinfo.type != CPP_SEMICOLON && !open_brace) |
3e2becc4 MP |
6388 | warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, |
6389 | for_tinfo.location, RID_FOR); | |
6390 | ||
27bf414c JM |
6391 | c_break_label = save_break; |
6392 | c_cont_label = save_cont; | |
6393 | } | |
6394 | ||
6395 | /* Parse an asm statement, a GNU extension. This is a full-blown asm | |
6396 | statement with inputs, outputs, clobbers, and volatile tag | |
6397 | allowed. | |
6398 | ||
6399 | asm-statement: | |
6400 | asm type-qualifier[opt] ( asm-argument ) ; | |
1c384bf1 | 6401 | asm type-qualifier[opt] goto ( asm-goto-argument ) ; |
27bf414c JM |
6402 | |
6403 | asm-argument: | |
6404 | asm-string-literal | |
6405 | asm-string-literal : asm-operands[opt] | |
6406 | asm-string-literal : asm-operands[opt] : asm-operands[opt] | |
1c384bf1 RH |
6407 | asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt] |
6408 | ||
6409 | asm-goto-argument: | |
6410 | asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \ | |
6411 | : asm-goto-operands | |
27bf414c JM |
6412 | |
6413 | Qualifiers other than volatile are accepted in the syntax but | |
6414 | warned for. */ | |
6415 | ||
6416 | static tree | |
6417 | c_parser_asm_statement (c_parser *parser) | |
6418 | { | |
1c384bf1 RH |
6419 | tree quals, str, outputs, inputs, clobbers, labels, ret; |
6420 | bool simple, is_goto; | |
c2255bc4 | 6421 | location_t asm_loc = c_parser_peek_token (parser)->location; |
1c384bf1 RH |
6422 | int section, nsections; |
6423 | ||
27bf414c JM |
6424 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); |
6425 | c_parser_consume_token (parser); | |
6426 | if (c_parser_next_token_is_keyword (parser, RID_VOLATILE)) | |
6427 | { | |
6428 | quals = c_parser_peek_token (parser)->value; | |
6429 | c_parser_consume_token (parser); | |
6430 | } | |
6431 | else if (c_parser_next_token_is_keyword (parser, RID_CONST) | |
6432 | || c_parser_next_token_is_keyword (parser, RID_RESTRICT)) | |
6433 | { | |
3ba09659 AH |
6434 | warning_at (c_parser_peek_token (parser)->location, |
6435 | 0, | |
6436 | "%E qualifier ignored on asm", | |
6437 | c_parser_peek_token (parser)->value); | |
27bf414c JM |
6438 | quals = NULL_TREE; |
6439 | c_parser_consume_token (parser); | |
6440 | } | |
6441 | else | |
6442 | quals = NULL_TREE; | |
1c384bf1 RH |
6443 | |
6444 | is_goto = false; | |
6445 | if (c_parser_next_token_is_keyword (parser, RID_GOTO)) | |
6446 | { | |
6447 | c_parser_consume_token (parser); | |
6448 | is_goto = true; | |
6449 | } | |
6450 | ||
27bf414c | 6451 | /* ??? Follow the C++ parser rather than using the |
46c2514e TT |
6452 | lex_untranslated_string kludge. */ |
6453 | parser->lex_untranslated_string = true; | |
1c384bf1 RH |
6454 | ret = NULL; |
6455 | ||
32129a17 DM |
6456 | matching_parens parens; |
6457 | if (!parens.require_open (parser)) | |
1c384bf1 RH |
6458 | goto error; |
6459 | ||
27bf414c | 6460 | str = c_parser_asm_string_literal (parser); |
b85eb797 | 6461 | if (str == NULL_TREE) |
1c384bf1 RH |
6462 | goto error_close_paren; |
6463 | ||
6464 | simple = true; | |
6465 | outputs = NULL_TREE; | |
6466 | inputs = NULL_TREE; | |
6467 | clobbers = NULL_TREE; | |
6468 | labels = NULL_TREE; | |
6469 | ||
6470 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) | |
6471 | goto done_asm; | |
6472 | ||
6473 | /* Parse each colon-delimited section of operands. */ | |
6474 | nsections = 3 + is_goto; | |
6475 | for (section = 0; section < nsections; ++section) | |
b85eb797 | 6476 | { |
1c384bf1 RH |
6477 | if (!c_parser_require (parser, CPP_COLON, |
6478 | is_goto | |
324ff1a0 | 6479 | ? G_("expected %<:%>") |
62e1c678 DM |
6480 | : G_("expected %<:%> or %<)%>"), |
6481 | UNKNOWN_LOCATION, is_goto)) | |
1c384bf1 RH |
6482 | goto error_close_paren; |
6483 | ||
6484 | /* Once past any colon, we're no longer a simple asm. */ | |
6485 | simple = false; | |
6486 | ||
6487 | if ((!c_parser_next_token_is (parser, CPP_COLON) | |
6488 | && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
6489 | || section == 3) | |
6490 | switch (section) | |
6491 | { | |
6492 | case 0: | |
6493 | /* For asm goto, we don't allow output operands, but reserve | |
6494 | the slot for a future extension that does allow them. */ | |
6495 | if (!is_goto) | |
eadd3d0d | 6496 | outputs = c_parser_asm_operands (parser); |
1c384bf1 RH |
6497 | break; |
6498 | case 1: | |
eadd3d0d | 6499 | inputs = c_parser_asm_operands (parser); |
1c384bf1 RH |
6500 | break; |
6501 | case 2: | |
6502 | clobbers = c_parser_asm_clobbers (parser); | |
6503 | break; | |
6504 | case 3: | |
6505 | labels = c_parser_asm_goto_operands (parser); | |
6506 | break; | |
6507 | default: | |
6508 | gcc_unreachable (); | |
6509 | } | |
6510 | ||
6511 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) | |
6512 | goto done_asm; | |
27bf414c | 6513 | } |
1c384bf1 | 6514 | |
27bf414c | 6515 | done_asm: |
32129a17 | 6516 | if (!parens.require_close (parser)) |
27bf414c JM |
6517 | { |
6518 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
1c384bf1 | 6519 | goto error; |
27bf414c | 6520 | } |
1c384bf1 | 6521 | |
27bf414c JM |
6522 | if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) |
6523 | c_parser_skip_to_end_of_block_or_statement (parser); | |
1c384bf1 | 6524 | |
c2255bc4 | 6525 | ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs, |
1c384bf1 RH |
6526 | clobbers, labels, simple)); |
6527 | ||
6528 | error: | |
6529 | parser->lex_untranslated_string = false; | |
27bf414c | 6530 | return ret; |
1c384bf1 RH |
6531 | |
6532 | error_close_paren: | |
6533 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
6534 | goto error; | |
27bf414c JM |
6535 | } |
6536 | ||
eadd3d0d | 6537 | /* Parse asm operands, a GNU extension. |
27bf414c JM |
6538 | |
6539 | asm-operands: | |
6540 | asm-operand | |
6541 | asm-operands , asm-operand | |
6542 | ||
6543 | asm-operand: | |
6544 | asm-string-literal ( expression ) | |
6545 | [ identifier ] asm-string-literal ( expression ) | |
6546 | */ | |
6547 | ||
6548 | static tree | |
eadd3d0d | 6549 | c_parser_asm_operands (c_parser *parser) |
27bf414c JM |
6550 | { |
6551 | tree list = NULL_TREE; | |
6552 | while (true) | |
6553 | { | |
f2a71bbc JM |
6554 | tree name, str; |
6555 | struct c_expr expr; | |
27bf414c JM |
6556 | if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) |
6557 | { | |
6558 | c_parser_consume_token (parser); | |
6559 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
6560 | { | |
6561 | tree id = c_parser_peek_token (parser)->value; | |
6562 | c_parser_consume_token (parser); | |
6563 | name = build_string (IDENTIFIER_LENGTH (id), | |
6564 | IDENTIFIER_POINTER (id)); | |
6565 | } | |
6566 | else | |
6567 | { | |
6568 | c_parser_error (parser, "expected identifier"); | |
6569 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
6570 | return NULL_TREE; | |
6571 | } | |
6572 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, | |
6573 | "expected %<]%>"); | |
6574 | } | |
6575 | else | |
6576 | name = NULL_TREE; | |
6577 | str = c_parser_asm_string_literal (parser); | |
6578 | if (str == NULL_TREE) | |
6579 | return NULL_TREE; | |
46c2514e | 6580 | parser->lex_untranslated_string = false; |
32129a17 DM |
6581 | matching_parens parens; |
6582 | if (!parens.require_open (parser)) | |
27bf414c | 6583 | { |
46c2514e | 6584 | parser->lex_untranslated_string = true; |
27bf414c JM |
6585 | return NULL_TREE; |
6586 | } | |
f2a71bbc | 6587 | expr = c_parser_expression (parser); |
ebfbbdc5 | 6588 | mark_exp_read (expr.value); |
46c2514e | 6589 | parser->lex_untranslated_string = true; |
32129a17 | 6590 | if (!parens.require_close (parser)) |
27bf414c JM |
6591 | { |
6592 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
6593 | return NULL_TREE; | |
6594 | } | |
6595 | list = chainon (list, build_tree_list (build_tree_list (name, str), | |
f2a71bbc | 6596 | expr.value)); |
27bf414c JM |
6597 | if (c_parser_next_token_is (parser, CPP_COMMA)) |
6598 | c_parser_consume_token (parser); | |
6599 | else | |
6600 | break; | |
6601 | } | |
6602 | return list; | |
6603 | } | |
6604 | ||
6605 | /* Parse asm clobbers, a GNU extension. | |
6606 | ||
6607 | asm-clobbers: | |
6608 | asm-string-literal | |
6609 | asm-clobbers , asm-string-literal | |
6610 | */ | |
6611 | ||
6612 | static tree | |
6613 | c_parser_asm_clobbers (c_parser *parser) | |
6614 | { | |
6615 | tree list = NULL_TREE; | |
6616 | while (true) | |
6617 | { | |
6618 | tree str = c_parser_asm_string_literal (parser); | |
6619 | if (str) | |
6620 | list = tree_cons (NULL_TREE, str, list); | |
6621 | else | |
6622 | return NULL_TREE; | |
6623 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
6624 | c_parser_consume_token (parser); | |
6625 | else | |
6626 | break; | |
6627 | } | |
6628 | return list; | |
6629 | } | |
6630 | ||
1c384bf1 | 6631 | /* Parse asm goto labels, a GNU extension. |
b8698a0f | 6632 | |
1c384bf1 RH |
6633 | asm-goto-operands: |
6634 | identifier | |
6635 | asm-goto-operands , identifier | |
6636 | */ | |
6637 | ||
6638 | static tree | |
6639 | c_parser_asm_goto_operands (c_parser *parser) | |
6640 | { | |
6641 | tree list = NULL_TREE; | |
6642 | while (true) | |
6643 | { | |
6644 | tree name, label; | |
6645 | ||
6646 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
6647 | { | |
6648 | c_token *tok = c_parser_peek_token (parser); | |
6649 | name = tok->value; | |
6650 | label = lookup_label_for_goto (tok->location, name); | |
6651 | c_parser_consume_token (parser); | |
6652 | TREE_USED (label) = 1; | |
6653 | } | |
6654 | else | |
6655 | { | |
6656 | c_parser_error (parser, "expected identifier"); | |
6657 | return NULL_TREE; | |
6658 | } | |
6659 | ||
6660 | name = build_string (IDENTIFIER_LENGTH (name), | |
6661 | IDENTIFIER_POINTER (name)); | |
6662 | list = tree_cons (name, label, list); | |
6663 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
6664 | c_parser_consume_token (parser); | |
6665 | else | |
6666 | return nreverse (list); | |
6667 | } | |
6668 | } | |
6669 | ||
27bf414c | 6670 | /* Parse an expression other than a compound expression; that is, an |
31dc71a8 MP |
6671 | assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If |
6672 | AFTER is not NULL then it is an Objective-C message expression which | |
6673 | is the primary-expression starting the expression as an initializer. | |
27bf414c JM |
6674 | |
6675 | assignment-expression: | |
6676 | conditional-expression | |
6677 | unary-expression assignment-operator assignment-expression | |
6678 | ||
6679 | assignment-operator: one of | |
6680 | = *= /= %= += -= <<= >>= &= ^= |= | |
6681 | ||
6682 | In GNU C we accept any conditional expression on the LHS and | |
6683 | diagnose the invalid lvalue rather than producing a syntax | |
6684 | error. */ | |
6685 | ||
6686 | static struct c_expr | |
acf0174b JJ |
6687 | c_parser_expr_no_commas (c_parser *parser, struct c_expr *after, |
6688 | tree omp_atomic_lhs) | |
27bf414c JM |
6689 | { |
6690 | struct c_expr lhs, rhs, ret; | |
6691 | enum tree_code code; | |
c2255bc4 | 6692 | location_t op_location, exp_location; |
27bf414c | 6693 | gcc_assert (!after || c_dialect_objc ()); |
acf0174b | 6694 | lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs); |
c9f9eb5d | 6695 | op_location = c_parser_peek_token (parser)->location; |
27bf414c JM |
6696 | switch (c_parser_peek_token (parser)->type) |
6697 | { | |
6698 | case CPP_EQ: | |
6699 | code = NOP_EXPR; | |
6700 | break; | |
6701 | case CPP_MULT_EQ: | |
6702 | code = MULT_EXPR; | |
6703 | break; | |
6704 | case CPP_DIV_EQ: | |
6705 | code = TRUNC_DIV_EXPR; | |
6706 | break; | |
6707 | case CPP_MOD_EQ: | |
6708 | code = TRUNC_MOD_EXPR; | |
6709 | break; | |
6710 | case CPP_PLUS_EQ: | |
6711 | code = PLUS_EXPR; | |
6712 | break; | |
6713 | case CPP_MINUS_EQ: | |
6714 | code = MINUS_EXPR; | |
6715 | break; | |
6716 | case CPP_LSHIFT_EQ: | |
6717 | code = LSHIFT_EXPR; | |
6718 | break; | |
6719 | case CPP_RSHIFT_EQ: | |
6720 | code = RSHIFT_EXPR; | |
6721 | break; | |
6722 | case CPP_AND_EQ: | |
6723 | code = BIT_AND_EXPR; | |
6724 | break; | |
6725 | case CPP_XOR_EQ: | |
6726 | code = BIT_XOR_EXPR; | |
6727 | break; | |
6728 | case CPP_OR_EQ: | |
6729 | code = BIT_IOR_EXPR; | |
6730 | break; | |
6731 | default: | |
6732 | return lhs; | |
6733 | } | |
6734 | c_parser_consume_token (parser); | |
c2255bc4 | 6735 | exp_location = c_parser_peek_token (parser)->location; |
27bf414c | 6736 | rhs = c_parser_expr_no_commas (parser, NULL); |
267bac10 | 6737 | rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true); |
36536d79 | 6738 | |
25c22937 BI |
6739 | ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type, |
6740 | code, exp_location, rhs.value, | |
6741 | rhs.original_type); | |
ebedc9a3 | 6742 | set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ()); |
27bf414c JM |
6743 | if (code == NOP_EXPR) |
6744 | ret.original_code = MODIFY_EXPR; | |
6745 | else | |
6746 | { | |
6747 | TREE_NO_WARNING (ret.value) = 1; | |
6748 | ret.original_code = ERROR_MARK; | |
6749 | } | |
6866c6e8 | 6750 | ret.original_type = NULL; |
27bf414c JM |
6751 | return ret; |
6752 | } | |
6753 | ||
31dc71a8 MP |
6754 | /* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If |
6755 | AFTER is not NULL then it is an Objective-C message expression which is | |
27bf414c JM |
6756 | the primary-expression starting the expression as an initializer. |
6757 | ||
6758 | conditional-expression: | |
6759 | logical-OR-expression | |
6760 | logical-OR-expression ? expression : conditional-expression | |
6761 | ||
6762 | GNU extensions: | |
6763 | ||
6764 | conditional-expression: | |
6765 | logical-OR-expression ? : conditional-expression | |
6766 | */ | |
6767 | ||
6768 | static struct c_expr | |
acf0174b JJ |
6769 | c_parser_conditional_expression (c_parser *parser, struct c_expr *after, |
6770 | tree omp_atomic_lhs) | |
27bf414c JM |
6771 | { |
6772 | struct c_expr cond, exp1, exp2, ret; | |
a32c8316 | 6773 | location_t start, cond_loc, colon_loc; |
ba47d38d | 6774 | |
27bf414c | 6775 | gcc_assert (!after || c_dialect_objc ()); |
ba47d38d | 6776 | |
acf0174b | 6777 | cond = c_parser_binary_expression (parser, after, omp_atomic_lhs); |
ba47d38d | 6778 | |
27bf414c JM |
6779 | if (c_parser_next_token_is_not (parser, CPP_QUERY)) |
6780 | return cond; | |
ebedc9a3 DM |
6781 | if (cond.value != error_mark_node) |
6782 | start = cond.get_start (); | |
6783 | else | |
6784 | start = UNKNOWN_LOCATION; | |
c2255bc4 | 6785 | cond_loc = c_parser_peek_token (parser)->location; |
267bac10 | 6786 | cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true); |
27bf414c JM |
6787 | c_parser_consume_token (parser); |
6788 | if (c_parser_next_token_is (parser, CPP_COLON)) | |
6789 | { | |
8ce94e44 | 6790 | tree eptype = NULL_TREE; |
d166d4c3 | 6791 | |
a32c8316 | 6792 | location_t middle_loc = c_parser_peek_token (parser)->location; |
54dcdb88 | 6793 | pedwarn (middle_loc, OPT_Wpedantic, |
509c9d60 | 6794 | "ISO C forbids omitting the middle term of a ?: expression"); |
8ce94e44 JM |
6795 | if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR) |
6796 | { | |
6797 | eptype = TREE_TYPE (cond.value); | |
6798 | cond.value = TREE_OPERAND (cond.value, 0); | |
6799 | } | |
54dcdb88 BE |
6800 | tree e = cond.value; |
6801 | while (TREE_CODE (e) == COMPOUND_EXPR) | |
6802 | e = TREE_OPERAND (e, 1); | |
6803 | warn_for_omitted_condop (middle_loc, e); | |
27bf414c | 6804 | /* Make sure first operand is calculated only once. */ |
b2fa0a8b | 6805 | exp1.value = save_expr (default_conversion (cond.value)); |
8ce94e44 JM |
6806 | if (eptype) |
6807 | exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value); | |
6866c6e8 | 6808 | exp1.original_type = NULL; |
a32c8316 | 6809 | exp1.src_range = cond.src_range; |
ba47d38d | 6810 | cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value); |
7d882b83 | 6811 | c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node; |
27bf414c JM |
6812 | } |
6813 | else | |
6814 | { | |
6815 | cond.value | |
85498824 | 6816 | = c_objc_common_truthvalue_conversion |
ba47d38d | 6817 | (cond_loc, default_conversion (cond.value)); |
7d882b83 | 6818 | c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node; |
46bdb9cf | 6819 | exp1 = c_parser_expression_conv (parser); |
ebfbbdc5 | 6820 | mark_exp_read (exp1.value); |
7d882b83 ILT |
6821 | c_inhibit_evaluation_warnings += |
6822 | ((cond.value == truthvalue_true_node) | |
6823 | - (cond.value == truthvalue_false_node)); | |
27bf414c | 6824 | } |
744aa42f ILT |
6825 | |
6826 | colon_loc = c_parser_peek_token (parser)->location; | |
27bf414c JM |
6827 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
6828 | { | |
7d882b83 | 6829 | c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; |
27bf414c JM |
6830 | ret.value = error_mark_node; |
6831 | ret.original_code = ERROR_MARK; | |
6866c6e8 | 6832 | ret.original_type = NULL; |
27bf414c JM |
6833 | return ret; |
6834 | } | |
c2255bc4 AH |
6835 | { |
6836 | location_t exp2_loc = c_parser_peek_token (parser)->location; | |
acf0174b | 6837 | exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE); |
267bac10 | 6838 | exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true); |
c2255bc4 | 6839 | } |
7d882b83 | 6840 | c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; |
a32c8316 MP |
6841 | location_t loc1 = make_location (exp1.get_start (), exp1.src_range); |
6842 | location_t loc2 = make_location (exp2.get_start (), exp2.src_range); | |
744aa42f | 6843 | ret.value = build_conditional_expr (colon_loc, cond.value, |
928c19bb | 6844 | cond.original_code == C_MAYBE_CONST_EXPR, |
a32c8316 MP |
6845 | exp1.value, exp1.original_type, loc1, |
6846 | exp2.value, exp2.original_type, loc2); | |
27bf414c | 6847 | ret.original_code = ERROR_MARK; |
6866c6e8 ILT |
6848 | if (exp1.value == error_mark_node || exp2.value == error_mark_node) |
6849 | ret.original_type = NULL; | |
6850 | else | |
6851 | { | |
6852 | tree t1, t2; | |
6853 | ||
6854 | /* If both sides are enum type, the default conversion will have | |
6855 | made the type of the result be an integer type. We want to | |
6856 | remember the enum types we started with. */ | |
6857 | t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value); | |
6858 | t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value); | |
6859 | ret.original_type = ((t1 != error_mark_node | |
6860 | && t2 != error_mark_node | |
6861 | && (TYPE_MAIN_VARIANT (t1) | |
6862 | == TYPE_MAIN_VARIANT (t2))) | |
6863 | ? t1 | |
6864 | : NULL); | |
6865 | } | |
ebedc9a3 | 6866 | set_c_expr_source_range (&ret, start, exp2.get_finish ()); |
27bf414c JM |
6867 | return ret; |
6868 | } | |
6869 | ||
6870 | /* Parse a binary expression; that is, a logical-OR-expression (C90 | |
31dc71a8 MP |
6871 | 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not |
6872 | NULL then it is an Objective-C message expression which is the | |
6873 | primary-expression starting the expression as an initializer. | |
acf0174b JJ |
6874 | |
6875 | OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic, | |
6876 | when it should be the unfolded lhs. In a valid OpenMP source, | |
6877 | one of the operands of the toplevel binary expression must be equal | |
6878 | to it. In that case, just return a build2 created binary operation | |
6879 | rather than result of parser_build_binary_op. | |
27bf414c JM |
6880 | |
6881 | multiplicative-expression: | |
6882 | cast-expression | |
6883 | multiplicative-expression * cast-expression | |
6884 | multiplicative-expression / cast-expression | |
6885 | multiplicative-expression % cast-expression | |
6886 | ||
6887 | additive-expression: | |
6888 | multiplicative-expression | |
6889 | additive-expression + multiplicative-expression | |
6890 | additive-expression - multiplicative-expression | |
6891 | ||
6892 | shift-expression: | |
6893 | additive-expression | |
6894 | shift-expression << additive-expression | |
6895 | shift-expression >> additive-expression | |
6896 | ||
6897 | relational-expression: | |
6898 | shift-expression | |
6899 | relational-expression < shift-expression | |
6900 | relational-expression > shift-expression | |
6901 | relational-expression <= shift-expression | |
6902 | relational-expression >= shift-expression | |
6903 | ||
6904 | equality-expression: | |
6905 | relational-expression | |
6906 | equality-expression == relational-expression | |
6907 | equality-expression != relational-expression | |
6908 | ||
6909 | AND-expression: | |
6910 | equality-expression | |
6911 | AND-expression & equality-expression | |
6912 | ||
6913 | exclusive-OR-expression: | |
6914 | AND-expression | |
6915 | exclusive-OR-expression ^ AND-expression | |
6916 | ||
6917 | inclusive-OR-expression: | |
6918 | exclusive-OR-expression | |
6919 | inclusive-OR-expression | exclusive-OR-expression | |
6920 | ||
6921 | logical-AND-expression: | |
6922 | inclusive-OR-expression | |
6923 | logical-AND-expression && inclusive-OR-expression | |
6924 | ||
6925 | logical-OR-expression: | |
6926 | logical-AND-expression | |
6927 | logical-OR-expression || logical-AND-expression | |
6928 | */ | |
6929 | ||
6930 | static struct c_expr | |
20906c66 | 6931 | c_parser_binary_expression (c_parser *parser, struct c_expr *after, |
acf0174b | 6932 | tree omp_atomic_lhs) |
27bf414c JM |
6933 | { |
6934 | /* A binary expression is parsed using operator-precedence parsing, | |
6935 | with the operands being cast expressions. All the binary | |
6936 | operators are left-associative. Thus a binary expression is of | |
6937 | form: | |
6938 | ||
6939 | E0 op1 E1 op2 E2 ... | |
6940 | ||
6941 | which we represent on a stack. On the stack, the precedence | |
6942 | levels are strictly increasing. When a new operator is | |
6943 | encountered of higher precedence than that at the top of the | |
6944 | stack, it is pushed; its LHS is the top expression, and its RHS | |
6945 | is everything parsed until it is popped. When a new operator is | |
6946 | encountered with precedence less than or equal to that at the top | |
6947 | of the stack, triples E[i-1] op[i] E[i] are popped and replaced | |
6948 | by the result of the operation until the operator at the top of | |
6949 | the stack has lower precedence than the new operator or there is | |
6950 | only one element on the stack; then the top expression is the LHS | |
6951 | of the new operator. In the case of logical AND and OR | |
7d882b83 ILT |
6952 | expressions, we also need to adjust c_inhibit_evaluation_warnings |
6953 | as appropriate when the operators are pushed and popped. */ | |
27bf414c | 6954 | |
27bf414c JM |
6955 | struct { |
6956 | /* The expression at this stack level. */ | |
6957 | struct c_expr expr; | |
6958 | /* The precedence of the operator on its left, PREC_NONE at the | |
6959 | bottom of the stack. */ | |
20906c66 | 6960 | enum c_parser_prec prec; |
27bf414c JM |
6961 | /* The operation on its left. */ |
6962 | enum tree_code op; | |
ca80e52b EB |
6963 | /* The source location of this operation. */ |
6964 | location_t loc; | |
40ffd95f BE |
6965 | /* The sizeof argument if expr.original_code == SIZEOF_EXPR. */ |
6966 | tree sizeof_arg; | |
27bf414c JM |
6967 | } stack[NUM_PRECS]; |
6968 | int sp; | |
ba47d38d | 6969 | /* Location of the binary operator. */ |
1f6d0c60 | 6970 | location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
27bf414c JM |
6971 | #define POP \ |
6972 | do { \ | |
6973 | switch (stack[sp].op) \ | |
6974 | { \ | |
6975 | case TRUTH_ANDIF_EXPR: \ | |
7d882b83 ILT |
6976 | c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ |
6977 | == truthvalue_false_node); \ | |
27bf414c JM |
6978 | break; \ |
6979 | case TRUTH_ORIF_EXPR: \ | |
7d882b83 ILT |
6980 | c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ |
6981 | == truthvalue_true_node); \ | |
27bf414c | 6982 | break; \ |
40ffd95f BE |
6983 | case TRUNC_DIV_EXPR: \ |
6984 | if (stack[sp - 1].expr.original_code == SIZEOF_EXPR \ | |
6985 | && stack[sp].expr.original_code == SIZEOF_EXPR) \ | |
6986 | { \ | |
6987 | tree type0 = stack[sp - 1].sizeof_arg; \ | |
6988 | tree type1 = stack[sp].sizeof_arg; \ | |
6989 | tree first_arg = type0; \ | |
6990 | if (!TYPE_P (type0)) \ | |
6991 | type0 = TREE_TYPE (type0); \ | |
6992 | if (!TYPE_P (type1)) \ | |
6993 | type1 = TREE_TYPE (type1); \ | |
6994 | if (POINTER_TYPE_P (type0) \ | |
6995 | && comptypes (TREE_TYPE (type0), type1) \ | |
6996 | && !(TREE_CODE (first_arg) == PARM_DECL \ | |
6997 | && C_ARRAY_PARAMETER (first_arg) \ | |
6998 | && warn_sizeof_array_argument)) \ | |
6999 | if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \ | |
7000 | "division %<sizeof (%T) / sizeof (%T)%> does " \ | |
7001 | "not compute the number of array elements", \ | |
7002 | type0, type1)) \ | |
7003 | if (DECL_P (first_arg)) \ | |
7004 | inform (DECL_SOURCE_LOCATION (first_arg), \ | |
7005 | "first %<sizeof%> operand was declared here"); \ | |
7006 | } \ | |
7007 | break; \ | |
27bf414c JM |
7008 | default: \ |
7009 | break; \ | |
7010 | } \ | |
f2a71bbc | 7011 | stack[sp - 1].expr \ |
267bac10 JM |
7012 | = convert_lvalue_to_rvalue (stack[sp - 1].loc, \ |
7013 | stack[sp - 1].expr, true, true); \ | |
f2a71bbc | 7014 | stack[sp].expr \ |
267bac10 JM |
7015 | = convert_lvalue_to_rvalue (stack[sp].loc, \ |
7016 | stack[sp].expr, true, true); \ | |
acf0174b JJ |
7017 | if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \ |
7018 | && c_parser_peek_token (parser)->type == CPP_SEMICOLON \ | |
7019 | && ((1 << stack[sp].prec) \ | |
fa01ffcc JJ |
7020 | & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \ |
7021 | | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \ | |
acf0174b JJ |
7022 | && stack[sp].op != TRUNC_MOD_EXPR \ |
7023 | && stack[0].expr.value != error_mark_node \ | |
7024 | && stack[1].expr.value != error_mark_node \ | |
7025 | && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \ | |
7026 | || c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \ | |
7027 | stack[0].expr.value \ | |
7028 | = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ | |
7029 | stack[0].expr.value, stack[1].expr.value); \ | |
7030 | else \ | |
7031 | stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ | |
7032 | stack[sp].op, \ | |
7033 | stack[sp - 1].expr, \ | |
7034 | stack[sp].expr); \ | |
27bf414c JM |
7035 | sp--; \ |
7036 | } while (0) | |
7037 | gcc_assert (!after || c_dialect_objc ()); | |
ca80e52b | 7038 | stack[0].loc = c_parser_peek_token (parser)->location; |
27bf414c | 7039 | stack[0].expr = c_parser_cast_expression (parser, after); |
acf0174b | 7040 | stack[0].prec = PREC_NONE; |
40ffd95f | 7041 | stack[0].sizeof_arg = c_last_sizeof_arg; |
27bf414c JM |
7042 | sp = 0; |
7043 | while (true) | |
7044 | { | |
20906c66 | 7045 | enum c_parser_prec oprec; |
27bf414c | 7046 | enum tree_code ocode; |
ebedc9a3 | 7047 | source_range src_range; |
27bf414c JM |
7048 | if (parser->error) |
7049 | goto out; | |
7050 | switch (c_parser_peek_token (parser)->type) | |
7051 | { | |
7052 | case CPP_MULT: | |
7053 | oprec = PREC_MULT; | |
7054 | ocode = MULT_EXPR; | |
7055 | break; | |
7056 | case CPP_DIV: | |
7057 | oprec = PREC_MULT; | |
7058 | ocode = TRUNC_DIV_EXPR; | |
7059 | break; | |
7060 | case CPP_MOD: | |
7061 | oprec = PREC_MULT; | |
7062 | ocode = TRUNC_MOD_EXPR; | |
7063 | break; | |
7064 | case CPP_PLUS: | |
7065 | oprec = PREC_ADD; | |
7066 | ocode = PLUS_EXPR; | |
7067 | break; | |
7068 | case CPP_MINUS: | |
7069 | oprec = PREC_ADD; | |
7070 | ocode = MINUS_EXPR; | |
7071 | break; | |
7072 | case CPP_LSHIFT: | |
7073 | oprec = PREC_SHIFT; | |
7074 | ocode = LSHIFT_EXPR; | |
7075 | break; | |
7076 | case CPP_RSHIFT: | |
7077 | oprec = PREC_SHIFT; | |
7078 | ocode = RSHIFT_EXPR; | |
7079 | break; | |
7080 | case CPP_LESS: | |
7081 | oprec = PREC_REL; | |
7082 | ocode = LT_EXPR; | |
7083 | break; | |
7084 | case CPP_GREATER: | |
7085 | oprec = PREC_REL; | |
7086 | ocode = GT_EXPR; | |
7087 | break; | |
7088 | case CPP_LESS_EQ: | |
7089 | oprec = PREC_REL; | |
7090 | ocode = LE_EXPR; | |
7091 | break; | |
7092 | case CPP_GREATER_EQ: | |
7093 | oprec = PREC_REL; | |
7094 | ocode = GE_EXPR; | |
7095 | break; | |
7096 | case CPP_EQ_EQ: | |
7097 | oprec = PREC_EQ; | |
7098 | ocode = EQ_EXPR; | |
7099 | break; | |
7100 | case CPP_NOT_EQ: | |
7101 | oprec = PREC_EQ; | |
7102 | ocode = NE_EXPR; | |
7103 | break; | |
7104 | case CPP_AND: | |
7105 | oprec = PREC_BITAND; | |
7106 | ocode = BIT_AND_EXPR; | |
7107 | break; | |
7108 | case CPP_XOR: | |
7109 | oprec = PREC_BITXOR; | |
7110 | ocode = BIT_XOR_EXPR; | |
7111 | break; | |
7112 | case CPP_OR: | |
7113 | oprec = PREC_BITOR; | |
7114 | ocode = BIT_IOR_EXPR; | |
7115 | break; | |
7116 | case CPP_AND_AND: | |
7117 | oprec = PREC_LOGAND; | |
7118 | ocode = TRUTH_ANDIF_EXPR; | |
7119 | break; | |
7120 | case CPP_OR_OR: | |
7121 | oprec = PREC_LOGOR; | |
7122 | ocode = TRUTH_ORIF_EXPR; | |
7123 | break; | |
7124 | default: | |
7125 | /* Not a binary operator, so end of the binary | |
7126 | expression. */ | |
7127 | goto out; | |
7128 | } | |
ba47d38d | 7129 | binary_loc = c_parser_peek_token (parser)->location; |
27bf414c | 7130 | while (oprec <= stack[sp].prec) |
acf0174b | 7131 | POP; |
20906c66 | 7132 | c_parser_consume_token (parser); |
27bf414c JM |
7133 | switch (ocode) |
7134 | { | |
7135 | case TRUTH_ANDIF_EXPR: | |
ebedc9a3 | 7136 | src_range = stack[sp].expr.src_range; |
f2a71bbc | 7137 | stack[sp].expr |
267bac10 JM |
7138 | = convert_lvalue_to_rvalue (stack[sp].loc, |
7139 | stack[sp].expr, true, true); | |
85498824 | 7140 | stack[sp].expr.value = c_objc_common_truthvalue_conversion |
ca80e52b | 7141 | (stack[sp].loc, default_conversion (stack[sp].expr.value)); |
7d882b83 ILT |
7142 | c_inhibit_evaluation_warnings += (stack[sp].expr.value |
7143 | == truthvalue_false_node); | |
ebedc9a3 | 7144 | set_c_expr_source_range (&stack[sp].expr, src_range); |
27bf414c JM |
7145 | break; |
7146 | case TRUTH_ORIF_EXPR: | |
ebedc9a3 | 7147 | src_range = stack[sp].expr.src_range; |
f2a71bbc | 7148 | stack[sp].expr |
267bac10 JM |
7149 | = convert_lvalue_to_rvalue (stack[sp].loc, |
7150 | stack[sp].expr, true, true); | |
85498824 | 7151 | stack[sp].expr.value = c_objc_common_truthvalue_conversion |
ca80e52b | 7152 | (stack[sp].loc, default_conversion (stack[sp].expr.value)); |
7d882b83 ILT |
7153 | c_inhibit_evaluation_warnings += (stack[sp].expr.value |
7154 | == truthvalue_true_node); | |
ebedc9a3 | 7155 | set_c_expr_source_range (&stack[sp].expr, src_range); |
27bf414c JM |
7156 | break; |
7157 | default: | |
7158 | break; | |
7159 | } | |
7160 | sp++; | |
ca80e52b | 7161 | stack[sp].loc = binary_loc; |
27bf414c JM |
7162 | stack[sp].expr = c_parser_cast_expression (parser, NULL); |
7163 | stack[sp].prec = oprec; | |
7164 | stack[sp].op = ocode; | |
40ffd95f | 7165 | stack[sp].sizeof_arg = c_last_sizeof_arg; |
27bf414c JM |
7166 | } |
7167 | out: | |
7168 | while (sp > 0) | |
7169 | POP; | |
7170 | return stack[0].expr; | |
7171 | #undef POP | |
7172 | } | |
7173 | ||
31dc71a8 MP |
7174 | /* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER |
7175 | is not NULL then it is an Objective-C message expression which is the | |
27bf414c JM |
7176 | primary-expression starting the expression as an initializer. |
7177 | ||
7178 | cast-expression: | |
7179 | unary-expression | |
7180 | ( type-name ) unary-expression | |
7181 | */ | |
7182 | ||
7183 | static struct c_expr | |
7184 | c_parser_cast_expression (c_parser *parser, struct c_expr *after) | |
7185 | { | |
c2255bc4 | 7186 | location_t cast_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
7187 | gcc_assert (!after || c_dialect_objc ()); |
7188 | if (after) | |
c2255bc4 AH |
7189 | return c_parser_postfix_expression_after_primary (parser, |
7190 | cast_loc, *after); | |
27bf414c JM |
7191 | /* If the expression begins with a parenthesized type name, it may |
7192 | be either a cast or a compound literal; we need to see whether | |
7193 | the next character is '{' to tell the difference. If not, it is | |
29ce73cb PB |
7194 | an unary expression. Full detection of unknown typenames here |
7195 | would require a 3-token lookahead. */ | |
27bf414c JM |
7196 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
7197 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) | |
7198 | { | |
7199 | struct c_type_name *type_name; | |
7200 | struct c_expr ret; | |
f2a71bbc | 7201 | struct c_expr expr; |
32129a17 DM |
7202 | matching_parens parens; |
7203 | parens.consume_open (parser); | |
27bf414c | 7204 | type_name = c_parser_type_name (parser); |
32129a17 | 7205 | parens.skip_until_found_close (parser); |
27bf414c JM |
7206 | if (type_name == NULL) |
7207 | { | |
7208 | ret.value = error_mark_node; | |
7209 | ret.original_code = ERROR_MARK; | |
6866c6e8 | 7210 | ret.original_type = NULL; |
27bf414c JM |
7211 | return ret; |
7212 | } | |
33c9159e AH |
7213 | |
7214 | /* Save casted types in the function's used types hash table. */ | |
8d8d1a28 | 7215 | used_types_insert (type_name->specs->type); |
33c9159e | 7216 | |
27bf414c | 7217 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
24b97832 | 7218 | return c_parser_postfix_expression_after_paren_type (parser, type_name, |
c2255bc4 AH |
7219 | cast_loc); |
7220 | { | |
7221 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
7222 | expr = c_parser_cast_expression (parser, NULL); | |
267bac10 | 7223 | expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true); |
c2255bc4 AH |
7224 | } |
7225 | ret.value = c_cast_expr (cast_loc, type_name, expr.value); | |
ebedc9a3 DM |
7226 | if (ret.value && expr.value) |
7227 | set_c_expr_source_range (&ret, cast_loc, expr.get_finish ()); | |
27bf414c | 7228 | ret.original_code = ERROR_MARK; |
6866c6e8 | 7229 | ret.original_type = NULL; |
27bf414c JM |
7230 | return ret; |
7231 | } | |
7232 | else | |
7233 | return c_parser_unary_expression (parser); | |
7234 | } | |
7235 | ||
31dc71a8 | 7236 | /* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3). |
27bf414c JM |
7237 | |
7238 | unary-expression: | |
7239 | postfix-expression | |
7240 | ++ unary-expression | |
7241 | -- unary-expression | |
7242 | unary-operator cast-expression | |
7243 | sizeof unary-expression | |
7244 | sizeof ( type-name ) | |
7245 | ||
7246 | unary-operator: one of | |
7247 | & * + - ~ ! | |
7248 | ||
7249 | GNU extensions: | |
7250 | ||
7251 | unary-expression: | |
7252 | __alignof__ unary-expression | |
7253 | __alignof__ ( type-name ) | |
7254 | && identifier | |
7255 | ||
48b0b196 | 7256 | (C11 permits _Alignof with type names only.) |
d19fa6b5 | 7257 | |
27bf414c JM |
7258 | unary-operator: one of |
7259 | __extension__ __real__ __imag__ | |
7260 | ||
0a35513e AH |
7261 | Transactional Memory: |
7262 | ||
7263 | unary-expression: | |
7264 | transaction-expression | |
7265 | ||
27bf414c JM |
7266 | In addition, the GNU syntax treats ++ and -- as unary operators, so |
7267 | they may be applied to cast expressions with errors for non-lvalues | |
7268 | given later. */ | |
7269 | ||
7270 | static struct c_expr | |
7271 | c_parser_unary_expression (c_parser *parser) | |
7272 | { | |
7273 | int ext; | |
46bdb9cf | 7274 | struct c_expr ret, op; |
c2255bc4 AH |
7275 | location_t op_loc = c_parser_peek_token (parser)->location; |
7276 | location_t exp_loc; | |
ebedc9a3 | 7277 | location_t finish; |
6866c6e8 ILT |
7278 | ret.original_code = ERROR_MARK; |
7279 | ret.original_type = NULL; | |
27bf414c JM |
7280 | switch (c_parser_peek_token (parser)->type) |
7281 | { | |
7282 | case CPP_PLUS_PLUS: | |
7283 | c_parser_consume_token (parser); | |
c2255bc4 | 7284 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7285 | op = c_parser_cast_expression (parser, NULL); |
36536d79 BI |
7286 | |
7287 | /* If there is array notations in op, we expand them. */ | |
b72271b9 | 7288 | if (flag_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF) |
36536d79 BI |
7289 | return fix_array_notation_expr (exp_loc, PREINCREMENT_EXPR, op); |
7290 | else | |
7291 | { | |
7292 | op = default_function_array_read_conversion (exp_loc, op); | |
7293 | return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); | |
7294 | } | |
27bf414c JM |
7295 | case CPP_MINUS_MINUS: |
7296 | c_parser_consume_token (parser); | |
c2255bc4 | 7297 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7298 | op = c_parser_cast_expression (parser, NULL); |
36536d79 BI |
7299 | |
7300 | /* If there is array notations in op, we expand them. */ | |
b72271b9 | 7301 | if (flag_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF) |
36536d79 BI |
7302 | return fix_array_notation_expr (exp_loc, PREDECREMENT_EXPR, op); |
7303 | else | |
7304 | { | |
7305 | op = default_function_array_read_conversion (exp_loc, op); | |
7306 | return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); | |
7307 | } | |
27bf414c JM |
7308 | case CPP_AND: |
7309 | c_parser_consume_token (parser); | |
ebfbbdc5 JJ |
7310 | op = c_parser_cast_expression (parser, NULL); |
7311 | mark_exp_read (op.value); | |
7312 | return parser_build_unary_op (op_loc, ADDR_EXPR, op); | |
27bf414c | 7313 | case CPP_MULT: |
7443cf13 DM |
7314 | { |
7315 | c_parser_consume_token (parser); | |
7316 | exp_loc = c_parser_peek_token (parser)->location; | |
7317 | op = c_parser_cast_expression (parser, NULL); | |
7318 | finish = op.get_finish (); | |
7319 | op = convert_lvalue_to_rvalue (exp_loc, op, true, true); | |
7320 | location_t combined_loc = make_location (op_loc, op_loc, finish); | |
7321 | ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR); | |
7322 | ret.src_range.m_start = op_loc; | |
7323 | ret.src_range.m_finish = finish; | |
7324 | return ret; | |
7325 | } | |
27bf414c | 7326 | case CPP_PLUS: |
8400e75e | 7327 | if (!c_dialect_objc () && !in_system_header_at (input_location)) |
c2255bc4 | 7328 | warning_at (op_loc, |
3ba09659 AH |
7329 | OPT_Wtraditional, |
7330 | "traditional C rejects the unary plus operator"); | |
c7412148 | 7331 | c_parser_consume_token (parser); |
c2255bc4 | 7332 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7333 | op = c_parser_cast_expression (parser, NULL); |
267bac10 | 7334 | op = convert_lvalue_to_rvalue (exp_loc, op, true, true); |
c2255bc4 | 7335 | return parser_build_unary_op (op_loc, CONVERT_EXPR, op); |
27bf414c JM |
7336 | case CPP_MINUS: |
7337 | c_parser_consume_token (parser); | |
c2255bc4 | 7338 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7339 | op = c_parser_cast_expression (parser, NULL); |
267bac10 | 7340 | op = convert_lvalue_to_rvalue (exp_loc, op, true, true); |
c2255bc4 | 7341 | return parser_build_unary_op (op_loc, NEGATE_EXPR, op); |
27bf414c JM |
7342 | case CPP_COMPL: |
7343 | c_parser_consume_token (parser); | |
c2255bc4 | 7344 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7345 | op = c_parser_cast_expression (parser, NULL); |
267bac10 | 7346 | op = convert_lvalue_to_rvalue (exp_loc, op, true, true); |
c2255bc4 | 7347 | return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); |
27bf414c JM |
7348 | case CPP_NOT: |
7349 | c_parser_consume_token (parser); | |
c2255bc4 | 7350 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7351 | op = c_parser_cast_expression (parser, NULL); |
267bac10 | 7352 | op = convert_lvalue_to_rvalue (exp_loc, op, true, true); |
c2255bc4 | 7353 | return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); |
27bf414c JM |
7354 | case CPP_AND_AND: |
7355 | /* Refer to the address of a label as a pointer. */ | |
7356 | c_parser_consume_token (parser); | |
7357 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
7358 | { | |
7359 | ret.value = finish_label_address_expr | |
c2255bc4 | 7360 | (c_parser_peek_token (parser)->value, op_loc); |
bef08b71 DM |
7361 | set_c_expr_source_range (&ret, op_loc, |
7362 | c_parser_peek_token (parser)->get_finish ()); | |
27bf414c | 7363 | c_parser_consume_token (parser); |
27bf414c JM |
7364 | } |
7365 | else | |
7366 | { | |
7367 | c_parser_error (parser, "expected identifier"); | |
f7b6353a | 7368 | ret.set_error (); |
27bf414c | 7369 | } |
f7b6353a | 7370 | return ret; |
27bf414c JM |
7371 | case CPP_KEYWORD: |
7372 | switch (c_parser_peek_token (parser)->keyword) | |
7373 | { | |
7374 | case RID_SIZEOF: | |
7375 | return c_parser_sizeof_expression (parser); | |
7376 | case RID_ALIGNOF: | |
7377 | return c_parser_alignof_expression (parser); | |
7378 | case RID_EXTENSION: | |
7379 | c_parser_consume_token (parser); | |
7380 | ext = disable_extension_diagnostics (); | |
7381 | ret = c_parser_cast_expression (parser, NULL); | |
7382 | restore_extension_diagnostics (ext); | |
7383 | return ret; | |
7384 | case RID_REALPART: | |
7385 | c_parser_consume_token (parser); | |
c2255bc4 | 7386 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7387 | op = c_parser_cast_expression (parser, NULL); |
c2255bc4 AH |
7388 | op = default_function_array_conversion (exp_loc, op); |
7389 | return parser_build_unary_op (op_loc, REALPART_EXPR, op); | |
27bf414c JM |
7390 | case RID_IMAGPART: |
7391 | c_parser_consume_token (parser); | |
c2255bc4 | 7392 | exp_loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 7393 | op = c_parser_cast_expression (parser, NULL); |
c2255bc4 AH |
7394 | op = default_function_array_conversion (exp_loc, op); |
7395 | return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); | |
0a35513e AH |
7396 | case RID_TRANSACTION_ATOMIC: |
7397 | case RID_TRANSACTION_RELAXED: | |
7398 | return c_parser_transaction_expression (parser, | |
7399 | c_parser_peek_token (parser)->keyword); | |
27bf414c JM |
7400 | default: |
7401 | return c_parser_postfix_expression (parser); | |
7402 | } | |
7403 | default: | |
7404 | return c_parser_postfix_expression (parser); | |
7405 | } | |
7406 | } | |
7407 | ||
7408 | /* Parse a sizeof expression. */ | |
7409 | ||
7410 | static struct c_expr | |
7411 | c_parser_sizeof_expression (c_parser *parser) | |
7412 | { | |
7413 | struct c_expr expr; | |
ebedc9a3 | 7414 | struct c_expr result; |
c7412148 | 7415 | location_t expr_loc; |
27bf414c | 7416 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF)); |
ebedc9a3 DM |
7417 | |
7418 | location_t start; | |
7419 | location_t finish = UNKNOWN_LOCATION; | |
7420 | ||
7421 | start = c_parser_peek_token (parser)->location; | |
7422 | ||
27bf414c | 7423 | c_parser_consume_token (parser); |
7d882b83 | 7424 | c_inhibit_evaluation_warnings++; |
27bf414c JM |
7425 | in_sizeof++; |
7426 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) | |
7427 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) | |
7428 | { | |
7429 | /* Either sizeof ( type-name ) or sizeof unary-expression | |
7430 | starting with a compound literal. */ | |
7431 | struct c_type_name *type_name; | |
32129a17 DM |
7432 | matching_parens parens; |
7433 | parens.consume_open (parser); | |
c7412148 | 7434 | expr_loc = c_parser_peek_token (parser)->location; |
27bf414c | 7435 | type_name = c_parser_type_name (parser); |
32129a17 | 7436 | parens.skip_until_found_close (parser); |
ebedc9a3 | 7437 | finish = parser->tokens_buf[0].location; |
27bf414c JM |
7438 | if (type_name == NULL) |
7439 | { | |
7440 | struct c_expr ret; | |
7d882b83 | 7441 | c_inhibit_evaluation_warnings--; |
27bf414c JM |
7442 | in_sizeof--; |
7443 | ret.value = error_mark_node; | |
7444 | ret.original_code = ERROR_MARK; | |
6866c6e8 | 7445 | ret.original_type = NULL; |
27bf414c JM |
7446 | return ret; |
7447 | } | |
7448 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
7449 | { | |
4bd2511b JL |
7450 | expr = c_parser_postfix_expression_after_paren_type (parser, |
7451 | type_name, | |
7452 | expr_loc); | |
ebedc9a3 | 7453 | finish = expr.get_finish (); |
4bd2511b | 7454 | goto sizeof_expr; |
27bf414c | 7455 | } |
4bd2511b JL |
7456 | /* sizeof ( type-name ). */ |
7457 | c_inhibit_evaluation_warnings--; | |
7458 | in_sizeof--; | |
ebedc9a3 | 7459 | result = c_expr_sizeof_type (expr_loc, type_name); |
27bf414c JM |
7460 | } |
7461 | else | |
7462 | { | |
c7412148 | 7463 | expr_loc = c_parser_peek_token (parser)->location; |
27bf414c | 7464 | expr = c_parser_unary_expression (parser); |
ebedc9a3 | 7465 | finish = expr.get_finish (); |
4bd2511b JL |
7466 | sizeof_expr: |
7467 | c_inhibit_evaluation_warnings--; | |
7468 | in_sizeof--; | |
7469 | mark_exp_read (expr.value); | |
7470 | if (TREE_CODE (expr.value) == COMPONENT_REF | |
7471 | && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) | |
7472 | error_at (expr_loc, "%<sizeof%> applied to a bit-field"); | |
ebedc9a3 | 7473 | result = c_expr_sizeof_expr (expr_loc, expr); |
27bf414c | 7474 | } |
ebedc9a3 DM |
7475 | if (finish != UNKNOWN_LOCATION) |
7476 | set_c_expr_source_range (&result, start, finish); | |
7477 | return result; | |
27bf414c JM |
7478 | } |
7479 | ||
7480 | /* Parse an alignof expression. */ | |
7481 | ||
7482 | static struct c_expr | |
7483 | c_parser_alignof_expression (c_parser *parser) | |
7484 | { | |
7485 | struct c_expr expr; | |
a1b93f8d DM |
7486 | location_t start_loc = c_parser_peek_token (parser)->location; |
7487 | location_t end_loc; | |
d19fa6b5 | 7488 | tree alignof_spelling = c_parser_peek_token (parser)->value; |
27bf414c | 7489 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF)); |
296674db JM |
7490 | bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling), |
7491 | "_Alignof") == 0; | |
d19fa6b5 | 7492 | /* A diagnostic is not required for the use of this identifier in |
48b0b196 | 7493 | the implementation namespace; only diagnose it for the C11 |
d19fa6b5 | 7494 | spelling because of existing code using the other spellings. */ |
35aff4fb | 7495 | if (is_c11_alignof) |
d19fa6b5 JM |
7496 | { |
7497 | if (flag_isoc99) | |
a1b93f8d | 7498 | pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE", |
35aff4fb | 7499 | alignof_spelling); |
d19fa6b5 | 7500 | else |
a1b93f8d | 7501 | pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE", |
35aff4fb | 7502 | alignof_spelling); |
d19fa6b5 | 7503 | } |
27bf414c | 7504 | c_parser_consume_token (parser); |
7d882b83 | 7505 | c_inhibit_evaluation_warnings++; |
27bf414c JM |
7506 | in_alignof++; |
7507 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) | |
7508 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) | |
7509 | { | |
7510 | /* Either __alignof__ ( type-name ) or __alignof__ | |
7511 | unary-expression starting with a compound literal. */ | |
24b97832 | 7512 | location_t loc; |
27bf414c JM |
7513 | struct c_type_name *type_name; |
7514 | struct c_expr ret; | |
32129a17 DM |
7515 | matching_parens parens; |
7516 | parens.consume_open (parser); | |
24b97832 | 7517 | loc = c_parser_peek_token (parser)->location; |
27bf414c | 7518 | type_name = c_parser_type_name (parser); |
a1b93f8d | 7519 | end_loc = c_parser_peek_token (parser)->location; |
32129a17 | 7520 | parens.skip_until_found_close (parser); |
27bf414c JM |
7521 | if (type_name == NULL) |
7522 | { | |
7523 | struct c_expr ret; | |
7d882b83 | 7524 | c_inhibit_evaluation_warnings--; |
27bf414c JM |
7525 | in_alignof--; |
7526 | ret.value = error_mark_node; | |
7527 | ret.original_code = ERROR_MARK; | |
6866c6e8 | 7528 | ret.original_type = NULL; |
27bf414c JM |
7529 | return ret; |
7530 | } | |
7531 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
7532 | { | |
7533 | expr = c_parser_postfix_expression_after_paren_type (parser, | |
24b97832 ILT |
7534 | type_name, |
7535 | loc); | |
27bf414c JM |
7536 | goto alignof_expr; |
7537 | } | |
7538 | /* alignof ( type-name ). */ | |
7d882b83 | 7539 | c_inhibit_evaluation_warnings--; |
27bf414c | 7540 | in_alignof--; |
296674db JM |
7541 | ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name, |
7542 | NULL, NULL), | |
7543 | false, is_c11_alignof, 1); | |
27bf414c | 7544 | ret.original_code = ERROR_MARK; |
6866c6e8 | 7545 | ret.original_type = NULL; |
a1b93f8d | 7546 | set_c_expr_source_range (&ret, start_loc, end_loc); |
27bf414c JM |
7547 | return ret; |
7548 | } | |
7549 | else | |
7550 | { | |
7551 | struct c_expr ret; | |
7552 | expr = c_parser_unary_expression (parser); | |
a1b93f8d | 7553 | end_loc = expr.src_range.m_finish; |
27bf414c | 7554 | alignof_expr: |
ebfbbdc5 | 7555 | mark_exp_read (expr.value); |
7d882b83 | 7556 | c_inhibit_evaluation_warnings--; |
27bf414c | 7557 | in_alignof--; |
aa0db437 MS |
7558 | if (is_c11_alignof) |
7559 | pedwarn (start_loc, | |
7560 | OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>", | |
7561 | alignof_spelling); | |
a1b93f8d | 7562 | ret.value = c_alignof_expr (start_loc, expr.value); |
27bf414c | 7563 | ret.original_code = ERROR_MARK; |
6866c6e8 | 7564 | ret.original_type = NULL; |
a1b93f8d | 7565 | set_c_expr_source_range (&ret, start_loc, end_loc); |
27bf414c JM |
7566 | return ret; |
7567 | } | |
7568 | } | |
7569 | ||
f90e8e2e | 7570 | /* Helper function to read arguments of builtins which are interfaces |
2205ed25 | 7571 | for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and |
f90e8e2e AS |
7572 | others. The name of the builtin is passed using BNAME parameter. |
7573 | Function returns true if there were no errors while parsing and | |
46c6e1e2 DM |
7574 | stores the arguments in CEXPR_LIST. If it returns true, |
7575 | *OUT_CLOSE_PAREN_LOC is written to with the location of the closing | |
7576 | parenthesis. */ | |
f90e8e2e AS |
7577 | static bool |
7578 | c_parser_get_builtin_args (c_parser *parser, const char *bname, | |
4e7d7b3d | 7579 | vec<c_expr_t, va_gc> **ret_cexpr_list, |
46c6e1e2 DM |
7580 | bool choose_expr_p, |
7581 | location_t *out_close_paren_loc) | |
f90e8e2e AS |
7582 | { |
7583 | location_t loc = c_parser_peek_token (parser)->location; | |
9771b263 | 7584 | vec<c_expr_t, va_gc> *cexpr_list; |
86785830 | 7585 | c_expr_t expr; |
4e7d7b3d | 7586 | bool saved_force_folding_builtin_constant_p; |
f90e8e2e | 7587 | |
86785830 | 7588 | *ret_cexpr_list = NULL; |
f90e8e2e AS |
7589 | if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) |
7590 | { | |
7591 | error_at (loc, "cannot take address of %qs", bname); | |
7592 | return false; | |
7593 | } | |
7594 | ||
7595 | c_parser_consume_token (parser); | |
7596 | ||
7597 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
7598 | { | |
46c6e1e2 | 7599 | *out_close_paren_loc = c_parser_peek_token (parser)->location; |
f90e8e2e AS |
7600 | c_parser_consume_token (parser); |
7601 | return true; | |
7602 | } | |
86785830 | 7603 | |
4e7d7b3d JJ |
7604 | saved_force_folding_builtin_constant_p |
7605 | = force_folding_builtin_constant_p; | |
7606 | force_folding_builtin_constant_p |= choose_expr_p; | |
86785830 | 7607 | expr = c_parser_expr_no_commas (parser, NULL); |
4e7d7b3d JJ |
7608 | force_folding_builtin_constant_p |
7609 | = saved_force_folding_builtin_constant_p; | |
9771b263 | 7610 | vec_alloc (cexpr_list, 1); |
b581c05c | 7611 | vec_safe_push (cexpr_list, expr); |
86785830 AS |
7612 | while (c_parser_next_token_is (parser, CPP_COMMA)) |
7613 | { | |
7614 | c_parser_consume_token (parser); | |
7615 | expr = c_parser_expr_no_commas (parser, NULL); | |
b581c05c | 7616 | vec_safe_push (cexpr_list, expr); |
86785830 | 7617 | } |
f90e8e2e | 7618 | |
46c6e1e2 | 7619 | *out_close_paren_loc = c_parser_peek_token (parser)->location; |
f90e8e2e AS |
7620 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) |
7621 | return false; | |
7622 | ||
86785830 | 7623 | *ret_cexpr_list = cexpr_list; |
f90e8e2e AS |
7624 | return true; |
7625 | } | |
7626 | ||
433cc7b0 TT |
7627 | /* This represents a single generic-association. */ |
7628 | ||
7629 | struct c_generic_association | |
7630 | { | |
7631 | /* The location of the starting token of the type. */ | |
7632 | location_t type_location; | |
fb48aadc | 7633 | /* The association's type, or NULL_TREE for 'default'. */ |
433cc7b0 TT |
7634 | tree type; |
7635 | /* The association's expression. */ | |
7636 | struct c_expr expression; | |
7637 | }; | |
7638 | ||
7639 | /* Parse a generic-selection. (C11 6.5.1.1). | |
7640 | ||
7641 | generic-selection: | |
7642 | _Generic ( assignment-expression , generic-assoc-list ) | |
7643 | ||
7644 | generic-assoc-list: | |
7645 | generic-association | |
7646 | generic-assoc-list , generic-association | |
7647 | ||
7648 | generic-association: | |
7649 | type-name : assignment-expression | |
7650 | default : assignment-expression | |
7651 | */ | |
7652 | ||
7653 | static struct c_expr | |
7654 | c_parser_generic_selection (c_parser *parser) | |
7655 | { | |
433cc7b0 TT |
7656 | struct c_expr selector, error_expr; |
7657 | tree selector_type; | |
7658 | struct c_generic_association matched_assoc; | |
7659 | bool match_found = false; | |
7660 | location_t generic_loc, selector_loc; | |
7661 | ||
7662 | error_expr.original_code = ERROR_MARK; | |
7663 | error_expr.original_type = NULL; | |
8a40fef3 | 7664 | error_expr.set_error (); |
433cc7b0 TT |
7665 | matched_assoc.type_location = UNKNOWN_LOCATION; |
7666 | matched_assoc.type = NULL_TREE; | |
7667 | matched_assoc.expression = error_expr; | |
7668 | ||
7669 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC)); | |
7670 | generic_loc = c_parser_peek_token (parser)->location; | |
7671 | c_parser_consume_token (parser); | |
35aff4fb MP |
7672 | if (flag_isoc99) |
7673 | pedwarn_c99 (generic_loc, OPT_Wpedantic, | |
433cc7b0 | 7674 | "ISO C99 does not support %<_Generic%>"); |
35aff4fb MP |
7675 | else |
7676 | pedwarn_c99 (generic_loc, OPT_Wpedantic, | |
433cc7b0 | 7677 | "ISO C90 does not support %<_Generic%>"); |
433cc7b0 | 7678 | |
32129a17 DM |
7679 | matching_parens parens; |
7680 | if (!parens.require_open (parser)) | |
433cc7b0 TT |
7681 | return error_expr; |
7682 | ||
7683 | c_inhibit_evaluation_warnings++; | |
7684 | selector_loc = c_parser_peek_token (parser)->location; | |
7685 | selector = c_parser_expr_no_commas (parser, NULL); | |
7686 | selector = default_function_array_conversion (selector_loc, selector); | |
7687 | c_inhibit_evaluation_warnings--; | |
7688 | ||
7689 | if (selector.value == error_mark_node) | |
7690 | { | |
7691 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
7692 | return selector; | |
7693 | } | |
7694 | selector_type = TREE_TYPE (selector.value); | |
7695 | /* In ISO C terms, rvalues (including the controlling expression of | |
7696 | _Generic) do not have qualified types. */ | |
7697 | if (TREE_CODE (selector_type) != ARRAY_TYPE) | |
7698 | selector_type = TYPE_MAIN_VARIANT (selector_type); | |
7699 | /* In ISO C terms, _Noreturn is not part of the type of expressions | |
7700 | such as &abort, but in GCC it is represented internally as a type | |
7701 | qualifier. */ | |
7702 | if (FUNCTION_POINTER_TYPE_P (selector_type) | |
7703 | && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED) | |
7704 | selector_type | |
7705 | = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type))); | |
7706 | ||
7707 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |
7708 | { | |
7709 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
7710 | return error_expr; | |
7711 | } | |
7712 | ||
8c681247 | 7713 | auto_vec<c_generic_association> associations; |
433cc7b0 TT |
7714 | while (1) |
7715 | { | |
7716 | struct c_generic_association assoc, *iter; | |
7717 | unsigned int ix; | |
7718 | c_token *token = c_parser_peek_token (parser); | |
7719 | ||
7720 | assoc.type_location = token->location; | |
7721 | if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT) | |
7722 | { | |
7723 | c_parser_consume_token (parser); | |
7724 | assoc.type = NULL_TREE; | |
7725 | } | |
7726 | else | |
7727 | { | |
7728 | struct c_type_name *type_name; | |
7729 | ||
7730 | type_name = c_parser_type_name (parser); | |
7731 | if (type_name == NULL) | |
7732 | { | |
7733 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8c681247 | 7734 | return error_expr; |
433cc7b0 TT |
7735 | } |
7736 | assoc.type = groktypename (type_name, NULL, NULL); | |
7737 | if (assoc.type == error_mark_node) | |
7738 | { | |
7739 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8c681247 | 7740 | return error_expr; |
433cc7b0 TT |
7741 | } |
7742 | ||
7743 | if (TREE_CODE (assoc.type) == FUNCTION_TYPE) | |
7744 | error_at (assoc.type_location, | |
7745 | "%<_Generic%> association has function type"); | |
7746 | else if (!COMPLETE_TYPE_P (assoc.type)) | |
7747 | error_at (assoc.type_location, | |
7748 | "%<_Generic%> association has incomplete type"); | |
7749 | ||
7750 | if (variably_modified_type_p (assoc.type, NULL_TREE)) | |
7751 | error_at (assoc.type_location, | |
7752 | "%<_Generic%> association has " | |
7753 | "variable length type"); | |
7754 | } | |
7755 | ||
7756 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
7757 | { | |
7758 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8c681247 | 7759 | return error_expr; |
433cc7b0 TT |
7760 | } |
7761 | ||
7762 | assoc.expression = c_parser_expr_no_commas (parser, NULL); | |
7763 | if (assoc.expression.value == error_mark_node) | |
7764 | { | |
7765 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8c681247 | 7766 | return error_expr; |
433cc7b0 TT |
7767 | } |
7768 | ||
7769 | for (ix = 0; associations.iterate (ix, &iter); ++ix) | |
7770 | { | |
7771 | if (assoc.type == NULL_TREE) | |
7772 | { | |
7773 | if (iter->type == NULL_TREE) | |
7774 | { | |
7775 | error_at (assoc.type_location, | |
7776 | "duplicate %<default%> case in %<_Generic%>"); | |
7777 | inform (iter->type_location, "original %<default%> is here"); | |
7778 | } | |
7779 | } | |
7780 | else if (iter->type != NULL_TREE) | |
7781 | { | |
7782 | if (comptypes (assoc.type, iter->type)) | |
7783 | { | |
7784 | error_at (assoc.type_location, | |
7785 | "%<_Generic%> specifies two compatible types"); | |
7786 | inform (iter->type_location, "compatible type is here"); | |
7787 | } | |
7788 | } | |
7789 | } | |
7790 | ||
7791 | if (assoc.type == NULL_TREE) | |
7792 | { | |
7793 | if (!match_found) | |
7794 | { | |
7795 | matched_assoc = assoc; | |
7796 | match_found = true; | |
7797 | } | |
7798 | } | |
7799 | else if (comptypes (assoc.type, selector_type)) | |
7800 | { | |
7801 | if (!match_found || matched_assoc.type == NULL_TREE) | |
7802 | { | |
7803 | matched_assoc = assoc; | |
7804 | match_found = true; | |
7805 | } | |
7806 | else | |
7807 | { | |
7808 | error_at (assoc.type_location, | |
883c8f06 | 7809 | "%<_Generic%> selector matches multiple associations"); |
433cc7b0 TT |
7810 | inform (matched_assoc.type_location, |
7811 | "other match is here"); | |
7812 | } | |
7813 | } | |
7814 | ||
7815 | associations.safe_push (assoc); | |
7816 | ||
7817 | if (c_parser_peek_token (parser)->type != CPP_COMMA) | |
7818 | break; | |
7819 | c_parser_consume_token (parser); | |
7820 | } | |
7821 | ||
32129a17 | 7822 | if (!parens.require_close (parser)) |
433cc7b0 TT |
7823 | { |
7824 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
7825 | return error_expr; | |
7826 | } | |
7827 | ||
7828 | if (!match_found) | |
7829 | { | |
7830 | error_at (selector_loc, "%<_Generic%> selector of type %qT is not " | |
7831 | "compatible with any association", | |
7832 | selector_type); | |
7833 | return error_expr; | |
7834 | } | |
7835 | ||
7836 | return matched_assoc.expression; | |
433cc7b0 | 7837 | } |
f90e8e2e | 7838 | |
3ca0dc60 JM |
7839 | /* Check the validity of a function pointer argument *EXPR (argument |
7840 | position POS) to __builtin_tgmath. Return the number of function | |
7841 | arguments if possibly valid; return 0 having reported an error if | |
7842 | not valid. */ | |
7843 | ||
7844 | static unsigned int | |
7845 | check_tgmath_function (c_expr *expr, unsigned int pos) | |
7846 | { | |
7847 | tree type = TREE_TYPE (expr->value); | |
7848 | if (!FUNCTION_POINTER_TYPE_P (type)) | |
7849 | { | |
7850 | error_at (expr->get_location (), | |
7851 | "argument %u of %<__builtin_tgmath%> is not a function pointer", | |
7852 | pos); | |
7853 | return 0; | |
7854 | } | |
7855 | type = TREE_TYPE (type); | |
7856 | if (!prototype_p (type)) | |
7857 | { | |
7858 | error_at (expr->get_location (), | |
7859 | "argument %u of %<__builtin_tgmath%> is unprototyped", pos); | |
7860 | return 0; | |
7861 | } | |
7862 | if (stdarg_p (type)) | |
7863 | { | |
7864 | error_at (expr->get_location (), | |
7865 | "argument %u of %<__builtin_tgmath%> has variable arguments", | |
7866 | pos); | |
7867 | return 0; | |
7868 | } | |
7869 | unsigned int nargs = 0; | |
7870 | function_args_iterator iter; | |
7871 | tree t; | |
7872 | FOREACH_FUNCTION_ARGS (type, t, iter) | |
7873 | { | |
7874 | if (t == void_type_node) | |
7875 | break; | |
7876 | nargs++; | |
7877 | } | |
7878 | if (nargs == 0) | |
7879 | { | |
7880 | error_at (expr->get_location (), | |
7881 | "argument %u of %<__builtin_tgmath%> has no arguments", pos); | |
7882 | return 0; | |
7883 | } | |
7884 | return nargs; | |
7885 | } | |
7886 | ||
7887 | /* Ways in which a parameter or return value of a type-generic macro | |
7888 | may vary between the different functions the macro may call. */ | |
7889 | enum tgmath_parm_kind | |
7890 | { | |
7891 | tgmath_fixed, tgmath_real, tgmath_complex | |
7892 | }; | |
7893 | ||
31dc71a8 | 7894 | /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2, |
3e7b80d7 MP |
7895 | C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to |
7896 | call c_parser_postfix_expression_after_paren_type on encountering them. | |
27bf414c JM |
7897 | |
7898 | postfix-expression: | |
7899 | primary-expression | |
7900 | postfix-expression [ expression ] | |
7901 | postfix-expression ( argument-expression-list[opt] ) | |
7902 | postfix-expression . identifier | |
7903 | postfix-expression -> identifier | |
7904 | postfix-expression ++ | |
7905 | postfix-expression -- | |
7906 | ( type-name ) { initializer-list } | |
7907 | ( type-name ) { initializer-list , } | |
7908 | ||
7909 | argument-expression-list: | |
7910 | argument-expression | |
7911 | argument-expression-list , argument-expression | |
7912 | ||
7913 | primary-expression: | |
7914 | identifier | |
7915 | constant | |
7916 | string-literal | |
7917 | ( expression ) | |
433cc7b0 | 7918 | generic-selection |
27bf414c JM |
7919 | |
7920 | GNU extensions: | |
7921 | ||
7922 | primary-expression: | |
7923 | __func__ | |
7924 | (treated as a keyword in GNU C) | |
7925 | __FUNCTION__ | |
7926 | __PRETTY_FUNCTION__ | |
7927 | ( compound-statement ) | |
7928 | __builtin_va_arg ( assignment-expression , type-name ) | |
7929 | __builtin_offsetof ( type-name , offsetof-member-designator ) | |
7930 | __builtin_choose_expr ( assignment-expression , | |
7931 | assignment-expression , | |
7932 | assignment-expression ) | |
7933 | __builtin_types_compatible_p ( type-name , type-name ) | |
3ca0dc60 | 7934 | __builtin_tgmath ( expr-list ) |
d4a83c10 | 7935 | __builtin_complex ( assignment-expression , assignment-expression ) |
f90e8e2e | 7936 | __builtin_shuffle ( assignment-expression , assignment-expression ) |
3e7b80d7 | 7937 | __builtin_shuffle ( assignment-expression , |
f90e8e2e AS |
7938 | assignment-expression , |
7939 | assignment-expression, ) | |
27bf414c JM |
7940 | |
7941 | offsetof-member-designator: | |
7942 | identifier | |
7943 | offsetof-member-designator . identifier | |
7944 | offsetof-member-designator [ expression ] | |
7945 | ||
7946 | Objective-C: | |
7947 | ||
7948 | primary-expression: | |
7949 | [ objc-receiver objc-message-args ] | |
7950 | @selector ( objc-selector-arg ) | |
7951 | @protocol ( identifier ) | |
7952 | @encode ( type-name ) | |
7953 | objc-string-literal | |
bede2adc | 7954 | Classname . identifier |
27bf414c JM |
7955 | */ |
7956 | ||
7957 | static struct c_expr | |
7958 | c_parser_postfix_expression (c_parser *parser) | |
7959 | { | |
f90e8e2e | 7960 | struct c_expr expr, e1; |
27bf414c | 7961 | struct c_type_name *t1, *t2; |
c2255bc4 | 7962 | location_t loc = c_parser_peek_token (parser)->location;; |
ebedc9a3 | 7963 | source_range tok_range = c_parser_peek_token (parser)->get_range (); |
6866c6e8 ILT |
7964 | expr.original_code = ERROR_MARK; |
7965 | expr.original_type = NULL; | |
27bf414c JM |
7966 | switch (c_parser_peek_token (parser)->type) |
7967 | { | |
7968 | case CPP_NUMBER: | |
754ccf7c | 7969 | expr.value = c_parser_peek_token (parser)->value; |
ebedc9a3 | 7970 | set_c_expr_source_range (&expr, tok_range); |
754ccf7c JJ |
7971 | loc = c_parser_peek_token (parser)->location; |
7972 | c_parser_consume_token (parser); | |
7973 | if (TREE_CODE (expr.value) == FIXED_CST | |
7974 | && !targetm.fixed_point_supported_p ()) | |
7975 | { | |
7976 | error_at (loc, "fixed-point types not supported for this target"); | |
7977 | expr.value = error_mark_node; | |
7978 | } | |
7979 | break; | |
27bf414c | 7980 | case CPP_CHAR: |
b6baa67d KVH |
7981 | case CPP_CHAR16: |
7982 | case CPP_CHAR32: | |
27bf414c JM |
7983 | case CPP_WCHAR: |
7984 | expr.value = c_parser_peek_token (parser)->value; | |
a9342885 MP |
7985 | /* For the purpose of warning when a pointer is compared with |
7986 | a zero character constant. */ | |
7987 | expr.original_type = char_type_node; | |
ebedc9a3 | 7988 | set_c_expr_source_range (&expr, tok_range); |
27bf414c JM |
7989 | c_parser_consume_token (parser); |
7990 | break; | |
7991 | case CPP_STRING: | |
b6baa67d KVH |
7992 | case CPP_STRING16: |
7993 | case CPP_STRING32: | |
27bf414c | 7994 | case CPP_WSTRING: |
2c6e3f55 | 7995 | case CPP_UTF8STRING: |
27bf414c | 7996 | expr.value = c_parser_peek_token (parser)->value; |
ebedc9a3 | 7997 | set_c_expr_source_range (&expr, tok_range); |
27bf414c JM |
7998 | expr.original_code = STRING_CST; |
7999 | c_parser_consume_token (parser); | |
8000 | break; | |
8001 | case CPP_OBJC_STRING: | |
8002 | gcc_assert (c_dialect_objc ()); | |
8003 | expr.value | |
8004 | = objc_build_string_object (c_parser_peek_token (parser)->value); | |
ebedc9a3 | 8005 | set_c_expr_source_range (&expr, tok_range); |
27bf414c JM |
8006 | c_parser_consume_token (parser); |
8007 | break; | |
8008 | case CPP_NAME: | |
bede2adc | 8009 | switch (c_parser_peek_token (parser)->id_kind) |
27bf414c | 8010 | { |
bede2adc NP |
8011 | case C_ID_ID: |
8012 | { | |
8013 | tree id = c_parser_peek_token (parser)->value; | |
8014 | c_parser_consume_token (parser); | |
8015 | expr.value = build_external_ref (loc, id, | |
8016 | (c_parser_peek_token (parser)->type | |
8017 | == CPP_OPEN_PAREN), | |
8018 | &expr.original_type); | |
ebedc9a3 | 8019 | set_c_expr_source_range (&expr, tok_range); |
bede2adc NP |
8020 | break; |
8021 | } | |
8022 | case C_ID_CLASSNAME: | |
8023 | { | |
8024 | /* Here we parse the Objective-C 2.0 Class.name dot | |
8025 | syntax. */ | |
8026 | tree class_name = c_parser_peek_token (parser)->value; | |
8027 | tree component; | |
8028 | c_parser_consume_token (parser); | |
8029 | gcc_assert (c_dialect_objc ()); | |
8030 | if (!c_parser_require (parser, CPP_DOT, "expected %<.%>")) | |
8031 | { | |
8a40fef3 | 8032 | expr.set_error (); |
bede2adc NP |
8033 | break; |
8034 | } | |
8035 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
8036 | { | |
8037 | c_parser_error (parser, "expected identifier"); | |
8a40fef3 | 8038 | expr.set_error (); |
bede2adc NP |
8039 | break; |
8040 | } | |
cbd03aee DM |
8041 | c_token *component_tok = c_parser_peek_token (parser); |
8042 | component = component_tok->value; | |
8043 | location_t end_loc = component_tok->get_finish (); | |
bede2adc NP |
8044 | c_parser_consume_token (parser); |
8045 | expr.value = objc_build_class_component_ref (class_name, | |
8046 | component); | |
cbd03aee | 8047 | set_c_expr_source_range (&expr, loc, end_loc); |
bede2adc NP |
8048 | break; |
8049 | } | |
8050 | default: | |
27bf414c | 8051 | c_parser_error (parser, "expected expression"); |
8a40fef3 | 8052 | expr.set_error (); |
27bf414c JM |
8053 | break; |
8054 | } | |
27bf414c JM |
8055 | break; |
8056 | case CPP_OPEN_PAREN: | |
8057 | /* A parenthesized expression, statement expression or compound | |
8058 | literal. */ | |
8059 | if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE) | |
8060 | { | |
8061 | /* A statement expression. */ | |
8062 | tree stmt; | |
c2255bc4 | 8063 | location_t brace_loc; |
27bf414c | 8064 | c_parser_consume_token (parser); |
c2255bc4 | 8065 | brace_loc = c_parser_peek_token (parser)->location; |
27bf414c | 8066 | c_parser_consume_token (parser); |
38e01f9e | 8067 | if (!building_stmt_list_p ()) |
27bf414c | 8068 | { |
c2255bc4 | 8069 | error_at (loc, "braced-group within expression allowed " |
3ba09659 | 8070 | "only inside a function"); |
27bf414c JM |
8071 | parser->error = true; |
8072 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); | |
8073 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8a40fef3 | 8074 | expr.set_error (); |
27bf414c JM |
8075 | break; |
8076 | } | |
8077 | stmt = c_begin_stmt_expr (); | |
8078 | c_parser_compound_statement_nostart (parser); | |
bef08b71 | 8079 | location_t close_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
8080 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
8081 | "expected %<)%>"); | |
c1771a20 | 8082 | pedwarn (loc, OPT_Wpedantic, |
509c9d60 | 8083 | "ISO C forbids braced-groups within expressions"); |
c2255bc4 | 8084 | expr.value = c_finish_stmt_expr (brace_loc, stmt); |
bef08b71 | 8085 | set_c_expr_source_range (&expr, loc, close_loc); |
82c3c067 | 8086 | mark_exp_read (expr.value); |
27bf414c | 8087 | } |
27bf414c JM |
8088 | else |
8089 | { | |
8090 | /* A parenthesized expression. */ | |
ebedc9a3 | 8091 | location_t loc_open_paren = c_parser_peek_token (parser)->location; |
27bf414c JM |
8092 | c_parser_consume_token (parser); |
8093 | expr = c_parser_expression (parser); | |
8094 | if (TREE_CODE (expr.value) == MODIFY_EXPR) | |
8095 | TREE_NO_WARNING (expr.value) = 1; | |
40ffd95f BE |
8096 | if (expr.original_code != C_MAYBE_CONST_EXPR |
8097 | && expr.original_code != SIZEOF_EXPR) | |
928c19bb | 8098 | expr.original_code = ERROR_MARK; |
6866c6e8 | 8099 | /* Don't change EXPR.ORIGINAL_TYPE. */ |
ebedc9a3 DM |
8100 | location_t loc_close_paren = c_parser_peek_token (parser)->location; |
8101 | set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren); | |
27bf414c | 8102 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
32129a17 | 8103 | "expected %<)%>", loc_open_paren); |
27bf414c JM |
8104 | } |
8105 | break; | |
8106 | case CPP_KEYWORD: | |
8107 | switch (c_parser_peek_token (parser)->keyword) | |
8108 | { | |
8109 | case RID_FUNCTION_NAME: | |
6dc99c33 MP |
8110 | pedwarn (loc, OPT_Wpedantic, "ISO C does not support " |
8111 | "%<__FUNCTION__%> predefined identifier"); | |
8112 | expr.value = fname_decl (loc, | |
8113 | c_parser_peek_token (parser)->keyword, | |
8114 | c_parser_peek_token (parser)->value); | |
bef08b71 | 8115 | set_c_expr_source_range (&expr, loc, loc); |
6dc99c33 MP |
8116 | c_parser_consume_token (parser); |
8117 | break; | |
27bf414c | 8118 | case RID_PRETTY_FUNCTION_NAME: |
6dc99c33 MP |
8119 | pedwarn (loc, OPT_Wpedantic, "ISO C does not support " |
8120 | "%<__PRETTY_FUNCTION__%> predefined identifier"); | |
8121 | expr.value = fname_decl (loc, | |
8122 | c_parser_peek_token (parser)->keyword, | |
8123 | c_parser_peek_token (parser)->value); | |
bef08b71 | 8124 | set_c_expr_source_range (&expr, loc, loc); |
6dc99c33 MP |
8125 | c_parser_consume_token (parser); |
8126 | break; | |
27bf414c | 8127 | case RID_C99_FUNCTION_NAME: |
6dc99c33 MP |
8128 | pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support " |
8129 | "%<__func__%> predefined identifier"); | |
c2255bc4 | 8130 | expr.value = fname_decl (loc, |
3ba09659 | 8131 | c_parser_peek_token (parser)->keyword, |
27bf414c | 8132 | c_parser_peek_token (parser)->value); |
bef08b71 | 8133 | set_c_expr_source_range (&expr, loc, loc); |
27bf414c JM |
8134 | c_parser_consume_token (parser); |
8135 | break; | |
8136 | case RID_VA_ARG: | |
bef08b71 DM |
8137 | { |
8138 | location_t start_loc = loc; | |
8139 | c_parser_consume_token (parser); | |
32129a17 DM |
8140 | matching_parens parens; |
8141 | if (!parens.require_open (parser)) | |
bef08b71 | 8142 | { |
8a40fef3 | 8143 | expr.set_error (); |
bef08b71 DM |
8144 | break; |
8145 | } | |
8146 | e1 = c_parser_expr_no_commas (parser, NULL); | |
8147 | mark_exp_read (e1.value); | |
8148 | e1.value = c_fully_fold (e1.value, false, NULL); | |
8149 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |
8150 | { | |
8151 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8a40fef3 | 8152 | expr.set_error (); |
bef08b71 DM |
8153 | break; |
8154 | } | |
8155 | loc = c_parser_peek_token (parser)->location; | |
8156 | t1 = c_parser_type_name (parser); | |
8157 | location_t end_loc = c_parser_peek_token (parser)->get_finish (); | |
8158 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
8159 | "expected %<)%>"); | |
8160 | if (t1 == NULL) | |
8161 | { | |
8a40fef3 | 8162 | expr.set_error (); |
bef08b71 DM |
8163 | } |
8164 | else | |
8165 | { | |
8166 | tree type_expr = NULL_TREE; | |
f187980b | 8167 | expr.value = c_build_va_arg (start_loc, e1.value, loc, |
bef08b71 DM |
8168 | groktypename (t1, &type_expr, NULL)); |
8169 | if (type_expr) | |
8170 | { | |
8171 | expr.value = build2 (C_MAYBE_CONST_EXPR, | |
8172 | TREE_TYPE (expr.value), type_expr, | |
8173 | expr.value); | |
8174 | C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; | |
8175 | } | |
8176 | set_c_expr_source_range (&expr, start_loc, end_loc); | |
8177 | } | |
8178 | } | |
27bf414c JM |
8179 | break; |
8180 | case RID_OFFSETOF: | |
27bf414c | 8181 | { |
32129a17 DM |
8182 | c_parser_consume_token (parser); |
8183 | matching_parens parens; | |
8184 | if (!parens.require_open (parser)) | |
8185 | { | |
8186 | expr.set_error (); | |
8187 | break; | |
8188 | } | |
8189 | t1 = c_parser_type_name (parser); | |
8190 | if (t1 == NULL) | |
8191 | parser->error = true; | |
8192 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |
8193 | gcc_assert (parser->error); | |
8194 | if (parser->error) | |
8195 | { | |
8196 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8197 | expr.set_error (); | |
8198 | break; | |
8199 | } | |
928c19bb | 8200 | tree type = groktypename (t1, NULL, NULL); |
27bf414c JM |
8201 | tree offsetof_ref; |
8202 | if (type == error_mark_node) | |
8203 | offsetof_ref = error_mark_node; | |
8204 | else | |
c2255bc4 AH |
8205 | { |
8206 | offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); | |
8207 | SET_EXPR_LOCATION (offsetof_ref, loc); | |
8208 | } | |
27bf414c JM |
8209 | /* Parse the second argument to __builtin_offsetof. We |
8210 | must have one identifier, and beyond that we want to | |
8211 | accept sub structure and sub array references. */ | |
8212 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
8213 | { | |
6ffd47b7 | 8214 | c_token *comp_tok = c_parser_peek_token (parser); |
27bf414c | 8215 | offsetof_ref = build_component_ref |
6ffd47b7 | 8216 | (loc, offsetof_ref, comp_tok->value, comp_tok->location); |
27bf414c JM |
8217 | c_parser_consume_token (parser); |
8218 | while (c_parser_next_token_is (parser, CPP_DOT) | |
8219 | || c_parser_next_token_is (parser, | |
634b5df5 JJ |
8220 | CPP_OPEN_SQUARE) |
8221 | || c_parser_next_token_is (parser, | |
8222 | CPP_DEREF)) | |
27bf414c | 8223 | { |
634b5df5 JJ |
8224 | if (c_parser_next_token_is (parser, CPP_DEREF)) |
8225 | { | |
8226 | loc = c_parser_peek_token (parser)->location; | |
c2255bc4 AH |
8227 | offsetof_ref = build_array_ref (loc, |
8228 | offsetof_ref, | |
8229 | integer_zero_node); | |
634b5df5 JJ |
8230 | goto do_dot; |
8231 | } | |
8232 | else if (c_parser_next_token_is (parser, CPP_DOT)) | |
27bf414c | 8233 | { |
634b5df5 | 8234 | do_dot: |
27bf414c JM |
8235 | c_parser_consume_token (parser); |
8236 | if (c_parser_next_token_is_not (parser, | |
8237 | CPP_NAME)) | |
8238 | { | |
8239 | c_parser_error (parser, "expected identifier"); | |
8240 | break; | |
8241 | } | |
6ffd47b7 | 8242 | c_token *comp_tok = c_parser_peek_token (parser); |
27bf414c | 8243 | offsetof_ref = build_component_ref |
6ffd47b7 DM |
8244 | (loc, offsetof_ref, comp_tok->value, |
8245 | comp_tok->location); | |
27bf414c JM |
8246 | c_parser_consume_token (parser); |
8247 | } | |
8248 | else | |
8249 | { | |
267bac10 | 8250 | struct c_expr ce; |
27bf414c | 8251 | tree idx; |
6a3799eb | 8252 | loc = c_parser_peek_token (parser)->location; |
27bf414c | 8253 | c_parser_consume_token (parser); |
267bac10 JM |
8254 | ce = c_parser_expression (parser); |
8255 | ce = convert_lvalue_to_rvalue (loc, ce, false, false); | |
8256 | idx = ce.value; | |
928c19bb | 8257 | idx = c_fully_fold (idx, false, NULL); |
27bf414c JM |
8258 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, |
8259 | "expected %<]%>"); | |
c2255bc4 | 8260 | offsetof_ref = build_array_ref (loc, offsetof_ref, idx); |
27bf414c JM |
8261 | } |
8262 | } | |
8263 | } | |
8264 | else | |
8265 | c_parser_error (parser, "expected identifier"); | |
bef08b71 | 8266 | location_t end_loc = c_parser_peek_token (parser)->get_finish (); |
27bf414c JM |
8267 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
8268 | "expected %<)%>"); | |
cf9e9959 | 8269 | expr.value = fold_offsetof (offsetof_ref); |
bef08b71 | 8270 | set_c_expr_source_range (&expr, loc, end_loc); |
27bf414c JM |
8271 | } |
8272 | break; | |
8273 | case RID_CHOOSE_EXPR: | |
27bf414c | 8274 | { |
9771b263 | 8275 | vec<c_expr_t, va_gc> *cexpr_list; |
86785830 AS |
8276 | c_expr_t *e1_p, *e2_p, *e3_p; |
8277 | tree c; | |
46c6e1e2 | 8278 | location_t close_paren_loc; |
27bf414c | 8279 | |
f90e8e2e AS |
8280 | c_parser_consume_token (parser); |
8281 | if (!c_parser_get_builtin_args (parser, | |
8282 | "__builtin_choose_expr", | |
46c6e1e2 DM |
8283 | &cexpr_list, true, |
8284 | &close_paren_loc)) | |
f90e8e2e | 8285 | { |
8a40fef3 | 8286 | expr.set_error (); |
f90e8e2e AS |
8287 | break; |
8288 | } | |
8289 | ||
9771b263 | 8290 | if (vec_safe_length (cexpr_list) != 3) |
f90e8e2e AS |
8291 | { |
8292 | error_at (loc, "wrong number of arguments to " | |
8293 | "%<__builtin_choose_expr%>"); | |
8a40fef3 | 8294 | expr.set_error (); |
f90e8e2e AS |
8295 | break; |
8296 | } | |
86785830 | 8297 | |
9771b263 DN |
8298 | e1_p = &(*cexpr_list)[0]; |
8299 | e2_p = &(*cexpr_list)[1]; | |
8300 | e3_p = &(*cexpr_list)[2]; | |
86785830 AS |
8301 | |
8302 | c = e1_p->value; | |
8303 | mark_exp_read (e2_p->value); | |
8304 | mark_exp_read (e3_p->value); | |
928c19bb JM |
8305 | if (TREE_CODE (c) != INTEGER_CST |
8306 | || !INTEGRAL_TYPE_P (TREE_TYPE (c))) | |
3ba09659 AH |
8307 | error_at (loc, |
8308 | "first argument to %<__builtin_choose_expr%> not" | |
8309 | " a constant"); | |
928c19bb | 8310 | constant_expression_warning (c); |
86785830 | 8311 | expr = integer_zerop (c) ? *e3_p : *e2_p; |
46c6e1e2 | 8312 | set_c_expr_source_range (&expr, loc, close_paren_loc); |
f90e8e2e | 8313 | break; |
27bf414c | 8314 | } |
27bf414c | 8315 | case RID_TYPES_COMPATIBLE_P: |
27bf414c | 8316 | { |
32129a17 DM |
8317 | c_parser_consume_token (parser); |
8318 | matching_parens parens; | |
8319 | if (!parens.require_open (parser)) | |
8320 | { | |
8321 | expr.set_error (); | |
8322 | break; | |
8323 | } | |
8324 | t1 = c_parser_type_name (parser); | |
8325 | if (t1 == NULL) | |
8326 | { | |
8327 | expr.set_error (); | |
8328 | break; | |
8329 | } | |
8330 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |
8331 | { | |
8332 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
8333 | expr.set_error (); | |
8334 | break; | |
8335 | } | |
8336 | t2 = c_parser_type_name (parser); | |
8337 | if (t2 == NULL) | |
8338 | { | |
8339 | expr.set_error (); | |
8340 | break; | |
8341 | } | |
4bbf545b | 8342 | location_t close_paren_loc = c_parser_peek_token (parser)->location; |
32129a17 | 8343 | parens.skip_until_found_close (parser); |
27bf414c | 8344 | tree e1, e2; |
9abfe986 AP |
8345 | e1 = groktypename (t1, NULL, NULL); |
8346 | e2 = groktypename (t2, NULL, NULL); | |
8347 | if (e1 == error_mark_node || e2 == error_mark_node) | |
8348 | { | |
8a40fef3 | 8349 | expr.set_error (); |
9abfe986 AP |
8350 | break; |
8351 | } | |
27bf414c | 8352 | |
9abfe986 AP |
8353 | e1 = TYPE_MAIN_VARIANT (e1); |
8354 | e2 = TYPE_MAIN_VARIANT (e2); | |
27bf414c | 8355 | |
9a9d280e AS |
8356 | expr.value |
8357 | = comptypes (e1, e2) ? integer_one_node : integer_zero_node; | |
4bbf545b | 8358 | set_c_expr_source_range (&expr, loc, close_paren_loc); |
27bf414c JM |
8359 | } |
8360 | break; | |
3ca0dc60 JM |
8361 | case RID_BUILTIN_TGMATH: |
8362 | { | |
8363 | vec<c_expr_t, va_gc> *cexpr_list; | |
8364 | location_t close_paren_loc; | |
8365 | ||
8366 | c_parser_consume_token (parser); | |
8367 | if (!c_parser_get_builtin_args (parser, | |
8368 | "__builtin_tgmath", | |
8369 | &cexpr_list, false, | |
8370 | &close_paren_loc)) | |
8371 | { | |
8372 | expr.set_error (); | |
8373 | break; | |
8374 | } | |
8375 | ||
8376 | if (vec_safe_length (cexpr_list) < 3) | |
8377 | { | |
8378 | error_at (loc, "too few arguments to %<__builtin_tgmath%>"); | |
8379 | expr.set_error (); | |
8380 | break; | |
8381 | } | |
8382 | ||
8383 | unsigned int i; | |
8384 | c_expr_t *p; | |
8385 | FOR_EACH_VEC_ELT (*cexpr_list, i, p) | |
8386 | *p = convert_lvalue_to_rvalue (loc, *p, true, true); | |
8387 | unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1); | |
8388 | if (nargs == 0) | |
8389 | { | |
8390 | expr.set_error (); | |
8391 | break; | |
8392 | } | |
8393 | if (vec_safe_length (cexpr_list) < nargs) | |
8394 | { | |
8395 | error_at (loc, "too few arguments to %<__builtin_tgmath%>"); | |
8396 | expr.set_error (); | |
8397 | break; | |
8398 | } | |
8399 | unsigned int num_functions = vec_safe_length (cexpr_list) - nargs; | |
8400 | if (num_functions < 2) | |
8401 | { | |
8402 | error_at (loc, "too few arguments to %<__builtin_tgmath%>"); | |
8403 | expr.set_error (); | |
8404 | break; | |
8405 | } | |
8406 | ||
8407 | /* The first NUM_FUNCTIONS expressions are the function | |
8408 | pointers. The remaining NARGS expressions are the | |
8409 | arguments that are to be passed to one of those | |
8410 | functions, chosen following <tgmath.h> rules. */ | |
8411 | for (unsigned int j = 1; j < num_functions; j++) | |
8412 | { | |
8413 | unsigned int this_nargs | |
8414 | = check_tgmath_function (&(*cexpr_list)[j], j + 1); | |
8415 | if (this_nargs == 0) | |
8416 | { | |
8417 | expr.set_error (); | |
8418 | goto out; | |
8419 | } | |
8420 | if (this_nargs != nargs) | |
8421 | { | |
8422 | error_at ((*cexpr_list)[j].get_location (), | |
8423 | "argument %u of %<__builtin_tgmath%> has " | |
8424 | "wrong number of arguments", j + 1); | |
8425 | expr.set_error (); | |
8426 | goto out; | |
8427 | } | |
8428 | } | |
8429 | ||
8430 | /* The functions all have the same number of arguments. | |
8431 | Determine whether arguments and return types vary in | |
8432 | ways permitted for <tgmath.h> functions. */ | |
8433 | /* The first entry in each of these vectors is for the | |
8434 | return type, subsequent entries for parameter | |
8435 | types. */ | |
8436 | auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1); | |
8437 | auto_vec<tree> parm_first (nargs + 1); | |
8438 | auto_vec<bool> parm_complex (nargs + 1); | |
8439 | auto_vec<bool> parm_varies (nargs + 1); | |
8440 | tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value)); | |
8441 | tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type)); | |
8442 | parm_first.quick_push (first_ret); | |
8443 | parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE); | |
8444 | parm_varies.quick_push (false); | |
8445 | function_args_iterator iter; | |
8446 | tree t; | |
8447 | unsigned int argpos; | |
8448 | FOREACH_FUNCTION_ARGS (first_type, t, iter) | |
8449 | { | |
8450 | if (t == void_type_node) | |
8451 | break; | |
8452 | parm_first.quick_push (TYPE_MAIN_VARIANT (t)); | |
8453 | parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE); | |
8454 | parm_varies.quick_push (false); | |
8455 | } | |
8456 | for (unsigned int j = 1; j < num_functions; j++) | |
8457 | { | |
8458 | tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); | |
8459 | tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type)); | |
8460 | if (ret != parm_first[0]) | |
8461 | { | |
8462 | parm_varies[0] = true; | |
8463 | if (!SCALAR_FLOAT_TYPE_P (parm_first[0]) | |
8464 | && !COMPLEX_FLOAT_TYPE_P (parm_first[0])) | |
8465 | { | |
8466 | error_at ((*cexpr_list)[0].get_location (), | |
8467 | "invalid type-generic return type for " | |
8468 | "argument %u of %<__builtin_tgmath%>", | |
8469 | 1); | |
8470 | expr.set_error (); | |
8471 | goto out; | |
8472 | } | |
8473 | if (!SCALAR_FLOAT_TYPE_P (ret) | |
8474 | && !COMPLEX_FLOAT_TYPE_P (ret)) | |
8475 | { | |
8476 | error_at ((*cexpr_list)[j].get_location (), | |
8477 | "invalid type-generic return type for " | |
8478 | "argument %u of %<__builtin_tgmath%>", | |
8479 | j + 1); | |
8480 | expr.set_error (); | |
8481 | goto out; | |
8482 | } | |
8483 | } | |
8484 | if (TREE_CODE (ret) == COMPLEX_TYPE) | |
8485 | parm_complex[0] = true; | |
8486 | argpos = 1; | |
8487 | FOREACH_FUNCTION_ARGS (type, t, iter) | |
8488 | { | |
8489 | if (t == void_type_node) | |
8490 | break; | |
8491 | t = TYPE_MAIN_VARIANT (t); | |
8492 | if (t != parm_first[argpos]) | |
8493 | { | |
8494 | parm_varies[argpos] = true; | |
8495 | if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos]) | |
8496 | && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos])) | |
8497 | { | |
8498 | error_at ((*cexpr_list)[0].get_location (), | |
8499 | "invalid type-generic type for " | |
8500 | "argument %u of argument %u of " | |
8501 | "%<__builtin_tgmath%>", argpos, 1); | |
8502 | expr.set_error (); | |
8503 | goto out; | |
8504 | } | |
8505 | if (!SCALAR_FLOAT_TYPE_P (t) | |
8506 | && !COMPLEX_FLOAT_TYPE_P (t)) | |
8507 | { | |
8508 | error_at ((*cexpr_list)[j].get_location (), | |
8509 | "invalid type-generic type for " | |
8510 | "argument %u of argument %u of " | |
8511 | "%<__builtin_tgmath%>", argpos, j + 1); | |
8512 | expr.set_error (); | |
8513 | goto out; | |
8514 | } | |
8515 | } | |
8516 | if (TREE_CODE (t) == COMPLEX_TYPE) | |
8517 | parm_complex[argpos] = true; | |
8518 | argpos++; | |
8519 | } | |
8520 | } | |
8521 | enum tgmath_parm_kind max_variation = tgmath_fixed; | |
8522 | for (unsigned int j = 0; j <= nargs; j++) | |
8523 | { | |
8524 | enum tgmath_parm_kind this_kind; | |
8525 | if (parm_varies[j]) | |
8526 | { | |
8527 | if (parm_complex[j]) | |
8528 | max_variation = this_kind = tgmath_complex; | |
8529 | else | |
8530 | { | |
8531 | this_kind = tgmath_real; | |
8532 | if (max_variation != tgmath_complex) | |
8533 | max_variation = tgmath_real; | |
8534 | } | |
8535 | } | |
8536 | else | |
8537 | this_kind = tgmath_fixed; | |
8538 | parm_kind.quick_push (this_kind); | |
8539 | } | |
8540 | if (max_variation == tgmath_fixed) | |
8541 | { | |
8542 | error_at (loc, "function arguments of %<__builtin_tgmath%> " | |
8543 | "all have the same type"); | |
8544 | expr.set_error (); | |
8545 | break; | |
8546 | } | |
8547 | ||
8548 | /* Identify a parameter (not the return type) that varies, | |
8549 | including with complex types if any variation includes | |
8550 | complex types; there must be at least one such | |
8551 | parameter. */ | |
8552 | unsigned int tgarg = 0; | |
8553 | for (unsigned int j = 1; j <= nargs; j++) | |
8554 | if (parm_kind[j] == max_variation) | |
8555 | { | |
8556 | tgarg = j; | |
8557 | break; | |
8558 | } | |
8559 | if (tgarg == 0) | |
8560 | { | |
8561 | error_at (loc, "function arguments of %<__builtin_tgmath%> " | |
8562 | "lack type-generic parameter"); | |
8563 | expr.set_error (); | |
8564 | break; | |
8565 | } | |
8566 | ||
8567 | /* Determine the type of the relevant parameter for each | |
8568 | function. */ | |
8569 | auto_vec<tree> tg_type (num_functions); | |
8570 | for (unsigned int j = 0; j < num_functions; j++) | |
8571 | { | |
8572 | tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); | |
8573 | argpos = 1; | |
8574 | FOREACH_FUNCTION_ARGS (type, t, iter) | |
8575 | { | |
8576 | if (argpos == tgarg) | |
8577 | { | |
8578 | tg_type.quick_push (TYPE_MAIN_VARIANT (t)); | |
8579 | break; | |
8580 | } | |
8581 | argpos++; | |
8582 | } | |
8583 | } | |
8584 | ||
8585 | /* Verify that the corresponding types are different for | |
8586 | all the listed functions. Also determine whether all | |
8587 | the types are complex, whether all the types are | |
8588 | standard or binary, and whether all the types are | |
8589 | decimal. */ | |
8590 | bool all_complex = true; | |
8591 | bool all_binary = true; | |
8592 | bool all_decimal = true; | |
8593 | hash_set<tree> tg_types; | |
8594 | FOR_EACH_VEC_ELT (tg_type, i, t) | |
8595 | { | |
8596 | if (TREE_CODE (t) == COMPLEX_TYPE) | |
8597 | all_decimal = false; | |
8598 | else | |
8599 | { | |
8600 | all_complex = false; | |
8601 | if (DECIMAL_FLOAT_TYPE_P (t)) | |
8602 | all_binary = false; | |
8603 | else | |
8604 | all_decimal = false; | |
8605 | } | |
8606 | if (tg_types.add (t)) | |
8607 | { | |
8608 | error_at ((*cexpr_list)[i].get_location (), | |
8609 | "duplicate type-generic parameter type for " | |
8610 | "function argument %u of %<__builtin_tgmath%>", | |
8611 | i + 1); | |
8612 | expr.set_error (); | |
8613 | goto out; | |
8614 | } | |
8615 | } | |
8616 | ||
8617 | /* Verify that other parameters and the return type whose | |
8618 | types vary have their types varying in the correct | |
8619 | way. */ | |
8620 | for (unsigned int j = 0; j < num_functions; j++) | |
8621 | { | |
8622 | tree exp_type = tg_type[j]; | |
8623 | tree exp_real_type = exp_type; | |
8624 | if (TREE_CODE (exp_type) == COMPLEX_TYPE) | |
8625 | exp_real_type = TREE_TYPE (exp_type); | |
8626 | tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); | |
8627 | tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type)); | |
8628 | if ((parm_kind[0] == tgmath_complex && ret != exp_type) | |
8629 | || (parm_kind[0] == tgmath_real && ret != exp_real_type)) | |
8630 | { | |
8631 | error_at ((*cexpr_list)[j].get_location (), | |
8632 | "bad return type for function argument %u " | |
8633 | "of %<__builtin_tgmath%>", j + 1); | |
8634 | expr.set_error (); | |
8635 | goto out; | |
8636 | } | |
8637 | argpos = 1; | |
8638 | FOREACH_FUNCTION_ARGS (type, t, iter) | |
8639 | { | |
8640 | if (t == void_type_node) | |
8641 | break; | |
8642 | t = TYPE_MAIN_VARIANT (t); | |
8643 | if ((parm_kind[argpos] == tgmath_complex | |
8644 | && t != exp_type) | |
8645 | || (parm_kind[argpos] == tgmath_real | |
8646 | && t != exp_real_type)) | |
8647 | { | |
8648 | error_at ((*cexpr_list)[j].get_location (), | |
8649 | "bad type for argument %u of " | |
8650 | "function argument %u of " | |
8651 | "%<__builtin_tgmath%>", argpos, j + 1); | |
8652 | expr.set_error (); | |
8653 | goto out; | |
8654 | } | |
8655 | argpos++; | |
8656 | } | |
8657 | } | |
8658 | ||
8659 | /* The functions listed are a valid set of functions for a | |
8660 | <tgmath.h> macro to select between. Identify the | |
8661 | matching function, if any. First, the argument types | |
8662 | must be combined following <tgmath.h> rules. Integer | |
8663 | types are treated as _Decimal64 if any type-generic | |
8664 | argument is decimal, or if the only alternatives for | |
8665 | type-generic arguments are of decimal types, and are | |
8666 | otherwise treated as double (or _Complex double for | |
8667 | complex integer types). After that adjustment, types | |
8668 | are combined following the usual arithmetic | |
8669 | conversions. If the function only accepts complex | |
8670 | arguments, a complex type is produced. */ | |
8671 | bool arg_complex = all_complex; | |
8672 | bool arg_binary = all_binary; | |
8673 | bool arg_int_decimal = all_decimal; | |
8674 | for (unsigned int j = 1; j <= nargs; j++) | |
8675 | { | |
8676 | if (parm_kind[j] == tgmath_fixed) | |
8677 | continue; | |
8678 | c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1]; | |
8679 | tree type = TREE_TYPE (ce->value); | |
8680 | if (!INTEGRAL_TYPE_P (type) | |
8681 | && !SCALAR_FLOAT_TYPE_P (type) | |
8682 | && TREE_CODE (type) != COMPLEX_TYPE) | |
8683 | { | |
8684 | error_at (ce->get_location (), | |
8685 | "invalid type of argument %u of type-generic " | |
8686 | "function", j); | |
8687 | expr.set_error (); | |
8688 | goto out; | |
8689 | } | |
8690 | if (DECIMAL_FLOAT_TYPE_P (type)) | |
8691 | { | |
8692 | arg_int_decimal = true; | |
8693 | if (all_complex) | |
8694 | { | |
8695 | error_at (ce->get_location (), | |
8696 | "decimal floating-point argument %u to " | |
8697 | "complex-only type-generic function", j); | |
8698 | expr.set_error (); | |
8699 | goto out; | |
8700 | } | |
8701 | else if (all_binary) | |
8702 | { | |
8703 | error_at (ce->get_location (), | |
8704 | "decimal floating-point argument %u to " | |
8705 | "binary-only type-generic function", j); | |
8706 | expr.set_error (); | |
8707 | goto out; | |
8708 | } | |
8709 | else if (arg_complex) | |
8710 | { | |
8711 | error_at (ce->get_location (), | |
8712 | "both complex and decimal floating-point " | |
8713 | "arguments to type-generic function"); | |
8714 | expr.set_error (); | |
8715 | goto out; | |
8716 | } | |
8717 | else if (arg_binary) | |
8718 | { | |
8719 | error_at (ce->get_location (), | |
8720 | "both binary and decimal floating-point " | |
8721 | "arguments to type-generic function"); | |
8722 | expr.set_error (); | |
8723 | goto out; | |
8724 | } | |
8725 | } | |
8726 | else if (TREE_CODE (type) == COMPLEX_TYPE) | |
8727 | { | |
8728 | arg_complex = true; | |
8729 | if (COMPLEX_FLOAT_TYPE_P (type)) | |
8730 | arg_binary = true; | |
8731 | if (all_decimal) | |
8732 | { | |
8733 | error_at (ce->get_location (), | |
8734 | "complex argument %u to " | |
8735 | "decimal-only type-generic function", j); | |
8736 | expr.set_error (); | |
8737 | goto out; | |
8738 | } | |
8739 | else if (arg_int_decimal) | |
8740 | { | |
8741 | error_at (ce->get_location (), | |
8742 | "both complex and decimal floating-point " | |
8743 | "arguments to type-generic function"); | |
8744 | expr.set_error (); | |
8745 | goto out; | |
8746 | } | |
8747 | } | |
8748 | else if (SCALAR_FLOAT_TYPE_P (type)) | |
8749 | { | |
8750 | arg_binary = true; | |
8751 | if (all_decimal) | |
8752 | { | |
8753 | error_at (ce->get_location (), | |
8754 | "binary argument %u to " | |
8755 | "decimal-only type-generic function", j); | |
8756 | expr.set_error (); | |
8757 | goto out; | |
8758 | } | |
8759 | else if (arg_int_decimal) | |
8760 | { | |
8761 | error_at (ce->get_location (), | |
8762 | "both binary and decimal floating-point " | |
8763 | "arguments to type-generic function"); | |
8764 | expr.set_error (); | |
8765 | goto out; | |
8766 | } | |
8767 | } | |
8768 | } | |
8769 | tree arg_real = NULL_TREE; | |
8770 | for (unsigned int j = 1; j <= nargs; j++) | |
8771 | { | |
8772 | if (parm_kind[j] == tgmath_fixed) | |
8773 | continue; | |
8774 | c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1]; | |
8775 | tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value)); | |
8776 | if (TREE_CODE (type) == COMPLEX_TYPE) | |
8777 | type = TREE_TYPE (type); | |
8778 | if (INTEGRAL_TYPE_P (type)) | |
8779 | type = (arg_int_decimal | |
8780 | ? dfloat64_type_node | |
8781 | : double_type_node); | |
8782 | if (arg_real == NULL_TREE) | |
8783 | arg_real = type; | |
8784 | else | |
8785 | arg_real = common_type (arg_real, type); | |
8786 | if (arg_real == error_mark_node) | |
8787 | { | |
8788 | expr.set_error (); | |
8789 | goto out; | |
8790 | } | |
8791 | } | |
8792 | tree arg_type = (arg_complex | |
8793 | ? build_complex_type (arg_real) | |
8794 | : arg_real); | |
8795 | ||
8796 | /* Look for a function to call with type-generic parameter | |
8797 | type ARG_TYPE. */ | |
8798 | c_expr_t *fn = NULL; | |
8799 | for (unsigned int j = 0; j < num_functions; j++) | |
8800 | { | |
8801 | if (tg_type[j] == arg_type) | |
8802 | { | |
8803 | fn = &(*cexpr_list)[j]; | |
8804 | break; | |
8805 | } | |
8806 | } | |
8807 | if (fn == NULL | |
8808 | && parm_kind[0] == tgmath_fixed | |
8809 | && SCALAR_FLOAT_TYPE_P (parm_first[0])) | |
8810 | { | |
8811 | /* Presume this is a macro that rounds its result to a | |
8812 | narrower type, and look for the first function with | |
8813 | at least the range and precision of the argument | |
8814 | type. */ | |
8815 | for (unsigned int j = 0; j < num_functions; j++) | |
8816 | { | |
8817 | if (arg_complex | |
8818 | != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE)) | |
8819 | continue; | |
8820 | tree real_tg_type = (arg_complex | |
8821 | ? TREE_TYPE (tg_type[j]) | |
8822 | : tg_type[j]); | |
8823 | if (DECIMAL_FLOAT_TYPE_P (arg_real) | |
8824 | != DECIMAL_FLOAT_TYPE_P (real_tg_type)) | |
8825 | continue; | |
8826 | scalar_float_mode arg_mode | |
8827 | = SCALAR_FLOAT_TYPE_MODE (arg_real); | |
8828 | scalar_float_mode tg_mode | |
8829 | = SCALAR_FLOAT_TYPE_MODE (real_tg_type); | |
8830 | const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode); | |
8831 | const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode); | |
8832 | if (arg_fmt->b == tg_fmt->b | |
8833 | && arg_fmt->p <= tg_fmt->p | |
8834 | && arg_fmt->emax <= tg_fmt->emax | |
8835 | && (arg_fmt->emin - arg_fmt->p | |
8836 | >= tg_fmt->emin - tg_fmt->p)) | |
8837 | { | |
8838 | fn = &(*cexpr_list)[j]; | |
8839 | break; | |
8840 | } | |
8841 | } | |
8842 | } | |
8843 | if (fn == NULL) | |
8844 | { | |
8845 | error_at (loc, "no matching function for type-generic call"); | |
8846 | expr.set_error (); | |
8847 | break; | |
8848 | } | |
8849 | ||
8850 | /* Construct a call to FN. */ | |
8851 | vec<tree, va_gc> *args; | |
8852 | vec_alloc (args, nargs); | |
8853 | vec<tree, va_gc> *origtypes; | |
8854 | vec_alloc (origtypes, nargs); | |
8855 | auto_vec<location_t> arg_loc (nargs); | |
8856 | for (unsigned int j = 0; j < nargs; j++) | |
8857 | { | |
8858 | c_expr_t *ce = &(*cexpr_list)[num_functions + j]; | |
8859 | args->quick_push (ce->value); | |
8860 | arg_loc.quick_push (ce->get_location ()); | |
8861 | origtypes->quick_push (ce->original_type); | |
8862 | } | |
8863 | expr.value = c_build_function_call_vec (loc, arg_loc, fn->value, | |
8864 | args, origtypes); | |
8865 | set_c_expr_source_range (&expr, loc, close_paren_loc); | |
8866 | break; | |
8867 | } | |
74893f25 RH |
8868 | case RID_BUILTIN_CALL_WITH_STATIC_CHAIN: |
8869 | { | |
8870 | vec<c_expr_t, va_gc> *cexpr_list; | |
8871 | c_expr_t *e2_p; | |
8872 | tree chain_value; | |
46c6e1e2 | 8873 | location_t close_paren_loc; |
74893f25 RH |
8874 | |
8875 | c_parser_consume_token (parser); | |
8876 | if (!c_parser_get_builtin_args (parser, | |
8877 | "__builtin_call_with_static_chain", | |
46c6e1e2 DM |
8878 | &cexpr_list, false, |
8879 | &close_paren_loc)) | |
74893f25 | 8880 | { |
8a40fef3 | 8881 | expr.set_error (); |
74893f25 RH |
8882 | break; |
8883 | } | |
8884 | if (vec_safe_length (cexpr_list) != 2) | |
8885 | { | |
8886 | error_at (loc, "wrong number of arguments to " | |
8887 | "%<__builtin_call_with_static_chain%>"); | |
8a40fef3 | 8888 | expr.set_error (); |
74893f25 RH |
8889 | break; |
8890 | } | |
8891 | ||
8892 | expr = (*cexpr_list)[0]; | |
8893 | e2_p = &(*cexpr_list)[1]; | |
8894 | *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true); | |
8895 | chain_value = e2_p->value; | |
8896 | mark_exp_read (chain_value); | |
8897 | ||
8898 | if (TREE_CODE (expr.value) != CALL_EXPR) | |
8899 | error_at (loc, "first argument to " | |
8900 | "%<__builtin_call_with_static_chain%> " | |
8901 | "must be a call expression"); | |
8902 | else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE) | |
8903 | error_at (loc, "second argument to " | |
8904 | "%<__builtin_call_with_static_chain%> " | |
8905 | "must be a pointer type"); | |
8906 | else | |
8907 | CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value; | |
46c6e1e2 | 8908 | set_c_expr_source_range (&expr, loc, close_paren_loc); |
74893f25 RH |
8909 | break; |
8910 | } | |
d4a83c10 | 8911 | case RID_BUILTIN_COMPLEX: |
86785830 | 8912 | { |
9771b263 | 8913 | vec<c_expr_t, va_gc> *cexpr_list; |
86785830 | 8914 | c_expr_t *e1_p, *e2_p; |
46c6e1e2 | 8915 | location_t close_paren_loc; |
86785830 | 8916 | |
f90e8e2e AS |
8917 | c_parser_consume_token (parser); |
8918 | if (!c_parser_get_builtin_args (parser, | |
8919 | "__builtin_complex", | |
46c6e1e2 DM |
8920 | &cexpr_list, false, |
8921 | &close_paren_loc)) | |
f90e8e2e | 8922 | { |
8a40fef3 | 8923 | expr.set_error (); |
f90e8e2e AS |
8924 | break; |
8925 | } | |
8926 | ||
9771b263 | 8927 | if (vec_safe_length (cexpr_list) != 2) |
f90e8e2e AS |
8928 | { |
8929 | error_at (loc, "wrong number of arguments to " | |
8930 | "%<__builtin_complex%>"); | |
8a40fef3 | 8931 | expr.set_error (); |
f90e8e2e AS |
8932 | break; |
8933 | } | |
86785830 | 8934 | |
9771b263 DN |
8935 | e1_p = &(*cexpr_list)[0]; |
8936 | e2_p = &(*cexpr_list)[1]; | |
86785830 | 8937 | |
267bac10 | 8938 | *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true); |
86785830 AS |
8939 | if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR) |
8940 | e1_p->value = convert (TREE_TYPE (e1_p->value), | |
8941 | TREE_OPERAND (e1_p->value, 0)); | |
267bac10 | 8942 | *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true); |
86785830 AS |
8943 | if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR) |
8944 | e2_p->value = convert (TREE_TYPE (e2_p->value), | |
8945 | TREE_OPERAND (e2_p->value, 0)); | |
8946 | if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value)) | |
8947 | || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value)) | |
8948 | || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)) | |
8949 | || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))) | |
f90e8e2e AS |
8950 | { |
8951 | error_at (loc, "%<__builtin_complex%> operand " | |
8952 | "not of real binary floating-point type"); | |
8a40fef3 | 8953 | expr.set_error (); |
f90e8e2e AS |
8954 | break; |
8955 | } | |
86785830 AS |
8956 | if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value)) |
8957 | != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value))) | |
f90e8e2e AS |
8958 | { |
8959 | error_at (loc, | |
8960 | "%<__builtin_complex%> operands of different types"); | |
8a40fef3 | 8961 | expr.set_error (); |
f90e8e2e AS |
8962 | break; |
8963 | } | |
f3bede71 MP |
8964 | pedwarn_c90 (loc, OPT_Wpedantic, |
8965 | "ISO C90 does not support complex types"); | |
46c6e1e2 DM |
8966 | expr.value = build2_loc (loc, COMPLEX_EXPR, |
8967 | build_complex_type | |
8968 | (TYPE_MAIN_VARIANT | |
8969 | (TREE_TYPE (e1_p->value))), | |
8970 | e1_p->value, e2_p->value); | |
8971 | set_c_expr_source_range (&expr, loc, close_paren_loc); | |
f90e8e2e AS |
8972 | break; |
8973 | } | |
8974 | case RID_BUILTIN_SHUFFLE: | |
8975 | { | |
9771b263 | 8976 | vec<c_expr_t, va_gc> *cexpr_list; |
9243c51d JJ |
8977 | unsigned int i; |
8978 | c_expr_t *p; | |
46c6e1e2 | 8979 | location_t close_paren_loc; |
86785830 | 8980 | |
f90e8e2e AS |
8981 | c_parser_consume_token (parser); |
8982 | if (!c_parser_get_builtin_args (parser, | |
8983 | "__builtin_shuffle", | |
46c6e1e2 DM |
8984 | &cexpr_list, false, |
8985 | &close_paren_loc)) | |
f90e8e2e | 8986 | { |
8a40fef3 | 8987 | expr.set_error (); |
f90e8e2e AS |
8988 | break; |
8989 | } | |
8990 | ||
9771b263 | 8991 | FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p) |
267bac10 | 8992 | *p = convert_lvalue_to_rvalue (loc, *p, true, true); |
9243c51d | 8993 | |
9771b263 | 8994 | if (vec_safe_length (cexpr_list) == 2) |
86785830 | 8995 | expr.value = |
2205ed25 | 8996 | c_build_vec_perm_expr |
9771b263 DN |
8997 | (loc, (*cexpr_list)[0].value, |
8998 | NULL_TREE, (*cexpr_list)[1].value); | |
86785830 | 8999 | |
9771b263 | 9000 | else if (vec_safe_length (cexpr_list) == 3) |
86785830 | 9001 | expr.value = |
2205ed25 | 9002 | c_build_vec_perm_expr |
9771b263 DN |
9003 | (loc, (*cexpr_list)[0].value, |
9004 | (*cexpr_list)[1].value, | |
9005 | (*cexpr_list)[2].value); | |
f90e8e2e AS |
9006 | else |
9007 | { | |
9008 | error_at (loc, "wrong number of arguments to " | |
9009 | "%<__builtin_shuffle%>"); | |
8a40fef3 | 9010 | expr.set_error (); |
f90e8e2e | 9011 | } |
46c6e1e2 | 9012 | set_c_expr_source_range (&expr, loc, close_paren_loc); |
f90e8e2e AS |
9013 | break; |
9014 | } | |
27bf414c | 9015 | case RID_AT_SELECTOR: |
27bf414c | 9016 | { |
32129a17 DM |
9017 | gcc_assert (c_dialect_objc ()); |
9018 | c_parser_consume_token (parser); | |
9019 | matching_parens parens; | |
9020 | if (!parens.require_open (parser)) | |
9021 | { | |
9022 | expr.set_error (); | |
9023 | break; | |
9024 | } | |
27bf414c | 9025 | tree sel = c_parser_objc_selector_arg (parser); |
cbd03aee | 9026 | location_t close_loc = c_parser_peek_token (parser)->location; |
32129a17 | 9027 | parens.skip_until_found_close (parser); |
c2255bc4 | 9028 | expr.value = objc_build_selector_expr (loc, sel); |
cbd03aee | 9029 | set_c_expr_source_range (&expr, loc, close_loc); |
27bf414c JM |
9030 | } |
9031 | break; | |
9032 | case RID_AT_PROTOCOL: | |
27bf414c | 9033 | { |
32129a17 DM |
9034 | gcc_assert (c_dialect_objc ()); |
9035 | c_parser_consume_token (parser); | |
9036 | matching_parens parens; | |
9037 | if (!parens.require_open (parser)) | |
9038 | { | |
9039 | expr.set_error (); | |
9040 | break; | |
9041 | } | |
9042 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9043 | { | |
9044 | c_parser_error (parser, "expected identifier"); | |
9045 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
9046 | expr.set_error (); | |
9047 | break; | |
9048 | } | |
27bf414c JM |
9049 | tree id = c_parser_peek_token (parser)->value; |
9050 | c_parser_consume_token (parser); | |
cbd03aee | 9051 | location_t close_loc = c_parser_peek_token (parser)->location; |
32129a17 | 9052 | parens.skip_until_found_close (parser); |
27bf414c | 9053 | expr.value = objc_build_protocol_expr (id); |
cbd03aee | 9054 | set_c_expr_source_range (&expr, loc, close_loc); |
27bf414c JM |
9055 | } |
9056 | break; | |
9057 | case RID_AT_ENCODE: | |
27bf414c | 9058 | { |
32129a17 DM |
9059 | /* Extension to support C-structures in the archiver. */ |
9060 | gcc_assert (c_dialect_objc ()); | |
9061 | c_parser_consume_token (parser); | |
9062 | matching_parens parens; | |
9063 | if (!parens.require_open (parser)) | |
9064 | { | |
9065 | expr.set_error (); | |
9066 | break; | |
9067 | } | |
9068 | t1 = c_parser_type_name (parser); | |
9069 | if (t1 == NULL) | |
9070 | { | |
9071 | expr.set_error (); | |
9072 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
9073 | break; | |
9074 | } | |
cbd03aee | 9075 | location_t close_loc = c_parser_peek_token (parser)->location; |
32129a17 | 9076 | parens.skip_until_found_close (parser); |
928c19bb | 9077 | tree type = groktypename (t1, NULL, NULL); |
27bf414c | 9078 | expr.value = objc_build_encode_expr (type); |
cbd03aee | 9079 | set_c_expr_source_range (&expr, loc, close_loc); |
27bf414c JM |
9080 | } |
9081 | break; | |
433cc7b0 TT |
9082 | case RID_GENERIC: |
9083 | expr = c_parser_generic_selection (parser); | |
9084 | break; | |
939b37da BI |
9085 | case RID_CILK_SPAWN: |
9086 | c_parser_consume_token (parser); | |
b72271b9 | 9087 | if (!flag_cilkplus) |
939b37da BI |
9088 | { |
9089 | error_at (loc, "-fcilkplus must be enabled to use " | |
9090 | "%<_Cilk_spawn%>"); | |
7ff6ca38 | 9091 | expr = c_parser_cast_expression (parser, NULL); |
8a40fef3 | 9092 | expr.set_error (); |
939b37da | 9093 | } |
9a74f20c | 9094 | else if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) |
939b37da BI |
9095 | { |
9096 | error_at (loc, "consecutive %<_Cilk_spawn%> keywords " | |
9097 | "are not permitted"); | |
9098 | /* Now flush out all the _Cilk_spawns. */ | |
9099 | while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) | |
9100 | c_parser_consume_token (parser); | |
7ff6ca38 | 9101 | expr = c_parser_cast_expression (parser, NULL); |
939b37da BI |
9102 | } |
9103 | else | |
9104 | { | |
7ff6ca38 | 9105 | expr = c_parser_cast_expression (parser, NULL); |
939b37da BI |
9106 | expr.value = build_cilk_spawn (loc, expr.value); |
9107 | } | |
7ff6ca38 | 9108 | break; |
27bf414c JM |
9109 | default: |
9110 | c_parser_error (parser, "expected expression"); | |
8a40fef3 | 9111 | expr.set_error (); |
27bf414c JM |
9112 | break; |
9113 | } | |
9114 | break; | |
9115 | case CPP_OPEN_SQUARE: | |
9116 | if (c_dialect_objc ()) | |
9117 | { | |
9118 | tree receiver, args; | |
9119 | c_parser_consume_token (parser); | |
9120 | receiver = c_parser_objc_receiver (parser); | |
9121 | args = c_parser_objc_message_args (parser); | |
cbd03aee | 9122 | location_t close_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
9123 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, |
9124 | "expected %<]%>"); | |
eb345401 | 9125 | expr.value = objc_build_message_expr (receiver, args); |
cbd03aee | 9126 | set_c_expr_source_range (&expr, loc, close_loc); |
27bf414c JM |
9127 | break; |
9128 | } | |
9129 | /* Else fall through to report error. */ | |
191816a3 | 9130 | /* FALLTHRU */ |
27bf414c JM |
9131 | default: |
9132 | c_parser_error (parser, "expected expression"); | |
8a40fef3 | 9133 | expr.set_error (); |
27bf414c JM |
9134 | break; |
9135 | } | |
3ca0dc60 | 9136 | out: |
a10704e1 DM |
9137 | return c_parser_postfix_expression_after_primary |
9138 | (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); | |
27bf414c JM |
9139 | } |
9140 | ||
9141 | /* Parse a postfix expression after a parenthesized type name: the | |
9142 | brace-enclosed initializer of a compound literal, possibly followed | |
9143 | by some postfix operators. This is separate because it is not | |
9144 | possible to tell until after the type name whether a cast | |
9145 | expression has a cast or a compound literal, or whether the operand | |
9146 | of sizeof is a parenthesized type name or starts with a compound | |
24b97832 ILT |
9147 | literal. TYPE_LOC is the location where TYPE_NAME starts--the |
9148 | location of the first token after the parentheses around the type | |
9149 | name. */ | |
27bf414c JM |
9150 | |
9151 | static struct c_expr | |
9152 | c_parser_postfix_expression_after_paren_type (c_parser *parser, | |
24b97832 ILT |
9153 | struct c_type_name *type_name, |
9154 | location_t type_loc) | |
27bf414c JM |
9155 | { |
9156 | tree type; | |
9157 | struct c_expr init; | |
928c19bb | 9158 | bool non_const; |
27bf414c | 9159 | struct c_expr expr; |
c7412148 | 9160 | location_t start_loc; |
928c19bb JM |
9161 | tree type_expr = NULL_TREE; |
9162 | bool type_expr_const = true; | |
c2255bc4 | 9163 | check_compound_literal_type (type_loc, type_name); |
5dd9a9d0 DM |
9164 | rich_location richloc (line_table, type_loc); |
9165 | start_init (NULL_TREE, NULL, 0, &richloc); | |
928c19bb | 9166 | type = groktypename (type_name, &type_expr, &type_expr_const); |
c7412148 | 9167 | start_loc = c_parser_peek_token (parser)->location; |
85cad37c | 9168 | if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) |
27bf414c | 9169 | { |
24b97832 | 9170 | error_at (type_loc, "compound literal has variable size"); |
27bf414c JM |
9171 | type = error_mark_node; |
9172 | } | |
16595a1f | 9173 | init = c_parser_braced_init (parser, type, false, NULL); |
27bf414c | 9174 | finish_init (); |
d033409e | 9175 | maybe_warn_string_init (type_loc, type, init); |
27bf414c | 9176 | |
36c5e70a BE |
9177 | if (type != error_mark_node |
9178 | && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)) | |
9179 | && current_function_decl) | |
9180 | { | |
9181 | error ("compound literal qualified by address-space qualifier"); | |
9182 | type = error_mark_node; | |
9183 | } | |
9184 | ||
f3bede71 | 9185 | pedwarn_c90 (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals"); |
928c19bb JM |
9186 | non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR) |
9187 | ? CONSTRUCTOR_NON_CONST (init.value) | |
9188 | : init.original_code == C_MAYBE_CONST_EXPR); | |
9189 | non_const |= !type_expr_const; | |
c2255bc4 | 9190 | expr.value = build_compound_literal (start_loc, type, init.value, non_const); |
bef08b71 | 9191 | set_c_expr_source_range (&expr, init.src_range); |
27bf414c | 9192 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9193 | expr.original_type = NULL; |
a5b5c8b6 MP |
9194 | if (type != error_mark_node |
9195 | && expr.value != error_mark_node | |
9196 | && type_expr) | |
928c19bb JM |
9197 | { |
9198 | if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR) | |
9199 | { | |
9200 | gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE); | |
9201 | C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr; | |
9202 | } | |
9203 | else | |
9204 | { | |
9205 | gcc_assert (!non_const); | |
9206 | expr.value = build2 (C_MAYBE_CONST_EXPR, type, | |
9207 | type_expr, expr.value); | |
9208 | } | |
9209 | } | |
c2255bc4 | 9210 | return c_parser_postfix_expression_after_primary (parser, start_loc, expr); |
27bf414c JM |
9211 | } |
9212 | ||
1a4049e7 JJ |
9213 | /* Callback function for sizeof_pointer_memaccess_warning to compare |
9214 | types. */ | |
9215 | ||
9216 | static bool | |
9217 | sizeof_ptr_memacc_comptypes (tree type1, tree type2) | |
9218 | { | |
9219 | return comptypes (type1, type2) == 1; | |
9220 | } | |
9221 | ||
27bf414c | 9222 | /* Parse a postfix expression after the initial primary or compound |
c2255bc4 AH |
9223 | literal; that is, parse a series of postfix operators. |
9224 | ||
9225 | EXPR_LOC is the location of the primary expression. */ | |
27bf414c JM |
9226 | |
9227 | static struct c_expr | |
9228 | c_parser_postfix_expression_after_primary (c_parser *parser, | |
c2255bc4 | 9229 | location_t expr_loc, |
27bf414c JM |
9230 | struct c_expr expr) |
9231 | { | |
928c19bb | 9232 | struct c_expr orig_expr; |
bbbbb16a | 9233 | tree ident, idx; |
6ffd47b7 | 9234 | location_t sizeof_arg_loc[3], comp_loc; |
3a785c97 | 9235 | tree sizeof_arg[3]; |
b108f48f | 9236 | unsigned int literal_zero_mask; |
3a785c97 | 9237 | unsigned int i; |
9771b263 | 9238 | vec<tree, va_gc> *exprlist; |
2ee028f1 | 9239 | vec<tree, va_gc> *origtypes = NULL; |
81e5eca8 | 9240 | vec<location_t> arg_loc = vNULL; |
ebedc9a3 DM |
9241 | location_t start; |
9242 | location_t finish; | |
81e5eca8 | 9243 | |
27bf414c JM |
9244 | while (true) |
9245 | { | |
c2255bc4 | 9246 | location_t op_loc = c_parser_peek_token (parser)->location; |
27bf414c JM |
9247 | switch (c_parser_peek_token (parser)->type) |
9248 | { | |
9249 | case CPP_OPEN_SQUARE: | |
9250 | /* Array reference. */ | |
9251 | c_parser_consume_token (parser); | |
b72271b9 | 9252 | if (flag_cilkplus |
36536d79 BI |
9253 | && c_parser_peek_token (parser)->type == CPP_COLON) |
9254 | /* If we are here, then we have something like this: | |
9255 | Array [ : ] | |
9256 | */ | |
9257 | expr.value = c_parser_array_notation (expr_loc, parser, NULL_TREE, | |
9258 | expr.value); | |
9259 | else | |
9260 | { | |
9261 | idx = c_parser_expression (parser).value; | |
9262 | /* Here we have 3 options: | |
9263 | 1. Array [EXPR] -- Normal Array call. | |
9264 | 2. Array [EXPR : EXPR] -- Array notation without stride. | |
9265 | 3. Array [EXPR : EXPR : EXPR] -- Array notation with stride. | |
9266 | ||
9267 | For 1, we just handle it just like a normal array expression. | |
9268 | For 2 and 3 we handle it like we handle array notations. The | |
9269 | idx value we have above becomes the initial/start index. | |
9270 | */ | |
b72271b9 | 9271 | if (flag_cilkplus |
36536d79 BI |
9272 | && c_parser_peek_token (parser)->type == CPP_COLON) |
9273 | expr.value = c_parser_array_notation (expr_loc, parser, idx, | |
9274 | expr.value); | |
9275 | else | |
9276 | { | |
9277 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, | |
9278 | "expected %<]%>"); | |
ebedc9a3 DM |
9279 | start = expr.get_start (); |
9280 | finish = parser->tokens_buf[0].location; | |
36536d79 | 9281 | expr.value = build_array_ref (op_loc, expr.value, idx); |
ebedc9a3 | 9282 | set_c_expr_source_range (&expr, start, finish); |
36536d79 BI |
9283 | } |
9284 | } | |
27bf414c | 9285 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9286 | expr.original_type = NULL; |
27bf414c JM |
9287 | break; |
9288 | case CPP_OPEN_PAREN: | |
9289 | /* Function call. */ | |
9290 | c_parser_consume_token (parser); | |
3a785c97 JJ |
9291 | for (i = 0; i < 3; i++) |
9292 | { | |
9293 | sizeof_arg[i] = NULL_TREE; | |
9294 | sizeof_arg_loc[i] = UNKNOWN_LOCATION; | |
9295 | } | |
b108f48f | 9296 | literal_zero_mask = 0; |
27bf414c | 9297 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
bbbbb16a | 9298 | exprlist = NULL; |
27bf414c | 9299 | else |
1a4049e7 | 9300 | exprlist = c_parser_expr_list (parser, true, false, &origtypes, |
81e5eca8 | 9301 | sizeof_arg_loc, sizeof_arg, |
b108f48f | 9302 | &arg_loc, &literal_zero_mask); |
27bf414c JM |
9303 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
9304 | "expected %<)%>"); | |
928c19bb | 9305 | orig_expr = expr; |
ebfbbdc5 | 9306 | mark_exp_read (expr.value); |
3a785c97 JJ |
9307 | if (warn_sizeof_pointer_memaccess) |
9308 | sizeof_pointer_memaccess_warning (sizeof_arg_loc, | |
1a4049e7 | 9309 | expr.value, exprlist, |
3a785c97 | 9310 | sizeof_arg, |
1a4049e7 | 9311 | sizeof_ptr_memacc_comptypes); |
c1e1f433 | 9312 | if (TREE_CODE (expr.value) == FUNCTION_DECL |
b108f48f JJ |
9313 | && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL |
9314 | && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET | |
c1e1f433 BS |
9315 | && vec_safe_length (exprlist) == 3) |
9316 | { | |
9317 | tree arg0 = (*exprlist)[0]; | |
9318 | tree arg2 = (*exprlist)[2]; | |
9319 | warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); | |
9320 | } | |
b108f48f | 9321 | |
ebedc9a3 DM |
9322 | start = expr.get_start (); |
9323 | finish = parser->tokens_buf[0].get_finish (); | |
8edbfaa6 JJ |
9324 | expr.value |
9325 | = c_build_function_call_vec (expr_loc, arg_loc, expr.value, | |
9326 | exprlist, origtypes); | |
ebedc9a3 DM |
9327 | set_c_expr_source_range (&expr, start, finish); |
9328 | ||
27bf414c | 9329 | expr.original_code = ERROR_MARK; |
928c19bb JM |
9330 | if (TREE_CODE (expr.value) == INTEGER_CST |
9331 | && TREE_CODE (orig_expr.value) == FUNCTION_DECL | |
9332 | && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL | |
9333 | && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) | |
9334 | expr.original_code = C_MAYBE_CONST_EXPR; | |
6866c6e8 | 9335 | expr.original_type = NULL; |
9771b263 | 9336 | if (exprlist) |
bbbbb16a | 9337 | { |
c166b898 ILT |
9338 | release_tree_vector (exprlist); |
9339 | release_tree_vector (origtypes); | |
bbbbb16a | 9340 | } |
81e5eca8 | 9341 | arg_loc.release (); |
27bf414c JM |
9342 | break; |
9343 | case CPP_DOT: | |
9344 | /* Structure element reference. */ | |
9345 | c_parser_consume_token (parser); | |
c2255bc4 | 9346 | expr = default_function_array_conversion (expr_loc, expr); |
27bf414c | 9347 | if (c_parser_next_token_is (parser, CPP_NAME)) |
6ffd47b7 DM |
9348 | { |
9349 | c_token *comp_tok = c_parser_peek_token (parser); | |
9350 | ident = comp_tok->value; | |
9351 | comp_loc = comp_tok->location; | |
9352 | } | |
27bf414c JM |
9353 | else |
9354 | { | |
9355 | c_parser_error (parser, "expected identifier"); | |
8a40fef3 | 9356 | expr.set_error (); |
27bf414c | 9357 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9358 | expr.original_type = NULL; |
27bf414c JM |
9359 | return expr; |
9360 | } | |
ebedc9a3 DM |
9361 | start = expr.get_start (); |
9362 | finish = c_parser_peek_token (parser)->get_finish (); | |
27bf414c | 9363 | c_parser_consume_token (parser); |
6ffd47b7 DM |
9364 | expr.value = build_component_ref (op_loc, expr.value, ident, |
9365 | comp_loc); | |
ebedc9a3 | 9366 | set_c_expr_source_range (&expr, start, finish); |
27bf414c | 9367 | expr.original_code = ERROR_MARK; |
6866c6e8 ILT |
9368 | if (TREE_CODE (expr.value) != COMPONENT_REF) |
9369 | expr.original_type = NULL; | |
9370 | else | |
9371 | { | |
9372 | /* Remember the original type of a bitfield. */ | |
9373 | tree field = TREE_OPERAND (expr.value, 1); | |
9374 | if (TREE_CODE (field) != FIELD_DECL) | |
9375 | expr.original_type = NULL; | |
9376 | else | |
9377 | expr.original_type = DECL_BIT_FIELD_TYPE (field); | |
9378 | } | |
27bf414c JM |
9379 | break; |
9380 | case CPP_DEREF: | |
9381 | /* Structure element reference. */ | |
9382 | c_parser_consume_token (parser); | |
267bac10 | 9383 | expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false); |
27bf414c | 9384 | if (c_parser_next_token_is (parser, CPP_NAME)) |
6ffd47b7 DM |
9385 | { |
9386 | c_token *comp_tok = c_parser_peek_token (parser); | |
9387 | ident = comp_tok->value; | |
9388 | comp_loc = comp_tok->location; | |
9389 | } | |
27bf414c JM |
9390 | else |
9391 | { | |
9392 | c_parser_error (parser, "expected identifier"); | |
8a40fef3 | 9393 | expr.set_error (); |
27bf414c | 9394 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9395 | expr.original_type = NULL; |
27bf414c JM |
9396 | return expr; |
9397 | } | |
ebedc9a3 DM |
9398 | start = expr.get_start (); |
9399 | finish = c_parser_peek_token (parser)->get_finish (); | |
27bf414c | 9400 | c_parser_consume_token (parser); |
c2255bc4 AH |
9401 | expr.value = build_component_ref (op_loc, |
9402 | build_indirect_ref (op_loc, | |
c9f9eb5d | 9403 | expr.value, |
dd865ef6 | 9404 | RO_ARROW), |
6ffd47b7 | 9405 | ident, comp_loc); |
ebedc9a3 | 9406 | set_c_expr_source_range (&expr, start, finish); |
27bf414c | 9407 | expr.original_code = ERROR_MARK; |
6866c6e8 ILT |
9408 | if (TREE_CODE (expr.value) != COMPONENT_REF) |
9409 | expr.original_type = NULL; | |
9410 | else | |
9411 | { | |
9412 | /* Remember the original type of a bitfield. */ | |
9413 | tree field = TREE_OPERAND (expr.value, 1); | |
9414 | if (TREE_CODE (field) != FIELD_DECL) | |
9415 | expr.original_type = NULL; | |
9416 | else | |
9417 | expr.original_type = DECL_BIT_FIELD_TYPE (field); | |
9418 | } | |
27bf414c JM |
9419 | break; |
9420 | case CPP_PLUS_PLUS: | |
9421 | /* Postincrement. */ | |
ebedc9a3 DM |
9422 | start = expr.get_start (); |
9423 | finish = c_parser_peek_token (parser)->get_finish (); | |
27bf414c | 9424 | c_parser_consume_token (parser); |
36536d79 | 9425 | /* If the expressions have array notations, we expand them. */ |
b72271b9 | 9426 | if (flag_cilkplus |
36536d79 BI |
9427 | && TREE_CODE (expr.value) == ARRAY_NOTATION_REF) |
9428 | expr = fix_array_notation_expr (expr_loc, POSTINCREMENT_EXPR, expr); | |
9429 | else | |
9430 | { | |
9431 | expr = default_function_array_read_conversion (expr_loc, expr); | |
e51fbec3 MP |
9432 | expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR, |
9433 | expr.value, false); | |
36536d79 | 9434 | } |
ebedc9a3 | 9435 | set_c_expr_source_range (&expr, start, finish); |
27bf414c | 9436 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9437 | expr.original_type = NULL; |
27bf414c JM |
9438 | break; |
9439 | case CPP_MINUS_MINUS: | |
9440 | /* Postdecrement. */ | |
ebedc9a3 DM |
9441 | start = expr.get_start (); |
9442 | finish = c_parser_peek_token (parser)->get_finish (); | |
27bf414c | 9443 | c_parser_consume_token (parser); |
36536d79 | 9444 | /* If the expressions have array notations, we expand them. */ |
b72271b9 | 9445 | if (flag_cilkplus |
36536d79 BI |
9446 | && TREE_CODE (expr.value) == ARRAY_NOTATION_REF) |
9447 | expr = fix_array_notation_expr (expr_loc, POSTDECREMENT_EXPR, expr); | |
9448 | else | |
9449 | { | |
9450 | expr = default_function_array_read_conversion (expr_loc, expr); | |
e51fbec3 MP |
9451 | expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR, |
9452 | expr.value, false); | |
36536d79 | 9453 | } |
ebedc9a3 | 9454 | set_c_expr_source_range (&expr, start, finish); |
27bf414c | 9455 | expr.original_code = ERROR_MARK; |
6866c6e8 | 9456 | expr.original_type = NULL; |
27bf414c JM |
9457 | break; |
9458 | default: | |
9459 | return expr; | |
9460 | } | |
9461 | } | |
9462 | } | |
9463 | ||
31dc71a8 | 9464 | /* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17). |
27bf414c JM |
9465 | |
9466 | expression: | |
9467 | assignment-expression | |
9468 | expression , assignment-expression | |
9469 | */ | |
9470 | ||
9471 | static struct c_expr | |
9472 | c_parser_expression (c_parser *parser) | |
9473 | { | |
267bac10 | 9474 | location_t tloc = c_parser_peek_token (parser)->location; |
27bf414c JM |
9475 | struct c_expr expr; |
9476 | expr = c_parser_expr_no_commas (parser, NULL); | |
267bac10 JM |
9477 | if (c_parser_next_token_is (parser, CPP_COMMA)) |
9478 | expr = convert_lvalue_to_rvalue (tloc, expr, true, false); | |
27bf414c JM |
9479 | while (c_parser_next_token_is (parser, CPP_COMMA)) |
9480 | { | |
9481 | struct c_expr next; | |
056928b2 | 9482 | tree lhsval; |
c2255bc4 AH |
9483 | location_t loc = c_parser_peek_token (parser)->location; |
9484 | location_t expr_loc; | |
27bf414c | 9485 | c_parser_consume_token (parser); |
c2255bc4 | 9486 | expr_loc = c_parser_peek_token (parser)->location; |
056928b2 JJ |
9487 | lhsval = expr.value; |
9488 | while (TREE_CODE (lhsval) == COMPOUND_EXPR) | |
9489 | lhsval = TREE_OPERAND (lhsval, 1); | |
9490 | if (DECL_P (lhsval) || handled_component_p (lhsval)) | |
9491 | mark_exp_read (lhsval); | |
27bf414c | 9492 | next = c_parser_expr_no_commas (parser, NULL); |
267bac10 | 9493 | next = convert_lvalue_to_rvalue (expr_loc, next, true, false); |
c2255bc4 | 9494 | expr.value = build_compound_expr (loc, expr.value, next.value); |
27bf414c | 9495 | expr.original_code = COMPOUND_EXPR; |
81f40b79 | 9496 | expr.original_type = next.original_type; |
27bf414c JM |
9497 | } |
9498 | return expr; | |
9499 | } | |
9500 | ||
267bac10 JM |
9501 | /* Parse an expression and convert functions or arrays to pointers and |
9502 | lvalues to rvalues. */ | |
46bdb9cf JM |
9503 | |
9504 | static struct c_expr | |
9505 | c_parser_expression_conv (c_parser *parser) | |
9506 | { | |
9507 | struct c_expr expr; | |
c2255bc4 | 9508 | location_t loc = c_parser_peek_token (parser)->location; |
46bdb9cf | 9509 | expr = c_parser_expression (parser); |
267bac10 | 9510 | expr = convert_lvalue_to_rvalue (loc, expr, true, false); |
46bdb9cf JM |
9511 | return expr; |
9512 | } | |
9513 | ||
b108f48f JJ |
9514 | /* Helper function of c_parser_expr_list. Check if IDXth (0 based) |
9515 | argument is a literal zero alone and if so, set it in literal_zero_mask. */ | |
9516 | ||
9517 | static inline void | |
9518 | c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask, | |
9519 | unsigned int idx) | |
9520 | { | |
9521 | if (idx >= HOST_BITS_PER_INT) | |
9522 | return; | |
9523 | ||
9524 | c_token *tok = c_parser_peek_token (parser); | |
9525 | switch (tok->type) | |
9526 | { | |
9527 | case CPP_NUMBER: | |
9528 | case CPP_CHAR: | |
9529 | case CPP_WCHAR: | |
9530 | case CPP_CHAR16: | |
9531 | case CPP_CHAR32: | |
9532 | /* If a parameter is literal zero alone, remember it | |
9533 | for -Wmemset-transposed-args warning. */ | |
9534 | if (integer_zerop (tok->value) | |
9535 | && !TREE_OVERFLOW (tok->value) | |
9536 | && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA | |
9537 | || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN)) | |
9538 | *literal_zero_mask |= 1U << idx; | |
9539 | default: | |
9540 | break; | |
9541 | } | |
9542 | } | |
9543 | ||
46bdb9cf | 9544 | /* Parse a non-empty list of expressions. If CONVERT_P, convert |
267bac10 | 9545 | functions and arrays to pointers and lvalues to rvalues. If |
81e5eca8 MP |
9546 | FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the |
9547 | locations of function arguments into this vector. | |
27bf414c JM |
9548 | |
9549 | nonempty-expr-list: | |
9550 | assignment-expression | |
9551 | nonempty-expr-list , assignment-expression | |
9552 | */ | |
9553 | ||
9771b263 | 9554 | static vec<tree, va_gc> * |
bbbbb16a | 9555 | c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, |
9771b263 | 9556 | vec<tree, va_gc> **p_orig_types, |
81e5eca8 | 9557 | location_t *sizeof_arg_loc, tree *sizeof_arg, |
b108f48f JJ |
9558 | vec<location_t> *locations, |
9559 | unsigned int *literal_zero_mask) | |
27bf414c | 9560 | { |
9771b263 DN |
9561 | vec<tree, va_gc> *ret; |
9562 | vec<tree, va_gc> *orig_types; | |
27bf414c | 9563 | struct c_expr expr; |
3a785c97 | 9564 | unsigned int idx = 0; |
bbbbb16a | 9565 | |
c166b898 | 9566 | ret = make_tree_vector (); |
bbbbb16a ILT |
9567 | if (p_orig_types == NULL) |
9568 | orig_types = NULL; | |
9569 | else | |
c166b898 | 9570 | orig_types = make_tree_vector (); |
bbbbb16a | 9571 | |
b108f48f JJ |
9572 | if (literal_zero_mask) |
9573 | c_parser_check_literal_zero (parser, literal_zero_mask, 0); | |
27bf414c | 9574 | expr = c_parser_expr_no_commas (parser, NULL); |
46bdb9cf | 9575 | if (convert_p) |
7f204c0f | 9576 | expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true); |
928c19bb JM |
9577 | if (fold_p) |
9578 | expr.value = c_fully_fold (expr.value, false, NULL); | |
9771b263 DN |
9579 | ret->quick_push (expr.value); |
9580 | if (orig_types) | |
9581 | orig_types->quick_push (expr.original_type); | |
81e5eca8 | 9582 | if (locations) |
7f204c0f | 9583 | locations->safe_push (expr.get_location ()); |
3a785c97 | 9584 | if (sizeof_arg != NULL |
3a785c97 JJ |
9585 | && expr.original_code == SIZEOF_EXPR) |
9586 | { | |
9587 | sizeof_arg[0] = c_last_sizeof_arg; | |
40ffd95f | 9588 | sizeof_arg_loc[0] = c_last_sizeof_loc; |
3a785c97 | 9589 | } |
27bf414c JM |
9590 | while (c_parser_next_token_is (parser, CPP_COMMA)) |
9591 | { | |
9592 | c_parser_consume_token (parser); | |
b108f48f JJ |
9593 | if (literal_zero_mask) |
9594 | c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1); | |
27bf414c | 9595 | expr = c_parser_expr_no_commas (parser, NULL); |
46bdb9cf | 9596 | if (convert_p) |
7f204c0f DM |
9597 | expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, |
9598 | true); | |
928c19bb JM |
9599 | if (fold_p) |
9600 | expr.value = c_fully_fold (expr.value, false, NULL); | |
9771b263 DN |
9601 | vec_safe_push (ret, expr.value); |
9602 | if (orig_types) | |
9603 | vec_safe_push (orig_types, expr.original_type); | |
81e5eca8 | 9604 | if (locations) |
7f204c0f | 9605 | locations->safe_push (expr.get_location ()); |
3a785c97 JJ |
9606 | if (++idx < 3 |
9607 | && sizeof_arg != NULL | |
1a4049e7 JJ |
9608 | && expr.original_code == SIZEOF_EXPR) |
9609 | { | |
3a785c97 | 9610 | sizeof_arg[idx] = c_last_sizeof_arg; |
40ffd95f | 9611 | sizeof_arg_loc[idx] = c_last_sizeof_loc; |
1a4049e7 JJ |
9612 | } |
9613 | } | |
9771b263 | 9614 | if (orig_types) |
bbbbb16a | 9615 | *p_orig_types = orig_types; |
27bf414c JM |
9616 | return ret; |
9617 | } | |
27bf414c JM |
9618 | \f |
9619 | /* Parse Objective-C-specific constructs. */ | |
9620 | ||
9621 | /* Parse an objc-class-definition. | |
9622 | ||
9623 | objc-class-definition: | |
9624 | @interface identifier objc-superclass[opt] objc-protocol-refs[opt] | |
9625 | objc-class-instance-variables[opt] objc-methodprotolist @end | |
9626 | @implementation identifier objc-superclass[opt] | |
9627 | objc-class-instance-variables[opt] | |
9628 | @interface identifier ( identifier ) objc-protocol-refs[opt] | |
9629 | objc-methodprotolist @end | |
ec3e9f82 NP |
9630 | @interface identifier ( ) objc-protocol-refs[opt] |
9631 | objc-methodprotolist @end | |
27bf414c JM |
9632 | @implementation identifier ( identifier ) |
9633 | ||
9634 | objc-superclass: | |
9635 | : identifier | |
9636 | ||
9637 | "@interface identifier (" must start "@interface identifier ( | |
9638 | identifier ) ...": objc-methodprotolist in the first production may | |
0fa2e4df | 9639 | not start with a parenthesized identifier as a declarator of a data |
27bf414c JM |
9640 | definition with no declaration specifiers if the objc-superclass, |
9641 | objc-protocol-refs and objc-class-instance-variables are omitted. */ | |
9642 | ||
9643 | static void | |
c165dca7 | 9644 | c_parser_objc_class_definition (c_parser *parser, tree attributes) |
27bf414c JM |
9645 | { |
9646 | bool iface_p; | |
9647 | tree id1; | |
9648 | tree superclass; | |
9649 | if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE)) | |
9650 | iface_p = true; | |
9651 | else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION)) | |
9652 | iface_p = false; | |
9653 | else | |
9654 | gcc_unreachable (); | |
c165dca7 | 9655 | |
27bf414c JM |
9656 | c_parser_consume_token (parser); |
9657 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9658 | { | |
9659 | c_parser_error (parser, "expected identifier"); | |
9660 | return; | |
9661 | } | |
9662 | id1 = c_parser_peek_token (parser)->value; | |
9663 | c_parser_consume_token (parser); | |
9664 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
9665 | { | |
ec3e9f82 | 9666 | /* We have a category or class extension. */ |
27bf414c JM |
9667 | tree id2; |
9668 | tree proto = NULL_TREE; | |
32129a17 DM |
9669 | matching_parens parens; |
9670 | parens.consume_open (parser); | |
27bf414c JM |
9671 | if (c_parser_next_token_is_not (parser, CPP_NAME)) |
9672 | { | |
ec3e9f82 NP |
9673 | if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
9674 | { | |
9675 | /* We have a class extension. */ | |
9676 | id2 = NULL_TREE; | |
9677 | } | |
9678 | else | |
9679 | { | |
9680 | c_parser_error (parser, "expected identifier or %<)%>"); | |
9681 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
9682 | return; | |
9683 | } | |
9684 | } | |
9685 | else | |
9686 | { | |
9687 | id2 = c_parser_peek_token (parser)->value; | |
9688 | c_parser_consume_token (parser); | |
27bf414c | 9689 | } |
32129a17 | 9690 | parens.skip_until_found_close (parser); |
27bf414c JM |
9691 | if (!iface_p) |
9692 | { | |
9693 | objc_start_category_implementation (id1, id2); | |
9694 | return; | |
9695 | } | |
9696 | if (c_parser_next_token_is (parser, CPP_LESS)) | |
9697 | proto = c_parser_objc_protocol_refs (parser); | |
c165dca7 | 9698 | objc_start_category_interface (id1, id2, proto, attributes); |
27bf414c JM |
9699 | c_parser_objc_methodprotolist (parser); |
9700 | c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); | |
9701 | objc_finish_interface (); | |
9702 | return; | |
9703 | } | |
9704 | if (c_parser_next_token_is (parser, CPP_COLON)) | |
9705 | { | |
9706 | c_parser_consume_token (parser); | |
9707 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9708 | { | |
9709 | c_parser_error (parser, "expected identifier"); | |
9710 | return; | |
9711 | } | |
9712 | superclass = c_parser_peek_token (parser)->value; | |
9713 | c_parser_consume_token (parser); | |
9714 | } | |
9715 | else | |
9716 | superclass = NULL_TREE; | |
9717 | if (iface_p) | |
9718 | { | |
9719 | tree proto = NULL_TREE; | |
9720 | if (c_parser_next_token_is (parser, CPP_LESS)) | |
9721 | proto = c_parser_objc_protocol_refs (parser); | |
c165dca7 | 9722 | objc_start_class_interface (id1, superclass, proto, attributes); |
27bf414c JM |
9723 | } |
9724 | else | |
9725 | objc_start_class_implementation (id1, superclass); | |
9726 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
9727 | c_parser_objc_class_instance_variables (parser); | |
9728 | if (iface_p) | |
9729 | { | |
9730 | objc_continue_interface (); | |
9731 | c_parser_objc_methodprotolist (parser); | |
9732 | c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); | |
9733 | objc_finish_interface (); | |
9734 | } | |
9735 | else | |
9736 | { | |
9737 | objc_continue_implementation (); | |
9738 | return; | |
9739 | } | |
9740 | } | |
9741 | ||
9742 | /* Parse objc-class-instance-variables. | |
9743 | ||
9744 | objc-class-instance-variables: | |
9745 | { objc-instance-variable-decl-list[opt] } | |
9746 | ||
9747 | objc-instance-variable-decl-list: | |
9748 | objc-visibility-spec | |
9749 | objc-instance-variable-decl ; | |
9750 | ; | |
9751 | objc-instance-variable-decl-list objc-visibility-spec | |
9752 | objc-instance-variable-decl-list objc-instance-variable-decl ; | |
9753 | objc-instance-variable-decl-list ; | |
9754 | ||
9755 | objc-visibility-spec: | |
9756 | @private | |
9757 | @protected | |
9758 | @public | |
9759 | ||
9760 | objc-instance-variable-decl: | |
9761 | struct-declaration | |
9762 | */ | |
9763 | ||
9764 | static void | |
9765 | c_parser_objc_class_instance_variables (c_parser *parser) | |
9766 | { | |
9767 | gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); | |
9768 | c_parser_consume_token (parser); | |
9769 | while (c_parser_next_token_is_not (parser, CPP_EOF)) | |
9770 | { | |
9771 | tree decls; | |
9772 | /* Parse any stray semicolon. */ | |
9773 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
9774 | { | |
c1771a20 | 9775 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
4e26ba90 | 9776 | "extra semicolon"); |
27bf414c JM |
9777 | c_parser_consume_token (parser); |
9778 | continue; | |
9779 | } | |
9780 | /* Stop if at the end of the instance variables. */ | |
9781 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
9782 | { | |
9783 | c_parser_consume_token (parser); | |
9784 | break; | |
9785 | } | |
9786 | /* Parse any objc-visibility-spec. */ | |
49b91f05 | 9787 | if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE)) |
27bf414c JM |
9788 | { |
9789 | c_parser_consume_token (parser); | |
c37d8c30 | 9790 | objc_set_visibility (OBJC_IVAR_VIS_PRIVATE); |
27bf414c JM |
9791 | continue; |
9792 | } | |
49b91f05 | 9793 | else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED)) |
27bf414c JM |
9794 | { |
9795 | c_parser_consume_token (parser); | |
c37d8c30 | 9796 | objc_set_visibility (OBJC_IVAR_VIS_PROTECTED); |
27bf414c JM |
9797 | continue; |
9798 | } | |
49b91f05 | 9799 | else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC)) |
27bf414c JM |
9800 | { |
9801 | c_parser_consume_token (parser); | |
c37d8c30 IS |
9802 | objc_set_visibility (OBJC_IVAR_VIS_PUBLIC); |
9803 | continue; | |
9804 | } | |
9805 | else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE)) | |
9806 | { | |
9807 | c_parser_consume_token (parser); | |
9808 | objc_set_visibility (OBJC_IVAR_VIS_PACKAGE); | |
27bf414c JM |
9809 | continue; |
9810 | } | |
bc4071dd RH |
9811 | else if (c_parser_next_token_is (parser, CPP_PRAGMA)) |
9812 | { | |
dda1bf61 | 9813 | c_parser_pragma (parser, pragma_external, NULL); |
bc4071dd RH |
9814 | continue; |
9815 | } | |
9816 | ||
27bf414c JM |
9817 | /* Parse some comma-separated declarations. */ |
9818 | decls = c_parser_struct_declaration (parser); | |
4e26ba90 NP |
9819 | if (decls == NULL) |
9820 | { | |
9821 | /* There is a syntax error. We want to skip the offending | |
9822 | tokens up to the next ';' (included) or '}' | |
9823 | (excluded). */ | |
9824 | ||
9825 | /* First, skip manually a ')' or ']'. This is because they | |
9826 | reduce the nesting level, so c_parser_skip_until_found() | |
9827 | wouldn't be able to skip past them. */ | |
9828 | c_token *token = c_parser_peek_token (parser); | |
9829 | if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE) | |
9830 | c_parser_consume_token (parser); | |
9831 | ||
9832 | /* Then, do the standard skipping. */ | |
9833 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
9834 | ||
9835 | /* We hopefully recovered. Start normal parsing again. */ | |
9836 | parser->error = false; | |
9837 | continue; | |
9838 | } | |
9839 | else | |
9840 | { | |
9841 | /* Comma-separated instance variables are chained together | |
9842 | in reverse order; add them one by one. */ | |
9843 | tree ivar = nreverse (decls); | |
9844 | for (; ivar; ivar = DECL_CHAIN (ivar)) | |
9845 | objc_add_instance_variable (copy_node (ivar)); | |
9846 | } | |
27bf414c JM |
9847 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
9848 | } | |
9849 | } | |
9850 | ||
9851 | /* Parse an objc-class-declaration. | |
9852 | ||
9853 | objc-class-declaration: | |
9854 | @class identifier-list ; | |
9855 | */ | |
9856 | ||
9857 | static void | |
9858 | c_parser_objc_class_declaration (c_parser *parser) | |
9859 | { | |
49b91f05 | 9860 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS)); |
27bf414c JM |
9861 | c_parser_consume_token (parser); |
9862 | /* Any identifiers, including those declared as type names, are OK | |
9863 | here. */ | |
9864 | while (true) | |
9865 | { | |
9866 | tree id; | |
9867 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9868 | { | |
9869 | c_parser_error (parser, "expected identifier"); | |
da57d1b9 NP |
9870 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); |
9871 | parser->error = false; | |
9872 | return; | |
27bf414c JM |
9873 | } |
9874 | id = c_parser_peek_token (parser)->value; | |
32dabdaf | 9875 | objc_declare_class (id); |
27bf414c JM |
9876 | c_parser_consume_token (parser); |
9877 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
9878 | c_parser_consume_token (parser); | |
9879 | else | |
9880 | break; | |
9881 | } | |
9882 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
27bf414c JM |
9883 | } |
9884 | ||
9885 | /* Parse an objc-alias-declaration. | |
9886 | ||
9887 | objc-alias-declaration: | |
9888 | @compatibility_alias identifier identifier ; | |
9889 | */ | |
9890 | ||
9891 | static void | |
9892 | c_parser_objc_alias_declaration (c_parser *parser) | |
9893 | { | |
9894 | tree id1, id2; | |
9895 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS)); | |
9896 | c_parser_consume_token (parser); | |
9897 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9898 | { | |
9899 | c_parser_error (parser, "expected identifier"); | |
9900 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
9901 | return; | |
9902 | } | |
9903 | id1 = c_parser_peek_token (parser)->value; | |
9904 | c_parser_consume_token (parser); | |
9905 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9906 | { | |
9907 | c_parser_error (parser, "expected identifier"); | |
9908 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
9909 | return; | |
9910 | } | |
9911 | id2 = c_parser_peek_token (parser)->value; | |
9912 | c_parser_consume_token (parser); | |
9913 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
9914 | objc_declare_alias (id1, id2); | |
9915 | } | |
9916 | ||
9917 | /* Parse an objc-protocol-definition. | |
9918 | ||
9919 | objc-protocol-definition: | |
9920 | @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end | |
9921 | @protocol identifier-list ; | |
9922 | ||
9923 | "@protocol identifier ;" should be resolved as "@protocol | |
9924 | identifier-list ;": objc-methodprotolist may not start with a | |
9925 | semicolon in the first alternative if objc-protocol-refs are | |
9926 | omitted. */ | |
9927 | ||
9928 | static void | |
c165dca7 | 9929 | c_parser_objc_protocol_definition (c_parser *parser, tree attributes) |
27bf414c JM |
9930 | { |
9931 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)); | |
c165dca7 | 9932 | |
27bf414c JM |
9933 | c_parser_consume_token (parser); |
9934 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9935 | { | |
9936 | c_parser_error (parser, "expected identifier"); | |
9937 | return; | |
9938 | } | |
9939 | if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA | |
9940 | || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON) | |
9941 | { | |
27bf414c JM |
9942 | /* Any identifiers, including those declared as type names, are |
9943 | OK here. */ | |
9944 | while (true) | |
9945 | { | |
9946 | tree id; | |
9947 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
9948 | { | |
9949 | c_parser_error (parser, "expected identifier"); | |
9950 | break; | |
9951 | } | |
9952 | id = c_parser_peek_token (parser)->value; | |
c59633d9 | 9953 | objc_declare_protocol (id, attributes); |
27bf414c JM |
9954 | c_parser_consume_token (parser); |
9955 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
9956 | c_parser_consume_token (parser); | |
9957 | else | |
9958 | break; | |
9959 | } | |
9960 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
27bf414c JM |
9961 | } |
9962 | else | |
9963 | { | |
9964 | tree id = c_parser_peek_token (parser)->value; | |
9965 | tree proto = NULL_TREE; | |
9966 | c_parser_consume_token (parser); | |
9967 | if (c_parser_next_token_is (parser, CPP_LESS)) | |
9968 | proto = c_parser_objc_protocol_refs (parser); | |
0bacb8c7 | 9969 | parser->objc_pq_context = true; |
c165dca7 | 9970 | objc_start_protocol (id, proto, attributes); |
27bf414c JM |
9971 | c_parser_objc_methodprotolist (parser); |
9972 | c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); | |
0bacb8c7 | 9973 | parser->objc_pq_context = false; |
27bf414c JM |
9974 | objc_finish_interface (); |
9975 | } | |
9976 | } | |
9977 | ||
9978 | /* Parse an objc-method-type. | |
9979 | ||
9980 | objc-method-type: | |
9981 | + | |
9982 | - | |
27bf414c | 9983 | |
249a82c4 NP |
9984 | Return true if it is a class method (+) and false if it is |
9985 | an instance method (-). | |
9986 | */ | |
9987 | static inline bool | |
27bf414c JM |
9988 | c_parser_objc_method_type (c_parser *parser) |
9989 | { | |
9990 | switch (c_parser_peek_token (parser)->type) | |
9991 | { | |
9992 | case CPP_PLUS: | |
9993 | c_parser_consume_token (parser); | |
249a82c4 | 9994 | return true; |
27bf414c JM |
9995 | case CPP_MINUS: |
9996 | c_parser_consume_token (parser); | |
249a82c4 | 9997 | return false; |
27bf414c JM |
9998 | default: |
9999 | gcc_unreachable (); | |
10000 | } | |
10001 | } | |
10002 | ||
10003 | /* Parse an objc-method-definition. | |
10004 | ||
10005 | objc-method-definition: | |
10006 | objc-method-type objc-method-decl ;[opt] compound-statement | |
10007 | */ | |
10008 | ||
10009 | static void | |
10010 | c_parser_objc_method_definition (c_parser *parser) | |
10011 | { | |
249a82c4 | 10012 | bool is_class_method = c_parser_objc_method_type (parser); |
a04a722b | 10013 | tree decl, attributes = NULL_TREE, expr = NULL_TREE; |
0bacb8c7 | 10014 | parser->objc_pq_context = true; |
a04a722b JM |
10015 | decl = c_parser_objc_method_decl (parser, is_class_method, &attributes, |
10016 | &expr); | |
f7e71da5 IS |
10017 | if (decl == error_mark_node) |
10018 | return; /* Bail here. */ | |
10019 | ||
27bf414c JM |
10020 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
10021 | { | |
10022 | c_parser_consume_token (parser); | |
c1771a20 | 10023 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 10024 | "extra semicolon in method definition specified"); |
27bf414c | 10025 | } |
f7e71da5 | 10026 | |
8f078c08 AP |
10027 | if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
10028 | { | |
10029 | c_parser_error (parser, "expected %<{%>"); | |
10030 | return; | |
10031 | } | |
f7e71da5 | 10032 | |
0bacb8c7 | 10033 | parser->objc_pq_context = false; |
a04a722b | 10034 | if (objc_start_method_definition (is_class_method, decl, attributes, expr)) |
45547c7f NP |
10035 | { |
10036 | add_stmt (c_parser_compound_statement (parser)); | |
10037 | objc_finish_method_definition (current_function_decl); | |
10038 | } | |
10039 | else | |
10040 | { | |
10041 | /* This code is executed when we find a method definition | |
a26d8862 NP |
10042 | outside of an @implementation context (or invalid for other |
10043 | reasons). Parse the method (to keep going) but do not emit | |
10044 | any code. | |
45547c7f NP |
10045 | */ |
10046 | c_parser_compound_statement (parser); | |
10047 | } | |
27bf414c JM |
10048 | } |
10049 | ||
10050 | /* Parse an objc-methodprotolist. | |
10051 | ||
10052 | objc-methodprotolist: | |
10053 | empty | |
10054 | objc-methodprotolist objc-methodproto | |
10055 | objc-methodprotolist declaration | |
10056 | objc-methodprotolist ; | |
92902b1b IS |
10057 | @optional |
10058 | @required | |
27bf414c JM |
10059 | |
10060 | The declaration is a data definition, which may be missing | |
10061 | declaration specifiers under the same rules and diagnostics as | |
10062 | other data definitions outside functions, and the stray semicolon | |
10063 | is diagnosed the same way as a stray semicolon outside a | |
10064 | function. */ | |
10065 | ||
10066 | static void | |
10067 | c_parser_objc_methodprotolist (c_parser *parser) | |
10068 | { | |
10069 | while (true) | |
10070 | { | |
10071 | /* The list is terminated by @end. */ | |
10072 | switch (c_parser_peek_token (parser)->type) | |
10073 | { | |
10074 | case CPP_SEMICOLON: | |
c1771a20 | 10075 | pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic, |
509c9d60 | 10076 | "ISO C does not allow extra %<;%> outside of a function"); |
27bf414c JM |
10077 | c_parser_consume_token (parser); |
10078 | break; | |
10079 | case CPP_PLUS: | |
10080 | case CPP_MINUS: | |
10081 | c_parser_objc_methodproto (parser); | |
10082 | break; | |
b9b58168 | 10083 | case CPP_PRAGMA: |
dda1bf61 | 10084 | c_parser_pragma (parser, pragma_external, NULL); |
b9b58168 | 10085 | break; |
27bf414c JM |
10086 | case CPP_EOF: |
10087 | return; | |
10088 | default: | |
10089 | if (c_parser_next_token_is_keyword (parser, RID_AT_END)) | |
10090 | return; | |
668ea4b1 | 10091 | else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY)) |
f614132b | 10092 | c_parser_objc_at_property_declaration (parser); |
92902b1b IS |
10093 | else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL)) |
10094 | { | |
10095 | objc_set_method_opt (true); | |
10096 | c_parser_consume_token (parser); | |
10097 | } | |
10098 | else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED)) | |
10099 | { | |
10100 | objc_set_method_opt (false); | |
10101 | c_parser_consume_token (parser); | |
10102 | } | |
10103 | else | |
10104 | c_parser_declaration_or_fndef (parser, false, false, true, | |
acf0174b | 10105 | false, true, NULL, vNULL); |
27bf414c JM |
10106 | break; |
10107 | } | |
10108 | } | |
10109 | } | |
10110 | ||
10111 | /* Parse an objc-methodproto. | |
10112 | ||
10113 | objc-methodproto: | |
10114 | objc-method-type objc-method-decl ; | |
10115 | */ | |
10116 | ||
10117 | static void | |
10118 | c_parser_objc_methodproto (c_parser *parser) | |
10119 | { | |
249a82c4 | 10120 | bool is_class_method = c_parser_objc_method_type (parser); |
f7e71da5 | 10121 | tree decl, attributes = NULL_TREE; |
249a82c4 | 10122 | |
27bf414c | 10123 | /* Remember protocol qualifiers in prototypes. */ |
0bacb8c7 | 10124 | parser->objc_pq_context = true; |
a04a722b JM |
10125 | decl = c_parser_objc_method_decl (parser, is_class_method, &attributes, |
10126 | NULL); | |
f7e71da5 | 10127 | /* Forget protocol qualifiers now. */ |
0bacb8c7 | 10128 | parser->objc_pq_context = false; |
f7e71da5 IS |
10129 | |
10130 | /* Do not allow the presence of attributes to hide an erroneous | |
10131 | method implementation in the interface section. */ | |
10132 | if (!c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
10133 | { | |
10134 | c_parser_error (parser, "expected %<;%>"); | |
10135 | return; | |
10136 | } | |
10137 | ||
10138 | if (decl != error_mark_node) | |
249a82c4 | 10139 | objc_add_method_declaration (is_class_method, decl, attributes); |
f7e71da5 | 10140 | |
27bf414c JM |
10141 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
10142 | } | |
10143 | ||
f7e71da5 IS |
10144 | /* If we are at a position that method attributes may be present, check that |
10145 | there are not any parsed already (a syntax error) and then collect any | |
10146 | specified at the current location. Finally, if new attributes were present, | |
10147 | check that the next token is legal ( ';' for decls and '{' for defs). */ | |
10148 | ||
10149 | static bool | |
10150 | c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes) | |
10151 | { | |
10152 | bool bad = false; | |
10153 | if (*attributes) | |
10154 | { | |
10155 | c_parser_error (parser, | |
10156 | "method attributes must be specified at the end only"); | |
10157 | *attributes = NULL_TREE; | |
10158 | bad = true; | |
10159 | } | |
10160 | ||
10161 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
10162 | *attributes = c_parser_attributes (parser); | |
10163 | ||
10164 | /* If there were no attributes here, just report any earlier error. */ | |
10165 | if (*attributes == NULL_TREE || bad) | |
10166 | return bad; | |
10167 | ||
10168 | /* If the attributes are followed by a ; or {, then just report any earlier | |
10169 | error. */ | |
10170 | if (c_parser_next_token_is (parser, CPP_SEMICOLON) | |
10171 | || c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
10172 | return bad; | |
10173 | ||
10174 | /* We've got attributes, but not at the end. */ | |
10175 | c_parser_error (parser, | |
10176 | "expected %<;%> or %<{%> after method attribute definition"); | |
10177 | return true; | |
10178 | } | |
10179 | ||
27bf414c JM |
10180 | /* Parse an objc-method-decl. |
10181 | ||
10182 | objc-method-decl: | |
10183 | ( objc-type-name ) objc-selector | |
10184 | objc-selector | |
10185 | ( objc-type-name ) objc-keyword-selector objc-optparmlist | |
10186 | objc-keyword-selector objc-optparmlist | |
f7e71da5 | 10187 | attributes |
27bf414c JM |
10188 | |
10189 | objc-keyword-selector: | |
10190 | objc-keyword-decl | |
10191 | objc-keyword-selector objc-keyword-decl | |
10192 | ||
10193 | objc-keyword-decl: | |
10194 | objc-selector : ( objc-type-name ) identifier | |
10195 | objc-selector : identifier | |
10196 | : ( objc-type-name ) identifier | |
10197 | : identifier | |
10198 | ||
10199 | objc-optparmlist: | |
10200 | objc-optparms objc-optellipsis | |
10201 | ||
10202 | objc-optparms: | |
10203 | empty | |
10204 | objc-opt-parms , parameter-declaration | |
10205 | ||
10206 | objc-optellipsis: | |
10207 | empty | |
10208 | , ... | |
10209 | */ | |
10210 | ||
10211 | static tree | |
a04a722b JM |
10212 | c_parser_objc_method_decl (c_parser *parser, bool is_class_method, |
10213 | tree *attributes, tree *expr) | |
27bf414c JM |
10214 | { |
10215 | tree type = NULL_TREE; | |
10216 | tree sel; | |
10217 | tree parms = NULL_TREE; | |
dbb74365 | 10218 | bool ellipsis = false; |
f7e71da5 | 10219 | bool attr_err = false; |
dbb74365 | 10220 | |
f7e71da5 | 10221 | *attributes = NULL_TREE; |
27bf414c JM |
10222 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) |
10223 | { | |
32129a17 DM |
10224 | matching_parens parens; |
10225 | parens.consume_open (parser); | |
27bf414c | 10226 | type = c_parser_objc_type_name (parser); |
32129a17 | 10227 | parens.skip_until_found_close (parser); |
27bf414c JM |
10228 | } |
10229 | sel = c_parser_objc_selector (parser); | |
10230 | /* If there is no selector, or a colon follows, we have an | |
10231 | objc-keyword-selector. If there is a selector, and a colon does | |
10232 | not follow, that selector ends the objc-method-decl. */ | |
10233 | if (!sel || c_parser_next_token_is (parser, CPP_COLON)) | |
10234 | { | |
10235 | tree tsel = sel; | |
10236 | tree list = NULL_TREE; | |
27bf414c JM |
10237 | while (true) |
10238 | { | |
10239 | tree atype = NULL_TREE, id, keyworddecl; | |
f7e71da5 | 10240 | tree param_attr = NULL_TREE; |
27bf414c JM |
10241 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
10242 | break; | |
10243 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
10244 | { | |
10245 | c_parser_consume_token (parser); | |
10246 | atype = c_parser_objc_type_name (parser); | |
10247 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
10248 | "expected %<)%>"); | |
10249 | } | |
f7e71da5 IS |
10250 | /* New ObjC allows attributes on method parameters. */ |
10251 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
10252 | param_attr = c_parser_attributes (parser); | |
27bf414c JM |
10253 | if (c_parser_next_token_is_not (parser, CPP_NAME)) |
10254 | { | |
10255 | c_parser_error (parser, "expected identifier"); | |
10256 | return error_mark_node; | |
10257 | } | |
10258 | id = c_parser_peek_token (parser)->value; | |
10259 | c_parser_consume_token (parser); | |
f7e71da5 | 10260 | keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr); |
27bf414c JM |
10261 | list = chainon (list, keyworddecl); |
10262 | tsel = c_parser_objc_selector (parser); | |
10263 | if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) | |
10264 | break; | |
10265 | } | |
f7e71da5 IS |
10266 | |
10267 | attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ; | |
10268 | ||
27bf414c JM |
10269 | /* Parse the optional parameter list. Optional Objective-C |
10270 | method parameters follow the C syntax, and may include '...' | |
10271 | to denote a variable number of arguments. */ | |
10272 | parms = make_node (TREE_LIST); | |
27bf414c JM |
10273 | while (c_parser_next_token_is (parser, CPP_COMMA)) |
10274 | { | |
10275 | struct c_parm *parm; | |
10276 | c_parser_consume_token (parser); | |
10277 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
10278 | { | |
10279 | ellipsis = true; | |
10280 | c_parser_consume_token (parser); | |
f7e71da5 IS |
10281 | attr_err |= c_parser_objc_maybe_method_attributes |
10282 | (parser, attributes) ; | |
27bf414c JM |
10283 | break; |
10284 | } | |
10285 | parm = c_parser_parameter_declaration (parser, NULL_TREE); | |
10286 | if (parm == NULL) | |
10287 | break; | |
10288 | parms = chainon (parms, | |
a04a722b | 10289 | build_tree_list (NULL_TREE, grokparm (parm, expr))); |
27bf414c | 10290 | } |
27bf414c JM |
10291 | sel = list; |
10292 | } | |
f7e71da5 IS |
10293 | else |
10294 | attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ; | |
10295 | ||
10296 | if (sel == NULL) | |
10297 | { | |
10298 | c_parser_error (parser, "objective-c method declaration is expected"); | |
10299 | return error_mark_node; | |
10300 | } | |
10301 | ||
10302 | if (attr_err) | |
10303 | return error_mark_node; | |
10304 | ||
249a82c4 | 10305 | return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis); |
27bf414c JM |
10306 | } |
10307 | ||
10308 | /* Parse an objc-type-name. | |
10309 | ||
10310 | objc-type-name: | |
10311 | objc-type-qualifiers[opt] type-name | |
10312 | objc-type-qualifiers[opt] | |
10313 | ||
10314 | objc-type-qualifiers: | |
10315 | objc-type-qualifier | |
10316 | objc-type-qualifiers objc-type-qualifier | |
10317 | ||
10318 | objc-type-qualifier: one of | |
10319 | in out inout bycopy byref oneway | |
10320 | */ | |
10321 | ||
10322 | static tree | |
10323 | c_parser_objc_type_name (c_parser *parser) | |
10324 | { | |
10325 | tree quals = NULL_TREE; | |
d75d71e0 | 10326 | struct c_type_name *type_name = NULL; |
27bf414c JM |
10327 | tree type = NULL_TREE; |
10328 | while (true) | |
10329 | { | |
10330 | c_token *token = c_parser_peek_token (parser); | |
10331 | if (token->type == CPP_KEYWORD | |
10332 | && (token->keyword == RID_IN | |
10333 | || token->keyword == RID_OUT | |
10334 | || token->keyword == RID_INOUT | |
10335 | || token->keyword == RID_BYCOPY | |
10336 | || token->keyword == RID_BYREF | |
10337 | || token->keyword == RID_ONEWAY)) | |
10338 | { | |
71fc71d8 | 10339 | quals = chainon (build_tree_list (NULL_TREE, token->value), quals); |
27bf414c JM |
10340 | c_parser_consume_token (parser); |
10341 | } | |
10342 | else | |
10343 | break; | |
10344 | } | |
29ce73cb | 10345 | if (c_parser_next_tokens_start_typename (parser, cla_prefer_type)) |
d75d71e0 ILT |
10346 | type_name = c_parser_type_name (parser); |
10347 | if (type_name) | |
928c19bb | 10348 | type = groktypename (type_name, NULL, NULL); |
046608a3 NP |
10349 | |
10350 | /* If the type is unknown, and error has already been produced and | |
10351 | we need to recover from the error. In that case, use NULL_TREE | |
10352 | for the type, as if no type had been specified; this will use the | |
10353 | default type ('id') which is good for error recovery. */ | |
10354 | if (type == error_mark_node) | |
10355 | type = NULL_TREE; | |
10356 | ||
27bf414c JM |
10357 | return build_tree_list (quals, type); |
10358 | } | |
10359 | ||
10360 | /* Parse objc-protocol-refs. | |
10361 | ||
10362 | objc-protocol-refs: | |
10363 | < identifier-list > | |
10364 | */ | |
10365 | ||
10366 | static tree | |
10367 | c_parser_objc_protocol_refs (c_parser *parser) | |
10368 | { | |
10369 | tree list = NULL_TREE; | |
10370 | gcc_assert (c_parser_next_token_is (parser, CPP_LESS)); | |
10371 | c_parser_consume_token (parser); | |
10372 | /* Any identifiers, including those declared as type names, are OK | |
10373 | here. */ | |
10374 | while (true) | |
10375 | { | |
10376 | tree id; | |
10377 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
10378 | { | |
10379 | c_parser_error (parser, "expected identifier"); | |
10380 | break; | |
10381 | } | |
10382 | id = c_parser_peek_token (parser)->value; | |
10383 | list = chainon (list, build_tree_list (NULL_TREE, id)); | |
10384 | c_parser_consume_token (parser); | |
10385 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
10386 | c_parser_consume_token (parser); | |
10387 | else | |
10388 | break; | |
10389 | } | |
10390 | c_parser_require (parser, CPP_GREATER, "expected %<>%>"); | |
10391 | return list; | |
10392 | } | |
10393 | ||
437c2322 | 10394 | /* Parse an objc-try-catch-finally-statement. |
27bf414c | 10395 | |
437c2322 | 10396 | objc-try-catch-finally-statement: |
27bf414c JM |
10397 | @try compound-statement objc-catch-list[opt] |
10398 | @try compound-statement objc-catch-list[opt] @finally compound-statement | |
10399 | ||
10400 | objc-catch-list: | |
437c2322 NP |
10401 | @catch ( objc-catch-parameter-declaration ) compound-statement |
10402 | objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement | |
10403 | ||
10404 | objc-catch-parameter-declaration: | |
10405 | parameter-declaration | |
10406 | '...' | |
10407 | ||
10408 | where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS. | |
10409 | ||
10410 | PS: This function is identical to cp_parser_objc_try_catch_finally_statement | |
10411 | for C++. Keep them in sync. */ | |
27bf414c JM |
10412 | |
10413 | static void | |
437c2322 | 10414 | c_parser_objc_try_catch_finally_statement (c_parser *parser) |
27bf414c | 10415 | { |
437c2322 | 10416 | location_t location; |
27bf414c | 10417 | tree stmt; |
437c2322 | 10418 | |
49b91f05 | 10419 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY)); |
27bf414c | 10420 | c_parser_consume_token (parser); |
437c2322 | 10421 | location = c_parser_peek_token (parser)->location; |
46270f14 | 10422 | objc_maybe_warn_exceptions (location); |
27bf414c | 10423 | stmt = c_parser_compound_statement (parser); |
437c2322 NP |
10424 | objc_begin_try_stmt (location, stmt); |
10425 | ||
49b91f05 | 10426 | while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH)) |
27bf414c JM |
10427 | { |
10428 | struct c_parm *parm; | |
437c2322 NP |
10429 | tree parameter_declaration = error_mark_node; |
10430 | bool seen_open_paren = false; | |
10431 | ||
27bf414c | 10432 | c_parser_consume_token (parser); |
32129a17 DM |
10433 | matching_parens parens; |
10434 | if (!parens.require_open (parser)) | |
437c2322 NP |
10435 | seen_open_paren = true; |
10436 | if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) | |
27bf414c | 10437 | { |
437c2322 NP |
10438 | /* We have "@catch (...)" (where the '...' are literally |
10439 | what is in the code). Skip the '...'. | |
10440 | parameter_declaration is set to NULL_TREE, and | |
10441 | objc_being_catch_clauses() knows that that means | |
10442 | '...'. */ | |
10443 | c_parser_consume_token (parser); | |
10444 | parameter_declaration = NULL_TREE; | |
27bf414c | 10445 | } |
437c2322 NP |
10446 | else |
10447 | { | |
10448 | /* We have "@catch (NSException *exception)" or something | |
10449 | like that. Parse the parameter declaration. */ | |
10450 | parm = c_parser_parameter_declaration (parser, NULL_TREE); | |
10451 | if (parm == NULL) | |
10452 | parameter_declaration = error_mark_node; | |
10453 | else | |
a04a722b | 10454 | parameter_declaration = grokparm (parm, NULL); |
437c2322 NP |
10455 | } |
10456 | if (seen_open_paren) | |
32129a17 | 10457 | parens.require_close (parser); |
437c2322 NP |
10458 | else |
10459 | { | |
10460 | /* If there was no open parenthesis, we are recovering from | |
10461 | an error, and we are trying to figure out what mistake | |
10462 | the user has made. */ | |
10463 | ||
10464 | /* If there is an immediate closing parenthesis, the user | |
10465 | probably forgot the opening one (ie, they typed "@catch | |
10466 | NSException *e)". Parse the closing parenthesis and keep | |
10467 | going. */ | |
10468 | if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |
10469 | c_parser_consume_token (parser); | |
10470 | ||
10471 | /* If these is no immediate closing parenthesis, the user | |
10472 | probably doesn't know that parenthesis are required at | |
10473 | all (ie, they typed "@catch NSException *e"). So, just | |
10474 | forget about the closing parenthesis and keep going. */ | |
10475 | } | |
10476 | objc_begin_catch_clause (parameter_declaration); | |
27bf414c JM |
10477 | if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) |
10478 | c_parser_compound_statement_nostart (parser); | |
10479 | objc_finish_catch_clause (); | |
10480 | } | |
10481 | if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY)) | |
10482 | { | |
27bf414c | 10483 | c_parser_consume_token (parser); |
437c2322 NP |
10484 | location = c_parser_peek_token (parser)->location; |
10485 | stmt = c_parser_compound_statement (parser); | |
10486 | objc_build_finally_clause (location, stmt); | |
27bf414c JM |
10487 | } |
10488 | objc_finish_try_stmt (); | |
10489 | } | |
10490 | ||
10491 | /* Parse an objc-synchronized-statement. | |
10492 | ||
10493 | objc-synchronized-statement: | |
10494 | @synchronized ( expression ) compound-statement | |
10495 | */ | |
10496 | ||
10497 | static void | |
10498 | c_parser_objc_synchronized_statement (c_parser *parser) | |
10499 | { | |
10500 | location_t loc; | |
10501 | tree expr, stmt; | |
10502 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED)); | |
10503 | c_parser_consume_token (parser); | |
10504 | loc = c_parser_peek_token (parser)->location; | |
46270f14 | 10505 | objc_maybe_warn_exceptions (loc); |
32129a17 DM |
10506 | matching_parens parens; |
10507 | if (parens.require_open (parser)) | |
27bf414c | 10508 | { |
267bac10 JM |
10509 | struct c_expr ce = c_parser_expression (parser); |
10510 | ce = convert_lvalue_to_rvalue (loc, ce, false, false); | |
10511 | expr = ce.value; | |
928c19bb | 10512 | expr = c_fully_fold (expr, false, NULL); |
32129a17 | 10513 | parens.skip_until_found_close (parser); |
27bf414c JM |
10514 | } |
10515 | else | |
10516 | expr = error_mark_node; | |
10517 | stmt = c_parser_compound_statement (parser); | |
10518 | objc_build_synchronized (loc, expr, stmt); | |
10519 | } | |
10520 | ||
10521 | /* Parse an objc-selector; return NULL_TREE without an error if the | |
10522 | next token is not an objc-selector. | |
10523 | ||
10524 | objc-selector: | |
10525 | identifier | |
10526 | one of | |
10527 | enum struct union if else while do for switch case default | |
10528 | break continue return goto asm sizeof typeof __alignof | |
10529 | unsigned long const short volatile signed restrict _Complex | |
10530 | in out inout bycopy byref oneway int char float double void _Bool | |
267bac10 | 10531 | _Atomic |
27bf414c JM |
10532 | |
10533 | ??? Why this selection of keywords but not, for example, storage | |
10534 | class specifiers? */ | |
10535 | ||
10536 | static tree | |
10537 | c_parser_objc_selector (c_parser *parser) | |
10538 | { | |
10539 | c_token *token = c_parser_peek_token (parser); | |
10540 | tree value = token->value; | |
10541 | if (token->type == CPP_NAME) | |
10542 | { | |
10543 | c_parser_consume_token (parser); | |
10544 | return value; | |
10545 | } | |
10546 | if (token->type != CPP_KEYWORD) | |
10547 | return NULL_TREE; | |
10548 | switch (token->keyword) | |
10549 | { | |
10550 | case RID_ENUM: | |
10551 | case RID_STRUCT: | |
10552 | case RID_UNION: | |
10553 | case RID_IF: | |
10554 | case RID_ELSE: | |
10555 | case RID_WHILE: | |
10556 | case RID_DO: | |
10557 | case RID_FOR: | |
10558 | case RID_SWITCH: | |
10559 | case RID_CASE: | |
10560 | case RID_DEFAULT: | |
10561 | case RID_BREAK: | |
10562 | case RID_CONTINUE: | |
10563 | case RID_RETURN: | |
10564 | case RID_GOTO: | |
10565 | case RID_ASM: | |
10566 | case RID_SIZEOF: | |
10567 | case RID_TYPEOF: | |
10568 | case RID_ALIGNOF: | |
10569 | case RID_UNSIGNED: | |
10570 | case RID_LONG: | |
10571 | case RID_CONST: | |
10572 | case RID_SHORT: | |
10573 | case RID_VOLATILE: | |
10574 | case RID_SIGNED: | |
10575 | case RID_RESTRICT: | |
10576 | case RID_COMPLEX: | |
10577 | case RID_IN: | |
10578 | case RID_OUT: | |
10579 | case RID_INOUT: | |
10580 | case RID_BYCOPY: | |
10581 | case RID_BYREF: | |
10582 | case RID_ONEWAY: | |
10583 | case RID_INT: | |
10584 | case RID_CHAR: | |
10585 | case RID_FLOAT: | |
10586 | case RID_DOUBLE: | |
c65699ef | 10587 | CASE_RID_FLOATN_NX: |
27bf414c JM |
10588 | case RID_VOID: |
10589 | case RID_BOOL: | |
267bac10 | 10590 | case RID_ATOMIC: |
38b7bc7f | 10591 | case RID_AUTO_TYPE: |
78a7c317 DD |
10592 | case RID_INT_N_0: |
10593 | case RID_INT_N_1: | |
10594 | case RID_INT_N_2: | |
10595 | case RID_INT_N_3: | |
27bf414c JM |
10596 | c_parser_consume_token (parser); |
10597 | return value; | |
10598 | default: | |
10599 | return NULL_TREE; | |
10600 | } | |
10601 | } | |
10602 | ||
10603 | /* Parse an objc-selector-arg. | |
10604 | ||
10605 | objc-selector-arg: | |
10606 | objc-selector | |
10607 | objc-keywordname-list | |
10608 | ||
10609 | objc-keywordname-list: | |
10610 | objc-keywordname | |
10611 | objc-keywordname-list objc-keywordname | |
10612 | ||
10613 | objc-keywordname: | |
10614 | objc-selector : | |
10615 | : | |
10616 | */ | |
10617 | ||
10618 | static tree | |
10619 | c_parser_objc_selector_arg (c_parser *parser) | |
10620 | { | |
10621 | tree sel = c_parser_objc_selector (parser); | |
10622 | tree list = NULL_TREE; | |
10623 | if (sel && c_parser_next_token_is_not (parser, CPP_COLON)) | |
10624 | return sel; | |
10625 | while (true) | |
10626 | { | |
10627 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
10628 | return list; | |
10629 | list = chainon (list, build_tree_list (sel, NULL_TREE)); | |
10630 | sel = c_parser_objc_selector (parser); | |
10631 | if (!sel && c_parser_next_token_is_not (parser, CPP_COLON)) | |
10632 | break; | |
10633 | } | |
10634 | return list; | |
10635 | } | |
10636 | ||
10637 | /* Parse an objc-receiver. | |
10638 | ||
10639 | objc-receiver: | |
10640 | expression | |
10641 | class-name | |
10642 | type-name | |
10643 | */ | |
10644 | ||
10645 | static tree | |
10646 | c_parser_objc_receiver (c_parser *parser) | |
10647 | { | |
267bac10 JM |
10648 | location_t loc = c_parser_peek_token (parser)->location; |
10649 | ||
27bf414c JM |
10650 | if (c_parser_peek_token (parser)->type == CPP_NAME |
10651 | && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME | |
10652 | || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) | |
10653 | { | |
10654 | tree id = c_parser_peek_token (parser)->value; | |
10655 | c_parser_consume_token (parser); | |
10656 | return objc_get_class_reference (id); | |
10657 | } | |
267bac10 JM |
10658 | struct c_expr ce = c_parser_expression (parser); |
10659 | ce = convert_lvalue_to_rvalue (loc, ce, false, false); | |
10660 | return c_fully_fold (ce.value, false, NULL); | |
27bf414c JM |
10661 | } |
10662 | ||
10663 | /* Parse objc-message-args. | |
10664 | ||
10665 | objc-message-args: | |
10666 | objc-selector | |
10667 | objc-keywordarg-list | |
10668 | ||
10669 | objc-keywordarg-list: | |
10670 | objc-keywordarg | |
10671 | objc-keywordarg-list objc-keywordarg | |
10672 | ||
10673 | objc-keywordarg: | |
10674 | objc-selector : objc-keywordexpr | |
10675 | : objc-keywordexpr | |
10676 | */ | |
10677 | ||
10678 | static tree | |
10679 | c_parser_objc_message_args (c_parser *parser) | |
10680 | { | |
10681 | tree sel = c_parser_objc_selector (parser); | |
10682 | tree list = NULL_TREE; | |
10683 | if (sel && c_parser_next_token_is_not (parser, CPP_COLON)) | |
10684 | return sel; | |
10685 | while (true) | |
10686 | { | |
10687 | tree keywordexpr; | |
10688 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
0a7d7dea | 10689 | return error_mark_node; |
27bf414c JM |
10690 | keywordexpr = c_parser_objc_keywordexpr (parser); |
10691 | list = chainon (list, build_tree_list (sel, keywordexpr)); | |
10692 | sel = c_parser_objc_selector (parser); | |
10693 | if (!sel && c_parser_next_token_is_not (parser, CPP_COLON)) | |
10694 | break; | |
10695 | } | |
10696 | return list; | |
10697 | } | |
10698 | ||
10699 | /* Parse an objc-keywordexpr. | |
10700 | ||
10701 | objc-keywordexpr: | |
10702 | nonempty-expr-list | |
10703 | */ | |
10704 | ||
10705 | static tree | |
10706 | c_parser_objc_keywordexpr (c_parser *parser) | |
10707 | { | |
bbbbb16a | 10708 | tree ret; |
9771b263 | 10709 | vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true, |
81e5eca8 | 10710 | NULL, NULL, NULL, NULL); |
9771b263 | 10711 | if (vec_safe_length (expr_list) == 1) |
27bf414c JM |
10712 | { |
10713 | /* Just return the expression, remove a level of | |
10714 | indirection. */ | |
9771b263 | 10715 | ret = (*expr_list)[0]; |
27bf414c JM |
10716 | } |
10717 | else | |
10718 | { | |
10719 | /* We have a comma expression, we will collapse later. */ | |
c166b898 | 10720 | ret = build_tree_list_vec (expr_list); |
27bf414c | 10721 | } |
c166b898 | 10722 | release_tree_vector (expr_list); |
bbbbb16a | 10723 | return ret; |
27bf414c JM |
10724 | } |
10725 | ||
c165dca7 IS |
10726 | /* A check, needed in several places, that ObjC interface, implementation or |
10727 | method definitions are not prefixed by incorrect items. */ | |
10728 | static bool | |
10729 | c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, | |
10730 | struct c_declspecs *specs) | |
10731 | { | |
9e5b2115 PB |
10732 | if (!specs->declspecs_seen_p || specs->non_sc_seen_p |
10733 | || specs->typespec_kind != ctsk_none) | |
c165dca7 IS |
10734 | { |
10735 | c_parser_error (parser, | |
10736 | "no type or storage class may be specified here,"); | |
10737 | c_parser_skip_to_end_of_block_or_statement (parser); | |
10738 | return true; | |
10739 | } | |
10740 | return false; | |
10741 | } | |
668ea4b1 | 10742 | |
f614132b | 10743 | /* Parse an Objective-C @property declaration. The syntax is: |
668ea4b1 | 10744 | |
f614132b NP |
10745 | objc-property-declaration: |
10746 | '@property' objc-property-attributes[opt] struct-declaration ; | |
668ea4b1 | 10747 | |
f614132b NP |
10748 | objc-property-attributes: |
10749 | '(' objc-property-attribute-list ')' | |
10750 | ||
10751 | objc-property-attribute-list: | |
10752 | objc-property-attribute | |
10753 | objc-property-attribute-list, objc-property-attribute | |
10754 | ||
10755 | objc-property-attribute | |
10756 | 'getter' = identifier | |
10757 | 'setter' = identifier | |
10758 | 'readonly' | |
10759 | 'readwrite' | |
10760 | 'assign' | |
10761 | 'retain' | |
10762 | 'copy' | |
10763 | 'nonatomic' | |
10764 | ||
10765 | For example: | |
10766 | @property NSString *name; | |
10767 | @property (readonly) id object; | |
10768 | @property (retain, nonatomic, getter=getTheName) id name; | |
10769 | @property int a, b, c; | |
10770 | ||
10771 | PS: This function is identical to cp_parser_objc_at_propery_declaration | |
200290f2 | 10772 | for C++. Keep them in sync. */ |
668ea4b1 | 10773 | static void |
f614132b | 10774 | c_parser_objc_at_property_declaration (c_parser *parser) |
668ea4b1 | 10775 | { |
200290f2 NP |
10776 | /* The following variables hold the attributes of the properties as |
10777 | parsed. They are 'false' or 'NULL_TREE' if the attribute was not | |
10778 | seen. When we see an attribute, we set them to 'true' (if they | |
10779 | are boolean properties) or to the identifier (if they have an | |
10780 | argument, ie, for getter and setter). Note that here we only | |
10781 | parse the list of attributes, check the syntax and accumulate the | |
10782 | attributes that we find. objc_add_property_declaration() will | |
10783 | then process the information. */ | |
10784 | bool property_assign = false; | |
10785 | bool property_copy = false; | |
10786 | tree property_getter_ident = NULL_TREE; | |
10787 | bool property_nonatomic = false; | |
10788 | bool property_readonly = false; | |
10789 | bool property_readwrite = false; | |
10790 | bool property_retain = false; | |
10791 | tree property_setter_ident = NULL_TREE; | |
200290f2 NP |
10792 | |
10793 | /* 'properties' is the list of properties that we read. Usually a | |
10794 | single one, but maybe more (eg, in "@property int a, b, c;" there | |
10795 | are three). */ | |
f614132b NP |
10796 | tree properties; |
10797 | location_t loc; | |
200290f2 | 10798 | |
f614132b NP |
10799 | loc = c_parser_peek_token (parser)->location; |
10800 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY)); | |
668ea4b1 | 10801 | |
f614132b | 10802 | c_parser_consume_token (parser); /* Eat '@property'. */ |
668ea4b1 | 10803 | |
f614132b NP |
10804 | /* Parse the optional attribute list... */ |
10805 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
668ea4b1 | 10806 | { |
32129a17 DM |
10807 | matching_parens parens; |
10808 | ||
f614132b | 10809 | /* Eat the '(' */ |
32129a17 DM |
10810 | parens.consume_open (parser); |
10811 | ||
f614132b NP |
10812 | /* Property attribute keywords are valid now. */ |
10813 | parser->objc_property_attr_context = true; | |
10814 | ||
10815 | while (true) | |
668ea4b1 | 10816 | { |
f614132b NP |
10817 | bool syntax_error = false; |
10818 | c_token *token = c_parser_peek_token (parser); | |
10819 | enum rid keyword; | |
10820 | ||
10821 | if (token->type != CPP_KEYWORD) | |
10822 | { | |
10823 | if (token->type == CPP_CLOSE_PAREN) | |
10824 | c_parser_error (parser, "expected identifier"); | |
10825 | else | |
10826 | { | |
10827 | c_parser_consume_token (parser); | |
10828 | c_parser_error (parser, "unknown property attribute"); | |
10829 | } | |
10830 | break; | |
10831 | } | |
10832 | keyword = token->keyword; | |
200290f2 | 10833 | c_parser_consume_token (parser); |
f614132b NP |
10834 | switch (keyword) |
10835 | { | |
200290f2 | 10836 | case RID_ASSIGN: property_assign = true; break; |
200290f2 NP |
10837 | case RID_COPY: property_copy = true; break; |
10838 | case RID_NONATOMIC: property_nonatomic = true; break; | |
10839 | case RID_READONLY: property_readonly = true; break; | |
10840 | case RID_READWRITE: property_readwrite = true; break; | |
10841 | case RID_RETAIN: property_retain = true; break; | |
10842 | ||
f614132b NP |
10843 | case RID_GETTER: |
10844 | case RID_SETTER: | |
f614132b NP |
10845 | if (c_parser_next_token_is_not (parser, CPP_EQ)) |
10846 | { | |
d853ee42 NP |
10847 | if (keyword == RID_GETTER) |
10848 | c_parser_error (parser, | |
10849 | "missing %<=%> (after %<getter%> attribute)"); | |
10850 | else | |
10851 | c_parser_error (parser, | |
10852 | "missing %<=%> (after %<setter%> attribute)"); | |
f614132b NP |
10853 | syntax_error = true; |
10854 | break; | |
10855 | } | |
10856 | c_parser_consume_token (parser); /* eat the = */ | |
10857 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
10858 | { | |
10859 | c_parser_error (parser, "expected identifier"); | |
10860 | syntax_error = true; | |
10861 | break; | |
10862 | } | |
f614132b NP |
10863 | if (keyword == RID_SETTER) |
10864 | { | |
200290f2 NP |
10865 | if (property_setter_ident != NULL_TREE) |
10866 | c_parser_error (parser, "the %<setter%> attribute may only be specified once"); | |
10867 | else | |
10868 | property_setter_ident = c_parser_peek_token (parser)->value; | |
f614132b | 10869 | c_parser_consume_token (parser); |
200290f2 NP |
10870 | if (c_parser_next_token_is_not (parser, CPP_COLON)) |
10871 | c_parser_error (parser, "setter name must terminate with %<:%>"); | |
10872 | else | |
10873 | c_parser_consume_token (parser); | |
f614132b | 10874 | } |
46a88c12 | 10875 | else |
f614132b | 10876 | { |
200290f2 NP |
10877 | if (property_getter_ident != NULL_TREE) |
10878 | c_parser_error (parser, "the %<getter%> attribute may only be specified once"); | |
10879 | else | |
10880 | property_getter_ident = c_parser_peek_token (parser)->value; | |
f614132b | 10881 | c_parser_consume_token (parser); |
f614132b | 10882 | } |
200290f2 NP |
10883 | break; |
10884 | default: | |
10885 | c_parser_error (parser, "unknown property attribute"); | |
f614132b NP |
10886 | syntax_error = true; |
10887 | break; | |
10888 | } | |
10889 | ||
10890 | if (syntax_error) | |
668ea4b1 | 10891 | break; |
f614132b NP |
10892 | |
10893 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
668ea4b1 | 10894 | c_parser_consume_token (parser); |
f614132b | 10895 | else |
668ea4b1 IS |
10896 | break; |
10897 | } | |
f614132b | 10898 | parser->objc_property_attr_context = false; |
32129a17 | 10899 | parens.skip_until_found_close (parser); |
f614132b NP |
10900 | } |
10901 | /* ... and the property declaration(s). */ | |
10902 | properties = c_parser_struct_declaration (parser); | |
668ea4b1 | 10903 | |
f614132b NP |
10904 | if (properties == error_mark_node) |
10905 | { | |
10906 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
10907 | parser->error = false; | |
10908 | return; | |
10909 | } | |
668ea4b1 | 10910 | |
f614132b NP |
10911 | if (properties == NULL_TREE) |
10912 | c_parser_error (parser, "expected identifier"); | |
10913 | else | |
10914 | { | |
10915 | /* Comma-separated properties are chained together in | |
10916 | reverse order; add them one by one. */ | |
10917 | properties = nreverse (properties); | |
10918 | ||
10919 | for (; properties; properties = TREE_CHAIN (properties)) | |
200290f2 NP |
10920 | objc_add_property_declaration (loc, copy_node (properties), |
10921 | property_readonly, property_readwrite, | |
10922 | property_assign, property_retain, | |
10923 | property_copy, property_nonatomic, | |
46a88c12 | 10924 | property_getter_ident, property_setter_ident); |
f614132b | 10925 | } |
668ea4b1 IS |
10926 | |
10927 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
f614132b | 10928 | parser->error = false; |
668ea4b1 IS |
10929 | } |
10930 | ||
da57d1b9 NP |
10931 | /* Parse an Objective-C @synthesize declaration. The syntax is: |
10932 | ||
10933 | objc-synthesize-declaration: | |
10934 | @synthesize objc-synthesize-identifier-list ; | |
10935 | ||
10936 | objc-synthesize-identifier-list: | |
10937 | objc-synthesize-identifier | |
10938 | objc-synthesize-identifier-list, objc-synthesize-identifier | |
10939 | ||
10940 | objc-synthesize-identifier | |
10941 | identifier | |
10942 | identifier = identifier | |
10943 | ||
10944 | For example: | |
10945 | @synthesize MyProperty; | |
10946 | @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty; | |
10947 | ||
10948 | PS: This function is identical to cp_parser_objc_at_synthesize_declaration | |
10949 | for C++. Keep them in sync. | |
10950 | */ | |
10951 | static void | |
10952 | c_parser_objc_at_synthesize_declaration (c_parser *parser) | |
10953 | { | |
10954 | tree list = NULL_TREE; | |
10955 | location_t loc; | |
10956 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE)); | |
10957 | loc = c_parser_peek_token (parser)->location; | |
10958 | ||
10959 | c_parser_consume_token (parser); | |
10960 | while (true) | |
10961 | { | |
10962 | tree property, ivar; | |
10963 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
10964 | { | |
10965 | c_parser_error (parser, "expected identifier"); | |
10966 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
10967 | /* Once we find the semicolon, we can resume normal parsing. | |
10968 | We have to reset parser->error manually because | |
10969 | c_parser_skip_until_found() won't reset it for us if the | |
10970 | next token is precisely a semicolon. */ | |
10971 | parser->error = false; | |
10972 | return; | |
10973 | } | |
10974 | property = c_parser_peek_token (parser)->value; | |
10975 | c_parser_consume_token (parser); | |
10976 | if (c_parser_next_token_is (parser, CPP_EQ)) | |
10977 | { | |
10978 | c_parser_consume_token (parser); | |
10979 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
10980 | { | |
10981 | c_parser_error (parser, "expected identifier"); | |
10982 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
10983 | parser->error = false; | |
10984 | return; | |
10985 | } | |
10986 | ivar = c_parser_peek_token (parser)->value; | |
10987 | c_parser_consume_token (parser); | |
10988 | } | |
10989 | else | |
10990 | ivar = NULL_TREE; | |
10991 | list = chainon (list, build_tree_list (ivar, property)); | |
10992 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
10993 | c_parser_consume_token (parser); | |
10994 | else | |
10995 | break; | |
10996 | } | |
10997 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
10998 | objc_add_synthesize_declaration (loc, list); | |
10999 | } | |
11000 | ||
11001 | /* Parse an Objective-C @dynamic declaration. The syntax is: | |
11002 | ||
11003 | objc-dynamic-declaration: | |
11004 | @dynamic identifier-list ; | |
11005 | ||
11006 | For example: | |
11007 | @dynamic MyProperty; | |
11008 | @dynamic MyProperty, AnotherProperty; | |
11009 | ||
11010 | PS: This function is identical to cp_parser_objc_at_dynamic_declaration | |
11011 | for C++. Keep them in sync. | |
11012 | */ | |
11013 | static void | |
11014 | c_parser_objc_at_dynamic_declaration (c_parser *parser) | |
11015 | { | |
11016 | tree list = NULL_TREE; | |
11017 | location_t loc; | |
11018 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC)); | |
11019 | loc = c_parser_peek_token (parser)->location; | |
11020 | ||
11021 | c_parser_consume_token (parser); | |
11022 | while (true) | |
11023 | { | |
11024 | tree property; | |
11025 | if (c_parser_next_token_is_not (parser, CPP_NAME)) | |
11026 | { | |
11027 | c_parser_error (parser, "expected identifier"); | |
11028 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); | |
11029 | parser->error = false; | |
11030 | return; | |
11031 | } | |
11032 | property = c_parser_peek_token (parser)->value; | |
11033 | list = chainon (list, build_tree_list (NULL_TREE, property)); | |
11034 | c_parser_consume_token (parser); | |
11035 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
11036 | c_parser_consume_token (parser); | |
11037 | else | |
11038 | break; | |
11039 | } | |
11040 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
11041 | objc_add_dynamic_declaration (loc, list); | |
11042 | } | |
11043 | ||
27bf414c | 11044 | \f |
953ff289 DN |
11045 | /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore |
11046 | should be considered, statements. ALLOW_STMT is true if we're within | |
11047 | the context of a function and such pragmas are to be allowed. Returns | |
11048 | true if we actually parsed such a pragma. */ | |
27bf414c | 11049 | |
bc4071dd | 11050 | static bool |
dda1bf61 | 11051 | c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) |
bc4071dd RH |
11052 | { |
11053 | unsigned int id; | |
a71dbc63 | 11054 | const char *construct = NULL; |
bc4071dd RH |
11055 | |
11056 | id = c_parser_peek_token (parser)->pragma_kind; | |
11057 | gcc_assert (id != PRAGMA_NONE); | |
11058 | ||
11059 | switch (id) | |
11060 | { | |
6e232ba4 JN |
11061 | case PRAGMA_OACC_DECLARE: |
11062 | c_parser_oacc_declare (parser); | |
11063 | return false; | |
11064 | ||
41dbbb37 | 11065 | case PRAGMA_OACC_ENTER_DATA: |
c5af52eb CP |
11066 | if (context != pragma_compound) |
11067 | { | |
a71dbc63 JJ |
11068 | construct = "acc enter data"; |
11069 | in_compound: | |
c5af52eb | 11070 | if (context == pragma_stmt) |
a71dbc63 JJ |
11071 | { |
11072 | error_at (c_parser_peek_token (parser)->location, | |
11073 | "%<#pragma %s%> may only be used in compound " | |
11074 | "statements", construct); | |
11075 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11076 | return false; | |
11077 | } | |
c5af52eb CP |
11078 | goto bad_stmt; |
11079 | } | |
41dbbb37 TS |
11080 | c_parser_oacc_enter_exit_data (parser, true); |
11081 | return false; | |
11082 | ||
11083 | case PRAGMA_OACC_EXIT_DATA: | |
c5af52eb CP |
11084 | if (context != pragma_compound) |
11085 | { | |
a71dbc63 JJ |
11086 | construct = "acc exit data"; |
11087 | goto in_compound; | |
c5af52eb | 11088 | } |
41dbbb37 TS |
11089 | c_parser_oacc_enter_exit_data (parser, false); |
11090 | return false; | |
11091 | ||
3a40d81d | 11092 | case PRAGMA_OACC_ROUTINE: |
ae9281fc TS |
11093 | if (context != pragma_external) |
11094 | { | |
11095 | error_at (c_parser_peek_token (parser)->location, | |
11096 | "%<#pragma acc routine%> must be at file scope"); | |
11097 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11098 | return false; | |
11099 | } | |
3a40d81d NS |
11100 | c_parser_oacc_routine (parser, context); |
11101 | return false; | |
11102 | ||
41dbbb37 TS |
11103 | case PRAGMA_OACC_UPDATE: |
11104 | if (context != pragma_compound) | |
11105 | { | |
a71dbc63 JJ |
11106 | construct = "acc update"; |
11107 | goto in_compound; | |
41dbbb37 TS |
11108 | } |
11109 | c_parser_oacc_update (parser); | |
11110 | return false; | |
11111 | ||
953ff289 DN |
11112 | case PRAGMA_OMP_BARRIER: |
11113 | if (context != pragma_compound) | |
11114 | { | |
a71dbc63 JJ |
11115 | construct = "omp barrier"; |
11116 | goto in_compound; | |
953ff289 DN |
11117 | } |
11118 | c_parser_omp_barrier (parser); | |
11119 | return false; | |
11120 | ||
11121 | case PRAGMA_OMP_FLUSH: | |
11122 | if (context != pragma_compound) | |
11123 | { | |
a71dbc63 JJ |
11124 | construct = "omp flush"; |
11125 | goto in_compound; | |
953ff289 DN |
11126 | } |
11127 | c_parser_omp_flush (parser); | |
11128 | return false; | |
11129 | ||
a68ab351 JJ |
11130 | case PRAGMA_OMP_TASKWAIT: |
11131 | if (context != pragma_compound) | |
11132 | { | |
a71dbc63 JJ |
11133 | construct = "omp taskwait"; |
11134 | goto in_compound; | |
a68ab351 JJ |
11135 | } |
11136 | c_parser_omp_taskwait (parser); | |
11137 | return false; | |
11138 | ||
20906c66 JJ |
11139 | case PRAGMA_OMP_TASKYIELD: |
11140 | if (context != pragma_compound) | |
11141 | { | |
a71dbc63 JJ |
11142 | construct = "omp taskyield"; |
11143 | goto in_compound; | |
20906c66 JJ |
11144 | } |
11145 | c_parser_omp_taskyield (parser); | |
11146 | return false; | |
11147 | ||
acf0174b JJ |
11148 | case PRAGMA_OMP_CANCEL: |
11149 | if (context != pragma_compound) | |
11150 | { | |
a71dbc63 JJ |
11151 | construct = "omp cancel"; |
11152 | goto in_compound; | |
acf0174b JJ |
11153 | } |
11154 | c_parser_omp_cancel (parser); | |
11155 | return false; | |
11156 | ||
11157 | case PRAGMA_OMP_CANCELLATION_POINT: | |
54d19c3b | 11158 | c_parser_omp_cancellation_point (parser, context); |
acf0174b JJ |
11159 | return false; |
11160 | ||
953ff289 DN |
11161 | case PRAGMA_OMP_THREADPRIVATE: |
11162 | c_parser_omp_threadprivate (parser); | |
11163 | return false; | |
11164 | ||
acf0174b | 11165 | case PRAGMA_OMP_TARGET: |
dda1bf61 | 11166 | return c_parser_omp_target (parser, context, if_p); |
acf0174b JJ |
11167 | |
11168 | case PRAGMA_OMP_END_DECLARE_TARGET: | |
11169 | c_parser_omp_end_declare_target (parser); | |
11170 | return false; | |
11171 | ||
953ff289 | 11172 | case PRAGMA_OMP_SECTION: |
3ba09659 AH |
11173 | error_at (c_parser_peek_token (parser)->location, |
11174 | "%<#pragma omp section%> may only be used in " | |
11175 | "%<#pragma omp sections%> construct"); | |
953ff289 DN |
11176 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); |
11177 | return false; | |
11178 | ||
f9d8d994 | 11179 | case PRAGMA_OMP_DECLARE: |
acf0174b JJ |
11180 | c_parser_omp_declare (parser, context); |
11181 | return false; | |
d9a6bd32 JJ |
11182 | |
11183 | case PRAGMA_OMP_ORDERED: | |
dda1bf61 | 11184 | return c_parser_omp_ordered (parser, context, if_p); |
d9a6bd32 | 11185 | |
8170608b TB |
11186 | case PRAGMA_IVDEP: |
11187 | c_parser_consume_pragma (parser); | |
11188 | c_parser_skip_to_pragma_eol (parser); | |
d4af74d4 TB |
11189 | if (!c_parser_next_token_is_keyword (parser, RID_FOR) |
11190 | && !c_parser_next_token_is_keyword (parser, RID_WHILE) | |
11191 | && !c_parser_next_token_is_keyword (parser, RID_DO)) | |
8170608b | 11192 | { |
d4af74d4 | 11193 | c_parser_error (parser, "for, while or do statement expected"); |
8170608b TB |
11194 | return false; |
11195 | } | |
d4af74d4 | 11196 | if (c_parser_next_token_is_keyword (parser, RID_FOR)) |
dda1bf61 | 11197 | c_parser_for_statement (parser, true, if_p); |
d4af74d4 | 11198 | else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) |
dda1bf61 | 11199 | c_parser_while_statement (parser, true, if_p); |
d4af74d4 TB |
11200 | else |
11201 | c_parser_do_statement (parser, true); | |
8170608b | 11202 | return false; |
acf0174b | 11203 | |
bc4071dd RH |
11204 | case PRAGMA_GCC_PCH_PREPROCESS: |
11205 | c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first"); | |
11206 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11207 | return false; | |
11208 | ||
c02065fc AH |
11209 | case PRAGMA_CILK_SIMD: |
11210 | if (!c_parser_cilk_verify_simd (parser, context)) | |
11211 | return false; | |
11212 | c_parser_consume_pragma (parser); | |
dda1bf61 | 11213 | c_parser_cilk_simd (parser, if_p); |
c02065fc | 11214 | return false; |
9a771876 JJ |
11215 | case PRAGMA_CILK_GRAINSIZE: |
11216 | if (!flag_cilkplus) | |
11217 | { | |
11218 | warning (0, "%<#pragma grainsize%> ignored because -fcilkplus is not" | |
11219 | " enabled"); | |
11220 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11221 | return false; | |
11222 | } | |
11223 | if (context == pragma_external) | |
11224 | { | |
11225 | error_at (c_parser_peek_token (parser)->location, | |
11226 | "%<#pragma grainsize%> must be inside a function"); | |
11227 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11228 | return false; | |
11229 | } | |
dda1bf61 | 11230 | c_parser_cilk_grainsize (parser, if_p); |
9a771876 | 11231 | return false; |
c02065fc | 11232 | |
c5af52eb CP |
11233 | case PRAGMA_OACC_WAIT: |
11234 | if (context != pragma_compound) | |
11235 | { | |
a71dbc63 JJ |
11236 | construct = "acc wait"; |
11237 | goto in_compound; | |
c5af52eb CP |
11238 | } |
11239 | /* FALL THROUGH. */ | |
11240 | ||
bc4071dd | 11241 | default: |
953ff289 DN |
11242 | if (id < PRAGMA_FIRST_EXTERNAL) |
11243 | { | |
acf0174b | 11244 | if (context != pragma_stmt && context != pragma_compound) |
953ff289 DN |
11245 | { |
11246 | bad_stmt: | |
11247 | c_parser_error (parser, "expected declaration specifiers"); | |
11248 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
11249 | return false; | |
11250 | } | |
dda1bf61 | 11251 | c_parser_omp_construct (parser, if_p); |
953ff289 DN |
11252 | return true; |
11253 | } | |
bc4071dd RH |
11254 | break; |
11255 | } | |
11256 | ||
11257 | c_parser_consume_pragma (parser); | |
11258 | c_invoke_pragma_handler (id); | |
27bf414c | 11259 | |
b8698a0f | 11260 | /* Skip to EOL, but suppress any error message. Those will have been |
bc4071dd RH |
11261 | generated by the handler routine through calling error, as opposed |
11262 | to calling c_parser_error. */ | |
11263 | parser->error = true; | |
11264 | c_parser_skip_to_pragma_eol (parser); | |
11265 | ||
11266 | return false; | |
11267 | } | |
11268 | ||
11269 | /* The interface the pragma parsers have to the lexer. */ | |
11270 | ||
11271 | enum cpp_ttype | |
c4914de6 | 11272 | pragma_lex (tree *value, location_t *loc) |
bc4071dd RH |
11273 | { |
11274 | c_token *tok = c_parser_peek_token (the_parser); | |
11275 | enum cpp_ttype ret = tok->type; | |
11276 | ||
11277 | *value = tok->value; | |
c4914de6 MLI |
11278 | if (loc) |
11279 | *loc = tok->location; | |
11280 | ||
bc4071dd RH |
11281 | if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF) |
11282 | ret = CPP_EOF; | |
11283 | else | |
11284 | { | |
11285 | if (ret == CPP_KEYWORD) | |
11286 | ret = CPP_NAME; | |
11287 | c_parser_consume_token (the_parser); | |
11288 | } | |
11289 | ||
11290 | return ret; | |
11291 | } | |
11292 | ||
11293 | static void | |
11294 | c_parser_pragma_pch_preprocess (c_parser *parser) | |
11295 | { | |
11296 | tree name = NULL; | |
11297 | ||
11298 | c_parser_consume_pragma (parser); | |
11299 | if (c_parser_next_token_is (parser, CPP_STRING)) | |
11300 | { | |
11301 | name = c_parser_peek_token (parser)->value; | |
11302 | c_parser_consume_token (parser); | |
11303 | } | |
11304 | else | |
11305 | c_parser_error (parser, "expected string literal"); | |
11306 | c_parser_skip_to_pragma_eol (parser); | |
11307 | ||
11308 | if (name) | |
11309 | c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name)); | |
11310 | } | |
953ff289 | 11311 | \f |
41dbbb37 | 11312 | /* OpenACC and OpenMP parsing routines. */ |
953ff289 DN |
11313 | |
11314 | /* Returns name of the next clause. | |
11315 | If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and | |
11316 | the token is not consumed. Otherwise appropriate pragma_omp_clause is | |
11317 | returned and the token is consumed. */ | |
11318 | ||
11319 | static pragma_omp_clause | |
11320 | c_parser_omp_clause_name (c_parser *parser) | |
11321 | { | |
11322 | pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE; | |
11323 | ||
41dbbb37 TS |
11324 | if (c_parser_next_token_is_keyword (parser, RID_AUTO)) |
11325 | result = PRAGMA_OACC_CLAUSE_AUTO; | |
11326 | else if (c_parser_next_token_is_keyword (parser, RID_IF)) | |
953ff289 DN |
11327 | result = PRAGMA_OMP_CLAUSE_IF; |
11328 | else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)) | |
11329 | result = PRAGMA_OMP_CLAUSE_DEFAULT; | |
acf0174b JJ |
11330 | else if (c_parser_next_token_is_keyword (parser, RID_FOR)) |
11331 | result = PRAGMA_OMP_CLAUSE_FOR; | |
953ff289 DN |
11332 | else if (c_parser_next_token_is (parser, CPP_NAME)) |
11333 | { | |
11334 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
11335 | ||
11336 | switch (p[0]) | |
11337 | { | |
acf0174b JJ |
11338 | case 'a': |
11339 | if (!strcmp ("aligned", p)) | |
11340 | result = PRAGMA_OMP_CLAUSE_ALIGNED; | |
41dbbb37 TS |
11341 | else if (!strcmp ("async", p)) |
11342 | result = PRAGMA_OACC_CLAUSE_ASYNC; | |
acf0174b | 11343 | break; |
953ff289 | 11344 | case 'c': |
a68ab351 JJ |
11345 | if (!strcmp ("collapse", p)) |
11346 | result = PRAGMA_OMP_CLAUSE_COLLAPSE; | |
41dbbb37 TS |
11347 | else if (!strcmp ("copy", p)) |
11348 | result = PRAGMA_OACC_CLAUSE_COPY; | |
a68ab351 | 11349 | else if (!strcmp ("copyin", p)) |
953ff289 | 11350 | result = PRAGMA_OMP_CLAUSE_COPYIN; |
41dbbb37 TS |
11351 | else if (!strcmp ("copyout", p)) |
11352 | result = PRAGMA_OACC_CLAUSE_COPYOUT; | |
953ff289 DN |
11353 | else if (!strcmp ("copyprivate", p)) |
11354 | result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; | |
41dbbb37 TS |
11355 | else if (!strcmp ("create", p)) |
11356 | result = PRAGMA_OACC_CLAUSE_CREATE; | |
953ff289 | 11357 | break; |
acf0174b | 11358 | case 'd': |
d9a6bd32 JJ |
11359 | if (!strcmp ("defaultmap", p)) |
11360 | result = PRAGMA_OMP_CLAUSE_DEFAULTMAP; | |
11361 | else if (!strcmp ("delete", p)) | |
41dbbb37 TS |
11362 | result = PRAGMA_OACC_CLAUSE_DELETE; |
11363 | else if (!strcmp ("depend", p)) | |
acf0174b JJ |
11364 | result = PRAGMA_OMP_CLAUSE_DEPEND; |
11365 | else if (!strcmp ("device", p)) | |
11366 | result = PRAGMA_OMP_CLAUSE_DEVICE; | |
41dbbb37 TS |
11367 | else if (!strcmp ("deviceptr", p)) |
11368 | result = PRAGMA_OACC_CLAUSE_DEVICEPTR; | |
6e232ba4 JN |
11369 | else if (!strcmp ("device_resident", p)) |
11370 | result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT; | |
acf0174b JJ |
11371 | else if (!strcmp ("dist_schedule", p)) |
11372 | result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; | |
11373 | break; | |
953ff289 | 11374 | case 'f': |
20906c66 JJ |
11375 | if (!strcmp ("final", p)) |
11376 | result = PRAGMA_OMP_CLAUSE_FINAL; | |
11377 | else if (!strcmp ("firstprivate", p)) | |
953ff289 | 11378 | result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; |
acf0174b JJ |
11379 | else if (!strcmp ("from", p)) |
11380 | result = PRAGMA_OMP_CLAUSE_FROM; | |
11381 | break; | |
41dbbb37 TS |
11382 | case 'g': |
11383 | if (!strcmp ("gang", p)) | |
11384 | result = PRAGMA_OACC_CLAUSE_GANG; | |
d9a6bd32 JJ |
11385 | else if (!strcmp ("grainsize", p)) |
11386 | result = PRAGMA_OMP_CLAUSE_GRAINSIZE; | |
41dbbb37 TS |
11387 | break; |
11388 | case 'h': | |
d9a6bd32 JJ |
11389 | if (!strcmp ("hint", p)) |
11390 | result = PRAGMA_OMP_CLAUSE_HINT; | |
11391 | else if (!strcmp ("host", p)) | |
41dbbb37 TS |
11392 | result = PRAGMA_OACC_CLAUSE_HOST; |
11393 | break; | |
acf0174b JJ |
11394 | case 'i': |
11395 | if (!strcmp ("inbranch", p)) | |
11396 | result = PRAGMA_OMP_CLAUSE_INBRANCH; | |
7a5e4956 CP |
11397 | else if (!strcmp ("independent", p)) |
11398 | result = PRAGMA_OACC_CLAUSE_INDEPENDENT; | |
d9a6bd32 JJ |
11399 | else if (!strcmp ("is_device_ptr", p)) |
11400 | result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR; | |
953ff289 DN |
11401 | break; |
11402 | case 'l': | |
11403 | if (!strcmp ("lastprivate", p)) | |
11404 | result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; | |
acf0174b JJ |
11405 | else if (!strcmp ("linear", p)) |
11406 | result = PRAGMA_OMP_CLAUSE_LINEAR; | |
d9a6bd32 JJ |
11407 | else if (!strcmp ("link", p)) |
11408 | result = PRAGMA_OMP_CLAUSE_LINK; | |
953ff289 | 11409 | break; |
20906c66 | 11410 | case 'm': |
acf0174b JJ |
11411 | if (!strcmp ("map", p)) |
11412 | result = PRAGMA_OMP_CLAUSE_MAP; | |
11413 | else if (!strcmp ("mergeable", p)) | |
20906c66 | 11414 | result = PRAGMA_OMP_CLAUSE_MERGEABLE; |
b72271b9 | 11415 | else if (flag_cilkplus && !strcmp ("mask", p)) |
41958c28 | 11416 | result = PRAGMA_CILK_CLAUSE_MASK; |
20906c66 | 11417 | break; |
953ff289 | 11418 | case 'n': |
d9a6bd32 JJ |
11419 | if (!strcmp ("nogroup", p)) |
11420 | result = PRAGMA_OMP_CLAUSE_NOGROUP; | |
11421 | else if (!strcmp ("notinbranch", p)) | |
acf0174b JJ |
11422 | result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; |
11423 | else if (!strcmp ("nowait", p)) | |
953ff289 | 11424 | result = PRAGMA_OMP_CLAUSE_NOWAIT; |
41dbbb37 TS |
11425 | else if (!strcmp ("num_gangs", p)) |
11426 | result = PRAGMA_OACC_CLAUSE_NUM_GANGS; | |
d9a6bd32 JJ |
11427 | else if (!strcmp ("num_tasks", p)) |
11428 | result = PRAGMA_OMP_CLAUSE_NUM_TASKS; | |
acf0174b JJ |
11429 | else if (!strcmp ("num_teams", p)) |
11430 | result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; | |
953ff289 DN |
11431 | else if (!strcmp ("num_threads", p)) |
11432 | result = PRAGMA_OMP_CLAUSE_NUM_THREADS; | |
41dbbb37 TS |
11433 | else if (!strcmp ("num_workers", p)) |
11434 | result = PRAGMA_OACC_CLAUSE_NUM_WORKERS; | |
b72271b9 | 11435 | else if (flag_cilkplus && !strcmp ("nomask", p)) |
41958c28 | 11436 | result = PRAGMA_CILK_CLAUSE_NOMASK; |
953ff289 DN |
11437 | break; |
11438 | case 'o': | |
11439 | if (!strcmp ("ordered", p)) | |
11440 | result = PRAGMA_OMP_CLAUSE_ORDERED; | |
11441 | break; | |
11442 | case 'p': | |
acf0174b JJ |
11443 | if (!strcmp ("parallel", p)) |
11444 | result = PRAGMA_OMP_CLAUSE_PARALLEL; | |
41dbbb37 TS |
11445 | else if (!strcmp ("present", p)) |
11446 | result = PRAGMA_OACC_CLAUSE_PRESENT; | |
11447 | else if (!strcmp ("present_or_copy", p) | |
11448 | || !strcmp ("pcopy", p)) | |
11449 | result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY; | |
11450 | else if (!strcmp ("present_or_copyin", p) | |
11451 | || !strcmp ("pcopyin", p)) | |
11452 | result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN; | |
11453 | else if (!strcmp ("present_or_copyout", p) | |
11454 | || !strcmp ("pcopyout", p)) | |
11455 | result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT; | |
11456 | else if (!strcmp ("present_or_create", p) | |
11457 | || !strcmp ("pcreate", p)) | |
11458 | result = PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE; | |
d9a6bd32 JJ |
11459 | else if (!strcmp ("priority", p)) |
11460 | result = PRAGMA_OMP_CLAUSE_PRIORITY; | |
acf0174b | 11461 | else if (!strcmp ("private", p)) |
953ff289 | 11462 | result = PRAGMA_OMP_CLAUSE_PRIVATE; |
acf0174b JJ |
11463 | else if (!strcmp ("proc_bind", p)) |
11464 | result = PRAGMA_OMP_CLAUSE_PROC_BIND; | |
953ff289 DN |
11465 | break; |
11466 | case 'r': | |
11467 | if (!strcmp ("reduction", p)) | |
11468 | result = PRAGMA_OMP_CLAUSE_REDUCTION; | |
11469 | break; | |
11470 | case 's': | |
acf0174b JJ |
11471 | if (!strcmp ("safelen", p)) |
11472 | result = PRAGMA_OMP_CLAUSE_SAFELEN; | |
11473 | else if (!strcmp ("schedule", p)) | |
953ff289 | 11474 | result = PRAGMA_OMP_CLAUSE_SCHEDULE; |
acf0174b JJ |
11475 | else if (!strcmp ("sections", p)) |
11476 | result = PRAGMA_OMP_CLAUSE_SECTIONS; | |
41dbbb37 TS |
11477 | else if (!strcmp ("seq", p)) |
11478 | result = PRAGMA_OACC_CLAUSE_SEQ; | |
953ff289 DN |
11479 | else if (!strcmp ("shared", p)) |
11480 | result = PRAGMA_OMP_CLAUSE_SHARED; | |
d9a6bd32 JJ |
11481 | else if (!strcmp ("simd", p)) |
11482 | result = PRAGMA_OMP_CLAUSE_SIMD; | |
acf0174b JJ |
11483 | else if (!strcmp ("simdlen", p)) |
11484 | result = PRAGMA_OMP_CLAUSE_SIMDLEN; | |
41dbbb37 TS |
11485 | else if (!strcmp ("self", p)) |
11486 | result = PRAGMA_OACC_CLAUSE_SELF; | |
acf0174b JJ |
11487 | break; |
11488 | case 't': | |
11489 | if (!strcmp ("taskgroup", p)) | |
11490 | result = PRAGMA_OMP_CLAUSE_TASKGROUP; | |
11491 | else if (!strcmp ("thread_limit", p)) | |
11492 | result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT; | |
d9a6bd32 JJ |
11493 | else if (!strcmp ("threads", p)) |
11494 | result = PRAGMA_OMP_CLAUSE_THREADS; | |
7a5e4956 CP |
11495 | else if (!strcmp ("tile", p)) |
11496 | result = PRAGMA_OACC_CLAUSE_TILE; | |
acf0174b JJ |
11497 | else if (!strcmp ("to", p)) |
11498 | result = PRAGMA_OMP_CLAUSE_TO; | |
953ff289 | 11499 | break; |
a68ab351 | 11500 | case 'u': |
acf0174b JJ |
11501 | if (!strcmp ("uniform", p)) |
11502 | result = PRAGMA_OMP_CLAUSE_UNIFORM; | |
11503 | else if (!strcmp ("untied", p)) | |
a68ab351 | 11504 | result = PRAGMA_OMP_CLAUSE_UNTIED; |
37d5ad46 JB |
11505 | else if (!strcmp ("use_device", p)) |
11506 | result = PRAGMA_OACC_CLAUSE_USE_DEVICE; | |
ff7a55bf TS |
11507 | else if (!strcmp ("use_device_ptr", p)) |
11508 | result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR; | |
a68ab351 | 11509 | break; |
41958c28 | 11510 | case 'v': |
41dbbb37 TS |
11511 | if (!strcmp ("vector", p)) |
11512 | result = PRAGMA_OACC_CLAUSE_VECTOR; | |
11513 | else if (!strcmp ("vector_length", p)) | |
11514 | result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH; | |
11515 | else if (flag_cilkplus && !strcmp ("vectorlength", p)) | |
41958c28 BI |
11516 | result = PRAGMA_CILK_CLAUSE_VECTORLENGTH; |
11517 | break; | |
41dbbb37 TS |
11518 | case 'w': |
11519 | if (!strcmp ("wait", p)) | |
11520 | result = PRAGMA_OACC_CLAUSE_WAIT; | |
11521 | else if (!strcmp ("worker", p)) | |
11522 | result = PRAGMA_OACC_CLAUSE_WORKER; | |
11523 | break; | |
953ff289 DN |
11524 | } |
11525 | } | |
11526 | ||
11527 | if (result != PRAGMA_OMP_CLAUSE_NONE) | |
11528 | c_parser_consume_token (parser); | |
11529 | ||
11530 | return result; | |
11531 | } | |
11532 | ||
11533 | /* Validate that a clause of the given type does not already exist. */ | |
11534 | ||
11535 | static void | |
d75d71e0 ILT |
11536 | check_no_duplicate_clause (tree clauses, enum omp_clause_code code, |
11537 | const char *name) | |
953ff289 DN |
11538 | { |
11539 | tree c; | |
11540 | ||
11541 | for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) | |
aaf46ef9 | 11542 | if (OMP_CLAUSE_CODE (c) == code) |
953ff289 | 11543 | { |
c2255bc4 AH |
11544 | location_t loc = OMP_CLAUSE_LOCATION (c); |
11545 | error_at (loc, "too many %qs clauses", name); | |
953ff289 DN |
11546 | break; |
11547 | } | |
11548 | } | |
11549 | ||
41dbbb37 TS |
11550 | /* OpenACC 2.0 |
11551 | Parse wait clause or wait directive parameters. */ | |
11552 | ||
11553 | static tree | |
11554 | c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) | |
11555 | { | |
11556 | vec<tree, va_gc> *args; | |
11557 | tree t, args_tree; | |
11558 | ||
32129a17 DM |
11559 | matching_parens parens; |
11560 | if (!parens.require_open (parser)) | |
41dbbb37 TS |
11561 | return list; |
11562 | ||
11563 | args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL); | |
11564 | ||
11565 | if (args->length () == 0) | |
11566 | { | |
11567 | c_parser_error (parser, "expected integer expression before ')'"); | |
11568 | release_tree_vector (args); | |
11569 | return list; | |
11570 | } | |
11571 | ||
11572 | args_tree = build_tree_list_vec (args); | |
11573 | ||
11574 | for (t = args_tree; t; t = TREE_CHAIN (t)) | |
11575 | { | |
11576 | tree targ = TREE_VALUE (t); | |
11577 | ||
11578 | if (targ != error_mark_node) | |
11579 | { | |
11580 | if (!INTEGRAL_TYPE_P (TREE_TYPE (targ))) | |
11581 | { | |
11582 | c_parser_error (parser, "expression must be integral"); | |
11583 | targ = error_mark_node; | |
11584 | } | |
11585 | else | |
11586 | { | |
11587 | tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT); | |
11588 | ||
11589 | OMP_CLAUSE_DECL (c) = targ; | |
11590 | OMP_CLAUSE_CHAIN (c) = list; | |
11591 | list = c; | |
11592 | } | |
11593 | } | |
11594 | } | |
11595 | ||
11596 | release_tree_vector (args); | |
32129a17 | 11597 | parens.require_close (parser); |
41dbbb37 TS |
11598 | return list; |
11599 | } | |
11600 | ||
11601 | /* OpenACC 2.0, OpenMP 2.5: | |
953ff289 DN |
11602 | variable-list: |
11603 | identifier | |
11604 | variable-list , identifier | |
11605 | ||
c2255bc4 AH |
11606 | If KIND is nonzero, create the appropriate node and install the |
11607 | decl in OMP_CLAUSE_DECL and add the node to the head of the list. | |
11608 | If KIND is nonzero, CLAUSE_LOC is the location of the clause. | |
953ff289 DN |
11609 | |
11610 | If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; | |
11611 | return the list created. */ | |
11612 | ||
11613 | static tree | |
c2255bc4 AH |
11614 | c_parser_omp_variable_list (c_parser *parser, |
11615 | location_t clause_loc, | |
acf0174b | 11616 | enum omp_clause_code kind, tree list) |
953ff289 DN |
11617 | { |
11618 | if (c_parser_next_token_is_not (parser, CPP_NAME) | |
11619 | || c_parser_peek_token (parser)->id_kind != C_ID_ID) | |
11620 | c_parser_error (parser, "expected identifier"); | |
11621 | ||
11622 | while (c_parser_next_token_is (parser, CPP_NAME) | |
11623 | && c_parser_peek_token (parser)->id_kind == C_ID_ID) | |
11624 | { | |
11625 | tree t = lookup_name (c_parser_peek_token (parser)->value); | |
11626 | ||
11627 | if (t == NULL_TREE) | |
acf0174b JJ |
11628 | { |
11629 | undeclared_variable (c_parser_peek_token (parser)->location, | |
11630 | c_parser_peek_token (parser)->value); | |
11631 | t = error_mark_node; | |
11632 | } | |
11633 | ||
11634 | c_parser_consume_token (parser); | |
11635 | ||
11636 | if (t == error_mark_node) | |
953ff289 DN |
11637 | ; |
11638 | else if (kind != 0) | |
11639 | { | |
acf0174b JJ |
11640 | switch (kind) |
11641 | { | |
41dbbb37 | 11642 | case OMP_CLAUSE__CACHE_: |
4b1ffdb1 TS |
11643 | /* The OpenACC cache directive explicitly only allows "array |
11644 | elements or subarrays". */ | |
41dbbb37 TS |
11645 | if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE) |
11646 | { | |
11647 | c_parser_error (parser, "expected %<[%>"); | |
11648 | t = error_mark_node; | |
11649 | break; | |
11650 | } | |
d9a6bd32 | 11651 | /* FALLTHROUGH */ |
acf0174b JJ |
11652 | case OMP_CLAUSE_MAP: |
11653 | case OMP_CLAUSE_FROM: | |
11654 | case OMP_CLAUSE_TO: | |
d9a6bd32 JJ |
11655 | while (c_parser_next_token_is (parser, CPP_DOT)) |
11656 | { | |
11657 | location_t op_loc = c_parser_peek_token (parser)->location; | |
11658 | c_parser_consume_token (parser); | |
11659 | if (!c_parser_next_token_is (parser, CPP_NAME)) | |
11660 | { | |
11661 | c_parser_error (parser, "expected identifier"); | |
11662 | t = error_mark_node; | |
11663 | break; | |
11664 | } | |
6ffd47b7 DM |
11665 | |
11666 | c_token *comp_tok = c_parser_peek_token (parser); | |
11667 | tree ident = comp_tok->value; | |
11668 | location_t comp_loc = comp_tok->location; | |
d9a6bd32 | 11669 | c_parser_consume_token (parser); |
6ffd47b7 | 11670 | t = build_component_ref (op_loc, t, ident, comp_loc); |
d9a6bd32 JJ |
11671 | } |
11672 | /* FALLTHROUGH */ | |
acf0174b | 11673 | case OMP_CLAUSE_DEPEND: |
d9a6bd32 | 11674 | case OMP_CLAUSE_REDUCTION: |
acf0174b JJ |
11675 | while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) |
11676 | { | |
11677 | tree low_bound = NULL_TREE, length = NULL_TREE; | |
11678 | ||
11679 | c_parser_consume_token (parser); | |
11680 | if (!c_parser_next_token_is (parser, CPP_COLON)) | |
d90c0a59 | 11681 | { |
9dc5773f JJ |
11682 | location_t expr_loc |
11683 | = c_parser_peek_token (parser)->location; | |
11684 | c_expr expr = c_parser_expression (parser); | |
11685 | expr = convert_lvalue_to_rvalue (expr_loc, expr, | |
11686 | false, true); | |
11687 | low_bound = expr.value; | |
d90c0a59 | 11688 | } |
acf0174b JJ |
11689 | if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) |
11690 | length = integer_one_node; | |
11691 | else | |
11692 | { | |
11693 | /* Look for `:'. */ | |
11694 | if (!c_parser_require (parser, CPP_COLON, | |
11695 | "expected %<:%>")) | |
11696 | { | |
11697 | t = error_mark_node; | |
11698 | break; | |
11699 | } | |
11700 | if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) | |
d90c0a59 | 11701 | { |
9dc5773f JJ |
11702 | location_t expr_loc |
11703 | = c_parser_peek_token (parser)->location; | |
11704 | c_expr expr = c_parser_expression (parser); | |
11705 | expr = convert_lvalue_to_rvalue (expr_loc, expr, | |
11706 | false, true); | |
11707 | length = expr.value; | |
d90c0a59 | 11708 | } |
acf0174b JJ |
11709 | } |
11710 | /* Look for the closing `]'. */ | |
11711 | if (!c_parser_require (parser, CPP_CLOSE_SQUARE, | |
11712 | "expected %<]%>")) | |
11713 | { | |
11714 | t = error_mark_node; | |
11715 | break; | |
11716 | } | |
41dbbb37 | 11717 | |
acf0174b JJ |
11718 | t = tree_cons (low_bound, length, t); |
11719 | } | |
11720 | break; | |
11721 | default: | |
11722 | break; | |
11723 | } | |
11724 | ||
11725 | if (t != error_mark_node) | |
11726 | { | |
11727 | tree u = build_omp_clause (clause_loc, kind); | |
11728 | OMP_CLAUSE_DECL (u) = t; | |
11729 | OMP_CLAUSE_CHAIN (u) = list; | |
11730 | list = u; | |
11731 | } | |
953ff289 DN |
11732 | } |
11733 | else | |
11734 | list = tree_cons (t, NULL_TREE, list); | |
11735 | ||
953ff289 DN |
11736 | if (c_parser_next_token_is_not (parser, CPP_COMMA)) |
11737 | break; | |
11738 | ||
11739 | c_parser_consume_token (parser); | |
11740 | } | |
11741 | ||
11742 | return list; | |
11743 | } | |
11744 | ||
11745 | /* Similarly, but expect leading and trailing parenthesis. This is a very | |
41dbbb37 | 11746 | common case for OpenACC and OpenMP clauses. */ |
953ff289 DN |
11747 | |
11748 | static tree | |
d75d71e0 ILT |
11749 | c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, |
11750 | tree list) | |
953ff289 | 11751 | { |
c2255bc4 AH |
11752 | /* The clauses location. */ |
11753 | location_t loc = c_parser_peek_token (parser)->location; | |
11754 | ||
32129a17 DM |
11755 | matching_parens parens; |
11756 | if (parens.require_open (parser)) | |
953ff289 | 11757 | { |
c2255bc4 | 11758 | list = c_parser_omp_variable_list (parser, loc, kind, list); |
32129a17 | 11759 | parens.skip_until_found_close (parser); |
953ff289 DN |
11760 | } |
11761 | return list; | |
11762 | } | |
11763 | ||
41dbbb37 TS |
11764 | /* OpenACC 2.0: |
11765 | copy ( variable-list ) | |
11766 | copyin ( variable-list ) | |
11767 | copyout ( variable-list ) | |
11768 | create ( variable-list ) | |
11769 | delete ( variable-list ) | |
11770 | present ( variable-list ) | |
11771 | present_or_copy ( variable-list ) | |
11772 | pcopy ( variable-list ) | |
11773 | present_or_copyin ( variable-list ) | |
11774 | pcopyin ( variable-list ) | |
11775 | present_or_copyout ( variable-list ) | |
11776 | pcopyout ( variable-list ) | |
11777 | present_or_create ( variable-list ) | |
11778 | pcreate ( variable-list ) */ | |
11779 | ||
11780 | static tree | |
11781 | c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind, | |
11782 | tree list) | |
11783 | { | |
11784 | enum gomp_map_kind kind; | |
11785 | switch (c_kind) | |
11786 | { | |
11787 | case PRAGMA_OACC_CLAUSE_COPY: | |
11788 | kind = GOMP_MAP_FORCE_TOFROM; | |
11789 | break; | |
11790 | case PRAGMA_OACC_CLAUSE_COPYIN: | |
11791 | kind = GOMP_MAP_FORCE_TO; | |
11792 | break; | |
11793 | case PRAGMA_OACC_CLAUSE_COPYOUT: | |
11794 | kind = GOMP_MAP_FORCE_FROM; | |
11795 | break; | |
11796 | case PRAGMA_OACC_CLAUSE_CREATE: | |
11797 | kind = GOMP_MAP_FORCE_ALLOC; | |
11798 | break; | |
11799 | case PRAGMA_OACC_CLAUSE_DELETE: | |
91106e84 | 11800 | kind = GOMP_MAP_DELETE; |
41dbbb37 TS |
11801 | break; |
11802 | case PRAGMA_OACC_CLAUSE_DEVICE: | |
11803 | kind = GOMP_MAP_FORCE_TO; | |
11804 | break; | |
6e232ba4 JN |
11805 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
11806 | kind = GOMP_MAP_DEVICE_RESIDENT; | |
11807 | break; | |
41dbbb37 TS |
11808 | case PRAGMA_OACC_CLAUSE_HOST: |
11809 | case PRAGMA_OACC_CLAUSE_SELF: | |
11810 | kind = GOMP_MAP_FORCE_FROM; | |
11811 | break; | |
6e232ba4 JN |
11812 | case PRAGMA_OACC_CLAUSE_LINK: |
11813 | kind = GOMP_MAP_LINK; | |
11814 | break; | |
41dbbb37 TS |
11815 | case PRAGMA_OACC_CLAUSE_PRESENT: |
11816 | kind = GOMP_MAP_FORCE_PRESENT; | |
11817 | break; | |
11818 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY: | |
11819 | kind = GOMP_MAP_TOFROM; | |
11820 | break; | |
11821 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN: | |
11822 | kind = GOMP_MAP_TO; | |
11823 | break; | |
11824 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT: | |
11825 | kind = GOMP_MAP_FROM; | |
11826 | break; | |
11827 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE: | |
11828 | kind = GOMP_MAP_ALLOC; | |
11829 | break; | |
11830 | default: | |
11831 | gcc_unreachable (); | |
11832 | } | |
11833 | tree nl, c; | |
11834 | nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list); | |
11835 | ||
11836 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) | |
11837 | OMP_CLAUSE_SET_MAP_KIND (c, kind); | |
11838 | ||
11839 | return nl; | |
11840 | } | |
11841 | ||
11842 | /* OpenACC 2.0: | |
11843 | deviceptr ( variable-list ) */ | |
11844 | ||
11845 | static tree | |
11846 | c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list) | |
11847 | { | |
11848 | location_t loc = c_parser_peek_token (parser)->location; | |
11849 | tree vars, t; | |
11850 | ||
11851 | /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic | |
11852 | c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR, | |
11853 | variable-list must only allow for pointer variables. */ | |
11854 | vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); | |
11855 | for (t = vars; t && t; t = TREE_CHAIN (t)) | |
11856 | { | |
11857 | tree v = TREE_PURPOSE (t); | |
11858 | ||
11859 | /* FIXME diagnostics: Ideally we should keep individual | |
11860 | locations for all the variables in the var list to make the | |
11861 | following errors more precise. Perhaps | |
11862 | c_parser_omp_var_list_parens() should construct a list of | |
11863 | locations to go along with the var list. */ | |
11864 | ||
ba539195 | 11865 | if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL) |
41dbbb37 TS |
11866 | error_at (loc, "%qD is not a variable", v); |
11867 | else if (TREE_TYPE (v) == error_mark_node) | |
11868 | ; | |
11869 | else if (!POINTER_TYPE_P (TREE_TYPE (v))) | |
11870 | error_at (loc, "%qD is not a pointer variable", v); | |
11871 | ||
11872 | tree u = build_omp_clause (loc, OMP_CLAUSE_MAP); | |
11873 | OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR); | |
11874 | OMP_CLAUSE_DECL (u) = v; | |
11875 | OMP_CLAUSE_CHAIN (u) = list; | |
11876 | list = u; | |
11877 | } | |
11878 | ||
11879 | return list; | |
11880 | } | |
11881 | ||
11882 | /* OpenACC 2.0, OpenMP 3.0: | |
a68ab351 JJ |
11883 | collapse ( constant-expression ) */ |
11884 | ||
11885 | static tree | |
11886 | c_parser_omp_clause_collapse (c_parser *parser, tree list) | |
11887 | { | |
11888 | tree c, num = error_mark_node; | |
11889 | HOST_WIDE_INT n; | |
11890 | location_t loc; | |
11891 | ||
11892 | check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse"); | |
02889d23 | 11893 | check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile"); |
a68ab351 JJ |
11894 | |
11895 | loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
11896 | matching_parens parens; |
11897 | if (parens.require_open (parser)) | |
a68ab351 JJ |
11898 | { |
11899 | num = c_parser_expr_no_commas (parser, NULL).value; | |
32129a17 | 11900 | parens.skip_until_found_close (parser); |
a68ab351 JJ |
11901 | } |
11902 | if (num == error_mark_node) | |
11903 | return list; | |
acf0174b JJ |
11904 | mark_exp_read (num); |
11905 | num = c_fully_fold (num, false, NULL); | |
a68ab351 | 11906 | if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) |
9541ffee | 11907 | || !tree_fits_shwi_p (num) |
9439e9a1 | 11908 | || (n = tree_to_shwi (num)) <= 0 |
a68ab351 JJ |
11909 | || (int) n != n) |
11910 | { | |
3ba09659 AH |
11911 | error_at (loc, |
11912 | "collapse argument needs positive constant integer expression"); | |
a68ab351 JJ |
11913 | return list; |
11914 | } | |
c2255bc4 | 11915 | c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); |
a68ab351 JJ |
11916 | OMP_CLAUSE_COLLAPSE_EXPR (c) = num; |
11917 | OMP_CLAUSE_CHAIN (c) = list; | |
11918 | return c; | |
11919 | } | |
11920 | ||
953ff289 DN |
11921 | /* OpenMP 2.5: |
11922 | copyin ( variable-list ) */ | |
11923 | ||
11924 | static tree | |
11925 | c_parser_omp_clause_copyin (c_parser *parser, tree list) | |
11926 | { | |
11927 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list); | |
11928 | } | |
11929 | ||
11930 | /* OpenMP 2.5: | |
11931 | copyprivate ( variable-list ) */ | |
11932 | ||
11933 | static tree | |
11934 | c_parser_omp_clause_copyprivate (c_parser *parser, tree list) | |
11935 | { | |
11936 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list); | |
11937 | } | |
11938 | ||
11939 | /* OpenMP 2.5: | |
7fd549d2 | 11940 | default ( none | shared ) |
7a5e4956 | 11941 | |
7fd549d2 TS |
11942 | OpenACC: |
11943 | default ( none | present ) */ | |
953ff289 DN |
11944 | |
11945 | static tree | |
7a5e4956 | 11946 | c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc) |
953ff289 DN |
11947 | { |
11948 | enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
c2255bc4 | 11949 | location_t loc = c_parser_peek_token (parser)->location; |
953ff289 DN |
11950 | tree c; |
11951 | ||
32129a17 DM |
11952 | matching_parens parens; |
11953 | if (!parens.require_open (parser)) | |
953ff289 DN |
11954 | return list; |
11955 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
11956 | { | |
11957 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
11958 | ||
11959 | switch (p[0]) | |
11960 | { | |
11961 | case 'n': | |
11962 | if (strcmp ("none", p) != 0) | |
11963 | goto invalid_kind; | |
11964 | kind = OMP_CLAUSE_DEFAULT_NONE; | |
11965 | break; | |
11966 | ||
7fd549d2 TS |
11967 | case 'p': |
11968 | if (strcmp ("present", p) != 0 || !is_oacc) | |
11969 | goto invalid_kind; | |
11970 | kind = OMP_CLAUSE_DEFAULT_PRESENT; | |
11971 | break; | |
11972 | ||
953ff289 | 11973 | case 's': |
7a5e4956 | 11974 | if (strcmp ("shared", p) != 0 || is_oacc) |
953ff289 DN |
11975 | goto invalid_kind; |
11976 | kind = OMP_CLAUSE_DEFAULT_SHARED; | |
11977 | break; | |
11978 | ||
11979 | default: | |
11980 | goto invalid_kind; | |
11981 | } | |
11982 | ||
11983 | c_parser_consume_token (parser); | |
11984 | } | |
11985 | else | |
11986 | { | |
11987 | invalid_kind: | |
7a5e4956 | 11988 | if (is_oacc) |
7fd549d2 | 11989 | c_parser_error (parser, "expected %<none%> or %<present%>"); |
7a5e4956 CP |
11990 | else |
11991 | c_parser_error (parser, "expected %<none%> or %<shared%>"); | |
953ff289 | 11992 | } |
32129a17 | 11993 | parens.skip_until_found_close (parser); |
953ff289 DN |
11994 | |
11995 | if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) | |
11996 | return list; | |
11997 | ||
11998 | check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default"); | |
c2255bc4 | 11999 | c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT); |
953ff289 DN |
12000 | OMP_CLAUSE_CHAIN (c) = list; |
12001 | OMP_CLAUSE_DEFAULT_KIND (c) = kind; | |
12002 | ||
12003 | return c; | |
12004 | } | |
12005 | ||
12006 | /* OpenMP 2.5: | |
12007 | firstprivate ( variable-list ) */ | |
12008 | ||
12009 | static tree | |
12010 | c_parser_omp_clause_firstprivate (c_parser *parser, tree list) | |
12011 | { | |
12012 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list); | |
12013 | } | |
12014 | ||
20906c66 JJ |
12015 | /* OpenMP 3.1: |
12016 | final ( expression ) */ | |
12017 | ||
12018 | static tree | |
12019 | c_parser_omp_clause_final (c_parser *parser, tree list) | |
12020 | { | |
12021 | location_t loc = c_parser_peek_token (parser)->location; | |
12022 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
12023 | { | |
12024 | tree t = c_parser_paren_condition (parser); | |
12025 | tree c; | |
12026 | ||
12027 | check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final"); | |
12028 | ||
12029 | c = build_omp_clause (loc, OMP_CLAUSE_FINAL); | |
12030 | OMP_CLAUSE_FINAL_EXPR (c) = t; | |
12031 | OMP_CLAUSE_CHAIN (c) = list; | |
12032 | list = c; | |
12033 | } | |
12034 | else | |
12035 | c_parser_error (parser, "expected %<(%>"); | |
12036 | ||
12037 | return list; | |
12038 | } | |
12039 | ||
41dbbb37 | 12040 | /* OpenACC, OpenMP 2.5: |
d9a6bd32 JJ |
12041 | if ( expression ) |
12042 | ||
12043 | OpenMP 4.5: | |
12044 | if ( directive-name-modifier : expression ) | |
12045 | ||
12046 | directive-name-modifier: | |
12047 | parallel | task | taskloop | target data | target | target update | |
12048 | | target enter data | target exit data */ | |
953ff289 DN |
12049 | |
12050 | static tree | |
d9a6bd32 | 12051 | c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) |
953ff289 | 12052 | { |
d9a6bd32 JJ |
12053 | location_t location = c_parser_peek_token (parser)->location; |
12054 | enum tree_code if_modifier = ERROR_MARK; | |
953ff289 | 12055 | |
32129a17 DM |
12056 | matching_parens parens; |
12057 | if (!parens.require_open (parser)) | |
d9a6bd32 | 12058 | return list; |
953ff289 | 12059 | |
d9a6bd32 JJ |
12060 | if (is_omp && c_parser_next_token_is (parser, CPP_NAME)) |
12061 | { | |
12062 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
12063 | int n = 2; | |
12064 | if (strcmp (p, "parallel") == 0) | |
12065 | if_modifier = OMP_PARALLEL; | |
12066 | else if (strcmp (p, "task") == 0) | |
12067 | if_modifier = OMP_TASK; | |
12068 | else if (strcmp (p, "taskloop") == 0) | |
12069 | if_modifier = OMP_TASKLOOP; | |
12070 | else if (strcmp (p, "target") == 0) | |
12071 | { | |
12072 | if_modifier = OMP_TARGET; | |
12073 | if (c_parser_peek_2nd_token (parser)->type == CPP_NAME) | |
12074 | { | |
12075 | p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value); | |
12076 | if (strcmp ("data", p) == 0) | |
12077 | if_modifier = OMP_TARGET_DATA; | |
12078 | else if (strcmp ("update", p) == 0) | |
12079 | if_modifier = OMP_TARGET_UPDATE; | |
12080 | else if (strcmp ("enter", p) == 0) | |
12081 | if_modifier = OMP_TARGET_ENTER_DATA; | |
12082 | else if (strcmp ("exit", p) == 0) | |
12083 | if_modifier = OMP_TARGET_EXIT_DATA; | |
12084 | if (if_modifier != OMP_TARGET) | |
12085 | { | |
12086 | n = 3; | |
12087 | c_parser_consume_token (parser); | |
12088 | } | |
12089 | else | |
12090 | { | |
12091 | location_t loc = c_parser_peek_2nd_token (parser)->location; | |
12092 | error_at (loc, "expected %<data%>, %<update%>, %<enter%> " | |
12093 | "or %<exit%>"); | |
12094 | if_modifier = ERROR_MARK; | |
12095 | } | |
12096 | if (if_modifier == OMP_TARGET_ENTER_DATA | |
12097 | || if_modifier == OMP_TARGET_EXIT_DATA) | |
12098 | { | |
12099 | if (c_parser_peek_2nd_token (parser)->type == CPP_NAME) | |
12100 | { | |
12101 | p = IDENTIFIER_POINTER | |
12102 | (c_parser_peek_2nd_token (parser)->value); | |
12103 | if (strcmp ("data", p) == 0) | |
12104 | n = 4; | |
12105 | } | |
12106 | if (n == 4) | |
12107 | c_parser_consume_token (parser); | |
12108 | else | |
12109 | { | |
12110 | location_t loc | |
12111 | = c_parser_peek_2nd_token (parser)->location; | |
12112 | error_at (loc, "expected %<data%>"); | |
12113 | if_modifier = ERROR_MARK; | |
12114 | } | |
12115 | } | |
12116 | } | |
12117 | } | |
12118 | if (if_modifier != ERROR_MARK) | |
12119 | { | |
12120 | if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
12121 | { | |
12122 | c_parser_consume_token (parser); | |
12123 | c_parser_consume_token (parser); | |
12124 | } | |
12125 | else | |
12126 | { | |
12127 | if (n > 2) | |
12128 | { | |
12129 | location_t loc = c_parser_peek_2nd_token (parser)->location; | |
12130 | error_at (loc, "expected %<:%>"); | |
12131 | } | |
12132 | if_modifier = ERROR_MARK; | |
12133 | } | |
12134 | } | |
953ff289 | 12135 | } |
953ff289 | 12136 | |
d9a6bd32 | 12137 | tree t = c_parser_condition (parser), c; |
32129a17 | 12138 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12139 | |
12140 | for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) | |
12141 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) | |
12142 | { | |
12143 | if (if_modifier != ERROR_MARK | |
12144 | && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) | |
12145 | { | |
12146 | const char *p = NULL; | |
12147 | switch (if_modifier) | |
12148 | { | |
12149 | case OMP_PARALLEL: p = "parallel"; break; | |
12150 | case OMP_TASK: p = "task"; break; | |
12151 | case OMP_TASKLOOP: p = "taskloop"; break; | |
12152 | case OMP_TARGET_DATA: p = "target data"; break; | |
12153 | case OMP_TARGET: p = "target"; break; | |
12154 | case OMP_TARGET_UPDATE: p = "target update"; break; | |
12155 | case OMP_TARGET_ENTER_DATA: p = "enter data"; break; | |
12156 | case OMP_TARGET_EXIT_DATA: p = "exit data"; break; | |
12157 | default: gcc_unreachable (); | |
12158 | } | |
12159 | error_at (location, "too many %<if%> clauses with %qs modifier", | |
12160 | p); | |
12161 | return list; | |
12162 | } | |
12163 | else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) | |
12164 | { | |
12165 | if (!is_omp) | |
12166 | error_at (location, "too many %<if%> clauses"); | |
12167 | else | |
12168 | error_at (location, "too many %<if%> clauses without modifier"); | |
12169 | return list; | |
12170 | } | |
12171 | else if (if_modifier == ERROR_MARK | |
12172 | || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK) | |
12173 | { | |
12174 | error_at (location, "if any %<if%> clause has modifier, then all " | |
12175 | "%<if%> clauses have to use modifier"); | |
12176 | return list; | |
12177 | } | |
12178 | } | |
12179 | ||
12180 | c = build_omp_clause (location, OMP_CLAUSE_IF); | |
12181 | OMP_CLAUSE_IF_MODIFIER (c) = if_modifier; | |
12182 | OMP_CLAUSE_IF_EXPR (c) = t; | |
12183 | OMP_CLAUSE_CHAIN (c) = list; | |
12184 | return c; | |
953ff289 DN |
12185 | } |
12186 | ||
12187 | /* OpenMP 2.5: | |
12188 | lastprivate ( variable-list ) */ | |
12189 | ||
12190 | static tree | |
12191 | c_parser_omp_clause_lastprivate (c_parser *parser, tree list) | |
12192 | { | |
12193 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list); | |
12194 | } | |
12195 | ||
20906c66 JJ |
12196 | /* OpenMP 3.1: |
12197 | mergeable */ | |
12198 | ||
12199 | static tree | |
12200 | c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list) | |
12201 | { | |
12202 | tree c; | |
12203 | ||
12204 | /* FIXME: Should we allow duplicates? */ | |
12205 | check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable"); | |
12206 | ||
12207 | c = build_omp_clause (c_parser_peek_token (parser)->location, | |
12208 | OMP_CLAUSE_MERGEABLE); | |
12209 | OMP_CLAUSE_CHAIN (c) = list; | |
12210 | ||
12211 | return c; | |
12212 | } | |
12213 | ||
953ff289 DN |
12214 | /* OpenMP 2.5: |
12215 | nowait */ | |
12216 | ||
12217 | static tree | |
12218 | c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) | |
12219 | { | |
12220 | tree c; | |
c2255bc4 | 12221 | location_t loc = c_parser_peek_token (parser)->location; |
953ff289 DN |
12222 | |
12223 | check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait"); | |
12224 | ||
c2255bc4 | 12225 | c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); |
953ff289 DN |
12226 | OMP_CLAUSE_CHAIN (c) = list; |
12227 | return c; | |
12228 | } | |
12229 | ||
12230 | /* OpenMP 2.5: | |
12231 | num_threads ( expression ) */ | |
12232 | ||
12233 | static tree | |
12234 | c_parser_omp_clause_num_threads (c_parser *parser, tree list) | |
12235 | { | |
c2255bc4 | 12236 | location_t num_threads_loc = c_parser_peek_token (parser)->location; |
32129a17 DM |
12237 | matching_parens parens; |
12238 | if (parens.require_open (parser)) | |
953ff289 | 12239 | { |
c7412148 | 12240 | location_t expr_loc = c_parser_peek_token (parser)->location; |
9dc5773f JJ |
12241 | c_expr expr = c_parser_expression (parser); |
12242 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12243 | tree c, t = expr.value; | |
928c19bb | 12244 | t = c_fully_fold (t, false, NULL); |
953ff289 | 12245 | |
32129a17 | 12246 | parens.skip_until_found_close (parser); |
953ff289 DN |
12247 | |
12248 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12249 | { | |
12250 | c_parser_error (parser, "expected integer expression"); | |
12251 | return list; | |
12252 | } | |
12253 | ||
12254 | /* Attempt to statically determine when the number isn't positive. */ | |
db3927fb | 12255 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, |
953ff289 | 12256 | build_int_cst (TREE_TYPE (t), 0)); |
21ba0cea | 12257 | protected_set_expr_location (c, expr_loc); |
953ff289 DN |
12258 | if (c == boolean_true_node) |
12259 | { | |
3ba09659 AH |
12260 | warning_at (expr_loc, 0, |
12261 | "%<num_threads%> value must be positive"); | |
953ff289 DN |
12262 | t = integer_one_node; |
12263 | } | |
12264 | ||
12265 | check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads"); | |
12266 | ||
c2255bc4 | 12267 | c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS); |
953ff289 DN |
12268 | OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; |
12269 | OMP_CLAUSE_CHAIN (c) = list; | |
12270 | list = c; | |
12271 | } | |
12272 | ||
12273 | return list; | |
12274 | } | |
12275 | ||
d9a6bd32 JJ |
12276 | /* OpenMP 4.5: |
12277 | num_tasks ( expression ) */ | |
12278 | ||
12279 | static tree | |
12280 | c_parser_omp_clause_num_tasks (c_parser *parser, tree list) | |
12281 | { | |
12282 | location_t num_tasks_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
12283 | matching_parens parens; |
12284 | if (parens.require_open (parser)) | |
d9a6bd32 JJ |
12285 | { |
12286 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
12287 | c_expr expr = c_parser_expression (parser); |
12288 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12289 | tree c, t = expr.value; | |
d9a6bd32 JJ |
12290 | t = c_fully_fold (t, false, NULL); |
12291 | ||
32129a17 | 12292 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12293 | |
12294 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12295 | { | |
12296 | c_parser_error (parser, "expected integer expression"); | |
12297 | return list; | |
12298 | } | |
12299 | ||
12300 | /* Attempt to statically determine when the number isn't positive. */ | |
12301 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, | |
12302 | build_int_cst (TREE_TYPE (t), 0)); | |
12303 | if (CAN_HAVE_LOCATION_P (c)) | |
12304 | SET_EXPR_LOCATION (c, expr_loc); | |
12305 | if (c == boolean_true_node) | |
12306 | { | |
12307 | warning_at (expr_loc, 0, "%<num_tasks%> value must be positive"); | |
12308 | t = integer_one_node; | |
12309 | } | |
12310 | ||
12311 | check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks"); | |
12312 | ||
12313 | c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS); | |
12314 | OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; | |
12315 | OMP_CLAUSE_CHAIN (c) = list; | |
12316 | list = c; | |
12317 | } | |
12318 | ||
12319 | return list; | |
12320 | } | |
12321 | ||
12322 | /* OpenMP 4.5: | |
12323 | grainsize ( expression ) */ | |
12324 | ||
12325 | static tree | |
12326 | c_parser_omp_clause_grainsize (c_parser *parser, tree list) | |
12327 | { | |
12328 | location_t grainsize_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
12329 | matching_parens parens; |
12330 | if (parens.require_open (parser)) | |
d9a6bd32 JJ |
12331 | { |
12332 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
12333 | c_expr expr = c_parser_expression (parser); |
12334 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12335 | tree c, t = expr.value; | |
d9a6bd32 JJ |
12336 | t = c_fully_fold (t, false, NULL); |
12337 | ||
32129a17 | 12338 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12339 | |
12340 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12341 | { | |
12342 | c_parser_error (parser, "expected integer expression"); | |
12343 | return list; | |
12344 | } | |
12345 | ||
12346 | /* Attempt to statically determine when the number isn't positive. */ | |
12347 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, | |
12348 | build_int_cst (TREE_TYPE (t), 0)); | |
12349 | if (CAN_HAVE_LOCATION_P (c)) | |
12350 | SET_EXPR_LOCATION (c, expr_loc); | |
12351 | if (c == boolean_true_node) | |
12352 | { | |
12353 | warning_at (expr_loc, 0, "%<grainsize%> value must be positive"); | |
12354 | t = integer_one_node; | |
12355 | } | |
12356 | ||
12357 | check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize"); | |
12358 | ||
12359 | c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE); | |
12360 | OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; | |
12361 | OMP_CLAUSE_CHAIN (c) = list; | |
12362 | list = c; | |
12363 | } | |
12364 | ||
12365 | return list; | |
12366 | } | |
12367 | ||
12368 | /* OpenMP 4.5: | |
12369 | priority ( expression ) */ | |
12370 | ||
12371 | static tree | |
12372 | c_parser_omp_clause_priority (c_parser *parser, tree list) | |
12373 | { | |
12374 | location_t priority_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
12375 | matching_parens parens; |
12376 | if (parens.require_open (parser)) | |
d9a6bd32 JJ |
12377 | { |
12378 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
12379 | c_expr expr = c_parser_expression (parser); |
12380 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12381 | tree c, t = expr.value; | |
d9a6bd32 JJ |
12382 | t = c_fully_fold (t, false, NULL); |
12383 | ||
32129a17 | 12384 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12385 | |
12386 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12387 | { | |
12388 | c_parser_error (parser, "expected integer expression"); | |
12389 | return list; | |
12390 | } | |
12391 | ||
12392 | /* Attempt to statically determine when the number isn't | |
12393 | non-negative. */ | |
12394 | c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t, | |
12395 | build_int_cst (TREE_TYPE (t), 0)); | |
12396 | if (CAN_HAVE_LOCATION_P (c)) | |
12397 | SET_EXPR_LOCATION (c, expr_loc); | |
12398 | if (c == boolean_true_node) | |
12399 | { | |
12400 | warning_at (expr_loc, 0, "%<priority%> value must be non-negative"); | |
12401 | t = integer_one_node; | |
12402 | } | |
12403 | ||
12404 | check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority"); | |
12405 | ||
12406 | c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY); | |
12407 | OMP_CLAUSE_PRIORITY_EXPR (c) = t; | |
12408 | OMP_CLAUSE_CHAIN (c) = list; | |
12409 | list = c; | |
12410 | } | |
12411 | ||
12412 | return list; | |
12413 | } | |
12414 | ||
12415 | /* OpenMP 4.5: | |
12416 | hint ( expression ) */ | |
12417 | ||
12418 | static tree | |
12419 | c_parser_omp_clause_hint (c_parser *parser, tree list) | |
12420 | { | |
12421 | location_t hint_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
12422 | matching_parens parens; |
12423 | if (parens.require_open (parser)) | |
d9a6bd32 | 12424 | { |
9dc5773f JJ |
12425 | location_t expr_loc = c_parser_peek_token (parser)->location; |
12426 | c_expr expr = c_parser_expression (parser); | |
12427 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12428 | tree c, t = expr.value; | |
d9a6bd32 JJ |
12429 | t = c_fully_fold (t, false, NULL); |
12430 | ||
32129a17 | 12431 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12432 | |
12433 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12434 | { | |
12435 | c_parser_error (parser, "expected integer expression"); | |
12436 | return list; | |
12437 | } | |
12438 | ||
12439 | check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint"); | |
12440 | ||
12441 | c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT); | |
12442 | OMP_CLAUSE_HINT_EXPR (c) = t; | |
12443 | OMP_CLAUSE_CHAIN (c) = list; | |
12444 | list = c; | |
12445 | } | |
12446 | ||
12447 | return list; | |
12448 | } | |
12449 | ||
12450 | /* OpenMP 4.5: | |
12451 | defaultmap ( tofrom : scalar ) */ | |
12452 | ||
12453 | static tree | |
12454 | c_parser_omp_clause_defaultmap (c_parser *parser, tree list) | |
12455 | { | |
12456 | location_t loc = c_parser_peek_token (parser)->location; | |
12457 | tree c; | |
12458 | const char *p; | |
12459 | ||
32129a17 DM |
12460 | matching_parens parens; |
12461 | if (!parens.require_open (parser)) | |
d9a6bd32 JJ |
12462 | return list; |
12463 | if (!c_parser_next_token_is (parser, CPP_NAME)) | |
12464 | { | |
12465 | c_parser_error (parser, "expected %<tofrom%>"); | |
12466 | goto out_err; | |
12467 | } | |
12468 | p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
12469 | if (strcmp (p, "tofrom") != 0) | |
12470 | { | |
12471 | c_parser_error (parser, "expected %<tofrom%>"); | |
12472 | goto out_err; | |
12473 | } | |
12474 | c_parser_consume_token (parser); | |
12475 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
12476 | goto out_err; | |
12477 | if (!c_parser_next_token_is (parser, CPP_NAME)) | |
12478 | { | |
12479 | c_parser_error (parser, "expected %<scalar%>"); | |
12480 | goto out_err; | |
12481 | } | |
12482 | p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
12483 | if (strcmp (p, "scalar") != 0) | |
12484 | { | |
12485 | c_parser_error (parser, "expected %<scalar%>"); | |
12486 | goto out_err; | |
12487 | } | |
12488 | c_parser_consume_token (parser); | |
32129a17 | 12489 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12490 | check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap"); |
12491 | c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP); | |
12492 | OMP_CLAUSE_CHAIN (c) = list; | |
12493 | return c; | |
12494 | ||
12495 | out_err: | |
32129a17 | 12496 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12497 | return list; |
12498 | } | |
12499 | ||
c7b48c8a TS |
12500 | /* OpenACC 2.0: |
12501 | use_device ( variable-list ) | |
12502 | ||
12503 | OpenMP 4.5: | |
d9a6bd32 JJ |
12504 | use_device_ptr ( variable-list ) */ |
12505 | ||
12506 | static tree | |
12507 | c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list) | |
12508 | { | |
12509 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_PTR, | |
12510 | list); | |
12511 | } | |
12512 | ||
12513 | /* OpenMP 4.5: | |
12514 | is_device_ptr ( variable-list ) */ | |
12515 | ||
12516 | static tree | |
12517 | c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list) | |
12518 | { | |
12519 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_IS_DEVICE_PTR, list); | |
12520 | } | |
12521 | ||
41dbbb37 | 12522 | /* OpenACC: |
1e47f02b TS |
12523 | num_gangs ( expression ) |
12524 | num_workers ( expression ) | |
12525 | vector_length ( expression ) */ | |
41dbbb37 TS |
12526 | |
12527 | static tree | |
1e47f02b TS |
12528 | c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code, |
12529 | tree list) | |
41dbbb37 | 12530 | { |
1e47f02b | 12531 | location_t loc = c_parser_peek_token (parser)->location; |
41dbbb37 | 12532 | |
32129a17 DM |
12533 | matching_parens parens; |
12534 | if (!parens.require_open (parser)) | |
1e47f02b | 12535 | return list; |
41dbbb37 | 12536 | |
1e47f02b TS |
12537 | location_t expr_loc = c_parser_peek_token (parser)->location; |
12538 | c_expr expr = c_parser_expression (parser); | |
12539 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
12540 | tree c, t = expr.value; | |
12541 | t = c_fully_fold (t, false, NULL); | |
41dbbb37 | 12542 | |
32129a17 | 12543 | parens.skip_until_found_close (parser); |
41dbbb37 | 12544 | |
1e47f02b TS |
12545 | if (t == error_mark_node) |
12546 | return list; | |
12547 | else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12548 | { | |
12549 | error_at (expr_loc, "%qs expression must be integral", | |
12550 | omp_clause_code_name[code]); | |
12551 | return list; | |
12552 | } | |
41dbbb37 | 12553 | |
1e47f02b TS |
12554 | /* Attempt to statically determine when the number isn't positive. */ |
12555 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, | |
12556 | build_int_cst (TREE_TYPE (t), 0)); | |
12557 | protected_set_expr_location (c, expr_loc); | |
12558 | if (c == boolean_true_node) | |
12559 | { | |
12560 | warning_at (expr_loc, 0, | |
12561 | "%qs value must be positive", | |
12562 | omp_clause_code_name[code]); | |
12563 | t = integer_one_node; | |
41dbbb37 TS |
12564 | } |
12565 | ||
1e47f02b TS |
12566 | check_no_duplicate_clause (list, code, omp_clause_code_name[code]); |
12567 | ||
12568 | c = build_omp_clause (loc, code); | |
12569 | OMP_CLAUSE_OPERAND (c, 0) = t; | |
12570 | OMP_CLAUSE_CHAIN (c) = list; | |
12571 | return c; | |
41dbbb37 TS |
12572 | } |
12573 | ||
765dd391 CP |
12574 | /* OpenACC: |
12575 | ||
12576 | gang [( gang-arg-list )] | |
12577 | worker [( [num:] int-expr )] | |
12578 | vector [( [length:] int-expr )] | |
12579 | ||
12580 | where gang-arg is one of: | |
12581 | ||
12582 | [num:] int-expr | |
12583 | static: size-expr | |
12584 | ||
12585 | and size-expr may be: | |
12586 | ||
12587 | * | |
12588 | int-expr | |
12589 | */ | |
12590 | ||
12591 | static tree | |
12592 | c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind, | |
12593 | const char *str, tree list) | |
12594 | { | |
12595 | const char *id = "num"; | |
12596 | tree ops[2] = { NULL_TREE, NULL_TREE }, c; | |
12597 | location_t loc = c_parser_peek_token (parser)->location; | |
12598 | ||
12599 | if (kind == OMP_CLAUSE_VECTOR) | |
12600 | id = "length"; | |
12601 | ||
12602 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
12603 | { | |
12604 | c_parser_consume_token (parser); | |
12605 | ||
12606 | do | |
12607 | { | |
12608 | c_token *next = c_parser_peek_token (parser); | |
12609 | int idx = 0; | |
12610 | ||
12611 | /* Gang static argument. */ | |
12612 | if (kind == OMP_CLAUSE_GANG | |
12613 | && c_parser_next_token_is_keyword (parser, RID_STATIC)) | |
12614 | { | |
12615 | c_parser_consume_token (parser); | |
12616 | ||
12617 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |
12618 | goto cleanup_error; | |
12619 | ||
12620 | idx = 1; | |
12621 | if (ops[idx] != NULL_TREE) | |
12622 | { | |
12623 | c_parser_error (parser, "too many %<static%> arguments"); | |
12624 | goto cleanup_error; | |
12625 | } | |
12626 | ||
12627 | /* Check for the '*' argument. */ | |
7a5e4956 CP |
12628 | if (c_parser_next_token_is (parser, CPP_MULT) |
12629 | && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA | |
12630 | || c_parser_peek_2nd_token (parser)->type | |
12631 | == CPP_CLOSE_PAREN)) | |
765dd391 CP |
12632 | { |
12633 | c_parser_consume_token (parser); | |
12634 | ops[idx] = integer_minus_one_node; | |
12635 | ||
12636 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
12637 | { | |
12638 | c_parser_consume_token (parser); | |
12639 | continue; | |
12640 | } | |
12641 | else | |
12642 | break; | |
12643 | } | |
12644 | } | |
12645 | /* Worker num: argument and vector length: arguments. */ | |
12646 | else if (c_parser_next_token_is (parser, CPP_NAME) | |
12647 | && strcmp (id, IDENTIFIER_POINTER (next->value)) == 0 | |
12648 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
12649 | { | |
12650 | c_parser_consume_token (parser); /* id */ | |
12651 | c_parser_consume_token (parser); /* ':' */ | |
12652 | } | |
12653 | ||
12654 | /* Now collect the actual argument. */ | |
12655 | if (ops[idx] != NULL_TREE) | |
12656 | { | |
12657 | c_parser_error (parser, "unexpected argument"); | |
12658 | goto cleanup_error; | |
12659 | } | |
12660 | ||
12661 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
12662 | c_expr cexpr = c_parser_expr_no_commas (parser, NULL); |
12663 | cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true); | |
12664 | tree expr = cexpr.value; | |
765dd391 CP |
12665 | if (expr == error_mark_node) |
12666 | goto cleanup_error; | |
12667 | ||
765dd391 CP |
12668 | expr = c_fully_fold (expr, false, NULL); |
12669 | ||
12670 | /* Attempt to statically determine when the number isn't a | |
12671 | positive integer. */ | |
12672 | ||
12673 | if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))) | |
12674 | { | |
12675 | c_parser_error (parser, "expected integer expression"); | |
12676 | return list; | |
12677 | } | |
12678 | ||
12679 | tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr, | |
12680 | build_int_cst (TREE_TYPE (expr), 0)); | |
12681 | if (c == boolean_true_node) | |
12682 | { | |
12683 | warning_at (loc, 0, | |
2f6f187a | 12684 | "%qs value must be positive", str); |
765dd391 CP |
12685 | expr = integer_one_node; |
12686 | } | |
12687 | ||
12688 | ops[idx] = expr; | |
12689 | ||
12690 | if (kind == OMP_CLAUSE_GANG | |
12691 | && c_parser_next_token_is (parser, CPP_COMMA)) | |
12692 | { | |
12693 | c_parser_consume_token (parser); | |
12694 | continue; | |
12695 | } | |
12696 | break; | |
12697 | } | |
12698 | while (1); | |
12699 | ||
12700 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |
12701 | goto cleanup_error; | |
12702 | } | |
12703 | ||
12704 | check_no_duplicate_clause (list, kind, str); | |
12705 | ||
12706 | c = build_omp_clause (loc, kind); | |
12707 | ||
12708 | if (ops[1]) | |
12709 | OMP_CLAUSE_OPERAND (c, 1) = ops[1]; | |
12710 | ||
12711 | OMP_CLAUSE_OPERAND (c, 0) = ops[0]; | |
12712 | OMP_CLAUSE_CHAIN (c) = list; | |
12713 | ||
12714 | return c; | |
12715 | ||
12716 | cleanup_error: | |
12717 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0); | |
12718 | return list; | |
12719 | } | |
12720 | ||
12721 | /* OpenACC: | |
12722 | auto | |
12723 | independent | |
12724 | nohost | |
12725 | seq */ | |
12726 | ||
12727 | static tree | |
12728 | c_parser_oacc_simple_clause (c_parser *parser, enum omp_clause_code code, | |
12729 | tree list) | |
12730 | { | |
12731 | check_no_duplicate_clause (list, code, omp_clause_code_name[code]); | |
12732 | ||
12733 | tree c = build_omp_clause (c_parser_peek_token (parser)->location, code); | |
12734 | OMP_CLAUSE_CHAIN (c) = list; | |
12735 | ||
12736 | return c; | |
12737 | } | |
12738 | ||
41dbbb37 TS |
12739 | /* OpenACC: |
12740 | async [( int-expr )] */ | |
12741 | ||
12742 | static tree | |
12743 | c_parser_oacc_clause_async (c_parser *parser, tree list) | |
12744 | { | |
12745 | tree c, t; | |
12746 | location_t loc = c_parser_peek_token (parser)->location; | |
12747 | ||
12748 | t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL); | |
12749 | ||
12750 | if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN) | |
12751 | { | |
12752 | c_parser_consume_token (parser); | |
12753 | ||
12754 | t = c_parser_expression (parser).value; | |
12755 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
12756 | c_parser_error (parser, "expected integer expression"); | |
12757 | else if (t == error_mark_node | |
12758 | || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |
12759 | return list; | |
12760 | } | |
12761 | else | |
12762 | t = c_fully_fold (t, false, NULL); | |
12763 | ||
12764 | check_no_duplicate_clause (list, OMP_CLAUSE_ASYNC, "async"); | |
12765 | ||
12766 | c = build_omp_clause (loc, OMP_CLAUSE_ASYNC); | |
12767 | OMP_CLAUSE_ASYNC_EXPR (c) = t; | |
12768 | OMP_CLAUSE_CHAIN (c) = list; | |
12769 | list = c; | |
12770 | ||
12771 | return list; | |
12772 | } | |
12773 | ||
7a5e4956 CP |
12774 | /* OpenACC 2.0: |
12775 | tile ( size-expr-list ) */ | |
12776 | ||
12777 | static tree | |
12778 | c_parser_oacc_clause_tile (c_parser *parser, tree list) | |
12779 | { | |
12780 | tree c, expr = error_mark_node; | |
02889d23 | 12781 | location_t loc; |
7a5e4956 CP |
12782 | tree tile = NULL_TREE; |
12783 | ||
12784 | check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile"); | |
02889d23 | 12785 | check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse"); |
7a5e4956 CP |
12786 | |
12787 | loc = c_parser_peek_token (parser)->location; | |
12788 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |
12789 | return list; | |
12790 | ||
12791 | do | |
12792 | { | |
02889d23 CLT |
12793 | if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>")) |
12794 | return list; | |
12795 | ||
7a5e4956 CP |
12796 | if (c_parser_next_token_is (parser, CPP_MULT) |
12797 | && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA | |
12798 | || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN)) | |
12799 | { | |
12800 | c_parser_consume_token (parser); | |
02889d23 | 12801 | expr = integer_zero_node; |
7a5e4956 CP |
12802 | } |
12803 | else | |
12804 | { | |
02889d23 | 12805 | location_t expr_loc = c_parser_peek_token (parser)->location; |
9dc5773f JJ |
12806 | c_expr cexpr = c_parser_expr_no_commas (parser, NULL); |
12807 | cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true); | |
12808 | expr = cexpr.value; | |
7a5e4956 CP |
12809 | |
12810 | if (expr == error_mark_node) | |
12811 | { | |
12812 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
12813 | "expected %<)%>"); | |
12814 | return list; | |
12815 | } | |
12816 | ||
7a5e4956 CP |
12817 | expr = c_fully_fold (expr, false, NULL); |
12818 | ||
02889d23 CLT |
12819 | if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) |
12820 | || !tree_fits_shwi_p (expr) | |
12821 | || tree_to_shwi (expr) <= 0) | |
7a5e4956 | 12822 | { |
02889d23 CLT |
12823 | error_at (expr_loc, "%<tile%> argument needs positive" |
12824 | " integral constant"); | |
12825 | expr = integer_zero_node; | |
7a5e4956 CP |
12826 | } |
12827 | } | |
12828 | ||
12829 | tile = tree_cons (NULL_TREE, expr, tile); | |
7a5e4956 CP |
12830 | } |
12831 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)); | |
12832 | ||
12833 | /* Consume the trailing ')'. */ | |
12834 | c_parser_consume_token (parser); | |
12835 | ||
12836 | c = build_omp_clause (loc, OMP_CLAUSE_TILE); | |
12837 | tile = nreverse (tile); | |
12838 | OMP_CLAUSE_TILE_LIST (c) = tile; | |
12839 | OMP_CLAUSE_CHAIN (c) = list; | |
12840 | return c; | |
12841 | } | |
12842 | ||
41dbbb37 TS |
12843 | /* OpenACC: |
12844 | wait ( int-expr-list ) */ | |
12845 | ||
12846 | static tree | |
12847 | c_parser_oacc_clause_wait (c_parser *parser, tree list) | |
12848 | { | |
12849 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
12850 | ||
12851 | if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN) | |
12852 | list = c_parser_oacc_wait_list (parser, clause_loc, list); | |
12853 | ||
12854 | return list; | |
12855 | } | |
12856 | ||
953ff289 | 12857 | /* OpenMP 2.5: |
d9a6bd32 JJ |
12858 | ordered |
12859 | ||
12860 | OpenMP 4.5: | |
12861 | ordered ( constant-expression ) */ | |
953ff289 DN |
12862 | |
12863 | static tree | |
c2255bc4 | 12864 | c_parser_omp_clause_ordered (c_parser *parser, tree list) |
953ff289 | 12865 | { |
953ff289 DN |
12866 | check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered"); |
12867 | ||
d9a6bd32 JJ |
12868 | tree c, num = NULL_TREE; |
12869 | HOST_WIDE_INT n; | |
12870 | location_t loc = c_parser_peek_token (parser)->location; | |
12871 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
12872 | { | |
32129a17 DM |
12873 | matching_parens parens; |
12874 | parens.consume_open (parser); | |
d9a6bd32 | 12875 | num = c_parser_expr_no_commas (parser, NULL).value; |
32129a17 | 12876 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
12877 | } |
12878 | if (num == error_mark_node) | |
12879 | return list; | |
12880 | if (num) | |
12881 | { | |
12882 | mark_exp_read (num); | |
12883 | num = c_fully_fold (num, false, NULL); | |
12884 | if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) | |
12885 | || !tree_fits_shwi_p (num) | |
12886 | || (n = tree_to_shwi (num)) <= 0 | |
12887 | || (int) n != n) | |
12888 | { | |
12889 | error_at (loc, "ordered argument needs positive " | |
12890 | "constant integer expression"); | |
12891 | return list; | |
12892 | } | |
12893 | } | |
12894 | c = build_omp_clause (loc, OMP_CLAUSE_ORDERED); | |
12895 | OMP_CLAUSE_ORDERED_EXPR (c) = num; | |
953ff289 DN |
12896 | OMP_CLAUSE_CHAIN (c) = list; |
12897 | return c; | |
12898 | } | |
12899 | ||
12900 | /* OpenMP 2.5: | |
12901 | private ( variable-list ) */ | |
12902 | ||
12903 | static tree | |
12904 | c_parser_omp_clause_private (c_parser *parser, tree list) | |
12905 | { | |
12906 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list); | |
12907 | } | |
12908 | ||
12909 | /* OpenMP 2.5: | |
12910 | reduction ( reduction-operator : variable-list ) | |
12911 | ||
12912 | reduction-operator: | |
20906c66 | 12913 | One of: + * - & ^ | && || |
acf0174b | 12914 | |
20906c66 JJ |
12915 | OpenMP 3.1: |
12916 | ||
12917 | reduction-operator: | |
acf0174b JJ |
12918 | One of: + * - & ^ | && || max min |
12919 | ||
12920 | OpenMP 4.0: | |
12921 | ||
12922 | reduction-operator: | |
12923 | One of: + * - & ^ | && || | |
12924 | identifier */ | |
953ff289 DN |
12925 | |
12926 | static tree | |
12927 | c_parser_omp_clause_reduction (c_parser *parser, tree list) | |
12928 | { | |
c2255bc4 | 12929 | location_t clause_loc = c_parser_peek_token (parser)->location; |
32129a17 DM |
12930 | matching_parens parens; |
12931 | if (parens.require_open (parser)) | |
953ff289 | 12932 | { |
acf0174b JJ |
12933 | enum tree_code code = ERROR_MARK; |
12934 | tree reduc_id = NULL_TREE; | |
953ff289 DN |
12935 | |
12936 | switch (c_parser_peek_token (parser)->type) | |
12937 | { | |
12938 | case CPP_PLUS: | |
12939 | code = PLUS_EXPR; | |
12940 | break; | |
12941 | case CPP_MULT: | |
12942 | code = MULT_EXPR; | |
12943 | break; | |
12944 | case CPP_MINUS: | |
12945 | code = MINUS_EXPR; | |
12946 | break; | |
12947 | case CPP_AND: | |
12948 | code = BIT_AND_EXPR; | |
12949 | break; | |
12950 | case CPP_XOR: | |
12951 | code = BIT_XOR_EXPR; | |
12952 | break; | |
12953 | case CPP_OR: | |
12954 | code = BIT_IOR_EXPR; | |
12955 | break; | |
12956 | case CPP_AND_AND: | |
12957 | code = TRUTH_ANDIF_EXPR; | |
12958 | break; | |
12959 | case CPP_OR_OR: | |
12960 | code = TRUTH_ORIF_EXPR; | |
12961 | break; | |
20906c66 JJ |
12962 | case CPP_NAME: |
12963 | { | |
12964 | const char *p | |
12965 | = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
12966 | if (strcmp (p, "min") == 0) | |
12967 | { | |
12968 | code = MIN_EXPR; | |
12969 | break; | |
12970 | } | |
12971 | if (strcmp (p, "max") == 0) | |
12972 | { | |
12973 | code = MAX_EXPR; | |
12974 | break; | |
12975 | } | |
acf0174b JJ |
12976 | reduc_id = c_parser_peek_token (parser)->value; |
12977 | break; | |
20906c66 | 12978 | } |
953ff289 DN |
12979 | default: |
12980 | c_parser_error (parser, | |
12981 | "expected %<+%>, %<*%>, %<-%>, %<&%>, " | |
79c9b7a8 | 12982 | "%<^%>, %<|%>, %<&&%>, %<||%> or identifier"); |
953ff289 DN |
12983 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0); |
12984 | return list; | |
12985 | } | |
12986 | c_parser_consume_token (parser); | |
acf0174b | 12987 | reduc_id = c_omp_reduction_id (code, reduc_id); |
953ff289 DN |
12988 | if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
12989 | { | |
12990 | tree nl, c; | |
12991 | ||
c2255bc4 AH |
12992 | nl = c_parser_omp_variable_list (parser, clause_loc, |
12993 | OMP_CLAUSE_REDUCTION, list); | |
953ff289 | 12994 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
acf0174b | 12995 | { |
d9a6bd32 JJ |
12996 | tree d = OMP_CLAUSE_DECL (c), type; |
12997 | if (TREE_CODE (d) != TREE_LIST) | |
12998 | type = TREE_TYPE (d); | |
12999 | else | |
13000 | { | |
13001 | int cnt = 0; | |
13002 | tree t; | |
13003 | for (t = d; TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t)) | |
13004 | cnt++; | |
13005 | type = TREE_TYPE (t); | |
13006 | while (cnt > 0) | |
13007 | { | |
13008 | if (TREE_CODE (type) != POINTER_TYPE | |
13009 | && TREE_CODE (type) != ARRAY_TYPE) | |
13010 | break; | |
13011 | type = TREE_TYPE (type); | |
13012 | cnt--; | |
13013 | } | |
13014 | } | |
13015 | while (TREE_CODE (type) == ARRAY_TYPE) | |
13016 | type = TREE_TYPE (type); | |
acf0174b JJ |
13017 | OMP_CLAUSE_REDUCTION_CODE (c) = code; |
13018 | if (code == ERROR_MARK | |
13019 | || !(INTEGRAL_TYPE_P (type) | |
13020 | || TREE_CODE (type) == REAL_TYPE | |
13021 | || TREE_CODE (type) == COMPLEX_TYPE)) | |
13022 | OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) | |
13023 | = c_omp_reduction_lookup (reduc_id, | |
13024 | TYPE_MAIN_VARIANT (type)); | |
13025 | } | |
953ff289 DN |
13026 | |
13027 | list = nl; | |
13028 | } | |
32129a17 | 13029 | parens.skip_until_found_close (parser); |
953ff289 DN |
13030 | } |
13031 | return list; | |
13032 | } | |
13033 | ||
13034 | /* OpenMP 2.5: | |
13035 | schedule ( schedule-kind ) | |
13036 | schedule ( schedule-kind , expression ) | |
13037 | ||
13038 | schedule-kind: | |
a68ab351 | 13039 | static | dynamic | guided | runtime | auto |
d9a6bd32 JJ |
13040 | |
13041 | OpenMP 4.5: | |
13042 | schedule ( schedule-modifier : schedule-kind ) | |
e01d41e5 | 13043 | schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression ) |
d9a6bd32 JJ |
13044 | |
13045 | schedule-modifier: | |
e01d41e5 JJ |
13046 | simd |
13047 | monotonic | |
13048 | nonmonotonic */ | |
953ff289 DN |
13049 | |
13050 | static tree | |
13051 | c_parser_omp_clause_schedule (c_parser *parser, tree list) | |
13052 | { | |
13053 | tree c, t; | |
c2255bc4 | 13054 | location_t loc = c_parser_peek_token (parser)->location; |
e01d41e5 | 13055 | int modifiers = 0, nmodifiers = 0; |
953ff289 | 13056 | |
32129a17 DM |
13057 | matching_parens parens; |
13058 | if (!parens.require_open (parser)) | |
953ff289 DN |
13059 | return list; |
13060 | ||
c2255bc4 | 13061 | c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE); |
953ff289 | 13062 | |
e01d41e5 | 13063 | while (c_parser_next_token_is (parser, CPP_NAME)) |
d9a6bd32 JJ |
13064 | { |
13065 | tree kind = c_parser_peek_token (parser)->value; | |
13066 | const char *p = IDENTIFIER_POINTER (kind); | |
e01d41e5 JJ |
13067 | if (strcmp ("simd", p) == 0) |
13068 | OMP_CLAUSE_SCHEDULE_SIMD (c) = 1; | |
13069 | else if (strcmp ("monotonic", p) == 0) | |
13070 | modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC; | |
13071 | else if (strcmp ("nonmonotonic", p) == 0) | |
13072 | modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC; | |
13073 | else | |
13074 | break; | |
13075 | c_parser_consume_token (parser); | |
13076 | if (nmodifiers++ == 0 | |
13077 | && c_parser_next_token_is (parser, CPP_COMMA)) | |
13078 | c_parser_consume_token (parser); | |
13079 | else | |
d9a6bd32 | 13080 | { |
e01d41e5 JJ |
13081 | c_parser_require (parser, CPP_COLON, "expected %<:%>"); |
13082 | break; | |
d9a6bd32 JJ |
13083 | } |
13084 | } | |
13085 | ||
e01d41e5 JJ |
13086 | if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC |
13087 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) | |
13088 | == (OMP_CLAUSE_SCHEDULE_MONOTONIC | |
13089 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) | |
13090 | { | |
13091 | error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers " | |
13092 | "specified"); | |
13093 | modifiers = 0; | |
13094 | } | |
13095 | ||
953ff289 DN |
13096 | if (c_parser_next_token_is (parser, CPP_NAME)) |
13097 | { | |
13098 | tree kind = c_parser_peek_token (parser)->value; | |
13099 | const char *p = IDENTIFIER_POINTER (kind); | |
13100 | ||
13101 | switch (p[0]) | |
13102 | { | |
13103 | case 'd': | |
13104 | if (strcmp ("dynamic", p) != 0) | |
13105 | goto invalid_kind; | |
13106 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; | |
13107 | break; | |
13108 | ||
13109 | case 'g': | |
13110 | if (strcmp ("guided", p) != 0) | |
13111 | goto invalid_kind; | |
13112 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; | |
13113 | break; | |
13114 | ||
13115 | case 'r': | |
13116 | if (strcmp ("runtime", p) != 0) | |
13117 | goto invalid_kind; | |
13118 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; | |
13119 | break; | |
13120 | ||
13121 | default: | |
13122 | goto invalid_kind; | |
13123 | } | |
13124 | } | |
13125 | else if (c_parser_next_token_is_keyword (parser, RID_STATIC)) | |
13126 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; | |
a68ab351 JJ |
13127 | else if (c_parser_next_token_is_keyword (parser, RID_AUTO)) |
13128 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO; | |
953ff289 DN |
13129 | else |
13130 | goto invalid_kind; | |
13131 | ||
13132 | c_parser_consume_token (parser); | |
13133 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
13134 | { | |
c7412148 | 13135 | location_t here; |
953ff289 DN |
13136 | c_parser_consume_token (parser); |
13137 | ||
c7412148 | 13138 | here = c_parser_peek_token (parser)->location; |
9dc5773f JJ |
13139 | c_expr expr = c_parser_expr_no_commas (parser, NULL); |
13140 | expr = convert_lvalue_to_rvalue (here, expr, false, true); | |
13141 | t = expr.value; | |
928c19bb | 13142 | t = c_fully_fold (t, false, NULL); |
953ff289 DN |
13143 | |
13144 | if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) | |
3ba09659 AH |
13145 | error_at (here, "schedule %<runtime%> does not take " |
13146 | "a %<chunk_size%> parameter"); | |
a68ab351 | 13147 | else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) |
3ba09659 AH |
13148 | error_at (here, |
13149 | "schedule %<auto%> does not take " | |
13150 | "a %<chunk_size%> parameter"); | |
953ff289 | 13151 | else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) |
7211a097 JJ |
13152 | { |
13153 | /* Attempt to statically determine when the number isn't | |
13154 | positive. */ | |
13155 | tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t, | |
13156 | build_int_cst (TREE_TYPE (t), 0)); | |
13157 | protected_set_expr_location (s, loc); | |
13158 | if (s == boolean_true_node) | |
13159 | { | |
13160 | warning_at (loc, 0, | |
13161 | "chunk size value must be positive"); | |
13162 | t = integer_one_node; | |
13163 | } | |
13164 | OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; | |
13165 | } | |
953ff289 DN |
13166 | else |
13167 | c_parser_error (parser, "expected integer expression"); | |
13168 | ||
32129a17 | 13169 | parens.skip_until_found_close (parser); |
953ff289 DN |
13170 | } |
13171 | else | |
13172 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
13173 | "expected %<,%> or %<)%>"); | |
13174 | ||
e01d41e5 JJ |
13175 | OMP_CLAUSE_SCHEDULE_KIND (c) |
13176 | = (enum omp_clause_schedule_kind) | |
13177 | (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers); | |
13178 | ||
953ff289 DN |
13179 | check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule"); |
13180 | OMP_CLAUSE_CHAIN (c) = list; | |
13181 | return c; | |
13182 | ||
13183 | invalid_kind: | |
13184 | c_parser_error (parser, "invalid schedule kind"); | |
13185 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0); | |
13186 | return list; | |
13187 | } | |
13188 | ||
13189 | /* OpenMP 2.5: | |
13190 | shared ( variable-list ) */ | |
13191 | ||
13192 | static tree | |
13193 | c_parser_omp_clause_shared (c_parser *parser, tree list) | |
13194 | { | |
13195 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list); | |
13196 | } | |
13197 | ||
a68ab351 JJ |
13198 | /* OpenMP 3.0: |
13199 | untied */ | |
13200 | ||
13201 | static tree | |
13202 | c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list) | |
13203 | { | |
13204 | tree c; | |
13205 | ||
13206 | /* FIXME: Should we allow duplicates? */ | |
13207 | check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied"); | |
13208 | ||
c2255bc4 AH |
13209 | c = build_omp_clause (c_parser_peek_token (parser)->location, |
13210 | OMP_CLAUSE_UNTIED); | |
a68ab351 | 13211 | OMP_CLAUSE_CHAIN (c) = list; |
c2255bc4 | 13212 | |
a68ab351 JJ |
13213 | return c; |
13214 | } | |
13215 | ||
41dbbb37 TS |
13216 | /* OpenMP 4.0: |
13217 | inbranch | |
13218 | notinbranch */ | |
13219 | ||
13220 | static tree | |
13221 | c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED, | |
13222 | enum omp_clause_code code, tree list) | |
13223 | { | |
13224 | check_no_duplicate_clause (list, code, omp_clause_code_name[code]); | |
13225 | ||
13226 | tree c = build_omp_clause (c_parser_peek_token (parser)->location, code); | |
13227 | OMP_CLAUSE_CHAIN (c) = list; | |
13228 | ||
13229 | return c; | |
13230 | } | |
13231 | ||
13232 | /* OpenMP 4.0: | |
13233 | parallel | |
13234 | for | |
13235 | sections | |
13236 | taskgroup */ | |
13237 | ||
13238 | static tree | |
13239 | c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED, | |
13240 | enum omp_clause_code code, tree list) | |
13241 | { | |
13242 | tree c = build_omp_clause (c_parser_peek_token (parser)->location, code); | |
13243 | OMP_CLAUSE_CHAIN (c) = list; | |
acf0174b JJ |
13244 | |
13245 | return c; | |
13246 | } | |
13247 | ||
d9a6bd32 JJ |
13248 | /* OpenMP 4.5: |
13249 | nogroup */ | |
13250 | ||
13251 | static tree | |
13252 | c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list) | |
13253 | { | |
13254 | check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup"); | |
13255 | tree c = build_omp_clause (c_parser_peek_token (parser)->location, | |
13256 | OMP_CLAUSE_NOGROUP); | |
13257 | OMP_CLAUSE_CHAIN (c) = list; | |
13258 | return c; | |
13259 | } | |
13260 | ||
13261 | /* OpenMP 4.5: | |
13262 | simd | |
13263 | threads */ | |
13264 | ||
13265 | static tree | |
13266 | c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED, | |
13267 | enum omp_clause_code code, tree list) | |
13268 | { | |
13269 | check_no_duplicate_clause (list, code, omp_clause_code_name[code]); | |
13270 | tree c = build_omp_clause (c_parser_peek_token (parser)->location, code); | |
13271 | OMP_CLAUSE_CHAIN (c) = list; | |
13272 | return c; | |
13273 | } | |
13274 | ||
acf0174b JJ |
13275 | /* OpenMP 4.0: |
13276 | num_teams ( expression ) */ | |
13277 | ||
13278 | static tree | |
13279 | c_parser_omp_clause_num_teams (c_parser *parser, tree list) | |
13280 | { | |
13281 | location_t num_teams_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
13282 | matching_parens parens; |
13283 | if (parens.require_open (parser)) | |
acf0174b JJ |
13284 | { |
13285 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
13286 | c_expr expr = c_parser_expression (parser); |
13287 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13288 | tree c, t = expr.value; | |
acf0174b JJ |
13289 | t = c_fully_fold (t, false, NULL); |
13290 | ||
32129a17 | 13291 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13292 | |
13293 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
953ff289 | 13294 | { |
acf0174b JJ |
13295 | c_parser_error (parser, "expected integer expression"); |
13296 | return list; | |
953ff289 DN |
13297 | } |
13298 | ||
acf0174b JJ |
13299 | /* Attempt to statically determine when the number isn't positive. */ |
13300 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, | |
13301 | build_int_cst (TREE_TYPE (t), 0)); | |
21ba0cea | 13302 | protected_set_expr_location (c, expr_loc); |
acf0174b | 13303 | if (c == boolean_true_node) |
953ff289 | 13304 | { |
acf0174b JJ |
13305 | warning_at (expr_loc, 0, "%<num_teams%> value must be positive"); |
13306 | t = integer_one_node; | |
953ff289 | 13307 | } |
953ff289 | 13308 | |
acf0174b | 13309 | check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams"); |
953ff289 | 13310 | |
acf0174b JJ |
13311 | c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS); |
13312 | OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t; | |
13313 | OMP_CLAUSE_CHAIN (c) = list; | |
13314 | list = c; | |
13315 | } | |
953ff289 | 13316 | |
acf0174b JJ |
13317 | return list; |
13318 | } | |
953ff289 | 13319 | |
acf0174b JJ |
13320 | /* OpenMP 4.0: |
13321 | thread_limit ( expression ) */ | |
953ff289 DN |
13322 | |
13323 | static tree | |
acf0174b | 13324 | c_parser_omp_clause_thread_limit (c_parser *parser, tree list) |
953ff289 | 13325 | { |
68c81f24 | 13326 | location_t num_thread_limit_loc = c_parser_peek_token (parser)->location; |
32129a17 DM |
13327 | matching_parens parens; |
13328 | if (parens.require_open (parser)) | |
acf0174b JJ |
13329 | { |
13330 | location_t expr_loc = c_parser_peek_token (parser)->location; | |
9dc5773f JJ |
13331 | c_expr expr = c_parser_expression (parser); |
13332 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13333 | tree c, t = expr.value; | |
acf0174b | 13334 | t = c_fully_fold (t, false, NULL); |
953ff289 | 13335 | |
32129a17 | 13336 | parens.skip_until_found_close (parser); |
953ff289 | 13337 | |
acf0174b JJ |
13338 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) |
13339 | { | |
13340 | c_parser_error (parser, "expected integer expression"); | |
13341 | return list; | |
13342 | } | |
c2255bc4 | 13343 | |
acf0174b JJ |
13344 | /* Attempt to statically determine when the number isn't positive. */ |
13345 | c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, | |
13346 | build_int_cst (TREE_TYPE (t), 0)); | |
21ba0cea | 13347 | protected_set_expr_location (c, expr_loc); |
acf0174b JJ |
13348 | if (c == boolean_true_node) |
13349 | { | |
13350 | warning_at (expr_loc, 0, "%<thread_limit%> value must be positive"); | |
13351 | t = integer_one_node; | |
13352 | } | |
20906c66 | 13353 | |
acf0174b JJ |
13354 | check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT, |
13355 | "thread_limit"); | |
20906c66 | 13356 | |
68c81f24 | 13357 | c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT); |
acf0174b JJ |
13358 | OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t; |
13359 | OMP_CLAUSE_CHAIN (c) = list; | |
13360 | list = c; | |
13361 | } | |
20906c66 | 13362 | |
acf0174b JJ |
13363 | return list; |
13364 | } | |
20906c66 | 13365 | |
acf0174b JJ |
13366 | /* OpenMP 4.0: |
13367 | aligned ( variable-list ) | |
13368 | aligned ( variable-list : constant-expression ) */ | |
20906c66 | 13369 | |
acf0174b JJ |
13370 | static tree |
13371 | c_parser_omp_clause_aligned (c_parser *parser, tree list) | |
13372 | { | |
13373 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
13374 | tree nl, c; | |
20906c66 | 13375 | |
32129a17 DM |
13376 | matching_parens parens; |
13377 | if (!parens.require_open (parser)) | |
acf0174b | 13378 | return list; |
20906c66 | 13379 | |
acf0174b JJ |
13380 | nl = c_parser_omp_variable_list (parser, clause_loc, |
13381 | OMP_CLAUSE_ALIGNED, list); | |
20906c66 | 13382 | |
acf0174b JJ |
13383 | if (c_parser_next_token_is (parser, CPP_COLON)) |
13384 | { | |
13385 | c_parser_consume_token (parser); | |
9dc5773f JJ |
13386 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13387 | c_expr expr = c_parser_expr_no_commas (parser, NULL); | |
13388 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13389 | tree alignment = expr.value; | |
acf0174b | 13390 | alignment = c_fully_fold (alignment, false, NULL); |
fce5e5e3 JJ |
13391 | if (TREE_CODE (alignment) != INTEGER_CST |
13392 | || !INTEGRAL_TYPE_P (TREE_TYPE (alignment)) | |
13393 | || tree_int_cst_sgn (alignment) != 1) | |
acf0174b JJ |
13394 | { |
13395 | error_at (clause_loc, "%<aligned%> clause alignment expression must " | |
13396 | "be positive constant integer expression"); | |
13397 | alignment = NULL_TREE; | |
13398 | } | |
953ff289 | 13399 | |
acf0174b JJ |
13400 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
13401 | OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; | |
13402 | } | |
13403 | ||
32129a17 | 13404 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13405 | return nl; |
13406 | } | |
13407 | ||
13408 | /* OpenMP 4.0: | |
13409 | linear ( variable-list ) | |
d9a6bd32 JJ |
13410 | linear ( variable-list : expression ) |
13411 | ||
13412 | OpenMP 4.5: | |
13413 | linear ( modifier ( variable-list ) ) | |
13414 | linear ( modifier ( variable-list ) : expression ) */ | |
acf0174b JJ |
13415 | |
13416 | static tree | |
41958c28 | 13417 | c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) |
953ff289 | 13418 | { |
acf0174b JJ |
13419 | location_t clause_loc = c_parser_peek_token (parser)->location; |
13420 | tree nl, c, step; | |
d9a6bd32 | 13421 | enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; |
acf0174b | 13422 | |
32129a17 DM |
13423 | matching_parens parens; |
13424 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13425 | return list; |
13426 | ||
d9a6bd32 JJ |
13427 | if (!is_cilk_simd_fn |
13428 | && c_parser_next_token_is (parser, CPP_NAME)) | |
13429 | { | |
13430 | c_token *tok = c_parser_peek_token (parser); | |
13431 | const char *p = IDENTIFIER_POINTER (tok->value); | |
13432 | if (strcmp ("val", p) == 0) | |
13433 | kind = OMP_CLAUSE_LINEAR_VAL; | |
13434 | if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN) | |
13435 | kind = OMP_CLAUSE_LINEAR_DEFAULT; | |
13436 | if (kind != OMP_CLAUSE_LINEAR_DEFAULT) | |
13437 | { | |
13438 | c_parser_consume_token (parser); | |
13439 | c_parser_consume_token (parser); | |
13440 | } | |
13441 | } | |
13442 | ||
acf0174b JJ |
13443 | nl = c_parser_omp_variable_list (parser, clause_loc, |
13444 | OMP_CLAUSE_LINEAR, list); | |
13445 | ||
d9a6bd32 | 13446 | if (kind != OMP_CLAUSE_LINEAR_DEFAULT) |
32129a17 | 13447 | parens.skip_until_found_close (parser); |
d9a6bd32 | 13448 | |
acf0174b JJ |
13449 | if (c_parser_next_token_is (parser, CPP_COLON)) |
13450 | { | |
13451 | c_parser_consume_token (parser); | |
9dc5773f JJ |
13452 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13453 | c_expr expr = c_parser_expression (parser); | |
13454 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13455 | step = expr.value; | |
acf0174b | 13456 | step = c_fully_fold (step, false, NULL); |
41958c28 BI |
13457 | if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) |
13458 | { | |
13459 | sorry ("using parameters for %<linear%> step is not supported yet"); | |
13460 | step = integer_one_node; | |
13461 | } | |
acf0174b JJ |
13462 | if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) |
13463 | { | |
13464 | error_at (clause_loc, "%<linear%> clause step expression must " | |
13465 | "be integral"); | |
13466 | step = integer_one_node; | |
13467 | } | |
13468 | ||
13469 | } | |
13470 | else | |
13471 | step = integer_one_node; | |
13472 | ||
13473 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) | |
13474 | { | |
13475 | OMP_CLAUSE_LINEAR_STEP (c) = step; | |
d9a6bd32 | 13476 | OMP_CLAUSE_LINEAR_KIND (c) = kind; |
acf0174b JJ |
13477 | } |
13478 | ||
32129a17 | 13479 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13480 | return nl; |
13481 | } | |
13482 | ||
13483 | /* OpenMP 4.0: | |
13484 | safelen ( constant-expression ) */ | |
13485 | ||
13486 | static tree | |
13487 | c_parser_omp_clause_safelen (c_parser *parser, tree list) | |
13488 | { | |
13489 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
13490 | tree c, t; | |
13491 | ||
32129a17 DM |
13492 | matching_parens parens; |
13493 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13494 | return list; |
13495 | ||
9dc5773f JJ |
13496 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13497 | c_expr expr = c_parser_expr_no_commas (parser, NULL); | |
13498 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13499 | t = expr.value; | |
acf0174b | 13500 | t = c_fully_fold (t, false, NULL); |
fce5e5e3 JJ |
13501 | if (TREE_CODE (t) != INTEGER_CST |
13502 | || !INTEGRAL_TYPE_P (TREE_TYPE (t)) | |
13503 | || tree_int_cst_sgn (t) != 1) | |
acf0174b JJ |
13504 | { |
13505 | error_at (clause_loc, "%<safelen%> clause expression must " | |
13506 | "be positive constant integer expression"); | |
13507 | t = NULL_TREE; | |
13508 | } | |
13509 | ||
32129a17 | 13510 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13511 | if (t == NULL_TREE || t == error_mark_node) |
13512 | return list; | |
13513 | ||
13514 | check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen"); | |
13515 | ||
13516 | c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN); | |
13517 | OMP_CLAUSE_SAFELEN_EXPR (c) = t; | |
13518 | OMP_CLAUSE_CHAIN (c) = list; | |
13519 | return c; | |
13520 | } | |
13521 | ||
13522 | /* OpenMP 4.0: | |
13523 | simdlen ( constant-expression ) */ | |
13524 | ||
13525 | static tree | |
13526 | c_parser_omp_clause_simdlen (c_parser *parser, tree list) | |
13527 | { | |
13528 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
13529 | tree c, t; | |
13530 | ||
32129a17 DM |
13531 | matching_parens parens; |
13532 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13533 | return list; |
13534 | ||
9dc5773f JJ |
13535 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13536 | c_expr expr = c_parser_expr_no_commas (parser, NULL); | |
13537 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13538 | t = expr.value; | |
acf0174b | 13539 | t = c_fully_fold (t, false, NULL); |
fce5e5e3 JJ |
13540 | if (TREE_CODE (t) != INTEGER_CST |
13541 | || !INTEGRAL_TYPE_P (TREE_TYPE (t)) | |
13542 | || tree_int_cst_sgn (t) != 1) | |
acf0174b JJ |
13543 | { |
13544 | error_at (clause_loc, "%<simdlen%> clause expression must " | |
13545 | "be positive constant integer expression"); | |
13546 | t = NULL_TREE; | |
13547 | } | |
13548 | ||
32129a17 | 13549 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13550 | if (t == NULL_TREE || t == error_mark_node) |
13551 | return list; | |
13552 | ||
13553 | check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen"); | |
13554 | ||
13555 | c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN); | |
13556 | OMP_CLAUSE_SIMDLEN_EXPR (c) = t; | |
13557 | OMP_CLAUSE_CHAIN (c) = list; | |
13558 | return c; | |
13559 | } | |
13560 | ||
d9a6bd32 JJ |
13561 | /* OpenMP 4.5: |
13562 | vec: | |
13563 | identifier [+/- integer] | |
13564 | vec , identifier [+/- integer] | |
13565 | */ | |
13566 | ||
13567 | static tree | |
13568 | c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, | |
13569 | tree list) | |
13570 | { | |
13571 | tree vec = NULL; | |
13572 | if (c_parser_next_token_is_not (parser, CPP_NAME) | |
13573 | || c_parser_peek_token (parser)->id_kind != C_ID_ID) | |
13574 | { | |
13575 | c_parser_error (parser, "expected identifier"); | |
13576 | return list; | |
13577 | } | |
13578 | ||
13579 | while (c_parser_next_token_is (parser, CPP_NAME) | |
13580 | && c_parser_peek_token (parser)->id_kind == C_ID_ID) | |
13581 | { | |
13582 | tree t = lookup_name (c_parser_peek_token (parser)->value); | |
13583 | tree addend = NULL; | |
13584 | ||
13585 | if (t == NULL_TREE) | |
13586 | { | |
13587 | undeclared_variable (c_parser_peek_token (parser)->location, | |
13588 | c_parser_peek_token (parser)->value); | |
13589 | t = error_mark_node; | |
13590 | } | |
13591 | ||
13592 | c_parser_consume_token (parser); | |
13593 | ||
13594 | bool neg = false; | |
13595 | if (c_parser_next_token_is (parser, CPP_MINUS)) | |
13596 | neg = true; | |
13597 | else if (!c_parser_next_token_is (parser, CPP_PLUS)) | |
13598 | { | |
13599 | addend = integer_zero_node; | |
13600 | neg = false; | |
13601 | goto add_to_vector; | |
13602 | } | |
13603 | c_parser_consume_token (parser); | |
13604 | ||
13605 | if (c_parser_next_token_is_not (parser, CPP_NUMBER)) | |
13606 | { | |
13607 | c_parser_error (parser, "expected integer"); | |
13608 | return list; | |
13609 | } | |
13610 | ||
13611 | addend = c_parser_peek_token (parser)->value; | |
13612 | if (TREE_CODE (addend) != INTEGER_CST) | |
13613 | { | |
13614 | c_parser_error (parser, "expected integer"); | |
13615 | return list; | |
13616 | } | |
13617 | c_parser_consume_token (parser); | |
13618 | ||
13619 | add_to_vector: | |
13620 | if (t != error_mark_node) | |
13621 | { | |
13622 | vec = tree_cons (addend, t, vec); | |
13623 | if (neg) | |
13624 | OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; | |
13625 | } | |
13626 | ||
13627 | if (c_parser_next_token_is_not (parser, CPP_COMMA)) | |
13628 | break; | |
13629 | ||
13630 | c_parser_consume_token (parser); | |
13631 | } | |
13632 | ||
13633 | if (vec == NULL_TREE) | |
13634 | return list; | |
13635 | ||
13636 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); | |
13637 | OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; | |
13638 | OMP_CLAUSE_DECL (u) = nreverse (vec); | |
13639 | OMP_CLAUSE_CHAIN (u) = list; | |
13640 | return u; | |
13641 | } | |
13642 | ||
acf0174b JJ |
13643 | /* OpenMP 4.0: |
13644 | depend ( depend-kind: variable-list ) | |
13645 | ||
13646 | depend-kind: | |
d9a6bd32 JJ |
13647 | in | out | inout |
13648 | ||
13649 | OpenMP 4.5: | |
13650 | depend ( source ) | |
13651 | ||
13652 | depend ( sink : vec ) */ | |
acf0174b JJ |
13653 | |
13654 | static tree | |
13655 | c_parser_omp_clause_depend (c_parser *parser, tree list) | |
13656 | { | |
13657 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
13658 | enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; | |
13659 | tree nl, c; | |
13660 | ||
32129a17 DM |
13661 | matching_parens parens; |
13662 | if (!parens.require_open (parser)) | |
acf0174b | 13663 | return list; |
953ff289 | 13664 | |
20906c66 JJ |
13665 | if (c_parser_next_token_is (parser, CPP_NAME)) |
13666 | { | |
13667 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
acf0174b JJ |
13668 | if (strcmp ("in", p) == 0) |
13669 | kind = OMP_CLAUSE_DEPEND_IN; | |
13670 | else if (strcmp ("inout", p) == 0) | |
13671 | kind = OMP_CLAUSE_DEPEND_INOUT; | |
13672 | else if (strcmp ("out", p) == 0) | |
13673 | kind = OMP_CLAUSE_DEPEND_OUT; | |
d9a6bd32 JJ |
13674 | else if (strcmp ("source", p) == 0) |
13675 | kind = OMP_CLAUSE_DEPEND_SOURCE; | |
13676 | else if (strcmp ("sink", p) == 0) | |
13677 | kind = OMP_CLAUSE_DEPEND_SINK; | |
20906c66 | 13678 | else |
acf0174b | 13679 | goto invalid_kind; |
20906c66 | 13680 | } |
acf0174b JJ |
13681 | else |
13682 | goto invalid_kind; | |
953ff289 | 13683 | |
acf0174b | 13684 | c_parser_consume_token (parser); |
d9a6bd32 JJ |
13685 | |
13686 | if (kind == OMP_CLAUSE_DEPEND_SOURCE) | |
13687 | { | |
13688 | c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); | |
13689 | OMP_CLAUSE_DEPEND_KIND (c) = kind; | |
13690 | OMP_CLAUSE_DECL (c) = NULL_TREE; | |
13691 | OMP_CLAUSE_CHAIN (c) = list; | |
32129a17 | 13692 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
13693 | return c; |
13694 | } | |
13695 | ||
acf0174b JJ |
13696 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
13697 | goto resync_fail; | |
13698 | ||
d9a6bd32 JJ |
13699 | if (kind == OMP_CLAUSE_DEPEND_SINK) |
13700 | nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list); | |
13701 | else | |
13702 | { | |
13703 | nl = c_parser_omp_variable_list (parser, clause_loc, | |
13704 | OMP_CLAUSE_DEPEND, list); | |
acf0174b | 13705 | |
d9a6bd32 JJ |
13706 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
13707 | OMP_CLAUSE_DEPEND_KIND (c) = kind; | |
13708 | } | |
acf0174b | 13709 | |
32129a17 | 13710 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13711 | return nl; |
13712 | ||
13713 | invalid_kind: | |
13714 | c_parser_error (parser, "invalid depend kind"); | |
13715 | resync_fail: | |
32129a17 | 13716 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13717 | return list; |
13718 | } | |
13719 | ||
13720 | /* OpenMP 4.0: | |
13721 | map ( map-kind: variable-list ) | |
13722 | map ( variable-list ) | |
13723 | ||
13724 | map-kind: | |
d9a6bd32 JJ |
13725 | alloc | to | from | tofrom |
13726 | ||
13727 | OpenMP 4.5: | |
13728 | map-kind: | |
13729 | alloc | to | from | tofrom | release | delete | |
13730 | ||
13731 | map ( always [,] map-kind: variable-list ) */ | |
acf0174b JJ |
13732 | |
13733 | static tree | |
13734 | c_parser_omp_clause_map (c_parser *parser, tree list) | |
13735 | { | |
13736 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
41dbbb37 | 13737 | enum gomp_map_kind kind = GOMP_MAP_TOFROM; |
d9a6bd32 JJ |
13738 | int always = 0; |
13739 | enum c_id_kind always_id_kind = C_ID_NONE; | |
13740 | location_t always_loc = UNKNOWN_LOCATION; | |
13741 | tree always_id = NULL_TREE; | |
acf0174b JJ |
13742 | tree nl, c; |
13743 | ||
32129a17 DM |
13744 | matching_parens parens; |
13745 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13746 | return list; |
13747 | ||
d9a6bd32 JJ |
13748 | if (c_parser_next_token_is (parser, CPP_NAME)) |
13749 | { | |
13750 | c_token *tok = c_parser_peek_token (parser); | |
13751 | const char *p = IDENTIFIER_POINTER (tok->value); | |
13752 | always_id_kind = tok->id_kind; | |
13753 | always_loc = tok->location; | |
13754 | always_id = tok->value; | |
13755 | if (strcmp ("always", p) == 0) | |
13756 | { | |
13757 | c_token *sectok = c_parser_peek_2nd_token (parser); | |
13758 | if (sectok->type == CPP_COMMA) | |
13759 | { | |
13760 | c_parser_consume_token (parser); | |
13761 | c_parser_consume_token (parser); | |
13762 | always = 2; | |
13763 | } | |
13764 | else if (sectok->type == CPP_NAME) | |
13765 | { | |
13766 | p = IDENTIFIER_POINTER (sectok->value); | |
13767 | if (strcmp ("alloc", p) == 0 | |
13768 | || strcmp ("to", p) == 0 | |
13769 | || strcmp ("from", p) == 0 | |
13770 | || strcmp ("tofrom", p) == 0 | |
13771 | || strcmp ("release", p) == 0 | |
13772 | || strcmp ("delete", p) == 0) | |
13773 | { | |
13774 | c_parser_consume_token (parser); | |
13775 | always = 1; | |
13776 | } | |
13777 | } | |
13778 | } | |
13779 | } | |
13780 | ||
acf0174b JJ |
13781 | if (c_parser_next_token_is (parser, CPP_NAME) |
13782 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
20906c66 | 13783 | { |
acf0174b JJ |
13784 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
13785 | if (strcmp ("alloc", p) == 0) | |
41dbbb37 | 13786 | kind = GOMP_MAP_ALLOC; |
acf0174b | 13787 | else if (strcmp ("to", p) == 0) |
d9a6bd32 | 13788 | kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; |
acf0174b | 13789 | else if (strcmp ("from", p) == 0) |
d9a6bd32 | 13790 | kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; |
acf0174b | 13791 | else if (strcmp ("tofrom", p) == 0) |
d9a6bd32 JJ |
13792 | kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; |
13793 | else if (strcmp ("release", p) == 0) | |
13794 | kind = GOMP_MAP_RELEASE; | |
13795 | else if (strcmp ("delete", p) == 0) | |
13796 | kind = GOMP_MAP_DELETE; | |
20906c66 JJ |
13797 | else |
13798 | { | |
acf0174b JJ |
13799 | c_parser_error (parser, "invalid map kind"); |
13800 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
13801 | "expected %<)%>"); | |
13802 | return list; | |
20906c66 | 13803 | } |
acf0174b JJ |
13804 | c_parser_consume_token (parser); |
13805 | c_parser_consume_token (parser); | |
20906c66 | 13806 | } |
d9a6bd32 JJ |
13807 | else if (always) |
13808 | { | |
13809 | if (always_id_kind != C_ID_ID) | |
13810 | { | |
13811 | c_parser_error (parser, "expected identifier"); | |
32129a17 | 13812 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
13813 | return list; |
13814 | } | |
13815 | ||
13816 | tree t = lookup_name (always_id); | |
13817 | if (t == NULL_TREE) | |
13818 | { | |
13819 | undeclared_variable (always_loc, always_id); | |
13820 | t = error_mark_node; | |
13821 | } | |
13822 | if (t != error_mark_node) | |
13823 | { | |
13824 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_MAP); | |
13825 | OMP_CLAUSE_DECL (u) = t; | |
13826 | OMP_CLAUSE_CHAIN (u) = list; | |
13827 | OMP_CLAUSE_SET_MAP_KIND (u, kind); | |
13828 | list = u; | |
13829 | } | |
13830 | if (always == 1) | |
13831 | { | |
32129a17 | 13832 | parens.skip_until_found_close (parser); |
d9a6bd32 JJ |
13833 | return list; |
13834 | } | |
13835 | } | |
20906c66 | 13836 | |
acf0174b JJ |
13837 | nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list); |
13838 | ||
13839 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) | |
41dbbb37 | 13840 | OMP_CLAUSE_SET_MAP_KIND (c, kind); |
acf0174b | 13841 | |
32129a17 | 13842 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13843 | return nl; |
13844 | } | |
13845 | ||
13846 | /* OpenMP 4.0: | |
13847 | device ( expression ) */ | |
13848 | ||
13849 | static tree | |
13850 | c_parser_omp_clause_device (c_parser *parser, tree list) | |
13851 | { | |
13852 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
32129a17 DM |
13853 | matching_parens parens; |
13854 | if (parens.require_open (parser)) | |
953ff289 | 13855 | { |
9dc5773f JJ |
13856 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13857 | c_expr expr = c_parser_expr_no_commas (parser, NULL); | |
13858 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13859 | tree c, t = expr.value; | |
acf0174b JJ |
13860 | t = c_fully_fold (t, false, NULL); |
13861 | ||
32129a17 | 13862 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13863 | |
13864 | if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) | |
20906c66 | 13865 | { |
acf0174b JJ |
13866 | c_parser_error (parser, "expected integer expression"); |
13867 | return list; | |
20906c66 | 13868 | } |
953ff289 | 13869 | |
acf0174b | 13870 | check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device"); |
953ff289 | 13871 | |
acf0174b JJ |
13872 | c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE); |
13873 | OMP_CLAUSE_DEVICE_ID (c) = t; | |
13874 | OMP_CLAUSE_CHAIN (c) = list; | |
13875 | list = c; | |
13876 | } | |
953ff289 | 13877 | |
acf0174b JJ |
13878 | return list; |
13879 | } | |
13880 | ||
13881 | /* OpenMP 4.0: | |
13882 | dist_schedule ( static ) | |
13883 | dist_schedule ( static , expression ) */ | |
13884 | ||
13885 | static tree | |
13886 | c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) | |
13887 | { | |
13888 | tree c, t = NULL_TREE; | |
13889 | location_t loc = c_parser_peek_token (parser)->location; | |
13890 | ||
32129a17 DM |
13891 | matching_parens parens; |
13892 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13893 | return list; |
13894 | ||
13895 | if (!c_parser_next_token_is_keyword (parser, RID_STATIC)) | |
13896 | { | |
13897 | c_parser_error (parser, "invalid dist_schedule kind"); | |
13898 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
13899 | "expected %<)%>"); | |
13900 | return list; | |
13901 | } | |
13902 | ||
13903 | c_parser_consume_token (parser); | |
13904 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
13905 | { | |
13906 | c_parser_consume_token (parser); | |
13907 | ||
9dc5773f JJ |
13908 | location_t expr_loc = c_parser_peek_token (parser)->location; |
13909 | c_expr expr = c_parser_expr_no_commas (parser, NULL); | |
13910 | expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); | |
13911 | t = expr.value; | |
acf0174b | 13912 | t = c_fully_fold (t, false, NULL); |
32129a17 | 13913 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13914 | } |
13915 | else | |
13916 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
13917 | "expected %<,%> or %<)%>"); | |
13918 | ||
13919 | check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule"); | |
13920 | if (t == error_mark_node) | |
13921 | return list; | |
13922 | ||
13923 | c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE); | |
13924 | OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; | |
13925 | OMP_CLAUSE_CHAIN (c) = list; | |
13926 | return c; | |
13927 | } | |
13928 | ||
13929 | /* OpenMP 4.0: | |
13930 | proc_bind ( proc-bind-kind ) | |
13931 | ||
13932 | proc-bind-kind: | |
13933 | master | close | spread */ | |
13934 | ||
13935 | static tree | |
13936 | c_parser_omp_clause_proc_bind (c_parser *parser, tree list) | |
13937 | { | |
13938 | location_t clause_loc = c_parser_peek_token (parser)->location; | |
13939 | enum omp_clause_proc_bind_kind kind; | |
13940 | tree c; | |
13941 | ||
32129a17 DM |
13942 | matching_parens parens; |
13943 | if (!parens.require_open (parser)) | |
acf0174b JJ |
13944 | return list; |
13945 | ||
13946 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
13947 | { | |
13948 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
13949 | if (strcmp ("master", p) == 0) | |
13950 | kind = OMP_CLAUSE_PROC_BIND_MASTER; | |
13951 | else if (strcmp ("close", p) == 0) | |
13952 | kind = OMP_CLAUSE_PROC_BIND_CLOSE; | |
13953 | else if (strcmp ("spread", p) == 0) | |
13954 | kind = OMP_CLAUSE_PROC_BIND_SPREAD; | |
13955 | else | |
13956 | goto invalid_kind; | |
13957 | } | |
13958 | else | |
13959 | goto invalid_kind; | |
13960 | ||
13961 | c_parser_consume_token (parser); | |
32129a17 | 13962 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13963 | c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND); |
13964 | OMP_CLAUSE_PROC_BIND_KIND (c) = kind; | |
13965 | OMP_CLAUSE_CHAIN (c) = list; | |
13966 | return c; | |
13967 | ||
13968 | invalid_kind: | |
13969 | c_parser_error (parser, "invalid proc_bind kind"); | |
32129a17 | 13970 | parens.skip_until_found_close (parser); |
acf0174b JJ |
13971 | return list; |
13972 | } | |
13973 | ||
13974 | /* OpenMP 4.0: | |
13975 | to ( variable-list ) */ | |
13976 | ||
13977 | static tree | |
13978 | c_parser_omp_clause_to (c_parser *parser, tree list) | |
13979 | { | |
13980 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list); | |
13981 | } | |
13982 | ||
13983 | /* OpenMP 4.0: | |
13984 | from ( variable-list ) */ | |
13985 | ||
13986 | static tree | |
13987 | c_parser_omp_clause_from (c_parser *parser, tree list) | |
13988 | { | |
13989 | return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list); | |
13990 | } | |
13991 | ||
13992 | /* OpenMP 4.0: | |
13993 | uniform ( variable-list ) */ | |
13994 | ||
13995 | static tree | |
13996 | c_parser_omp_clause_uniform (c_parser *parser, tree list) | |
13997 | { | |
13998 | /* The clauses location. */ | |
13999 | location_t loc = c_parser_peek_token (parser)->location; | |
14000 | ||
32129a17 DM |
14001 | matching_parens parens; |
14002 | if (parens.require_open (parser)) | |
acf0174b JJ |
14003 | { |
14004 | list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM, | |
14005 | list); | |
32129a17 | 14006 | parens.skip_until_found_close (parser); |
acf0174b JJ |
14007 | } |
14008 | return list; | |
14009 | } | |
14010 | ||
41dbbb37 TS |
14011 | /* Parse all OpenACC clauses. The set clauses allowed by the directive |
14012 | is a bitmask in MASK. Return the list of clauses found. */ | |
14013 | ||
14014 | static tree | |
14015 | c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask, | |
14016 | const char *where, bool finish_p = true) | |
14017 | { | |
14018 | tree clauses = NULL; | |
14019 | bool first = true; | |
14020 | ||
14021 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
14022 | { | |
14023 | location_t here; | |
14024 | pragma_omp_clause c_kind; | |
14025 | const char *c_name; | |
14026 | tree prev = clauses; | |
14027 | ||
14028 | if (!first && c_parser_next_token_is (parser, CPP_COMMA)) | |
14029 | c_parser_consume_token (parser); | |
14030 | ||
14031 | here = c_parser_peek_token (parser)->location; | |
14032 | c_kind = c_parser_omp_clause_name (parser); | |
14033 | ||
14034 | switch (c_kind) | |
14035 | { | |
14036 | case PRAGMA_OACC_CLAUSE_ASYNC: | |
14037 | clauses = c_parser_oacc_clause_async (parser, clauses); | |
14038 | c_name = "async"; | |
14039 | break; | |
765dd391 CP |
14040 | case PRAGMA_OACC_CLAUSE_AUTO: |
14041 | clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_AUTO, | |
14042 | clauses); | |
14043 | c_name = "auto"; | |
14044 | break; | |
41dbbb37 TS |
14045 | case PRAGMA_OACC_CLAUSE_COLLAPSE: |
14046 | clauses = c_parser_omp_clause_collapse (parser, clauses); | |
14047 | c_name = "collapse"; | |
14048 | break; | |
14049 | case PRAGMA_OACC_CLAUSE_COPY: | |
14050 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14051 | c_name = "copy"; | |
14052 | break; | |
14053 | case PRAGMA_OACC_CLAUSE_COPYIN: | |
14054 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14055 | c_name = "copyin"; | |
14056 | break; | |
14057 | case PRAGMA_OACC_CLAUSE_COPYOUT: | |
14058 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14059 | c_name = "copyout"; | |
14060 | break; | |
14061 | case PRAGMA_OACC_CLAUSE_CREATE: | |
14062 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14063 | c_name = "create"; | |
14064 | break; | |
14065 | case PRAGMA_OACC_CLAUSE_DELETE: | |
14066 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14067 | c_name = "delete"; | |
14068 | break; | |
7a5e4956 CP |
14069 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
14070 | clauses = c_parser_omp_clause_default (parser, clauses, true); | |
14071 | c_name = "default"; | |
14072 | break; | |
41dbbb37 TS |
14073 | case PRAGMA_OACC_CLAUSE_DEVICE: |
14074 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14075 | c_name = "device"; | |
14076 | break; | |
14077 | case PRAGMA_OACC_CLAUSE_DEVICEPTR: | |
14078 | clauses = c_parser_oacc_data_clause_deviceptr (parser, clauses); | |
14079 | c_name = "deviceptr"; | |
14080 | break; | |
6e232ba4 JN |
14081 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
14082 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14083 | c_name = "device_resident"; | |
14084 | break; | |
41dbbb37 TS |
14085 | case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE: |
14086 | clauses = c_parser_omp_clause_firstprivate (parser, clauses); | |
14087 | c_name = "firstprivate"; | |
14088 | break; | |
765dd391 CP |
14089 | case PRAGMA_OACC_CLAUSE_GANG: |
14090 | c_name = "gang"; | |
14091 | clauses = c_parser_oacc_shape_clause (parser, OMP_CLAUSE_GANG, | |
14092 | c_name, clauses); | |
14093 | break; | |
41dbbb37 TS |
14094 | case PRAGMA_OACC_CLAUSE_HOST: |
14095 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14096 | c_name = "host"; | |
14097 | break; | |
14098 | case PRAGMA_OACC_CLAUSE_IF: | |
d9a6bd32 | 14099 | clauses = c_parser_omp_clause_if (parser, clauses, false); |
41dbbb37 TS |
14100 | c_name = "if"; |
14101 | break; | |
7a5e4956 CP |
14102 | case PRAGMA_OACC_CLAUSE_INDEPENDENT: |
14103 | clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_INDEPENDENT, | |
14104 | clauses); | |
14105 | c_name = "independent"; | |
14106 | break; | |
6e232ba4 JN |
14107 | case PRAGMA_OACC_CLAUSE_LINK: |
14108 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14109 | c_name = "link"; | |
14110 | break; | |
41dbbb37 | 14111 | case PRAGMA_OACC_CLAUSE_NUM_GANGS: |
1e47f02b TS |
14112 | clauses = c_parser_oacc_single_int_clause (parser, |
14113 | OMP_CLAUSE_NUM_GANGS, | |
14114 | clauses); | |
41dbbb37 TS |
14115 | c_name = "num_gangs"; |
14116 | break; | |
14117 | case PRAGMA_OACC_CLAUSE_NUM_WORKERS: | |
1e47f02b TS |
14118 | clauses = c_parser_oacc_single_int_clause (parser, |
14119 | OMP_CLAUSE_NUM_WORKERS, | |
14120 | clauses); | |
41dbbb37 TS |
14121 | c_name = "num_workers"; |
14122 | break; | |
14123 | case PRAGMA_OACC_CLAUSE_PRESENT: | |
14124 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14125 | c_name = "present"; | |
14126 | break; | |
14127 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY: | |
14128 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14129 | c_name = "present_or_copy"; | |
14130 | break; | |
14131 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN: | |
14132 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14133 | c_name = "present_or_copyin"; | |
14134 | break; | |
14135 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT: | |
14136 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14137 | c_name = "present_or_copyout"; | |
14138 | break; | |
14139 | case PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE: | |
14140 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14141 | c_name = "present_or_create"; | |
14142 | break; | |
14143 | case PRAGMA_OACC_CLAUSE_PRIVATE: | |
14144 | clauses = c_parser_omp_clause_private (parser, clauses); | |
14145 | c_name = "private"; | |
14146 | break; | |
14147 | case PRAGMA_OACC_CLAUSE_REDUCTION: | |
14148 | clauses = c_parser_omp_clause_reduction (parser, clauses); | |
14149 | c_name = "reduction"; | |
14150 | break; | |
14151 | case PRAGMA_OACC_CLAUSE_SELF: | |
14152 | clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); | |
14153 | c_name = "self"; | |
14154 | break; | |
765dd391 CP |
14155 | case PRAGMA_OACC_CLAUSE_SEQ: |
14156 | clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ, | |
14157 | clauses); | |
14158 | c_name = "seq"; | |
14159 | break; | |
7a5e4956 CP |
14160 | case PRAGMA_OACC_CLAUSE_TILE: |
14161 | clauses = c_parser_oacc_clause_tile (parser, clauses); | |
14162 | c_name = "tile"; | |
14163 | break; | |
ff7a55bf | 14164 | case PRAGMA_OACC_CLAUSE_USE_DEVICE: |
c7b48c8a | 14165 | clauses = c_parser_omp_clause_use_device_ptr (parser, clauses); |
ff7a55bf TS |
14166 | c_name = "use_device"; |
14167 | break; | |
765dd391 CP |
14168 | case PRAGMA_OACC_CLAUSE_VECTOR: |
14169 | c_name = "vector"; | |
14170 | clauses = c_parser_oacc_shape_clause (parser, OMP_CLAUSE_VECTOR, | |
14171 | c_name, clauses); | |
14172 | break; | |
41dbbb37 | 14173 | case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH: |
1e47f02b TS |
14174 | clauses = c_parser_oacc_single_int_clause (parser, |
14175 | OMP_CLAUSE_VECTOR_LENGTH, | |
14176 | clauses); | |
41dbbb37 TS |
14177 | c_name = "vector_length"; |
14178 | break; | |
14179 | case PRAGMA_OACC_CLAUSE_WAIT: | |
14180 | clauses = c_parser_oacc_clause_wait (parser, clauses); | |
14181 | c_name = "wait"; | |
14182 | break; | |
765dd391 CP |
14183 | case PRAGMA_OACC_CLAUSE_WORKER: |
14184 | c_name = "worker"; | |
14185 | clauses = c_parser_oacc_shape_clause (parser, OMP_CLAUSE_WORKER, | |
14186 | c_name, clauses); | |
14187 | break; | |
41dbbb37 TS |
14188 | default: |
14189 | c_parser_error (parser, "expected %<#pragma acc%> clause"); | |
14190 | goto saw_error; | |
14191 | } | |
14192 | ||
14193 | first = false; | |
14194 | ||
0bb99c11 | 14195 | if (((mask >> c_kind) & 1) == 0) |
41dbbb37 TS |
14196 | { |
14197 | /* Remove the invalid clause(s) from the list to avoid | |
14198 | confusing the rest of the compiler. */ | |
14199 | clauses = prev; | |
14200 | error_at (here, "%qs is not valid for %qs", c_name, where); | |
14201 | } | |
14202 | } | |
14203 | ||
14204 | saw_error: | |
14205 | c_parser_skip_to_pragma_eol (parser); | |
14206 | ||
14207 | if (finish_p) | |
77886428 | 14208 | return c_finish_omp_clauses (clauses, C_ORT_ACC); |
41dbbb37 TS |
14209 | |
14210 | return clauses; | |
14211 | } | |
14212 | ||
acf0174b | 14213 | /* Parse all OpenMP clauses. The set clauses allowed by the directive |
41dbbb37 | 14214 | is a bitmask in MASK. Return the list of clauses found. */ |
acf0174b JJ |
14215 | |
14216 | static tree | |
14217 | c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, | |
14218 | const char *where, bool finish_p = true) | |
14219 | { | |
14220 | tree clauses = NULL; | |
41958c28 | 14221 | bool first = true, cilk_simd_fn = false; |
acf0174b JJ |
14222 | |
14223 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
14224 | { | |
14225 | location_t here; | |
14226 | pragma_omp_clause c_kind; | |
14227 | const char *c_name; | |
14228 | tree prev = clauses; | |
14229 | ||
14230 | if (!first && c_parser_next_token_is (parser, CPP_COMMA)) | |
14231 | c_parser_consume_token (parser); | |
14232 | ||
14233 | here = c_parser_peek_token (parser)->location; | |
14234 | c_kind = c_parser_omp_clause_name (parser); | |
14235 | ||
14236 | switch (c_kind) | |
953ff289 | 14237 | { |
acf0174b JJ |
14238 | case PRAGMA_OMP_CLAUSE_COLLAPSE: |
14239 | clauses = c_parser_omp_clause_collapse (parser, clauses); | |
14240 | c_name = "collapse"; | |
953ff289 | 14241 | break; |
acf0174b JJ |
14242 | case PRAGMA_OMP_CLAUSE_COPYIN: |
14243 | clauses = c_parser_omp_clause_copyin (parser, clauses); | |
14244 | c_name = "copyin"; | |
953ff289 | 14245 | break; |
acf0174b JJ |
14246 | case PRAGMA_OMP_CLAUSE_COPYPRIVATE: |
14247 | clauses = c_parser_omp_clause_copyprivate (parser, clauses); | |
14248 | c_name = "copyprivate"; | |
953ff289 | 14249 | break; |
acf0174b | 14250 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
7a5e4956 | 14251 | clauses = c_parser_omp_clause_default (parser, clauses, false); |
acf0174b | 14252 | c_name = "default"; |
953ff289 | 14253 | break; |
acf0174b JJ |
14254 | case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: |
14255 | clauses = c_parser_omp_clause_firstprivate (parser, clauses); | |
14256 | c_name = "firstprivate"; | |
953ff289 | 14257 | break; |
acf0174b JJ |
14258 | case PRAGMA_OMP_CLAUSE_FINAL: |
14259 | clauses = c_parser_omp_clause_final (parser, clauses); | |
14260 | c_name = "final"; | |
953ff289 | 14261 | break; |
d9a6bd32 JJ |
14262 | case PRAGMA_OMP_CLAUSE_GRAINSIZE: |
14263 | clauses = c_parser_omp_clause_grainsize (parser, clauses); | |
14264 | c_name = "grainsize"; | |
14265 | break; | |
14266 | case PRAGMA_OMP_CLAUSE_HINT: | |
14267 | clauses = c_parser_omp_clause_hint (parser, clauses); | |
14268 | c_name = "hint"; | |
14269 | break; | |
14270 | case PRAGMA_OMP_CLAUSE_DEFAULTMAP: | |
14271 | clauses = c_parser_omp_clause_defaultmap (parser, clauses); | |
14272 | c_name = "defaultmap"; | |
14273 | break; | |
acf0174b | 14274 | case PRAGMA_OMP_CLAUSE_IF: |
d9a6bd32 | 14275 | clauses = c_parser_omp_clause_if (parser, clauses, true); |
acf0174b | 14276 | c_name = "if"; |
953ff289 | 14277 | break; |
acf0174b JJ |
14278 | case PRAGMA_OMP_CLAUSE_LASTPRIVATE: |
14279 | clauses = c_parser_omp_clause_lastprivate (parser, clauses); | |
14280 | c_name = "lastprivate"; | |
953ff289 | 14281 | break; |
acf0174b JJ |
14282 | case PRAGMA_OMP_CLAUSE_MERGEABLE: |
14283 | clauses = c_parser_omp_clause_mergeable (parser, clauses); | |
14284 | c_name = "mergeable"; | |
953ff289 | 14285 | break; |
acf0174b JJ |
14286 | case PRAGMA_OMP_CLAUSE_NOWAIT: |
14287 | clauses = c_parser_omp_clause_nowait (parser, clauses); | |
14288 | c_name = "nowait"; | |
14289 | break; | |
d9a6bd32 JJ |
14290 | case PRAGMA_OMP_CLAUSE_NUM_TASKS: |
14291 | clauses = c_parser_omp_clause_num_tasks (parser, clauses); | |
14292 | c_name = "num_tasks"; | |
14293 | break; | |
acf0174b JJ |
14294 | case PRAGMA_OMP_CLAUSE_NUM_THREADS: |
14295 | clauses = c_parser_omp_clause_num_threads (parser, clauses); | |
14296 | c_name = "num_threads"; | |
14297 | break; | |
14298 | case PRAGMA_OMP_CLAUSE_ORDERED: | |
14299 | clauses = c_parser_omp_clause_ordered (parser, clauses); | |
14300 | c_name = "ordered"; | |
14301 | break; | |
d9a6bd32 JJ |
14302 | case PRAGMA_OMP_CLAUSE_PRIORITY: |
14303 | clauses = c_parser_omp_clause_priority (parser, clauses); | |
14304 | c_name = "priority"; | |
14305 | break; | |
acf0174b JJ |
14306 | case PRAGMA_OMP_CLAUSE_PRIVATE: |
14307 | clauses = c_parser_omp_clause_private (parser, clauses); | |
14308 | c_name = "private"; | |
14309 | break; | |
14310 | case PRAGMA_OMP_CLAUSE_REDUCTION: | |
14311 | clauses = c_parser_omp_clause_reduction (parser, clauses); | |
14312 | c_name = "reduction"; | |
14313 | break; | |
14314 | case PRAGMA_OMP_CLAUSE_SCHEDULE: | |
14315 | clauses = c_parser_omp_clause_schedule (parser, clauses); | |
14316 | c_name = "schedule"; | |
14317 | break; | |
14318 | case PRAGMA_OMP_CLAUSE_SHARED: | |
14319 | clauses = c_parser_omp_clause_shared (parser, clauses); | |
14320 | c_name = "shared"; | |
14321 | break; | |
14322 | case PRAGMA_OMP_CLAUSE_UNTIED: | |
14323 | clauses = c_parser_omp_clause_untied (parser, clauses); | |
14324 | c_name = "untied"; | |
14325 | break; | |
14326 | case PRAGMA_OMP_CLAUSE_INBRANCH: | |
41958c28 | 14327 | case PRAGMA_CILK_CLAUSE_MASK: |
acf0174b JJ |
14328 | clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH, |
14329 | clauses); | |
14330 | c_name = "inbranch"; | |
14331 | break; | |
14332 | case PRAGMA_OMP_CLAUSE_NOTINBRANCH: | |
41958c28 | 14333 | case PRAGMA_CILK_CLAUSE_NOMASK: |
acf0174b JJ |
14334 | clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH, |
14335 | clauses); | |
14336 | c_name = "notinbranch"; | |
14337 | break; | |
14338 | case PRAGMA_OMP_CLAUSE_PARALLEL: | |
14339 | clauses | |
14340 | = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL, | |
14341 | clauses); | |
14342 | c_name = "parallel"; | |
14343 | if (!first) | |
20906c66 | 14344 | { |
acf0174b JJ |
14345 | clause_not_first: |
14346 | error_at (here, "%qs must be the first clause of %qs", | |
14347 | c_name, where); | |
14348 | clauses = prev; | |
14349 | } | |
14350 | break; | |
14351 | case PRAGMA_OMP_CLAUSE_FOR: | |
14352 | clauses | |
14353 | = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR, | |
14354 | clauses); | |
14355 | c_name = "for"; | |
14356 | if (!first) | |
14357 | goto clause_not_first; | |
14358 | break; | |
14359 | case PRAGMA_OMP_CLAUSE_SECTIONS: | |
14360 | clauses | |
14361 | = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS, | |
14362 | clauses); | |
14363 | c_name = "sections"; | |
14364 | if (!first) | |
14365 | goto clause_not_first; | |
14366 | break; | |
14367 | case PRAGMA_OMP_CLAUSE_TASKGROUP: | |
14368 | clauses | |
14369 | = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP, | |
14370 | clauses); | |
14371 | c_name = "taskgroup"; | |
14372 | if (!first) | |
14373 | goto clause_not_first; | |
14374 | break; | |
d9a6bd32 JJ |
14375 | case PRAGMA_OMP_CLAUSE_LINK: |
14376 | clauses | |
14377 | = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LINK, clauses); | |
14378 | c_name = "link"; | |
14379 | break; | |
acf0174b | 14380 | case PRAGMA_OMP_CLAUSE_TO: |
d9a6bd32 JJ |
14381 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0) |
14382 | clauses | |
14383 | = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE, | |
14384 | clauses); | |
14385 | else | |
14386 | clauses = c_parser_omp_clause_to (parser, clauses); | |
acf0174b JJ |
14387 | c_name = "to"; |
14388 | break; | |
14389 | case PRAGMA_OMP_CLAUSE_FROM: | |
14390 | clauses = c_parser_omp_clause_from (parser, clauses); | |
14391 | c_name = "from"; | |
14392 | break; | |
14393 | case PRAGMA_OMP_CLAUSE_UNIFORM: | |
14394 | clauses = c_parser_omp_clause_uniform (parser, clauses); | |
14395 | c_name = "uniform"; | |
14396 | break; | |
14397 | case PRAGMA_OMP_CLAUSE_NUM_TEAMS: | |
14398 | clauses = c_parser_omp_clause_num_teams (parser, clauses); | |
14399 | c_name = "num_teams"; | |
14400 | break; | |
14401 | case PRAGMA_OMP_CLAUSE_THREAD_LIMIT: | |
14402 | clauses = c_parser_omp_clause_thread_limit (parser, clauses); | |
14403 | c_name = "thread_limit"; | |
14404 | break; | |
14405 | case PRAGMA_OMP_CLAUSE_ALIGNED: | |
14406 | clauses = c_parser_omp_clause_aligned (parser, clauses); | |
14407 | c_name = "aligned"; | |
14408 | break; | |
41958c28 BI |
14409 | case PRAGMA_OMP_CLAUSE_LINEAR: |
14410 | if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0) | |
14411 | cilk_simd_fn = true; | |
14412 | clauses = c_parser_omp_clause_linear (parser, clauses, cilk_simd_fn); | |
acf0174b JJ |
14413 | c_name = "linear"; |
14414 | break; | |
14415 | case PRAGMA_OMP_CLAUSE_DEPEND: | |
14416 | clauses = c_parser_omp_clause_depend (parser, clauses); | |
14417 | c_name = "depend"; | |
14418 | break; | |
14419 | case PRAGMA_OMP_CLAUSE_MAP: | |
14420 | clauses = c_parser_omp_clause_map (parser, clauses); | |
14421 | c_name = "map"; | |
14422 | break; | |
d9a6bd32 JJ |
14423 | case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR: |
14424 | clauses = c_parser_omp_clause_use_device_ptr (parser, clauses); | |
14425 | c_name = "use_device_ptr"; | |
14426 | break; | |
14427 | case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR: | |
14428 | clauses = c_parser_omp_clause_is_device_ptr (parser, clauses); | |
14429 | c_name = "is_device_ptr"; | |
14430 | break; | |
acf0174b JJ |
14431 | case PRAGMA_OMP_CLAUSE_DEVICE: |
14432 | clauses = c_parser_omp_clause_device (parser, clauses); | |
14433 | c_name = "device"; | |
14434 | break; | |
14435 | case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE: | |
14436 | clauses = c_parser_omp_clause_dist_schedule (parser, clauses); | |
14437 | c_name = "dist_schedule"; | |
14438 | break; | |
14439 | case PRAGMA_OMP_CLAUSE_PROC_BIND: | |
14440 | clauses = c_parser_omp_clause_proc_bind (parser, clauses); | |
14441 | c_name = "proc_bind"; | |
14442 | break; | |
14443 | case PRAGMA_OMP_CLAUSE_SAFELEN: | |
14444 | clauses = c_parser_omp_clause_safelen (parser, clauses); | |
14445 | c_name = "safelen"; | |
14446 | break; | |
41958c28 BI |
14447 | case PRAGMA_CILK_CLAUSE_VECTORLENGTH: |
14448 | clauses = c_parser_cilk_clause_vectorlength (parser, clauses, true); | |
14449 | c_name = "simdlen"; | |
14450 | break; | |
acf0174b JJ |
14451 | case PRAGMA_OMP_CLAUSE_SIMDLEN: |
14452 | clauses = c_parser_omp_clause_simdlen (parser, clauses); | |
14453 | c_name = "simdlen"; | |
14454 | break; | |
d9a6bd32 JJ |
14455 | case PRAGMA_OMP_CLAUSE_NOGROUP: |
14456 | clauses = c_parser_omp_clause_nogroup (parser, clauses); | |
14457 | c_name = "nogroup"; | |
14458 | break; | |
14459 | case PRAGMA_OMP_CLAUSE_THREADS: | |
14460 | clauses | |
14461 | = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS, | |
14462 | clauses); | |
14463 | c_name = "threads"; | |
14464 | break; | |
14465 | case PRAGMA_OMP_CLAUSE_SIMD: | |
14466 | clauses | |
14467 | = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD, | |
14468 | clauses); | |
14469 | c_name = "simd"; | |
14470 | break; | |
953ff289 | 14471 | default: |
acf0174b | 14472 | c_parser_error (parser, "expected %<#pragma omp%> clause"); |
953ff289 DN |
14473 | goto saw_error; |
14474 | } | |
14475 | ||
acf0174b JJ |
14476 | first = false; |
14477 | ||
0bb99c11 | 14478 | if (((mask >> c_kind) & 1) == 0) |
acf0174b JJ |
14479 | { |
14480 | /* Remove the invalid clause(s) from the list to avoid | |
14481 | confusing the rest of the compiler. */ | |
14482 | clauses = prev; | |
14483 | error_at (here, "%qs is not valid for %qs", c_name, where); | |
14484 | } | |
14485 | } | |
14486 | ||
14487 | saw_error: | |
14488 | c_parser_skip_to_pragma_eol (parser); | |
14489 | ||
14490 | if (finish_p) | |
d9a6bd32 JJ |
14491 | { |
14492 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0) | |
77886428 CP |
14493 | return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD); |
14494 | return c_finish_omp_clauses (clauses, C_ORT_OMP); | |
d9a6bd32 | 14495 | } |
acf0174b JJ |
14496 | |
14497 | return clauses; | |
14498 | } | |
14499 | ||
41dbbb37 | 14500 | /* OpenACC 2.0, OpenMP 2.5: |
acf0174b JJ |
14501 | structured-block: |
14502 | statement | |
14503 | ||
14504 | In practice, we're also interested in adding the statement to an | |
14505 | outer node. So it is convenient if we work around the fact that | |
14506 | c_parser_statement calls add_stmt. */ | |
14507 | ||
14508 | static tree | |
dda1bf61 | 14509 | c_parser_omp_structured_block (c_parser *parser, bool *if_p) |
acf0174b JJ |
14510 | { |
14511 | tree stmt = push_stmt_list (); | |
dda1bf61 | 14512 | c_parser_statement (parser, if_p); |
acf0174b JJ |
14513 | return pop_stmt_list (stmt); |
14514 | } | |
14515 | ||
41dbbb37 TS |
14516 | /* OpenACC 2.0: |
14517 | # pragma acc cache (variable-list) new-line | |
14518 | ||
14519 | LOC is the location of the #pragma token. | |
14520 | */ | |
14521 | ||
14522 | static tree | |
14523 | c_parser_oacc_cache (location_t loc, c_parser *parser) | |
14524 | { | |
14525 | tree stmt, clauses; | |
14526 | ||
14527 | clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL); | |
77886428 | 14528 | clauses = c_finish_omp_clauses (clauses, C_ORT_ACC); |
41dbbb37 TS |
14529 | |
14530 | c_parser_skip_to_pragma_eol (parser); | |
14531 | ||
14532 | stmt = make_node (OACC_CACHE); | |
14533 | TREE_TYPE (stmt) = void_type_node; | |
14534 | OACC_CACHE_CLAUSES (stmt) = clauses; | |
14535 | SET_EXPR_LOCATION (stmt, loc); | |
14536 | add_stmt (stmt); | |
14537 | ||
14538 | return stmt; | |
14539 | } | |
14540 | ||
14541 | /* OpenACC 2.0: | |
14542 | # pragma acc data oacc-data-clause[optseq] new-line | |
14543 | structured-block | |
14544 | ||
14545 | LOC is the location of the #pragma token. | |
14546 | */ | |
14547 | ||
14548 | #define OACC_DATA_CLAUSE_MASK \ | |
14549 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ | |
14550 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | |
14551 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | |
14552 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | |
14553 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ | |
14554 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
14555 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ | |
14556 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ | |
14557 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ | |
14558 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ | |
14559 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) ) | |
14560 | ||
14561 | static tree | |
dda1bf61 | 14562 | c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p) |
41dbbb37 TS |
14563 | { |
14564 | tree stmt, clauses, block; | |
14565 | ||
14566 | clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK, | |
14567 | "#pragma acc data"); | |
14568 | ||
14569 | block = c_begin_omp_parallel (); | |
dda1bf61 | 14570 | add_stmt (c_parser_omp_structured_block (parser, if_p)); |
41dbbb37 TS |
14571 | |
14572 | stmt = c_finish_oacc_data (loc, clauses, block); | |
14573 | ||
14574 | return stmt; | |
14575 | } | |
14576 | ||
6e232ba4 JN |
14577 | /* OpenACC 2.0: |
14578 | # pragma acc declare oacc-data-clause[optseq] new-line | |
14579 | */ | |
14580 | ||
14581 | #define OACC_DECLARE_CLAUSE_MASK \ | |
14582 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ | |
14583 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | |
14584 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | |
14585 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | |
14586 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ | |
14587 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \ | |
14588 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \ | |
14589 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ | |
14590 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ | |
14591 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ | |
14592 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ | |
14593 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) ) | |
14594 | ||
14595 | static void | |
14596 | c_parser_oacc_declare (c_parser *parser) | |
14597 | { | |
14598 | location_t pragma_loc = c_parser_peek_token (parser)->location; | |
14599 | tree clauses, stmt, t, decl; | |
14600 | ||
14601 | bool error = false; | |
14602 | ||
14603 | c_parser_consume_pragma (parser); | |
14604 | ||
14605 | clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK, | |
14606 | "#pragma acc declare"); | |
14607 | if (!clauses) | |
14608 | { | |
14609 | error_at (pragma_loc, | |
14610 | "no valid clauses specified in %<#pragma acc declare%>"); | |
14611 | return; | |
14612 | } | |
14613 | ||
14614 | for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) | |
14615 | { | |
14616 | location_t loc = OMP_CLAUSE_LOCATION (t); | |
14617 | decl = OMP_CLAUSE_DECL (t); | |
14618 | if (!DECL_P (decl)) | |
14619 | { | |
14620 | error_at (loc, "array section in %<#pragma acc declare%>"); | |
14621 | error = true; | |
14622 | continue; | |
14623 | } | |
14624 | ||
14625 | switch (OMP_CLAUSE_MAP_KIND (t)) | |
14626 | { | |
e46c7770 | 14627 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
6e232ba4 JN |
14628 | case GOMP_MAP_FORCE_ALLOC: |
14629 | case GOMP_MAP_FORCE_TO: | |
14630 | case GOMP_MAP_FORCE_DEVICEPTR: | |
14631 | case GOMP_MAP_DEVICE_RESIDENT: | |
14632 | break; | |
14633 | ||
6e232ba4 JN |
14634 | case GOMP_MAP_LINK: |
14635 | if (!global_bindings_p () | |
14636 | && (TREE_STATIC (decl) | |
14637 | || !DECL_EXTERNAL (decl))) | |
14638 | { | |
14639 | error_at (loc, | |
aa326bfb | 14640 | "%qD must be a global variable in " |
6e232ba4 JN |
14641 | "%<#pragma acc declare link%>", |
14642 | decl); | |
14643 | error = true; | |
14644 | continue; | |
14645 | } | |
14646 | break; | |
14647 | ||
14648 | default: | |
14649 | if (global_bindings_p ()) | |
14650 | { | |
14651 | error_at (loc, "invalid OpenACC clause at file scope"); | |
14652 | error = true; | |
14653 | continue; | |
14654 | } | |
14655 | if (DECL_EXTERNAL (decl)) | |
14656 | { | |
14657 | error_at (loc, | |
14658 | "invalid use of %<extern%> variable %qD " | |
14659 | "in %<#pragma acc declare%>", decl); | |
14660 | error = true; | |
14661 | continue; | |
14662 | } | |
14663 | else if (TREE_PUBLIC (decl)) | |
14664 | { | |
14665 | error_at (loc, | |
14666 | "invalid use of %<global%> variable %qD " | |
14667 | "in %<#pragma acc declare%>", decl); | |
14668 | error = true; | |
14669 | continue; | |
14670 | } | |
14671 | break; | |
14672 | } | |
14673 | ||
14674 | if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)) | |
14675 | || lookup_attribute ("omp declare target link", | |
14676 | DECL_ATTRIBUTES (decl))) | |
14677 | { | |
14678 | error_at (loc, "variable %qD used more than once with " | |
14679 | "%<#pragma acc declare%>", decl); | |
14680 | error = true; | |
14681 | continue; | |
14682 | } | |
14683 | ||
14684 | if (!error) | |
14685 | { | |
14686 | tree id; | |
14687 | ||
14688 | if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK) | |
14689 | id = get_identifier ("omp declare target link"); | |
14690 | else | |
14691 | id = get_identifier ("omp declare target"); | |
14692 | ||
14693 | DECL_ATTRIBUTES (decl) | |
14694 | = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl)); | |
14695 | ||
14696 | if (global_bindings_p ()) | |
14697 | { | |
14698 | symtab_node *node = symtab_node::get (decl); | |
14699 | if (node != NULL) | |
14700 | { | |
14701 | node->offloadable = 1; | |
688c4de0 | 14702 | if (ENABLE_OFFLOADING) |
6e232ba4 | 14703 | { |
688c4de0 IV |
14704 | g->have_offload = true; |
14705 | if (is_a <varpool_node *> (node)) | |
e6d6ec9e | 14706 | vec_safe_push (offload_vars, decl); |
6e232ba4 | 14707 | } |
6e232ba4 JN |
14708 | } |
14709 | } | |
14710 | } | |
14711 | } | |
14712 | ||
14713 | if (error || global_bindings_p ()) | |
14714 | return; | |
14715 | ||
14716 | stmt = make_node (OACC_DECLARE); | |
14717 | TREE_TYPE (stmt) = void_type_node; | |
14718 | OACC_DECLARE_CLAUSES (stmt) = clauses; | |
14719 | SET_EXPR_LOCATION (stmt, pragma_loc); | |
14720 | ||
14721 | add_stmt (stmt); | |
14722 | ||
14723 | return; | |
14724 | } | |
14725 | ||
41dbbb37 TS |
14726 | /* OpenACC 2.0: |
14727 | # pragma acc enter data oacc-enter-data-clause[optseq] new-line | |
14728 | ||
14729 | or | |
14730 | ||
14731 | # pragma acc exit data oacc-exit-data-clause[optseq] new-line | |
14732 | ||
14733 | ||
14734 | LOC is the location of the #pragma token. | |
14735 | */ | |
14736 | ||
14737 | #define OACC_ENTER_DATA_CLAUSE_MASK \ | |
14738 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
14739 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | |
14740 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | |
14741 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | |
14742 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ | |
14743 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | |
14744 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) | |
14745 | ||
14746 | #define OACC_EXIT_DATA_CLAUSE_MASK \ | |
14747 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
14748 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | |
14749 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | |
14750 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \ | |
14751 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) | |
14752 | ||
14753 | static void | |
14754 | c_parser_oacc_enter_exit_data (c_parser *parser, bool enter) | |
14755 | { | |
14756 | location_t loc = c_parser_peek_token (parser)->location; | |
14757 | tree clauses, stmt; | |
c5af52eb | 14758 | const char *p = ""; |
41dbbb37 TS |
14759 | |
14760 | c_parser_consume_pragma (parser); | |
14761 | ||
c5af52eb | 14762 | if (c_parser_next_token_is (parser, CPP_NAME)) |
41dbbb37 | 14763 | { |
c5af52eb CP |
14764 | p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
14765 | c_parser_consume_token (parser); | |
41dbbb37 TS |
14766 | } |
14767 | ||
41dbbb37 TS |
14768 | if (strcmp (p, "data") != 0) |
14769 | { | |
324ff1a0 JJ |
14770 | error_at (loc, "expected %<data%> after %<#pragma acc %s%>", |
14771 | enter ? "enter" : "exit"); | |
c5af52eb | 14772 | parser->error = true; |
41dbbb37 TS |
14773 | c_parser_skip_to_pragma_eol (parser); |
14774 | return; | |
14775 | } | |
14776 | ||
41dbbb37 TS |
14777 | if (enter) |
14778 | clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK, | |
14779 | "#pragma acc enter data"); | |
14780 | else | |
14781 | clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK, | |
14782 | "#pragma acc exit data"); | |
14783 | ||
629b3d75 | 14784 | if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE) |
41dbbb37 | 14785 | { |
324ff1a0 JJ |
14786 | error_at (loc, "%<#pragma acc %s data%> has no data movement clause", |
14787 | enter ? "enter" : "exit"); | |
41dbbb37 TS |
14788 | return; |
14789 | } | |
14790 | ||
06aca1d5 | 14791 | stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA); |
41dbbb37 | 14792 | TREE_TYPE (stmt) = void_type_node; |
b811915d | 14793 | OMP_STANDALONE_CLAUSES (stmt) = clauses; |
41dbbb37 TS |
14794 | SET_EXPR_LOCATION (stmt, loc); |
14795 | add_stmt (stmt); | |
14796 | } | |
14797 | ||
14798 | ||
37d5ad46 JB |
14799 | /* OpenACC 2.0: |
14800 | # pragma acc host_data oacc-data-clause[optseq] new-line | |
14801 | structured-block | |
14802 | */ | |
14803 | ||
14804 | #define OACC_HOST_DATA_CLAUSE_MASK \ | |
14805 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) ) | |
14806 | ||
14807 | static tree | |
dda1bf61 | 14808 | c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p) |
37d5ad46 JB |
14809 | { |
14810 | tree stmt, clauses, block; | |
14811 | ||
14812 | clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK, | |
14813 | "#pragma acc host_data"); | |
14814 | ||
14815 | block = c_begin_omp_parallel (); | |
dda1bf61 | 14816 | add_stmt (c_parser_omp_structured_block (parser, if_p)); |
37d5ad46 JB |
14817 | stmt = c_finish_oacc_host_data (loc, clauses, block); |
14818 | return stmt; | |
14819 | } | |
14820 | ||
14821 | ||
41dbbb37 TS |
14822 | /* OpenACC 2.0: |
14823 | ||
14824 | # pragma acc loop oacc-loop-clause[optseq] new-line | |
14825 | structured-block | |
14826 | ||
14827 | LOC is the location of the #pragma token. | |
14828 | */ | |
14829 | ||
14830 | #define OACC_LOOP_CLAUSE_MASK \ | |
14831 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \ | |
7a5e4956 CP |
14832 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
14833 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ | |
765dd391 CP |
14834 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ |
14835 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ | |
14836 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ | |
14837 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \ | |
7a5e4956 | 14838 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \ |
765dd391 | 14839 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ |
7a5e4956 | 14840 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) ) |
41dbbb37 | 14841 | static tree |
88bae6f4 | 14842 | c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name, |
dda1bf61 | 14843 | omp_clause_mask mask, tree *cclauses, bool *if_p) |
41dbbb37 | 14844 | { |
e7ff0319 CP |
14845 | bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1; |
14846 | ||
41dbbb37 | 14847 | strcat (p_name, " loop"); |
88bae6f4 | 14848 | mask |= OACC_LOOP_CLAUSE_MASK; |
41dbbb37 | 14849 | |
88bae6f4 TS |
14850 | tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name, |
14851 | cclauses == NULL); | |
14852 | if (cclauses) | |
14853 | { | |
e7ff0319 | 14854 | clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel); |
88bae6f4 | 14855 | if (*cclauses) |
77886428 | 14856 | *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC); |
88bae6f4 | 14857 | if (clauses) |
77886428 | 14858 | clauses = c_finish_omp_clauses (clauses, C_ORT_ACC); |
88bae6f4 | 14859 | } |
41dbbb37 | 14860 | |
88bae6f4 | 14861 | tree block = c_begin_compound_stmt (true); |
dda1bf61 JJ |
14862 | tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL, |
14863 | if_p); | |
41dbbb37 TS |
14864 | block = c_end_compound_stmt (loc, block, true); |
14865 | add_stmt (block); | |
14866 | ||
14867 | return stmt; | |
14868 | } | |
14869 | ||
14870 | /* OpenACC 2.0: | |
88bae6f4 TS |
14871 | # pragma acc kernels oacc-kernels-clause[optseq] new-line |
14872 | structured-block | |
14873 | ||
14874 | or | |
14875 | ||
41dbbb37 TS |
14876 | # pragma acc parallel oacc-parallel-clause[optseq] new-line |
14877 | structured-block | |
14878 | ||
14879 | LOC is the location of the #pragma token. | |
14880 | */ | |
14881 | ||
88bae6f4 TS |
14882 | #define OACC_KERNELS_CLAUSE_MASK \ |
14883 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | |
14884 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ | |
14885 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | |
14886 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | |
14887 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | |
7a5e4956 | 14888 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
88bae6f4 TS |
14889 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
14890 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
fd71a9a2 TS |
14891 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
14892 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ | |
88bae6f4 TS |
14893 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
14894 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ | |
14895 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ | |
14896 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ | |
14897 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | |
fd71a9a2 | 14898 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ |
88bae6f4 TS |
14899 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
14900 | ||
41dbbb37 TS |
14901 | #define OACC_PARALLEL_CLAUSE_MASK \ |
14902 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | |
14903 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ | |
14904 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | |
14905 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | |
14906 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | |
7a5e4956 | 14907 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
41dbbb37 TS |
14908 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
14909 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
7a5e4956 CP |
14910 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
14911 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \ | |
41dbbb37 TS |
14912 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
14913 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ | |
14914 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ | |
14915 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ | |
14916 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ | |
14917 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ | |
14918 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | |
14919 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ | |
14920 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ | |
14921 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) | |
14922 | ||
14923 | static tree | |
88bae6f4 | 14924 | c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser, |
dda1bf61 JJ |
14925 | enum pragma_kind p_kind, char *p_name, |
14926 | bool *if_p) | |
41dbbb37 | 14927 | { |
88bae6f4 TS |
14928 | omp_clause_mask mask; |
14929 | enum tree_code code; | |
14930 | switch (p_kind) | |
14931 | { | |
14932 | case PRAGMA_OACC_KERNELS: | |
14933 | strcat (p_name, " kernels"); | |
14934 | mask = OACC_KERNELS_CLAUSE_MASK; | |
14935 | code = OACC_KERNELS; | |
14936 | break; | |
14937 | case PRAGMA_OACC_PARALLEL: | |
14938 | strcat (p_name, " parallel"); | |
14939 | mask = OACC_PARALLEL_CLAUSE_MASK; | |
14940 | code = OACC_PARALLEL; | |
14941 | break; | |
14942 | default: | |
14943 | gcc_unreachable (); | |
14944 | } | |
41dbbb37 TS |
14945 | |
14946 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
14947 | { | |
14948 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
14949 | if (strcmp (p, "loop") == 0) | |
14950 | { | |
14951 | c_parser_consume_token (parser); | |
88bae6f4 TS |
14952 | tree block = c_begin_omp_parallel (); |
14953 | tree clauses; | |
dda1bf61 | 14954 | c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p); |
88bae6f4 | 14955 | return c_finish_omp_construct (loc, code, block, clauses); |
41dbbb37 TS |
14956 | } |
14957 | } | |
14958 | ||
88bae6f4 | 14959 | tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name); |
41dbbb37 | 14960 | |
88bae6f4 | 14961 | tree block = c_begin_omp_parallel (); |
dda1bf61 | 14962 | add_stmt (c_parser_omp_structured_block (parser, if_p)); |
41dbbb37 | 14963 | |
88bae6f4 | 14964 | return c_finish_omp_construct (loc, code, block, clauses); |
41dbbb37 TS |
14965 | } |
14966 | ||
3a40d81d NS |
14967 | /* OpenACC 2.0: |
14968 | # pragma acc routine oacc-routine-clause[optseq] new-line | |
14969 | function-definition | |
14970 | ||
14971 | # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line | |
14972 | */ | |
14973 | ||
14974 | #define OACC_ROUTINE_CLAUSE_MASK \ | |
14975 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ | |
14976 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ | |
14977 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ | |
14978 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) ) | |
14979 | ||
14980 | /* Parse an OpenACC routine directive. For named directives, we apply | |
14981 | immediately to the named function. For unnamed ones we then parse | |
14982 | a declaration or definition, which must be for a function. */ | |
14983 | ||
14984 | static void | |
14985 | c_parser_oacc_routine (c_parser *parser, enum pragma_context context) | |
14986 | { | |
ae9281fc TS |
14987 | gcc_checking_assert (context == pragma_external); |
14988 | ||
0b212d8c | 14989 | oacc_routine_data data; |
ae9281fc TS |
14990 | data.error_seen = false; |
14991 | data.fndecl_seen = false; | |
0b212d8c TS |
14992 | data.clauses = NULL_TREE; |
14993 | data.loc = c_parser_peek_token (parser)->location; | |
3a40d81d NS |
14994 | |
14995 | c_parser_consume_pragma (parser); | |
14996 | ||
ae9281fc TS |
14997 | /* Look for optional '( name )'. */ |
14998 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
3a40d81d | 14999 | { |
ae9281fc | 15000 | c_parser_consume_token (parser); /* '(' */ |
3a40d81d | 15001 | |
ae9281fc TS |
15002 | tree decl = NULL_TREE; |
15003 | c_token *name_token = c_parser_peek_token (parser); | |
15004 | location_t name_loc = name_token->location; | |
15005 | if (name_token->type == CPP_NAME | |
15006 | && (name_token->id_kind == C_ID_ID | |
15007 | || name_token->id_kind == C_ID_TYPENAME)) | |
3a40d81d | 15008 | { |
ae9281fc | 15009 | decl = lookup_name (name_token->value); |
3a40d81d | 15010 | if (!decl) |
ae9281fc TS |
15011 | error_at (name_loc, |
15012 | "%qE has not been declared", name_token->value); | |
a04e69c0 | 15013 | c_parser_consume_token (parser); |
3a40d81d NS |
15014 | } |
15015 | else | |
15016 | c_parser_error (parser, "expected function name"); | |
15017 | ||
a04e69c0 TS |
15018 | if (!decl |
15019 | || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |
15020 | { | |
15021 | c_parser_skip_to_pragma_eol (parser, false); | |
15022 | return; | |
15023 | } | |
ae9281fc TS |
15024 | |
15025 | data.clauses | |
15026 | = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, | |
15027 | "#pragma acc routine"); | |
15028 | ||
15029 | if (TREE_CODE (decl) != FUNCTION_DECL) | |
15030 | { | |
15031 | error_at (name_loc, "%qD does not refer to a function", decl); | |
15032 | return; | |
15033 | } | |
15034 | ||
15035 | c_finish_oacc_routine (&data, decl, false); | |
3a40d81d | 15036 | } |
ae9281fc TS |
15037 | else /* No optional '( name )'. */ |
15038 | { | |
15039 | data.clauses | |
15040 | = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, | |
15041 | "#pragma acc routine"); | |
3a40d81d | 15042 | |
ae9281fc TS |
15043 | /* Emit a helpful diagnostic if there's another pragma following this |
15044 | one. Also don't allow a static assertion declaration, as in the | |
15045 | following we'll just parse a *single* "declaration or function | |
15046 | definition", and the static assertion counts an one. */ | |
15047 | if (c_parser_next_token_is (parser, CPP_PRAGMA) | |
15048 | || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) | |
15049 | { | |
15050 | error_at (data.loc, | |
15051 | "%<#pragma acc routine%> not immediately followed by" | |
15052 | " function declaration or definition"); | |
15053 | /* ..., and then just keep going. */ | |
15054 | return; | |
15055 | } | |
15056 | ||
15057 | /* We only have to consider the pragma_external case here. */ | |
15058 | if (c_parser_next_token_is (parser, CPP_KEYWORD) | |
15059 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION) | |
15060 | { | |
15061 | int ext = disable_extension_diagnostics (); | |
15062 | do | |
15063 | c_parser_consume_token (parser); | |
15064 | while (c_parser_next_token_is (parser, CPP_KEYWORD) | |
15065 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION); | |
15066 | c_parser_declaration_or_fndef (parser, true, true, true, false, true, | |
15067 | NULL, vNULL, &data); | |
15068 | restore_extension_diagnostics (ext); | |
15069 | } | |
15070 | else | |
15071 | c_parser_declaration_or_fndef (parser, true, true, true, false, true, | |
15072 | NULL, vNULL, &data); | |
15073 | } | |
3a40d81d NS |
15074 | } |
15075 | ||
0b212d8c TS |
15076 | /* Finalize an OpenACC routine pragma, applying it to FNDECL. |
15077 | IS_DEFN is true if we're applying it to the definition. */ | |
3a40d81d NS |
15078 | |
15079 | static void | |
0b212d8c | 15080 | c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl, |
ae9281fc | 15081 | bool is_defn) |
3a40d81d | 15082 | { |
ae9281fc TS |
15083 | /* Keep going if we're in error reporting mode. */ |
15084 | if (data->error_seen | |
15085 | || fndecl == error_mark_node) | |
15086 | return; | |
15087 | ||
15088 | if (data->fndecl_seen) | |
3a40d81d | 15089 | { |
ae9281fc TS |
15090 | error_at (data->loc, |
15091 | "%<#pragma acc routine%> not immediately followed by" | |
15092 | " a single function declaration or definition"); | |
15093 | data->error_seen = true; | |
15094 | return; | |
15095 | } | |
15096 | if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) | |
15097 | { | |
15098 | error_at (data->loc, | |
15099 | "%<#pragma acc routine%> not immediately followed by" | |
15100 | " function declaration or definition"); | |
15101 | data->error_seen = true; | |
3a40d81d NS |
15102 | return; |
15103 | } | |
15104 | ||
629b3d75 | 15105 | if (oacc_get_fn_attrib (fndecl)) |
ae9281fc TS |
15106 | { |
15107 | error_at (data->loc, | |
15108 | "%<#pragma acc routine%> already applied to %qD", fndecl); | |
15109 | data->error_seen = true; | |
15110 | return; | |
15111 | } | |
3a40d81d NS |
15112 | |
15113 | if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl))) | |
ae9281fc TS |
15114 | { |
15115 | error_at (data->loc, | |
324ff1a0 JJ |
15116 | TREE_USED (fndecl) |
15117 | ? G_("%<#pragma acc routine%> must be applied before use") | |
15118 | : G_("%<#pragma acc routine%> must be applied before " | |
15119 | "definition")); | |
ae9281fc TS |
15120 | data->error_seen = true; |
15121 | return; | |
15122 | } | |
3a40d81d | 15123 | |
0b212d8c | 15124 | /* Process the routine's dimension clauses. */ |
629b3d75 MJ |
15125 | tree dims = oacc_build_routine_dims (data->clauses); |
15126 | oacc_replace_fn_attrib (fndecl, dims); | |
3a40d81d | 15127 | |
0b212d8c | 15128 | /* Add an "omp declare target" attribute. */ |
3a40d81d NS |
15129 | DECL_ATTRIBUTES (fndecl) |
15130 | = tree_cons (get_identifier ("omp declare target"), | |
0b212d8c | 15131 | NULL_TREE, DECL_ATTRIBUTES (fndecl)); |
ae9281fc TS |
15132 | |
15133 | /* Remember that we've used this "#pragma acc routine". */ | |
15134 | data->fndecl_seen = true; | |
3a40d81d NS |
15135 | } |
15136 | ||
41dbbb37 TS |
15137 | /* OpenACC 2.0: |
15138 | # pragma acc update oacc-update-clause[optseq] new-line | |
15139 | */ | |
15140 | ||
15141 | #define OACC_UPDATE_CLAUSE_MASK \ | |
15142 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | |
15143 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \ | |
15144 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \ | |
15145 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ | |
15146 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ | |
15147 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) | |
15148 | ||
15149 | static void | |
15150 | c_parser_oacc_update (c_parser *parser) | |
15151 | { | |
15152 | location_t loc = c_parser_peek_token (parser)->location; | |
15153 | ||
15154 | c_parser_consume_pragma (parser); | |
15155 | ||
15156 | tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK, | |
15157 | "#pragma acc update"); | |
629b3d75 | 15158 | if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE) |
41dbbb37 TS |
15159 | { |
15160 | error_at (loc, | |
15161 | "%<#pragma acc update%> must contain at least one " | |
7a5e4956 | 15162 | "%<device%> or %<host%> or %<self%> clause"); |
41dbbb37 TS |
15163 | return; |
15164 | } | |
15165 | ||
15166 | if (parser->error) | |
15167 | return; | |
15168 | ||
15169 | tree stmt = make_node (OACC_UPDATE); | |
15170 | TREE_TYPE (stmt) = void_type_node; | |
15171 | OACC_UPDATE_CLAUSES (stmt) = clauses; | |
15172 | SET_EXPR_LOCATION (stmt, loc); | |
15173 | add_stmt (stmt); | |
15174 | } | |
15175 | ||
15176 | /* OpenACC 2.0: | |
15177 | # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line | |
15178 | ||
15179 | LOC is the location of the #pragma token. | |
15180 | */ | |
15181 | ||
15182 | #define OACC_WAIT_CLAUSE_MASK \ | |
15183 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) ) | |
15184 | ||
15185 | static tree | |
15186 | c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name) | |
15187 | { | |
15188 | tree clauses, list = NULL_TREE, stmt = NULL_TREE; | |
15189 | ||
15190 | if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN) | |
15191 | list = c_parser_oacc_wait_list (parser, loc, list); | |
15192 | ||
15193 | strcpy (p_name, " wait"); | |
15194 | clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, p_name); | |
15195 | stmt = c_finish_oacc_wait (loc, list, clauses); | |
04d2fbcc | 15196 | add_stmt (stmt); |
41dbbb37 TS |
15197 | |
15198 | return stmt; | |
15199 | } | |
15200 | ||
acf0174b JJ |
15201 | /* OpenMP 2.5: |
15202 | # pragma omp atomic new-line | |
15203 | expression-stmt | |
15204 | ||
15205 | expression-stmt: | |
15206 | x binop= expr | x++ | ++x | x-- | --x | |
15207 | binop: | |
15208 | +, *, -, /, &, ^, |, <<, >> | |
15209 | ||
15210 | where x is an lvalue expression with scalar type. | |
15211 | ||
15212 | OpenMP 3.1: | |
15213 | # pragma omp atomic new-line | |
15214 | update-stmt | |
15215 | ||
15216 | # pragma omp atomic read new-line | |
15217 | read-stmt | |
15218 | ||
15219 | # pragma omp atomic write new-line | |
15220 | write-stmt | |
15221 | ||
15222 | # pragma omp atomic update new-line | |
15223 | update-stmt | |
15224 | ||
15225 | # pragma omp atomic capture new-line | |
15226 | capture-stmt | |
15227 | ||
15228 | # pragma omp atomic capture new-line | |
15229 | capture-block | |
15230 | ||
15231 | read-stmt: | |
15232 | v = x | |
15233 | write-stmt: | |
15234 | x = expr | |
15235 | update-stmt: | |
15236 | expression-stmt | x = x binop expr | |
15237 | capture-stmt: | |
15238 | v = expression-stmt | |
15239 | capture-block: | |
15240 | { v = x; update-stmt; } | { update-stmt; v = x; } | |
15241 | ||
15242 | OpenMP 4.0: | |
15243 | update-stmt: | |
15244 | expression-stmt | x = x binop expr | x = expr binop x | |
15245 | capture-stmt: | |
15246 | v = update-stmt | |
15247 | capture-block: | |
15248 | { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; } | |
15249 | ||
15250 | where x and v are lvalue expressions with scalar type. | |
15251 | ||
15252 | LOC is the location of the #pragma token. */ | |
15253 | ||
15254 | static void | |
15255 | c_parser_omp_atomic (location_t loc, c_parser *parser) | |
15256 | { | |
15257 | tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE; | |
15258 | tree lhs1 = NULL_TREE, rhs1 = NULL_TREE; | |
15259 | tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE; | |
15260 | enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR; | |
15261 | struct c_expr expr; | |
15262 | location_t eloc; | |
15263 | bool structured_block = false; | |
15264 | bool swapped = false; | |
15265 | bool seq_cst = false; | |
f4b189d5 | 15266 | bool non_lvalue_p; |
acf0174b | 15267 | |
42056eac JJ |
15268 | if (c_parser_next_token_is (parser, CPP_NAME)) |
15269 | { | |
15270 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
15271 | if (!strcmp (p, "seq_cst")) | |
15272 | { | |
15273 | seq_cst = true; | |
15274 | c_parser_consume_token (parser); | |
15275 | if (c_parser_next_token_is (parser, CPP_COMMA) | |
15276 | && c_parser_peek_2nd_token (parser)->type == CPP_NAME) | |
15277 | c_parser_consume_token (parser); | |
15278 | } | |
15279 | } | |
acf0174b JJ |
15280 | if (c_parser_next_token_is (parser, CPP_NAME)) |
15281 | { | |
15282 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
15283 | ||
15284 | if (!strcmp (p, "read")) | |
15285 | code = OMP_ATOMIC_READ; | |
15286 | else if (!strcmp (p, "write")) | |
15287 | code = NOP_EXPR; | |
15288 | else if (!strcmp (p, "update")) | |
15289 | code = OMP_ATOMIC; | |
15290 | else if (!strcmp (p, "capture")) | |
15291 | code = OMP_ATOMIC_CAPTURE_NEW; | |
15292 | else | |
15293 | p = NULL; | |
15294 | if (p) | |
15295 | c_parser_consume_token (parser); | |
15296 | } | |
42056eac | 15297 | if (!seq_cst) |
acf0174b | 15298 | { |
42056eac JJ |
15299 | if (c_parser_next_token_is (parser, CPP_COMMA) |
15300 | && c_parser_peek_2nd_token (parser)->type == CPP_NAME) | |
15301 | c_parser_consume_token (parser); | |
15302 | ||
15303 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
acf0174b | 15304 | { |
42056eac JJ |
15305 | const char *p |
15306 | = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
15307 | if (!strcmp (p, "seq_cst")) | |
15308 | { | |
15309 | seq_cst = true; | |
15310 | c_parser_consume_token (parser); | |
15311 | } | |
acf0174b JJ |
15312 | } |
15313 | } | |
15314 | c_parser_skip_to_pragma_eol (parser); | |
15315 | ||
15316 | switch (code) | |
15317 | { | |
15318 | case OMP_ATOMIC_READ: | |
15319 | case NOP_EXPR: /* atomic write */ | |
f4b189d5 JJ |
15320 | v = c_parser_cast_expression (parser, NULL).value; |
15321 | non_lvalue_p = !lvalue_p (v); | |
f9c59f7e | 15322 | v = c_fully_fold (v, false, NULL, true); |
acf0174b JJ |
15323 | if (v == error_mark_node) |
15324 | goto saw_error; | |
f4b189d5 JJ |
15325 | if (non_lvalue_p) |
15326 | v = non_lvalue (v); | |
acf0174b JJ |
15327 | loc = c_parser_peek_token (parser)->location; |
15328 | if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) | |
15329 | goto saw_error; | |
15330 | if (code == NOP_EXPR) | |
f4b189d5 JJ |
15331 | { |
15332 | lhs = c_parser_expression (parser).value; | |
15333 | lhs = c_fully_fold (lhs, false, NULL); | |
15334 | if (lhs == error_mark_node) | |
15335 | goto saw_error; | |
15336 | } | |
acf0174b | 15337 | else |
f4b189d5 JJ |
15338 | { |
15339 | lhs = c_parser_cast_expression (parser, NULL).value; | |
15340 | non_lvalue_p = !lvalue_p (lhs); | |
f9c59f7e | 15341 | lhs = c_fully_fold (lhs, false, NULL, true); |
f4b189d5 JJ |
15342 | if (lhs == error_mark_node) |
15343 | goto saw_error; | |
15344 | if (non_lvalue_p) | |
15345 | lhs = non_lvalue (lhs); | |
15346 | } | |
acf0174b JJ |
15347 | if (code == NOP_EXPR) |
15348 | { | |
15349 | /* atomic write is represented by OMP_ATOMIC with NOP_EXPR | |
15350 | opcode. */ | |
15351 | code = OMP_ATOMIC; | |
15352 | rhs = lhs; | |
15353 | lhs = v; | |
15354 | v = NULL_TREE; | |
15355 | } | |
15356 | goto done; | |
15357 | case OMP_ATOMIC_CAPTURE_NEW: | |
15358 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
15359 | { | |
15360 | c_parser_consume_token (parser); | |
15361 | structured_block = true; | |
15362 | } | |
15363 | else | |
15364 | { | |
f4b189d5 JJ |
15365 | v = c_parser_cast_expression (parser, NULL).value; |
15366 | non_lvalue_p = !lvalue_p (v); | |
f9c59f7e | 15367 | v = c_fully_fold (v, false, NULL, true); |
acf0174b JJ |
15368 | if (v == error_mark_node) |
15369 | goto saw_error; | |
f4b189d5 JJ |
15370 | if (non_lvalue_p) |
15371 | v = non_lvalue (v); | |
acf0174b JJ |
15372 | if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) |
15373 | goto saw_error; | |
15374 | } | |
15375 | break; | |
15376 | default: | |
15377 | break; | |
15378 | } | |
15379 | ||
15380 | /* For structured_block case we don't know yet whether | |
15381 | old or new x should be captured. */ | |
15382 | restart: | |
15383 | eloc = c_parser_peek_token (parser)->location; | |
f4b189d5 | 15384 | expr = c_parser_cast_expression (parser, NULL); |
acf0174b JJ |
15385 | lhs = expr.value; |
15386 | expr = default_function_array_conversion (eloc, expr); | |
15387 | unfolded_lhs = expr.value; | |
f9c59f7e | 15388 | lhs = c_fully_fold (lhs, false, NULL, true); |
acf0174b JJ |
15389 | orig_lhs = lhs; |
15390 | switch (TREE_CODE (lhs)) | |
15391 | { | |
15392 | case ERROR_MARK: | |
15393 | saw_error: | |
15394 | c_parser_skip_to_end_of_block_or_statement (parser); | |
15395 | if (structured_block) | |
15396 | { | |
15397 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
15398 | c_parser_consume_token (parser); | |
15399 | else if (code == OMP_ATOMIC_CAPTURE_NEW) | |
15400 | { | |
15401 | c_parser_skip_to_end_of_block_or_statement (parser); | |
15402 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
15403 | c_parser_consume_token (parser); | |
15404 | } | |
15405 | } | |
15406 | return; | |
15407 | ||
15408 | case POSTINCREMENT_EXPR: | |
15409 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) | |
15410 | code = OMP_ATOMIC_CAPTURE_OLD; | |
15411 | /* FALLTHROUGH */ | |
15412 | case PREINCREMENT_EXPR: | |
15413 | lhs = TREE_OPERAND (lhs, 0); | |
15414 | unfolded_lhs = NULL_TREE; | |
15415 | opcode = PLUS_EXPR; | |
15416 | rhs = integer_one_node; | |
15417 | break; | |
15418 | ||
15419 | case POSTDECREMENT_EXPR: | |
15420 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) | |
15421 | code = OMP_ATOMIC_CAPTURE_OLD; | |
15422 | /* FALLTHROUGH */ | |
15423 | case PREDECREMENT_EXPR: | |
15424 | lhs = TREE_OPERAND (lhs, 0); | |
15425 | unfolded_lhs = NULL_TREE; | |
15426 | opcode = MINUS_EXPR; | |
15427 | rhs = integer_one_node; | |
15428 | break; | |
15429 | ||
15430 | case COMPOUND_EXPR: | |
15431 | if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR | |
15432 | && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR | |
15433 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR | |
15434 | && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0) | |
15435 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND | |
15436 | (TREE_OPERAND (lhs, 1), 0), 0))) | |
15437 | == BOOLEAN_TYPE) | |
15438 | /* Undo effects of boolean_increment for post {in,de}crement. */ | |
15439 | lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0); | |
15440 | /* FALLTHRU */ | |
15441 | case MODIFY_EXPR: | |
15442 | if (TREE_CODE (lhs) == MODIFY_EXPR | |
15443 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE) | |
15444 | { | |
15445 | /* Undo effects of boolean_increment. */ | |
15446 | if (integer_onep (TREE_OPERAND (lhs, 1))) | |
15447 | { | |
15448 | /* This is pre or post increment. */ | |
15449 | rhs = TREE_OPERAND (lhs, 1); | |
15450 | lhs = TREE_OPERAND (lhs, 0); | |
15451 | unfolded_lhs = NULL_TREE; | |
15452 | opcode = NOP_EXPR; | |
15453 | if (code == OMP_ATOMIC_CAPTURE_NEW | |
15454 | && !structured_block | |
15455 | && TREE_CODE (orig_lhs) == COMPOUND_EXPR) | |
15456 | code = OMP_ATOMIC_CAPTURE_OLD; | |
15457 | break; | |
15458 | } | |
15459 | if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR | |
15460 | && TREE_OPERAND (lhs, 0) | |
15461 | == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) | |
15462 | { | |
15463 | /* This is pre or post decrement. */ | |
15464 | rhs = TREE_OPERAND (lhs, 1); | |
15465 | lhs = TREE_OPERAND (lhs, 0); | |
15466 | unfolded_lhs = NULL_TREE; | |
15467 | opcode = NOP_EXPR; | |
15468 | if (code == OMP_ATOMIC_CAPTURE_NEW | |
15469 | && !structured_block | |
15470 | && TREE_CODE (orig_lhs) == COMPOUND_EXPR) | |
15471 | code = OMP_ATOMIC_CAPTURE_OLD; | |
15472 | break; | |
15473 | } | |
15474 | } | |
15475 | /* FALLTHRU */ | |
15476 | default: | |
f4b189d5 JJ |
15477 | if (!lvalue_p (unfolded_lhs)) |
15478 | lhs = non_lvalue (lhs); | |
acf0174b JJ |
15479 | switch (c_parser_peek_token (parser)->type) |
15480 | { | |
15481 | case CPP_MULT_EQ: | |
15482 | opcode = MULT_EXPR; | |
15483 | break; | |
15484 | case CPP_DIV_EQ: | |
15485 | opcode = TRUNC_DIV_EXPR; | |
15486 | break; | |
15487 | case CPP_PLUS_EQ: | |
15488 | opcode = PLUS_EXPR; | |
15489 | break; | |
15490 | case CPP_MINUS_EQ: | |
15491 | opcode = MINUS_EXPR; | |
15492 | break; | |
15493 | case CPP_LSHIFT_EQ: | |
15494 | opcode = LSHIFT_EXPR; | |
15495 | break; | |
15496 | case CPP_RSHIFT_EQ: | |
15497 | opcode = RSHIFT_EXPR; | |
15498 | break; | |
15499 | case CPP_AND_EQ: | |
15500 | opcode = BIT_AND_EXPR; | |
15501 | break; | |
15502 | case CPP_OR_EQ: | |
15503 | opcode = BIT_IOR_EXPR; | |
15504 | break; | |
15505 | case CPP_XOR_EQ: | |
15506 | opcode = BIT_XOR_EXPR; | |
15507 | break; | |
15508 | case CPP_EQ: | |
15509 | c_parser_consume_token (parser); | |
15510 | eloc = c_parser_peek_token (parser)->location; | |
15511 | expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs); | |
15512 | rhs1 = expr.value; | |
15513 | switch (TREE_CODE (rhs1)) | |
15514 | { | |
15515 | case MULT_EXPR: | |
15516 | case TRUNC_DIV_EXPR: | |
4886ec8e | 15517 | case RDIV_EXPR: |
acf0174b JJ |
15518 | case PLUS_EXPR: |
15519 | case MINUS_EXPR: | |
15520 | case LSHIFT_EXPR: | |
15521 | case RSHIFT_EXPR: | |
15522 | case BIT_AND_EXPR: | |
15523 | case BIT_IOR_EXPR: | |
15524 | case BIT_XOR_EXPR: | |
15525 | if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs)) | |
15526 | { | |
15527 | opcode = TREE_CODE (rhs1); | |
f9c59f7e JJ |
15528 | rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL, |
15529 | true); | |
15530 | rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL, | |
15531 | true); | |
acf0174b JJ |
15532 | goto stmt_done; |
15533 | } | |
15534 | if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs)) | |
15535 | { | |
15536 | opcode = TREE_CODE (rhs1); | |
f9c59f7e JJ |
15537 | rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL, |
15538 | true); | |
15539 | rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL, | |
15540 | true); | |
acf0174b JJ |
15541 | swapped = !commutative_tree_code (opcode); |
15542 | goto stmt_done; | |
15543 | } | |
15544 | break; | |
15545 | case ERROR_MARK: | |
15546 | goto saw_error; | |
15547 | default: | |
15548 | break; | |
15549 | } | |
15550 | if (c_parser_peek_token (parser)->type == CPP_SEMICOLON) | |
15551 | { | |
15552 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW) | |
15553 | { | |
15554 | code = OMP_ATOMIC_CAPTURE_OLD; | |
15555 | v = lhs; | |
15556 | lhs = NULL_TREE; | |
15557 | expr = default_function_array_read_conversion (eloc, expr); | |
15558 | unfolded_lhs1 = expr.value; | |
f9c59f7e | 15559 | lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true); |
acf0174b JJ |
15560 | rhs1 = NULL_TREE; |
15561 | c_parser_consume_token (parser); | |
15562 | goto restart; | |
15563 | } | |
15564 | if (structured_block) | |
15565 | { | |
15566 | opcode = NOP_EXPR; | |
15567 | expr = default_function_array_read_conversion (eloc, expr); | |
f9c59f7e | 15568 | rhs = c_fully_fold (expr.value, false, NULL, true); |
acf0174b JJ |
15569 | rhs1 = NULL_TREE; |
15570 | goto stmt_done; | |
15571 | } | |
15572 | } | |
15573 | c_parser_error (parser, "invalid form of %<#pragma omp atomic%>"); | |
15574 | goto saw_error; | |
15575 | default: | |
15576 | c_parser_error (parser, | |
15577 | "invalid operator for %<#pragma omp atomic%>"); | |
15578 | goto saw_error; | |
15579 | } | |
15580 | ||
15581 | /* Arrange to pass the location of the assignment operator to | |
15582 | c_finish_omp_atomic. */ | |
15583 | loc = c_parser_peek_token (parser)->location; | |
15584 | c_parser_consume_token (parser); | |
15585 | eloc = c_parser_peek_token (parser)->location; | |
15586 | expr = c_parser_expression (parser); | |
15587 | expr = default_function_array_read_conversion (eloc, expr); | |
15588 | rhs = expr.value; | |
f9c59f7e | 15589 | rhs = c_fully_fold (rhs, false, NULL, true); |
acf0174b JJ |
15590 | break; |
15591 | } | |
15592 | stmt_done: | |
15593 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW) | |
15594 | { | |
15595 | if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |
15596 | goto saw_error; | |
f4b189d5 JJ |
15597 | v = c_parser_cast_expression (parser, NULL).value; |
15598 | non_lvalue_p = !lvalue_p (v); | |
f9c59f7e | 15599 | v = c_fully_fold (v, false, NULL, true); |
acf0174b JJ |
15600 | if (v == error_mark_node) |
15601 | goto saw_error; | |
f4b189d5 JJ |
15602 | if (non_lvalue_p) |
15603 | v = non_lvalue (v); | |
acf0174b JJ |
15604 | if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) |
15605 | goto saw_error; | |
15606 | eloc = c_parser_peek_token (parser)->location; | |
f4b189d5 | 15607 | expr = c_parser_cast_expression (parser, NULL); |
acf0174b JJ |
15608 | lhs1 = expr.value; |
15609 | expr = default_function_array_read_conversion (eloc, expr); | |
15610 | unfolded_lhs1 = expr.value; | |
f9c59f7e | 15611 | lhs1 = c_fully_fold (lhs1, false, NULL, true); |
acf0174b JJ |
15612 | if (lhs1 == error_mark_node) |
15613 | goto saw_error; | |
f4b189d5 JJ |
15614 | if (!lvalue_p (unfolded_lhs1)) |
15615 | lhs1 = non_lvalue (lhs1); | |
acf0174b JJ |
15616 | } |
15617 | if (structured_block) | |
15618 | { | |
15619 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
15620 | c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"); | |
15621 | } | |
15622 | done: | |
15623 | if (unfolded_lhs && unfolded_lhs1 | |
15624 | && !c_tree_equal (unfolded_lhs, unfolded_lhs1)) | |
15625 | { | |
15626 | error ("%<#pragma omp atomic capture%> uses two different " | |
15627 | "expressions for memory"); | |
15628 | stmt = error_mark_node; | |
15629 | } | |
15630 | else | |
15631 | stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, | |
15632 | swapped, seq_cst); | |
15633 | if (stmt != error_mark_node) | |
15634 | add_stmt (stmt); | |
15635 | ||
15636 | if (!structured_block) | |
15637 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
15638 | } | |
15639 | ||
15640 | ||
15641 | /* OpenMP 2.5: | |
15642 | # pragma omp barrier new-line | |
15643 | */ | |
15644 | ||
15645 | static void | |
15646 | c_parser_omp_barrier (c_parser *parser) | |
15647 | { | |
15648 | location_t loc = c_parser_peek_token (parser)->location; | |
15649 | c_parser_consume_pragma (parser); | |
15650 | c_parser_skip_to_pragma_eol (parser); | |
15651 | ||
15652 | c_finish_omp_barrier (loc); | |
15653 | } | |
15654 | ||
15655 | /* OpenMP 2.5: | |
15656 | # pragma omp critical [(name)] new-line | |
15657 | structured-block | |
15658 | ||
d9a6bd32 JJ |
15659 | OpenMP 4.5: |
15660 | # pragma omp critical [(name) [hint(expression)]] new-line | |
15661 | ||
acf0174b JJ |
15662 | LOC is the location of the #pragma itself. */ |
15663 | ||
d9a6bd32 JJ |
15664 | #define OMP_CRITICAL_CLAUSE_MASK \ |
15665 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) ) | |
15666 | ||
acf0174b | 15667 | static tree |
dda1bf61 | 15668 | c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p) |
acf0174b | 15669 | { |
d9a6bd32 | 15670 | tree stmt, name = NULL_TREE, clauses = NULL_TREE; |
acf0174b JJ |
15671 | |
15672 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
15673 | { | |
15674 | c_parser_consume_token (parser); | |
15675 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
15676 | { | |
15677 | name = c_parser_peek_token (parser)->value; | |
15678 | c_parser_consume_token (parser); | |
15679 | c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); | |
15680 | } | |
15681 | else | |
15682 | c_parser_error (parser, "expected identifier"); | |
d9a6bd32 JJ |
15683 | |
15684 | clauses = c_parser_omp_all_clauses (parser, | |
15685 | OMP_CRITICAL_CLAUSE_MASK, | |
15686 | "#pragma omp critical"); | |
15687 | } | |
15688 | else | |
15689 | { | |
15690 | if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
15691 | c_parser_error (parser, "expected %<(%> or end of line"); | |
15692 | c_parser_skip_to_pragma_eol (parser); | |
acf0174b | 15693 | } |
acf0174b | 15694 | |
dda1bf61 | 15695 | stmt = c_parser_omp_structured_block (parser, if_p); |
d9a6bd32 | 15696 | return c_finish_omp_critical (loc, stmt, name, clauses); |
acf0174b JJ |
15697 | } |
15698 | ||
15699 | /* OpenMP 2.5: | |
15700 | # pragma omp flush flush-vars[opt] new-line | |
15701 | ||
15702 | flush-vars: | |
15703 | ( variable-list ) */ | |
15704 | ||
15705 | static void | |
15706 | c_parser_omp_flush (c_parser *parser) | |
15707 | { | |
15708 | location_t loc = c_parser_peek_token (parser)->location; | |
15709 | c_parser_consume_pragma (parser); | |
15710 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
15711 | c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); | |
15712 | else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
15713 | c_parser_error (parser, "expected %<(%> or end of line"); | |
15714 | c_parser_skip_to_pragma_eol (parser); | |
15715 | ||
15716 | c_finish_omp_flush (loc); | |
15717 | } | |
15718 | ||
41dbbb37 | 15719 | /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP. |
acf0174b JJ |
15720 | The real trick here is to determine the loop control variable early |
15721 | so that we can push a new decl if necessary to make it private. | |
41dbbb37 TS |
15722 | LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp", |
15723 | respectively. */ | |
acf0174b JJ |
15724 | |
15725 | static tree | |
15726 | c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, | |
dda1bf61 | 15727 | tree clauses, tree *cclauses, bool *if_p) |
acf0174b JJ |
15728 | { |
15729 | tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; | |
a8a098ac JJ |
15730 | tree declv, condv, incrv, initv, ret = NULL_TREE; |
15731 | tree pre_body = NULL_TREE, this_pre_body; | |
d9a6bd32 | 15732 | tree ordered_cl = NULL_TREE; |
acf0174b | 15733 | bool fail = false, open_brace_parsed = false; |
d9a6bd32 | 15734 | int i, collapse = 1, ordered = 0, count, nbraces = 0; |
acf0174b | 15735 | location_t for_loc; |
02889d23 | 15736 | bool tiling = false; |
acf0174b JJ |
15737 | vec<tree, va_gc> *for_block = make_tree_vector (); |
15738 | ||
15739 | for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) | |
15740 | if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) | |
9439e9a1 | 15741 | collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); |
02889d23 CLT |
15742 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE) |
15743 | { | |
15744 | tiling = true; | |
15745 | collapse = list_length (OMP_CLAUSE_TILE_LIST (cl)); | |
15746 | } | |
d9a6bd32 JJ |
15747 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED |
15748 | && OMP_CLAUSE_ORDERED_EXPR (cl)) | |
15749 | { | |
15750 | ordered_cl = cl; | |
15751 | ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); | |
15752 | } | |
15753 | ||
15754 | if (ordered && ordered < collapse) | |
15755 | { | |
15756 | error_at (OMP_CLAUSE_LOCATION (ordered_cl), | |
15757 | "%<ordered%> clause parameter is less than %<collapse%>"); | |
15758 | OMP_CLAUSE_ORDERED_EXPR (ordered_cl) | |
15759 | = build_int_cst (NULL_TREE, collapse); | |
15760 | ordered = collapse; | |
15761 | } | |
15762 | if (ordered) | |
15763 | { | |
15764 | for (tree *pc = &clauses; *pc; ) | |
15765 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) | |
15766 | { | |
15767 | error_at (OMP_CLAUSE_LOCATION (*pc), | |
15768 | "%<linear%> clause may not be specified together " | |
15769 | "with %<ordered%> clause with a parameter"); | |
15770 | *pc = OMP_CLAUSE_CHAIN (*pc); | |
15771 | } | |
15772 | else | |
15773 | pc = &OMP_CLAUSE_CHAIN (*pc); | |
15774 | } | |
acf0174b | 15775 | |
02889d23 | 15776 | gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); |
d9a6bd32 | 15777 | count = ordered ? ordered : collapse; |
acf0174b | 15778 | |
d9a6bd32 JJ |
15779 | declv = make_tree_vec (count); |
15780 | initv = make_tree_vec (count); | |
15781 | condv = make_tree_vec (count); | |
15782 | incrv = make_tree_vec (count); | |
acf0174b | 15783 | |
9a771876 JJ |
15784 | if (code != CILK_FOR |
15785 | && !c_parser_next_token_is_keyword (parser, RID_FOR)) | |
acf0174b JJ |
15786 | { |
15787 | c_parser_error (parser, "for statement expected"); | |
15788 | return NULL; | |
15789 | } | |
9a771876 JJ |
15790 | if (code == CILK_FOR |
15791 | && !c_parser_next_token_is_keyword (parser, RID_CILK_FOR)) | |
15792 | { | |
15793 | c_parser_error (parser, "_Cilk_for statement expected"); | |
15794 | return NULL; | |
15795 | } | |
acf0174b JJ |
15796 | for_loc = c_parser_peek_token (parser)->location; |
15797 | c_parser_consume_token (parser); | |
15798 | ||
d9a6bd32 | 15799 | for (i = 0; i < count; i++) |
acf0174b JJ |
15800 | { |
15801 | int bracecount = 0; | |
15802 | ||
32129a17 DM |
15803 | matching_parens parens; |
15804 | if (!parens.require_open (parser)) | |
acf0174b JJ |
15805 | goto pop_scopes; |
15806 | ||
15807 | /* Parse the initialization declaration or expression. */ | |
15808 | if (c_parser_next_tokens_start_declaration (parser)) | |
15809 | { | |
15810 | if (i > 0) | |
15811 | vec_safe_push (for_block, c_begin_compound_stmt (true)); | |
a8a098ac | 15812 | this_pre_body = push_stmt_list (); |
acf0174b JJ |
15813 | c_parser_declaration_or_fndef (parser, true, true, true, true, true, |
15814 | NULL, vNULL); | |
a8a098ac JJ |
15815 | if (this_pre_body) |
15816 | { | |
15817 | this_pre_body = pop_stmt_list (this_pre_body); | |
15818 | if (pre_body) | |
15819 | { | |
15820 | tree t = pre_body; | |
15821 | pre_body = push_stmt_list (); | |
15822 | add_stmt (t); | |
15823 | add_stmt (this_pre_body); | |
15824 | pre_body = pop_stmt_list (pre_body); | |
15825 | } | |
15826 | else | |
15827 | pre_body = this_pre_body; | |
15828 | } | |
acf0174b JJ |
15829 | decl = check_for_loop_decls (for_loc, flag_isoc99); |
15830 | if (decl == NULL) | |
15831 | goto error_init; | |
15832 | if (DECL_INITIAL (decl) == error_mark_node) | |
15833 | decl = error_mark_node; | |
15834 | init = decl; | |
15835 | } | |
15836 | else if (c_parser_next_token_is (parser, CPP_NAME) | |
15837 | && c_parser_peek_2nd_token (parser)->type == CPP_EQ) | |
15838 | { | |
15839 | struct c_expr decl_exp; | |
15840 | struct c_expr init_exp; | |
15841 | location_t init_loc; | |
15842 | ||
15843 | decl_exp = c_parser_postfix_expression (parser); | |
15844 | decl = decl_exp.value; | |
15845 | ||
15846 | c_parser_require (parser, CPP_EQ, "expected %<=%>"); | |
15847 | ||
15848 | init_loc = c_parser_peek_token (parser)->location; | |
15849 | init_exp = c_parser_expr_no_commas (parser, NULL); | |
15850 | init_exp = default_function_array_read_conversion (init_loc, | |
15851 | init_exp); | |
15852 | init = build_modify_expr (init_loc, decl, decl_exp.original_type, | |
15853 | NOP_EXPR, init_loc, init_exp.value, | |
15854 | init_exp.original_type); | |
15855 | init = c_process_expr_stmt (init_loc, init); | |
15856 | ||
15857 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
15858 | } | |
15859 | else | |
15860 | { | |
15861 | error_init: | |
15862 | c_parser_error (parser, | |
15863 | "expected iteration declaration or initialization"); | |
15864 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |
15865 | "expected %<)%>"); | |
15866 | fail = true; | |
15867 | goto parse_next; | |
15868 | } | |
15869 | ||
15870 | /* Parse the loop condition. */ | |
15871 | cond = NULL_TREE; | |
15872 | if (c_parser_next_token_is_not (parser, CPP_SEMICOLON)) | |
15873 | { | |
15874 | location_t cond_loc = c_parser_peek_token (parser)->location; | |
15875 | struct c_expr cond_expr | |
15876 | = c_parser_binary_expression (parser, NULL, NULL_TREE); | |
15877 | ||
15878 | cond = cond_expr.value; | |
15879 | cond = c_objc_common_truthvalue_conversion (cond_loc, cond); | |
ebc6a85e TV |
15880 | if (COMPARISON_CLASS_P (cond)) |
15881 | { | |
15882 | tree op0 = TREE_OPERAND (cond, 0), op1 = TREE_OPERAND (cond, 1); | |
15883 | op0 = c_fully_fold (op0, false, NULL); | |
15884 | op1 = c_fully_fold (op1, false, NULL); | |
15885 | TREE_OPERAND (cond, 0) = op0; | |
15886 | TREE_OPERAND (cond, 1) = op1; | |
15887 | } | |
acf0174b JJ |
15888 | switch (cond_expr.original_code) |
15889 | { | |
15890 | case GT_EXPR: | |
15891 | case GE_EXPR: | |
15892 | case LT_EXPR: | |
15893 | case LE_EXPR: | |
15894 | break; | |
c02065fc | 15895 | case NE_EXPR: |
9a771876 | 15896 | if (code == CILK_SIMD || code == CILK_FOR) |
c02065fc AH |
15897 | break; |
15898 | /* FALLTHRU. */ | |
acf0174b JJ |
15899 | default: |
15900 | /* Can't be cond = error_mark_node, because we want to preserve | |
15901 | the location until c_finish_omp_for. */ | |
15902 | cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node); | |
15903 | break; | |
15904 | } | |
15905 | protected_set_expr_location (cond, cond_loc); | |
15906 | } | |
15907 | c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); | |
15908 | ||
15909 | /* Parse the increment expression. */ | |
15910 | incr = NULL_TREE; | |
15911 | if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) | |
15912 | { | |
15913 | location_t incr_loc = c_parser_peek_token (parser)->location; | |
15914 | ||
15915 | incr = c_process_expr_stmt (incr_loc, | |
15916 | c_parser_expression (parser).value); | |
15917 | } | |
32129a17 | 15918 | parens.skip_until_found_close (parser); |
acf0174b JJ |
15919 | |
15920 | if (decl == NULL || decl == error_mark_node || init == error_mark_node) | |
15921 | fail = true; | |
15922 | else | |
15923 | { | |
15924 | TREE_VEC_ELT (declv, i) = decl; | |
15925 | TREE_VEC_ELT (initv, i) = init; | |
15926 | TREE_VEC_ELT (condv, i) = cond; | |
15927 | TREE_VEC_ELT (incrv, i) = incr; | |
15928 | } | |
15929 | ||
15930 | parse_next: | |
d9a6bd32 | 15931 | if (i == count - 1) |
acf0174b JJ |
15932 | break; |
15933 | ||
15934 | /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed | |
15935 | in between the collapsed for loops to be still considered perfectly | |
15936 | nested. Hopefully the final version clarifies this. | |
15937 | For now handle (multiple) {'s and empty statements. */ | |
15938 | do | |
15939 | { | |
15940 | if (c_parser_next_token_is_keyword (parser, RID_FOR)) | |
15941 | { | |
15942 | c_parser_consume_token (parser); | |
15943 | break; | |
15944 | } | |
15945 | else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |
15946 | { | |
15947 | c_parser_consume_token (parser); | |
15948 | bracecount++; | |
15949 | } | |
15950 | else if (bracecount | |
15951 | && c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
15952 | c_parser_consume_token (parser); | |
15953 | else | |
15954 | { | |
15955 | c_parser_error (parser, "not enough perfectly nested loops"); | |
15956 | if (bracecount) | |
15957 | { | |
15958 | open_brace_parsed = true; | |
15959 | bracecount--; | |
15960 | } | |
15961 | fail = true; | |
d9a6bd32 | 15962 | count = 0; |
acf0174b JJ |
15963 | break; |
15964 | } | |
15965 | } | |
15966 | while (1); | |
15967 | ||
15968 | nbraces += bracecount; | |
15969 | } | |
15970 | ||
dda1bf61 JJ |
15971 | if (nbraces) |
15972 | if_p = NULL; | |
15973 | ||
acf0174b | 15974 | save_break = c_break_label; |
c02065fc AH |
15975 | if (code == CILK_SIMD) |
15976 | c_break_label = build_int_cst (size_type_node, 2); | |
15977 | else | |
15978 | c_break_label = size_one_node; | |
acf0174b JJ |
15979 | save_cont = c_cont_label; |
15980 | c_cont_label = NULL_TREE; | |
15981 | body = push_stmt_list (); | |
15982 | ||
15983 | if (open_brace_parsed) | |
15984 | { | |
15985 | location_t here = c_parser_peek_token (parser)->location; | |
15986 | stmt = c_begin_compound_stmt (true); | |
15987 | c_parser_compound_statement_nostart (parser); | |
15988 | add_stmt (c_end_compound_stmt (here, stmt, true)); | |
15989 | } | |
15990 | else | |
dda1bf61 | 15991 | add_stmt (c_parser_c99_block_statement (parser, if_p)); |
acf0174b JJ |
15992 | if (c_cont_label) |
15993 | { | |
15994 | tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label); | |
15995 | SET_EXPR_LOCATION (t, loc); | |
15996 | add_stmt (t); | |
15997 | } | |
15998 | ||
15999 | body = pop_stmt_list (body); | |
16000 | c_break_label = save_break; | |
16001 | c_cont_label = save_cont; | |
16002 | ||
16003 | while (nbraces) | |
16004 | { | |
16005 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
16006 | { | |
16007 | c_parser_consume_token (parser); | |
16008 | nbraces--; | |
16009 | } | |
16010 | else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |
16011 | c_parser_consume_token (parser); | |
16012 | else | |
16013 | { | |
16014 | c_parser_error (parser, "collapsed loops not perfectly nested"); | |
16015 | while (nbraces) | |
16016 | { | |
16017 | location_t here = c_parser_peek_token (parser)->location; | |
16018 | stmt = c_begin_compound_stmt (true); | |
16019 | add_stmt (body); | |
16020 | c_parser_compound_statement_nostart (parser); | |
16021 | body = c_end_compound_stmt (here, stmt, true); | |
16022 | nbraces--; | |
16023 | } | |
16024 | goto pop_scopes; | |
16025 | } | |
16026 | } | |
16027 | ||
16028 | /* Only bother calling c_finish_omp_for if we haven't already generated | |
16029 | an error from the initialization parsing. */ | |
16030 | if (!fail) | |
16031 | { | |
d9a6bd32 | 16032 | stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv, |
a8a098ac | 16033 | incrv, body, pre_body); |
e01d41e5 JJ |
16034 | |
16035 | /* Check for iterators appearing in lb, b or incr expressions. */ | |
16036 | if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL)) | |
16037 | stmt = NULL_TREE; | |
16038 | ||
acf0174b JJ |
16039 | if (stmt) |
16040 | { | |
e01d41e5 JJ |
16041 | add_stmt (stmt); |
16042 | ||
acf0174b JJ |
16043 | if (cclauses != NULL |
16044 | && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL) | |
16045 | { | |
16046 | tree *c; | |
16047 | for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; ) | |
16048 | if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE | |
16049 | && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE) | |
16050 | c = &OMP_CLAUSE_CHAIN (*c); | |
16051 | else | |
16052 | { | |
d9a6bd32 | 16053 | for (i = 0; i < count; i++) |
acf0174b JJ |
16054 | if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c)) |
16055 | break; | |
d9a6bd32 | 16056 | if (i == count) |
acf0174b JJ |
16057 | c = &OMP_CLAUSE_CHAIN (*c); |
16058 | else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE) | |
16059 | { | |
16060 | error_at (loc, | |
16061 | "iteration variable %qD should not be firstprivate", | |
16062 | OMP_CLAUSE_DECL (*c)); | |
16063 | *c = OMP_CLAUSE_CHAIN (*c); | |
16064 | } | |
16065 | else | |
16066 | { | |
41b37d5e JJ |
16067 | /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ |
16068 | tree l = *c; | |
16069 | *c = OMP_CLAUSE_CHAIN (*c); | |
56ad0e38 JJ |
16070 | if (code == OMP_SIMD) |
16071 | { | |
16072 | OMP_CLAUSE_CHAIN (l) | |
16073 | = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; | |
16074 | cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l; | |
16075 | } | |
16076 | else | |
16077 | { | |
16078 | OMP_CLAUSE_CHAIN (l) = clauses; | |
16079 | clauses = l; | |
16080 | } | |
acf0174b JJ |
16081 | } |
16082 | } | |
16083 | } | |
16084 | OMP_FOR_CLAUSES (stmt) = clauses; | |
16085 | } | |
16086 | ret = stmt; | |
16087 | } | |
16088 | pop_scopes: | |
16089 | while (!for_block->is_empty ()) | |
16090 | { | |
16091 | /* FIXME diagnostics: LOC below should be the actual location of | |
16092 | this particular for block. We need to build a list of | |
16093 | locations to go along with FOR_BLOCK. */ | |
16094 | stmt = c_end_compound_stmt (loc, for_block->pop (), true); | |
16095 | add_stmt (stmt); | |
16096 | } | |
16097 | release_tree_vector (for_block); | |
16098 | return ret; | |
16099 | } | |
16100 | ||
16101 | /* Helper function for OpenMP parsing, split clauses and call | |
16102 | finish_omp_clauses on each of the set of clauses afterwards. */ | |
16103 | ||
16104 | static void | |
16105 | omp_split_clauses (location_t loc, enum tree_code code, | |
16106 | omp_clause_mask mask, tree clauses, tree *cclauses) | |
16107 | { | |
16108 | int i; | |
16109 | c_omp_split_clauses (loc, code, mask, clauses, cclauses); | |
16110 | for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) | |
16111 | if (cclauses[i]) | |
77886428 | 16112 | cclauses[i] = c_finish_omp_clauses (cclauses[i], C_ORT_OMP); |
acf0174b JJ |
16113 | } |
16114 | ||
16115 | /* OpenMP 4.0: | |
16116 | #pragma omp simd simd-clause[optseq] new-line | |
16117 | for-loop | |
16118 | ||
16119 | LOC is the location of the #pragma token. | |
16120 | */ | |
16121 | ||
16122 | #define OMP_SIMD_CLAUSE_MASK \ | |
16123 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \ | |
d9a6bd32 | 16124 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ |
acf0174b JJ |
16125 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
16126 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ | |
16127 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16128 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | |
16129 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | |
16130 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) | |
16131 | ||
16132 | static tree | |
16133 | c_parser_omp_simd (location_t loc, c_parser *parser, | |
dda1bf61 JJ |
16134 | char *p_name, omp_clause_mask mask, tree *cclauses, |
16135 | bool *if_p) | |
acf0174b JJ |
16136 | { |
16137 | tree block, clauses, ret; | |
16138 | ||
16139 | strcat (p_name, " simd"); | |
16140 | mask |= OMP_SIMD_CLAUSE_MASK; | |
acf0174b JJ |
16141 | |
16142 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); | |
16143 | if (cclauses) | |
16144 | { | |
16145 | omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); | |
16146 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; | |
629b3d75 | 16147 | tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR], |
d9a6bd32 JJ |
16148 | OMP_CLAUSE_ORDERED); |
16149 | if (c && OMP_CLAUSE_ORDERED_EXPR (c)) | |
16150 | { | |
16151 | error_at (OMP_CLAUSE_LOCATION (c), | |
16152 | "%<ordered%> clause with parameter may not be specified " | |
16153 | "on %qs construct", p_name); | |
16154 | OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; | |
16155 | } | |
acf0174b JJ |
16156 | } |
16157 | ||
16158 | block = c_begin_compound_stmt (true); | |
dda1bf61 | 16159 | ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p); |
acf0174b JJ |
16160 | block = c_end_compound_stmt (loc, block, true); |
16161 | add_stmt (block); | |
16162 | ||
16163 | return ret; | |
16164 | } | |
16165 | ||
16166 | /* OpenMP 2.5: | |
16167 | #pragma omp for for-clause[optseq] new-line | |
16168 | for-loop | |
16169 | ||
16170 | OpenMP 4.0: | |
16171 | #pragma omp for simd for-simd-clause[optseq] new-line | |
16172 | for-loop | |
16173 | ||
16174 | LOC is the location of the #pragma token. | |
16175 | */ | |
16176 | ||
16177 | #define OMP_FOR_CLAUSE_MASK \ | |
16178 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16179 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16180 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | |
d9a6bd32 | 16181 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
acf0174b JJ |
16182 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
16183 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ | |
16184 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ | |
16185 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ | |
16186 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
16187 | ||
16188 | static tree | |
16189 | c_parser_omp_for (location_t loc, c_parser *parser, | |
dda1bf61 JJ |
16190 | char *p_name, omp_clause_mask mask, tree *cclauses, |
16191 | bool *if_p) | |
acf0174b JJ |
16192 | { |
16193 | tree block, clauses, ret; | |
16194 | ||
16195 | strcat (p_name, " for"); | |
16196 | mask |= OMP_FOR_CLAUSE_MASK; | |
00631022 JJ |
16197 | /* parallel for{, simd} disallows nowait clause, but for |
16198 | target {teams distribute ,}parallel for{, simd} it should be accepted. */ | |
16199 | if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0) | |
acf0174b | 16200 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); |
d9a6bd32 JJ |
16201 | /* Composite distribute parallel for{, simd} disallows ordered clause. */ |
16202 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) | |
16203 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED); | |
acf0174b JJ |
16204 | |
16205 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
20906c66 | 16206 | { |
acf0174b JJ |
16207 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
16208 | ||
16209 | if (strcmp (p, "simd") == 0) | |
16210 | { | |
16211 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; | |
16212 | if (cclauses == NULL) | |
16213 | cclauses = cclauses_buf; | |
16214 | ||
16215 | c_parser_consume_token (parser); | |
6d7f7e0a | 16216 | if (!flag_openmp) /* flag_openmp_simd */ |
dda1bf61 JJ |
16217 | return c_parser_omp_simd (loc, parser, p_name, mask, cclauses, |
16218 | if_p); | |
acf0174b | 16219 | block = c_begin_compound_stmt (true); |
dda1bf61 | 16220 | ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p); |
acf0174b JJ |
16221 | block = c_end_compound_stmt (loc, block, true); |
16222 | if (ret == NULL_TREE) | |
16223 | return ret; | |
16224 | ret = make_node (OMP_FOR); | |
16225 | TREE_TYPE (ret) = void_type_node; | |
16226 | OMP_FOR_BODY (ret) = block; | |
16227 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; | |
16228 | SET_EXPR_LOCATION (ret, loc); | |
16229 | add_stmt (ret); | |
16230 | return ret; | |
16231 | } | |
20906c66 | 16232 | } |
6d7f7e0a TB |
16233 | if (!flag_openmp) /* flag_openmp_simd */ |
16234 | { | |
62021f64 | 16235 | c_parser_skip_to_pragma_eol (parser, false); |
6d7f7e0a TB |
16236 | return NULL_TREE; |
16237 | } | |
acf0174b | 16238 | |
d9a6bd32 JJ |
16239 | /* Composite distribute parallel for disallows linear clause. */ |
16240 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) | |
16241 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR); | |
16242 | ||
acf0174b JJ |
16243 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); |
16244 | if (cclauses) | |
20906c66 | 16245 | { |
acf0174b JJ |
16246 | omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses); |
16247 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; | |
20906c66 | 16248 | } |
20906c66 | 16249 | |
acf0174b | 16250 | block = c_begin_compound_stmt (true); |
dda1bf61 | 16251 | ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p); |
acf0174b JJ |
16252 | block = c_end_compound_stmt (loc, block, true); |
16253 | add_stmt (block); | |
16254 | ||
16255 | return ret; | |
953ff289 DN |
16256 | } |
16257 | ||
acf0174b JJ |
16258 | /* OpenMP 2.5: |
16259 | # pragma omp master new-line | |
16260 | structured-block | |
16261 | ||
16262 | LOC is the location of the #pragma token. | |
16263 | */ | |
16264 | ||
16265 | static tree | |
dda1bf61 | 16266 | c_parser_omp_master (location_t loc, c_parser *parser, bool *if_p) |
acf0174b JJ |
16267 | { |
16268 | c_parser_skip_to_pragma_eol (parser); | |
dda1bf61 JJ |
16269 | return c_finish_omp_master (loc, c_parser_omp_structured_block (parser, |
16270 | if_p)); | |
acf0174b | 16271 | } |
953ff289 DN |
16272 | |
16273 | /* OpenMP 2.5: | |
acf0174b JJ |
16274 | # pragma omp ordered new-line |
16275 | structured-block | |
16276 | ||
d9a6bd32 JJ |
16277 | OpenMP 4.5: |
16278 | # pragma omp ordered ordered-clauses new-line | |
16279 | structured-block | |
16280 | ||
16281 | # pragma omp ordered depend-clauses new-line */ | |
16282 | ||
16283 | #define OMP_ORDERED_CLAUSE_MASK \ | |
16284 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ | |
16285 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) | |
16286 | ||
16287 | #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ | |
16288 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) | |
16289 | ||
16290 | static bool | |
dda1bf61 JJ |
16291 | c_parser_omp_ordered (c_parser *parser, enum pragma_context context, |
16292 | bool *if_p) | |
d9a6bd32 JJ |
16293 | { |
16294 | location_t loc = c_parser_peek_token (parser)->location; | |
16295 | c_parser_consume_pragma (parser); | |
16296 | ||
16297 | if (context != pragma_stmt && context != pragma_compound) | |
16298 | { | |
16299 | c_parser_error (parser, "expected declaration specifiers"); | |
192b048b | 16300 | c_parser_skip_to_pragma_eol (parser, false); |
d9a6bd32 JJ |
16301 | return false; |
16302 | } | |
16303 | ||
16304 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
16305 | { | |
16306 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
16307 | ||
16308 | if (!strcmp ("depend", p)) | |
16309 | { | |
d2e05fcb JJ |
16310 | if (!flag_openmp) /* flag_openmp_simd */ |
16311 | { | |
16312 | c_parser_skip_to_pragma_eol (parser, false); | |
16313 | return false; | |
16314 | } | |
d9a6bd32 JJ |
16315 | if (context == pragma_stmt) |
16316 | { | |
16317 | error_at (loc, | |
883c8f06 | 16318 | "%<#pragma omp ordered%> with %<depend%> clause may " |
d9a6bd32 | 16319 | "only be used in compound statements"); |
aec17bfe | 16320 | c_parser_skip_to_pragma_eol (parser, false); |
d9a6bd32 JJ |
16321 | return false; |
16322 | } | |
16323 | ||
16324 | tree clauses | |
16325 | = c_parser_omp_all_clauses (parser, | |
16326 | OMP_ORDERED_DEPEND_CLAUSE_MASK, | |
16327 | "#pragma omp ordered"); | |
16328 | c_finish_omp_ordered (loc, clauses, NULL_TREE); | |
16329 | return false; | |
16330 | } | |
16331 | } | |
953ff289 | 16332 | |
d9a6bd32 JJ |
16333 | tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK, |
16334 | "#pragma omp ordered"); | |
d2e05fcb JJ |
16335 | |
16336 | if (!flag_openmp /* flag_openmp_simd */ | |
16337 | && omp_find_clause (clauses, OMP_CLAUSE_SIMD) == NULL_TREE) | |
16338 | return false; | |
16339 | ||
d9a6bd32 | 16340 | c_finish_omp_ordered (loc, clauses, |
dda1bf61 | 16341 | c_parser_omp_structured_block (parser, if_p)); |
d9a6bd32 | 16342 | return true; |
acf0174b | 16343 | } |
953ff289 | 16344 | |
acf0174b JJ |
16345 | /* OpenMP 2.5: |
16346 | ||
16347 | section-scope: | |
16348 | { section-sequence } | |
16349 | ||
16350 | section-sequence: | |
16351 | section-directive[opt] structured-block | |
16352 | section-sequence section-directive structured-block | |
16353 | ||
16354 | SECTIONS_LOC is the location of the #pragma omp sections. */ | |
16355 | ||
16356 | static tree | |
16357 | c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) | |
16358 | { | |
16359 | tree stmt, substmt; | |
16360 | bool error_suppress = false; | |
16361 | location_t loc; | |
16362 | ||
16363 | loc = c_parser_peek_token (parser)->location; | |
16364 | if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) | |
16365 | { | |
16366 | /* Avoid skipping until the end of the block. */ | |
16367 | parser->error = false; | |
16368 | return NULL_TREE; | |
16369 | } | |
16370 | ||
16371 | stmt = push_stmt_list (); | |
16372 | ||
16373 | if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) | |
16374 | { | |
dda1bf61 | 16375 | substmt = c_parser_omp_structured_block (parser, NULL); |
acf0174b JJ |
16376 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
16377 | SET_EXPR_LOCATION (substmt, loc); | |
16378 | add_stmt (substmt); | |
16379 | } | |
16380 | ||
16381 | while (1) | |
16382 | { | |
16383 | if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |
16384 | break; | |
16385 | if (c_parser_next_token_is (parser, CPP_EOF)) | |
16386 | break; | |
16387 | ||
16388 | loc = c_parser_peek_token (parser)->location; | |
16389 | if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION) | |
16390 | { | |
16391 | c_parser_consume_pragma (parser); | |
16392 | c_parser_skip_to_pragma_eol (parser); | |
16393 | error_suppress = false; | |
16394 | } | |
16395 | else if (!error_suppress) | |
16396 | { | |
16397 | error_at (loc, "expected %<#pragma omp section%> or %<}%>"); | |
16398 | error_suppress = true; | |
16399 | } | |
16400 | ||
dda1bf61 | 16401 | substmt = c_parser_omp_structured_block (parser, NULL); |
acf0174b JJ |
16402 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
16403 | SET_EXPR_LOCATION (substmt, loc); | |
16404 | add_stmt (substmt); | |
16405 | } | |
16406 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, | |
16407 | "expected %<#pragma omp section%> or %<}%>"); | |
16408 | ||
16409 | substmt = pop_stmt_list (stmt); | |
16410 | ||
16411 | stmt = make_node (OMP_SECTIONS); | |
16412 | SET_EXPR_LOCATION (stmt, sections_loc); | |
16413 | TREE_TYPE (stmt) = void_type_node; | |
16414 | OMP_SECTIONS_BODY (stmt) = substmt; | |
16415 | ||
16416 | return add_stmt (stmt); | |
953ff289 DN |
16417 | } |
16418 | ||
16419 | /* OpenMP 2.5: | |
acf0174b JJ |
16420 | # pragma omp sections sections-clause[optseq] newline |
16421 | sections-scope | |
c2255bc4 | 16422 | |
acf0174b JJ |
16423 | LOC is the location of the #pragma token. |
16424 | */ | |
16425 | ||
16426 | #define OMP_SECTIONS_CLAUSE_MASK \ | |
16427 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16428 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16429 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | |
16430 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | |
16431 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
953ff289 DN |
16432 | |
16433 | static tree | |
acf0174b JJ |
16434 | c_parser_omp_sections (location_t loc, c_parser *parser, |
16435 | char *p_name, omp_clause_mask mask, tree *cclauses) | |
953ff289 | 16436 | { |
acf0174b | 16437 | tree block, clauses, ret; |
953ff289 | 16438 | |
acf0174b JJ |
16439 | strcat (p_name, " sections"); |
16440 | mask |= OMP_SECTIONS_CLAUSE_MASK; | |
16441 | if (cclauses) | |
16442 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); | |
16443 | ||
16444 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); | |
16445 | if (cclauses) | |
16446 | { | |
16447 | omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses); | |
16448 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]; | |
16449 | } | |
16450 | ||
16451 | block = c_begin_compound_stmt (true); | |
16452 | ret = c_parser_omp_sections_scope (loc, parser); | |
16453 | if (ret) | |
16454 | OMP_SECTIONS_CLAUSES (ret) = clauses; | |
16455 | block = c_end_compound_stmt (loc, block, true); | |
16456 | add_stmt (block); | |
16457 | ||
16458 | return ret; | |
16459 | } | |
16460 | ||
16461 | /* OpenMP 2.5: | |
cef0fd0e TS |
16462 | # pragma omp parallel parallel-clause[optseq] new-line |
16463 | structured-block | |
16464 | # pragma omp parallel for parallel-for-clause[optseq] new-line | |
16465 | structured-block | |
16466 | # pragma omp parallel sections parallel-sections-clause[optseq] new-line | |
16467 | structured-block | |
16468 | ||
16469 | OpenMP 4.0: | |
16470 | # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line | |
16471 | structured-block | |
acf0174b JJ |
16472 | |
16473 | LOC is the location of the #pragma token. | |
16474 | */ | |
16475 | ||
16476 | #define OMP_PARALLEL_CLAUSE_MASK \ | |
16477 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | |
16478 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16479 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16480 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ | |
16481 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | |
16482 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \ | |
16483 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | |
16484 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \ | |
16485 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) | |
16486 | ||
16487 | static tree | |
16488 | c_parser_omp_parallel (location_t loc, c_parser *parser, | |
dda1bf61 JJ |
16489 | char *p_name, omp_clause_mask mask, tree *cclauses, |
16490 | bool *if_p) | |
acf0174b JJ |
16491 | { |
16492 | tree stmt, clauses, block; | |
16493 | ||
16494 | strcat (p_name, " parallel"); | |
16495 | mask |= OMP_PARALLEL_CLAUSE_MASK; | |
d9a6bd32 JJ |
16496 | /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */ |
16497 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0 | |
16498 | && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0) | |
16499 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN); | |
acf0174b JJ |
16500 | |
16501 | if (c_parser_next_token_is_keyword (parser, RID_FOR)) | |
953ff289 | 16502 | { |
acf0174b JJ |
16503 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
16504 | if (cclauses == NULL) | |
16505 | cclauses = cclauses_buf; | |
16506 | ||
953ff289 | 16507 | c_parser_consume_token (parser); |
6d7f7e0a | 16508 | if (!flag_openmp) /* flag_openmp_simd */ |
dda1bf61 | 16509 | return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p); |
acf0174b | 16510 | block = c_begin_omp_parallel (); |
dda1bf61 | 16511 | tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p); |
acf0174b JJ |
16512 | stmt |
16513 | = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], | |
16514 | block); | |
e162a134 JJ |
16515 | if (ret == NULL_TREE) |
16516 | return ret; | |
acf0174b JJ |
16517 | OMP_PARALLEL_COMBINED (stmt) = 1; |
16518 | return stmt; | |
16519 | } | |
d9a6bd32 JJ |
16520 | /* When combined with distribute, parallel has to be followed by for. |
16521 | #pragma omp target parallel is allowed though. */ | |
16522 | else if (cclauses | |
16523 | && (mask & (OMP_CLAUSE_MASK_1 | |
16524 | << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) | |
acf0174b JJ |
16525 | { |
16526 | error_at (loc, "expected %<for%> after %qs", p_name); | |
16527 | c_parser_skip_to_pragma_eol (parser); | |
16528 | return NULL_TREE; | |
16529 | } | |
6d7f7e0a TB |
16530 | else if (!flag_openmp) /* flag_openmp_simd */ |
16531 | { | |
62021f64 | 16532 | c_parser_skip_to_pragma_eol (parser, false); |
6d7f7e0a TB |
16533 | return NULL_TREE; |
16534 | } | |
d9a6bd32 | 16535 | else if (cclauses == NULL && c_parser_next_token_is (parser, CPP_NAME)) |
acf0174b JJ |
16536 | { |
16537 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
16538 | if (strcmp (p, "sections") == 0) | |
953ff289 | 16539 | { |
acf0174b JJ |
16540 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
16541 | if (cclauses == NULL) | |
16542 | cclauses = cclauses_buf; | |
16543 | ||
953ff289 | 16544 | c_parser_consume_token (parser); |
acf0174b JJ |
16545 | block = c_begin_omp_parallel (); |
16546 | c_parser_omp_sections (loc, parser, p_name, mask, cclauses); | |
16547 | stmt = c_finish_omp_parallel (loc, | |
16548 | cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], | |
16549 | block); | |
16550 | OMP_PARALLEL_COMBINED (stmt) = 1; | |
16551 | return stmt; | |
953ff289 | 16552 | } |
953ff289 | 16553 | } |
953ff289 | 16554 | |
acf0174b | 16555 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); |
d9a6bd32 JJ |
16556 | if (cclauses) |
16557 | { | |
16558 | omp_split_clauses (loc, OMP_PARALLEL, mask, clauses, cclauses); | |
16559 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; | |
16560 | } | |
acf0174b JJ |
16561 | |
16562 | block = c_begin_omp_parallel (); | |
dda1bf61 | 16563 | c_parser_statement (parser, if_p); |
acf0174b JJ |
16564 | stmt = c_finish_omp_parallel (loc, clauses, block); |
16565 | ||
16566 | return stmt; | |
16567 | } | |
16568 | ||
16569 | /* OpenMP 2.5: | |
16570 | # pragma omp single single-clause[optseq] new-line | |
16571 | structured-block | |
16572 | ||
16573 | LOC is the location of the #pragma. | |
16574 | */ | |
16575 | ||
16576 | #define OMP_SINGLE_CLAUSE_MASK \ | |
16577 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16578 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16579 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ | |
16580 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
16581 | ||
16582 | static tree | |
dda1bf61 | 16583 | c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p) |
acf0174b JJ |
16584 | { |
16585 | tree stmt = make_node (OMP_SINGLE); | |
16586 | SET_EXPR_LOCATION (stmt, loc); | |
16587 | TREE_TYPE (stmt) = void_type_node; | |
16588 | ||
16589 | OMP_SINGLE_CLAUSES (stmt) | |
16590 | = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, | |
16591 | "#pragma omp single"); | |
dda1bf61 | 16592 | OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p); |
acf0174b JJ |
16593 | |
16594 | return add_stmt (stmt); | |
16595 | } | |
16596 | ||
16597 | /* OpenMP 3.0: | |
16598 | # pragma omp task task-clause[optseq] new-line | |
16599 | ||
16600 | LOC is the location of the #pragma. | |
16601 | */ | |
16602 | ||
16603 | #define OMP_TASK_CLAUSE_MASK \ | |
16604 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | |
16605 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ | |
16606 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ | |
16607 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16608 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16609 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | |
16610 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ | |
16611 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ | |
d9a6bd32 JJ |
16612 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
16613 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)) | |
acf0174b JJ |
16614 | |
16615 | static tree | |
dda1bf61 | 16616 | c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p) |
acf0174b JJ |
16617 | { |
16618 | tree clauses, block; | |
16619 | ||
16620 | clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK, | |
16621 | "#pragma omp task"); | |
16622 | ||
16623 | block = c_begin_omp_task (); | |
dda1bf61 | 16624 | c_parser_statement (parser, if_p); |
acf0174b | 16625 | return c_finish_omp_task (loc, clauses, block); |
953ff289 DN |
16626 | } |
16627 | ||
acf0174b JJ |
16628 | /* OpenMP 3.0: |
16629 | # pragma omp taskwait new-line | |
16630 | */ | |
953ff289 DN |
16631 | |
16632 | static void | |
acf0174b | 16633 | c_parser_omp_taskwait (c_parser *parser) |
953ff289 | 16634 | { |
c2255bc4 | 16635 | location_t loc = c_parser_peek_token (parser)->location; |
953ff289 | 16636 | c_parser_consume_pragma (parser); |
953ff289 DN |
16637 | c_parser_skip_to_pragma_eol (parser); |
16638 | ||
acf0174b | 16639 | c_finish_omp_taskwait (loc); |
953ff289 DN |
16640 | } |
16641 | ||
acf0174b JJ |
16642 | /* OpenMP 3.1: |
16643 | # pragma omp taskyield new-line | |
16644 | */ | |
953ff289 | 16645 | |
acf0174b JJ |
16646 | static void |
16647 | c_parser_omp_taskyield (c_parser *parser) | |
953ff289 | 16648 | { |
acf0174b JJ |
16649 | location_t loc = c_parser_peek_token (parser)->location; |
16650 | c_parser_consume_pragma (parser); | |
16651 | c_parser_skip_to_pragma_eol (parser); | |
a68ab351 | 16652 | |
acf0174b JJ |
16653 | c_finish_omp_taskyield (loc); |
16654 | } | |
3ba09659 | 16655 | |
acf0174b JJ |
16656 | /* OpenMP 4.0: |
16657 | # pragma omp taskgroup new-line | |
16658 | */ | |
953ff289 | 16659 | |
acf0174b | 16660 | static tree |
dda1bf61 | 16661 | c_parser_omp_taskgroup (c_parser *parser, bool *if_p) |
acf0174b JJ |
16662 | { |
16663 | location_t loc = c_parser_peek_token (parser)->location; | |
16664 | c_parser_skip_to_pragma_eol (parser); | |
dda1bf61 JJ |
16665 | return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser, |
16666 | if_p)); | |
acf0174b | 16667 | } |
c9f9eb5d | 16668 | |
acf0174b JJ |
16669 | /* OpenMP 4.0: |
16670 | # pragma omp cancel cancel-clause[optseq] new-line | |
953ff289 | 16671 | |
acf0174b JJ |
16672 | LOC is the location of the #pragma. |
16673 | */ | |
a68ab351 | 16674 | |
acf0174b JJ |
16675 | #define OMP_CANCEL_CLAUSE_MASK \ |
16676 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ | |
16677 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ | |
16678 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ | |
16679 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \ | |
16680 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) | |
a68ab351 | 16681 | |
acf0174b JJ |
16682 | static void |
16683 | c_parser_omp_cancel (c_parser *parser) | |
16684 | { | |
16685 | location_t loc = c_parser_peek_token (parser)->location; | |
a68ab351 | 16686 | |
acf0174b JJ |
16687 | c_parser_consume_pragma (parser); |
16688 | tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK, | |
16689 | "#pragma omp cancel"); | |
953ff289 | 16690 | |
acf0174b JJ |
16691 | c_finish_omp_cancel (loc, clauses); |
16692 | } | |
953ff289 | 16693 | |
acf0174b JJ |
16694 | /* OpenMP 4.0: |
16695 | # pragma omp cancellation point cancelpt-clause[optseq] new-line | |
953ff289 | 16696 | |
acf0174b JJ |
16697 | LOC is the location of the #pragma. |
16698 | */ | |
953ff289 | 16699 | |
acf0174b JJ |
16700 | #define OMP_CANCELLATION_POINT_CLAUSE_MASK \ |
16701 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ | |
16702 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ | |
16703 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ | |
16704 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP)) | |
a68ab351 | 16705 | |
acf0174b | 16706 | static void |
54d19c3b | 16707 | c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context) |
acf0174b JJ |
16708 | { |
16709 | location_t loc = c_parser_peek_token (parser)->location; | |
16710 | tree clauses; | |
16711 | bool point_seen = false; | |
16712 | ||
16713 | c_parser_consume_pragma (parser); | |
16714 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
a68ab351 | 16715 | { |
acf0174b JJ |
16716 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
16717 | if (strcmp (p, "point") == 0) | |
a68ab351 | 16718 | { |
acf0174b JJ |
16719 | c_parser_consume_token (parser); |
16720 | point_seen = true; | |
a68ab351 | 16721 | } |
a68ab351 | 16722 | } |
acf0174b | 16723 | if (!point_seen) |
a68ab351 | 16724 | { |
acf0174b JJ |
16725 | c_parser_error (parser, "expected %<point%>"); |
16726 | c_parser_skip_to_pragma_eol (parser); | |
16727 | return; | |
a68ab351 | 16728 | } |
953ff289 | 16729 | |
54d19c3b TS |
16730 | if (context != pragma_compound) |
16731 | { | |
16732 | if (context == pragma_stmt) | |
a71dbc63 JJ |
16733 | error_at (loc, |
16734 | "%<#pragma %s%> may only be used in compound statements", | |
16735 | "omp cancellation point"); | |
54d19c3b TS |
16736 | else |
16737 | c_parser_error (parser, "expected declaration specifiers"); | |
16738 | c_parser_skip_to_pragma_eol (parser, false); | |
16739 | return; | |
16740 | } | |
16741 | ||
acf0174b JJ |
16742 | clauses |
16743 | = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK, | |
16744 | "#pragma omp cancellation point"); | |
c2255bc4 | 16745 | |
acf0174b JJ |
16746 | c_finish_omp_cancellation_point (loc, clauses); |
16747 | } | |
953ff289 | 16748 | |
acf0174b JJ |
16749 | /* OpenMP 4.0: |
16750 | #pragma omp distribute distribute-clause[optseq] new-line | |
16751 | for-loop */ | |
16752 | ||
16753 | #define OMP_DISTRIBUTE_CLAUSE_MASK \ | |
16754 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16755 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
e01d41e5 | 16756 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
acf0174b JJ |
16757 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ |
16758 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) | |
953ff289 DN |
16759 | |
16760 | static tree | |
acf0174b | 16761 | c_parser_omp_distribute (location_t loc, c_parser *parser, |
dda1bf61 JJ |
16762 | char *p_name, omp_clause_mask mask, tree *cclauses, |
16763 | bool *if_p) | |
953ff289 | 16764 | { |
acf0174b JJ |
16765 | tree clauses, block, ret; |
16766 | ||
16767 | strcat (p_name, " distribute"); | |
16768 | mask |= OMP_DISTRIBUTE_CLAUSE_MASK; | |
16769 | ||
16770 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
16771 | { | |
16772 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
16773 | bool simd = false; | |
16774 | bool parallel = false; | |
16775 | ||
16776 | if (strcmp (p, "simd") == 0) | |
16777 | simd = true; | |
16778 | else | |
16779 | parallel = strcmp (p, "parallel") == 0; | |
16780 | if (parallel || simd) | |
16781 | { | |
16782 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; | |
16783 | if (cclauses == NULL) | |
16784 | cclauses = cclauses_buf; | |
16785 | c_parser_consume_token (parser); | |
6d7f7e0a TB |
16786 | if (!flag_openmp) /* flag_openmp_simd */ |
16787 | { | |
16788 | if (simd) | |
dda1bf61 JJ |
16789 | return c_parser_omp_simd (loc, parser, p_name, mask, cclauses, |
16790 | if_p); | |
6d7f7e0a TB |
16791 | else |
16792 | return c_parser_omp_parallel (loc, parser, p_name, mask, | |
dda1bf61 | 16793 | cclauses, if_p); |
6d7f7e0a | 16794 | } |
acf0174b JJ |
16795 | block = c_begin_compound_stmt (true); |
16796 | if (simd) | |
dda1bf61 JJ |
16797 | ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, |
16798 | if_p); | |
acf0174b | 16799 | else |
dda1bf61 JJ |
16800 | ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses, |
16801 | if_p); | |
acf0174b JJ |
16802 | block = c_end_compound_stmt (loc, block, true); |
16803 | if (ret == NULL) | |
16804 | return ret; | |
16805 | ret = make_node (OMP_DISTRIBUTE); | |
16806 | TREE_TYPE (ret) = void_type_node; | |
16807 | OMP_FOR_BODY (ret) = block; | |
16808 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; | |
16809 | SET_EXPR_LOCATION (ret, loc); | |
16810 | add_stmt (ret); | |
16811 | return ret; | |
16812 | } | |
16813 | } | |
6d7f7e0a TB |
16814 | if (!flag_openmp) /* flag_openmp_simd */ |
16815 | { | |
62021f64 | 16816 | c_parser_skip_to_pragma_eol (parser, false); |
6d7f7e0a TB |
16817 | return NULL_TREE; |
16818 | } | |
953ff289 | 16819 | |
acf0174b JJ |
16820 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); |
16821 | if (cclauses) | |
16822 | { | |
16823 | omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses); | |
16824 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; | |
16825 | } | |
953ff289 DN |
16826 | |
16827 | block = c_begin_compound_stmt (true); | |
dda1bf61 JJ |
16828 | ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL, |
16829 | if_p); | |
c2255bc4 | 16830 | block = c_end_compound_stmt (loc, block, true); |
953ff289 DN |
16831 | add_stmt (block); |
16832 | ||
16833 | return ret; | |
16834 | } | |
16835 | ||
acf0174b JJ |
16836 | /* OpenMP 4.0: |
16837 | # pragma omp teams teams-clause[optseq] new-line | |
16838 | structured-block */ | |
c2255bc4 | 16839 | |
acf0174b JJ |
16840 | #define OMP_TEAMS_CLAUSE_MASK \ |
16841 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
16842 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
16843 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | |
16844 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | |
16845 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \ | |
16846 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ | |
16847 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)) | |
953ff289 DN |
16848 | |
16849 | static tree | |
acf0174b | 16850 | c_parser_omp_teams (location_t loc, c_parser *parser, |
dda1bf61 JJ |
16851 | char *p_name, omp_clause_mask mask, tree *cclauses, |
16852 | bool *if_p) | |
953ff289 | 16853 | { |
acf0174b JJ |
16854 | tree clauses, block, ret; |
16855 | ||
16856 | strcat (p_name, " teams"); | |
16857 | mask |= OMP_TEAMS_CLAUSE_MASK; | |
16858 | ||
16859 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
16860 | { | |
16861 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
16862 | if (strcmp (p, "distribute") == 0) | |
16863 | { | |
16864 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; | |
16865 | if (cclauses == NULL) | |
16866 | cclauses = cclauses_buf; | |
16867 | ||
16868 | c_parser_consume_token (parser); | |
6d7f7e0a | 16869 | if (!flag_openmp) /* flag_openmp_simd */ |
dda1bf61 JJ |
16870 | return c_parser_omp_distribute (loc, parser, p_name, mask, |
16871 | cclauses, if_p); | |
acf0174b | 16872 | block = c_begin_compound_stmt (true); |
dda1bf61 JJ |
16873 | ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses, |
16874 | if_p); | |
acf0174b JJ |
16875 | block = c_end_compound_stmt (loc, block, true); |
16876 | if (ret == NULL) | |
16877 | return ret; | |
16878 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; | |
16879 | ret = make_node (OMP_TEAMS); | |
16880 | TREE_TYPE (ret) = void_type_node; | |
16881 | OMP_TEAMS_CLAUSES (ret) = clauses; | |
16882 | OMP_TEAMS_BODY (ret) = block; | |
41b37d5e | 16883 | OMP_TEAMS_COMBINED (ret) = 1; |
acf0174b JJ |
16884 | return add_stmt (ret); |
16885 | } | |
16886 | } | |
6d7f7e0a TB |
16887 | if (!flag_openmp) /* flag_openmp_simd */ |
16888 | { | |
62021f64 | 16889 | c_parser_skip_to_pragma_eol (parser, false); |
6d7f7e0a TB |
16890 | return NULL_TREE; |
16891 | } | |
acf0174b JJ |
16892 | |
16893 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); | |
16894 | if (cclauses) | |
16895 | { | |
16896 | omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses); | |
16897 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; | |
16898 | } | |
16899 | ||
16900 | tree stmt = make_node (OMP_TEAMS); | |
16901 | TREE_TYPE (stmt) = void_type_node; | |
16902 | OMP_TEAMS_CLAUSES (stmt) = clauses; | |
dda1bf61 | 16903 | OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser, if_p); |
acf0174b JJ |
16904 | |
16905 | return add_stmt (stmt); | |
953ff289 DN |
16906 | } |
16907 | ||
acf0174b JJ |
16908 | /* OpenMP 4.0: |
16909 | # pragma omp target data target-data-clause[optseq] new-line | |
16910 | structured-block */ | |
c2255bc4 | 16911 | |
acf0174b JJ |
16912 | #define OMP_TARGET_DATA_CLAUSE_MASK \ |
16913 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | |
16914 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ | |
d9a6bd32 JJ |
16915 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
16916 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR)) | |
953ff289 DN |
16917 | |
16918 | static tree | |
dda1bf61 | 16919 | c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p) |
953ff289 | 16920 | { |
d9a6bd32 | 16921 | tree clauses |
acf0174b JJ |
16922 | = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, |
16923 | "#pragma omp target data"); | |
d9a6bd32 JJ |
16924 | int map_seen = 0; |
16925 | for (tree *pc = &clauses; *pc;) | |
16926 | { | |
16927 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) | |
16928 | switch (OMP_CLAUSE_MAP_KIND (*pc)) | |
16929 | { | |
16930 | case GOMP_MAP_TO: | |
16931 | case GOMP_MAP_ALWAYS_TO: | |
16932 | case GOMP_MAP_FROM: | |
16933 | case GOMP_MAP_ALWAYS_FROM: | |
16934 | case GOMP_MAP_TOFROM: | |
16935 | case GOMP_MAP_ALWAYS_TOFROM: | |
16936 | case GOMP_MAP_ALLOC: | |
16937 | map_seen = 3; | |
16938 | break; | |
16939 | case GOMP_MAP_FIRSTPRIVATE_POINTER: | |
e01d41e5 | 16940 | case GOMP_MAP_ALWAYS_POINTER: |
d9a6bd32 JJ |
16941 | break; |
16942 | default: | |
16943 | map_seen |= 1; | |
16944 | error_at (OMP_CLAUSE_LOCATION (*pc), | |
16945 | "%<#pragma omp target data%> with map-type other " | |
16946 | "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> " | |
16947 | "on %<map%> clause"); | |
16948 | *pc = OMP_CLAUSE_CHAIN (*pc); | |
16949 | continue; | |
16950 | } | |
16951 | pc = &OMP_CLAUSE_CHAIN (*pc); | |
16952 | } | |
16953 | ||
16954 | if (map_seen != 3) | |
16955 | { | |
16956 | if (map_seen == 0) | |
16957 | error_at (loc, | |
16958 | "%<#pragma omp target data%> must contain at least " | |
16959 | "one %<map%> clause"); | |
16960 | return NULL_TREE; | |
16961 | } | |
16962 | ||
16963 | tree stmt = make_node (OMP_TARGET_DATA); | |
16964 | TREE_TYPE (stmt) = void_type_node; | |
16965 | OMP_TARGET_DATA_CLAUSES (stmt) = clauses; | |
acf0174b JJ |
16966 | keep_next_level (); |
16967 | tree block = c_begin_compound_stmt (true); | |
dda1bf61 | 16968 | add_stmt (c_parser_omp_structured_block (parser, if_p)); |
acf0174b | 16969 | OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true); |
953ff289 | 16970 | |
acf0174b JJ |
16971 | SET_EXPR_LOCATION (stmt, loc); |
16972 | return add_stmt (stmt); | |
16973 | } | |
953ff289 | 16974 | |
acf0174b JJ |
16975 | /* OpenMP 4.0: |
16976 | # pragma omp target update target-update-clause[optseq] new-line */ | |
c2255bc4 | 16977 | |
acf0174b JJ |
16978 | #define OMP_TARGET_UPDATE_CLAUSE_MASK \ |
16979 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \ | |
16980 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ | |
16981 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | |
d9a6bd32 JJ |
16982 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
16983 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | |
16984 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
953ff289 | 16985 | |
acf0174b JJ |
16986 | static bool |
16987 | c_parser_omp_target_update (location_t loc, c_parser *parser, | |
16988 | enum pragma_context context) | |
953ff289 | 16989 | { |
acf0174b JJ |
16990 | if (context == pragma_stmt) |
16991 | { | |
a71dbc63 JJ |
16992 | error_at (loc, "%<#pragma %s%> may only be used in compound statements", |
16993 | "omp target update"); | |
aec17bfe | 16994 | c_parser_skip_to_pragma_eol (parser, false); |
acf0174b JJ |
16995 | return false; |
16996 | } | |
953ff289 | 16997 | |
acf0174b JJ |
16998 | tree clauses |
16999 | = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK, | |
17000 | "#pragma omp target update"); | |
629b3d75 MJ |
17001 | if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE |
17002 | && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE) | |
953ff289 | 17003 | { |
acf0174b | 17004 | error_at (loc, |
06aca1d5 | 17005 | "%<#pragma omp target update%> must contain at least one " |
acf0174b JJ |
17006 | "%<from%> or %<to%> clauses"); |
17007 | return false; | |
953ff289 DN |
17008 | } |
17009 | ||
acf0174b JJ |
17010 | tree stmt = make_node (OMP_TARGET_UPDATE); |
17011 | TREE_TYPE (stmt) = void_type_node; | |
17012 | OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses; | |
17013 | SET_EXPR_LOCATION (stmt, loc); | |
17014 | add_stmt (stmt); | |
17015 | return false; | |
17016 | } | |
953ff289 | 17017 | |
d9a6bd32 JJ |
17018 | /* OpenMP 4.5: |
17019 | # pragma omp target enter data target-data-clause[optseq] new-line */ | |
17020 | ||
17021 | #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \ | |
17022 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | |
17023 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ | |
17024 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | |
17025 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | |
17026 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
17027 | ||
17028 | static tree | |
17029 | c_parser_omp_target_enter_data (location_t loc, c_parser *parser, | |
17030 | enum pragma_context context) | |
17031 | { | |
17032 | bool data_seen = false; | |
17033 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
17034 | { | |
17035 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
17036 | if (strcmp (p, "data") == 0) | |
17037 | { | |
17038 | c_parser_consume_token (parser); | |
17039 | data_seen = true; | |
17040 | } | |
17041 | } | |
17042 | if (!data_seen) | |
17043 | { | |
17044 | c_parser_error (parser, "expected %<data%>"); | |
17045 | c_parser_skip_to_pragma_eol (parser); | |
17046 | return NULL_TREE; | |
17047 | } | |
17048 | ||
17049 | if (context == pragma_stmt) | |
17050 | { | |
a71dbc63 JJ |
17051 | error_at (loc, "%<#pragma %s%> may only be used in compound statements", |
17052 | "omp target enter data"); | |
aec17bfe | 17053 | c_parser_skip_to_pragma_eol (parser, false); |
d9a6bd32 JJ |
17054 | return NULL_TREE; |
17055 | } | |
17056 | ||
17057 | tree clauses | |
17058 | = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK, | |
17059 | "#pragma omp target enter data"); | |
17060 | int map_seen = 0; | |
17061 | for (tree *pc = &clauses; *pc;) | |
17062 | { | |
17063 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) | |
17064 | switch (OMP_CLAUSE_MAP_KIND (*pc)) | |
17065 | { | |
17066 | case GOMP_MAP_TO: | |
17067 | case GOMP_MAP_ALWAYS_TO: | |
17068 | case GOMP_MAP_ALLOC: | |
17069 | map_seen = 3; | |
17070 | break; | |
17071 | case GOMP_MAP_FIRSTPRIVATE_POINTER: | |
e01d41e5 | 17072 | case GOMP_MAP_ALWAYS_POINTER: |
d9a6bd32 JJ |
17073 | break; |
17074 | default: | |
17075 | map_seen |= 1; | |
17076 | error_at (OMP_CLAUSE_LOCATION (*pc), | |
17077 | "%<#pragma omp target enter data%> with map-type other " | |
17078 | "than %<to%> or %<alloc%> on %<map%> clause"); | |
17079 | *pc = OMP_CLAUSE_CHAIN (*pc); | |
17080 | continue; | |
17081 | } | |
17082 | pc = &OMP_CLAUSE_CHAIN (*pc); | |
17083 | } | |
17084 | ||
17085 | if (map_seen != 3) | |
17086 | { | |
17087 | if (map_seen == 0) | |
17088 | error_at (loc, | |
17089 | "%<#pragma omp target enter data%> must contain at least " | |
17090 | "one %<map%> clause"); | |
17091 | return NULL_TREE; | |
17092 | } | |
17093 | ||
17094 | tree stmt = make_node (OMP_TARGET_ENTER_DATA); | |
17095 | TREE_TYPE (stmt) = void_type_node; | |
17096 | OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses; | |
17097 | SET_EXPR_LOCATION (stmt, loc); | |
17098 | add_stmt (stmt); | |
17099 | return stmt; | |
17100 | } | |
17101 | ||
17102 | /* OpenMP 4.5: | |
17103 | # pragma omp target exit data target-data-clause[optseq] new-line */ | |
17104 | ||
17105 | #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \ | |
17106 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | |
17107 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ | |
17108 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | |
17109 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | |
17110 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) | |
17111 | ||
17112 | static tree | |
17113 | c_parser_omp_target_exit_data (location_t loc, c_parser *parser, | |
17114 | enum pragma_context context) | |
17115 | { | |
17116 | bool data_seen = false; | |
17117 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
17118 | { | |
17119 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
17120 | if (strcmp (p, "data") == 0) | |
17121 | { | |
17122 | c_parser_consume_token (parser); | |
17123 | data_seen = true; | |
17124 | } | |
17125 | } | |
17126 | if (!data_seen) | |
17127 | { | |
17128 | c_parser_error (parser, "expected %<data%>"); | |
17129 | c_parser_skip_to_pragma_eol (parser); | |
17130 | return NULL_TREE; | |
17131 | } | |
17132 | ||
17133 | if (context == pragma_stmt) | |
17134 | { | |
a71dbc63 JJ |
17135 | error_at (loc, "%<#pragma %s%> may only be used in compound statements", |
17136 | "omp target exit data"); | |
aec17bfe | 17137 | c_parser_skip_to_pragma_eol (parser, false); |
d9a6bd32 JJ |
17138 | return NULL_TREE; |
17139 | } | |
17140 | ||
17141 | tree clauses | |
17142 | = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK, | |
17143 | "#pragma omp target exit data"); | |
17144 | ||
17145 | int map_seen = 0; | |
17146 | for (tree *pc = &clauses; *pc;) | |
17147 | { | |
17148 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) | |
17149 | switch (OMP_CLAUSE_MAP_KIND (*pc)) | |
17150 | { | |
17151 | case GOMP_MAP_FROM: | |
17152 | case GOMP_MAP_ALWAYS_FROM: | |
17153 | case GOMP_MAP_RELEASE: | |
17154 | case GOMP_MAP_DELETE: | |
17155 | map_seen = 3; | |
17156 | break; | |
17157 | case GOMP_MAP_FIRSTPRIVATE_POINTER: | |
e01d41e5 | 17158 | case GOMP_MAP_ALWAYS_POINTER: |
d9a6bd32 JJ |
17159 | break; |
17160 | default: | |
17161 | map_seen |= 1; | |
17162 | error_at (OMP_CLAUSE_LOCATION (*pc), | |
17163 | "%<#pragma omp target exit data%> with map-type other " | |
883c8f06 | 17164 | "than %<from%>, %<release%> or %<delete%> on %<map%>" |
d9a6bd32 JJ |
17165 | " clause"); |
17166 | *pc = OMP_CLAUSE_CHAIN (*pc); | |
17167 | continue; | |
17168 | } | |
17169 | pc = &OMP_CLAUSE_CHAIN (*pc); | |
17170 | } | |
17171 | ||
17172 | if (map_seen != 3) | |
17173 | { | |
17174 | if (map_seen == 0) | |
17175 | error_at (loc, | |
17176 | "%<#pragma omp target exit data%> must contain at least one " | |
17177 | "%<map%> clause"); | |
17178 | return NULL_TREE; | |
17179 | } | |
17180 | ||
17181 | tree stmt = make_node (OMP_TARGET_EXIT_DATA); | |
17182 | TREE_TYPE (stmt) = void_type_node; | |
17183 | OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses; | |
17184 | SET_EXPR_LOCATION (stmt, loc); | |
17185 | add_stmt (stmt); | |
17186 | return stmt; | |
17187 | } | |
17188 | ||
acf0174b JJ |
17189 | /* OpenMP 4.0: |
17190 | # pragma omp target target-clause[optseq] new-line | |
17191 | structured-block */ | |
953ff289 | 17192 | |
acf0174b JJ |
17193 | #define OMP_TARGET_CLAUSE_MASK \ |
17194 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | |
17195 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ | |
d9a6bd32 JJ |
17196 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
17197 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | |
17198 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ | |
17199 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
17200 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
17201 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \ | |
17202 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)) | |
953ff289 | 17203 | |
acf0174b | 17204 | static bool |
dda1bf61 | 17205 | c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p) |
acf0174b JJ |
17206 | { |
17207 | location_t loc = c_parser_peek_token (parser)->location; | |
17208 | c_parser_consume_pragma (parser); | |
d9a6bd32 | 17209 | tree *pc = NULL, stmt, block; |
953ff289 | 17210 | |
acf0174b JJ |
17211 | if (context != pragma_stmt && context != pragma_compound) |
17212 | { | |
17213 | c_parser_error (parser, "expected declaration specifiers"); | |
17214 | c_parser_skip_to_pragma_eol (parser); | |
17215 | return false; | |
953ff289 DN |
17216 | } |
17217 | ||
acf0174b | 17218 | if (c_parser_next_token_is (parser, CPP_NAME)) |
953ff289 | 17219 | { |
acf0174b | 17220 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); |
d9a6bd32 | 17221 | enum tree_code ccode = ERROR_MARK; |
953ff289 | 17222 | |
6d7f7e0a | 17223 | if (strcmp (p, "teams") == 0) |
d9a6bd32 JJ |
17224 | ccode = OMP_TEAMS; |
17225 | else if (strcmp (p, "parallel") == 0) | |
17226 | ccode = OMP_PARALLEL; | |
17227 | else if (strcmp (p, "simd") == 0) | |
17228 | ccode = OMP_SIMD; | |
17229 | if (ccode != ERROR_MARK) | |
acf0174b JJ |
17230 | { |
17231 | tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT]; | |
17232 | char p_name[sizeof ("#pragma omp target teams distribute " | |
17233 | "parallel for simd")]; | |
953ff289 | 17234 | |
acf0174b | 17235 | c_parser_consume_token (parser); |
e7bd1de1 | 17236 | strcpy (p_name, "#pragma omp target"); |
6d7f7e0a | 17237 | if (!flag_openmp) /* flag_openmp_simd */ |
edbba2ce | 17238 | { |
d9a6bd32 JJ |
17239 | tree stmt; |
17240 | switch (ccode) | |
17241 | { | |
17242 | case OMP_TEAMS: | |
17243 | stmt = c_parser_omp_teams (loc, parser, p_name, | |
17244 | OMP_TARGET_CLAUSE_MASK, | |
dda1bf61 | 17245 | cclauses, if_p); |
d9a6bd32 JJ |
17246 | break; |
17247 | case OMP_PARALLEL: | |
17248 | stmt = c_parser_omp_parallel (loc, parser, p_name, | |
17249 | OMP_TARGET_CLAUSE_MASK, | |
dda1bf61 | 17250 | cclauses, if_p); |
d9a6bd32 JJ |
17251 | break; |
17252 | case OMP_SIMD: | |
17253 | stmt = c_parser_omp_simd (loc, parser, p_name, | |
17254 | OMP_TARGET_CLAUSE_MASK, | |
dda1bf61 | 17255 | cclauses, if_p); |
d9a6bd32 JJ |
17256 | break; |
17257 | default: | |
17258 | gcc_unreachable (); | |
17259 | } | |
edbba2ce TS |
17260 | return stmt != NULL_TREE; |
17261 | } | |
acf0174b | 17262 | keep_next_level (); |
d9a6bd32 JJ |
17263 | tree block = c_begin_compound_stmt (true), ret; |
17264 | switch (ccode) | |
17265 | { | |
17266 | case OMP_TEAMS: | |
17267 | ret = c_parser_omp_teams (loc, parser, p_name, | |
dda1bf61 JJ |
17268 | OMP_TARGET_CLAUSE_MASK, cclauses, |
17269 | if_p); | |
d9a6bd32 JJ |
17270 | break; |
17271 | case OMP_PARALLEL: | |
17272 | ret = c_parser_omp_parallel (loc, parser, p_name, | |
dda1bf61 JJ |
17273 | OMP_TARGET_CLAUSE_MASK, cclauses, |
17274 | if_p); | |
d9a6bd32 JJ |
17275 | break; |
17276 | case OMP_SIMD: | |
17277 | ret = c_parser_omp_simd (loc, parser, p_name, | |
dda1bf61 JJ |
17278 | OMP_TARGET_CLAUSE_MASK, cclauses, |
17279 | if_p); | |
d9a6bd32 JJ |
17280 | break; |
17281 | default: | |
17282 | gcc_unreachable (); | |
17283 | } | |
acf0174b | 17284 | block = c_end_compound_stmt (loc, block, true); |
edbba2ce TS |
17285 | if (ret == NULL_TREE) |
17286 | return false; | |
e01d41e5 JJ |
17287 | if (ccode == OMP_TEAMS) |
17288 | { | |
17289 | /* For combined target teams, ensure the num_teams and | |
17290 | thread_limit clause expressions are evaluated on the host, | |
17291 | before entering the target construct. */ | |
17292 | tree c; | |
17293 | for (c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; | |
17294 | c; c = OMP_CLAUSE_CHAIN (c)) | |
17295 | if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS | |
17296 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT) | |
17297 | && TREE_CODE (OMP_CLAUSE_OPERAND (c, 0)) != INTEGER_CST) | |
17298 | { | |
17299 | tree expr = OMP_CLAUSE_OPERAND (c, 0); | |
17300 | tree tmp = create_tmp_var_raw (TREE_TYPE (expr)); | |
17301 | expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp, | |
17302 | expr, NULL_TREE, NULL_TREE); | |
17303 | add_stmt (expr); | |
17304 | OMP_CLAUSE_OPERAND (c, 0) = expr; | |
17305 | tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c), | |
17306 | OMP_CLAUSE_FIRSTPRIVATE); | |
17307 | OMP_CLAUSE_DECL (tc) = tmp; | |
17308 | OMP_CLAUSE_CHAIN (tc) | |
17309 | = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; | |
17310 | cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc; | |
17311 | } | |
17312 | } | |
acf0174b JJ |
17313 | tree stmt = make_node (OMP_TARGET); |
17314 | TREE_TYPE (stmt) = void_type_node; | |
17315 | OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; | |
17316 | OMP_TARGET_BODY (stmt) = block; | |
d9a6bd32 | 17317 | OMP_TARGET_COMBINED (stmt) = 1; |
acf0174b | 17318 | add_stmt (stmt); |
d9a6bd32 JJ |
17319 | pc = &OMP_TARGET_CLAUSES (stmt); |
17320 | goto check_clauses; | |
acf0174b | 17321 | } |
6d7f7e0a TB |
17322 | else if (!flag_openmp) /* flag_openmp_simd */ |
17323 | { | |
62021f64 | 17324 | c_parser_skip_to_pragma_eol (parser, false); |
edbba2ce | 17325 | return false; |
6d7f7e0a TB |
17326 | } |
17327 | else if (strcmp (p, "data") == 0) | |
17328 | { | |
17329 | c_parser_consume_token (parser); | |
dda1bf61 | 17330 | c_parser_omp_target_data (loc, parser, if_p); |
6d7f7e0a TB |
17331 | return true; |
17332 | } | |
d9a6bd32 JJ |
17333 | else if (strcmp (p, "enter") == 0) |
17334 | { | |
17335 | c_parser_consume_token (parser); | |
17336 | c_parser_omp_target_enter_data (loc, parser, context); | |
17337 | return false; | |
17338 | } | |
17339 | else if (strcmp (p, "exit") == 0) | |
17340 | { | |
17341 | c_parser_consume_token (parser); | |
17342 | c_parser_omp_target_exit_data (loc, parser, context); | |
17343 | return false; | |
17344 | } | |
6d7f7e0a TB |
17345 | else if (strcmp (p, "update") == 0) |
17346 | { | |
17347 | c_parser_consume_token (parser); | |
17348 | return c_parser_omp_target_update (loc, parser, context); | |
17349 | } | |
953ff289 | 17350 | } |
bcac0b4d JJ |
17351 | if (!flag_openmp) /* flag_openmp_simd */ |
17352 | { | |
17353 | c_parser_skip_to_pragma_eol (parser, false); | |
17354 | return false; | |
17355 | } | |
953ff289 | 17356 | |
d9a6bd32 | 17357 | stmt = make_node (OMP_TARGET); |
953ff289 | 17358 | TREE_TYPE (stmt) = void_type_node; |
953ff289 | 17359 | |
acf0174b JJ |
17360 | OMP_TARGET_CLAUSES (stmt) |
17361 | = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK, | |
17362 | "#pragma omp target"); | |
d9a6bd32 | 17363 | pc = &OMP_TARGET_CLAUSES (stmt); |
acf0174b | 17364 | keep_next_level (); |
d9a6bd32 | 17365 | block = c_begin_compound_stmt (true); |
dda1bf61 | 17366 | add_stmt (c_parser_omp_structured_block (parser, if_p)); |
acf0174b JJ |
17367 | OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true); |
17368 | ||
17369 | SET_EXPR_LOCATION (stmt, loc); | |
17370 | add_stmt (stmt); | |
d9a6bd32 JJ |
17371 | |
17372 | check_clauses: | |
17373 | while (*pc) | |
17374 | { | |
17375 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) | |
17376 | switch (OMP_CLAUSE_MAP_KIND (*pc)) | |
17377 | { | |
17378 | case GOMP_MAP_TO: | |
17379 | case GOMP_MAP_ALWAYS_TO: | |
17380 | case GOMP_MAP_FROM: | |
17381 | case GOMP_MAP_ALWAYS_FROM: | |
17382 | case GOMP_MAP_TOFROM: | |
17383 | case GOMP_MAP_ALWAYS_TOFROM: | |
17384 | case GOMP_MAP_ALLOC: | |
17385 | case GOMP_MAP_FIRSTPRIVATE_POINTER: | |
e01d41e5 | 17386 | case GOMP_MAP_ALWAYS_POINTER: |
d9a6bd32 JJ |
17387 | break; |
17388 | default: | |
17389 | error_at (OMP_CLAUSE_LOCATION (*pc), | |
17390 | "%<#pragma omp target%> with map-type other " | |
17391 | "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> " | |
17392 | "on %<map%> clause"); | |
17393 | *pc = OMP_CLAUSE_CHAIN (*pc); | |
17394 | continue; | |
17395 | } | |
17396 | pc = &OMP_CLAUSE_CHAIN (*pc); | |
17397 | } | |
acf0174b JJ |
17398 | return true; |
17399 | } | |
17400 | ||
17401 | /* OpenMP 4.0: | |
17402 | # pragma omp declare simd declare-simd-clauses[optseq] new-line */ | |
17403 | ||
17404 | #define OMP_DECLARE_SIMD_CLAUSE_MASK \ | |
17405 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ | |
17406 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ | |
17407 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ | |
17408 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ | |
17409 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ | |
17410 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) | |
17411 | ||
17412 | static void | |
17413 | c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context) | |
17414 | { | |
8c681247 | 17415 | auto_vec<c_token> clauses; |
acf0174b JJ |
17416 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) |
17417 | { | |
17418 | c_token *token = c_parser_peek_token (parser); | |
17419 | if (token->type == CPP_EOF) | |
17420 | { | |
17421 | c_parser_skip_to_pragma_eol (parser); | |
acf0174b JJ |
17422 | return; |
17423 | } | |
17424 | clauses.safe_push (*token); | |
17425 | c_parser_consume_token (parser); | |
17426 | } | |
17427 | clauses.safe_push (*c_parser_peek_token (parser)); | |
17428 | c_parser_skip_to_pragma_eol (parser); | |
17429 | ||
17430 | while (c_parser_next_token_is (parser, CPP_PRAGMA)) | |
17431 | { | |
17432 | if (c_parser_peek_token (parser)->pragma_kind | |
f9d8d994 | 17433 | != PRAGMA_OMP_DECLARE |
acf0174b JJ |
17434 | || c_parser_peek_2nd_token (parser)->type != CPP_NAME |
17435 | || strcmp (IDENTIFIER_POINTER | |
17436 | (c_parser_peek_2nd_token (parser)->value), | |
17437 | "simd") != 0) | |
17438 | { | |
17439 | c_parser_error (parser, | |
17440 | "%<#pragma omp declare simd%> must be followed by " | |
17441 | "function declaration or definition or another " | |
17442 | "%<#pragma omp declare simd%>"); | |
acf0174b JJ |
17443 | return; |
17444 | } | |
17445 | c_parser_consume_pragma (parser); | |
17446 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
17447 | { | |
17448 | c_token *token = c_parser_peek_token (parser); | |
17449 | if (token->type == CPP_EOF) | |
17450 | { | |
17451 | c_parser_skip_to_pragma_eol (parser); | |
acf0174b JJ |
17452 | return; |
17453 | } | |
17454 | clauses.safe_push (*token); | |
17455 | c_parser_consume_token (parser); | |
17456 | } | |
17457 | clauses.safe_push (*c_parser_peek_token (parser)); | |
17458 | c_parser_skip_to_pragma_eol (parser); | |
17459 | } | |
17460 | ||
17461 | /* Make sure nothing tries to read past the end of the tokens. */ | |
17462 | c_token eof_token; | |
17463 | memset (&eof_token, 0, sizeof (eof_token)); | |
17464 | eof_token.type = CPP_EOF; | |
17465 | clauses.safe_push (eof_token); | |
17466 | clauses.safe_push (eof_token); | |
17467 | ||
17468 | switch (context) | |
17469 | { | |
17470 | case pragma_external: | |
17471 | if (c_parser_next_token_is (parser, CPP_KEYWORD) | |
17472 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION) | |
17473 | { | |
17474 | int ext = disable_extension_diagnostics (); | |
17475 | do | |
17476 | c_parser_consume_token (parser); | |
17477 | while (c_parser_next_token_is (parser, CPP_KEYWORD) | |
17478 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION); | |
17479 | c_parser_declaration_or_fndef (parser, true, true, true, false, true, | |
17480 | NULL, clauses); | |
17481 | restore_extension_diagnostics (ext); | |
17482 | } | |
17483 | else | |
17484 | c_parser_declaration_or_fndef (parser, true, true, true, false, true, | |
17485 | NULL, clauses); | |
17486 | break; | |
17487 | case pragma_struct: | |
17488 | case pragma_param: | |
17489 | c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by " | |
17490 | "function declaration or definition"); | |
17491 | break; | |
17492 | case pragma_compound: | |
17493 | case pragma_stmt: | |
17494 | if (c_parser_next_token_is (parser, CPP_KEYWORD) | |
17495 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION) | |
17496 | { | |
17497 | int ext = disable_extension_diagnostics (); | |
17498 | do | |
17499 | c_parser_consume_token (parser); | |
17500 | while (c_parser_next_token_is (parser, CPP_KEYWORD) | |
17501 | && c_parser_peek_token (parser)->keyword == RID_EXTENSION); | |
17502 | if (c_parser_next_tokens_start_declaration (parser)) | |
17503 | { | |
17504 | c_parser_declaration_or_fndef (parser, true, true, true, true, | |
17505 | true, NULL, clauses); | |
17506 | restore_extension_diagnostics (ext); | |
17507 | break; | |
17508 | } | |
17509 | restore_extension_diagnostics (ext); | |
17510 | } | |
17511 | else if (c_parser_next_tokens_start_declaration (parser)) | |
17512 | { | |
17513 | c_parser_declaration_or_fndef (parser, true, true, true, true, true, | |
17514 | NULL, clauses); | |
17515 | break; | |
17516 | } | |
17517 | c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by " | |
17518 | "function declaration or definition"); | |
17519 | break; | |
17520 | default: | |
17521 | gcc_unreachable (); | |
17522 | } | |
953ff289 DN |
17523 | } |
17524 | ||
acf0174b JJ |
17525 | /* Finalize #pragma omp declare simd clauses after FNDECL has been parsed, |
17526 | and put that into "omp declare simd" attribute. */ | |
c2255bc4 | 17527 | |
acf0174b JJ |
17528 | static void |
17529 | c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, | |
17530 | vec<c_token> clauses) | |
17531 | { | |
b72271b9 | 17532 | if (flag_cilkplus |
fff77217 KY |
17533 | && (clauses.exists () |
17534 | || lookup_attribute ("simd", DECL_ATTRIBUTES (fndecl))) | |
17535 | && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
41958c28 | 17536 | { |
fff77217 KY |
17537 | error ("%<#pragma omp declare simd%> or %<simd%> attribute cannot be " |
17538 | "used in the same function marked as a Cilk Plus SIMD-enabled " | |
17539 | "function"); | |
41958c28 BI |
17540 | vec_free (parser->cilk_simd_fn_tokens); |
17541 | return; | |
17542 | } | |
17543 | ||
acf0174b JJ |
17544 | /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates |
17545 | error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd | |
17546 | has already processed the tokens. */ | |
41958c28 | 17547 | if (clauses.exists () && clauses[0].type == CPP_EOF) |
acf0174b JJ |
17548 | return; |
17549 | if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) | |
17550 | { | |
17551 | error ("%<#pragma omp declare simd%> not immediately followed by " | |
17552 | "a function declaration or definition"); | |
17553 | clauses[0].type = CPP_EOF; | |
17554 | return; | |
17555 | } | |
41958c28 | 17556 | if (clauses.exists () && clauses[0].type != CPP_NAME) |
acf0174b JJ |
17557 | { |
17558 | error_at (DECL_SOURCE_LOCATION (fndecl), | |
17559 | "%<#pragma omp declare simd%> not immediately followed by " | |
17560 | "a single function declaration or definition"); | |
17561 | clauses[0].type = CPP_EOF; | |
17562 | return; | |
17563 | } | |
953ff289 | 17564 | |
acf0174b JJ |
17565 | if (parms == NULL_TREE) |
17566 | parms = DECL_ARGUMENTS (fndecl); | |
953ff289 | 17567 | |
acf0174b JJ |
17568 | unsigned int tokens_avail = parser->tokens_avail; |
17569 | gcc_assert (parser->tokens == &parser->tokens_buf[0]); | |
41958c28 BI |
17570 | bool is_cilkplus_cilk_simd_fn = false; |
17571 | ||
b72271b9 | 17572 | if (flag_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) |
41958c28 BI |
17573 | { |
17574 | parser->tokens = parser->cilk_simd_fn_tokens->address (); | |
17575 | parser->tokens_avail = vec_safe_length (parser->cilk_simd_fn_tokens); | |
17576 | is_cilkplus_cilk_simd_fn = true; | |
fff77217 KY |
17577 | |
17578 | if (lookup_attribute ("simd", DECL_ATTRIBUTES (fndecl)) != NULL) | |
17579 | { | |
17580 | error_at (DECL_SOURCE_LOCATION (fndecl), | |
17581 | "%<__simd__%> attribute cannot be used in the same " | |
17582 | "function marked as a Cilk Plus SIMD-enabled function"); | |
17583 | vec_free (parser->cilk_simd_fn_tokens); | |
17584 | return; | |
17585 | } | |
17586 | ||
41958c28 BI |
17587 | } |
17588 | else | |
17589 | { | |
17590 | parser->tokens = clauses.address (); | |
17591 | parser->tokens_avail = clauses.length (); | |
17592 | } | |
17593 | ||
acf0174b JJ |
17594 | /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */ |
17595 | while (parser->tokens_avail > 3) | |
17596 | { | |
17597 | c_token *token = c_parser_peek_token (parser); | |
41958c28 BI |
17598 | if (!is_cilkplus_cilk_simd_fn) |
17599 | gcc_assert (token->type == CPP_NAME | |
17600 | && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); | |
17601 | else | |
17602 | gcc_assert (token->type == CPP_NAME | |
17603 | && is_cilkplus_vector_p (token->value)); | |
acf0174b JJ |
17604 | c_parser_consume_token (parser); |
17605 | parser->in_pragma = true; | |
953ff289 | 17606 | |
41958c28 BI |
17607 | tree c = NULL_TREE; |
17608 | if (is_cilkplus_cilk_simd_fn) | |
17609 | c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK, | |
17610 | "SIMD-enabled functions attribute"); | |
17611 | else | |
17612 | c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, | |
17613 | "#pragma omp declare simd"); | |
acf0174b JJ |
17614 | c = c_omp_declare_simd_clauses_to_numbers (parms, c); |
17615 | if (c != NULL_TREE) | |
17616 | c = tree_cons (NULL_TREE, c, NULL_TREE); | |
41958c28 | 17617 | if (is_cilkplus_cilk_simd_fn) |
fff77217 | 17618 | { |
74558dd9 BI |
17619 | tree k = build_tree_list (get_identifier ("cilk simd function"), |
17620 | NULL_TREE); | |
41958c28 BI |
17621 | TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl); |
17622 | DECL_ATTRIBUTES (fndecl) = k; | |
fff77217 | 17623 | } |
acf0174b JJ |
17624 | c = build_tree_list (get_identifier ("omp declare simd"), c); |
17625 | TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); | |
17626 | DECL_ATTRIBUTES (fndecl) = c; | |
17627 | } | |
953ff289 | 17628 | |
acf0174b JJ |
17629 | parser->tokens = &parser->tokens_buf[0]; |
17630 | parser->tokens_avail = tokens_avail; | |
41958c28 BI |
17631 | if (clauses.exists ()) |
17632 | clauses[0].type = CPP_PRAGMA; | |
17633 | ||
17634 | if (!vec_safe_is_empty (parser->cilk_simd_fn_tokens)) | |
17635 | vec_free (parser->cilk_simd_fn_tokens); | |
953ff289 DN |
17636 | } |
17637 | ||
953ff289 | 17638 | |
acf0174b JJ |
17639 | /* OpenMP 4.0: |
17640 | # pragma omp declare target new-line | |
17641 | declarations and definitions | |
d9a6bd32 JJ |
17642 | # pragma omp end declare target new-line |
17643 | ||
17644 | OpenMP 4.5: | |
17645 | # pragma omp declare target ( extended-list ) new-line | |
17646 | ||
17647 | # pragma omp declare target declare-target-clauses[seq] new-line */ | |
17648 | ||
17649 | #define OMP_DECLARE_TARGET_CLAUSE_MASK \ | |
17650 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ | |
17651 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) | |
953ff289 | 17652 | |
acf0174b JJ |
17653 | static void |
17654 | c_parser_omp_declare_target (c_parser *parser) | |
953ff289 | 17655 | { |
d9a6bd32 JJ |
17656 | location_t loc = c_parser_peek_token (parser)->location; |
17657 | tree clauses = NULL_TREE; | |
17658 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
17659 | clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, | |
17660 | "#pragma omp declare target"); | |
17661 | else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |
17662 | { | |
17663 | clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE, | |
17664 | clauses); | |
77886428 | 17665 | clauses = c_finish_omp_clauses (clauses, C_ORT_OMP); |
d9a6bd32 JJ |
17666 | c_parser_skip_to_pragma_eol (parser); |
17667 | } | |
17668 | else | |
17669 | { | |
17670 | c_parser_skip_to_pragma_eol (parser); | |
17671 | current_omp_declare_target_attribute++; | |
17672 | return; | |
17673 | } | |
17674 | if (current_omp_declare_target_attribute) | |
17675 | error_at (loc, "%<#pragma omp declare target%> with clauses in between " | |
17676 | "%<#pragma omp declare target%> without clauses and " | |
17677 | "%<#pragma omp end declare target%>"); | |
17678 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) | |
17679 | { | |
17680 | tree t = OMP_CLAUSE_DECL (c), id; | |
17681 | tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t)); | |
17682 | tree at2 = lookup_attribute ("omp declare target link", | |
17683 | DECL_ATTRIBUTES (t)); | |
17684 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK) | |
17685 | { | |
17686 | id = get_identifier ("omp declare target link"); | |
17687 | std::swap (at1, at2); | |
17688 | } | |
17689 | else | |
17690 | id = get_identifier ("omp declare target"); | |
17691 | if (at2) | |
17692 | { | |
17693 | error_at (OMP_CLAUSE_LOCATION (c), | |
17694 | "%qD specified both in declare target %<link%> and %<to%>" | |
17695 | " clauses", t); | |
17696 | continue; | |
17697 | } | |
17698 | if (!at1) | |
e01d41e5 | 17699 | { |
e01d41e5 | 17700 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
56f71478 JJ |
17701 | if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t)) |
17702 | continue; | |
17703 | ||
17704 | symtab_node *node = symtab_node::get (t); | |
e01d41e5 JJ |
17705 | if (node != NULL) |
17706 | { | |
17707 | node->offloadable = 1; | |
1d899da2 | 17708 | if (ENABLE_OFFLOADING) |
e01d41e5 | 17709 | { |
1d899da2 TS |
17710 | g->have_offload = true; |
17711 | if (is_a <varpool_node *> (node)) | |
e6d6ec9e | 17712 | vec_safe_push (offload_vars, t); |
e01d41e5 | 17713 | } |
e01d41e5 JJ |
17714 | } |
17715 | } | |
d9a6bd32 | 17716 | } |
acf0174b | 17717 | } |
953ff289 | 17718 | |
acf0174b JJ |
17719 | static void |
17720 | c_parser_omp_end_declare_target (c_parser *parser) | |
17721 | { | |
17722 | location_t loc = c_parser_peek_token (parser)->location; | |
17723 | c_parser_consume_pragma (parser); | |
17724 | if (c_parser_next_token_is (parser, CPP_NAME) | |
17725 | && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), | |
17726 | "declare") == 0) | |
953ff289 DN |
17727 | { |
17728 | c_parser_consume_token (parser); | |
acf0174b JJ |
17729 | if (c_parser_next_token_is (parser, CPP_NAME) |
17730 | && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), | |
17731 | "target") == 0) | |
17732 | c_parser_consume_token (parser); | |
17733 | else | |
953ff289 | 17734 | { |
acf0174b JJ |
17735 | c_parser_error (parser, "expected %<target%>"); |
17736 | c_parser_skip_to_pragma_eol (parser); | |
17737 | return; | |
953ff289 DN |
17738 | } |
17739 | } | |
acf0174b JJ |
17740 | else |
17741 | { | |
17742 | c_parser_error (parser, "expected %<declare%>"); | |
17743 | c_parser_skip_to_pragma_eol (parser); | |
17744 | return; | |
17745 | } | |
17746 | c_parser_skip_to_pragma_eol (parser); | |
17747 | if (!current_omp_declare_target_attribute) | |
17748 | error_at (loc, "%<#pragma omp end declare target%> without corresponding " | |
17749 | "%<#pragma omp declare target%>"); | |
17750 | else | |
17751 | current_omp_declare_target_attribute--; | |
17752 | } | |
953ff289 | 17753 | |
953ff289 | 17754 | |
acf0174b JJ |
17755 | /* OpenMP 4.0 |
17756 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ | |
17757 | initializer-clause[opt] new-line | |
17758 | ||
17759 | initializer-clause: | |
17760 | initializer (omp_priv = initializer) | |
17761 | initializer (function-name (argument-list)) */ | |
17762 | ||
17763 | static void | |
17764 | c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context) | |
17765 | { | |
17766 | unsigned int tokens_avail = 0, i; | |
17767 | vec<tree> types = vNULL; | |
17768 | vec<c_token> clauses = vNULL; | |
17769 | enum tree_code reduc_code = ERROR_MARK; | |
17770 | tree reduc_id = NULL_TREE; | |
17771 | tree type; | |
17772 | location_t rloc = c_parser_peek_token (parser)->location; | |
17773 | ||
17774 | if (context == pragma_struct || context == pragma_param) | |
953ff289 | 17775 | { |
acf0174b JJ |
17776 | error ("%<#pragma omp declare reduction%> not at file or block scope"); |
17777 | goto fail; | |
17778 | } | |
953ff289 | 17779 | |
acf0174b JJ |
17780 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
17781 | goto fail; | |
953ff289 | 17782 | |
acf0174b JJ |
17783 | switch (c_parser_peek_token (parser)->type) |
17784 | { | |
17785 | case CPP_PLUS: | |
17786 | reduc_code = PLUS_EXPR; | |
17787 | break; | |
17788 | case CPP_MULT: | |
17789 | reduc_code = MULT_EXPR; | |
17790 | break; | |
17791 | case CPP_MINUS: | |
17792 | reduc_code = MINUS_EXPR; | |
17793 | break; | |
17794 | case CPP_AND: | |
17795 | reduc_code = BIT_AND_EXPR; | |
17796 | break; | |
17797 | case CPP_XOR: | |
17798 | reduc_code = BIT_XOR_EXPR; | |
17799 | break; | |
17800 | case CPP_OR: | |
17801 | reduc_code = BIT_IOR_EXPR; | |
17802 | break; | |
17803 | case CPP_AND_AND: | |
17804 | reduc_code = TRUTH_ANDIF_EXPR; | |
17805 | break; | |
17806 | case CPP_OR_OR: | |
17807 | reduc_code = TRUTH_ORIF_EXPR; | |
17808 | break; | |
17809 | case CPP_NAME: | |
17810 | const char *p; | |
17811 | p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
17812 | if (strcmp (p, "min") == 0) | |
17813 | { | |
17814 | reduc_code = MIN_EXPR; | |
17815 | break; | |
17816 | } | |
17817 | if (strcmp (p, "max") == 0) | |
17818 | { | |
17819 | reduc_code = MAX_EXPR; | |
17820 | break; | |
17821 | } | |
17822 | reduc_id = c_parser_peek_token (parser)->value; | |
953ff289 | 17823 | break; |
953ff289 | 17824 | default: |
acf0174b JJ |
17825 | c_parser_error (parser, |
17826 | "expected %<+%>, %<*%>, %<-%>, %<&%>, " | |
79c9b7a8 | 17827 | "%<^%>, %<|%>, %<&&%>, %<||%> or identifier"); |
acf0174b | 17828 | goto fail; |
953ff289 DN |
17829 | } |
17830 | ||
acf0174b JJ |
17831 | tree orig_reduc_id, reduc_decl; |
17832 | orig_reduc_id = reduc_id; | |
17833 | reduc_id = c_omp_reduction_id (reduc_code, reduc_id); | |
17834 | reduc_decl = c_omp_reduction_decl (reduc_id); | |
17835 | c_parser_consume_token (parser); | |
953ff289 | 17836 | |
acf0174b JJ |
17837 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
17838 | goto fail; | |
c2255bc4 | 17839 | |
acf0174b JJ |
17840 | while (true) |
17841 | { | |
17842 | location_t loc = c_parser_peek_token (parser)->location; | |
17843 | struct c_type_name *ctype = c_parser_type_name (parser); | |
17844 | if (ctype != NULL) | |
17845 | { | |
17846 | type = groktypename (ctype, NULL, NULL); | |
17847 | if (type == error_mark_node) | |
17848 | ; | |
17849 | else if ((INTEGRAL_TYPE_P (type) | |
17850 | || TREE_CODE (type) == REAL_TYPE | |
17851 | || TREE_CODE (type) == COMPLEX_TYPE) | |
17852 | && orig_reduc_id == NULL_TREE) | |
17853 | error_at (loc, "predeclared arithmetic type in " | |
17854 | "%<#pragma omp declare reduction%>"); | |
17855 | else if (TREE_CODE (type) == FUNCTION_TYPE | |
17856 | || TREE_CODE (type) == ARRAY_TYPE) | |
17857 | error_at (loc, "function or array type in " | |
17858 | "%<#pragma omp declare reduction%>"); | |
9dc5773f JJ |
17859 | else if (TYPE_ATOMIC (type)) |
17860 | error_at (loc, "%<_Atomic%> qualified type in " | |
17861 | "%<#pragma omp declare reduction%>"); | |
acf0174b JJ |
17862 | else if (TYPE_QUALS_NO_ADDR_SPACE (type)) |
17863 | error_at (loc, "const, volatile or restrict qualified type in " | |
17864 | "%<#pragma omp declare reduction%>"); | |
17865 | else | |
17866 | { | |
17867 | tree t; | |
17868 | for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t)) | |
17869 | if (comptypes (TREE_PURPOSE (t), type)) | |
17870 | { | |
17871 | error_at (loc, "redeclaration of %qs " | |
17872 | "%<#pragma omp declare reduction%> for " | |
17873 | "type %qT", | |
17874 | IDENTIFIER_POINTER (reduc_id) | |
17875 | + sizeof ("omp declare reduction ") - 1, | |
17876 | type); | |
17877 | location_t ploc | |
17878 | = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t), | |
17879 | 0)); | |
17880 | error_at (ploc, "previous %<#pragma omp declare " | |
17881 | "reduction%>"); | |
17882 | break; | |
17883 | } | |
17884 | if (t == NULL_TREE) | |
17885 | types.safe_push (type); | |
17886 | } | |
17887 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |
17888 | c_parser_consume_token (parser); | |
17889 | else | |
17890 | break; | |
17891 | } | |
17892 | else | |
17893 | break; | |
17894 | } | |
953ff289 | 17895 | |
acf0174b JJ |
17896 | if (!c_parser_require (parser, CPP_COLON, "expected %<:%>") |
17897 | || types.is_empty ()) | |
17898 | { | |
17899 | fail: | |
17900 | clauses.release (); | |
17901 | types.release (); | |
17902 | while (true) | |
17903 | { | |
17904 | c_token *token = c_parser_peek_token (parser); | |
17905 | if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL) | |
17906 | break; | |
17907 | c_parser_consume_token (parser); | |
17908 | } | |
17909 | c_parser_skip_to_pragma_eol (parser); | |
17910 | return; | |
17911 | } | |
953ff289 | 17912 | |
acf0174b JJ |
17913 | if (types.length () > 1) |
17914 | { | |
17915 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
17916 | { | |
17917 | c_token *token = c_parser_peek_token (parser); | |
17918 | if (token->type == CPP_EOF) | |
17919 | goto fail; | |
17920 | clauses.safe_push (*token); | |
17921 | c_parser_consume_token (parser); | |
17922 | } | |
17923 | clauses.safe_push (*c_parser_peek_token (parser)); | |
17924 | c_parser_skip_to_pragma_eol (parser); | |
953ff289 | 17925 | |
acf0174b JJ |
17926 | /* Make sure nothing tries to read past the end of the tokens. */ |
17927 | c_token eof_token; | |
17928 | memset (&eof_token, 0, sizeof (eof_token)); | |
17929 | eof_token.type = CPP_EOF; | |
17930 | clauses.safe_push (eof_token); | |
17931 | clauses.safe_push (eof_token); | |
17932 | } | |
953ff289 | 17933 | |
acf0174b JJ |
17934 | int errs = errorcount; |
17935 | FOR_EACH_VEC_ELT (types, i, type) | |
17936 | { | |
17937 | tokens_avail = parser->tokens_avail; | |
17938 | gcc_assert (parser->tokens == &parser->tokens_buf[0]); | |
17939 | if (!clauses.is_empty ()) | |
17940 | { | |
17941 | parser->tokens = clauses.address (); | |
17942 | parser->tokens_avail = clauses.length (); | |
17943 | parser->in_pragma = true; | |
17944 | } | |
953ff289 | 17945 | |
acf0174b JJ |
17946 | bool nested = current_function_decl != NULL_TREE; |
17947 | if (nested) | |
17948 | c_push_function_context (); | |
17949 | tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, | |
17950 | reduc_id, default_function_type); | |
17951 | current_function_decl = fndecl; | |
17952 | allocate_struct_function (fndecl, true); | |
17953 | push_scope (); | |
17954 | tree stmt = push_stmt_list (); | |
17955 | /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't | |
17956 | warn about these. */ | |
17957 | tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL, | |
17958 | get_identifier ("omp_out"), type); | |
17959 | DECL_ARTIFICIAL (omp_out) = 1; | |
17960 | DECL_CONTEXT (omp_out) = fndecl; | |
17961 | pushdecl (omp_out); | |
17962 | tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL, | |
17963 | get_identifier ("omp_in"), type); | |
17964 | DECL_ARTIFICIAL (omp_in) = 1; | |
17965 | DECL_CONTEXT (omp_in) = fndecl; | |
17966 | pushdecl (omp_in); | |
17967 | struct c_expr combiner = c_parser_expression (parser); | |
17968 | struct c_expr initializer; | |
17969 | tree omp_priv = NULL_TREE, omp_orig = NULL_TREE; | |
17970 | bool bad = false; | |
17971 | initializer.value = error_mark_node; | |
17972 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |
17973 | bad = true; | |
17974 | else if (c_parser_next_token_is (parser, CPP_NAME) | |
17975 | && strcmp (IDENTIFIER_POINTER | |
17976 | (c_parser_peek_token (parser)->value), | |
17977 | "initializer") == 0) | |
17978 | { | |
17979 | c_parser_consume_token (parser); | |
17980 | pop_scope (); | |
17981 | push_scope (); | |
17982 | omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL, | |
17983 | get_identifier ("omp_priv"), type); | |
17984 | DECL_ARTIFICIAL (omp_priv) = 1; | |
17985 | DECL_INITIAL (omp_priv) = error_mark_node; | |
17986 | DECL_CONTEXT (omp_priv) = fndecl; | |
17987 | pushdecl (omp_priv); | |
17988 | omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL, | |
17989 | get_identifier ("omp_orig"), type); | |
17990 | DECL_ARTIFICIAL (omp_orig) = 1; | |
17991 | DECL_CONTEXT (omp_orig) = fndecl; | |
17992 | pushdecl (omp_orig); | |
17993 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |
17994 | bad = true; | |
17995 | else if (!c_parser_next_token_is (parser, CPP_NAME)) | |
17996 | { | |
17997 | c_parser_error (parser, "expected %<omp_priv%> or " | |
17998 | "function-name"); | |
17999 | bad = true; | |
18000 | } | |
18001 | else if (strcmp (IDENTIFIER_POINTER | |
18002 | (c_parser_peek_token (parser)->value), | |
18003 | "omp_priv") != 0) | |
18004 | { | |
18005 | if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN | |
18006 | || c_parser_peek_token (parser)->id_kind != C_ID_ID) | |
18007 | { | |
18008 | c_parser_error (parser, "expected function-name %<(%>"); | |
18009 | bad = true; | |
18010 | } | |
18011 | else | |
18012 | initializer = c_parser_postfix_expression (parser); | |
18013 | if (initializer.value | |
18014 | && TREE_CODE (initializer.value) == CALL_EXPR) | |
18015 | { | |
18016 | int j; | |
18017 | tree c = initializer.value; | |
18018 | for (j = 0; j < call_expr_nargs (c); j++) | |
d9a6bd32 JJ |
18019 | { |
18020 | tree a = CALL_EXPR_ARG (c, j); | |
18021 | STRIP_NOPS (a); | |
18022 | if (TREE_CODE (a) == ADDR_EXPR | |
18023 | && TREE_OPERAND (a, 0) == omp_priv) | |
18024 | break; | |
18025 | } | |
acf0174b JJ |
18026 | if (j == call_expr_nargs (c)) |
18027 | error ("one of the initializer call arguments should be " | |
18028 | "%<&omp_priv%>"); | |
18029 | } | |
18030 | } | |
18031 | else | |
18032 | { | |
18033 | c_parser_consume_token (parser); | |
18034 | if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) | |
18035 | bad = true; | |
18036 | else | |
18037 | { | |
18038 | tree st = push_stmt_list (); | |
acf0174b | 18039 | location_t loc = c_parser_peek_token (parser)->location; |
5dd9a9d0 DM |
18040 | rich_location richloc (line_table, loc); |
18041 | start_init (omp_priv, NULL_TREE, 0, &richloc); | |
acf0174b JJ |
18042 | struct c_expr init = c_parser_initializer (parser); |
18043 | finish_init (); | |
18044 | finish_decl (omp_priv, loc, init.value, | |
18045 | init.original_type, NULL_TREE); | |
18046 | pop_stmt_list (st); | |
18047 | } | |
18048 | } | |
18049 | if (!bad | |
18050 | && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |
18051 | bad = true; | |
18052 | } | |
c2255bc4 | 18053 | |
acf0174b JJ |
18054 | if (!bad) |
18055 | { | |
18056 | c_parser_skip_to_pragma_eol (parser); | |
a68ab351 | 18057 | |
acf0174b JJ |
18058 | tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3), |
18059 | DECL_INITIAL (reduc_decl)); | |
18060 | DECL_INITIAL (reduc_decl) = t; | |
18061 | DECL_SOURCE_LOCATION (omp_out) = rloc; | |
18062 | TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out; | |
18063 | TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in; | |
18064 | TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value; | |
18065 | walk_tree (&combiner.value, c_check_omp_declare_reduction_r, | |
18066 | &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL); | |
18067 | if (omp_priv) | |
18068 | { | |
18069 | DECL_SOURCE_LOCATION (omp_priv) = rloc; | |
18070 | TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv; | |
18071 | TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig; | |
18072 | TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value; | |
18073 | walk_tree (&initializer.value, c_check_omp_declare_reduction_r, | |
18074 | &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL); | |
18075 | walk_tree (&DECL_INITIAL (omp_priv), | |
18076 | c_check_omp_declare_reduction_r, | |
18077 | &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL); | |
18078 | } | |
18079 | } | |
a68ab351 | 18080 | |
acf0174b JJ |
18081 | pop_stmt_list (stmt); |
18082 | pop_scope (); | |
18083 | if (cfun->language != NULL) | |
18084 | { | |
18085 | ggc_free (cfun->language); | |
18086 | cfun->language = NULL; | |
18087 | } | |
18088 | set_cfun (NULL); | |
18089 | current_function_decl = NULL_TREE; | |
18090 | if (nested) | |
18091 | c_pop_function_context (); | |
a68ab351 | 18092 | |
acf0174b JJ |
18093 | if (!clauses.is_empty ()) |
18094 | { | |
18095 | parser->tokens = &parser->tokens_buf[0]; | |
18096 | parser->tokens_avail = tokens_avail; | |
18097 | } | |
18098 | if (bad) | |
18099 | goto fail; | |
18100 | if (errs != errorcount) | |
18101 | break; | |
18102 | } | |
a68ab351 | 18103 | |
acf0174b JJ |
18104 | clauses.release (); |
18105 | types.release (); | |
a68ab351 JJ |
18106 | } |
18107 | ||
953ff289 | 18108 | |
acf0174b JJ |
18109 | /* OpenMP 4.0 |
18110 | #pragma omp declare simd declare-simd-clauses[optseq] new-line | |
18111 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ | |
18112 | initializer-clause[opt] new-line | |
18113 | #pragma omp declare target new-line */ | |
20906c66 JJ |
18114 | |
18115 | static void | |
acf0174b | 18116 | c_parser_omp_declare (c_parser *parser, enum pragma_context context) |
20906c66 | 18117 | { |
20906c66 | 18118 | c_parser_consume_pragma (parser); |
acf0174b JJ |
18119 | if (c_parser_next_token_is (parser, CPP_NAME)) |
18120 | { | |
18121 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
18122 | if (strcmp (p, "simd") == 0) | |
18123 | { | |
18124 | /* c_parser_consume_token (parser); done in | |
18125 | c_parser_omp_declare_simd. */ | |
18126 | c_parser_omp_declare_simd (parser, context); | |
18127 | return; | |
18128 | } | |
18129 | if (strcmp (p, "reduction") == 0) | |
18130 | { | |
18131 | c_parser_consume_token (parser); | |
18132 | c_parser_omp_declare_reduction (parser, context); | |
18133 | return; | |
18134 | } | |
6d7f7e0a TB |
18135 | if (!flag_openmp) /* flag_openmp_simd */ |
18136 | { | |
62021f64 | 18137 | c_parser_skip_to_pragma_eol (parser, false); |
6d7f7e0a TB |
18138 | return; |
18139 | } | |
acf0174b JJ |
18140 | if (strcmp (p, "target") == 0) |
18141 | { | |
18142 | c_parser_consume_token (parser); | |
18143 | c_parser_omp_declare_target (parser); | |
18144 | return; | |
18145 | } | |
18146 | } | |
20906c66 | 18147 | |
acf0174b JJ |
18148 | c_parser_error (parser, "expected %<simd%> or %<reduction%> " |
18149 | "or %<target%>"); | |
18150 | c_parser_skip_to_pragma_eol (parser); | |
20906c66 JJ |
18151 | } |
18152 | ||
d9a6bd32 JJ |
18153 | /* OpenMP 4.5: |
18154 | #pragma omp taskloop taskloop-clause[optseq] new-line | |
18155 | for-loop | |
18156 | ||
18157 | #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line | |
18158 | for-loop */ | |
18159 | ||
18160 | #define OMP_TASKLOOP_CLAUSE_MASK \ | |
18161 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | |
18162 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | |
18163 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | |
18164 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ | |
18165 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ | |
18166 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \ | |
18167 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \ | |
18168 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ | |
18169 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ | |
18170 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | |
18171 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ | |
18172 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ | |
18173 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \ | |
18174 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)) | |
18175 | ||
18176 | static tree | |
18177 | c_parser_omp_taskloop (location_t loc, c_parser *parser, | |
dda1bf61 JJ |
18178 | char *p_name, omp_clause_mask mask, tree *cclauses, |
18179 | bool *if_p) | |
d9a6bd32 JJ |
18180 | { |
18181 | tree clauses, block, ret; | |
18182 | ||
18183 | strcat (p_name, " taskloop"); | |
18184 | mask |= OMP_TASKLOOP_CLAUSE_MASK; | |
18185 | ||
18186 | if (c_parser_next_token_is (parser, CPP_NAME)) | |
18187 | { | |
18188 | const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); | |
18189 | ||
18190 | if (strcmp (p, "simd") == 0) | |
18191 | { | |
18192 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; | |
18193 | if (cclauses == NULL) | |
18194 | cclauses = cclauses_buf; | |
18195 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION); | |
18196 | c_parser_consume_token (parser); | |
18197 | if (!flag_openmp) /* flag_openmp_simd */ | |
dda1bf61 JJ |
18198 | return c_parser_omp_simd (loc, parser, p_name, mask, cclauses, |
18199 | if_p); | |
d9a6bd32 | 18200 | block = c_begin_compound_stmt (true); |
dda1bf61 | 18201 | ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p); |
d9a6bd32 JJ |
18202 | block = c_end_compound_stmt (loc, block, true); |
18203 | if (ret == NULL) | |
18204 | return ret; | |
18205 | ret = make_node (OMP_TASKLOOP); | |
18206 | TREE_TYPE (ret) = void_type_node; | |
18207 | OMP_FOR_BODY (ret) = block; | |
18208 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; | |
18209 | SET_EXPR_LOCATION (ret, loc); | |
18210 | add_stmt (ret); | |
18211 | return ret; | |
18212 | } | |
18213 | } | |
18214 | if (!flag_openmp) /* flag_openmp_simd */ | |
18215 | { | |
18216 | c_parser_skip_to_pragma_eol (parser, false); | |
18217 | return NULL_TREE; | |
18218 | } | |
18219 | ||
18220 | clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); | |
18221 | if (cclauses) | |
18222 | { | |
18223 | omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses); | |
18224 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; | |
18225 | } | |
18226 | ||
18227 | block = c_begin_compound_stmt (true); | |
dda1bf61 | 18228 | ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p); |
d9a6bd32 JJ |
18229 | block = c_end_compound_stmt (loc, block, true); |
18230 | add_stmt (block); | |
18231 | ||
18232 | return ret; | |
18233 | } | |
18234 | ||
953ff289 DN |
18235 | /* Main entry point to parsing most OpenMP pragmas. */ |
18236 | ||
18237 | static void | |
dda1bf61 | 18238 | c_parser_omp_construct (c_parser *parser, bool *if_p) |
953ff289 DN |
18239 | { |
18240 | enum pragma_kind p_kind; | |
18241 | location_t loc; | |
18242 | tree stmt; | |
acf0174b JJ |
18243 | char p_name[sizeof "#pragma omp teams distribute parallel for simd"]; |
18244 | omp_clause_mask mask (0); | |
953ff289 DN |
18245 | |
18246 | loc = c_parser_peek_token (parser)->location; | |
18247 | p_kind = c_parser_peek_token (parser)->pragma_kind; | |
18248 | c_parser_consume_pragma (parser); | |
18249 | ||
18250 | switch (p_kind) | |
18251 | { | |
4bf9e5a8 TS |
18252 | case PRAGMA_OACC_ATOMIC: |
18253 | c_parser_omp_atomic (loc, parser); | |
18254 | return; | |
41dbbb37 TS |
18255 | case PRAGMA_OACC_CACHE: |
18256 | strcpy (p_name, "#pragma acc"); | |
18257 | stmt = c_parser_oacc_cache (loc, parser); | |
18258 | break; | |
18259 | case PRAGMA_OACC_DATA: | |
dda1bf61 | 18260 | stmt = c_parser_oacc_data (loc, parser, if_p); |
41dbbb37 | 18261 | break; |
37d5ad46 | 18262 | case PRAGMA_OACC_HOST_DATA: |
dda1bf61 | 18263 | stmt = c_parser_oacc_host_data (loc, parser, if_p); |
37d5ad46 | 18264 | break; |
41dbbb37 | 18265 | case PRAGMA_OACC_KERNELS: |
88bae6f4 | 18266 | case PRAGMA_OACC_PARALLEL: |
41dbbb37 | 18267 | strcpy (p_name, "#pragma acc"); |
dda1bf61 JJ |
18268 | stmt = c_parser_oacc_kernels_parallel (loc, parser, p_kind, p_name, |
18269 | if_p); | |
41dbbb37 TS |
18270 | break; |
18271 | case PRAGMA_OACC_LOOP: | |
18272 | strcpy (p_name, "#pragma acc"); | |
dda1bf61 | 18273 | stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p); |
41dbbb37 TS |
18274 | break; |
18275 | case PRAGMA_OACC_WAIT: | |
18276 | strcpy (p_name, "#pragma wait"); | |
18277 | stmt = c_parser_oacc_wait (loc, parser, p_name); | |
18278 | break; | |
953ff289 | 18279 | case PRAGMA_OMP_ATOMIC: |
c2255bc4 | 18280 | c_parser_omp_atomic (loc, parser); |
953ff289 DN |
18281 | return; |
18282 | case PRAGMA_OMP_CRITICAL: | |
dda1bf61 | 18283 | stmt = c_parser_omp_critical (loc, parser, if_p); |
953ff289 | 18284 | break; |
acf0174b JJ |
18285 | case PRAGMA_OMP_DISTRIBUTE: |
18286 | strcpy (p_name, "#pragma omp"); | |
dda1bf61 | 18287 | stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p); |
acf0174b | 18288 | break; |
953ff289 | 18289 | case PRAGMA_OMP_FOR: |
acf0174b | 18290 | strcpy (p_name, "#pragma omp"); |
dda1bf61 | 18291 | stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p); |
953ff289 DN |
18292 | break; |
18293 | case PRAGMA_OMP_MASTER: | |
dda1bf61 | 18294 | stmt = c_parser_omp_master (loc, parser, if_p); |
953ff289 | 18295 | break; |
953ff289 | 18296 | case PRAGMA_OMP_PARALLEL: |
acf0174b | 18297 | strcpy (p_name, "#pragma omp"); |
dda1bf61 | 18298 | stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p); |
953ff289 DN |
18299 | break; |
18300 | case PRAGMA_OMP_SECTIONS: | |
acf0174b JJ |
18301 | strcpy (p_name, "#pragma omp"); |
18302 | stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL); | |
18303 | break; | |
18304 | case PRAGMA_OMP_SIMD: | |
18305 | strcpy (p_name, "#pragma omp"); | |
dda1bf61 | 18306 | stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p); |
953ff289 DN |
18307 | break; |
18308 | case PRAGMA_OMP_SINGLE: | |
dda1bf61 | 18309 | stmt = c_parser_omp_single (loc, parser, if_p); |
953ff289 | 18310 | break; |
a68ab351 | 18311 | case PRAGMA_OMP_TASK: |
dda1bf61 | 18312 | stmt = c_parser_omp_task (loc, parser, if_p); |
a68ab351 | 18313 | break; |
acf0174b | 18314 | case PRAGMA_OMP_TASKGROUP: |
dda1bf61 | 18315 | stmt = c_parser_omp_taskgroup (parser, if_p); |
acf0174b | 18316 | break; |
d9a6bd32 JJ |
18317 | case PRAGMA_OMP_TASKLOOP: |
18318 | strcpy (p_name, "#pragma omp"); | |
dda1bf61 | 18319 | stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p); |
d9a6bd32 | 18320 | break; |
acf0174b JJ |
18321 | case PRAGMA_OMP_TEAMS: |
18322 | strcpy (p_name, "#pragma omp"); | |
dda1bf61 | 18323 | stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p); |
acf0174b | 18324 | break; |
953ff289 DN |
18325 | default: |
18326 | gcc_unreachable (); | |
18327 | } | |
18328 | ||
18329 | if (stmt) | |
c2255bc4 | 18330 | gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION); |
953ff289 DN |
18331 | } |
18332 | ||
18333 | ||
18334 | /* OpenMP 2.5: | |
18335 | # pragma omp threadprivate (variable-list) */ | |
18336 | ||
18337 | static void | |
18338 | c_parser_omp_threadprivate (c_parser *parser) | |
18339 | { | |
18340 | tree vars, t; | |
c2255bc4 | 18341 | location_t loc; |
953ff289 DN |
18342 | |
18343 | c_parser_consume_pragma (parser); | |
c2255bc4 | 18344 | loc = c_parser_peek_token (parser)->location; |
d75d71e0 | 18345 | vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); |
953ff289 | 18346 | |
953ff289 DN |
18347 | /* Mark every variable in VARS to be assigned thread local storage. */ |
18348 | for (t = vars; t; t = TREE_CHAIN (t)) | |
18349 | { | |
18350 | tree v = TREE_PURPOSE (t); | |
18351 | ||
c2255bc4 AH |
18352 | /* FIXME diagnostics: Ideally we should keep individual |
18353 | locations for all the variables in the var list to make the | |
18354 | following errors more precise. Perhaps | |
18355 | c_parser_omp_var_list_parens() should construct a list of | |
18356 | locations to go along with the var list. */ | |
18357 | ||
953ff289 DN |
18358 | /* If V had already been marked threadprivate, it doesn't matter |
18359 | whether it had been used prior to this point. */ | |
0ae9bd27 | 18360 | if (!VAR_P (v)) |
c2255bc4 | 18361 | error_at (loc, "%qD is not a variable", v); |
5df27e4a | 18362 | else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v)) |
c2255bc4 | 18363 | error_at (loc, "%qE declared %<threadprivate%> after first use", v); |
62f9079a | 18364 | else if (! is_global_var (v)) |
c2255bc4 | 18365 | error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v); |
5df27e4a JJ |
18366 | else if (TREE_TYPE (v) == error_mark_node) |
18367 | ; | |
953ff289 | 18368 | else if (! COMPLETE_TYPE_P (TREE_TYPE (v))) |
c2255bc4 | 18369 | error_at (loc, "%<threadprivate%> %qE has incomplete type", v); |
953ff289 DN |
18370 | else |
18371 | { | |
18372 | if (! DECL_THREAD_LOCAL_P (v)) | |
18373 | { | |
56363ffd | 18374 | set_decl_tls_model (v, decl_default_tls_model (v)); |
953ff289 DN |
18375 | /* If rtl has been already set for this var, call |
18376 | make_decl_rtl once again, so that encode_section_info | |
18377 | has a chance to look at the new decl flags. */ | |
18378 | if (DECL_RTL_SET_P (v)) | |
18379 | make_decl_rtl (v); | |
18380 | } | |
18381 | C_DECL_THREADPRIVATE_P (v) = 1; | |
18382 | } | |
18383 | } | |
18384 | ||
18385 | c_parser_skip_to_pragma_eol (parser); | |
18386 | } | |
c02065fc AH |
18387 | \f |
18388 | /* Cilk Plus <#pragma simd> parsing routines. */ | |
18389 | ||
18390 | /* Helper function for c_parser_pragma. Perform some sanity checking | |
18391 | for <#pragma simd> constructs. Returns FALSE if there was a | |
18392 | problem. */ | |
18393 | ||
18394 | static bool | |
18395 | c_parser_cilk_verify_simd (c_parser *parser, | |
18396 | enum pragma_context context) | |
18397 | { | |
b72271b9 | 18398 | if (!flag_cilkplus) |
c02065fc AH |
18399 | { |
18400 | warning (0, "pragma simd ignored because -fcilkplus is not enabled"); | |
18401 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
18402 | return false; | |
18403 | } | |
18404 | if (context == pragma_external) | |
18405 | { | |
18406 | c_parser_error (parser,"pragma simd must be inside a function"); | |
18407 | c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); | |
18408 | return false; | |
18409 | } | |
18410 | return true; | |
18411 | } | |
18412 | ||
18413 | /* Cilk Plus: | |
41958c28 BI |
18414 | This function is shared by SIMD-enabled functions and #pragma simd. |
18415 | If IS_SIMD_FN is true then it is parsing a SIMD-enabled function and | |
18416 | CLAUSES is unused. The main purpose of this function is to parse a | |
18417 | vectorlength attribute or clause and check for parse errors. | |
18418 | When IS_SIMD_FN is true then the function is merely caching the tokens | |
18419 | in PARSER->CILK_SIMD_FN_TOKENS. If errors are found then the token | |
18420 | cache is cleared since there is no reason to continue. | |
18421 | Syntax: | |
18422 | vectorlength ( constant-expression ) */ | |
c02065fc AH |
18423 | |
18424 | static tree | |
41958c28 BI |
18425 | c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, |
18426 | bool is_simd_fn) | |
c02065fc | 18427 | { |
41958c28 BI |
18428 | if (is_simd_fn) |
18429 | check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength"); | |
18430 | else | |
c02065fc AH |
18431 | /* The vectorlength clause behaves exactly like OpenMP's safelen |
18432 | clause. Represent it in OpenMP terms. */ | |
41958c28 | 18433 | check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); |
c02065fc | 18434 | |
32129a17 DM |
18435 | matching_parens parens; |
18436 | if (!parens.require_open (parser)) | |
c02065fc AH |
18437 | return clauses; |
18438 | ||
18439 | location_t loc = c_parser_peek_token (parser)->location; | |
18440 | tree expr = c_parser_expr_no_commas (parser, NULL).value; | |
18441 | expr = c_fully_fold (expr, false, NULL); | |
18442 | ||
41958c28 BI |
18443 | /* If expr is an error_mark_node then the above function would have |
18444 | emitted an error. No reason to do it twice. */ | |
18445 | if (expr == error_mark_node) | |
18446 | ; | |
18447 | else if (!TREE_TYPE (expr) | |
18448 | || !TREE_CONSTANT (expr) | |
18449 | || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) | |
18450 | ||
18451 | error_at (loc, "vectorlength must be an integer constant"); | |
8e6cdc90 | 18452 | else if (wi::exact_log2 (wi::to_wide (expr)) == -1) |
c02065fc AH |
18453 | error_at (loc, "vectorlength must be a power of 2"); |
18454 | else | |
18455 | { | |
41958c28 BI |
18456 | if (is_simd_fn) |
18457 | { | |
18458 | tree u = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN); | |
18459 | OMP_CLAUSE_SIMDLEN_EXPR (u) = expr; | |
18460 | OMP_CLAUSE_CHAIN (u) = clauses; | |
18461 | clauses = u; | |
18462 | } | |
18463 | else | |
18464 | { | |
18465 | tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); | |
18466 | OMP_CLAUSE_SAFELEN_EXPR (u) = expr; | |
18467 | OMP_CLAUSE_CHAIN (u) = clauses; | |
18468 | clauses = u; | |
18469 | } | |
c02065fc AH |
18470 | } |
18471 | ||
32129a17 | 18472 | parens.require_close (parser); |
c02065fc AH |
18473 | |
18474 | return clauses; | |
18475 | } | |
18476 | ||
18477 | /* Cilk Plus: | |
18478 | linear ( simd-linear-variable-list ) | |
18479 | ||
18480 | simd-linear-variable-list: | |
18481 | simd-linear-variable | |
18482 | simd-linear-variable-list , simd-linear-variable | |
18483 | ||
18484 | simd-linear-variable: | |
18485 | id-expression | |
18486 | id-expression : simd-linear-step | |
18487 | ||
18488 | simd-linear-step: | |
18489 | conditional-expression */ | |
18490 | ||
18491 | static tree | |
18492 | c_parser_cilk_clause_linear (c_parser *parser, tree clauses) | |
18493 | { | |
32129a17 DM |
18494 | matching_parens parens; |
18495 | if (!parens.require_open (parser)) | |
c02065fc AH |
18496 | return clauses; |
18497 | ||
18498 | location_t loc = c_parser_peek_token (parser)->location; | |
18499 | ||
18500 | if (c_parser_next_token_is_not (parser, CPP_NAME) | |
18501 | || c_parser_peek_token (parser)->id_kind != C_ID_ID) | |
18502 | c_parser_error (parser, "expected identifier"); | |
18503 | ||
18504 | while (c_parser_next_token_is (parser, CPP_NAME) | |
18505 | && c_parser_peek_token (parser)->id_kind == C_ID_ID) | |
18506 | { | |
18507 | tree var = lookup_name (c_parser_peek_token (parser)->value); | |
18508 | ||
18509 | if (var == NULL) | |
18510 | { | |
18511 | undeclared_variable (c_parser_peek_token (parser)->location, | |
18512 | c_parser_peek_token (parser)->value); | |
18513 | c_parser_consume_token (parser); | |
18514 | } | |
18515 | else if (var == error_mark_node) | |
18516 | c_parser_consume_token (parser); | |
18517 | else | |
18518 | { | |
18519 | tree step = integer_one_node; | |
18520 | ||
18521 | /* Parse the linear step if present. */ | |
18522 | if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |
18523 | { | |
18524 | c_parser_consume_token (parser); | |
18525 | c_parser_consume_token (parser); | |
18526 | ||
18527 | tree expr = c_parser_expr_no_commas (parser, NULL).value; | |
18528 | expr = c_fully_fold (expr, false, NULL); | |
18529 | ||
18530 | if (TREE_TYPE (expr) | |
18531 | && INTEGRAL_TYPE_P (TREE_TYPE (expr)) | |
18532 | && (TREE_CONSTANT (expr) | |
18533 | || DECL_P (expr))) | |
18534 | step = expr; | |
18535 | else | |
18536 | c_parser_error (parser, | |
18537 | "step size must be an integer constant " | |
18538 | "expression or an integer variable"); | |
18539 | } | |
18540 | else | |
18541 | c_parser_consume_token (parser); | |
18542 | ||
18543 | /* Use OMP_CLAUSE_LINEAR, which has the same semantics. */ | |
18544 | tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR); | |
18545 | OMP_CLAUSE_DECL (u) = var; | |
18546 | OMP_CLAUSE_LINEAR_STEP (u) = step; | |
18547 | OMP_CLAUSE_CHAIN (u) = clauses; | |
18548 | clauses = u; | |
18549 | } | |
18550 | ||
18551 | if (c_parser_next_token_is_not (parser, CPP_COMMA)) | |
18552 | break; | |
18553 | ||
18554 | c_parser_consume_token (parser); | |
18555 | } | |
18556 | ||
32129a17 | 18557 | parens.skip_until_found_close (parser); |
c02065fc AH |
18558 | |
18559 | return clauses; | |
18560 | } | |
18561 | ||
18562 | /* Returns the name of the next clause. If the clause is not | |
18563 | recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is | |
18564 | not consumed. Otherwise, the appropriate pragma_simd_clause is | |
18565 | returned and the token is consumed. */ | |
18566 | ||
41958c28 | 18567 | static pragma_omp_clause |
c02065fc AH |
18568 | c_parser_cilk_clause_name (c_parser *parser) |
18569 | { | |
41958c28 | 18570 | pragma_omp_clause result; |
c02065fc AH |
18571 | c_token *token = c_parser_peek_token (parser); |
18572 | ||
18573 | if (!token->value || token->type != CPP_NAME) | |
18574 | return PRAGMA_CILK_CLAUSE_NONE; | |
18575 | ||
18576 | const char *p = IDENTIFIER_POINTER (token->value); | |
18577 | ||
18578 | if (!strcmp (p, "vectorlength")) | |
18579 | result = PRAGMA_CILK_CLAUSE_VECTORLENGTH; | |
18580 | else if (!strcmp (p, "linear")) | |
18581 | result = PRAGMA_CILK_CLAUSE_LINEAR; | |
18582 | else if (!strcmp (p, "private")) | |
18583 | result = PRAGMA_CILK_CLAUSE_PRIVATE; | |
18584 | else if (!strcmp (p, "firstprivate")) | |
18585 | result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE; | |
18586 | else if (!strcmp (p, "lastprivate")) | |
18587 | result = PRAGMA_CILK_CLAUSE_LASTPRIVATE; | |
18588 | else if (!strcmp (p, "reduction")) | |
18589 | result = PRAGMA_CILK_CLAUSE_REDUCTION; | |
18590 | else | |
18591 | return PRAGMA_CILK_CLAUSE_NONE; | |
18592 | ||
18593 | c_parser_consume_token (parser); | |
18594 | return result; | |
18595 | } | |
18596 | ||
18597 | /* Parse all #<pragma simd> clauses. Return the list of clauses | |
18598 | found. */ | |
18599 | ||
18600 | static tree | |
18601 | c_parser_cilk_all_clauses (c_parser *parser) | |
18602 | { | |
18603 | tree clauses = NULL; | |
18604 | ||
18605 | while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) | |
18606 | { | |
41958c28 | 18607 | pragma_omp_clause c_kind; |
c02065fc AH |
18608 | |
18609 | c_kind = c_parser_cilk_clause_name (parser); | |
18610 | ||
18611 | switch (c_kind) | |
18612 | { | |
18613 | case PRAGMA_CILK_CLAUSE_VECTORLENGTH: | |
41958c28 | 18614 | clauses = c_parser_cilk_clause_vectorlength (parser, clauses, false); |
c02065fc AH |
18615 | break; |
18616 | case PRAGMA_CILK_CLAUSE_LINEAR: | |
18617 | clauses = c_parser_cilk_clause_linear (parser, clauses); | |
18618 | break; | |
18619 | case PRAGMA_CILK_CLAUSE_PRIVATE: | |
18620 | /* Use the OpenMP counterpart. */ | |
18621 | clauses = c_parser_omp_clause_private (parser, clauses); | |
18622 | break; | |
18623 | case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE: | |
18624 | /* Use the OpenMP counterpart. */ | |
18625 | clauses = c_parser_omp_clause_firstprivate (parser, clauses); | |
18626 | break; | |
18627 | case PRAGMA_CILK_CLAUSE_LASTPRIVATE: | |
18628 | /* Use the OpenMP counterpart. */ | |
18629 | clauses = c_parser_omp_clause_lastprivate (parser, clauses); | |
18630 | break; | |
18631 | case PRAGMA_CILK_CLAUSE_REDUCTION: | |
18632 | /* Use the OpenMP counterpart. */ | |
18633 | clauses = c_parser_omp_clause_reduction (parser, clauses); | |
18634 | break; | |
18635 | default: | |
18636 | c_parser_error (parser, "expected %<#pragma simd%> clause"); | |
18637 | goto saw_error; | |
18638 | } | |
18639 | } | |
18640 | ||
18641 | saw_error: | |
18642 | c_parser_skip_to_pragma_eol (parser); | |
77886428 | 18643 | return c_finish_omp_clauses (clauses, C_ORT_CILK); |
c02065fc AH |
18644 | } |
18645 | ||
9a771876 JJ |
18646 | /* This function helps parse the grainsize pragma for a _Cilk_for statement. |
18647 | Here is the correct syntax of this pragma: | |
18648 | #pragma cilk grainsize = <EXP> | |
18649 | */ | |
18650 | ||
18651 | static void | |
dda1bf61 | 18652 | c_parser_cilk_grainsize (c_parser *parser, bool *if_p) |
9a771876 JJ |
18653 | { |
18654 | extern tree convert_to_integer (tree, tree); | |
18655 | ||
18656 | /* consume the 'grainsize' keyword. */ | |
18657 | c_parser_consume_pragma (parser); | |
18658 | ||
18659 | if (c_parser_require (parser, CPP_EQ, "expected %<=%>") != 0) | |
18660 | { | |
18661 | struct c_expr g_expr = c_parser_binary_expression (parser, NULL, NULL); | |
18662 | if (g_expr.value == error_mark_node) | |
18663 | { | |
18664 | c_parser_skip_to_pragma_eol (parser); | |
18665 | return; | |
18666 | } | |
18667 | tree grain = convert_to_integer (long_integer_type_node, | |
18668 | c_fully_fold (g_expr.value, false, | |
18669 | NULL)); | |
18670 | c_parser_skip_to_pragma_eol (parser); | |
18671 | c_token *token = c_parser_peek_token (parser); | |
18672 | if (token && token->type == CPP_KEYWORD | |
18673 | && token->keyword == RID_CILK_FOR) | |
18674 | { | |
18675 | if (grain == NULL_TREE || grain == error_mark_node) | |
18676 | grain = integer_zero_node; | |
dda1bf61 | 18677 | c_parser_cilk_for (parser, grain, if_p); |
9a771876 JJ |
18678 | } |
18679 | else | |
18680 | warning (0, "%<#pragma cilk grainsize%> is not followed by " | |
18681 | "%<_Cilk_for%>"); | |
18682 | } | |
18683 | else | |
18684 | c_parser_skip_to_pragma_eol (parser); | |
18685 | } | |
18686 | ||
18687 | /* Main entry point for parsing Cilk Plus <#pragma simd> for loops. */ | |
953ff289 | 18688 | |
c02065fc | 18689 | static void |
dda1bf61 | 18690 | c_parser_cilk_simd (c_parser *parser, bool *if_p) |
c02065fc | 18691 | { |
c02065fc AH |
18692 | tree clauses = c_parser_cilk_all_clauses (parser); |
18693 | tree block = c_begin_compound_stmt (true); | |
18694 | location_t loc = c_parser_peek_token (parser)->location; | |
dda1bf61 | 18695 | c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL, if_p); |
c02065fc AH |
18696 | block = c_end_compound_stmt (loc, block, true); |
18697 | add_stmt (block); | |
18698 | } | |
9a771876 JJ |
18699 | |
18700 | /* Create an artificial decl with TYPE and emit initialization of it with | |
18701 | INIT. */ | |
18702 | ||
18703 | static tree | |
18704 | c_get_temp_regvar (tree type, tree init) | |
18705 | { | |
18706 | location_t loc = EXPR_LOCATION (init); | |
18707 | tree decl = build_decl (loc, VAR_DECL, NULL_TREE, type); | |
18708 | DECL_ARTIFICIAL (decl) = 1; | |
18709 | DECL_IGNORED_P (decl) = 1; | |
18710 | pushdecl (decl); | |
18711 | tree t = build2 (INIT_EXPR, type, decl, init); | |
18712 | add_stmt (t); | |
18713 | return decl; | |
18714 | } | |
18715 | ||
18716 | /* Main entry point for parsing Cilk Plus _Cilk_for loops. | |
18717 | GRAIN is the grain value passed in through pragma or 0. */ | |
18718 | ||
18719 | static void | |
dda1bf61 | 18720 | c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p) |
9a771876 JJ |
18721 | { |
18722 | tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE); | |
18723 | OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR; | |
18724 | OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain; | |
77886428 | 18725 | clauses = c_finish_omp_clauses (clauses, C_ORT_CILK); |
9a771876 JJ |
18726 | |
18727 | tree block = c_begin_compound_stmt (true); | |
18728 | tree sb = push_stmt_list (); | |
18729 | location_t loc = c_parser_peek_token (parser)->location; | |
dda1bf61 JJ |
18730 | tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL, |
18731 | if_p); | |
9a771876 JJ |
18732 | sb = pop_stmt_list (sb); |
18733 | ||
18734 | if (omp_for) | |
18735 | { | |
18736 | tree omp_par = make_node (OMP_PARALLEL); | |
18737 | TREE_TYPE (omp_par) = void_type_node; | |
18738 | OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE; | |
18739 | tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); | |
18740 | TREE_SIDE_EFFECTS (bind) = 1; | |
18741 | BIND_EXPR_BODY (bind) = sb; | |
18742 | OMP_PARALLEL_BODY (omp_par) = bind; | |
18743 | if (OMP_FOR_PRE_BODY (omp_for)) | |
18744 | { | |
18745 | add_stmt (OMP_FOR_PRE_BODY (omp_for)); | |
18746 | OMP_FOR_PRE_BODY (omp_for) = NULL_TREE; | |
18747 | } | |
18748 | tree init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0); | |
18749 | tree decl = TREE_OPERAND (init, 0); | |
18750 | tree cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0); | |
18751 | tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); | |
18752 | tree t = TREE_OPERAND (cond, 1), c, clauses = NULL_TREE; | |
18753 | if (TREE_CODE (t) != INTEGER_CST) | |
18754 | { | |
18755 | TREE_OPERAND (cond, 1) = c_get_temp_regvar (TREE_TYPE (t), t); | |
18756 | c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); | |
18757 | OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1); | |
18758 | OMP_CLAUSE_CHAIN (c) = clauses; | |
18759 | clauses = c; | |
18760 | } | |
18761 | if (TREE_CODE (incr) == MODIFY_EXPR) | |
18762 | { | |
18763 | t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); | |
18764 | if (TREE_CODE (t) != INTEGER_CST) | |
18765 | { | |
18766 | TREE_OPERAND (TREE_OPERAND (incr, 1), 1) | |
18767 | = c_get_temp_regvar (TREE_TYPE (t), t); | |
18768 | c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); | |
18769 | OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); | |
18770 | OMP_CLAUSE_CHAIN (c) = clauses; | |
18771 | clauses = c; | |
18772 | } | |
18773 | } | |
18774 | t = TREE_OPERAND (init, 1); | |
18775 | if (TREE_CODE (t) != INTEGER_CST) | |
18776 | { | |
18777 | TREE_OPERAND (init, 1) = c_get_temp_regvar (TREE_TYPE (t), t); | |
18778 | c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); | |
18779 | OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1); | |
18780 | OMP_CLAUSE_CHAIN (c) = clauses; | |
18781 | clauses = c; | |
18782 | } | |
18783 | c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); | |
18784 | OMP_CLAUSE_DECL (c) = decl; | |
18785 | OMP_CLAUSE_CHAIN (c) = clauses; | |
18786 | clauses = c; | |
18787 | c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_); | |
18788 | OMP_CLAUSE_OPERAND (c, 0) | |
18789 | = cilk_for_number_of_iterations (omp_for); | |
18790 | OMP_CLAUSE_CHAIN (c) = clauses; | |
77886428 | 18791 | OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, C_ORT_CILK); |
9a771876 JJ |
18792 | add_stmt (omp_par); |
18793 | } | |
18794 | ||
18795 | block = c_end_compound_stmt (loc, block, true); | |
18796 | add_stmt (block); | |
18797 | } | |
18798 | ||
c02065fc | 18799 | \f |
0a35513e AH |
18800 | /* Parse a transaction attribute (GCC Extension). |
18801 | ||
18802 | transaction-attribute: | |
18803 | attributes | |
18804 | [ [ any-word ] ] | |
18805 | ||
18806 | The transactional memory language description is written for C++, | |
18807 | and uses the C++0x attribute syntax. For compatibility, allow the | |
18808 | bracket style for transactions in C as well. */ | |
18809 | ||
18810 | static tree | |
18811 | c_parser_transaction_attributes (c_parser *parser) | |
18812 | { | |
18813 | tree attr_name, attr = NULL; | |
18814 | ||
18815 | if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) | |
18816 | return c_parser_attributes (parser); | |
18817 | ||
18818 | if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) | |
18819 | return NULL_TREE; | |
18820 | c_parser_consume_token (parser); | |
18821 | if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) | |
18822 | goto error1; | |
18823 | ||
18824 | attr_name = c_parser_attribute_any_word (parser); | |
18825 | if (attr_name) | |
18826 | { | |
18827 | c_parser_consume_token (parser); | |
18828 | attr = build_tree_list (attr_name, NULL_TREE); | |
18829 | } | |
18830 | else | |
18831 | c_parser_error (parser, "expected identifier"); | |
18832 | ||
18833 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); | |
18834 | error1: | |
18835 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); | |
18836 | return attr; | |
18837 | } | |
18838 | ||
18839 | /* Parse a __transaction_atomic or __transaction_relaxed statement | |
18840 | (GCC Extension). | |
18841 | ||
18842 | transaction-statement: | |
18843 | __transaction_atomic transaction-attribute[opt] compound-statement | |
18844 | __transaction_relaxed compound-statement | |
18845 | ||
18846 | Note that the only valid attribute is: "outer". | |
18847 | */ | |
18848 | ||
18849 | static tree | |
18850 | c_parser_transaction (c_parser *parser, enum rid keyword) | |
18851 | { | |
18852 | unsigned int old_in = parser->in_transaction; | |
18853 | unsigned int this_in = 1, new_in; | |
18854 | location_t loc = c_parser_peek_token (parser)->location; | |
18855 | tree stmt, attrs; | |
18856 | ||
18857 | gcc_assert ((keyword == RID_TRANSACTION_ATOMIC | |
18858 | || keyword == RID_TRANSACTION_RELAXED) | |
18859 | && c_parser_next_token_is_keyword (parser, keyword)); | |
18860 | c_parser_consume_token (parser); | |
18861 | ||
18862 | if (keyword == RID_TRANSACTION_RELAXED) | |
18863 | this_in |= TM_STMT_ATTR_RELAXED; | |
18864 | else | |
18865 | { | |
18866 | attrs = c_parser_transaction_attributes (parser); | |
18867 | if (attrs) | |
18868 | this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); | |
18869 | } | |
18870 | ||
18871 | /* Keep track if we're in the lexical scope of an outer transaction. */ | |
18872 | new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); | |
18873 | ||
18874 | parser->in_transaction = new_in; | |
18875 | stmt = c_parser_compound_statement (parser); | |
18876 | parser->in_transaction = old_in; | |
18877 | ||
18878 | if (flag_tm) | |
18879 | stmt = c_finish_transaction (loc, stmt, this_in); | |
18880 | else | |
18881 | error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ? | |
18882 | "%<__transaction_atomic%> without transactional memory support enabled" | |
18883 | : "%<__transaction_relaxed %> " | |
18884 | "without transactional memory support enabled")); | |
18885 | ||
18886 | return stmt; | |
18887 | } | |
18888 | ||
18889 | /* Parse a __transaction_atomic or __transaction_relaxed expression | |
18890 | (GCC Extension). | |
18891 | ||
18892 | transaction-expression: | |
18893 | __transaction_atomic ( expression ) | |
18894 | __transaction_relaxed ( expression ) | |
18895 | */ | |
18896 | ||
18897 | static struct c_expr | |
18898 | c_parser_transaction_expression (c_parser *parser, enum rid keyword) | |
18899 | { | |
18900 | struct c_expr ret; | |
18901 | unsigned int old_in = parser->in_transaction; | |
18902 | unsigned int this_in = 1; | |
18903 | location_t loc = c_parser_peek_token (parser)->location; | |
18904 | tree attrs; | |
18905 | ||
18906 | gcc_assert ((keyword == RID_TRANSACTION_ATOMIC | |
18907 | || keyword == RID_TRANSACTION_RELAXED) | |
18908 | && c_parser_next_token_is_keyword (parser, keyword)); | |
18909 | c_parser_consume_token (parser); | |
18910 | ||
18911 | if (keyword == RID_TRANSACTION_RELAXED) | |
18912 | this_in |= TM_STMT_ATTR_RELAXED; | |
18913 | else | |
18914 | { | |
18915 | attrs = c_parser_transaction_attributes (parser); | |
18916 | if (attrs) | |
18917 | this_in |= parse_tm_stmt_attr (attrs, 0); | |
18918 | } | |
18919 | ||
18920 | parser->in_transaction = this_in; | |
32129a17 DM |
18921 | matching_parens parens; |
18922 | if (parens.require_open (parser)) | |
0a35513e AH |
18923 | { |
18924 | tree expr = c_parser_expression (parser).value; | |
18925 | ret.original_type = TREE_TYPE (expr); | |
18926 | ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr); | |
18927 | if (this_in & TM_STMT_ATTR_RELAXED) | |
18928 | TRANSACTION_EXPR_RELAXED (ret.value) = 1; | |
18929 | SET_EXPR_LOCATION (ret.value, loc); | |
18930 | ret.original_code = TRANSACTION_EXPR; | |
32129a17 | 18931 | if (!parens.require_close (parser)) |
69b76518 TR |
18932 | { |
18933 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); | |
18934 | goto error; | |
18935 | } | |
0a35513e AH |
18936 | } |
18937 | else | |
18938 | { | |
69b76518 | 18939 | error: |
0a35513e AH |
18940 | ret.value = error_mark_node; |
18941 | ret.original_code = ERROR_MARK; | |
18942 | ret.original_type = NULL; | |
18943 | } | |
18944 | parser->in_transaction = old_in; | |
18945 | ||
18946 | if (!flag_tm) | |
18947 | error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ? | |
18948 | "%<__transaction_atomic%> without transactional memory support enabled" | |
18949 | : "%<__transaction_relaxed %> " | |
18950 | "without transactional memory support enabled")); | |
18951 | ||
bef08b71 DM |
18952 | set_c_expr_source_range (&ret, loc, loc); |
18953 | ||
0a35513e AH |
18954 | return ret; |
18955 | } | |
18956 | ||
18957 | /* Parse a __transaction_cancel statement (GCC Extension). | |
18958 | ||
18959 | transaction-cancel-statement: | |
18960 | __transaction_cancel transaction-attribute[opt] ; | |
18961 | ||
18962 | Note that the only valid attribute is "outer". | |
18963 | */ | |
18964 | ||
18965 | static tree | |
acf0174b | 18966 | c_parser_transaction_cancel (c_parser *parser) |
0a35513e AH |
18967 | { |
18968 | location_t loc = c_parser_peek_token (parser)->location; | |
18969 | tree attrs; | |
18970 | bool is_outer = false; | |
18971 | ||
18972 | gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL)); | |
18973 | c_parser_consume_token (parser); | |
18974 | ||
18975 | attrs = c_parser_transaction_attributes (parser); | |
18976 | if (attrs) | |
18977 | is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0); | |
18978 | ||
18979 | if (!flag_tm) | |
18980 | { | |
18981 | error_at (loc, "%<__transaction_cancel%> without " | |
18982 | "transactional memory support enabled"); | |
18983 | goto ret_error; | |
18984 | } | |
18985 | else if (parser->in_transaction & TM_STMT_ATTR_RELAXED) | |
18986 | { | |
18987 | error_at (loc, "%<__transaction_cancel%> within a " | |
18988 | "%<__transaction_relaxed%>"); | |
18989 | goto ret_error; | |
18990 | } | |
18991 | else if (is_outer) | |
18992 | { | |
18993 | if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0 | |
18994 | && !is_tm_may_cancel_outer (current_function_decl)) | |
18995 | { | |
18996 | error_at (loc, "outer %<__transaction_cancel%> not " | |
18997 | "within outer %<__transaction_atomic%>"); | |
18998 | error_at (loc, " or a %<transaction_may_cancel_outer%> function"); | |
18999 | goto ret_error; | |
19000 | } | |
19001 | } | |
19002 | else if (parser->in_transaction == 0) | |
19003 | { | |
19004 | error_at (loc, "%<__transaction_cancel%> not within " | |
19005 | "%<__transaction_atomic%>"); | |
19006 | goto ret_error; | |
19007 | } | |
19008 | ||
19009 | return add_stmt (build_tm_abort_call (loc, is_outer)); | |
19010 | ||
19011 | ret_error: | |
19012 | return build1 (NOP_EXPR, void_type_node, error_mark_node); | |
19013 | } | |
bc4071dd | 19014 | \f |
27bf414c JM |
19015 | /* Parse a single source file. */ |
19016 | ||
19017 | void | |
19018 | c_parse_file (void) | |
19019 | { | |
bc4071dd RH |
19020 | /* Use local storage to begin. If the first token is a pragma, parse it. |
19021 | If it is #pragma GCC pch_preprocess, then this will load a PCH file | |
19022 | which will cause garbage collection. */ | |
19023 | c_parser tparser; | |
19024 | ||
19025 | memset (&tparser, 0, sizeof tparser); | |
acf0174b | 19026 | tparser.tokens = &tparser.tokens_buf[0]; |
bc4071dd RH |
19027 | the_parser = &tparser; |
19028 | ||
19029 | if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS) | |
19030 | c_parser_pragma_pch_preprocess (&tparser); | |
19031 | ||
766090c2 | 19032 | the_parser = ggc_alloc<c_parser> (); |
bc4071dd | 19033 | *the_parser = tparser; |
acf0174b JJ |
19034 | if (tparser.tokens == &tparser.tokens_buf[0]) |
19035 | the_parser->tokens = &the_parser->tokens_buf[0]; | |
bc4071dd | 19036 | |
f9417da1 RG |
19037 | /* Initialize EH, if we've been told to do so. */ |
19038 | if (flag_exceptions) | |
1d65f45c | 19039 | using_eh_for_cleanups (); |
f9417da1 | 19040 | |
27bf414c JM |
19041 | c_parser_translation_unit (the_parser); |
19042 | the_parser = NULL; | |
19043 | } | |
19044 | ||
36536d79 BI |
19045 | /* This function parses Cilk Plus array notation. The starting index is |
19046 | passed in INITIAL_INDEX and the array name is passes in ARRAY_VALUE. The | |
19047 | return value of this function is a tree_node called VALUE_TREE of type | |
19048 | ARRAY_NOTATION_REF. */ | |
19049 | ||
19050 | static tree | |
19051 | c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, | |
19052 | tree array_value) | |
19053 | { | |
19054 | c_token *token = NULL; | |
19055 | tree start_index = NULL_TREE, end_index = NULL_TREE, stride = NULL_TREE; | |
19056 | tree value_tree = NULL_TREE, type = NULL_TREE, array_type = NULL_TREE; | |
19057 | tree array_type_domain = NULL_TREE; | |
19058 | ||
5e88a8f4 | 19059 | if (array_value == error_mark_node || initial_index == error_mark_node) |
36536d79 BI |
19060 | { |
19061 | /* No need to continue. If either of these 2 were true, then an error | |
19062 | must be emitted already. Thus, no need to emit them twice. */ | |
19063 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19064 | return error_mark_node; | |
19065 | } | |
19066 | ||
19067 | array_type = TREE_TYPE (array_value); | |
19068 | gcc_assert (array_type); | |
671a475e IZ |
19069 | if (TREE_CODE (array_type) != ARRAY_TYPE |
19070 | && TREE_CODE (array_type) != POINTER_TYPE) | |
19071 | { | |
19072 | error_at (loc, "base of array section must be pointer or array type"); | |
19073 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19074 | return error_mark_node; | |
19075 | } | |
36536d79 BI |
19076 | type = TREE_TYPE (array_type); |
19077 | token = c_parser_peek_token (parser); | |
19078 | ||
19079 | if (token->type == CPP_EOF) | |
19080 | { | |
19081 | c_parser_error (parser, "expected %<:%> or numeral"); | |
19082 | return value_tree; | |
19083 | } | |
19084 | else if (token->type == CPP_COLON) | |
19085 | { | |
19086 | if (!initial_index) | |
19087 | { | |
19088 | /* If we are here, then we have a case like this A[:]. */ | |
19089 | c_parser_consume_token (parser); | |
19090 | if (TREE_CODE (array_type) == POINTER_TYPE) | |
19091 | { | |
19092 | error_at (loc, "start-index and length fields necessary for " | |
19093 | "using array notations in pointers"); | |
19094 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19095 | return error_mark_node; | |
19096 | } | |
19097 | if (TREE_CODE (array_type) == FUNCTION_TYPE) | |
19098 | { | |
19099 | error_at (loc, "array notations cannot be used with function " | |
19100 | "type"); | |
19101 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19102 | return error_mark_node; | |
19103 | } | |
36536d79 BI |
19104 | array_type_domain = TYPE_DOMAIN (array_type); |
19105 | ||
19106 | if (!array_type_domain) | |
19107 | { | |
19108 | error_at (loc, "start-index and length fields necessary for " | |
19109 | "using array notations in dimensionless arrays"); | |
19110 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19111 | return error_mark_node; | |
19112 | } | |
19113 | ||
ff22eb12 | 19114 | start_index = TYPE_MIN_VALUE (array_type_domain); |
36536d79 BI |
19115 | start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, |
19116 | start_index); | |
ff22eb12 NS |
19117 | if (!TYPE_MAX_VALUE (array_type_domain) |
19118 | || !TREE_CONSTANT (TYPE_MAX_VALUE (array_type_domain))) | |
36536d79 BI |
19119 | { |
19120 | error_at (loc, "start-index and length fields necessary for " | |
19121 | "using array notations in variable-length arrays"); | |
19122 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19123 | return error_mark_node; | |
19124 | } | |
ff22eb12 | 19125 | end_index = TYPE_MAX_VALUE (array_type_domain); |
36536d79 BI |
19126 | end_index = fold_build2 (PLUS_EXPR, TREE_TYPE (end_index), |
19127 | end_index, integer_one_node); | |
19128 | end_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, end_index); | |
19129 | stride = build_int_cst (integer_type_node, 1); | |
19130 | stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride); | |
19131 | } | |
19132 | else if (initial_index != error_mark_node) | |
19133 | { | |
19134 | /* If we are here, then there should be 2 possibilities: | |
19135 | 1. Array [EXPR : EXPR] | |
19136 | 2. Array [EXPR : EXPR : EXPR] | |
19137 | */ | |
19138 | start_index = initial_index; | |
19139 | ||
19140 | if (TREE_CODE (array_type) == FUNCTION_TYPE) | |
19141 | { | |
19142 | error_at (loc, "array notations cannot be used with function " | |
19143 | "type"); | |
19144 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); | |
19145 | return error_mark_node; | |
19146 | } | |
36536d79 | 19147 | c_parser_consume_token (parser); /* consume the ':' */ |
267bac10 JM |
19148 | struct c_expr ce = c_parser_expression (parser); |
19149 | ce = convert_lvalue_to_rvalue (loc, ce, false, false); | |
19150 | end_index = ce.value; | |
36536d79 BI |
19151 | if (!end_index || end_index == error_mark_node) |
19152 | { | |
19153 | c_parser_skip_to_end_of_block_or_statement (parser); | |
19154 | return error_mark_node; | |
19155 | } | |
19156 | if (c_parser_peek_token (parser)->type == CPP_COLON) | |
19157 | { | |
19158 | c_parser_consume_token (parser); | |
267bac10 JM |
19159 | ce = c_parser_expression (parser); |
19160 | ce = convert_lvalue_to_rvalue (loc, ce, false, false); | |
19161 | stride = ce.value; | |
36536d79 BI |
19162 | if (!stride || stride == error_mark_node) |
19163 | { | |
19164 | c_parser_skip_to_end_of_block_or_statement (parser); | |
19165 | return error_mark_node; | |
19166 | } | |
19167 | } | |
19168 | } | |
19169 | else | |
19170 | c_parser_error (parser, "expected array notation expression"); | |
19171 | } | |
19172 | else | |
19173 | c_parser_error (parser, "expected array notation expression"); | |
19174 | ||
19175 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); | |
19176 | ||
19177 | value_tree = build_array_notation_ref (loc, array_value, start_index, | |
19178 | end_index, stride, type); | |
19179 | if (value_tree != error_mark_node) | |
19180 | SET_EXPR_LOCATION (value_tree, loc); | |
19181 | return value_tree; | |
19182 | } | |
19183 | ||
c2e84327 DM |
19184 | /* Parse the body of a function declaration marked with "__RTL". |
19185 | ||
19186 | The RTL parser works on the level of characters read from a | |
19187 | FILE *, whereas c_parser works at the level of tokens. | |
19188 | Square this circle by consuming all of the tokens up to and | |
19189 | including the closing brace, recording the start/end of the RTL | |
19190 | fragment, and reopening the file and re-reading the relevant | |
19191 | lines within the RTL parser. | |
19192 | ||
19193 | This requires the opening and closing braces of the C function | |
19194 | to be on separate lines from the RTL they wrap. | |
19195 | ||
19196 | Take ownership of START_WITH_PASS, if non-NULL. */ | |
19197 | ||
19198 | void | |
19199 | c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass) | |
19200 | { | |
19201 | if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) | |
19202 | { | |
19203 | free (start_with_pass); | |
19204 | return; | |
19205 | } | |
19206 | ||
19207 | location_t start_loc = c_parser_peek_token (parser)->location; | |
19208 | ||
19209 | /* Consume all tokens, up to the closing brace, handling | |
19210 | matching pairs of braces in the rtl dump. */ | |
19211 | int num_open_braces = 1; | |
19212 | while (1) | |
19213 | { | |
19214 | switch (c_parser_peek_token (parser)->type) | |
19215 | { | |
19216 | case CPP_OPEN_BRACE: | |
19217 | num_open_braces++; | |
19218 | break; | |
19219 | case CPP_CLOSE_BRACE: | |
19220 | if (--num_open_braces == 0) | |
19221 | goto found_closing_brace; | |
19222 | break; | |
19223 | case CPP_EOF: | |
19224 | error_at (start_loc, "no closing brace"); | |
19225 | free (start_with_pass); | |
19226 | return; | |
19227 | default: | |
19228 | break; | |
19229 | } | |
19230 | c_parser_consume_token (parser); | |
19231 | } | |
19232 | ||
19233 | found_closing_brace: | |
19234 | /* At the closing brace; record its location. */ | |
19235 | location_t end_loc = c_parser_peek_token (parser)->location; | |
19236 | ||
19237 | /* Consume the closing brace. */ | |
19238 | c_parser_consume_token (parser); | |
19239 | ||
19240 | /* Invoke the RTL parser. */ | |
19241 | if (!read_rtl_function_body_from_file_range (start_loc, end_loc)) | |
19242 | { | |
19243 | free (start_with_pass); | |
19244 | return; | |
19245 | } | |
19246 | ||
19247 | /* If a pass name was provided for START_WITH_PASS, run the backend | |
19248 | accordingly now, on the cfun created above, transferring | |
19249 | ownership of START_WITH_PASS. */ | |
19250 | if (start_with_pass) | |
19251 | run_rtl_passes (start_with_pass); | |
19252 | } | |
19253 | ||
d4a10d0a | 19254 | #include "gt-c-c-parser.h" |