aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog30
-rw-r--r--gcc/cp/cp-gimplify.c44
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/parser.c391
-rw-r--r--gcc/cp/pt.c58
-rw-r--r--gcc/cp/semantics.c75
6 files changed, 540 insertions, 63 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 65d0e7c..bc972a2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,33 @@
+2011-08-02 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (finish_omp_atomic): Adjust prototype.
+ (cxx_omp_const_qual_no_mutable): New prototype.
+ (finish_omp_taskyield): New prototype.
+ * parser.c (cp_parser_omp_atomic): (cp_parser_omp_atomic): Handle
+ parsing OpenMP 3.1 atomics. Adjust finish_omp_atomic caller.
+ (cp_parser_omp_clause_name): Handle final and mergeable clauses.
+ (cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New
+ functions.
+ (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
+ and PRAGMA_OMP_CLAUSE_MERGEABLE.
+ (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
+ (cp_parser_omp_taskyield): New function.
+ (cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
+ (cp_parser_omp_clause_reduction): Handle min and max.
+ * pt.c (tsubst_expr) <case OMP_ATOMIC>: Handle OpenMP 3.1 atomics.
+ (tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and
+ OMP_CLAUSE_MERGEABLE.
+ * semantics.c (finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1
+ arguments. Handle OpenMP 3.1 atomics. Adjust c_finish_omp_atomic
+ caller.
+ (finish_omp_clauses): Don't complain about const qualified
+ predetermined vars and static data members in firstprivate clause.
+ Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR
+ and MAX_EXPR.
+ (finish_omp_taskyield): New function.
+ * cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function.
+ (cxx_omp_predetermined_sharing): Use it.
+
2011-08-02 Jason Merrill <jason@redhat.com>
* call.c (build_call_a): Also check at_function_scope_p.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 2b4e70a..6aeae75 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1365,26 +1365,15 @@ cxx_omp_privatize_by_reference (const_tree decl)
return is_invisiref_parm (decl);
}
-/* True if OpenMP sharing attribute of DECL is predetermined. */
-
-enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+/* Return true if DECL is const qualified var having no mutable member. */
+bool
+cxx_omp_const_qual_no_mutable (tree decl)
{
- tree type;
-
- /* Static data members are predetermined as shared. */
- if (TREE_STATIC (decl))
- {
- tree ctx = CP_DECL_CONTEXT (decl);
- if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
- return OMP_CLAUSE_DEFAULT_SHARED;
- }
-
- type = TREE_TYPE (decl);
+ tree type = TREE_TYPE (decl);
if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (!is_invisiref_parm (decl))
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+ return false;
type = TREE_TYPE (type);
if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
@@ -1408,11 +1397,32 @@ cxx_omp_predetermined_sharing (tree decl)
}
if (type == error_mark_node)
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+ return false;
/* Variables with const-qualified type having no mutable member
are predetermined shared. */
if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
+ return true;
+
+ return false;
+}
+
+/* True if OpenMP sharing attribute of DECL is predetermined. */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+ /* Static data members are predetermined shared. */
+ if (TREE_STATIC (decl))
+ {
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
+ return OMP_CLAUSE_DEFAULT_SHARED;
+ }
+
+ /* Const qualified vars having no mutable member are predetermined
+ shared. */
+ if (cxx_omp_const_qual_no_mutable (decl))
return OMP_CLAUSE_DEFAULT_SHARED;
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fb17178..ff5509e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5454,10 +5454,12 @@ extern tree begin_omp_task (void);
extern tree finish_omp_task (tree, tree);
extern tree finish_omp_for (location_t, tree, tree,
tree, tree, tree, tree, tree);
-extern void finish_omp_atomic (enum tree_code, tree, tree);
+extern void finish_omp_atomic (enum tree_code, enum tree_code,
+ tree, tree, tree, tree, tree);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
+extern void finish_omp_taskyield (void);
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
@@ -5765,6 +5767,7 @@ extern void init_shadowed_var_for_decl (void);
extern int cp_gimplify_expr (tree *, gimple_seq *,
gimple_seq *);
extern void cp_genericize (tree);
+extern bool cxx_omp_const_qual_no_mutable (tree);
extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
extern tree cxx_omp_clause_default_ctor (tree, tree, tree);
extern tree cxx_omp_clause_copy_ctor (tree, tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3828ca9..576c842 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -23600,13 +23600,19 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
case 'f':
- if (!strcmp ("firstprivate", p))
+ if (!strcmp ("final", p))
+ result = PRAGMA_OMP_CLAUSE_FINAL;
+ else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
break;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
break;
+ case 'm':
+ if (!strcmp ("mergeable", p))
+ result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+ break;
case 'n':
if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -23836,6 +23842,34 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
return c;
}
+/* OpenMP 3.1:
+ final ( expression ) */
+
+static tree
+cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_condition (parser);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_FINAL);
+ OMP_CLAUSE_FINAL_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
/* OpenMP 2.5:
if ( expression ) */
@@ -23864,6 +23898,23 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
return c;
}
+/* OpenMP 3.1:
+ mergeable */
+
+static tree
+cp_parser_omp_clause_mergeable (cp_parser *parser ATTRIBUTE_UNUSED,
+ tree list, location_t location)
+{
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable",
+ location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
/* OpenMP 2.5:
nowait */
@@ -23931,7 +23982,12 @@ cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
reduction ( reduction-operator : variable-list )
reduction-operator:
- One of: + * - & ^ | && || */
+ One of: + * - & ^ | && ||
+
+ OpenMP 3.1:
+
+ reduction-operator:
+ One of: + * - & ^ | && || min max */
static tree
cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
@@ -23968,9 +24024,26 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
case CPP_OR_OR:
code = TRUTH_ORIF_EXPR;
break;
+ case CPP_NAME:
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "min") == 0)
+ {
+ code = MIN_EXPR;
+ break;
+ }
+ if (strcmp (p, "max") == 0)
+ {
+ code = MAX_EXPR;
+ break;
+ }
+ }
+ /* FALLTHROUGH */
default:
cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
- "%<|%>, %<&&%>, or %<||%>");
+ "%<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
resync_fail:
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
@@ -24143,6 +24216,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
token->location);
c_name = "default";
break;
+ case PRAGMA_OMP_CLAUSE_FINAL:
+ clauses = cp_parser_omp_clause_final (parser, clauses, token->location);
+ c_name = "final";
+ break;
case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
clauses);
@@ -24157,6 +24234,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
clauses);
c_name = "lastprivate";
break;
+ case PRAGMA_OMP_CLAUSE_MERGEABLE:
+ clauses = cp_parser_omp_clause_mergeable (parser, clauses,
+ token->location);
+ c_name = "mergeable";
+ break;
case PRAGMA_OMP_CLAUSE_NOWAIT:
clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
c_name = "nowait";
@@ -24267,34 +24349,140 @@ cp_parser_omp_structured_block (cp_parser *parser)
binop:
+, *, -, /, &, ^, |, <<, >>
- where x is an lvalue expression with scalar type. */
+ where x is an lvalue expression with scalar type.
+
+ OpenMP 3.1:
+ # pragma omp atomic new-line
+ update-stmt
+
+ # pragma omp atomic read new-line
+ read-stmt
+
+ # pragma omp atomic write new-line
+ write-stmt
+
+ # pragma omp atomic update new-line
+ update-stmt
+
+ # pragma omp atomic capture new-line
+ capture-stmt
+
+ # pragma omp atomic capture new-line
+ capture-block
+
+ read-stmt:
+ v = x
+ write-stmt:
+ x = expr
+ update-stmt:
+ expression-stmt | x = x binop expr
+ capture-stmt:
+ v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+ capture-block:
+ { v = x; update-stmt; } | { update-stmt; v = x; }
+
+ where x and v are lvalue expressions with scalar type. */
static void
cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
{
- tree lhs, rhs;
- enum tree_code code;
+ tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
+ tree rhs1 = NULL_TREE, orig_lhs;
+ enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+ bool structured_block = false;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (!strcmp (p, "read"))
+ code = OMP_ATOMIC_READ;
+ else if (!strcmp (p, "write"))
+ code = NOP_EXPR;
+ else if (!strcmp (p, "update"))
+ code = OMP_ATOMIC;
+ else if (!strcmp (p, "capture"))
+ code = OMP_ATOMIC_CAPTURE_NEW;
+ else
+ p = NULL;
+ if (p)
+ cp_lexer_consume_token (parser->lexer);
+ }
cp_parser_require_pragma_eol (parser, pragma_tok);
+ switch (code)
+ {
+ case OMP_ATOMIC_READ:
+ case NOP_EXPR: /* atomic write */
+ v = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ goto saw_error;
+ if (code == NOP_EXPR)
+ lhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ else
+ lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (lhs == error_mark_node)
+ goto saw_error;
+ if (code == NOP_EXPR)
+ {
+ /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+ opcode. */
+ code = OMP_ATOMIC;
+ rhs = lhs;
+ lhs = v;
+ v = NULL_TREE;
+ }
+ goto done;
+ case OMP_ATOMIC_CAPTURE_NEW:
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ structured_block = true;
+ }
+ else
+ {
+ v = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ goto saw_error;
+ }
+ default:
+ break;
+ }
+
+restart:
lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
/*cast_p=*/false, NULL);
+ orig_lhs = lhs;
switch (TREE_CODE (lhs))
{
case ERROR_MARK:
goto saw_error;
- case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ /* FALLTHROUGH */
+ case PREINCREMENT_EXPR:
lhs = TREE_OPERAND (lhs, 0);
- code = PLUS_EXPR;
+ opcode = PLUS_EXPR;
rhs = integer_one_node;
break;
- case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ /* FALLTHROUGH */
+ case PREDECREMENT_EXPR:
lhs = TREE_OPERAND (lhs, 0);
- code = MINUS_EXPR;
+ opcode = MINUS_EXPR;
rhs = integer_one_node;
break;
@@ -24312,48 +24500,123 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
case MODIFY_EXPR:
if (TREE_CODE (lhs) == MODIFY_EXPR
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
- {
- /* Undo effects of boolean_increment. */
- if (integer_onep (TREE_OPERAND (lhs, 1)))
- {
- /* This is pre or post increment. */
- rhs = TREE_OPERAND (lhs, 1);
- lhs = TREE_OPERAND (lhs, 0);
- code = NOP_EXPR;
- break;
- }
- }
+ {
+ /* Undo effects of boolean_increment. */
+ if (integer_onep (TREE_OPERAND (lhs, 1)))
+ {
+ /* This is pre or post increment. */
+ rhs = TREE_OPERAND (lhs, 1);
+ lhs = TREE_OPERAND (lhs, 0);
+ opcode = NOP_EXPR;
+ if (code == OMP_ATOMIC_CAPTURE_NEW
+ && !structured_block
+ && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ break;
+ }
+ }
/* FALLTHRU */
default:
switch (cp_lexer_peek_token (parser->lexer)->type)
{
case CPP_MULT_EQ:
- code = MULT_EXPR;
+ opcode = MULT_EXPR;
break;
case CPP_DIV_EQ:
- code = TRUNC_DIV_EXPR;
+ opcode = TRUNC_DIV_EXPR;
break;
case CPP_PLUS_EQ:
- code = PLUS_EXPR;
+ opcode = PLUS_EXPR;
break;
case CPP_MINUS_EQ:
- code = MINUS_EXPR;
+ opcode = MINUS_EXPR;
break;
case CPP_LSHIFT_EQ:
- code = LSHIFT_EXPR;
+ opcode = LSHIFT_EXPR;
break;
case CPP_RSHIFT_EQ:
- code = RSHIFT_EXPR;
+ opcode = RSHIFT_EXPR;
break;
case CPP_AND_EQ:
- code = BIT_AND_EXPR;
+ opcode = BIT_AND_EXPR;
break;
case CPP_OR_EQ:
- code = BIT_IOR_EXPR;
+ opcode = BIT_IOR_EXPR;
break;
case CPP_XOR_EQ:
- code = BIT_XOR_EXPR;
+ opcode = BIT_XOR_EXPR;
break;
+ case CPP_EQ:
+ if (structured_block || code == OMP_ATOMIC)
+ {
+ enum cp_parser_prec oprec;
+ cp_token *token;
+ cp_lexer_consume_token (parser->lexer);
+ rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (rhs1 == error_mark_node)
+ goto saw_error;
+ token = cp_lexer_peek_token (parser->lexer);
+ switch (token->type)
+ {
+ case CPP_SEMICOLON:
+ if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ v = lhs;
+ lhs = NULL_TREE;
+ lhs1 = rhs1;
+ rhs1 = NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ goto restart;
+ }
+ cp_parser_error (parser,
+ "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
+ case CPP_MULT:
+ opcode = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ opcode = TRUNC_DIV_EXPR;
+ break;
+ case CPP_PLUS:
+ opcode = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ opcode = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ opcode = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ opcode = RSHIFT_EXPR;
+ break;
+ case CPP_AND:
+ opcode = BIT_AND_EXPR;
+ break;
+ case CPP_OR:
+ opcode = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR:
+ opcode = BIT_XOR_EXPR;
+ break;
+ default:
+ cp_parser_error (parser,
+ "invalid operator for %<#pragma omp atomic%>");
+ goto saw_error;
+ }
+ oprec = TOKEN_PRECEDENCE (token);
+ gcc_assert (oprec != PREC_NOT_OPERATOR);
+ if (commutative_tree_code (opcode))
+ oprec = (enum cp_parser_prec) (oprec - 1);
+ cp_lexer_consume_token (parser->lexer);
+ rhs = cp_parser_binary_expression (parser, false, false,
+ oprec, NULL);
+ if (rhs == error_mark_node)
+ goto saw_error;
+ goto stmt_done;
+ }
+ /* FALLTHROUGH */
default:
cp_parser_error (parser,
"invalid operator for %<#pragma omp atomic%>");
@@ -24366,12 +24629,46 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
goto saw_error;
break;
}
- finish_omp_atomic (code, lhs, rhs);
- cp_parser_consume_semicolon_at_end_of_statement (parser);
+stmt_done:
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+ goto saw_error;
+ v = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (v == error_mark_node)
+ goto saw_error;
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ goto saw_error;
+ lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false, NULL);
+ if (lhs1 == error_mark_node)
+ goto saw_error;
+ }
+ if (structured_block)
+ {
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ }
+done:
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ if (!structured_block)
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
saw_error:
cp_parser_skip_to_end_of_block_or_statement (parser);
+ if (structured_block)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ cp_lexer_consume_token (parser->lexer);
+ else if (code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
}
@@ -25233,7 +25530,9 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
| (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
| (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+ | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
static tree
cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
@@ -25260,6 +25559,16 @@ cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
finish_omp_taskwait ();
}
+/* OpenMP 3.1:
+ # pragma omp taskyield new-line */
+
+static void
+cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ finish_omp_taskyield ();
+}
+
/* OpenMP 2.5:
# pragma omp threadprivate (variable-list) */
@@ -25435,6 +25744,22 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
}
break;
+ case PRAGMA_OMP_TASKYIELD:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_taskyield (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp taskyield%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_THREADPRIVATE:
cp_parser_omp_threadprivate (parser, pragma_tok);
return false;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a3cd956..3131e61 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12181,6 +12181,7 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_FINAL:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
@@ -12189,6 +12190,7 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
gcc_unreachable ();
@@ -12819,12 +12821,56 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_ATOMIC:
gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
- {
- tree op1 = TREE_OPERAND (t, 1);
- tree lhs = RECUR (TREE_OPERAND (op1, 0));
- tree rhs = RECUR (TREE_OPERAND (op1, 1));
- finish_omp_atomic (TREE_CODE (op1), lhs, rhs);
- }
+ if (TREE_CODE (TREE_OPERAND (t, 1)) != MODIFY_EXPR)
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree rhs1 = NULL_TREE;
+ tree lhs, rhs;
+ if (TREE_CODE (op1) == COMPOUND_EXPR)
+ {
+ rhs1 = RECUR (TREE_OPERAND (op1, 0));
+ op1 = TREE_OPERAND (op1, 1);
+ }
+ lhs = RECUR (TREE_OPERAND (op1, 0));
+ rhs = RECUR (TREE_OPERAND (op1, 1));
+ finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
+ NULL_TREE, NULL_TREE, rhs1);
+ }
+ else
+ {
+ tree op1 = TREE_OPERAND (t, 1);
+ tree v = NULL_TREE, lhs, rhs = NULL_TREE, lhs1 = NULL_TREE;
+ tree rhs1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (TREE_OPERAND (op1, 1));
+ enum tree_code opcode = NOP_EXPR;
+ if (code == OMP_ATOMIC_READ)
+ {
+ v = RECUR (TREE_OPERAND (op1, 0));
+ lhs = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+ }
+ else if (code == OMP_ATOMIC_CAPTURE_OLD
+ || code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ tree op11 = TREE_OPERAND (TREE_OPERAND (op1, 1), 1);
+ v = RECUR (TREE_OPERAND (op1, 0));
+ lhs1 = RECUR (TREE_OPERAND (TREE_OPERAND (op1, 1), 0));
+ if (TREE_CODE (op11) == COMPOUND_EXPR)
+ {
+ rhs1 = RECUR (TREE_OPERAND (op11, 0));
+ op11 = TREE_OPERAND (op11, 1);
+ }
+ lhs = RECUR (TREE_OPERAND (op11, 0));
+ rhs = RECUR (TREE_OPERAND (op11, 1));
+ opcode = TREE_CODE (op11);
+ }
+ else
+ {
+ code = OMP_ATOMIC;
+ lhs = RECUR (TREE_OPERAND (op1, 0));
+ rhs = RECUR (TREE_OPERAND (op1, 1));
+ }
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ }
break;
case EXPR_PACK_EXPANSION:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0b2a96f..a528477 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3905,6 +3905,14 @@ finish_omp_clauses (tree clauses)
OMP_CLAUSE_IF_EXPR (c) = t;
break;
+ case OMP_CLAUSE_FINAL:
+ t = OMP_CLAUSE_FINAL_EXPR (c);
+ t = maybe_convert_cond (t);
+ if (t == error_mark_node)
+ remove = true;
+ OMP_CLAUSE_FINAL_EXPR (c) = t;
+ break;
+
case OMP_CLAUSE_NUM_THREADS:
t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
if (t == error_mark_node)
@@ -3936,6 +3944,7 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
@@ -4030,6 +4039,8 @@ finish_omp_clauses (tree clauses)
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
break;
default:
error ("%qE has invalid type for %<reduction(%s)%>",
@@ -4074,6 +4085,10 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
break;
case OMP_CLAUSE_DEFAULT_SHARED:
+ /* const vars may be specified in firstprivate clause. */
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && cxx_omp_const_qual_no_mutable (t))
+ break;
share_name = "shared";
break;
case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -4697,15 +4712,22 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
}
void
-finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
+finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
+ tree rhs, tree v, tree lhs1, tree rhs1)
{
tree orig_lhs;
tree orig_rhs;
+ tree orig_v;
+ tree orig_lhs1;
+ tree orig_rhs1;
bool dependent_p;
tree stmt;
orig_lhs = lhs;
orig_rhs = rhs;
+ orig_v = v;
+ orig_lhs1 = lhs1;
+ orig_rhs1 = rhs1;
dependent_p = false;
stmt = NULL_TREE;
@@ -4714,22 +4736,53 @@ finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
if (processing_template_decl)
{
dependent_p = (type_dependent_expression_p (lhs)
- || type_dependent_expression_p (rhs));
+ || (rhs && type_dependent_expression_p (rhs))
+ || (v && type_dependent_expression_p (v))
+ || (lhs1 && type_dependent_expression_p (lhs1))
+ || (rhs1 && type_dependent_expression_p (rhs1)));
if (!dependent_p)
{
lhs = build_non_dependent_expr (lhs);
- rhs = build_non_dependent_expr (rhs);
+ if (rhs)
+ rhs = build_non_dependent_expr (rhs);
+ if (v)
+ v = build_non_dependent_expr (v);
+ if (lhs1)
+ lhs1 = build_non_dependent_expr (lhs1);
+ if (rhs1)
+ rhs1 = build_non_dependent_expr (rhs1);
}
}
if (!dependent_p)
{
- stmt = c_finish_omp_atomic (input_location, code, lhs, rhs);
+ stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
+ v, lhs1, rhs1);
if (stmt == error_mark_node)
return;
}
if (processing_template_decl)
- stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
- build2 (code, void_type_node, orig_lhs, orig_rhs));
+ {
+ if (code == OMP_ATOMIC_READ)
+ {
+ stmt = build_min_nt (OMP_ATOMIC_READ, orig_lhs);
+ stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+ }
+ else
+ {
+ if (opcode == NOP_EXPR)
+ stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
+ else
+ stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
+ if (orig_rhs1)
+ stmt = build_min_nt (COMPOUND_EXPR, orig_rhs1, stmt);
+ if (code != OMP_ATOMIC)
+ {
+ stmt = build_min_nt (code, orig_lhs1, stmt);
+ stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
+ }
+ }
+ stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
+ }
add_stmt (stmt);
}
@@ -4762,6 +4815,16 @@ finish_omp_taskwait (void)
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
+
+void
+finish_omp_taskyield (void)
+{
+ tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ VEC(tree,gc) *vec = make_tree_vector ();
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ finish_expr_stmt (stmt);
+}
void
init_cp_semantics (void)