Mercurial > hg > CbC > CbC_gcc
diff gcc/c/c-parser.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 5d30d517ebed 84e7813d76e9 |
children | 4e440907fcbf |
line wrap: on
line diff
--- a/gcc/c/c-parser.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/c/c-parser.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* Parser for C and Objective-C. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. Parser actions based on the old Bison parser; structure somewhat influenced by and fragments based on the C++ parser. @@ -36,6 +36,7 @@ location rather than implicitly using input_location. */ #include "config.h" +#define INCLUDE_UNIQUE_PTR #include "system.h" #include "coretypes.h" #include "target.h" @@ -65,6 +66,8 @@ #include "read-rtl-function.h" #include "run-rtl-passes.h" #include "intl.h" +#include "c-family/name-hint.h" +#include "tree-iterator.h" #ifndef noCbC #include "cbc-tree.h" #endif @@ -204,12 +207,6 @@ keywords are valid. */ BOOL_BITFIELD objc_property_attr_context : 1; - /* Cilk Plus specific parser/lexer information. */ - - /* Buffer to hold all the tokens from parsing the vector attribute for the - SIMD-enabled functions (formerly known as elemental functions). */ - vec <c_token, va_gc> *cilk_simd_fn_tokens; - /* Location of the last consumed token. */ location_t last_token_location; }; @@ -510,6 +507,7 @@ case RID_ACCUM: case RID_SAT: case RID_AUTO_TYPE: + case RID_ALIGNAS: #ifndef noCbC case RID_CbC_CODE: #endif @@ -1338,6 +1336,9 @@ /* Similarly for warn_c99_c11_compat. */ | ((warn_c99_c11_compat == 1) << 9) | ((warn_c99_c11_compat == -1) << 10) + /* Similarly for warn_c11_c2x_compat. */ + | ((warn_c11_c2x_compat == 1) << 11) + | ((warn_c11_c2x_compat == -1) << 12) ); cpp_opts->cpp_pedantic = pedantic = 0; warn_pointer_arith = 0; @@ -1348,6 +1349,7 @@ warn_overlength_strings = 0; warn_c90_c99_compat = 0; warn_c99_c11_compat = 0; + warn_c11_c2x_compat = 0; return ret; } @@ -1367,6 +1369,7 @@ /* See above for why is this needed. */ warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0); warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0); + warn_c11_c2x_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0); } /* Helper data structure for parsing #pragma acc routine. */ @@ -1417,9 +1420,9 @@ location_t * = NULL); static void c_parser_if_statement (c_parser *, bool *, vec<tree> *); static void c_parser_switch_statement (c_parser *, bool *); -static void c_parser_while_statement (c_parser *, bool, bool *); -static void c_parser_do_statement (c_parser *, bool); -static void c_parser_for_statement (c_parser *, bool, bool *); +static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *); +static void c_parser_do_statement (c_parser *, bool, unsigned short); +static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -1500,14 +1503,6 @@ static bool c_parser_objc_diagnose_bad_element_prefix (c_parser *, struct c_declspecs *); -/* Cilk Plus supporting routines. */ -static void c_parser_cilk_simd (c_parser *, bool *); -static void c_parser_cilk_for (c_parser *, tree, bool *); -static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context); -static tree c_parser_array_notation (location_t, c_parser *, tree, tree); -static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); -static void c_parser_cilk_grainsize (c_parser *, bool *); - static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass); /* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9). @@ -1668,6 +1663,20 @@ static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>); static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); +/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ + +static void +add_debug_begin_stmt (location_t loc) +{ + /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */ + if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ()) + return; + + tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node); + SET_EXPR_LOCATION (stmt, loc); + add_stmt (stmt); +} + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -1768,6 +1777,8 @@ bool diagnosed_no_specs = false; location_t here = c_parser_peek_token (parser)->location; + add_debug_begin_stmt (c_parser_peek_token (parser)->location); + if (static_assert_ok && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) { @@ -1794,36 +1805,38 @@ { /* This is not C++ with its implicit typedef. */ richloc.add_fixit_insert_before ("struct "); - error_at_rich_loc (&richloc, - "unknown type name %qE;" - " use %<struct%> keyword to refer to the type", - name); + error_at (&richloc, + "unknown type name %qE;" + " use %<struct%> keyword to refer to the type", + name); } else if (tag_exists_p (UNION_TYPE, name)) { richloc.add_fixit_insert_before ("union "); - error_at_rich_loc (&richloc, - "unknown type name %qE;" - " use %<union%> keyword to refer to the type", - name); + error_at (&richloc, + "unknown type name %qE;" + " use %<union%> keyword to refer to the type", + name); } else if (tag_exists_p (ENUMERAL_TYPE, name)) { richloc.add_fixit_insert_before ("enum "); - error_at_rich_loc (&richloc, - "unknown type name %qE;" - " use %<enum%> keyword to refer to the type", - name); - } - else - { - const char *hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME); + error_at (&richloc, + "unknown type name %qE;" + " use %<enum%> keyword to refer to the type", + name); + } + else + { + auto_diagnostic_group d; + name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME, + here); if (hint) { - richloc.add_fixit_replace (hint); - error_at_rich_loc (&richloc, - "unknown type name %qE; did you mean %qs?", - name, hint); + richloc.add_fixit_replace (hint.suggestion ()); + error_at (&richloc, + "unknown type name %qE; did you mean %qs?", + name, hint.suggestion ()); } else error_at (here, "unknown type name %qE", name); @@ -1992,8 +2005,7 @@ C_DTR_NORMAL, &dummy); if (declarator == NULL) { - if (omp_declare_simd_clauses.exists () - || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + if (omp_declare_simd_clauses.exists ()) c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, omp_declare_simd_clauses); if (oacc_routine_data) @@ -2097,8 +2109,7 @@ chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists () - || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + if (omp_declare_simd_clauses.exists ()) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); } @@ -2110,8 +2121,7 @@ chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists () - || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + if (omp_declare_simd_clauses.exists ()) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); init_loc = c_parser_peek_token (parser)->location; @@ -2152,8 +2162,7 @@ if (declarator->kind == cdk_function) if (DECL_ARGUMENTS (d) == NULL_TREE) DECL_ARGUMENTS (d) = declarator->u.arg_info->parms; - if (omp_declare_simd_clauses.exists () - || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + if (omp_declare_simd_clauses.exists ()) { tree parms = NULL_TREE; if (d && TREE_CODE (d) == FUNCTION_DECL) @@ -2309,8 +2318,7 @@ c_parser_declaration_or_fndef (parser, false, false, false, true, false, NULL, vNULL); store_parm_decls (); - if (omp_declare_simd_clauses.exists () - || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + if (omp_declare_simd_clauses.exists ()) c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, omp_declare_simd_clauses); if (oacc_routine_data) @@ -2345,11 +2353,7 @@ return; } else - { - fnbody = c_parser_compound_statement (parser); - if (flag_cilkplus && contains_array_notation_expr (fnbody)) - fnbody = expand_array_notation_exprs (fnbody); - } + fnbody = c_parser_compound_statement (parser); tree fndecl = current_function_decl; if (nested) { @@ -2414,6 +2418,10 @@ static_assert-declaration-no-semi: _Static_assert ( constant-expression , string-literal ) + + C2X: + static_assert-declaration-no-semi: + _Static_assert ( constant-expression ) */ static void @@ -2421,7 +2429,7 @@ { location_t assert_loc, value_loc; tree value; - tree string; + tree string = NULL_TREE; gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)); assert_loc = c_parser_peek_token (parser)->location; @@ -2439,27 +2447,33 @@ value = c_parser_expr_no_commas (parser, NULL).value; value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc); parser->lex_untranslated_string = true; - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - parser->lex_untranslated_string = false; - return; - } - switch (c_parser_peek_token (parser)->type) - { - case CPP_STRING: - case CPP_STRING16: - case CPP_STRING32: - case CPP_WSTRING: - case CPP_UTF8STRING: - string = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - parser->lex_untranslated_string = false; - break; - default: - c_parser_error (parser, "expected string literal"); - parser->lex_untranslated_string = false; - return; - } + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + switch (c_parser_peek_token (parser)->type) + { + case CPP_STRING: + case CPP_STRING16: + case CPP_STRING32: + case CPP_WSTRING: + case CPP_UTF8STRING: + string = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + parser->lex_untranslated_string = false; + break; + default: + c_parser_error (parser, "expected string literal"); + parser->lex_untranslated_string = false; + return; + } + } + else if (flag_isoc11) + /* If pedantic for pre-C11, the use of _Static_assert itself will + have been diagnosed, so do not also diagnose the use of this + new C2X feature of _Static_assert. */ + pedwarn_c11 (assert_loc, OPT_Wpedantic, + "ISO C11 does not support omitting the string in " + "%<_Static_assert%>"); parens.require_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (value))) @@ -2483,7 +2497,12 @@ } constant_expression_warning (value); if (integer_zerop (value)) - error_at (assert_loc, "static assertion failed: %E", string); + { + if (string) + error_at (assert_loc, "static assertion failed: %E", string); + else + error_at (assert_loc, "static assertion failed"); + } } /* Parse some declaration specifiers (possibly none) (C90 6.5, C99 @@ -2622,7 +2641,8 @@ has simply forgotten a semicolon, so we exit. */ if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef) && c_parser_next_tokens_start_typename (parser, la) - && !c_parser_next_token_is_qualifier (parser)) + && !c_parser_next_token_is_qualifier (parser) + && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS)) break; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -3198,9 +3218,8 @@ = c_parser_peek_token (parser)->location; gcc_rich_location richloc (semicolon_loc); richloc.add_fixit_remove (); - pedwarn_at_rich_loc - (&richloc, OPT_Wpedantic, - "extra semicolon in struct or union specified"); + pedwarn (&richloc, OPT_Wpedantic, + "extra semicolon in struct or union specified"); c_parser_consume_token (parser); continue; } @@ -3275,6 +3294,7 @@ specifier-qualifier-list: type-specifier specifier-qualifier-list[opt] type-qualifier specifier-qualifier-list[opt] + alignment-specifier specifier-qualifier-list[opt] attributes specifier-qualifier-list[opt] struct-declarator-list: @@ -3827,15 +3847,6 @@ dimen.value = NULL_TREE; star_seen = false; } - else if (flag_cilkplus - && c_parser_next_token_is (parser, CPP_COLON)) - { - dimen.value = error_mark_node; - star_seen = false; - error_at (c_parser_peek_token (parser)->location, - "array notations cannot be used in declaration"); - c_parser_consume_token (parser); - } else if (c_parser_next_token_is (parser, CPP_MULT)) { if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE) @@ -3858,14 +3869,6 @@ } if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) c_parser_consume_token (parser); - else if (flag_cilkplus - && c_parser_next_token_is (parser, CPP_COLON)) - { - error_at (c_parser_peek_token (parser)->location, - "array notations cannot be used in declaration"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return NULL; - } else { c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, @@ -4097,15 +4100,17 @@ c_parser_set_source_position_from_token (token); if (c_parser_next_tokens_start_typename (parser, cla_prefer_type)) { - const char *hint = lookup_name_fuzzy (token->value, - FUZZY_LOOKUP_TYPENAME); + auto_diagnostic_group d; + name_hint hint = lookup_name_fuzzy (token->value, + FUZZY_LOOKUP_TYPENAME, + token->location); if (hint) { gcc_rich_location richloc (token->location); - richloc.add_fixit_replace (hint); - error_at_rich_loc (&richloc, - "unknown type name %qE; did you mean %qs?", - token->value, hint); + richloc.add_fixit_replace (hint.suggestion ()); + error_at (&richloc, + "unknown type name %qE; did you mean %qs?", + token->value, hint.suggestion ()); } else error_at (token->location, "unknown type name %qE", token->value); @@ -4310,76 +4315,6 @@ return attr_name; } -#define CILK_SIMD_FN_CLAUSE_MASK \ - ((OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_VECTORLENGTH) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_LINEAR) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNIFORM) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_MASK) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_NOMASK)) - -/* Parses the vector attribute of SIMD enabled functions in Cilk Plus. - VEC_TOKEN is the "vector" token that is replaced with "simd" and - pushed into the token list. - Syntax: - vector - vector (<vector attributes>). */ - -static void -c_parser_cilk_simd_fn_vector_attrs (c_parser *parser, c_token vec_token) -{ - gcc_assert (is_cilkplus_vector_p (vec_token.value)); - - int paren_scope = 0; - vec_safe_push (parser->cilk_simd_fn_tokens, vec_token); - /* Consume the "vector" token. */ - c_parser_consume_token (parser); - - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - c_parser_consume_token (parser); - paren_scope++; - } - while (paren_scope > 0) - { - c_token *token = c_parser_peek_token (parser); - if (token->type == CPP_OPEN_PAREN) - paren_scope++; - else if (token->type == CPP_CLOSE_PAREN) - paren_scope--; - /* Do not push the last ')' since we are not pushing the '('. */ - if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0)) - vec_safe_push (parser->cilk_simd_fn_tokens, *token); - c_parser_consume_token (parser); - } - - /* Since we are converting an attribute to a pragma, we need to end the - attribute with PRAGMA_EOL. */ - c_token eol_token; - memset (&eol_token, 0, sizeof (eol_token)); - eol_token.type = CPP_PRAGMA_EOL; - vec_safe_push (parser->cilk_simd_fn_tokens, eol_token); -} - -/* Add 2 CPP_EOF at the end of PARSER->ELEM_FN_TOKENS vector. */ - -static void -c_finish_cilk_simd_fn_tokens (c_parser *parser) -{ - c_token last_token = parser->cilk_simd_fn_tokens->last (); - - /* c_parser_attributes is called in several places, so if these EOF - tokens are already inserted, then don't do them again. */ - if (last_token.type == CPP_EOF) - return; - - /* Two CPP_EOF token are added as a safety net since the normal C - front-end has two token look-ahead. */ - c_token eof_token; - eof_token.type = CPP_EOF; - vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); - vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); -} - /* Parse (possibly empty) attributes. This is a GNU extension. attributes: @@ -4447,16 +4382,6 @@ if (attr_name == NULL) break; attr_name = canonicalize_attr_name (attr_name); - if (is_cilkplus_vector_p (attr_name)) - { - c_token *v_token = c_parser_peek_token (parser); - v_token->value = canonicalize_attr_name (v_token->value); - c_parser_cilk_simd_fn_vector_attrs (parser, *v_token); - /* If the next token isn't a comma, we're done. */ - if (!c_parser_next_token_is (parser, CPP_COMMA)) - break; - continue; - } c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) { @@ -4553,25 +4478,25 @@ parser->lex_untranslated_string = false; } - if (flag_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) - c_finish_cilk_simd_fn_tokens (parser); return attrs; } -/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). +/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK + says whether alignment specifiers are OK (only in cases that might + be the type name of a compound literal). type-name: specifier-qualifier-list abstract-declarator[opt] */ struct c_type_name * -c_parser_type_name (c_parser *parser) +c_parser_type_name (c_parser *parser, bool alignas_ok) { struct c_declspecs *specs = build_null_declspecs (); struct c_declarator *declarator; struct c_type_name *ret; bool dummy = false; - c_parser_declspecs (parser, specs, false, true, true, false, false, + c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false, cla_prefer_type); if (!specs->declspecs_seen_p) { @@ -4710,7 +4635,7 @@ c_token *next_tok = c_parser_peek_token (parser); if (next_tok->type != CPP_CLOSE_BRACE) { - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; braces.skip_until_found_close (parser); @@ -4777,7 +4702,7 @@ else { struct c_expr init; - init.value = error_mark_node; + init.set_error (); init.original_code = ERROR_MARK; init.original_type = NULL; c_parser_error (parser, "expected identifier"); @@ -4913,7 +4838,7 @@ else { struct c_expr init; - init.value = error_mark_node; + init.set_error (); init.original_code = ERROR_MARK; init.original_type = NULL; c_parser_error (parser, "expected %<=%>"); @@ -5038,9 +4963,6 @@ stmt = c_begin_compound_stmt (true); c_parser_compound_statement_nostart (parser); - /* If the compound stmt contains array notations, then we expand them. */ - if (flag_cilkplus && contains_array_notation_expr (stmt)) - stmt = expand_array_notation_exprs (stmt); return c_end_compound_stmt (brace_loc, stmt, true); } @@ -5057,6 +4979,7 @@ location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { + add_debug_begin_stmt (c_parser_peek_token (parser)->location); c_parser_consume_token (parser); return; } @@ -5105,6 +5028,7 @@ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) { location_t loc = c_parser_peek_token (parser)->location; + loc = expansion_point_location_if_in_system_header (loc); if (c_parser_next_token_is_keyword (parser, RID_CASE) || c_parser_next_token_is_keyword (parser, RID_DEFAULT) || (c_parser_next_token_is (parser, CPP_NAME) @@ -5550,6 +5474,10 @@ parser->in_if_block = false; if (if_p != NULL) *if_p = false; + + if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE) + add_debug_begin_stmt (loc); + switch (c_parser_peek_token (parser)->type) { case CPP_OPEN_BRACE: @@ -5565,31 +5493,13 @@ c_parser_switch_statement (parser, if_p); break; case RID_WHILE: - c_parser_while_statement (parser, false, if_p); + c_parser_while_statement (parser, false, 0, if_p); break; case RID_DO: - c_parser_do_statement (parser, false); + c_parser_do_statement (parser, 0, false); break; case RID_FOR: - c_parser_for_statement (parser, false, if_p); - break; - case RID_CILK_FOR: - if (!flag_cilkplus) - { - error_at (c_parser_peek_token (parser)->location, - "-fcilkplus must be enabled to use %<_Cilk_for%>"); - c_parser_skip_to_end_of_block_or_statement (parser); - } - else - c_parser_cilk_for (parser, integer_zero_node, if_p); - break; - case RID_CILK_SYNC: - c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - if (!flag_cilkplus) - error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>"); - else - add_stmt (build_cilk_sync ()); + c_parser_for_statement (parser, false, 0, if_p); break; case RID_GOTO: c_parser_consume_token (parser); @@ -5611,11 +5521,6 @@ c_parser_consume_token (parser); val = c_parser_expression (parser); - if (check_no_cilk (val.value, - "Cilk array notation cannot be used as a computed goto expression", - "%<_Cilk_spawn%> statement cannot be used as a computed goto expression", - loc)) - val.value = error_mark_node; val = convert_lvalue_to_rvalue (loc, val, false, true); stmt = c_finish_goto_ptr (loc, val.value); } @@ -5703,15 +5608,8 @@ { struct c_expr expr = c_parser_expression (parser); expr = convert_lvalue_to_rvalue (loc, expr, false, false); - if (check_no_cilk (expr.value, - "Cilk array notation cannot be used for a throw expression", - "%<_Cilk_spawn%> statement cannot be used for a throw expression")) - expr.value = error_mark_node; - else - { - expr.value = c_fully_fold (expr.value, false, NULL); - stmt = objc_build_throw_stmt (loc, expr.value); - } + expr.value = c_fully_fold (expr.value, false, NULL); + stmt = objc_build_throw_stmt (loc, expr.value); goto expect_semicolon; } break; @@ -5989,7 +5887,6 @@ bool nested_if = false; tree first_body, second_body; bool in_if_block; - tree if_stmt; gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF)); token_indent_info if_tinfo @@ -5998,11 +5895,6 @@ block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; cond = c_parser_paren_condition (parser); - if (flag_cilkplus && contains_cilk_spawn_stmt (cond)) - { - error_at (loc, "if statement cannot contain %<Cilk_spawn%>"); - cond = error_mark_node; - } in_if_block = parser->in_if_block; parser->in_if_block = true; first_body = c_parser_if_body (parser, &nested_if, if_tinfo); @@ -6061,12 +5953,8 @@ } } c_finish_if_stmt (loc, cond, first_body, second_body); - if_stmt = c_end_compound_stmt (loc, block, flag_isoc99); - - /* If the if statement contains array notations, then we expand them. */ - if (flag_cilkplus && contains_array_notation_expr (if_stmt)) - if_stmt = fix_conditional_array_notations (if_stmt); - add_stmt (if_stmt); + add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); + c_parser_maybe_reclassify_token (parser); } @@ -6098,11 +5986,6 @@ ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false); expr = ce.value; /* ??? expr has no valid location? */ - if (check_no_cilk (expr, - "Cilk array notation cannot be used as a condition for switch statement", - "%<_Cilk_spawn%> statement cannot be used as a condition for switch statement", - switch_cond_loc)) - expr = error_mark_node; parens.skip_until_found_close (parser); } else @@ -6121,14 +6004,15 @@ if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON) warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc, RID_SWITCH); - c_finish_case (body, ce.original_type); if (c_break_label) { location_t here = c_parser_peek_token (parser)->location; tree t = build1 (LABEL_EXPR, void_type_node, c_break_label); SET_EXPR_LOCATION (t, here); - add_stmt (t); - } + SWITCH_BREAK_LABEL_P (c_break_label) = 1; + append_to_statement_list_force (t, &body); + } + c_finish_case (body, ce.original_type); c_break_label = save_break; add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); c_parser_maybe_reclassify_token (parser); @@ -6144,7 +6028,8 @@ implement -Wparentheses. */ static void -c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) +c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool *if_p) { tree block, cond, body, save_break, save_cont; location_t loc; @@ -6155,14 +6040,16 @@ block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; cond = c_parser_paren_condition (parser); - if (check_no_cilk (cond, - "Cilk array notation cannot be used as a condition for while statement", - "%<_Cilk_spawn%> statement cannot be used as a condition for while statement")) - cond = error_mark_node; if (ivdep && cond != error_mark_node) - cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, build_int_cst (integer_type_node, - annot_expr_ivdep_kind)); + annot_expr_ivdep_kind), + integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); save_break = c_break_label; c_break_label = NULL_TREE; save_cont = c_cont_label; @@ -6197,7 +6084,7 @@ */ static void -c_parser_do_statement (c_parser *parser, bool ivdep) +c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) { tree block, cond, body, save_break, save_cont, new_break, new_cont; location_t loc; @@ -6220,14 +6107,16 @@ new_cont = c_cont_label; c_cont_label = save_cont; cond = c_parser_paren_condition (parser); - if (check_no_cilk (cond, - "Cilk array notation cannot be used as a condition for a do-while statement", - "%<_Cilk_spawn%> statement cannot be used as a condition for a do-while statement")) - cond = error_mark_node; if (ivdep && cond != error_mark_node) - cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, build_int_cst (integer_type_node, - annot_expr_ivdep_kind)); + annot_expr_ivdep_kind), + integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); @@ -6294,7 +6183,8 @@ implement -Wparentheses. */ static void -c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) +c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool *if_p) { tree block, cond, incr, save_break, save_cont, body; /* The following are only used when parsing an ObjC foreach statement. */ @@ -6381,8 +6271,6 @@ struct c_expr ce; tree init_expression; ce = c_parser_expression (parser); - /* In theory we could forbid _Cilk_spawn here, as the spec says "only in top - level statement", but it works just fine, so allow it. */ init_expression = ce.value; parser->objc_could_be_foreach_context = false; if (c_parser_next_token_is_keyword (parser, RID_IN)) @@ -6415,6 +6303,12 @@ "%<GCC ivdep%> pragma"); cond = error_mark_node; } + else if (unroll) + { + c_parser_error (parser, "missing loop condition in loop with " + "%<GCC unroll%> pragma"); + cond = error_mark_node; + } else { c_parser_consume_token (parser); @@ -6424,17 +6318,19 @@ else { cond = c_parser_condition (parser); - if (check_no_cilk (cond, - "Cilk array notation cannot be used in a condition for a for-loop", - "%<_Cilk_spawn%> statement cannot be used in a condition for a for-loop")) - cond = error_mark_node; c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } if (ivdep && cond != error_mark_node) - cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, build_int_cst (integer_type_node, - annot_expr_ivdep_kind)); + annot_expr_ivdep_kind), + integer_zero_node); + if (unroll && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, unroll)); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -6929,7 +6825,7 @@ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) { c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; return ret; @@ -7098,14 +6994,18 @@ && !(TREE_CODE (first_arg) == PARM_DECL \ && C_ARRAY_PARAMETER (first_arg) \ && warn_sizeof_array_argument)) \ - if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \ - "division %<sizeof (%T) / sizeof (%T)%> does " \ - "not compute the number of array elements", \ - type0, type1)) \ - if (DECL_P (first_arg)) \ - inform (DECL_SOURCE_LOCATION (first_arg), \ - "first %<sizeof%> operand was declared here"); \ - } \ + { \ + auto_diagnostic_group d; \ + if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \ + "division %<sizeof (%T) / sizeof (%T)%> " \ + "does not compute the number of array " \ + "elements", \ + type0, type1)) \ + if (DECL_P (first_arg)) \ + inform (DECL_SOURCE_LOCATION (first_arg), \ + "first %<sizeof%> operand was declared here"); \ + } \ + } \ break; \ default: \ break; \ @@ -7303,11 +7203,11 @@ struct c_expr expr; matching_parens parens; parens.consume_open (parser); - type_name = c_parser_type_name (parser); + type_name = c_parser_type_name (parser, true); parens.skip_until_found_close (parser); if (type_name == NULL) { - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; return ret; @@ -7319,6 +7219,9 @@ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) return c_parser_postfix_expression_after_paren_type (parser, type_name, cast_loc); + if (type_name->specs->alignas_p) + error_at (type_name->specs->locations[cdw_alignas], + "alignment specified for type name in cast"); { location_t expr_loc = c_parser_peek_token (parser)->location; expr = c_parser_cast_expression (parser, NULL); @@ -7386,27 +7289,15 @@ exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - /* If there is array notations in op, we expand them. */ - if (flag_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF) - return fix_array_notation_expr (exp_loc, PREINCREMENT_EXPR, op); - else - { - op = default_function_array_read_conversion (exp_loc, op); - return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); - } + op = default_function_array_read_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); case CPP_MINUS_MINUS: c_parser_consume_token (parser); exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - /* If there is array notations in op, we expand them. */ - if (flag_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF) - return fix_array_notation_expr (exp_loc, PREDECREMENT_EXPR, op); - else - { - op = default_function_array_read_conversion (exp_loc, op); - return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); - } + op = default_function_array_read_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); case CPP_AND: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); @@ -7534,7 +7425,7 @@ matching_parens parens; parens.consume_open (parser); expr_loc = c_parser_peek_token (parser)->location; - type_name = c_parser_type_name (parser); + type_name = c_parser_type_name (parser, true); parens.skip_until_found_close (parser); finish = parser->tokens_buf[0].location; if (type_name == NULL) @@ -7542,7 +7433,7 @@ struct c_expr ret; c_inhibit_evaluation_warnings--; in_sizeof--; - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; return ret; @@ -7556,6 +7447,9 @@ goto sizeof_expr; } /* sizeof ( type-name ). */ + if (type_name->specs->alignas_p) + error_at (type_name->specs->locations[cdw_alignas], + "alignment specified for type name in %<sizeof%>"); c_inhibit_evaluation_warnings--; in_sizeof--; result = c_expr_sizeof_type (expr_loc, type_name); @@ -7617,7 +7511,7 @@ matching_parens parens; parens.consume_open (parser); loc = c_parser_peek_token (parser)->location; - type_name = c_parser_type_name (parser); + type_name = c_parser_type_name (parser, true); end_loc = c_parser_peek_token (parser)->location; parens.skip_until_found_close (parser); if (type_name == NULL) @@ -7625,7 +7519,7 @@ struct c_expr ret; c_inhibit_evaluation_warnings--; in_alignof--; - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; return ret; @@ -7638,6 +7532,10 @@ goto alignof_expr; } /* alignof ( type-name ). */ + if (type_name->specs->alignas_p) + error_at (type_name->specs->locations[cdw_alignas], + "alignment specified for type name in %qE", + alignof_spelling); c_inhibit_evaluation_warnings--; in_alignof--; ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name, @@ -7938,6 +7836,61 @@ return matched_assoc.expression; } +/* Check the validity of a function pointer argument *EXPR (argument + position POS) to __builtin_tgmath. Return the number of function + arguments if possibly valid; return 0 having reported an error if + not valid. */ + +static unsigned int +check_tgmath_function (c_expr *expr, unsigned int pos) +{ + tree type = TREE_TYPE (expr->value); + if (!FUNCTION_POINTER_TYPE_P (type)) + { + error_at (expr->get_location (), + "argument %u of %<__builtin_tgmath%> is not a function pointer", + pos); + return 0; + } + type = TREE_TYPE (type); + if (!prototype_p (type)) + { + error_at (expr->get_location (), + "argument %u of %<__builtin_tgmath%> is unprototyped", pos); + return 0; + } + if (stdarg_p (type)) + { + error_at (expr->get_location (), + "argument %u of %<__builtin_tgmath%> has variable arguments", + pos); + return 0; + } + unsigned int nargs = 0; + function_args_iterator iter; + tree t; + FOREACH_FUNCTION_ARGS (type, t, iter) + { + if (t == void_type_node) + break; + nargs++; + } + if (nargs == 0) + { + error_at (expr->get_location (), + "argument %u of %<__builtin_tgmath%> has no arguments", pos); + return 0; + } + return nargs; +} + +/* Ways in which a parameter or return value of a type-generic macro + may vary between the different functions the macro may call. */ +enum tgmath_parm_kind + { + tgmath_fixed, tgmath_real, tgmath_complex + }; + /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2, C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to call c_parser_postfix_expression_after_paren_type on encountering them. @@ -7978,6 +7931,7 @@ assignment-expression , assignment-expression ) __builtin_types_compatible_p ( type-name , type-name ) + __builtin_tgmath ( expr-list ) __builtin_complex ( assignment-expression , assignment-expression ) __builtin_shuffle ( assignment-expression , assignment-expression ) __builtin_shuffle ( assignment-expression , @@ -8137,7 +8091,7 @@ { struct c_expr expr, e1; struct c_type_name *t1, *t2; - location_t loc = c_parser_peek_token (parser)->location;; + location_t loc = c_parser_peek_token (parser)->location; source_range tok_range = c_parser_peek_token (parser)->get_range (); expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -8152,7 +8106,7 @@ && !targetm.fixed_point_supported_p ()) { error_at (loc, "fixed-point types not supported for this target"); - expr.value = error_mark_node; + expr.set_error (); } break; case CPP_CHAR: @@ -8242,7 +8196,10 @@ c_parser_consume_token (parser); brace_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); - if (!building_stmt_list_p ()) + /* If we've not yet started the current function's statement list, + or we're in the parameter scope of an old-style function + declaration, statement expressions are not allowed. */ + if (!building_stmt_list_p () || old_style_parameter_scope ()) { error_at (loc, "braced-group within expression allowed " "only inside a function"); @@ -8536,6 +8493,530 @@ set_c_expr_source_range (&expr, loc, close_paren_loc); } break; + case RID_BUILTIN_TGMATH: + { + vec<c_expr_t, va_gc> *cexpr_list; + location_t close_paren_loc; + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, + "__builtin_tgmath", + &cexpr_list, false, + &close_paren_loc)) + { + expr.set_error (); + break; + } + + if (vec_safe_length (cexpr_list) < 3) + { + error_at (loc, "too few arguments to %<__builtin_tgmath%>"); + expr.set_error (); + break; + } + + unsigned int i; + c_expr_t *p; + FOR_EACH_VEC_ELT (*cexpr_list, i, p) + *p = convert_lvalue_to_rvalue (loc, *p, true, true); + unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1); + if (nargs == 0) + { + expr.set_error (); + break; + } + if (vec_safe_length (cexpr_list) < nargs) + { + error_at (loc, "too few arguments to %<__builtin_tgmath%>"); + expr.set_error (); + break; + } + unsigned int num_functions = vec_safe_length (cexpr_list) - nargs; + if (num_functions < 2) + { + error_at (loc, "too few arguments to %<__builtin_tgmath%>"); + expr.set_error (); + break; + } + + /* The first NUM_FUNCTIONS expressions are the function + pointers. The remaining NARGS expressions are the + arguments that are to be passed to one of those + functions, chosen following <tgmath.h> rules. */ + for (unsigned int j = 1; j < num_functions; j++) + { + unsigned int this_nargs + = check_tgmath_function (&(*cexpr_list)[j], j + 1); + if (this_nargs == 0) + { + expr.set_error (); + goto out; + } + if (this_nargs != nargs) + { + error_at ((*cexpr_list)[j].get_location (), + "argument %u of %<__builtin_tgmath%> has " + "wrong number of arguments", j + 1); + expr.set_error (); + goto out; + } + } + + /* The functions all have the same number of arguments. + Determine whether arguments and return types vary in + ways permitted for <tgmath.h> functions. */ + /* The first entry in each of these vectors is for the + return type, subsequent entries for parameter + types. */ + auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1); + auto_vec<tree> parm_first (nargs + 1); + auto_vec<bool> parm_complex (nargs + 1); + auto_vec<bool> parm_varies (nargs + 1); + tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value)); + tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type)); + parm_first.quick_push (first_ret); + parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE); + parm_varies.quick_push (false); + function_args_iterator iter; + tree t; + unsigned int argpos; + FOREACH_FUNCTION_ARGS (first_type, t, iter) + { + if (t == void_type_node) + break; + parm_first.quick_push (TYPE_MAIN_VARIANT (t)); + parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE); + parm_varies.quick_push (false); + } + for (unsigned int j = 1; j < num_functions; j++) + { + tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); + tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + if (ret != parm_first[0]) + { + parm_varies[0] = true; + if (!SCALAR_FLOAT_TYPE_P (parm_first[0]) + && !COMPLEX_FLOAT_TYPE_P (parm_first[0])) + { + error_at ((*cexpr_list)[0].get_location (), + "invalid type-generic return type for " + "argument %u of %<__builtin_tgmath%>", + 1); + expr.set_error (); + goto out; + } + if (!SCALAR_FLOAT_TYPE_P (ret) + && !COMPLEX_FLOAT_TYPE_P (ret)) + { + error_at ((*cexpr_list)[j].get_location (), + "invalid type-generic return type for " + "argument %u of %<__builtin_tgmath%>", + j + 1); + expr.set_error (); + goto out; + } + } + if (TREE_CODE (ret) == COMPLEX_TYPE) + parm_complex[0] = true; + argpos = 1; + FOREACH_FUNCTION_ARGS (type, t, iter) + { + if (t == void_type_node) + break; + t = TYPE_MAIN_VARIANT (t); + if (t != parm_first[argpos]) + { + parm_varies[argpos] = true; + if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos]) + && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos])) + { + error_at ((*cexpr_list)[0].get_location (), + "invalid type-generic type for " + "argument %u of argument %u of " + "%<__builtin_tgmath%>", argpos, 1); + expr.set_error (); + goto out; + } + if (!SCALAR_FLOAT_TYPE_P (t) + && !COMPLEX_FLOAT_TYPE_P (t)) + { + error_at ((*cexpr_list)[j].get_location (), + "invalid type-generic type for " + "argument %u of argument %u of " + "%<__builtin_tgmath%>", argpos, j + 1); + expr.set_error (); + goto out; + } + } + if (TREE_CODE (t) == COMPLEX_TYPE) + parm_complex[argpos] = true; + argpos++; + } + } + enum tgmath_parm_kind max_variation = tgmath_fixed; + for (unsigned int j = 0; j <= nargs; j++) + { + enum tgmath_parm_kind this_kind; + if (parm_varies[j]) + { + if (parm_complex[j]) + max_variation = this_kind = tgmath_complex; + else + { + this_kind = tgmath_real; + if (max_variation != tgmath_complex) + max_variation = tgmath_real; + } + } + else + this_kind = tgmath_fixed; + parm_kind.quick_push (this_kind); + } + if (max_variation == tgmath_fixed) + { + error_at (loc, "function arguments of %<__builtin_tgmath%> " + "all have the same type"); + expr.set_error (); + break; + } + + /* Identify a parameter (not the return type) that varies, + including with complex types if any variation includes + complex types; there must be at least one such + parameter. */ + unsigned int tgarg = 0; + for (unsigned int j = 1; j <= nargs; j++) + if (parm_kind[j] == max_variation) + { + tgarg = j; + break; + } + if (tgarg == 0) + { + error_at (loc, "function arguments of %<__builtin_tgmath%> " + "lack type-generic parameter"); + expr.set_error (); + break; + } + + /* Determine the type of the relevant parameter for each + function. */ + auto_vec<tree> tg_type (num_functions); + for (unsigned int j = 0; j < num_functions; j++) + { + tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); + argpos = 1; + FOREACH_FUNCTION_ARGS (type, t, iter) + { + if (argpos == tgarg) + { + tg_type.quick_push (TYPE_MAIN_VARIANT (t)); + break; + } + argpos++; + } + } + + /* Verify that the corresponding types are different for + all the listed functions. Also determine whether all + the types are complex, whether all the types are + standard or binary, and whether all the types are + decimal. */ + bool all_complex = true; + bool all_binary = true; + bool all_decimal = true; + hash_set<tree> tg_types; + FOR_EACH_VEC_ELT (tg_type, i, t) + { + if (TREE_CODE (t) == COMPLEX_TYPE) + all_decimal = false; + else + { + all_complex = false; + if (DECIMAL_FLOAT_TYPE_P (t)) + all_binary = false; + else + all_decimal = false; + } + if (tg_types.add (t)) + { + error_at ((*cexpr_list)[i].get_location (), + "duplicate type-generic parameter type for " + "function argument %u of %<__builtin_tgmath%>", + i + 1); + expr.set_error (); + goto out; + } + } + + /* Verify that other parameters and the return type whose + types vary have their types varying in the correct + way. */ + for (unsigned int j = 0; j < num_functions; j++) + { + tree exp_type = tg_type[j]; + tree exp_real_type = exp_type; + if (TREE_CODE (exp_type) == COMPLEX_TYPE) + exp_real_type = TREE_TYPE (exp_type); + tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); + tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + if ((parm_kind[0] == tgmath_complex && ret != exp_type) + || (parm_kind[0] == tgmath_real && ret != exp_real_type)) + { + error_at ((*cexpr_list)[j].get_location (), + "bad return type for function argument %u " + "of %<__builtin_tgmath%>", j + 1); + expr.set_error (); + goto out; + } + argpos = 1; + FOREACH_FUNCTION_ARGS (type, t, iter) + { + if (t == void_type_node) + break; + t = TYPE_MAIN_VARIANT (t); + if ((parm_kind[argpos] == tgmath_complex + && t != exp_type) + || (parm_kind[argpos] == tgmath_real + && t != exp_real_type)) + { + error_at ((*cexpr_list)[j].get_location (), + "bad type for argument %u of " + "function argument %u of " + "%<__builtin_tgmath%>", argpos, j + 1); + expr.set_error (); + goto out; + } + argpos++; + } + } + + /* The functions listed are a valid set of functions for a + <tgmath.h> macro to select between. Identify the + matching function, if any. First, the argument types + must be combined following <tgmath.h> rules. Integer + types are treated as _Decimal64 if any type-generic + argument is decimal, or if the only alternatives for + type-generic arguments are of decimal types, and are + otherwise treated as double (or _Complex double for + complex integer types, or _Float64 or _Complex _Float64 + if all the return types are the same _FloatN or + _FloatNx type). After that adjustment, types are + combined following the usual arithmetic conversions. + If the function only accepts complex arguments, a + complex type is produced. */ + bool arg_complex = all_complex; + bool arg_binary = all_binary; + bool arg_int_decimal = all_decimal; + for (unsigned int j = 1; j <= nargs; j++) + { + if (parm_kind[j] == tgmath_fixed) + continue; + c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1]; + tree type = TREE_TYPE (ce->value); + if (!INTEGRAL_TYPE_P (type) + && !SCALAR_FLOAT_TYPE_P (type) + && TREE_CODE (type) != COMPLEX_TYPE) + { + error_at (ce->get_location (), + "invalid type of argument %u of type-generic " + "function", j); + expr.set_error (); + goto out; + } + if (DECIMAL_FLOAT_TYPE_P (type)) + { + arg_int_decimal = true; + if (all_complex) + { + error_at (ce->get_location (), + "decimal floating-point argument %u to " + "complex-only type-generic function", j); + expr.set_error (); + goto out; + } + else if (all_binary) + { + error_at (ce->get_location (), + "decimal floating-point argument %u to " + "binary-only type-generic function", j); + expr.set_error (); + goto out; + } + else if (arg_complex) + { + error_at (ce->get_location (), + "both complex and decimal floating-point " + "arguments to type-generic function"); + expr.set_error (); + goto out; + } + else if (arg_binary) + { + error_at (ce->get_location (), + "both binary and decimal floating-point " + "arguments to type-generic function"); + expr.set_error (); + goto out; + } + } + else if (TREE_CODE (type) == COMPLEX_TYPE) + { + arg_complex = true; + if (COMPLEX_FLOAT_TYPE_P (type)) + arg_binary = true; + if (all_decimal) + { + error_at (ce->get_location (), + "complex argument %u to " + "decimal-only type-generic function", j); + expr.set_error (); + goto out; + } + else if (arg_int_decimal) + { + error_at (ce->get_location (), + "both complex and decimal floating-point " + "arguments to type-generic function"); + expr.set_error (); + goto out; + } + } + else if (SCALAR_FLOAT_TYPE_P (type)) + { + arg_binary = true; + if (all_decimal) + { + error_at (ce->get_location (), + "binary argument %u to " + "decimal-only type-generic function", j); + expr.set_error (); + goto out; + } + else if (arg_int_decimal) + { + error_at (ce->get_location (), + "both binary and decimal floating-point " + "arguments to type-generic function"); + expr.set_error (); + goto out; + } + } + } + /* For a macro rounding its result to a narrower type, map + integer types to _Float64 not double if the return type + is a _FloatN or _FloatNx type. */ + bool arg_int_float64 = false; + if (parm_kind[0] == tgmath_fixed + && SCALAR_FLOAT_TYPE_P (parm_first[0]) + && float64_type_node != NULL_TREE) + for (unsigned int j = 0; j < NUM_FLOATN_NX_TYPES; j++) + if (parm_first[0] == FLOATN_TYPE_NODE (j)) + { + arg_int_float64 = true; + break; + } + tree arg_real = NULL_TREE; + for (unsigned int j = 1; j <= nargs; j++) + { + if (parm_kind[j] == tgmath_fixed) + continue; + c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1]; + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value)); + if (TREE_CODE (type) == COMPLEX_TYPE) + type = TREE_TYPE (type); + if (INTEGRAL_TYPE_P (type)) + type = (arg_int_decimal + ? dfloat64_type_node + : arg_int_float64 + ? float64_type_node + : double_type_node); + if (arg_real == NULL_TREE) + arg_real = type; + else + arg_real = common_type (arg_real, type); + if (arg_real == error_mark_node) + { + expr.set_error (); + goto out; + } + } + tree arg_type = (arg_complex + ? build_complex_type (arg_real) + : arg_real); + + /* Look for a function to call with type-generic parameter + type ARG_TYPE. */ + c_expr_t *fn = NULL; + for (unsigned int j = 0; j < num_functions; j++) + { + if (tg_type[j] == arg_type) + { + fn = &(*cexpr_list)[j]; + break; + } + } + if (fn == NULL + && parm_kind[0] == tgmath_fixed + && SCALAR_FLOAT_TYPE_P (parm_first[0])) + { + /* Presume this is a macro that rounds its result to a + narrower type, and look for the first function with + at least the range and precision of the argument + type. */ + for (unsigned int j = 0; j < num_functions; j++) + { + if (arg_complex + != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE)) + continue; + tree real_tg_type = (arg_complex + ? TREE_TYPE (tg_type[j]) + : tg_type[j]); + if (DECIMAL_FLOAT_TYPE_P (arg_real) + != DECIMAL_FLOAT_TYPE_P (real_tg_type)) + continue; + scalar_float_mode arg_mode + = SCALAR_FLOAT_TYPE_MODE (arg_real); + scalar_float_mode tg_mode + = SCALAR_FLOAT_TYPE_MODE (real_tg_type); + const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode); + const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode); + if (arg_fmt->b == tg_fmt->b + && arg_fmt->p <= tg_fmt->p + && arg_fmt->emax <= tg_fmt->emax + && (arg_fmt->emin - arg_fmt->p + >= tg_fmt->emin - tg_fmt->p)) + { + fn = &(*cexpr_list)[j]; + break; + } + } + } + if (fn == NULL) + { + error_at (loc, "no matching function for type-generic call"); + expr.set_error (); + break; + } + + /* Construct a call to FN. */ + vec<tree, va_gc> *args; + vec_alloc (args, nargs); + vec<tree, va_gc> *origtypes; + vec_alloc (origtypes, nargs); + auto_vec<location_t> arg_loc (nargs); + for (unsigned int j = 0; j < nargs; j++) + { + c_expr_t *ce = &(*cexpr_list)[num_functions + j]; + args->quick_push (ce->value); + arg_loc.quick_push (ce->get_location ()); + origtypes->quick_push (ce->original_type); + } + expr.value = c_build_function_call_vec (loc, arg_loc, fn->value, + args, origtypes); + set_c_expr_source_range (&expr, loc, close_paren_loc); + break; + } case RID_BUILTIN_CALL_WITH_STATIC_CHAIN: { vec<c_expr_t, va_gc> *cexpr_list; @@ -8839,30 +9320,6 @@ case RID_GENERIC: expr = c_parser_generic_selection (parser); break; - case RID_CILK_SPAWN: - c_parser_consume_token (parser); - if (!flag_cilkplus) - { - error_at (loc, "-fcilkplus must be enabled to use " - "%<_Cilk_spawn%>"); - expr = c_parser_cast_expression (parser, NULL); - expr.set_error (); - } - else if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) - { - error_at (loc, "consecutive %<_Cilk_spawn%> keywords " - "are not permitted"); - /* Now flush out all the _Cilk_spawns. */ - while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) - c_parser_consume_token (parser); - expr = c_parser_cast_expression (parser, NULL); - } - else - { - expr = c_parser_cast_expression (parser, NULL); - expr.value = build_cilk_spawn (loc, expr.value); - } - break; default: c_parser_error (parser, "expected expression"); expr.set_error (); @@ -8890,6 +9347,7 @@ expr.set_error (); break; } + out: return c_parser_postfix_expression_after_primary (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); } @@ -8943,7 +9401,21 @@ ? CONSTRUCTOR_NON_CONST (init.value) : init.original_code == C_MAYBE_CONST_EXPR); non_const |= !type_expr_const; - expr.value = build_compound_literal (start_loc, type, init.value, non_const); + unsigned int alignas_align = 0; + if (type != error_mark_node + && type_name->specs->align_log != -1) + { + alignas_align = 1U << type_name->specs->align_log; + if (alignas_align < min_align_of_type (type)) + { + error_at (type_name->specs->locations[cdw_alignas], + "%<_Alignas%> specifiers cannot reduce " + "alignment of compound literal"); + alignas_align = 0; + } + } + expr.value = build_compound_literal (start_loc, type, init.value, non_const, + alignas_align); set_c_expr_source_range (&expr, init.src_range); expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -8975,6 +9447,147 @@ return comptypes (type1, type2) == 1; } +/* Warn for patterns where abs-like function appears to be used incorrectly, + gracefully ignore any non-abs-like function. The warning location should + be LOC. FNDECL is the declaration of called function, it must be a + BUILT_IN_NORMAL function. ARG is the first and only argument of the + call. */ + +static void +warn_for_abs (location_t loc, tree fndecl, tree arg) +{ + tree atype = TREE_TYPE (arg); + + /* Casts from pointers (and thus arrays and fndecls) will generate + -Wint-conversion warnings. Most other wrong types hopefully lead to type + mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P + types and possibly other exotic types. */ + if (!INTEGRAL_TYPE_P (atype) + && !SCALAR_FLOAT_TYPE_P (atype) + && TREE_CODE (atype) != COMPLEX_TYPE) + return; + + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + case BUILT_IN_ABS: + case BUILT_IN_LABS: + case BUILT_IN_LLABS: + case BUILT_IN_IMAXABS: + if (!INTEGRAL_TYPE_P (atype)) + { + if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using integer absolute value function %qD when " + "argument is of floating point type %qT", + fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using integer absolute value function %qD when " + "argument is of complex type %qT", fndecl, atype); + else + gcc_unreachable (); + return; + } + if (TYPE_UNSIGNED (atype)) + warning_at (loc, OPT_Wabsolute_value, + "taking the absolute value of unsigned type %qT " + "has no effect", atype); + break; + + CASE_FLT_FN (BUILT_IN_FABS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS): + if (!SCALAR_FLOAT_TYPE_P (atype) + || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype))) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD " + "when argument is of integer type %qT", fndecl, atype); + else if (DECIMAL_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD " + "when argument is of decimal floating point type %qT", + fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD when " + "argument is of complex type %qT", fndecl, atype); + else + gcc_unreachable (); + return; + } + break; + + CASE_FLT_FN (BUILT_IN_CABS): + if (TREE_CODE (atype) != COMPLEX_TYPE) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using complex absolute value function %qD when " + "argument is of integer type %qT", fndecl, atype); + else if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using complex absolute value function %qD when " + "argument is of floating point type %qT", + fndecl, atype); + else + gcc_unreachable (); + + return; + } + break; + + case BUILT_IN_FABSD32: + case BUILT_IN_FABSD64: + case BUILT_IN_FABSD128: + if (!DECIMAL_FLOAT_TYPE_P (atype)) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of integer type %qT", + fndecl, atype); + else if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of floating point " + "type %qT", fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of complex type %qT", + fndecl, atype); + else + gcc_unreachable (); + return; + } + break; + + default: + return; + } + + if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl))) + return; + + tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); + if (TREE_CODE (atype) == COMPLEX_TYPE) + { + gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE); + atype = TREE_TYPE (atype); + ftype = TREE_TYPE (ftype); + } + + if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype)) + warning_at (loc, OPT_Wabsolute_value, + "absolute value function %qD given an argument of type %qT " + "but has parameter of type %qT which may cause truncation " + "of value", fndecl, atype, ftype); +} + + /* Parse a postfix expression after the initial primary or compound literal; that is, parse a series of postfix operators. @@ -9005,39 +9618,13 @@ case CPP_OPEN_SQUARE: /* Array reference. */ c_parser_consume_token (parser); - if (flag_cilkplus - && c_parser_peek_token (parser)->type == CPP_COLON) - /* If we are here, then we have something like this: - Array [ : ] - */ - expr.value = c_parser_array_notation (expr_loc, parser, NULL_TREE, - expr.value); - else - { - idx = c_parser_expression (parser).value; - /* Here we have 3 options: - 1. Array [EXPR] -- Normal Array call. - 2. Array [EXPR : EXPR] -- Array notation without stride. - 3. Array [EXPR : EXPR : EXPR] -- Array notation with stride. - - For 1, we just handle it just like a normal array expression. - For 2 and 3 we handle it like we handle array notations. The - idx value we have above becomes the initial/start index. - */ - if (flag_cilkplus - && c_parser_peek_token (parser)->type == CPP_COLON) - expr.value = c_parser_array_notation (expr_loc, parser, idx, - expr.value); - else - { - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - start = expr.get_start (); - finish = parser->tokens_buf[0].location; - expr.value = build_array_ref (op_loc, expr.value, idx); - set_c_expr_source_range (&expr, start, finish); - } - } + idx = c_parser_expression (parser).value; + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build_array_ref (op_loc, expr.value, idx); + set_c_expr_source_range (&expr, start, finish); expr.original_code = ERROR_MARK; expr.original_type = NULL; break; @@ -9065,14 +9652,19 @@ expr.value, exprlist, sizeof_arg, sizeof_ptr_memacc_comptypes); - if (TREE_CODE (expr.value) == FUNCTION_DECL - && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET - && vec_safe_length (exprlist) == 3) - { - tree arg0 = (*exprlist)[0]; - tree arg2 = (*exprlist)[2]; - warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); + if (TREE_CODE (expr.value) == FUNCTION_DECL) + { + if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET) + && vec_safe_length (exprlist) == 3) + { + tree arg0 = (*exprlist)[0]; + tree arg2 = (*exprlist)[2]; + warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); + } + if (warn_absolute_value + && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL) + && vec_safe_length (exprlist) == 1) + warn_for_abs (expr_loc, expr.value, (*exprlist)[0]); } start = expr.get_start (); @@ -9085,8 +9677,7 @@ expr.original_code = ERROR_MARK; if (TREE_CODE (expr.value) == INTEGER_CST && TREE_CODE (orig_expr.value) == FUNCTION_DECL - && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) + && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P)) expr.original_code = C_MAYBE_CONST_EXPR; expr.original_type = NULL; if (exprlist) @@ -9178,16 +9769,9 @@ start = expr.get_start (); finish = c_parser_peek_token (parser)->get_finish (); c_parser_consume_token (parser); - /* If the expressions have array notations, we expand them. */ - if (flag_cilkplus - && TREE_CODE (expr.value) == ARRAY_NOTATION_REF) - expr = fix_array_notation_expr (expr_loc, POSTINCREMENT_EXPR, expr); - else - { - expr = default_function_array_read_conversion (expr_loc, expr); - expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR, - expr.value, false); - } + expr = default_function_array_read_conversion (expr_loc, expr); + expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR, + expr.value, false); set_c_expr_source_range (&expr, start, finish); expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -9197,16 +9781,9 @@ start = expr.get_start (); finish = c_parser_peek_token (parser)->get_finish (); c_parser_consume_token (parser); - /* If the expressions have array notations, we expand them. */ - if (flag_cilkplus - && TREE_CODE (expr.value) == ARRAY_NOTATION_REF) - expr = fix_array_notation_expr (expr_loc, POSTDECREMENT_EXPR, expr); - else - { - expr = default_function_array_read_conversion (expr_loc, expr); - expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR, - expr.value, false); - } + expr = default_function_array_read_conversion (expr_loc, expr); + expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR, + expr.value, false); set_c_expr_source_range (&expr, start, finish); expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -10798,6 +11375,49 @@ } +/* Parse a pragma GCC ivdep. */ + +static bool +c_parse_pragma_ivdep (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + return true; +} + +/* Parse a pragma GCC unroll. */ + +static unsigned short +c_parser_pragma_unroll (c_parser *parser) +{ + unsigned short unroll; + c_parser_consume_pragma (parser); + location_t location = c_parser_peek_token (parser)->location; + tree expr = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (expr); + expr = c_fully_fold (expr, false, NULL); + HOST_WIDE_INT lunroll = 0; + if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) + || TREE_CODE (expr) != INTEGER_CST + || (lunroll = tree_to_shwi (expr)) < 0 + || lunroll >= USHRT_MAX) + { + error_at (location, "%<#pragma GCC unroll%> requires an" + " assignment-expression that evaluates to a non-negative" + " integral constant less than %u", USHRT_MAX); + unroll = 0; + } + else + { + unroll = (unsigned short)lunroll; + if (unroll == 0) + unroll = 1; + } + + c_parser_skip_to_pragma_eol (parser); + return unroll; +} + /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore should be considered, statements. ALLOW_STMT is true if we're within the context of a function and such pragmas are to be allowed. Returns @@ -10940,21 +11560,51 @@ return c_parser_omp_ordered (parser, context, if_p); case PRAGMA_IVDEP: - c_parser_consume_pragma (parser); - c_parser_skip_to_pragma_eol (parser); - if (!c_parser_next_token_is_keyword (parser, RID_FOR) - && !c_parser_next_token_is_keyword (parser, RID_WHILE) - && !c_parser_next_token_is_keyword (parser, RID_DO)) - { - c_parser_error (parser, "for, while or do statement expected"); - return false; - } - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, true, if_p); - else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, true, if_p); - else - c_parser_do_statement (parser, true); + { + const bool ivdep = c_parse_pragma_ivdep (parser); + unsigned short unroll; + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL) + unroll = c_parser_pragma_unroll (parser); + else + unroll = 0; + if (!c_parser_next_token_is_keyword (parser, RID_FOR) + && !c_parser_next_token_is_keyword (parser, RID_WHILE) + && !c_parser_next_token_is_keyword (parser, RID_DO)) + { + c_parser_error (parser, "for, while or do statement expected"); + return false; + } + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + c_parser_for_statement (parser, ivdep, unroll, if_p); + else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) + c_parser_while_statement (parser, ivdep, unroll, if_p); + else + c_parser_do_statement (parser, ivdep, unroll); + } + return false; + + case PRAGMA_UNROLL: + { + unsigned short unroll = c_parser_pragma_unroll (parser); + bool ivdep; + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP) + ivdep = c_parse_pragma_ivdep (parser); + else + ivdep = false; + if (!c_parser_next_token_is_keyword (parser, RID_FOR) + && !c_parser_next_token_is_keyword (parser, RID_WHILE) + && !c_parser_next_token_is_keyword (parser, RID_DO)) + { + c_parser_error (parser, "for, while or do statement expected"); + return false; + } + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + c_parser_for_statement (parser, ivdep, unroll, if_p); + else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) + c_parser_while_statement (parser, ivdep, unroll, if_p); + else + c_parser_do_statement (parser, ivdep, unroll); + } return false; case PRAGMA_GCC_PCH_PREPROCESS: @@ -10962,30 +11612,6 @@ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; - case PRAGMA_CILK_SIMD: - if (!c_parser_cilk_verify_simd (parser, context)) - return false; - c_parser_consume_pragma (parser); - c_parser_cilk_simd (parser, if_p); - return false; - case PRAGMA_CILK_GRAINSIZE: - if (!flag_cilkplus) - { - warning (0, "%<#pragma grainsize%> ignored because -fcilkplus is not" - " enabled"); - c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); - return false; - } - if (context == pragma_external) - { - error_at (c_parser_peek_token (parser)->location, - "%<#pragma grainsize%> must be inside a function"); - c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); - return false; - } - c_parser_cilk_grainsize (parser, if_p); - return false; - case PRAGMA_OACC_WAIT: if (context != pragma_compound) { @@ -11130,6 +11756,8 @@ case 'f': if (!strcmp ("final", p)) result = PRAGMA_OMP_CLAUSE_FINAL; + else if (!strcmp ("finalize", p)) + result = PRAGMA_OACC_CLAUSE_FINALIZE; else if (!strcmp ("firstprivate", p)) result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; else if (!strcmp ("from", p)) @@ -11148,7 +11776,9 @@ result = PRAGMA_OACC_CLAUSE_HOST; break; case 'i': - if (!strcmp ("inbranch", p)) + if (!strcmp ("if_present", p)) + result = PRAGMA_OACC_CLAUSE_IF_PRESENT; + else if (!strcmp ("inbranch", p)) result = PRAGMA_OMP_CLAUSE_INBRANCH; else if (!strcmp ("independent", p)) result = PRAGMA_OACC_CLAUSE_INDEPENDENT; @@ -11168,8 +11798,6 @@ result = PRAGMA_OMP_CLAUSE_MAP; else if (!strcmp ("mergeable", p)) result = PRAGMA_OMP_CLAUSE_MERGEABLE; - else if (flag_cilkplus && !strcmp ("mask", p)) - result = PRAGMA_CILK_CLAUSE_MASK; break; case 'n': if (!strcmp ("nogroup", p)) @@ -11188,8 +11816,6 @@ result = PRAGMA_OMP_CLAUSE_NUM_THREADS; else if (!strcmp ("num_workers", p)) result = PRAGMA_OACC_CLAUSE_NUM_WORKERS; - else if (flag_cilkplus && !strcmp ("nomask", p)) - result = PRAGMA_CILK_CLAUSE_NOMASK; break; case 'o': if (!strcmp ("ordered", p)) @@ -11200,18 +11826,20 @@ result = PRAGMA_OMP_CLAUSE_PARALLEL; else if (!strcmp ("present", p)) result = PRAGMA_OACC_CLAUSE_PRESENT; + /* As of OpenACC 2.5, these are now aliases of the non-present_or + clauses. */ else if (!strcmp ("present_or_copy", p) || !strcmp ("pcopy", p)) - result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY; + result = PRAGMA_OACC_CLAUSE_COPY; else if (!strcmp ("present_or_copyin", p) || !strcmp ("pcopyin", p)) - result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN; + result = PRAGMA_OACC_CLAUSE_COPYIN; else if (!strcmp ("present_or_copyout", p) || !strcmp ("pcopyout", p)) - result = PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT; + result = PRAGMA_OACC_CLAUSE_COPYOUT; else if (!strcmp ("present_or_create", p) || !strcmp ("pcreate", p)) - result = PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE; + result = PRAGMA_OACC_CLAUSE_CREATE; else if (!strcmp ("priority", p)) result = PRAGMA_OMP_CLAUSE_PRIORITY; else if (!strcmp ("private", p)) @@ -11230,6 +11858,8 @@ result = PRAGMA_OMP_CLAUSE_SCHEDULE; else if (!strcmp ("sections", p)) result = PRAGMA_OMP_CLAUSE_SECTIONS; + else if (!strcmp ("self", p)) /* "self" is a synonym for "host". */ + result = PRAGMA_OACC_CLAUSE_HOST; else if (!strcmp ("seq", p)) result = PRAGMA_OACC_CLAUSE_SEQ; else if (!strcmp ("shared", p)) @@ -11238,8 +11868,6 @@ result = PRAGMA_OMP_CLAUSE_SIMD; else if (!strcmp ("simdlen", p)) result = PRAGMA_OMP_CLAUSE_SIMDLEN; - else if (!strcmp ("self", p)) - result = PRAGMA_OACC_CLAUSE_SELF; break; case 't': if (!strcmp ("taskgroup", p)) @@ -11268,8 +11896,6 @@ result = PRAGMA_OACC_CLAUSE_VECTOR; else if (!strcmp ("vector_length", p)) result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH; - else if (flag_cilkplus && !strcmp ("vectorlength", p)) - result = PRAGMA_CILK_CLAUSE_VECTORLENGTH; break; case 'w': if (!strcmp ("wait", p)) @@ -11523,15 +12149,7 @@ copyout ( variable-list ) create ( variable-list ) delete ( variable-list ) - present ( variable-list ) - present_or_copy ( variable-list ) - pcopy ( variable-list ) - present_or_copyin ( variable-list ) - pcopyin ( variable-list ) - present_or_copyout ( variable-list ) - pcopyout ( variable-list ) - present_or_create ( variable-list ) - pcreate ( variable-list ) */ + present ( variable-list ) */ static tree c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind, @@ -11541,19 +12159,19 @@ switch (c_kind) { case PRAGMA_OACC_CLAUSE_COPY: - kind = GOMP_MAP_FORCE_TOFROM; + kind = GOMP_MAP_TOFROM; break; case PRAGMA_OACC_CLAUSE_COPYIN: - kind = GOMP_MAP_FORCE_TO; + kind = GOMP_MAP_TO; break; case PRAGMA_OACC_CLAUSE_COPYOUT: - kind = GOMP_MAP_FORCE_FROM; + kind = GOMP_MAP_FROM; break; case PRAGMA_OACC_CLAUSE_CREATE: - kind = GOMP_MAP_FORCE_ALLOC; + kind = GOMP_MAP_ALLOC; break; case PRAGMA_OACC_CLAUSE_DELETE: - kind = GOMP_MAP_DELETE; + kind = GOMP_MAP_RELEASE; break; case PRAGMA_OACC_CLAUSE_DEVICE: kind = GOMP_MAP_FORCE_TO; @@ -11562,7 +12180,6 @@ kind = GOMP_MAP_DEVICE_RESIDENT; break; case PRAGMA_OACC_CLAUSE_HOST: - case PRAGMA_OACC_CLAUSE_SELF: kind = GOMP_MAP_FORCE_FROM; break; case PRAGMA_OACC_CLAUSE_LINK: @@ -11571,18 +12188,6 @@ case PRAGMA_OACC_CLAUSE_PRESENT: kind = GOMP_MAP_FORCE_PRESENT; break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY: - kind = GOMP_MAP_TOFROM; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN: - kind = GOMP_MAP_TO; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT: - kind = GOMP_MAP_FROM; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE: - kind = GOMP_MAP_ALLOC; - break; default: gcc_unreachable (); } @@ -12474,8 +13079,9 @@ return list; } -/* OpenACC: +/* OpenACC 2.5: auto + finalize independent nohost seq */ @@ -13170,7 +13776,7 @@ linear ( modifier ( variable-list ) : expression ) */ static tree -c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) +c_parser_omp_clause_linear (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; @@ -13180,8 +13786,7 @@ if (!parens.require_open (parser)) return list; - if (!is_cilk_simd_fn - && c_parser_next_token_is (parser, CPP_NAME)) + if (c_parser_next_token_is (parser, CPP_NAME)) { c_token *tok = c_parser_peek_token (parser); const char *p = IDENTIFIER_POINTER (tok->value); @@ -13210,11 +13815,6 @@ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); step = expr.value; step = c_fully_fold (step, false, NULL); - if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) - { - sorry ("using parameters for %<linear%> step is not supported yet"); - step = integer_one_node; - } if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) { error_at (clause_loc, "%<linear%> clause step expression must " @@ -13838,6 +14438,11 @@ clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); c_name = "device_resident"; break; + case PRAGMA_OACC_CLAUSE_FINALIZE: + clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_FINALIZE, + clauses); + c_name = "finalize"; + break; case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE: clauses = c_parser_omp_clause_firstprivate (parser, clauses); c_name = "firstprivate"; @@ -13855,6 +14460,11 @@ clauses = c_parser_omp_clause_if (parser, clauses, false); c_name = "if"; break; + case PRAGMA_OACC_CLAUSE_IF_PRESENT: + clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_IF_PRESENT, + clauses); + c_name = "if_present"; + break; case PRAGMA_OACC_CLAUSE_INDEPENDENT: clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_INDEPENDENT, clauses); @@ -13880,22 +14490,6 @@ clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); c_name = "present"; break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY: - clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); - c_name = "present_or_copy"; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN: - clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); - c_name = "present_or_copyin"; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT: - clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); - c_name = "present_or_copyout"; - break; - case PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE: - clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); - c_name = "present_or_create"; - break; case PRAGMA_OACC_CLAUSE_PRIVATE: clauses = c_parser_omp_clause_private (parser, clauses); c_name = "private"; @@ -13904,10 +14498,6 @@ clauses = c_parser_omp_clause_reduction (parser, clauses); c_name = "reduction"; break; - case PRAGMA_OACC_CLAUSE_SELF: - clauses = c_parser_oacc_data_clause (parser, c_kind, clauses); - c_name = "self"; - break; case PRAGMA_OACC_CLAUSE_SEQ: clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ, clauses); @@ -13974,7 +14564,7 @@ const char *where, bool finish_p = true) { tree clauses = NULL; - bool first = true, cilk_simd_fn = false; + bool first = true; while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { @@ -14080,13 +14670,11 @@ c_name = "untied"; break; case PRAGMA_OMP_CLAUSE_INBRANCH: - case PRAGMA_CILK_CLAUSE_MASK: clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH, clauses); c_name = "inbranch"; break; case PRAGMA_OMP_CLAUSE_NOTINBRANCH: - case PRAGMA_CILK_CLAUSE_NOMASK: clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH, clauses); c_name = "notinbranch"; @@ -14163,9 +14751,7 @@ c_name = "aligned"; break; case PRAGMA_OMP_CLAUSE_LINEAR: - if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0) - cilk_simd_fn = true; - clauses = c_parser_omp_clause_linear (parser, clauses, cilk_simd_fn); + clauses = c_parser_omp_clause_linear (parser, clauses); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -14200,10 +14786,6 @@ clauses = c_parser_omp_clause_safelen (parser, clauses); c_name = "safelen"; break; - case PRAGMA_CILK_CLAUSE_VECTORLENGTH: - clauses = c_parser_cilk_clause_vectorlength (parser, clauses, true); - c_name = "simdlen"; - break; case PRAGMA_OMP_CLAUSE_SIMDLEN: clauses = c_parser_omp_clause_simdlen (parser, clauses); c_name = "simdlen"; @@ -14308,11 +14890,7 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) ) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)) static tree c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p) @@ -14342,11 +14920,7 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) ) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT)) static void c_parser_oacc_declare (c_parser *parser) @@ -14381,8 +14955,8 @@ switch (OMP_CLAUSE_MAP_KIND (t)) { case GOMP_MAP_FIRSTPRIVATE_POINTER: - case GOMP_MAP_FORCE_ALLOC: - case GOMP_MAP_FORCE_TO: + case GOMP_MAP_ALLOC: + case GOMP_MAP_TO: case GOMP_MAP_FORCE_DEVICEPTR: case GOMP_MAP_DEVICE_RESIDENT: break; @@ -14495,8 +15069,6 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) #define OACC_EXIT_DATA_CLAUSE_MASK \ @@ -14504,6 +15076,7 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) static void @@ -14647,10 +15220,6 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) @@ -14668,10 +15237,6 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPY) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYIN) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_COPYOUT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) @@ -14899,7 +15464,7 @@ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) static void @@ -15075,7 +15640,7 @@ case NOP_EXPR: /* atomic write */ v = c_parser_cast_expression (parser, NULL).value; non_lvalue_p = !lvalue_p (v); - v = c_fully_fold (v, false, NULL); + v = c_fully_fold (v, false, NULL, true); if (v == error_mark_node) goto saw_error; if (non_lvalue_p) @@ -15094,7 +15659,7 @@ { lhs = c_parser_cast_expression (parser, NULL).value; non_lvalue_p = !lvalue_p (lhs); - lhs = c_fully_fold (lhs, false, NULL); + lhs = c_fully_fold (lhs, false, NULL, true); if (lhs == error_mark_node) goto saw_error; if (non_lvalue_p) @@ -15120,7 +15685,7 @@ { v = c_parser_cast_expression (parser, NULL).value; non_lvalue_p = !lvalue_p (v); - v = c_fully_fold (v, false, NULL); + v = c_fully_fold (v, false, NULL, true); if (v == error_mark_node) goto saw_error; if (non_lvalue_p) @@ -15141,7 +15706,7 @@ lhs = expr.value; expr = default_function_array_conversion (eloc, expr); unfolded_lhs = expr.value; - lhs = c_fully_fold (lhs, false, NULL); + lhs = c_fully_fold (lhs, false, NULL, true); orig_lhs = lhs; switch (TREE_CODE (lhs)) { @@ -15281,15 +15846,19 @@ if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs)) { opcode = TREE_CODE (rhs1); - rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL); - rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL); + rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL, + true); + rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL, + true); goto stmt_done; } if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs)) { opcode = TREE_CODE (rhs1); - rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL); - rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL); + rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL, + true); + rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL, + true); swapped = !commutative_tree_code (opcode); goto stmt_done; } @@ -15308,7 +15877,7 @@ lhs = NULL_TREE; expr = default_function_array_read_conversion (eloc, expr); unfolded_lhs1 = expr.value; - lhs1 = c_fully_fold (unfolded_lhs1, false, NULL); + lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true); rhs1 = NULL_TREE; c_parser_consume_token (parser); goto restart; @@ -15317,7 +15886,7 @@ { opcode = NOP_EXPR; expr = default_function_array_read_conversion (eloc, expr); - rhs = c_fully_fold (expr.value, false, NULL); + rhs = c_fully_fold (expr.value, false, NULL, true); rhs1 = NULL_TREE; goto stmt_done; } @@ -15338,7 +15907,7 @@ expr = c_parser_expression (parser); expr = default_function_array_read_conversion (eloc, expr); rhs = expr.value; - rhs = c_fully_fold (rhs, false, NULL); + rhs = c_fully_fold (rhs, false, NULL, true); break; } stmt_done: @@ -15348,7 +15917,7 @@ goto saw_error; v = c_parser_cast_expression (parser, NULL).value; non_lvalue_p = !lvalue_p (v); - v = c_fully_fold (v, false, NULL); + v = c_fully_fold (v, false, NULL, true); if (v == error_mark_node) goto saw_error; if (non_lvalue_p) @@ -15360,7 +15929,7 @@ lhs1 = expr.value; expr = default_function_array_read_conversion (eloc, expr); unfolded_lhs1 = expr.value; - lhs1 = c_fully_fold (lhs1, false, NULL); + lhs1 = c_fully_fold (lhs1, false, NULL, true); if (lhs1 == error_mark_node) goto saw_error; if (!lvalue_p (unfolded_lhs1)) @@ -15533,18 +16102,11 @@ condv = make_tree_vec (count); incrv = make_tree_vec (count); - if (code != CILK_FOR - && !c_parser_next_token_is_keyword (parser, RID_FOR)) + if (!c_parser_next_token_is_keyword (parser, RID_FOR)) { c_parser_error (parser, "for statement expected"); return NULL; } - if (code == CILK_FOR - && !c_parser_next_token_is_keyword (parser, RID_CILK_FOR)) - { - c_parser_error (parser, "_Cilk_for statement expected"); - return NULL; - } for_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); @@ -15644,10 +16206,6 @@ case LT_EXPR: case LE_EXPR: break; - case NE_EXPR: - if (code == CILK_SIMD || code == CILK_FOR) - break; - /* FALLTHRU. */ default: /* Can't be cond = error_mark_node, because we want to preserve the location until c_finish_omp_for. */ @@ -15724,10 +16282,7 @@ if_p = NULL; save_break = c_break_label; - if (code == CILK_SIMD) - c_break_label = build_int_cst (size_type_node, 2); - else - c_break_label = size_one_node; + c_break_label = size_one_node; save_cont = c_cont_label; c_cont_label = NULL_TREE; body = push_stmt_list (); @@ -17238,11 +17793,11 @@ break; case pragma_struct: case pragma_param: + case pragma_stmt: c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by " "function declaration or definition"); break; case pragma_compound: - case pragma_stmt: if (c_parser_next_token_is (parser, CPP_KEYWORD) && c_parser_peek_token (parser)->keyword == RID_EXTENSION) { @@ -17281,18 +17836,6 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, vec<c_token> clauses) { - if (flag_cilkplus - && (clauses.exists () - || lookup_attribute ("simd", DECL_ATTRIBUTES (fndecl))) - && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) - { - error ("%<#pragma omp declare simd%> or %<simd%> attribute cannot be " - "used in the same function marked as a Cilk Plus SIMD-enabled " - "function"); - vec_free (parser->cilk_simd_fn_tokens); - return; - } - /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd has already processed the tokens. */ @@ -17319,60 +17862,26 @@ unsigned int tokens_avail = parser->tokens_avail; gcc_assert (parser->tokens == &parser->tokens_buf[0]); - bool is_cilkplus_cilk_simd_fn = false; - if (flag_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) - { - parser->tokens = parser->cilk_simd_fn_tokens->address (); - parser->tokens_avail = vec_safe_length (parser->cilk_simd_fn_tokens); - is_cilkplus_cilk_simd_fn = true; - - if (lookup_attribute ("simd", DECL_ATTRIBUTES (fndecl)) != NULL) - { - error_at (DECL_SOURCE_LOCATION (fndecl), - "%<__simd__%> attribute cannot be used in the same " - "function marked as a Cilk Plus SIMD-enabled function"); - vec_free (parser->cilk_simd_fn_tokens); - return; - } - - } - else - { - parser->tokens = clauses.address (); - parser->tokens_avail = clauses.length (); - } + + parser->tokens = clauses.address (); + parser->tokens_avail = clauses.length (); /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */ while (parser->tokens_avail > 3) { c_token *token = c_parser_peek_token (parser); - if (!is_cilkplus_cilk_simd_fn) - gcc_assert (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); - else - gcc_assert (token->type == CPP_NAME - && is_cilkplus_vector_p (token->value)); + gcc_assert (token->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); c_parser_consume_token (parser); parser->in_pragma = true; tree c = NULL_TREE; - if (is_cilkplus_cilk_simd_fn) - c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK, - "SIMD-enabled functions attribute"); - else - c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, + c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, "#pragma omp declare simd"); c = c_omp_declare_simd_clauses_to_numbers (parms, c); if (c != NULL_TREE) c = tree_cons (NULL_TREE, c, NULL_TREE); - if (is_cilkplus_cilk_simd_fn) - { - tree k = build_tree_list (get_identifier ("cilk simd function"), - NULL_TREE); - TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl); - DECL_ATTRIBUTES (fndecl) = k; - } c = build_tree_list (get_identifier ("omp declare simd"), c); TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); DECL_ATTRIBUTES (fndecl) = c; @@ -17382,9 +17891,6 @@ parser->tokens_avail = tokens_avail; if (clauses.exists ()) clauses[0].type = CPP_PRAGMA; - - if (!vec_safe_is_empty (parser->cilk_simd_fn_tokens)) - vec_free (parser->cilk_simd_fn_tokens); } @@ -17720,7 +18226,7 @@ struct c_expr initializer; tree omp_priv = NULL_TREE, omp_orig = NULL_TREE; bool bad = false; - initializer.value = error_mark_node; + initializer.set_error (); if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) bad = true; else if (c_parser_next_token_is (parser, CPP_NAME) @@ -18136,419 +18642,7 @@ c_parser_skip_to_pragma_eol (parser); } - -/* Cilk Plus <#pragma simd> parsing routines. */ - -/* Helper function for c_parser_pragma. Perform some sanity checking - for <#pragma simd> constructs. Returns FALSE if there was a - problem. */ - -static bool -c_parser_cilk_verify_simd (c_parser *parser, - enum pragma_context context) -{ - if (!flag_cilkplus) - { - warning (0, "pragma simd ignored because -fcilkplus is not enabled"); - c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); - return false; - } - if (context == pragma_external) - { - c_parser_error (parser,"pragma simd must be inside a function"); - c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); - return false; - } - return true; -} - -/* Cilk Plus: - This function is shared by SIMD-enabled functions and #pragma simd. - If IS_SIMD_FN is true then it is parsing a SIMD-enabled function and - CLAUSES is unused. The main purpose of this function is to parse a - vectorlength attribute or clause and check for parse errors. - When IS_SIMD_FN is true then the function is merely caching the tokens - in PARSER->CILK_SIMD_FN_TOKENS. If errors are found then the token - cache is cleared since there is no reason to continue. - Syntax: - vectorlength ( constant-expression ) */ - -static tree -c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, - bool is_simd_fn) -{ - if (is_simd_fn) - check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength"); - else - /* The vectorlength clause behaves exactly like OpenMP's safelen - clause. Represent it in OpenMP terms. */ - check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); - - matching_parens parens; - if (!parens.require_open (parser)) - return clauses; - - location_t loc = c_parser_peek_token (parser)->location; - tree expr = c_parser_expr_no_commas (parser, NULL).value; - expr = c_fully_fold (expr, false, NULL); - - /* If expr is an error_mark_node then the above function would have - emitted an error. No reason to do it twice. */ - if (expr == error_mark_node) - ; - else if (!TREE_TYPE (expr) - || !TREE_CONSTANT (expr) - || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) - - error_at (loc, "vectorlength must be an integer constant"); - else if (wi::exact_log2 (wi::to_wide (expr)) == -1) - error_at (loc, "vectorlength must be a power of 2"); - else - { - if (is_simd_fn) - { - tree u = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN); - OMP_CLAUSE_SIMDLEN_EXPR (u) = expr; - OMP_CLAUSE_CHAIN (u) = clauses; - clauses = u; - } - else - { - tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); - OMP_CLAUSE_SAFELEN_EXPR (u) = expr; - OMP_CLAUSE_CHAIN (u) = clauses; - clauses = u; - } - } - - parens.require_close (parser); - - return clauses; -} - -/* Cilk Plus: - linear ( simd-linear-variable-list ) - - simd-linear-variable-list: - simd-linear-variable - simd-linear-variable-list , simd-linear-variable - - simd-linear-variable: - id-expression - id-expression : simd-linear-step - - simd-linear-step: - conditional-expression */ - -static tree -c_parser_cilk_clause_linear (c_parser *parser, tree clauses) -{ - matching_parens parens; - if (!parens.require_open (parser)) - return clauses; - - location_t loc = c_parser_peek_token (parser)->location; - - if (c_parser_next_token_is_not (parser, CPP_NAME) - || c_parser_peek_token (parser)->id_kind != C_ID_ID) - c_parser_error (parser, "expected identifier"); - - while (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_ID) - { - tree var = lookup_name (c_parser_peek_token (parser)->value); - - if (var == NULL) - { - undeclared_variable (c_parser_peek_token (parser)->location, - c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - } - else if (var == error_mark_node) - c_parser_consume_token (parser); - else - { - tree step = integer_one_node; - - /* Parse the linear step if present. */ - if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) - { - c_parser_consume_token (parser); - c_parser_consume_token (parser); - - tree expr = c_parser_expr_no_commas (parser, NULL).value; - expr = c_fully_fold (expr, false, NULL); - - if (TREE_TYPE (expr) - && INTEGRAL_TYPE_P (TREE_TYPE (expr)) - && (TREE_CONSTANT (expr) - || DECL_P (expr))) - step = expr; - else - c_parser_error (parser, - "step size must be an integer constant " - "expression or an integer variable"); - } - else - c_parser_consume_token (parser); - - /* Use OMP_CLAUSE_LINEAR, which has the same semantics. */ - tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR); - OMP_CLAUSE_DECL (u) = var; - OMP_CLAUSE_LINEAR_STEP (u) = step; - OMP_CLAUSE_CHAIN (u) = clauses; - clauses = u; - } - - if (c_parser_next_token_is_not (parser, CPP_COMMA)) - break; - - c_parser_consume_token (parser); - } - - parens.skip_until_found_close (parser); - - return clauses; -} - -/* Returns the name of the next clause. If the clause is not - recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is - not consumed. Otherwise, the appropriate pragma_simd_clause is - returned and the token is consumed. */ - -static pragma_omp_clause -c_parser_cilk_clause_name (c_parser *parser) -{ - pragma_omp_clause result; - c_token *token = c_parser_peek_token (parser); - - if (!token->value || token->type != CPP_NAME) - return PRAGMA_CILK_CLAUSE_NONE; - - const char *p = IDENTIFIER_POINTER (token->value); - - if (!strcmp (p, "vectorlength")) - result = PRAGMA_CILK_CLAUSE_VECTORLENGTH; - else if (!strcmp (p, "linear")) - result = PRAGMA_CILK_CLAUSE_LINEAR; - else if (!strcmp (p, "private")) - result = PRAGMA_CILK_CLAUSE_PRIVATE; - else if (!strcmp (p, "firstprivate")) - result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE; - else if (!strcmp (p, "lastprivate")) - result = PRAGMA_CILK_CLAUSE_LASTPRIVATE; - else if (!strcmp (p, "reduction")) - result = PRAGMA_CILK_CLAUSE_REDUCTION; - else - return PRAGMA_CILK_CLAUSE_NONE; - - c_parser_consume_token (parser); - return result; -} - -/* Parse all #<pragma simd> clauses. Return the list of clauses - found. */ - -static tree -c_parser_cilk_all_clauses (c_parser *parser) -{ - tree clauses = NULL; - - while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) - { - pragma_omp_clause c_kind; - - c_kind = c_parser_cilk_clause_name (parser); - - switch (c_kind) - { - case PRAGMA_CILK_CLAUSE_VECTORLENGTH: - clauses = c_parser_cilk_clause_vectorlength (parser, clauses, false); - break; - case PRAGMA_CILK_CLAUSE_LINEAR: - clauses = c_parser_cilk_clause_linear (parser, clauses); - break; - case PRAGMA_CILK_CLAUSE_PRIVATE: - /* Use the OpenMP counterpart. */ - clauses = c_parser_omp_clause_private (parser, clauses); - break; - case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE: - /* Use the OpenMP counterpart. */ - clauses = c_parser_omp_clause_firstprivate (parser, clauses); - break; - case PRAGMA_CILK_CLAUSE_LASTPRIVATE: - /* Use the OpenMP counterpart. */ - clauses = c_parser_omp_clause_lastprivate (parser, clauses); - break; - case PRAGMA_CILK_CLAUSE_REDUCTION: - /* Use the OpenMP counterpart. */ - clauses = c_parser_omp_clause_reduction (parser, clauses); - break; - default: - c_parser_error (parser, "expected %<#pragma simd%> clause"); - goto saw_error; - } - } - - saw_error: - c_parser_skip_to_pragma_eol (parser); - return c_finish_omp_clauses (clauses, C_ORT_CILK); -} - -/* This function helps parse the grainsize pragma for a _Cilk_for statement. - Here is the correct syntax of this pragma: - #pragma cilk grainsize = <EXP> - */ - -static void -c_parser_cilk_grainsize (c_parser *parser, bool *if_p) -{ - extern tree convert_to_integer (tree, tree); - - /* consume the 'grainsize' keyword. */ - c_parser_consume_pragma (parser); - - if (c_parser_require (parser, CPP_EQ, "expected %<=%>") != 0) - { - struct c_expr g_expr = c_parser_binary_expression (parser, NULL, NULL); - if (g_expr.value == error_mark_node) - { - c_parser_skip_to_pragma_eol (parser); - return; - } - tree grain = convert_to_integer (long_integer_type_node, - c_fully_fold (g_expr.value, false, - NULL)); - c_parser_skip_to_pragma_eol (parser); - c_token *token = c_parser_peek_token (parser); - if (token && token->type == CPP_KEYWORD - && token->keyword == RID_CILK_FOR) - { - if (grain == NULL_TREE || grain == error_mark_node) - grain = integer_zero_node; - c_parser_cilk_for (parser, grain, if_p); - } - else - warning (0, "%<#pragma cilk grainsize%> is not followed by " - "%<_Cilk_for%>"); - } - else - c_parser_skip_to_pragma_eol (parser); -} - -/* Main entry point for parsing Cilk Plus <#pragma simd> for loops. */ - -static void -c_parser_cilk_simd (c_parser *parser, bool *if_p) -{ - tree clauses = c_parser_cilk_all_clauses (parser); - tree block = c_begin_compound_stmt (true); - location_t loc = c_parser_peek_token (parser)->location; - c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL, if_p); - block = c_end_compound_stmt (loc, block, true); - add_stmt (block); -} - -/* Create an artificial decl with TYPE and emit initialization of it with - INIT. */ - -static tree -c_get_temp_regvar (tree type, tree init) -{ - location_t loc = EXPR_LOCATION (init); - tree decl = build_decl (loc, VAR_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; - pushdecl (decl); - tree t = build2 (INIT_EXPR, type, decl, init); - add_stmt (t); - return decl; -} - -/* Main entry point for parsing Cilk Plus _Cilk_for loops. - GRAIN is the grain value passed in through pragma or 0. */ - -static void -c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p) -{ - tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE); - OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR; - OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain; - clauses = c_finish_omp_clauses (clauses, C_ORT_CILK); - - tree block = c_begin_compound_stmt (true); - tree sb = push_stmt_list (); - location_t loc = c_parser_peek_token (parser)->location; - tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL, - if_p); - sb = pop_stmt_list (sb); - - if (omp_for) - { - tree omp_par = make_node (OMP_PARALLEL); - TREE_TYPE (omp_par) = void_type_node; - OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE; - tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); - TREE_SIDE_EFFECTS (bind) = 1; - BIND_EXPR_BODY (bind) = sb; - OMP_PARALLEL_BODY (omp_par) = bind; - if (OMP_FOR_PRE_BODY (omp_for)) - { - add_stmt (OMP_FOR_PRE_BODY (omp_for)); - OMP_FOR_PRE_BODY (omp_for) = NULL_TREE; - } - tree init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0); - tree decl = TREE_OPERAND (init, 0); - tree cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0); - tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); - tree t = TREE_OPERAND (cond, 1), c, clauses = NULL_TREE; - if (TREE_CODE (t) != INTEGER_CST) - { - TREE_OPERAND (cond, 1) = c_get_temp_regvar (TREE_TYPE (t), t); - c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1); - OMP_CLAUSE_CHAIN (c) = clauses; - clauses = c; - } - if (TREE_CODE (incr) == MODIFY_EXPR) - { - t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); - if (TREE_CODE (t) != INTEGER_CST) - { - TREE_OPERAND (TREE_OPERAND (incr, 1), 1) - = c_get_temp_regvar (TREE_TYPE (t), t); - c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); - OMP_CLAUSE_CHAIN (c) = clauses; - clauses = c; - } - } - t = TREE_OPERAND (init, 1); - if (TREE_CODE (t) != INTEGER_CST) - { - TREE_OPERAND (init, 1) = c_get_temp_regvar (TREE_TYPE (t), t); - c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1); - OMP_CLAUSE_CHAIN (c) = clauses; - clauses = c; - } - c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); - OMP_CLAUSE_DECL (c) = decl; - OMP_CLAUSE_CHAIN (c) = clauses; - clauses = c; - c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_); - OMP_CLAUSE_OPERAND (c, 0) - = cilk_for_number_of_iterations (omp_for); - OMP_CLAUSE_CHAIN (c) = clauses; - OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, C_ORT_CILK); - add_stmt (omp_par); - } - - block = c_end_compound_stmt (loc, block, true); - add_stmt (block); -} - - + /* Parse a transaction attribute (GCC Extension). transaction-attribute: @@ -18689,7 +18783,7 @@ else { error: - ret.value = error_mark_node; + ret.set_error (); ret.original_code = ERROR_MARK; ret.original_type = NULL; } @@ -18794,145 +18888,6 @@ the_parser = NULL; } -/* This function parses Cilk Plus array notation. The starting index is - passed in INITIAL_INDEX and the array name is passes in ARRAY_VALUE. The - return value of this function is a tree_node called VALUE_TREE of type - ARRAY_NOTATION_REF. */ - -static tree -c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, - tree array_value) -{ - c_token *token = NULL; - tree start_index = NULL_TREE, end_index = NULL_TREE, stride = NULL_TREE; - tree value_tree = NULL_TREE, type = NULL_TREE, array_type = NULL_TREE; - tree array_type_domain = NULL_TREE; - - if (array_value == error_mark_node || initial_index == error_mark_node) - { - /* No need to continue. If either of these 2 were true, then an error - must be emitted already. Thus, no need to emit them twice. */ - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - - array_type = TREE_TYPE (array_value); - gcc_assert (array_type); - if (TREE_CODE (array_type) != ARRAY_TYPE - && TREE_CODE (array_type) != POINTER_TYPE) - { - error_at (loc, "base of array section must be pointer or array type"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - type = TREE_TYPE (array_type); - token = c_parser_peek_token (parser); - - if (token->type == CPP_EOF) - { - c_parser_error (parser, "expected %<:%> or numeral"); - return value_tree; - } - else if (token->type == CPP_COLON) - { - if (!initial_index) - { - /* If we are here, then we have a case like this A[:]. */ - c_parser_consume_token (parser); - if (TREE_CODE (array_type) == POINTER_TYPE) - { - error_at (loc, "start-index and length fields necessary for " - "using array notations in pointers"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - if (TREE_CODE (array_type) == FUNCTION_TYPE) - { - error_at (loc, "array notations cannot be used with function " - "type"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - array_type_domain = TYPE_DOMAIN (array_type); - - if (!array_type_domain) - { - error_at (loc, "start-index and length fields necessary for " - "using array notations in dimensionless arrays"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - - start_index = TYPE_MIN_VALUE (array_type_domain); - start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, - start_index); - if (!TYPE_MAX_VALUE (array_type_domain) - || !TREE_CONSTANT (TYPE_MAX_VALUE (array_type_domain))) - { - error_at (loc, "start-index and length fields necessary for " - "using array notations in variable-length arrays"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - end_index = TYPE_MAX_VALUE (array_type_domain); - end_index = fold_build2 (PLUS_EXPR, TREE_TYPE (end_index), - end_index, integer_one_node); - end_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, end_index); - stride = build_int_cst (integer_type_node, 1); - stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride); - } - else if (initial_index != error_mark_node) - { - /* If we are here, then there should be 2 possibilities: - 1. Array [EXPR : EXPR] - 2. Array [EXPR : EXPR : EXPR] - */ - start_index = initial_index; - - if (TREE_CODE (array_type) == FUNCTION_TYPE) - { - error_at (loc, "array notations cannot be used with function " - "type"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return error_mark_node; - } - c_parser_consume_token (parser); /* consume the ':' */ - struct c_expr ce = c_parser_expression (parser); - ce = convert_lvalue_to_rvalue (loc, ce, false, false); - end_index = ce.value; - if (!end_index || end_index == error_mark_node) - { - c_parser_skip_to_end_of_block_or_statement (parser); - return error_mark_node; - } - if (c_parser_peek_token (parser)->type == CPP_COLON) - { - c_parser_consume_token (parser); - ce = c_parser_expression (parser); - ce = convert_lvalue_to_rvalue (loc, ce, false, false); - stride = ce.value; - if (!stride || stride == error_mark_node) - { - c_parser_skip_to_end_of_block_or_statement (parser); - return error_mark_node; - } - } - } - else - c_parser_error (parser, "expected array notation expression"); - } - else - c_parser_error (parser, "expected array notation expression"); - - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); - - value_tree = build_array_notation_ref (loc, array_value, start_index, - end_index, stride, type); - if (value_tree != error_mark_node) - SET_EXPR_LOCATION (value_tree, loc); - return value_tree; -} - /* Parse the body of a function declaration marked with "__RTL". The RTL parser works on the level of characters read from a