summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog26
-rw-r--r--gcc/cp/Make-lang.in1
-rw-r--r--gcc/cp/cp-cilkplus.c77
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/parser.c619
-rw-r--r--gcc/cp/parser.h1
-rw-r--r--gcc/cp/pt.c1
-rw-r--r--gcc/cp/typeck2.c2
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);
}