diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/cp/cp-cilkplus.c | 77 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 619 | ||||
-rw-r--r-- | gcc/cp/parser.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 1 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
8 files changed, 577 insertions, 153 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b252637421f..2a16220dda2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2013-11-15 Aldy Hernandez <aldyh@redhat.com> + + * Make-lang.in (CXX_AND_OBJCXX_OBJS): Depend on cp/cp-cilkplus.o. + * cp-cilkplus.c: New file. + * cp-tree.h (cpp_validate_cilk_plus_loop): Protoize. + * parser.c (cp_parser_cilk_simd): New. + (cp_debug_parser): Add case for IN_CILK_SIMD_FOR. + (cp_parser_jump_statement): Same. + (cp_parser_omp_for_cond): Add new argument. + Add case for NE_EXPR. + (cp_parser_omp_for_loop): Pass new argument to + cp_parser_omp_for_cond. + Handle CILK_SIMD nodes. + Abstract initilization code to.. + (cp_parser_omp_for_loop_init): ...here. + (cp_parser_pragma): Add case for PRAGMA_CILK_SIMD. + (cp_parser_cilk_simd_vectorlength): New. + (cp_parser_cilk_simd_linear): New. + (cp_parser_cilk_simd_clause_name): New. + (cp_parser_cilk_simd_all_clauses): New. + (cp_parser_cilk_simd): New. + * parser.h (IN_CILK_SIMD_FOR): New macro. + * pt.c (tsubst_expr): Add case for CILK_SIMD. + * typeck2.c (cxx_readonly_error): Pass location argument to + readonly_error. + 2013-11-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/57887 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 9bcea20bd02..424f2e6cdc5 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -76,6 +76,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \ + cp/cp-cilkplus.o \ cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o \ cp/vtable-class-hierarchy.o $(CXX_C_OBJS) diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c new file mode 100644 index 00000000000..5c1090a097f --- /dev/null +++ b/gcc/cp/cp-cilkplus.c @@ -0,0 +1,77 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + This file contains routines to handle Cilk Plus specific + routines for the C++ Compiler. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Aldy Hernandez <aldyh@redhat.com>. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "cp-tree.h" +#include "diagnostic-core.h" + + +/* Callback for cp_walk_tree to validate the body of a pragma simd loop + or _cilk_for loop. + + This function is passed in as a function pointer to walk_tree. *TP is + the current tree pointer, *WALK_SUBTREES is set to 0 by this function if + recursing into TP's subtrees is unnecessary. *DATA is a bool variable that + is set to false if an error has occured. */ + +static tree +cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data) +{ + bool *valid = (bool *) data; + location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) : + UNKNOWN_LOCATION; + + if (!tp || !*tp) + return NULL_TREE; + + if (TREE_CODE (*tp) == THROW_EXPR) + { + error_at (loc, "throw expressions are not allowed inside loops " + "marked with pragma simd"); + *walk_subtrees = 0; + *valid = false; + } + else if (TREE_CODE (*tp) == TRY_BLOCK) + { + error_at (loc, "try statements are not allowed inside loops marked " + "with #pragma simd"); + *valid = false; + *walk_subtrees = 0; + } + return NULL_TREE; +} + + +/* Walks through all the subtrees of BODY using walk_tree to make sure + invalid statements/expressions are not found inside BODY. Returns + false if any invalid statements are found. */ + +bool +cpp_validate_cilk_plus_loop (tree body) +{ + bool valid = true; + cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux, + (void *) &valid, NULL); + return valid; +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e30922ab43a..4e26bd501b4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6177,6 +6177,9 @@ extern void vtv_save_class_info (tree); extern void vtv_recover_class_info (void); extern void vtv_build_vtable_verify_fndecl (void); +/* In cp-cilkplus.c. */ +extern bool cpp_validate_cilk_plus_loop (tree); + /* In cp/cp-array-notations.c */ extern tree expand_array_notation_exprs (tree); bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ab3325794d1..27f10543b82 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -233,6 +233,8 @@ static void cp_parser_initial_pragma static tree cp_literal_operator_id (const char *); +static void cp_parser_cilk_simd + (cp_parser *, cp_token *); static bool cp_parser_omp_declare_reduction_exprs (tree, cp_parser *); @@ -531,6 +533,8 @@ cp_debug_parser (FILE *file, cp_parser *parser) parser->in_statement & IN_SWITCH_STMT); cp_debug_print_flag (file, "Parsing a structured OpenMP block", parser->in_statement & IN_OMP_BLOCK); + cp_debug_print_flag (file, "Parsing a Cilk Plus for loop", + parser->in_statement & IN_CILK_SIMD_FOR); cp_debug_print_flag (file, "Parsing a an OpenMP loop", parser->in_statement & IN_OMP_FOR); cp_debug_print_flag (file, "Parsing an if statement", @@ -10558,6 +10562,9 @@ cp_parser_jump_statement (cp_parser* parser) case IN_OMP_FOR: error_at (token->location, "break statement used with OpenMP for loop"); break; + case IN_CILK_SIMD_FOR: + error_at (token->location, "break statement used with Cilk Plus for loop"); + break; } cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); break; @@ -10568,6 +10575,10 @@ cp_parser_jump_statement (cp_parser* parser) case 0: error_at (token->location, "continue statement not within a loop"); break; + case IN_CILK_SIMD_FOR: + error_at (token->location, + "continue statement within %<#pragma simd%> loop body"); + /* Fall through. */ case IN_ITERATION_STMT: case IN_OMP_FOR: statement = finish_continue_stmt (); @@ -28591,7 +28602,7 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) /* Helper function, to parse omp for increment expression. */ static tree -cp_parser_omp_for_cond (cp_parser *parser, tree decl) +cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code) { tree cond = cp_parser_binary_expression (parser, false, true, PREC_NOT_OPERATOR, NULL); @@ -28609,6 +28620,10 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl) case LT_EXPR: case LE_EXPR: break; + case NE_EXPR: + if (code == CILK_SIMD) + break; + /* Fall through: OpenMP disallows NE_EXPR. */ default: return error_mark_node; } @@ -28718,6 +28733,186 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl) return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs); } +/* Parse the initialization statement of either an OpenMP for loop or + a Cilk Plus for loop. + + PARSING_OPENMP is true if parsing OpenMP, or false if parsing Cilk + Plus. + + Return true if the resulting construct should have an + OMP_CLAUSE_PRIVATE added to it. */ + +static bool +cp_parser_omp_for_loop_init (cp_parser *parser, + bool parsing_openmp, + tree &this_pre_body, + vec<tree, va_gc> *for_block, + tree &init, + tree &decl, + tree &real_decl) +{ + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + return false; + + bool add_private_clause = false; + + /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too): + + init-expr: + var = lb + integer-type var = lb + random-access-iterator-type var = lb + pointer-type var = lb + */ + cp_decl_specifier_seq type_specifiers; + + /* First, try to parse as an initialized declaration. See + cp_parser_condition, from whence the bulk of this is copied. */ + + cp_parser_parse_tentatively (parser); + cp_parser_type_specifier_seq (parser, /*is_declaration=*/true, + /*is_trailing_return=*/false, + &type_specifiers); + if (cp_parser_parse_definitely (parser)) + { + /* If parsing a type specifier seq succeeded, then this + MUST be a initialized declaration. */ + tree asm_specification, attributes; + cp_declarator *declarator; + + declarator = cp_parser_declarator (parser, + CP_PARSER_DECLARATOR_NAMED, + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + attributes = cp_parser_attributes_opt (parser); + asm_specification = cp_parser_asm_specification_opt (parser); + + if (declarator == cp_error_declarator) + cp_parser_skip_to_end_of_statement (parser); + + else + { + tree pushed_scope, auto_node; + + decl = start_decl (declarator, &type_specifiers, + SD_INITIALIZED, attributes, + /*prefix_attributes=*/NULL_TREE, + &pushed_scope); + + auto_node = type_uses_auto (TREE_TYPE (decl)); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)) + { + if (cp_lexer_next_token_is (parser->lexer, + CPP_OPEN_PAREN)) + { + if (parsing_openmp) + error ("parenthesized initialization is not allowed in " + "OpenMP %<for%> loop"); + else + error ("parenthesized initialization is " + "not allowed in for-loop"); + } + else + /* Trigger an error. */ + cp_parser_require (parser, CPP_EQ, RT_EQ); + + init = error_mark_node; + cp_parser_skip_to_end_of_statement (parser); + } + else if (CLASS_TYPE_P (TREE_TYPE (decl)) + || type_dependent_expression_p (decl) + || auto_node) + { + bool is_direct_init, is_non_constant_init; + + init = cp_parser_initializer (parser, + &is_direct_init, + &is_non_constant_init); + + if (auto_node) + { + TREE_TYPE (decl) + = do_auto_deduction (TREE_TYPE (decl), init, + auto_node); + + if (!CLASS_TYPE_P (TREE_TYPE (decl)) + && !type_dependent_expression_p (decl)) + goto non_class; + } + + cp_finish_decl (decl, init, !is_non_constant_init, + asm_specification, + LOOKUP_ONLYCONVERTING); + if (CLASS_TYPE_P (TREE_TYPE (decl))) + { + vec_safe_push (for_block, this_pre_body); + init = NULL_TREE; + } + else + init = pop_stmt_list (this_pre_body); + this_pre_body = NULL_TREE; + } + else + { + /* Consume '='. */ + cp_lexer_consume_token (parser->lexer); + init = cp_parser_assignment_expression (parser, false, NULL); + + non_class: + if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) + init = error_mark_node; + else + cp_finish_decl (decl, NULL_TREE, + /*init_const_expr_p=*/false, + asm_specification, + LOOKUP_ONLYCONVERTING); + } + + if (pushed_scope) + pop_scope (pushed_scope); + } + } + else + { + cp_id_kind idk; + /* If parsing a type specifier sequence failed, then + this MUST be a simple expression. */ + cp_parser_parse_tentatively (parser); + decl = cp_parser_primary_expression (parser, false, false, + false, &idk); + if (!cp_parser_error_occurred (parser) + && decl + && DECL_P (decl) + && CLASS_TYPE_P (TREE_TYPE (decl))) + { + tree rhs; + + cp_parser_parse_definitely (parser); + cp_parser_require (parser, CPP_EQ, RT_EQ); + rhs = cp_parser_assignment_expression (parser, false, NULL); + finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs), + decl, NOP_EXPR, + rhs, + tf_warning_or_error)); + add_private_clause = true; + } + else + { + decl = NULL; + cp_parser_abort_tentative_parse (parser); + init = cp_parser_expression (parser, false, NULL); + if (init) + { + if (TREE_CODE (init) == MODIFY_EXPR + || TREE_CODE (init) == MODOP_EXPR) + real_decl = TREE_OPERAND (init, 0); + } + } + } + return add_private_clause; +} + /* Parse the restricted form of the for statement allowed by OpenMP. */ static tree @@ -28763,157 +28958,13 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, init = decl = real_decl = NULL; this_pre_body = push_stmt_list (); - if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) - { - /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too): - - init-expr: - var = lb - integer-type var = lb - random-access-iterator-type var = lb - pointer-type var = lb - */ - cp_decl_specifier_seq type_specifiers; - - /* First, try to parse as an initialized declaration. See - cp_parser_condition, from whence the bulk of this is copied. */ - cp_parser_parse_tentatively (parser); - cp_parser_type_specifier_seq (parser, /*is_declaration=*/true, - /*is_trailing_return=*/false, - &type_specifiers); - if (cp_parser_parse_definitely (parser)) - { - /* If parsing a type specifier seq succeeded, then this - MUST be a initialized declaration. */ - tree asm_specification, attributes; - cp_declarator *declarator; + add_private_clause + |= cp_parser_omp_for_loop_init (parser, + /*parsing_openmp=*/code != CILK_SIMD, + this_pre_body, for_block, + init, decl, real_decl); - declarator = cp_parser_declarator (parser, - CP_PARSER_DECLARATOR_NAMED, - /*ctor_dtor_or_conv_p=*/NULL, - /*parenthesized_p=*/NULL, - /*member_p=*/false); - attributes = cp_parser_attributes_opt (parser); - asm_specification = cp_parser_asm_specification_opt (parser); - - if (declarator == cp_error_declarator) - cp_parser_skip_to_end_of_statement (parser); - - else - { - tree pushed_scope, auto_node; - - decl = start_decl (declarator, &type_specifiers, - SD_INITIALIZED, attributes, - /*prefix_attributes=*/NULL_TREE, - &pushed_scope); - - auto_node = type_uses_auto (TREE_TYPE (decl)); - if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)) - { - if (cp_lexer_next_token_is (parser->lexer, - CPP_OPEN_PAREN)) - error ("parenthesized initialization is not allowed in " - "OpenMP %<for%> loop"); - else - /* Trigger an error. */ - cp_parser_require (parser, CPP_EQ, RT_EQ); - - init = error_mark_node; - cp_parser_skip_to_end_of_statement (parser); - } - else if (CLASS_TYPE_P (TREE_TYPE (decl)) - || type_dependent_expression_p (decl) - || auto_node) - { - bool is_direct_init, is_non_constant_init; - - init = cp_parser_initializer (parser, - &is_direct_init, - &is_non_constant_init); - - if (auto_node) - { - TREE_TYPE (decl) - = do_auto_deduction (TREE_TYPE (decl), init, - auto_node); - - if (!CLASS_TYPE_P (TREE_TYPE (decl)) - && !type_dependent_expression_p (decl)) - goto non_class; - } - - cp_finish_decl (decl, init, !is_non_constant_init, - asm_specification, - LOOKUP_ONLYCONVERTING); - if (CLASS_TYPE_P (TREE_TYPE (decl))) - { - vec_safe_push (for_block, this_pre_body); - init = NULL_TREE; - } - else - init = pop_stmt_list (this_pre_body); - this_pre_body = NULL_TREE; - } - else - { - /* Consume '='. */ - cp_lexer_consume_token (parser->lexer); - init = cp_parser_assignment_expression (parser, false, NULL); - - non_class: - if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) - init = error_mark_node; - else - cp_finish_decl (decl, NULL_TREE, - /*init_const_expr_p=*/false, - asm_specification, - LOOKUP_ONLYCONVERTING); - } - - if (pushed_scope) - pop_scope (pushed_scope); - } - } - else - { - cp_id_kind idk; - /* If parsing a type specifier sequence failed, then - this MUST be a simple expression. */ - cp_parser_parse_tentatively (parser); - decl = cp_parser_primary_expression (parser, false, false, - false, &idk); - if (!cp_parser_error_occurred (parser) - && decl - && DECL_P (decl) - && CLASS_TYPE_P (TREE_TYPE (decl))) - { - tree rhs; - - cp_parser_parse_definitely (parser); - cp_parser_require (parser, CPP_EQ, RT_EQ); - rhs = cp_parser_assignment_expression (parser, false, NULL); - finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs), - decl, NOP_EXPR, - rhs, - tf_warning_or_error)); - add_private_clause = true; - } - else - { - decl = NULL; - cp_parser_abort_tentative_parse (parser); - init = cp_parser_expression (parser, false, NULL); - if (init) - { - if (TREE_CODE (init) == MODIFY_EXPR - || TREE_CODE (init) == MODOP_EXPR) - real_decl = TREE_OPERAND (init, 0); - } - } - } - } cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); if (this_pre_body) { @@ -29002,7 +29053,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, cond = NULL; if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) - cond = cp_parser_omp_for_cond (parser, decl); + cond = cp_parser_omp_for_cond (parser, decl, code); cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); incr = NULL; @@ -29072,7 +29123,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, /* Note that we saved the original contents of this flag when we entered the structured block, and so we don't need to re-save it here. */ - parser->in_statement = IN_OMP_FOR; + if (code == CILK_SIMD) + parser->in_statement = IN_CILK_SIMD_FOR; + else + parser->in_statement = IN_OMP_FOR; /* Note that the grammar doesn't call for a structured block here, though the loop as a whole is a structured block. */ @@ -31127,6 +31181,16 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) return true; } + case PRAGMA_CILK_SIMD: + if (context == pragma_external) + { + error_at (pragma_tok->location, + "%<#pragma simd%> must be inside a function"); + break; + } + cp_parser_cilk_simd (parser, pragma_tok); + return true; + default: gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); c_invoke_pragma_handler (id); @@ -31192,6 +31256,257 @@ c_parse_file (void) the_parser = NULL; } +/* Parses the Cilk Plus #pragma simd vectorlength clause: + Syntax: + vectorlength ( constant-expression ) */ + +static tree +cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses) +{ + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + tree expr; + /* The vectorlength clause behaves exactly like OpenMP's safelen + clause. Thus, vectorlength is represented as OMP 4.0 + safelen. */ + check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc); + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + return error_mark_node; + + expr = cp_parser_constant_expression (parser, false, NULL); + expr = maybe_constant_value (expr); + + if (TREE_CONSTANT (expr) + && exact_log2 (TREE_INT_CST_LOW (expr)) == -1) + error_at (loc, "vectorlength must be a power of 2"); + else if (expr != error_mark_node) + { + tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (c) = expr; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + return error_mark_node; + return clauses; +} + +/* Handles the Cilk Plus #pragma simd linear clause. + Syntax: + 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 +cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses) +{ + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + return clauses; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + { + cp_parser_error (parser, "expected identifier"); + cp_parser_skip_to_closing_parenthesis (parser, false, false, true); + return error_mark_node; + } + + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + parser->colon_corrects_to_scope_p = false; + while (1) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + { + cp_parser_error (parser, "expected variable-name"); + clauses = error_mark_node; + break; + } + + tree var_name = cp_parser_id_expression (parser, false, true, NULL, + false, false); + tree decl = cp_parser_lookup_name_simple (parser, var_name, + token->location); + if (decl == error_mark_node) + { + cp_parser_name_lookup_error (parser, var_name, decl, NLE_NULL, + token->location); + clauses = error_mark_node; + } + else + { + tree e = NULL_TREE; + tree step_size = integer_one_node; + + /* If present, parse the linear step. Otherwise, assume the default + value of 1. */ + if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + cp_lexer_consume_token (parser->lexer); + + e = cp_parser_assignment_expression (parser, false, NULL); + e = maybe_constant_value (e); + + if (e == error_mark_node) + { + /* If an error has occurred, then the whole pragma is + considered ill-formed. Thus, no reason to keep + parsing. */ + clauses = error_mark_node; + break; + } + else if (type_dependent_expression_p (e) + || value_dependent_expression_p (e) + || (TREE_TYPE (e) + && INTEGRAL_TYPE_P (TREE_TYPE (e)) + && (TREE_CONSTANT (e) + || DECL_P (e)))) + step_size = e; + else + cp_parser_error (parser, + "step size must be an integer constant " + "expression or an integer variable"); + } + + /* Use the OMP_CLAUSE_LINEAR, which has the same semantics. */ + tree l = build_omp_clause (loc, OMP_CLAUSE_LINEAR); + OMP_CLAUSE_DECL (l) = decl; + OMP_CLAUSE_LINEAR_STEP (l) = step_size; + OMP_CLAUSE_CHAIN (l) = clauses; + clauses = l; + } + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) + break; + else + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "expected %<,%> or %<)%> after %qE", decl); + clauses = error_mark_node; + break; + } + } + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + cp_parser_skip_to_closing_parenthesis (parser, false, false, true); + return clauses; +} + +/* Returns the name of the next clause. If the clause is not + recognized, then PRAGMA_CILK_CLAUSE_NONE is returned and the next + token is not consumed. Otherwise, the appropriate enum from the + pragma_simd_clause is returned and the token is consumed. */ + +static pragma_cilk_clause +cp_parser_cilk_simd_clause_name (cp_parser *parser) +{ + pragma_cilk_clause clause_type; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->keyword == RID_PRIVATE) + clause_type = PRAGMA_CILK_CLAUSE_PRIVATE; + else if (!token->u.value || token->type != CPP_NAME) + return PRAGMA_CILK_CLAUSE_NONE; + else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "vectorlength")) + clause_type = PRAGMA_CILK_CLAUSE_VECTORLENGTH; + else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "linear")) + clause_type = PRAGMA_CILK_CLAUSE_LINEAR; + else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "firstprivate")) + clause_type = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE; + else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "lastprivate")) + clause_type = PRAGMA_CILK_CLAUSE_LASTPRIVATE; + else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "reduction")) + clause_type = PRAGMA_CILK_CLAUSE_REDUCTION; + else + return PRAGMA_CILK_CLAUSE_NONE; + + cp_lexer_consume_token (parser->lexer); + return clause_type; +} + +/* Parses all the #pragma simd clauses. Returns a list of clauses found. */ + +static tree +cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token) +{ + tree clauses = NULL_TREE; + + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL) + && clauses != error_mark_node) + { + pragma_cilk_clause c_kind; + c_kind = cp_parser_cilk_simd_clause_name (parser); + if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH) + clauses = cp_parser_cilk_simd_vectorlength (parser, clauses); + else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR) + clauses = cp_parser_cilk_simd_linear (parser, clauses); + else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE) + /* Use the OpenMP 4.0 equivalent function. */ + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses); + else if (c_kind == PRAGMA_CILK_CLAUSE_FIRSTPRIVATE) + /* Use the OpenMP 4.0 equivalent function. */ + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE, + clauses); + else if (c_kind == PRAGMA_CILK_CLAUSE_LASTPRIVATE) + /* Use the OMP 4.0 equivalent function. */ + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE, + clauses); + else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION) + /* Use the OMP 4.0 equivalent function. */ + clauses = cp_parser_omp_clause_reduction (parser, clauses); + else + { + clauses = error_mark_node; + cp_parser_error (parser, "expected %<#pragma simd%> clause"); + break; + } + } + + cp_parser_skip_to_pragma_eol (parser, pragma_token); + + if (clauses == error_mark_node) + return error_mark_node; + else + return c_finish_cilk_clauses (clauses); +} + +/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops. */ + +static void +cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token) +{ + tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token); + + if (clauses == error_mark_node) + return; + + if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR)) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "for statement expected"); + return; + } + + tree sb = begin_omp_structured_block (); + int save = cp_parser_begin_omp_structured_block (parser); + tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL); + if (ret) + cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret)); + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + return; +} + /* Create an identifier for a generic parameter type (a synthesized template parameter implied by `auto' or a concept identifier). */ diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 1024024d42d..edd4e6e8b98 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -300,6 +300,7 @@ typedef struct GTY(()) cp_parser { #define IN_OMP_BLOCK 4 #define IN_OMP_FOR 8 #define IN_IF_STMT 16 +#define IN_CILK_SIMD_FOR 32 unsigned char in_statement; /* TRUE if we are presently parsing the body of a switch statement. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e714e790ead..3bc8ccb0ee3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13566,6 +13566,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case OMP_FOR: case OMP_SIMD: + case CILK_SIMD: case OMP_DISTRIBUTE: { tree clauses, body, pre_body; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 9da8e3de844..5c4fdfa0162 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -125,7 +125,7 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring) "read-only reference %qD"), TREE_OPERAND (arg, 0)); else - readonly_error (arg, errstring); + readonly_error (input_location, arg, errstring); } |