diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 44 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/parser.c | 391 | ||||
-rw-r--r-- | gcc/cp/pt.c | 58 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 75 |
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) |