Hi! This patch brings the C FE roughly on feature parity with what has been done earlier to the C++ FE only. Thus, #pragma omp simd should work with C FE now, etc.
2013-04-24 Jakub Jelinek <ja...@redhat.com> c/ * c-parser.c (c_parser_compound_statement, c_parser_statement): Adjust comments for OpenMP 3.0+ additions. (c_parser_pragma): Handle PRAGMA_OMP_CANCEL and PRAGMA_OMP_CANCELLATION_POINT. (c_parser_omp_clause_name): Handle new OpenMP 4.0 clauses. (c_parser_omp_clause_collapse): Fully fold collapse expression. (c_parser_omp_clause_branch, c_parser_omp_clause_cancelkind, c_parser_omp_clause_num_teams, c_parser_omp_clause_aligned, c_parser_omp_clause_linear, c_parser_omp_clause_safelen, c_parser_omp_clause_simdlen, c_parser_omp_clause_depend, c_parser_omp_clause_map, c_parser_omp_clause_device, c_parser_omp_clause_dist_schedule, c_parser_omp_clause_proc_bind, c_parser_omp_clause_to, c_parser_omp_clause_from, c_parser_omp_clause_uniform): New functions. (c_parser_omp_all_clauses): Handle new OpenMP 4.0 clauses. (c_parser_omp_for_loop): Add CODE argument, pass it through to c_finish_omp_for. (OMP_SIMD_CLAUSE_MASK): Define. (c_parser_omp_simd): New function. (c_parser_omp_for): Parse #pragma omp for simd. (OMP_PARALLEL_CLAUSE_MASK): Add OMP_CLAUSE_PROC_BIND. (c_parser_omp_parallel): Parse #pragma omp parallel for simd. (OMP_TASK_CLAUSE_MASK): Add OMP_CLAUSE_DEPEND. (c_parser_omp_taskgroup): New function. (OMP_CANCEL_CLAUSE_MASK, OMP_CANCELLATION_POINT_CLAUSE_MASK): Define. (c_parser_omp_cancel, c_parser_omp_cancellation_point): New functions. (c_parser_omp_construct): Handle PRAGMA_OMP_SIMD and PRAGMA_OMP_TASKGROUP. (c_parser_transaction_cancel): Formatting fix. * c-tree.h (c_begin_omp_taskgroup, c_finish_omp_taskgroup, c_finish_omp_cancel, c_finish_omp_cancellation_point): New prototypes. * c-typeck.c (c_begin_omp_taskgroup, c_finish_omp_taskgroup, c_finish_omp_cancel, c_finish_omp_cancellation_point): New functions. (c_finish_omp_clauses): Handle new OpenMP 4.0 clauses. cp/ * parser.c (cp_parser_omp_clause_name): Add missing break after case 'i'. (cp_parser_omp_cancellation_point): Diagnose error if #pragma omp cancellation isn't followed by point. * semantics.c (finish_omp_clauses): Complain also about zero in alignment of aligned directive or safelen/simdlen expressions. (finish_omp_cancel): Fix up diagnostics wording. testsuite/ * c-c++-common/gomp/simd1.c: Enable also for C. * c-c++-common/gomp/simd2.c: Likewise. * c-c++-common/gomp/simd3.c: Likewise. * c-c++-common/gomp/simd4.c: Likewise. Adjust expected diagnostics for C. * c-c++-common/gomp/simd5.c: Enable also for C. --- gcc/c/c-parser.c.jj 2013-03-27 13:01:09.000000000 +0100 +++ gcc/c/c-parser.c 2013-04-24 18:22:37.195711949 +0200 @@ -1186,6 +1186,8 @@ static void c_parser_omp_barrier (c_pars static void c_parser_omp_flush (c_parser *); static void c_parser_omp_taskwait (c_parser *); static void c_parser_omp_taskyield (c_parser *); +static void c_parser_omp_cancel (c_parser *); +static void c_parser_omp_cancellation_point (c_parser *); enum pragma_context { pragma_external, pragma_stmt, pragma_compound }; static bool c_parser_pragma (c_parser *, enum pragma_context); @@ -4054,7 +4056,11 @@ c_parser_initval (c_parser *parser, stru openmp-directive: barrier-directive - flush-directive */ + flush-directive + taskwait-directive + taskyield-directive + cancel-directive + cancellation-point-directive */ static tree c_parser_compound_statement (c_parser *parser) @@ -4384,9 +4390,12 @@ c_parser_label (c_parser *parser) openmp-construct: parallel-construct for-construct + simd-construct + for-simd-construct sections-construct single-construct parallel-for-construct + parallel-for-simd-construct parallel-sections-construct master-construct critical-construct @@ -4399,6 +4408,12 @@ c_parser_label (c_parser *parser) for-construct: for-directive iteration-statement + simd-construct: + simd-directive iteration-statements + + for-simd-construct: + for-simd-directive iteration-statements + sections-construct: sections-directive section-scope @@ -4408,6 +4423,9 @@ c_parser_label (c_parser *parser) parallel-for-construct: parallel-for-directive iteration-statement + parallel-for-simd-construct: + parallel-for-simd-directive iteration-statement + parallel-sections-construct: parallel-sections-directive section-scope @@ -8606,6 +8624,28 @@ c_parser_pragma (c_parser *parser, enum c_parser_omp_taskyield (parser); return false; + case PRAGMA_OMP_CANCEL: + if (context != pragma_compound) + { + if (context == pragma_stmt) + c_parser_error (parser, "%<#pragma omp cancel%> may only be " + "used in compound statements"); + goto bad_stmt; + } + c_parser_omp_cancel (parser); + return false; + + case PRAGMA_OMP_CANCELLATION_POINT: + if (context != pragma_compound) + { + if (context == pragma_stmt) + c_parser_error (parser, "%<#pragma omp cancellation point%> may " + "only be used in compound statements"); + goto bad_stmt; + } + c_parser_omp_cancellation_point (parser); + return false; + case PRAGMA_OMP_THREADPRIVATE: c_parser_omp_threadprivate (parser); return false; @@ -8690,7 +8730,7 @@ c_parser_pragma_pch_preprocess (c_parser c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name)); } -/* OpenMP 2.5 parsing routines. */ +/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines. */ /* Returns name of the next clause. If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and @@ -8706,12 +8746,18 @@ c_parser_omp_clause_name (c_parser *pars result = PRAGMA_OMP_CLAUSE_IF; else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)) result = PRAGMA_OMP_CLAUSE_DEFAULT; + else if (c_parser_next_token_is_keyword (parser, RID_FOR)) + result = PRAGMA_OMP_CLAUSE_FOR; else if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); switch (p[0]) { + case 'a': + if (!strcmp ("aligned", p)) + result = PRAGMA_OMP_CLAUSE_ALIGNED; + break; case 'c': if (!strcmp ("collapse", p)) result = PRAGMA_OMP_CLAUSE_COLLAPSE; @@ -8720,23 +8766,45 @@ c_parser_omp_clause_name (c_parser *pars else if (!strcmp ("copyprivate", p)) result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; break; + case 'd': + if (!strcmp ("depend", p)) + result = PRAGMA_OMP_CLAUSE_DEPEND; + else if (!strcmp ("device", p)) + result = PRAGMA_OMP_CLAUSE_DEVICE; + else if (!strcmp ("dist_schedule", p)) + result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; + break; case 'f': if (!strcmp ("final", p)) result = PRAGMA_OMP_CLAUSE_FINAL; else if (!strcmp ("firstprivate", p)) result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; + else if (!strcmp ("from", p)) + result = PRAGMA_OMP_CLAUSE_FROM; + break; + case 'i': + if (!strcmp ("inbranch", p)) + result = PRAGMA_OMP_CLAUSE_INBRANCH; break; case 'l': if (!strcmp ("lastprivate", p)) result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; + else if (!strcmp ("linear", p)) + result = PRAGMA_OMP_CLAUSE_LINEAR; break; case 'm': - if (!strcmp ("mergeable", p)) + if (!strcmp ("map", p)) + result = PRAGMA_OMP_CLAUSE_MAP; + else if (!strcmp ("mergeable", p)) result = PRAGMA_OMP_CLAUSE_MERGEABLE; break; case 'n': - if (!strcmp ("nowait", p)) + if (!strcmp ("notinbranch", p)) + result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; + else if (!strcmp ("nowait", p)) result = PRAGMA_OMP_CLAUSE_NOWAIT; + else if (!strcmp ("num_teams", p)) + result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; else if (!strcmp ("num_threads", p)) result = PRAGMA_OMP_CLAUSE_NUM_THREADS; break; @@ -8745,21 +8813,39 @@ c_parser_omp_clause_name (c_parser *pars result = PRAGMA_OMP_CLAUSE_ORDERED; break; case 'p': - if (!strcmp ("private", p)) + if (!strcmp ("parallel", p)) + result = PRAGMA_OMP_CLAUSE_PARALLEL; + else if (!strcmp ("private", p)) result = PRAGMA_OMP_CLAUSE_PRIVATE; + else if (!strcmp ("proc_bind", p)) + result = PRAGMA_OMP_CLAUSE_PROC_BIND; break; case 'r': if (!strcmp ("reduction", p)) result = PRAGMA_OMP_CLAUSE_REDUCTION; break; case 's': - if (!strcmp ("schedule", p)) + if (!strcmp ("safelen", p)) + result = PRAGMA_OMP_CLAUSE_SAFELEN; + else if (!strcmp ("schedule", p)) result = PRAGMA_OMP_CLAUSE_SCHEDULE; + else if (!strcmp ("sections", p)) + result = PRAGMA_OMP_CLAUSE_SECTIONS; else if (!strcmp ("shared", p)) result = PRAGMA_OMP_CLAUSE_SHARED; + else if (!strcmp ("simdlen", p)) + result = PRAGMA_OMP_CLAUSE_SIMDLEN; + break; + case 't': + if (!strcmp ("taskgroup", p)) + result = PRAGMA_OMP_CLAUSE_TASKGROUP; + else if (!strcmp ("to", p)) + result = PRAGMA_OMP_CLAUSE_TO; break; case 'u': - if (!strcmp ("untied", p)) + if (!strcmp ("uniform", p)) + result = PRAGMA_OMP_CLAUSE_UNIFORM; + else if (!strcmp ("untied", p)) result = PRAGMA_OMP_CLAUSE_UNTIED; break; } @@ -8879,6 +8965,8 @@ c_parser_omp_clause_collapse (c_parser * } if (num == error_mark_node) return list; + mark_exp_read (num); + num = c_fully_fold (num, false, NULL); if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) || !host_integerp (num, 0) || (n = tree_low_cst (num, 0)) <= 0 @@ -9144,7 +9232,7 @@ c_parser_omp_clause_private (c_parser *p reduction-operator: One of: + * - & ^ | && || - + OpenMP 3.1: reduction-operator: @@ -9345,6 +9433,510 @@ c_parser_omp_clause_untied (c_parser *pa return c; } +/* OpenMP 4.0: + inbranch + notinbranch */ + +static tree +c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED, + enum omp_clause_code code, tree list) +{ + check_no_duplicate_clause (list, code, omp_clause_code_name[code]); + + tree c = build_omp_clause (c_parser_peek_token (parser)->location, code); + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 4.0: + parallel + for + sections + taskgroup */ + +static tree +c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED, + enum omp_clause_code code, tree list) +{ + tree c; + location_t loc = c_parser_peek_token (parser)->location; + + for (c = list; c; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_PARALLEL: + case OMP_CLAUSE_FOR: + case OMP_CLAUSE_SECTIONS: + case OMP_CLAUSE_TASKGROUP: + error_at (loc, "only one of %<parallel%>, %<for%>, %<sections%> " + "and %<taskgroup%> clauses can be specified"); + break; + default: + break; + } + + c = build_omp_clause (loc, code); + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 4.0: + num_teams ( expression ) */ + +static tree +c_parser_omp_clause_num_teams (c_parser *parser, tree list) +{ + location_t num_teams_loc = c_parser_peek_token (parser)->location; + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + location_t expr_loc = c_parser_peek_token (parser)->location; + tree c, t = c_parser_expression (parser).value; + mark_exp_read (t); + t = c_fully_fold (t, false, NULL); + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + + if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + c_parser_error (parser, "expected integer expression"); + return list; + } + + /* Attempt to statically determine when the number isn't positive. */ + c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, + build_int_cst (TREE_TYPE (t), 0)); + if (CAN_HAVE_LOCATION_P (c)) + SET_EXPR_LOCATION (c, expr_loc); + if (c == boolean_true_node) + { + warning_at (expr_loc, 0, "%<num_teams%> value must be positive"); + t = integer_one_node; + } + + check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams"); + + c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS); + OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + list = c; + } + + return list; +} + +/* OpenMP 4.0: + aligned ( variable-list ) + aligned ( variable-list : constant-expression ) */ + +static tree +c_parser_omp_clause_aligned (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + tree nl, c; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_ALIGNED, list); + + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + tree alignment = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (alignment); + alignment = c_fully_fold (alignment, false, NULL); + if (!INTEGRAL_TYPE_P (TREE_TYPE (alignment)) + && TREE_CODE (alignment) != INTEGER_CST + && tree_int_cst_sgn (alignment) != 1) + { + error_at (clause_loc, "%<aligned%> clause alignment expression must " + "be positive constant integer expression"); + alignment = NULL_TREE; + } + + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return nl; +} + +/* OpenMP 4.0: + linear ( variable-list ) + linear ( variable-list : expression ) */ + +static tree +c_parser_omp_clause_linear (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + tree nl, c, step; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_LINEAR, list); + + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + step = c_parser_expression (parser).value; + mark_exp_read (step); + step = c_fully_fold (step, false, NULL); + if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) + { + error_at (clause_loc, "%<linear%> clause step expression must " + "be integral"); + step = integer_one_node; + } + + } + else + step = integer_one_node; + + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + { + tree s = step; + if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == POINTER_TYPE) + { + s = pointer_int_sum (clause_loc, PLUS_EXPR, OMP_CLAUSE_DECL (c), s); + s = fold_build2_loc (clause_loc, MINUS_EXPR, sizetype, s, + OMP_CLAUSE_DECL (c)); + if (s == error_mark_node) + s = size_one_node; + } + OMP_CLAUSE_LINEAR_STEP (c) = s; + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return nl; +} + +/* OpenMP 4.0: + safelen ( constant-expression ) */ + +static tree +c_parser_omp_clause_safelen (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + tree c, t; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + t = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (t); + t = c_fully_fold (t, false, NULL); + if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (t) != INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + error_at (clause_loc, "%<safelen%> clause expression must " + "be positive constant integer expression"); + t = NULL_TREE; + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + if (t == NULL_TREE || t == error_mark_node) + return list; + + check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen"); + + c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 4.0: + simdlen ( constant-expression ) */ + +static tree +c_parser_omp_clause_simdlen (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + tree c, t; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + t = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (t); + t = c_fully_fold (t, false, NULL); + if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (t) != INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + error_at (clause_loc, "%<simdlen%> clause expression must " + "be positive constant integer expression"); + t = NULL_TREE; + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + if (t == NULL_TREE || t == error_mark_node) + return list; + + check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen"); + + c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN); + OMP_CLAUSE_SIMDLEN_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 4.0: + depend ( depend-kind: variable-list ) + + depend-kind: + in | out | inout */ + +static tree +c_parser_omp_clause_depend (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; + tree nl, c; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp ("in", p) == 0) + kind = OMP_CLAUSE_DEPEND_IN; + else if (strcmp ("inout", p) == 0) + kind = OMP_CLAUSE_DEPEND_INOUT; + else if (strcmp ("out", p) == 0) + kind = OMP_CLAUSE_DEPEND_OUT; + else + goto invalid_kind; + } + else + goto invalid_kind; + + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + goto resync_fail; + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_DEPEND, list); + + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_DEPEND_KIND (c) = kind; + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return nl; + + invalid_kind: + c_parser_error (parser, "invalid depend kind"); + resync_fail: + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return list; +} + +/* OpenMP 4.0: + map ( map-kind: variable-list ) + map ( variable-list ) + + map-kind: + alloc | to | from | tofrom */ + +static tree +c_parser_omp_clause_map (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + enum omp_clause_map_kind kind = OMP_CLAUSE_MAP_TOFROM; + tree nl, c; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp ("alloc", p) == 0) + kind = OMP_CLAUSE_MAP_ALLOC; + else if (strcmp ("to", p) == 0) + kind = OMP_CLAUSE_MAP_TO; + else if (strcmp ("from", p) == 0) + kind = OMP_CLAUSE_MAP_FROM; + else if (strcmp ("tofrom", p) == 0) + kind = OMP_CLAUSE_MAP_TOFROM; + else + { + c_parser_error (parser, "invalid map kind"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return list; + } + c_parser_consume_token (parser); + c_parser_consume_token (parser); + } + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_MAP, list); + + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_MAP_KIND (c) = kind; + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return nl; +} + +/* OpenMP 4.0: + device ( expression ) */ + +static tree +c_parser_omp_clause_device (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + tree c, t = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (t); + t = c_fully_fold (t, false, NULL); + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + + if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + c_parser_error (parser, "expected integer expression"); + return list; + } + + check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device"); + + c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE); + OMP_CLAUSE_DEVICE_ID (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + list = c; + } + + return list; +} + +/* OpenMP 4.0: + dist_schedule ( static ) + dist_schedule ( static , expression ) */ + +static tree +c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) +{ + tree c, t = NULL_TREE; + location_t loc = c_parser_peek_token (parser)->location; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + if (!c_parser_next_token_is_keyword (parser, RID_STATIC)) + { + c_parser_error (parser, "invalid dist_schedule kind"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return list; + } + + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + + t = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (t); + t = c_fully_fold (t, false, NULL); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + } + else + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<,%> or %<)%>"); + + check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule"); + if (t == error_mark_node) + return list; + + c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE); + OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 4.0: + proc_bind ( proc-bind-kind ) + + proc-bind-kind: + master | close | spread */ + +static tree +c_parser_omp_clause_proc_bind (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + enum omp_clause_proc_bind_kind kind; + tree c; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp ("master", p) == 0) + kind = OMP_CLAUSE_PROC_BIND_MASTER; + else if (strcmp ("close", p) == 0) + kind = OMP_CLAUSE_PROC_BIND_CLOSE; + else if (strcmp ("spread", p) == 0) + kind = OMP_CLAUSE_PROC_BIND_SPREAD; + else + goto invalid_kind; + } + else + goto invalid_kind; + + c_parser_consume_token (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND); + OMP_CLAUSE_PROC_BIND_KIND (c) = kind; + OMP_CLAUSE_CHAIN (c) = list; + return c; + + invalid_kind: + c_parser_error (parser, "invalid proc_bind kind"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + return list; +} + +/* OpenMP 4.0: + to ( variable-list ) */ + +static tree +c_parser_omp_clause_to (c_parser *parser, tree list) +{ + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list); +} + +/* OpenMP 4.0: + from ( variable-list ) */ + +static tree +c_parser_omp_clause_from (c_parser *parser, tree list) +{ + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list); +} + +/* OpenMP 4.0: + uniform ( variable-list ) */ + +static tree +c_parser_omp_clause_uniform (c_parser *parser, tree list) +{ + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_UNIFORM, list); +} + /* Parse all OpenMP clauses. The set clauses allowed by the directive is a bitmask in MASK. Return the list of clauses found; the result of clause default goes in *pdefault. */ @@ -9440,6 +10032,92 @@ c_parser_omp_all_clauses (c_parser *pars clauses = c_parser_omp_clause_untied (parser, clauses); c_name = "untied"; break; + case PRAGMA_OMP_CLAUSE_INBRANCH: + clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH, + clauses); + c_name = "inbranch"; + break; + case PRAGMA_OMP_CLAUSE_NOTINBRANCH: + clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH, + clauses); + c_name = "notinbranch"; + break; + case PRAGMA_OMP_CLAUSE_PARALLEL: + clauses + = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL, + clauses); + c_name = "parallel"; + break; + case PRAGMA_OMP_CLAUSE_FOR: + clauses + = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR, + clauses); + c_name = "for"; + break; + case PRAGMA_OMP_CLAUSE_SECTIONS: + clauses + = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS, + clauses); + c_name = "sections"; + break; + case PRAGMA_OMP_CLAUSE_TASKGROUP: + clauses + = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP, + clauses); + c_name = "taskgroup"; + break; + case PRAGMA_OMP_CLAUSE_TO: + clauses = c_parser_omp_clause_to (parser, clauses); + c_name = "to"; + break; + case PRAGMA_OMP_CLAUSE_FROM: + clauses = c_parser_omp_clause_from (parser, clauses); + c_name = "from"; + break; + case PRAGMA_OMP_CLAUSE_UNIFORM: + clauses = c_parser_omp_clause_uniform (parser, clauses); + c_name = "uniform"; + break; + case PRAGMA_OMP_CLAUSE_NUM_TEAMS: + clauses = c_parser_omp_clause_num_teams (parser, clauses); + c_name = "num_teams"; + break; + case PRAGMA_OMP_CLAUSE_ALIGNED: + clauses = c_parser_omp_clause_aligned (parser, clauses); + c_name = "aligned"; + break; + case PRAGMA_OMP_CLAUSE_LINEAR: + clauses = c_parser_omp_clause_linear (parser, clauses); + c_name = "linear"; + break; + case PRAGMA_OMP_CLAUSE_DEPEND: + clauses = c_parser_omp_clause_depend (parser, clauses); + c_name = "depend"; + break; + case PRAGMA_OMP_CLAUSE_MAP: + clauses = c_parser_omp_clause_map (parser, clauses); + c_name = "map"; + break; + case PRAGMA_OMP_CLAUSE_DEVICE: + clauses = c_parser_omp_clause_device (parser, clauses); + c_name = "device"; + break; + case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE: + clauses = c_parser_omp_clause_dist_schedule (parser, clauses); + c_name = "dist_schedule"; + break; + case PRAGMA_OMP_CLAUSE_PROC_BIND: + clauses = c_parser_omp_clause_proc_bind (parser, clauses); + c_name = "proc_bind"; + break; + case PRAGMA_OMP_CLAUSE_SAFELEN: + clauses = c_parser_omp_clause_safelen (parser, clauses); + c_name = "safelen"; + break; + case PRAGMA_OMP_CLAUSE_SIMDLEN: + clauses = c_parser_omp_clause_simdlen (parser, clauses); + c_name = "simdlen"; + break; default: c_parser_error (parser, "expected %<#pragma omp%> clause"); goto saw_error; @@ -9928,8 +10606,8 @@ c_parser_omp_flush (c_parser *parser) LOC is the location of the OMP in "#pragma omp". */ static tree -c_parser_omp_for_loop (location_t loc, - c_parser *parser, tree clauses, tree *par_clauses) +c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, + tree clauses, tree *par_clauses) { tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; tree declv, condv, incrv, initv, ret = NULL; @@ -10156,7 +10834,7 @@ c_parser_omp_for_loop (location_t loc, an error from the initialization parsing. */ if (!fail) { - stmt = c_finish_omp_for (loc, OMP_FOR, declv, initv, condv, + stmt = c_finish_omp_for (loc, code, declv, initv, condv, incrv, body, NULL); if (stmt) { @@ -10212,10 +10890,46 @@ pop_scopes: return ret; } +/* OpenMP 4.0: + #pragma omp simd simd-clause[optseq] new-line + for-loop + + LOC is the location of the #pragma token. +*/ + +#define OMP_SIMD_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) + +static tree +c_parser_omp_simd (location_t loc, c_parser *parser) +{ + tree block, clauses, ret; + + clauses = c_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK, + "#pragma omp simd"); + + block = c_begin_compound_stmt (true); + ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, NULL); + block = c_end_compound_stmt (loc, block, true); + add_stmt (block); + + return ret; +} + /* OpenMP 2.5: #pragma omp for for-clause[optseq] new-line for-loop + OpenMP 4.0: + #pragma omp for simd for-simd-clause[optseq] new-line + for-loop + LOC is the location of the #pragma token. */ @@ -10233,12 +10947,27 @@ static tree c_parser_omp_for (location_t loc, c_parser *parser) { tree block, clauses, ret; + enum tree_code code = OMP_FOR; + omp_clause_mask mask = OMP_FOR_CLAUSE_MASK; + const char *p_name = "#pragma omp for"; + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + + if (strcmp (p, "simd") == 0) + { + c_parser_consume_token (parser); + code = OMP_FOR_SIMD; + mask |= OMP_SIMD_CLAUSE_MASK; + p_name = "#pragma omp for simd"; + } + } - clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK, - "#pragma omp for"); + clauses = c_parser_omp_all_clauses (parser, mask, p_name); block = c_begin_compound_stmt (true); - ret = c_parser_omp_for_loop (loc, parser, clauses, NULL); + ret = c_parser_omp_for_loop (loc, parser, code, clauses, NULL); block = c_end_compound_stmt (loc, block, true); add_stmt (block); @@ -10409,7 +11138,8 @@ c_parser_omp_sections (location_t loc, c | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) static tree c_parser_omp_parallel (location_t loc, c_parser *parser) @@ -10426,6 +11156,18 @@ c_parser_omp_parallel (location_t loc, c p_name = "#pragma omp parallel for"; mask |= OMP_FOR_CLAUSE_MASK; mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "simd") == 0) + { + c_parser_consume_token (parser); + p_kind = PRAGMA_OMP_PARALLEL_FOR_SIMD; + p_name = "#pragma omp parallel for simd"; + mask |= OMP_SIMD_CLAUSE_MASK; + } + } } else if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -10453,7 +11195,16 @@ c_parser_omp_parallel (location_t loc, c case PRAGMA_OMP_PARALLEL_FOR: block = c_begin_omp_parallel (); c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); - c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause); + c_parser_omp_for_loop (loc, parser, OMP_FOR, ws_clause, &par_clause); + stmt = c_finish_omp_parallel (loc, par_clause, block); + OMP_PARALLEL_COMBINED (stmt) = 1; + break; + + case PRAGMA_OMP_PARALLEL_FOR_SIMD: + block = c_begin_omp_parallel (); + c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); + c_parser_omp_for_loop (loc, parser, OMP_FOR_SIMD, ws_clause, + &par_clause); stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; break; @@ -10517,7 +11268,8 @@ c_parser_omp_single (location_t loc, c_p | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)) static tree c_parser_omp_task (location_t loc, c_parser *parser) @@ -10560,6 +11312,89 @@ c_parser_omp_taskyield (c_parser *parser c_finish_omp_taskyield (loc); } +/* OpenMP 4.0: + # pragma omp taskgroup new-line +*/ + +static void +c_parser_omp_taskgroup (c_parser *parser) +{ + location_t loc = c_parser_peek_token (parser)->location; + c_parser_skip_to_pragma_eol (parser); + + tree block = c_begin_omp_taskgroup (); + c_parser_statement (parser); + c_finish_omp_taskgroup (loc, block); +} + +/* OpenMP 4.0: + # pragma omp cancel cancel-clause[optseq] new-line + + LOC is the location of the #pragma. +*/ + +#define OMP_CANCEL_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) + +static void +c_parser_omp_cancel (c_parser *parser) +{ + location_t loc = c_parser_peek_token (parser)->location; + + c_parser_consume_pragma (parser); + tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK, + "#pragma omp cancel"); + + c_finish_omp_cancel (loc, clauses); +} + +/* OpenMP 4.0: + # pragma omp cancellation point cancelpt-clause[optseq] new-line + + LOC is the location of the #pragma. +*/ + +#define OMP_CANCELLATION_POINT_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP)) + +static void +c_parser_omp_cancellation_point (c_parser *parser) +{ + location_t loc = c_parser_peek_token (parser)->location; + tree clauses; + bool point_seen = false; + + c_parser_consume_pragma (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "point") == 0) + { + c_parser_consume_token (parser); + point_seen = true; + } + } + if (!point_seen) + { + c_parser_error (parser, "expected %<point%>"); + c_parser_skip_to_pragma_eol (parser); + return; + } + + clauses + = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK, + "#pragma omp cancellation point"); + + c_finish_omp_cancellation_point (loc, clauses); +} + /* Main entry point to parsing most OpenMP pragmas. */ static void @@ -10596,12 +11431,18 @@ c_parser_omp_construct (c_parser *parser case PRAGMA_OMP_SECTIONS: stmt = c_parser_omp_sections (loc, parser); break; + case PRAGMA_OMP_SIMD: + stmt = c_parser_omp_simd (loc, parser); + break; case PRAGMA_OMP_SINGLE: stmt = c_parser_omp_single (loc, parser); break; case PRAGMA_OMP_TASK: stmt = c_parser_omp_task (loc, parser); break; + case PRAGMA_OMP_TASKGROUP: + c_parser_omp_taskgroup (parser); + return; default: gcc_unreachable (); } @@ -10828,7 +11669,7 @@ c_parser_transaction_expression (c_parse */ static tree -c_parser_transaction_cancel(c_parser *parser) +c_parser_transaction_cancel (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; tree attrs; --- gcc/c/c-tree.h.jj 2013-03-20 10:41:30.000000000 +0100 +++ gcc/c/c-tree.h 2013-04-24 16:53:21.648329563 +0200 @@ -637,6 +637,10 @@ extern tree c_begin_omp_parallel (void); extern tree c_finish_omp_parallel (location_t, tree, tree); extern tree c_begin_omp_task (void); extern tree c_finish_omp_task (location_t, tree, tree); +extern tree c_begin_omp_taskgroup (void); +extern void c_finish_omp_taskgroup (location_t, tree); +extern void c_finish_omp_cancel (location_t, tree); +extern void c_finish_omp_cancellation_point (location_t, tree); extern tree c_finish_omp_clauses (tree); extern tree c_build_va_arg (location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); --- gcc/c/c-typeck.c.jj 2013-03-20 10:41:30.000000000 +0100 +++ gcc/c/c-typeck.c 2013-04-24 17:51:21.228251517 +0200 @@ -10573,6 +10573,93 @@ c_finish_omp_task (location_t loc, tree return add_stmt (stmt); } +/* Like c_begin_compound_stmt, except force the retention of the BLOCK. */ + +tree +c_begin_omp_taskgroup (void) +{ + tree block; + + keep_next_level (); + block = c_begin_compound_stmt (true); + + return block; +} + +/* Generate code for #pragma omp taskgroup. */ + +void +c_finish_omp_taskgroup (location_t loc, tree block) +{ + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START); + tree stmt = build_call_expr_loc (loc, fn, 0); + block = c_end_compound_stmt (loc, block, true); + add_stmt (stmt); + add_stmt (block); + fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END); + stmt = build_call_expr_loc (loc, fn, 0); + add_stmt (stmt); +} + +/* Generate GOMP_cancel call for #pragma omp cancel. */ + +void +c_finish_omp_cancel (location_t loc, tree clauses) +{ + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL); + int mask = 0; + if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL)) + mask = 1; + else if (find_omp_clause (clauses, OMP_CLAUSE_FOR)) + mask = 2; + else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS)) + mask = 4; + else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP)) + mask = 8; + else + { + error_at (loc, "%<#pragma omp cancel must specify one of " + "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> " + "clauses"); + return; + } + tree stmt = build_call_expr_loc (loc, fn, 1, + build_int_cst (integer_type_node, mask)); + tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF); + if (ifc != NULL_TREE) + stmt = build3 (COND_EXPR, void_type_node, OMP_CLAUSE_IF_EXPR (ifc), + stmt, NULL_TREE); + add_stmt (stmt); +} + +/* Generate GOMP_cancellation_point call for + #pragma omp cancellation point. */ + +void +c_finish_omp_cancellation_point (location_t loc, tree clauses) +{ + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT); + int mask = 0; + if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL)) + mask = 1; + else if (find_omp_clause (clauses, OMP_CLAUSE_FOR)) + mask = 2; + else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS)) + mask = 4; + else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP)) + mask = 8; + else + { + error_at (loc, "%<#pragma omp cancellation point must specify one of " + "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> " + "clauses"); + return; + } + tree stmt = build_call_expr_loc (loc, fn, 1, + build_int_cst (integer_type_node, mask)); + add_stmt (stmt); +} + /* For all elements of CLAUSES, validate them vs OpenMP constraints. Remove any elements from the list that are invalid. */ @@ -10580,6 +10667,7 @@ tree c_finish_omp_clauses (tree clauses) { bitmap_head generic_head, firstprivate_head, lastprivate_head; + bitmap_head aligned_head; tree c, t, *pc = &clauses; const char *name; @@ -10587,6 +10675,7 @@ c_finish_omp_clauses (tree clauses) bitmap_initialize (&generic_head, &bitmap_default_obstack); bitmap_initialize (&firstprivate_head, &bitmap_default_obstack); bitmap_initialize (&lastprivate_head, &bitmap_default_obstack); + bitmap_initialize (&aligned_head, &bitmap_default_obstack); for (pc = &clauses, c = clauses; c ; c = *pc) { @@ -10674,6 +10763,19 @@ c_finish_omp_clauses (tree clauses) } goto check_dup_generic; + case OMP_CLAUSE_LINEAR: + name = "linear"; + t = OMP_CLAUSE_DECL (c); + if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) + { + error_at (OMP_CLAUSE_LOCATION (c), + "linear clause applied to non-integral non-pointer"); + remove = true; + break; + } + goto check_dup_generic; + check_dup_generic: t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) @@ -10738,6 +10840,71 @@ c_finish_omp_clauses (tree clauses) bitmap_set_bit (&lastprivate_head, DECL_UID (t)); break; + case OMP_CLAUSE_ALIGNED: + t = OMP_CLAUSE_DECL (c); + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<aligned%> clause", t); + remove = true; + } + else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE appears more than once in %<aligned%> clauses", + t); + remove = true; + } + else + bitmap_set_bit (&aligned_head, DECL_UID (t)); + break; + + case OMP_CLAUSE_DEPEND: + t = OMP_CLAUSE_DECL (c); + /* FIXME: depend clause argument may be also array section. */ + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<depend%> clause", t); + remove = true; + } + break; + + case OMP_CLAUSE_MAP: + case OMP_CLAUSE_TO: + case OMP_CLAUSE_FROM: + t = OMP_CLAUSE_DECL (c); + /* FIXME: map clause argument may be also array section. */ + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + else if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is threadprivate variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + break; + + case OMP_CLAUSE_UNIFORM: + t = OMP_CLAUSE_DECL (c); + if (TREE_CODE (t) != PARM_DECL) + { + if (DECL_P (t)) + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not an argument in %<uniform%> clause", t); + else + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not an argument in %<uniform%> clause", t); + remove = true; + } + break; + case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: @@ -10748,6 +10915,17 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_COLLAPSE: case OMP_CLAUSE_FINAL: case OMP_CLAUSE_MERGEABLE: + case OMP_CLAUSE_SAFELEN: + case OMP_CLAUSE_SIMDLEN: + case OMP_CLAUSE_DEVICE: + case OMP_CLAUSE_DIST_SCHEDULE: + case OMP_CLAUSE_INBRANCH: + case OMP_CLAUSE_NOTINBRANCH: + case OMP_CLAUSE_PARALLEL: + case OMP_CLAUSE_FOR: + case OMP_CLAUSE_SECTIONS: + case OMP_CLAUSE_TASKGROUP: + case OMP_CLAUSE_PROC_BIND: pc = &OMP_CLAUSE_CHAIN (c); continue; --- gcc/cp/parser.c.jj 2013-04-19 14:51:38.000000000 +0200 +++ gcc/cp/parser.c 2013-04-24 15:24:45.423043998 +0200 @@ -25767,6 +25767,7 @@ cp_parser_omp_clause_name (cp_parser *pa case 'i': if (!strcmp ("inbranch", p)) result = PRAGMA_OMP_CLAUSE_INBRANCH; + break; case 'l': if (!strcmp ("lastprivate", p)) result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; @@ -26644,7 +26645,7 @@ cp_parser_omp_clause_depend (cp_parser * /* OpenMP 4.0: map ( map-kind : variable-list ) - map ( variable-list) + map ( variable-list ) map-kind: alloc | to | from | tofrom */ @@ -28553,6 +28554,7 @@ cp_parser_omp_cancellation_point (cp_par } if (!point_seen) { + cp_parser_error (parser, "expected %<point%>"); cp_parser_require_pragma_eol (parser, pragma_tok); return; } --- gcc/cp/semantics.c.jj 2013-04-23 16:15:06.000000000 +0200 +++ gcc/cp/semantics.c 2013-04-24 16:29:36.590889777 +0200 @@ -4245,7 +4245,7 @@ finish_omp_clauses (tree clauses) if (!processing_template_decl) { if (TREE_CODE (t) != INTEGER_CST - || tree_int_cst_sgn (t) == -1) + || tree_int_cst_sgn (t) != 1) { error ("%qs length expression must be positive constant" " integer expression", @@ -4355,7 +4355,7 @@ finish_omp_clauses (tree clauses) if (!processing_template_decl) { if (TREE_CODE (t) != INTEGER_CST - || tree_int_cst_sgn (t) == -1) + || tree_int_cst_sgn (t) != 1) { error ("%<aligned%> clause alignment expression must be " "positive constant integer expression"); @@ -5394,7 +5394,7 @@ finish_omp_cancel (tree clauses) mask = 8; else { - error ("%<#pragma omp cancellation point must specify one of " + error ("%<#pragma omp cancel must specify one of " "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses"); return; } --- gcc/testsuite/c-c++-common/gomp/simd1.c.jj 2013-04-19 14:51:38.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/simd1.c 2013-04-24 18:12:30.290083554 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! c } } } */ +/* { dg-do compile } */ /* { dg-options "-fopenmp" } */ /* { dg-additional-options "-std=c99" { target c } } */ --- gcc/testsuite/c-c++-common/gomp/simd2.c.jj 2013-04-19 14:51:38.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/simd2.c 2013-04-24 18:12:40.817022184 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! c } } } */ +/* { dg-do compile } */ /* { dg-options "-fopenmp" } */ /* { dg-additional-options "-std=c99" { target c } } */ --- gcc/testsuite/c-c++-common/gomp/simd3.c.jj 2013-04-23 16:15:06.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/simd3.c 2013-04-24 18:12:48.286983584 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! c } } } */ +/* { dg-do compile } */ /* { dg-options "-fopenmp" } */ /* { dg-additional-options "-std=c99" { target c } } */ --- gcc/testsuite/c-c++-common/gomp/simd4.c.jj 2013-04-23 16:15:06.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/simd4.c 2013-04-24 18:23:19.706476536 +0200 @@ -1,8 +1,8 @@ -/* { dg-do compile { target { ! c } } } */ +/* { dg-do compile } */ /* { dg-options "-fopenmp" } */ /* { dg-additional-options "-std=c99" { target c } } */ -struct S *p; /* { dg-error "forward declaration" } */ +struct S *p; /* { dg-error "forward declaration" "" { target c++ } } */ float f; int j; @@ -12,10 +12,10 @@ foo (void) #pragma omp simd linear(p) linear(f : 1) for (int i = 0; i < 10; i++) ; -#pragma omp simd linear(j : 7.0) /* { dg-error "linear step expression must be integral" } */ +#pragma omp simd linear(j : 7.0) /* { dg-error "step expression must be integral" } */ for (int i = 0; i < 10; i++) ; } /* { dg-error "linear clause applied to" "" { target *-*-* } 12 } */ -/* { dg-error "incomplete type" "" { target *-*-* } 12 } */ +/* { dg-error "(incomplete|undefined) type" "" { target *-*-* } 12 } */ --- gcc/testsuite/c-c++-common/gomp/simd5.c.jj 2013-04-23 16:15:06.000000000 +0200 +++ gcc/testsuite/c-c++-common/gomp/simd5.c 2013-04-24 18:13:03.289897754 +0200 @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! c } } } */ +/* { dg-do compile } */ /* { dg-options "-fopenmp" } */ /* { dg-additional-options "-std=c99" { target c } } */ Jakub