Hi! In OpenMP 4.1, one can optionally use modifiers to say which construct the if clause belongs to.
Implemented thusly: 2015-07-15 Jakub Jelinek <ja...@redhat.com> * tree-core.h (struct tree_omp_clause): Add subcode.if_modifier field. * tree.h (OMP_CLAUSE_IF_MODIFIER): Define. * gimplify.c (gimplify_scan_omp_clauses): Add CODE argument. For OMP_CLAUSE_IF complain if OMP_CLAUSE_IF_MODIFIER is present and does not match code. Handle OMP_CLAUSE_GANG separately. (gimplify_oacc_cache, gimplify_omp_parallel, gimplify_omp_task, gimplify_omp_for, gimplify_omp_workshare, gimplify_omp_target_update, gimplify_expr): Adjust gimplify_scan_omp_clauses callers. * tree-pretty-print.c (dump_omp_clause): Print OMP_CLAUSE_IF_MODIFIER. c-family/ * c-omp.c (c_omp_split_clauses): Use OMP_CLAUSE_IF_MODIFIER to decide where to put OMP_CLAUSE_IF, without modifier duplicate to both target and parallel if combined. c/ * c-parser.c (c_parser_omp_clause_if): Add IS_OMP argument. Parse and diagnose directive-name-modifier. (c_parser_oacc_all_clauses, c_parser_omp_all_clauses): Adjust callers. cp/ * parser.c (cp_parser_omp_clause_if): Add IS_OMP argument. Parse and diagnose directive-name-modifier. (cp_parser_oacc_all_clauses, cp_parser_omp_all_clauses): Adjust callers. fortran/ * trans-openmp.c (gfc_trans_omp_clauses): Set OMP_CLAUSE_IF_MODIFIER to ERROR_MARK. testsuite/ * c-c++-common/gomp/if-1.c: New test. * c-c++-common/gomp/if-2.c: New test. --- gcc/tree-core.h.jj 2015-07-14 14:49:57.000000000 +0200 +++ gcc/tree-core.h 2015-07-15 09:06:43.660755515 +0200 @@ -1351,6 +1351,7 @@ struct GTY(()) tree_omp_clause { enum omp_clause_proc_bind_kind proc_bind_kind; enum tree_code reduction_code; enum omp_clause_linear_kind linear_kind; + enum tree_code if_modifier; } GTY ((skip)) subcode; /* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's --- gcc/tree.h.jj 2015-07-14 14:29:49.000000000 +0200 +++ gcc/tree.h 2015-07-15 09:09:56.450274941 +0200 @@ -1385,6 +1385,9 @@ extern void protected_set_expr_location #define OMP_CLAUSE_SHARED_FIRSTPRIVATE(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SHARED)->base.public_flag) +#define OMP_CLAUSE_IF_MODIFIER(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF)->omp_clause.subcode.if_modifier) + #define OMP_CLAUSE_FINAL_EXPR(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FINAL), 0) #define OMP_CLAUSE_IF_EXPR(NODE) \ --- gcc/gimplify.c.jj 2015-07-14 16:17:52.000000000 +0200 +++ gcc/gimplify.c 2015-07-15 11:09:06.831010500 +0200 @@ -6133,7 +6133,8 @@ find_decl_expr (tree *tp, int *walk_subt static void gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, - enum omp_region_type region_type) + enum omp_region_type region_type, + enum tree_code code) { struct gimplify_omp_ctx *ctx, *outer_ctx; tree c; @@ -6550,8 +6551,33 @@ gimplify_scan_omp_clauses (tree *list_p, } break; - case OMP_CLAUSE_FINAL: case OMP_CLAUSE_IF: + if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (c) != code) + { + const char *p[2]; + for (int i = 0; i < 2; i++) + switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code) + { + case OMP_PARALLEL: p[i] = "parallel"; break; + case OMP_TASK: p[i] = "task"; break; + case OMP_TASKLOOP: p[i] = "taskloop"; break; + case OMP_TARGET_DATA: p[i] = "target data"; break; + case OMP_TARGET: p[i] = "target"; break; + case OMP_TARGET_UPDATE: p[i] = "target update"; break; + case OMP_TARGET_ENTER_DATA: + p[i] = "target enter data"; break; + case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break; + default: gcc_unreachable (); + } + error_at (OMP_CLAUSE_LOCATION (c), + "expected %qs %<if%> clause modifier rather than %qs", + p[0], p[1]); + remove = true; + } + /* Fall through. */ + + case OMP_CLAUSE_FINAL: OMP_CLAUSE_OPERAND (c, 0) = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0)); /* Fall through. */ @@ -6572,15 +6598,19 @@ gimplify_scan_omp_clauses (tree *list_p, case OMP_CLAUSE_NUM_GANGS: case OMP_CLAUSE_NUM_WORKERS: case OMP_CLAUSE_VECTOR_LENGTH: - case OMP_CLAUSE_GANG: case OMP_CLAUSE_WORKER: case OMP_CLAUSE_VECTOR: if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR) remove = true; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG - && gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL, - is_gimple_val, fb_rvalue) == GS_ERROR) + break; + + case OMP_CLAUSE_GANG: + if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) + remove = true; + if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) remove = true; break; @@ -7009,7 +7039,8 @@ gimplify_oacc_cache (tree *expr_p, gimpl { tree expr = *expr_p; - gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_WORKSHARE); + gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_WORKSHARE, + OACC_CACHE); gimplify_adjust_omp_clauses (pre_p, &OACC_CACHE_CLAUSES (expr)); /* TODO: Do something sensible with this information. */ @@ -7032,7 +7063,7 @@ gimplify_omp_parallel (tree *expr_p, gim gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, OMP_PARALLEL_COMBINED (expr) ? ORT_COMBINED_PARALLEL - : ORT_PARALLEL); + : ORT_PARALLEL, OMP_PARALLEL); push_gimplify_context (); @@ -7068,7 +7099,7 @@ gimplify_omp_task (tree *expr_p, gimple_ gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, find_omp_clause (OMP_TASK_CLAUSES (expr), OMP_CLAUSE_UNTIED) - ? ORT_UNTIED_TASK : ORT_TASK); + ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK); push_gimplify_context (); @@ -7169,7 +7200,8 @@ gimplify_omp_for (tree *expr_p, gimple_s } if (TREE_CODE (for_stmt) != OMP_TASKLOOP) - gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort); + gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort, + TREE_CODE (for_stmt)); if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE) gimplify_omp_ctxp->distribute = true; @@ -7280,7 +7312,8 @@ gimplify_omp_for (tree *expr_p, gimple_s } } - gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort); + gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort, + OMP_TASKLOOP); } if (orig_for_stmt != for_stmt) @@ -7853,7 +7886,8 @@ gimplify_omp_workshare (tree *expr_p, gi default: gcc_unreachable (); } - gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort); + gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort, + TREE_CODE (expr)); if (ort == ORT_TARGET || ort == ORT_TARGET_DATA) { push_gimplify_context (); @@ -7962,7 +7996,7 @@ gimplify_omp_target_update (tree *expr_p gcc_unreachable (); } gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p, - ORT_WORKSHARE); + ORT_WORKSHARE, TREE_CODE (expr)); gimplify_adjust_omp_clauses (pre_p, &OMP_STANDALONE_CLAUSES (expr)); stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr)); @@ -8995,7 +9029,7 @@ gimplify_expr (tree *expr_p, gimple_seq break; case OMP_CRITICAL: gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p), - pre_p, ORT_WORKSHARE); + pre_p, ORT_WORKSHARE, OMP_CRITICAL); gimplify_adjust_omp_clauses (pre_p, &OMP_CRITICAL_CLAUSES (*expr_p)); g = gimple_build_omp_critical (body, --- gcc/tree-pretty-print.c.jj 2015-07-14 14:49:57.000000000 +0200 +++ gcc/tree-pretty-print.c 2015-07-15 11:17:43.463007390 +0200 @@ -367,6 +367,20 @@ dump_omp_clause (pretty_printer *pp, tre case OMP_CLAUSE_IF: pp_string (pp, "if("); + switch (OMP_CLAUSE_IF_MODIFIER (clause)) + { + case ERROR_MARK: break; + case OMP_PARALLEL: pp_string (pp, "parallel:"); break; + case OMP_TASK: pp_string (pp, "task:"); break; + case OMP_TASKLOOP: pp_string (pp, "taskloop:"); break; + case OMP_TARGET_DATA: pp_string (pp, "target data:"); break; + case OMP_TARGET: pp_string (pp, "target:"); break; + case OMP_TARGET_UPDATE: pp_string (pp, "target update:"); break; + case OMP_TARGET_ENTER_DATA: + pp_string (pp, "target enter data:"); break; + case OMP_TARGET_EXIT_DATA: pp_string (pp, "target exit data:"); break; + default: gcc_unreachable (); + } dump_generic_node (pp, OMP_CLAUSE_IF_EXPR (clause), spc, flags, false); pp_right_paren (pp); --- gcc/c-family/c-omp.c.jj 2015-07-14 14:49:57.000000000 +0200 +++ gcc/c-family/c-omp.c 2015-07-15 11:09:06.831010500 +0200 @@ -1010,10 +1010,39 @@ c_omp_split_clauses (location_t loc, enu if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) s = C_OMP_CLAUSE_SPLIT_TASKLOOP; - /* FIXME: This is currently being discussed. */ else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) - s = C_OMP_CLAUSE_SPLIT_PARALLEL; + { + if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_MAP)) != 0) + { + if (OMP_CLAUSE_IF_MODIFIER (clauses) == OMP_PARALLEL) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else if (OMP_CLAUSE_IF_MODIFIER (clauses) == OMP_TARGET) + s = C_OMP_CLAUSE_SPLIT_TARGET; + else if (OMP_CLAUSE_IF_MODIFIER (clauses) == ERROR_MARK) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_IF); + OMP_CLAUSE_IF_MODIFIER (c) + = OMP_CLAUSE_IF_MODIFIER (clauses); + OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses); + OMP_CLAUSE_CHAIN (c) + = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + } + else + { + error_at (OMP_CLAUSE_LOCATION (clauses), + "expected %<parallel%> or %<target%> %<if%> " + "clause modifier"); + continue; + } + } + else + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + } else s = C_OMP_CLAUSE_SPLIT_TARGET; break; --- gcc/c/c-parser.c.jj 2015-07-14 16:03:49.000000000 +0200 +++ gcc/c/c-parser.c 2015-07-15 12:53:35.626128964 +0200 @@ -10549,28 +10549,149 @@ c_parser_omp_clause_final (c_parser *par } /* OpenACC, OpenMP 2.5: - if ( expression ) */ + if ( expression ) + + OpenMP 4.1: + if ( directive-name-modifier : expression ) + + directive-name-modifier: + parallel | task | taskloop | target data | target | target update + | target enter data | target exit data */ static tree -c_parser_omp_clause_if (c_parser *parser, tree list) +c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) { - location_t loc = c_parser_peek_token (parser)->location; - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - tree t = c_parser_paren_condition (parser); - tree c; + location_t location = c_parser_peek_token (parser)->location; + enum tree_code if_modifier = ERROR_MARK; - check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if"); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; - c = build_omp_clause (loc, OMP_CLAUSE_IF); - OMP_CLAUSE_IF_EXPR (c) = t; - OMP_CLAUSE_CHAIN (c) = list; - list = c; + if (is_omp && c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + int n = 2; + if (strcmp (p, "parallel") == 0) + if_modifier = OMP_PARALLEL; + else if (strcmp (p, "task") == 0) + if_modifier = OMP_TASK; + else if (strcmp (p, "taskloop") == 0) + if_modifier = OMP_TASKLOOP; + else if (strcmp (p, "target") == 0) + { + if_modifier = OMP_TARGET; + if (c_parser_peek_2nd_token (parser)->type == CPP_NAME) + { + p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value); + if (strcmp ("data", p) == 0) + if_modifier = OMP_TARGET_DATA; + else if (strcmp ("update", p) == 0) + if_modifier = OMP_TARGET_UPDATE; + else if (strcmp ("enter", p) == 0) + if_modifier = OMP_TARGET_ENTER_DATA; + else if (strcmp ("exit", p) == 0) + if_modifier = OMP_TARGET_EXIT_DATA; + if (if_modifier != OMP_TARGET) + { + n = 3; + c_parser_consume_token (parser); + } + else + { + location_t loc = c_parser_peek_2nd_token (parser)->location; + error_at (loc, "expected %<data%>, %<update%>, %<enter%> " + "or %<exit%>"); + if_modifier = ERROR_MARK; + } + if (if_modifier == OMP_TARGET_ENTER_DATA + || if_modifier == OMP_TARGET_EXIT_DATA) + { + if (c_parser_peek_2nd_token (parser)->type == CPP_NAME) + { + p = IDENTIFIER_POINTER + (c_parser_peek_2nd_token (parser)->value); + if (strcmp ("data", p) == 0) + n = 4; + } + if (n == 4) + c_parser_consume_token (parser); + else + { + location_t loc + = c_parser_peek_2nd_token (parser)->location; + error_at (loc, "expected %<data%>"); + if_modifier = ERROR_MARK; + } + } + } + } + if (if_modifier != ERROR_MARK) + { + if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + } + else + { + if (n > 2) + { + location_t loc = c_parser_peek_2nd_token (parser)->location; + error_at (loc, "expected %<:%>"); + } + if_modifier = ERROR_MARK; + } + } } - else - c_parser_error (parser, "expected %<(%>"); - return list; + tree t = c_parser_condition (parser), c; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + + for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) + { + if (if_modifier != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) + { + const char *p = NULL; + switch (if_modifier) + { + case OMP_PARALLEL: p = "parallel"; break; + case OMP_TASK: p = "task"; break; + case OMP_TASKLOOP: p = "taskloop"; break; + case OMP_TARGET_DATA: p = "target data"; break; + case OMP_TARGET: p = "target"; break; + case OMP_TARGET_UPDATE: p = "target update"; break; + case OMP_TARGET_ENTER_DATA: p = "enter data"; break; + case OMP_TARGET_EXIT_DATA: p = "exit data"; break; + default: gcc_unreachable (); + } + error_at (location, "too many %<if%> clauses with %qs modifier", + p); + return list; + } + else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) + { + if (!is_omp) + error_at (location, "too many %<if%> clauses"); + else + error_at (location, "too many %<if%> clauses without modifier"); + return list; + } + else if (if_modifier == ERROR_MARK + || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK) + { + error_at (location, "if any %<if%> clause has modifier, then all " + "%<if%> clauses have to use modifier"); + return list; + } + } + + c = build_omp_clause (location, OMP_CLAUSE_IF); + OMP_CLAUSE_IF_MODIFIER (c) = if_modifier; + OMP_CLAUSE_IF_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + return c; } /* OpenMP 2.5: @@ -12150,7 +12271,7 @@ c_parser_oacc_all_clauses (c_parser *par c_name = "host"; break; case PRAGMA_OACC_CLAUSE_IF: - clauses = c_parser_omp_clause_if (parser, clauses); + clauses = c_parser_omp_clause_if (parser, clauses, false); c_name = "if"; break; case PRAGMA_OACC_CLAUSE_NUM_GANGS: @@ -12288,7 +12409,7 @@ c_parser_omp_all_clauses (c_parser *pars c_name = "defaultmap"; break; case PRAGMA_OMP_CLAUSE_IF: - clauses = c_parser_omp_clause_if (parser, clauses); + clauses = c_parser_omp_clause_if (parser, clauses, true); c_name = "if"; break; case PRAGMA_OMP_CLAUSE_LASTPRIVATE: --- gcc/cp/parser.c.jj 2015-07-14 17:39:06.000000000 +0200 +++ gcc/cp/parser.c 2015-07-15 12:13:04.950069705 +0200 @@ -28402,16 +28402,102 @@ cp_parser_omp_clause_final (cp_parser *p } /* OpenMP 2.5: - if ( expression ) */ + if ( expression ) + + OpenMP 4.1: + if ( directive-name-modifier : expression ) + + directive-name-modifier: + parallel | task | taskloop | target data | target | target update + | target enter data | target exit data */ static tree -cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location) +cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location, + bool is_omp) { tree t, c; + enum tree_code if_modifier = ERROR_MARK; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; + if (is_omp && 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); + int n = 2; + + if (strcmp ("parallel", p) == 0) + if_modifier = OMP_PARALLEL; + else if (strcmp ("task", p) == 0) + if_modifier = OMP_TASK; + else if (strcmp ("taskloop", p) == 0) + if_modifier = OMP_TASKLOOP; + else if (strcmp ("target", p) == 0) + { + if_modifier = OMP_TARGET; + if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + { + id = cp_lexer_peek_nth_token (parser->lexer, 2)->u.value; + p = IDENTIFIER_POINTER (id); + if (strcmp ("data", p) == 0) + if_modifier = OMP_TARGET_DATA; + else if (strcmp ("update", p) == 0) + if_modifier = OMP_TARGET_UPDATE; + else if (strcmp ("enter", p) == 0) + if_modifier = OMP_TARGET_ENTER_DATA; + else if (strcmp ("exit", p) == 0) + if_modifier = OMP_TARGET_EXIT_DATA; + if (if_modifier != OMP_TARGET) + n = 3; + else + { + location_t loc + = cp_lexer_peek_nth_token (parser->lexer, 2)->location; + error_at (loc, "expected %<data%>, %<update%>, %<enter%> " + "or %<exit%>"); + if_modifier = ERROR_MARK; + } + if (if_modifier == OMP_TARGET_ENTER_DATA + || if_modifier == OMP_TARGET_EXIT_DATA) + { + if (cp_lexer_nth_token_is (parser->lexer, 3, CPP_NAME)) + { + id = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value; + p = IDENTIFIER_POINTER (id); + if (strcmp ("data", p) == 0) + n = 4; + } + if (n != 4) + { + location_t loc + = cp_lexer_peek_nth_token (parser->lexer, 3)->location; + error_at (loc, "expected %<data%>"); + if_modifier = ERROR_MARK; + } + } + } + } + if (if_modifier != ERROR_MARK) + { + if (cp_lexer_nth_token_is (parser->lexer, n, CPP_COLON)) + { + while (n-- > 0) + cp_lexer_consume_token (parser->lexer); + } + else + { + if (n > 2) + { + location_t loc + = cp_lexer_peek_nth_token (parser->lexer, n)->location; + error_at (loc, "expected %<:%>"); + } + if_modifier = ERROR_MARK; + } + } + } + t = cp_parser_condition (parser); if (t == error_mark_node @@ -28420,9 +28506,48 @@ cp_parser_omp_clause_if (cp_parser *pars /*or_comma=*/false, /*consume_paren=*/true); - check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location); + for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) + { + if (if_modifier != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) + { + const char *p = NULL; + switch (if_modifier) + { + case OMP_PARALLEL: p = "parallel"; break; + case OMP_TASK: p = "task"; break; + case OMP_TASKLOOP: p = "taskloop"; break; + case OMP_TARGET_DATA: p = "target data"; break; + case OMP_TARGET: p = "target"; break; + case OMP_TARGET_UPDATE: p = "target update"; break; + case OMP_TARGET_ENTER_DATA: p = "enter data"; break; + case OMP_TARGET_EXIT_DATA: p = "exit data"; break; + default: gcc_unreachable (); + } + error_at (location, "too many %<if%> clauses with %qs modifier", + p); + return list; + } + else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) + { + if (!is_omp) + error_at (location, "too many %<if%> clauses"); + else + error_at (location, "too many %<if%> clauses without modifier"); + return list; + } + else if (if_modifier == ERROR_MARK + || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK) + { + error_at (location, "if any %<if%> clause has modifier, then all " + "%<if%> clauses have to use modifier"); + return list; + } + } c = build_omp_clause (location, OMP_CLAUSE_IF); + OMP_CLAUSE_IF_MODIFIER (c) = if_modifier; OMP_CLAUSE_IF_EXPR (c) = t; OMP_CLAUSE_CHAIN (c) = list; @@ -29713,7 +29838,7 @@ cp_parser_oacc_all_clauses (cp_parser *p c_name = "host"; break; case PRAGMA_OACC_CLAUSE_IF: - clauses = cp_parser_omp_clause_if (parser, clauses, here); + clauses = cp_parser_omp_clause_if (parser, clauses, here, false); c_name = "if"; break; case PRAGMA_OACC_CLAUSE_NUM_GANGS: @@ -29867,7 +29992,8 @@ cp_parser_omp_all_clauses (cp_parser *pa c_name = "is_device_ptr"; break; case PRAGMA_OMP_CLAUSE_IF: - clauses = cp_parser_omp_clause_if (parser, clauses, token->location); + clauses = cp_parser_omp_clause_if (parser, clauses, token->location, + true); c_name = "if"; break; case PRAGMA_OMP_CLAUSE_LASTPRIVATE: --- gcc/fortran/trans-openmp.c.jj 2015-07-09 09:44:47.000000000 +0200 +++ gcc/fortran/trans-openmp.c 2015-07-15 11:09:06.831010500 +0200 @@ -2245,6 +2245,7 @@ gfc_trans_omp_clauses (stmtblock_t *bloc gfc_add_block_to_block (block, &se.post); c = build_omp_clause (where.lb->location, OMP_CLAUSE_IF); + OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK; OMP_CLAUSE_IF_EXPR (c) = if_var; omp_clauses = gfc_trans_add_clause (c, omp_clauses); } --- gcc/testsuite/c-c++-common/gomp/if-1.c.jj 2015-07-15 11:47:36.807682266 +0200 +++ gcc/testsuite/c-c++-common/gomp/if-1.c 2015-07-15 11:47:52.548053177 +0200 @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +void +foo (int a, int b, int *p, int *q) +{ + int i; + #pragma omp parallel if (a) + ; + #pragma omp parallel if (parallel:a) + ; + #pragma omp parallel for simd if (a) + for (i = 0; i < 16; i++) + ; + #pragma omp parallel for simd if (parallel : a) + for (i = 0; i < 16; i++) + ; + #pragma omp task if (a) + ; + #pragma omp task if (task: a) + ; + #pragma omp taskloop if (a) + for (i = 0; i < 16; i++) + ; + #pragma omp taskloop if (taskloop : a) + for (i = 0; i < 16; i++) + ; + #pragma omp target if (a) + ; + #pragma omp target if (target: a) + ; + #pragma omp target teams distribute parallel for simd if (a) + for (i = 0; i < 16; i++) + ; + #pragma omp target teams distribute parallel for simd if (parallel : a) if (target: b) + for (i = 0; i < 16; i++) + ; + #pragma omp target data if (a) map (p[0:2]) + ; + #pragma omp target data if (target data: a) map (p[0:2]) + ; + #pragma omp target enter data if (a) map (to: p[0:2]) + #pragma omp target enter data if (target enter data: a) map (to: p[0:2]) + #pragma omp target exit data if (a) map (from: p[0:2]) + #pragma omp target exit data if (target exit data: a) map (from: p[0:2]) + #pragma omp target update if (a) to (q[0:3]) + #pragma omp target update if (target update:a) to (q[0:3]) +} --- gcc/testsuite/c-c++-common/gomp/if-2.c.jj 2015-07-15 11:47:39.644568886 +0200 +++ gcc/testsuite/c-c++-common/gomp/if-2.c 2015-07-15 12:07:10.829683856 +0200 @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +void +foo (int a, int b, int *p, int *q, int task) +{ + int i; + #pragma omp parallel if (a) if (b) /* { dg-error "too many .if. clauses without modifier" } */ + ; + #pragma omp parallel if (a) if (parallel: b) /* { dg-error "if any .if. clause has modifier, then all .if. clauses have to use modifier" } */ + ; + #pragma omp parallel if (parallel: a) if (b) /* { dg-error "if any .if. clause has modifier, then all .if. clauses have to use modifier" } */ + ; + #pragma omp parallel if (parallel:a) if (parallel:a) /* { dg-error "too many .if. clauses with .parallel. modifier" } */ + ; + #pragma omp parallel if (task:a) /* { dg-error "expected .parallel. .if. clause modifier rather than .task." } */ \ + if (taskloop: b) /* { dg-error "expected .parallel. .if. clause modifier rather than .taskloop." } */ + ; + #pragma omp parallel if (target update:a) /* { dg-error "expected .parallel. .if. clause modifier rather than .target update." } */ + ; + #pragma omp parallel for simd if (target update: a) /* { dg-error "expected .parallel. .if. clause modifier rather than .target update." } */ + for (i = 0; i < 16; i++) + ; + #pragma omp task if (task) + ; + #pragma omp task if (task: task) + ; + #pragma omp task if (parallel: a) /* { dg-error "expected .task. .if. clause modifier rather than .parallel." } */ + ; + #pragma omp taskloop if (task : a) /* { dg-error "expected .taskloop. .if. clause modifier rather than .task." } */ + for (i = 0; i < 16; i++) + ; + #pragma omp target if (taskloop: a) /* { dg-error "expected .target. .if. clause modifier rather than .taskloop." } */ + ; + #pragma omp target teams distribute parallel for simd if (target exit data : a) /* { dg-error "expected .parallel. or .target. .if. clause modifier" } */ + for (i = 0; i < 16; i++) + ; + #pragma omp target data if (target: a) map (p[0:2]) /* { dg-error "expected .target data. .if. clause modifier rather than .target." } */ + ; + #pragma omp target enter data if (target data: a) map (to: p[0:2]) /* { dg-error "expected .target enter data. .if. clause modifier rather than .target data." } */ + #pragma omp target exit data if (target enter data: a) map (from: p[0:2]) /* { dg-error "expected .target exit data. .if. clause modifier rather than .target enter data." } */ + #pragma omp target update if (target exit data:a) to (q[0:3]) /* { dg-error "expected .target update. .if. clause modifier rather than .target exit data." } */ +} Jakub