Hi! This patch adds changes similar to those that have been added for OpenMP 4.1 to the C FE so far. Note, taskloop with C++ class iterators isn't yet supported and the testsuite coverage is limited too.
2015-05-26 Jakub Jelinek <ja...@redhat.com> gcc/c/ * c-parser.c (c_parser_pragma): Return result of c_parser_omp_ordered instead of always returning false. (c_parser_omp_ordered): Return false or true depending on if it is a standalone directive or construct with body. (OMP_TARGET_UPDATE_CLAUSE_MASK): Allow depend and nowait clauses. (c_parser_omp_target): Return false for enter data and exit data. (c_parser_omp_taskloop): Mention composite taskloop simd construct. gcc/cp/ * parser.c (cp_parser_omp_clause_name): Handle grainsize, nogroup, num_tasks, priority, simd and threads clauses. (cp_parser_omp_clause_num_tasks, cp_parser_omp_clause_grainsize, cp_parser_omp_clause_priority): New functions. (cp_parser_omp_clause_ordered): Handle parsing of optional argument. (cp_parser_omp_clause_nogroup, cp_parser_omp_clause_orderedkind): New functions. (cp_parser_omp_clause_depend): Add LOC argument. Handle parsing of depend(source) and partially handle depend(sink:vec). (cp_parser_omp_clause_map): Parse optional always map type modifier. Handle parsing of delete map kind. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_{GRAINSIZE,NUM_TASKS,PRIORITY,NOGROUP,THREADS,SIMD}. (OMP_SIMD_CLAUSE_MASK): Add simdlen clause. (OMP_FOR_CLAUSE_MASK): Add linear clause. (OMP_ORDERED_CLAUSE_MASK, OMP_ORDERED_DEPEND_CLAUSE_MASK): Define. (cp_parser_omp_ordered): Handle parsing of the clauses, and if depend clause is present, parse it as standalone directive. Add CONTEXT argument. (OMP_TASK_CLAUSE_MASK): Add priority clause. (cp_parser_omp_target_data): Diagnose if no map clauses are present. (OMP_TARGET_ENTER_DATA_CLAUSE_MASK): Define. (cp_parser_omp_target_enter_data): New function. (OMP_TARGET_EXIT_DATA_CLAUSE_MASK): Define. (cp_parser_omp_target_exit_data): New function. (OMP_TARGET_UPDATE_CLAUSE_MASK, OMP_TARGET_CLAUSE_MASK): Add nowait and depend clauses. (cp_parser_omp_target): Handle #pragma omp target {enter,exit} data. (OMP_TASKLOOP_CLAUSE_MASK): Define. (cp_parser_omp_taskloop): New function. (cp_parser_omp_construct): Don't handle PRAGMA_OMP_ORDERED here. Handle PRAGMA_OMP_TASKLOOP. (cp_parser_pragma): Handle PRAGMA_OMP_ORDERED directly. Handle PRAGMA_OMP_TASKLOOP. * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_NUM_TASKS, OMP_CLAUSE_GRAINSIZE, OMP_CLAUSE_PRIORITY, OMP_CLAUSE_NOGROUP, OMP_CLAUSE_THREADS, OMP_CLAUSE_SIMD. Handle argument of OMP_CLAUSE_ORDERED. (tsubst_expr): Handle OMP_TASKLOOP. * semantics.c (finish_omp_clauses): Allow NULL OMP_CLAUSE_DECL for OMP_CLAUSE_DEPEND_SOURCE. Diagnose simdlen > safelen. Handle OMP_CLAUSE_{PRIORITY,GRAINSIZE,NUM_TASKS,NOGROUP,THREADS,SIMD} clauses. Warn about non-positive num_threads/num_teams/thread_limit arguments. * cp-gimplify.c (cp_gimplify_expr, cp_genericize_r): Handle OMP_TASKLOOP. * cp-tree.h (OMP_FOR_GIMPLIFYING_P): Adjust comment to include OMP_TASKLOOP. gcc/testsuite/ * gcc.dg/gomp/taskloop-1.c: Moved to... * c-c++-common/taskloop-1.c: ... here. New file. libgomp/ * testsuite/libgomp.c++/for-12.C: New test. * testsuite/libgomp.c++/taskloop-1.C: New test. * testsuite/libgomp.c++/taskloop-2.C: New test. * testsuite/libgomp.c++/taskloop-3.C: New test. * testsuite/libgomp.c++/taskloop-4.C: New test. --- gcc/c/c-parser.c.jj 2015-05-19 18:56:46.000000000 +0200 +++ gcc/c/c-parser.c 2015-05-26 19:12:30.919027239 +0200 @@ -9751,8 +9751,7 @@ c_parser_pragma (c_parser *parser, enum return false; case PRAGMA_OMP_ORDERED: - c_parser_omp_ordered (parser, context); - return false; + return c_parser_omp_ordered (parser, context); case PRAGMA_IVDEP: c_parser_consume_pragma (parser); @@ -13663,14 +13662,16 @@ c_parser_omp_ordered (c_parser *parser, = c_parser_omp_all_clauses (parser, OMP_ORDERED_DEPEND_CLAUSE_MASK, "#pragma omp ordered"); - return c_finish_omp_ordered (loc, clauses, NULL_TREE); + c_finish_omp_ordered (loc, clauses, NULL_TREE); + return false; } } tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK, "#pragma omp ordered"); - return c_finish_omp_ordered (loc, clauses, - c_parser_omp_structured_block (parser)); + c_finish_omp_ordered (loc, clauses, + c_parser_omp_structured_block (parser)); + return true; } /* OpenMP 2.5: @@ -14242,7 +14243,9 @@ c_parser_omp_target_data (location_t loc ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static bool c_parser_omp_target_update (location_t loc, c_parser *parser, @@ -14512,13 +14515,13 @@ c_parser_omp_target (c_parser *parser, e { c_parser_consume_token (parser); c_parser_omp_target_enter_data (loc, parser, context); - return true; + return false; } else if (strcmp (p, "exit") == 0) { c_parser_consume_token (parser); c_parser_omp_target_exit_data (loc, parser, context); - return true; + return false; } else if (strcmp (p, "update") == 0) { @@ -15212,6 +15215,9 @@ c_parser_omp_declare (c_parser *parser, /* OpenMP 4.1: #pragma omp taskloop taskloop-clause[optseq] new-line + for-loop + + #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line for-loop */ #define OMP_TASKLOOP_CLAUSE_MASK \ --- gcc/cp/parser.c.jj 2015-05-19 18:57:10.000000000 +0200 +++ gcc/cp/parser.c 2015-05-26 19:11:13.155223164 +0200 @@ -27631,6 +27631,10 @@ cp_parser_omp_clause_name (cp_parser *pa else if (!strcmp ("from", p)) result = PRAGMA_OMP_CLAUSE_FROM; break; + case 'g': + if (!strcmp ("grainsize", p)) + result = PRAGMA_OMP_CLAUSE_GRAINSIZE; + break; case 'h': if (!strcmp ("host", p)) result = PRAGMA_OACC_CLAUSE_HOST; @@ -27654,7 +27658,9 @@ cp_parser_omp_clause_name (cp_parser *pa result = PRAGMA_CILK_CLAUSE_MASK; break; case 'n': - if (!strcmp ("notinbranch", p)) + if (!strcmp ("nogroup", p)) + result = PRAGMA_OMP_CLAUSE_NOGROUP; + else if (!strcmp ("notinbranch", p)) result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; else if (!strcmp ("nowait", p)) result = PRAGMA_OMP_CLAUSE_NOWAIT; @@ -27662,6 +27668,8 @@ cp_parser_omp_clause_name (cp_parser *pa result = PRAGMA_CILK_CLAUSE_NOMASK; else if (!strcmp ("num_gangs", p)) result = PRAGMA_OACC_CLAUSE_NUM_GANGS; + else if (!strcmp ("num_tasks", p)) + result = PRAGMA_OMP_CLAUSE_NUM_TASKS; else if (!strcmp ("num_teams", p)) result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; else if (!strcmp ("num_threads", p)) @@ -27690,6 +27698,8 @@ cp_parser_omp_clause_name (cp_parser *pa else if (!strcmp ("present_or_create", p) || !strcmp ("pcreate", p)) result = PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE; + else if (!strcmp ("priority", p)) + result = PRAGMA_OMP_CLAUSE_PRIORITY; else if (!strcmp ("proc_bind", p)) result = PRAGMA_OMP_CLAUSE_PROC_BIND; break; @@ -27708,6 +27718,8 @@ cp_parser_omp_clause_name (cp_parser *pa result = PRAGMA_OACC_CLAUSE_SELF; else if (!strcmp ("shared", p)) result = PRAGMA_OMP_CLAUSE_SHARED; + else if (!strcmp ("simd", p)) + result = PRAGMA_OMP_CLAUSE_SIMD; else if (!strcmp ("simdlen", p)) result = PRAGMA_OMP_CLAUSE_SIMDLEN; break; @@ -27716,6 +27728,8 @@ cp_parser_omp_clause_name (cp_parser *pa result = PRAGMA_OMP_CLAUSE_TASKGROUP; else if (!strcmp ("thread_limit", p)) result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT; + else if (!strcmp ("threads", p)) + result = PRAGMA_OMP_CLAUSE_THREADS; else if (!strcmp ("to", p)) result = PRAGMA_OMP_CLAUSE_TO; break; @@ -28400,6 +28414,96 @@ cp_parser_omp_clause_num_threads (cp_par return c; } +/* OpenMP 4.1: + num_tasks ( expression ) */ + +static tree +cp_parser_omp_clause_num_tasks (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_expression (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_NUM_TASKS, + "num_tasks", location); + + c = build_omp_clause (location, OMP_CLAUSE_NUM_TASKS); + OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 4.1: + grainsize ( expression ) */ + +static tree +cp_parser_omp_clause_grainsize (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_expression (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_GRAINSIZE, + "grainsize", location); + + c = build_omp_clause (location, OMP_CLAUSE_GRAINSIZE); + OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 4.1: + priority ( expression ) */ + +static tree +cp_parser_omp_clause_priority (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_expression (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_GRAINSIZE, + "priority", location); + + c = build_omp_clause (location, OMP_CLAUSE_PRIORITY); + OMP_CLAUSE_PRIORITY_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + /* OpenACC: num_workers ( expression ) */ @@ -28438,19 +28542,49 @@ cp_parser_omp_clause_num_workers (cp_par } /* OpenMP 2.5: - ordered */ + ordered + + OpenMP 4.1: + ordered ( constant-expression ) */ static tree -cp_parser_omp_clause_ordered (cp_parser * /*parser*/, +cp_parser_omp_clause_ordered (cp_parser *parser, tree list, location_t location) { - tree c; + tree c, num = NULL_TREE; + HOST_WIDE_INT n; check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered", location); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + cp_lexer_consume_token (parser->lexer); + + num = cp_parser_constant_expression (parser); + + if (!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); + + if (num == error_mark_node) + return list; + num = fold_non_dependent_expr (num); + if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) + || !tree_fits_shwi_p (num) + || (n = tree_to_shwi (num)) <= 0 + || (int) n != n) + { + error_at (location, + "ordered argument needs positive constant integer " + "expression"); + return list; + } + } + c = build_omp_clause (location, OMP_CLAUSE_ORDERED); - OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; + OMP_CLAUSE_ORDERED_EXPR (c) = num; OMP_CLAUSE_CHAIN (c) = list; return c; } @@ -28702,6 +28836,34 @@ cp_parser_omp_clause_cancelkind (cp_pars return c; } +/* OpenMP 4.1: + nogroup */ + +static tree +cp_parser_omp_clause_nogroup (cp_parser * /*parser*/, + tree list, location_t location) +{ + check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup", location); + tree c = build_omp_clause (location, OMP_CLAUSE_NOGROUP); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 4.1: + simd + threads */ + +static tree +cp_parser_omp_clause_orderedkind (cp_parser * /*parser*/, + enum omp_clause_code code, + tree list, location_t location) +{ + check_no_duplicate_clause (list, code, omp_clause_code_name[code], location); + tree c = build_omp_clause (location, code); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 4.0: num_teams ( expression ) */ @@ -28900,10 +29062,16 @@ cp_parser_omp_clause_simdlen (cp_parser depend ( depend-kind : variable-list ) depend-kind: - in | out | inout */ + in | out | inout + + OpenMP 4.1: + depend ( depend-loop-kind [ : vec ] ) + + depend-loop-kind: + source | sink */ static tree -cp_parser_omp_clause_depend (cp_parser *parser, tree list) +cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) { tree nlist, c; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; @@ -28922,6 +29090,10 @@ cp_parser_omp_clause_depend (cp_parser * kind = OMP_CLAUSE_DEPEND_INOUT; else if (strcmp ("out", p) == 0) kind = OMP_CLAUSE_DEPEND_OUT; + else if (strcmp ("source", p) == 0) + kind = OMP_CLAUSE_DEPEND_SOURCE; + else if (strcmp ("sink", p) == 0) + kind = OMP_CLAUSE_DEPEND_SINK; else goto invalid_kind; } @@ -28929,6 +29101,22 @@ cp_parser_omp_clause_depend (cp_parser * goto invalid_kind; cp_lexer_consume_token (parser->lexer); + + if (kind == OMP_CLAUSE_DEPEND_SOURCE) + { + c = build_omp_clause (loc, OMP_CLAUSE_DEPEND); + OMP_CLAUSE_DEPEND_KIND (c) = kind; + OMP_CLAUSE_DECL (c) = NULL_TREE; + OMP_CLAUSE_CHAIN (c) = list; + if (!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); + return c; + } + + /* FIXME: Handle OMP_CLAUSE_DEPEND_SINK. */ + if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) goto resync_fail; @@ -28954,17 +29142,46 @@ cp_parser_omp_clause_depend (cp_parser * map ( variable-list ) map-kind: - alloc | to | from | tofrom */ + alloc | to | from | tofrom + + OpenMP 4.1: + map-kind: + alloc | to | from | tofrom | delete + + map ( always [,] map-kind: variable-list ) */ static tree cp_parser_omp_clause_map (cp_parser *parser, tree list) { tree nlist, c; enum gomp_map_kind kind = GOMP_MAP_TOFROM; + bool always = false; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; + 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 ("always", p) == 0) + { + int nth = 2; + if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COMMA) + nth++; + if (cp_lexer_peek_nth_token (parser->lexer, nth)->type == CPP_NAME + && (cp_lexer_peek_nth_token (parser->lexer, nth + 1)->type + == CPP_COLON)) + { + always = true; + cp_lexer_consume_token (parser->lexer); + if (nth == 3) + cp_lexer_consume_token (parser->lexer); + } + } + } + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON) { @@ -28979,6 +29196,8 @@ cp_parser_omp_clause_map (cp_parser *par kind = GOMP_MAP_FROM; else if (strcmp ("tofrom", p) == 0) kind = GOMP_MAP_TOFROM; + else if (strcmp ("delete", p) == 0) + kind = GOMP_MAP_FORCE_DEALLOC; else { cp_parser_error (parser, "invalid map kind"); @@ -28987,6 +29206,8 @@ cp_parser_omp_clause_map (cp_parser *par /*consume_paren=*/true); return list; } + if (always) + kind = (enum gomp_map_kind) (kind | GOMP_MAP_FLAG_FORCE); cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer); } @@ -29360,6 +29581,11 @@ cp_parser_omp_all_clauses (cp_parser *pa clauses); c_name = "firstprivate"; break; + case PRAGMA_OMP_CLAUSE_GRAINSIZE: + clauses = cp_parser_omp_clause_grainsize (parser, clauses, + token->location); + c_name = "grainsize"; + break; case PRAGMA_OMP_CLAUSE_IF: clauses = cp_parser_omp_clause_if (parser, clauses, token->location); c_name = "if"; @@ -29378,6 +29604,11 @@ cp_parser_omp_all_clauses (cp_parser *pa clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location); c_name = "nowait"; break; + case PRAGMA_OMP_CLAUSE_NUM_TASKS: + clauses = cp_parser_omp_clause_num_tasks (parser, clauses, + token->location); + c_name = "num_tasks"; + break; case PRAGMA_OMP_CLAUSE_NUM_THREADS: clauses = cp_parser_omp_clause_num_threads (parser, clauses, token->location); @@ -29388,6 +29619,11 @@ cp_parser_omp_all_clauses (cp_parser *pa token->location); c_name = "ordered"; break; + case PRAGMA_OMP_CLAUSE_PRIORITY: + clauses = cp_parser_omp_clause_priority (parser, clauses, + token->location); + c_name = "priority"; + break; case PRAGMA_OMP_CLAUSE_PRIVATE: clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses); @@ -29494,7 +29730,8 @@ cp_parser_omp_all_clauses (cp_parser *pa c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: - clauses = cp_parser_omp_clause_depend (parser, clauses); + clauses = cp_parser_omp_clause_depend (parser, clauses, + token->location); c_name = "depend"; break; case PRAGMA_OMP_CLAUSE_MAP: @@ -29526,6 +29763,23 @@ cp_parser_omp_all_clauses (cp_parser *pa token->location); c_name = "simdlen"; break; + case PRAGMA_OMP_CLAUSE_NOGROUP: + clauses = cp_parser_omp_clause_nogroup (parser, clauses, + token->location); + c_name = "nogroup"; + break; + case PRAGMA_OMP_CLAUSE_THREADS: + clauses + = cp_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS, + clauses, token->location); + c_name = "threads"; + break; + case PRAGMA_OMP_CLAUSE_SIMD: + clauses + = cp_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD, + clauses, token->location); + c_name = "simd"; + break; case PRAGMA_CILK_CLAUSE_VECTORLENGTH: clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, true); c_name = "simdlen"; @@ -30689,6 +30943,7 @@ cp_omp_split_clauses (location_t loc, en #define OMP_SIMD_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ @@ -30739,6 +30994,7 @@ cp_parser_omp_simd (cp_parser *parser, c ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ @@ -30829,15 +31085,62 @@ cp_parser_omp_master (cp_parser *parser, /* OpenMP 2.5: # pragma omp ordered new-line + structured-block + + OpenMP 4.1: + # pragma omp ordered ordered-clauses new-line structured-block */ -static tree -cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok) +#define OMP_ORDERED_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) + +#define OMP_ORDERED_DEPEND_CLAUSE_MASK \ + (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) + +static bool +cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, + enum pragma_context context) { - location_t loc = cp_lexer_peek_token (parser->lexer)->location; - cp_parser_require_pragma_eol (parser, pragma_tok); - return c_finish_omp_ordered (loc, NULL_TREE, - cp_parser_omp_structured_block (parser)); + location_t loc = pragma_tok->location; + + if (context != pragma_stmt && context != pragma_compound) + { + cp_parser_error (parser, "expected declaration specifiers"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return 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, "depend") == 0) + { + if (context == pragma_stmt) + { + error_at (pragma_tok->location, "%<#pragma omp ordered%> with " + "%<depend%> clause may only be used in compound " + "statements"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return false; + } + tree clauses + = cp_parser_omp_all_clauses (parser, + OMP_ORDERED_DEPEND_CLAUSE_MASK, + "#pragma omp ordered", pragma_tok); + c_finish_omp_ordered (loc, clauses, NULL_TREE); + return false; + } + } + + tree clauses + = cp_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK, + "#pragma omp ordered", pragma_tok); + c_finish_omp_ordered (loc, clauses, + cp_parser_omp_structured_block (parser)); + return true; } /* OpenMP 2.5: @@ -31075,7 +31378,8 @@ cp_parser_omp_single (cp_parser *parser, | (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_DEPEND)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)) static tree cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok) @@ -31379,12 +31683,21 @@ cp_parser_omp_teams (cp_parser *parser, static tree cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok) { + tree clauses + = cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, + "#pragma omp target data", pragma_tok); + if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE) + { + error_at (pragma_tok->location, + "%<#pragma omp target data%> must contain at least one " + "%<map%> clause"); + return NULL_TREE; + } + tree stmt = make_node (OMP_TARGET_DATA); TREE_TYPE (stmt) = void_type_node; + OMP_TARGET_DATA_CLAUSES (stmt) = clauses; - OMP_TARGET_DATA_CLAUSES (stmt) - = cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, - "#pragma omp target data", pragma_tok); keep_next_level (true); OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser); @@ -31392,6 +31705,172 @@ cp_parser_omp_target_data (cp_parser *pa return add_stmt (stmt); } +/* OpenMP 4.1: + # pragma omp target enter data target-enter-data-clause[optseq] new-line + structured-block */ + +#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, + enum pragma_context context) +{ + bool data_seen = 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, "data") == 0) + { + cp_lexer_consume_token (parser->lexer); + data_seen = true; + } + } + if (!data_seen) + { + cp_parser_error (parser, "expected %<data%>"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + if (context == pragma_stmt) + { + error_at (pragma_tok->location, + "%<#pragma omp target enter data%> may only be " + "used in compound statements"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + tree clauses + = cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK, + "#pragma omp target enter data", pragma_tok); + int map_seen = 0; + for (tree *pc = &clauses; *pc;) + { + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) + switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE) + { + case GOMP_MAP_TO: + case GOMP_MAP_ALLOC: + map_seen = 3; + break; + default: + map_seen |= 1; + error_at (OMP_CLAUSE_LOCATION (*pc), + "%<#pragma omp target enter data%> with map-type other " + "than %<to%> or %<alloc%> on %<map%> clause"); + *pc = OMP_CLAUSE_CHAIN (*pc); + continue; + } + pc = &OMP_CLAUSE_CHAIN (*pc); + } + + if (map_seen != 3) + { + if (map_seen == 0) + error_at (pragma_tok->location, + "%<#pragma omp target enter data%> must contain at least " + "one %<map%> clause"); + return NULL_TREE; + } + + tree stmt = make_node (OMP_TARGET_ENTER_DATA); + TREE_TYPE (stmt) = void_type_node; + OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses; + SET_EXPR_LOCATION (stmt, pragma_tok->location); + return add_stmt (stmt); +} + +/* OpenMP 4.1: + # pragma omp target exit data target-enter-data-clause[optseq] new-line + structured-block */ + +#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, + enum pragma_context context) +{ + bool data_seen = 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, "data") == 0) + { + cp_lexer_consume_token (parser->lexer); + data_seen = true; + } + } + if (!data_seen) + { + cp_parser_error (parser, "expected %<data%>"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + if (context == pragma_stmt) + { + error_at (pragma_tok->location, + "%<#pragma omp target exit data%> may only be " + "used in compound statements"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + tree clauses + = cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK, + "#pragma omp target exit data", pragma_tok); + int map_seen = 0; + for (tree *pc = &clauses; *pc;) + { + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) + switch (OMP_CLAUSE_MAP_KIND (*pc) & ~GOMP_MAP_FLAG_FORCE) + { + case GOMP_MAP_FROM: + case GOMP_MAP_FORCE_DEALLOC & ~GOMP_MAP_FLAG_FORCE: + map_seen = 3; + break; + default: + map_seen |= 1; + error_at (OMP_CLAUSE_LOCATION (*pc), + "%<#pragma omp target exit data%> with map-type other " + "than %<from%> or %<delete%> on %<map%> clause"); + *pc = OMP_CLAUSE_CHAIN (*pc); + continue; + } + pc = &OMP_CLAUSE_CHAIN (*pc); + } + + if (map_seen != 3) + { + if (map_seen == 0) + error_at (pragma_tok->location, + "%<#pragma omp target exit data%> must contain at least " + "one %<map%> clause"); + return NULL_TREE; + } + + tree stmt = make_node (OMP_TARGET_EXIT_DATA); + TREE_TYPE (stmt) = void_type_node; + OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses; + SET_EXPR_LOCATION (stmt, pragma_tok->location); + return add_stmt (stmt); +} + /* OpenMP 4.0: # pragma omp target update target-update-clause[optseq] new-line */ @@ -31399,7 +31878,9 @@ cp_parser_omp_target_data (cp_parser *pa ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static bool cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, @@ -31441,7 +31922,9 @@ cp_parser_omp_target_update (cp_parser * #define OMP_TARGET_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static bool cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, @@ -31501,6 +31984,18 @@ cp_parser_omp_target (cp_parser *parser, cp_parser_omp_target_data (parser, pragma_tok); return true; } + else if (strcmp (p, "enter") == 0) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_omp_target_enter_data (parser, pragma_tok, context); + return false; + } + else if (strcmp (p, "exit") == 0) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_omp_target_exit_data (parser, pragma_tok, context); + return false; + } else if (strcmp (p, "update") == 0) { cp_lexer_consume_token (parser->lexer); @@ -32480,6 +32975,96 @@ cp_parser_omp_declare (cp_parser *parser cp_parser_require_pragma_eol (parser, pragma_tok); } +/* OpenMP 4.1: +7 #pragma omp taskloop taskloop-clause[optseq] new-line + for-loop + + #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line + for-loop */ + +#define OMP_TASKLOOP_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) + +static tree +cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) +{ + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " taskloop"); + mask |= OMP_TASKLOOP_CLAUSE_MASK; + + 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, "simd") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, + cclauses); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, + cclauses); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + ret = make_node (OMP_TASKLOOP); + TREE_TYPE (ret) = void_type_node; + OMP_FOR_BODY (ret) = body; + OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; + SET_EXPR_LOCATION (ret, loc); + add_stmt (ret); + return ret; + } + } + if (!flag_openmp) /* flag_openmp_simd */ + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; + } + + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + + ret = cp_parser_omp_for_loop (parser, OMP_TASKLOOP, clauses, cclauses); + + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + + return ret; +} + /* Main entry point to OpenMP statement pragmas. */ static void @@ -32535,9 +33120,6 @@ cp_parser_omp_construct (cp_parser *pars case PRAGMA_OMP_MASTER: stmt = cp_parser_omp_master (parser, pragma_tok); break; - case PRAGMA_OMP_ORDERED: - stmt = cp_parser_omp_ordered (parser, pragma_tok); - break; case PRAGMA_OMP_PARALLEL: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL); @@ -32559,6 +33141,10 @@ cp_parser_omp_construct (cp_parser *pars case PRAGMA_OMP_TASKGROUP: stmt = cp_parser_omp_taskgroup (parser, pragma_tok); break; + case PRAGMA_OMP_TASKLOOP: + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL); + break; case PRAGMA_OMP_TEAMS: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL); @@ -33074,19 +33660,22 @@ cp_parser_pragma (cp_parser *parser, enu case PRAGMA_OMP_DISTRIBUTE: case PRAGMA_OMP_FOR: case PRAGMA_OMP_MASTER: - case PRAGMA_OMP_ORDERED: case PRAGMA_OMP_PARALLEL: case PRAGMA_OMP_SECTIONS: case PRAGMA_OMP_SIMD: case PRAGMA_OMP_SINGLE: case PRAGMA_OMP_TASK: case PRAGMA_OMP_TASKGROUP: + case PRAGMA_OMP_TASKLOOP: case PRAGMA_OMP_TEAMS: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; cp_parser_omp_construct (parser, pragma_tok); return true; + case PRAGMA_OMP_ORDERED: + return cp_parser_omp_ordered (parser, pragma_tok, context); + case PRAGMA_OMP_TARGET: return cp_parser_omp_target (parser, pragma_tok, context); --- gcc/cp/pt.c.jj 2015-05-19 18:57:08.000000000 +0200 +++ gcc/cp/pt.c 2015-05-26 20:35:55.459063518 +0200 @@ -13476,6 +13476,10 @@ tsubst_omp_clauses (tree clauses, bool d case OMP_CLAUSE_THREAD_LIMIT: case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_SIMDLEN: + case OMP_CLAUSE_NUM_TASKS: + case OMP_CLAUSE_GRAINSIZE: + case OMP_CLAUSE_PRIORITY: + case OMP_CLAUSE_ORDERED: OMP_CLAUSE_OPERAND (nc, 0) = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl, /*integral_constant_expression_p=*/false); @@ -13511,7 +13515,6 @@ tsubst_omp_clauses (tree clauses, bool d break; case OMP_CLAUSE_NOWAIT: - case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: case OMP_CLAUSE_UNTIED: case OMP_CLAUSE_MERGEABLE: @@ -13522,6 +13525,9 @@ tsubst_omp_clauses (tree clauses, bool d case OMP_CLAUSE_PARALLEL: case OMP_CLAUSE_SECTIONS: case OMP_CLAUSE_TASKGROUP: + case OMP_CLAUSE_NOGROUP: + case OMP_CLAUSE_THREADS: + case OMP_CLAUSE_SIMD: break; default: gcc_unreachable (); @@ -14152,6 +14158,7 @@ tsubst_expr (tree t, tree args, tsubst_f case CILK_SIMD: case CILK_FOR: case OMP_DISTRIBUTE: + case OMP_TASKLOOP: { tree clauses, body, pre_body; tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE; --- gcc/cp/semantics.c.jj 2015-05-14 09:04:24.000000000 +0200 +++ gcc/cp/semantics.c 2015-05-26 17:07:46.203181761 +0200 @@ -5301,6 +5301,7 @@ finish_omp_clauses (tree clauses) bitmap_head generic_head, firstprivate_head, lastprivate_head; bitmap_head aligned_head; tree c, t, *pc; + tree safelen = NULL_TREE; bool branch_seen = false; bool copyprivate_seen = false; @@ -5484,7 +5485,17 @@ finish_omp_clauses (tree clauses) { t = mark_rvalue_use (t); if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<num_threads%> value must be positive"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; } break; @@ -5552,6 +5563,8 @@ finish_omp_clauses (tree clauses) } } OMP_CLAUSE_OPERAND (c, 0) = t; + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SAFELEN) + safelen = c; } break; @@ -5569,7 +5582,17 @@ finish_omp_clauses (tree clauses) { t = mark_rvalue_use (t); if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<num_teams%> value must be positive"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t; } break; @@ -5626,7 +5649,17 @@ finish_omp_clauses (tree clauses) { t = mark_rvalue_use (t); if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<thread_limit%> value must be positive"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t; } break; @@ -5736,6 +5769,12 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_DEPEND: t = OMP_CLAUSE_DECL (c); + if (t == NULL_TREE) + { + gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) + == OMP_CLAUSE_DEPEND_SOURCE); + break; + } if (TREE_CODE (t) == TREE_LIST) { if (handle_omp_array_sections (c)) @@ -5851,6 +5890,93 @@ finish_omp_clauses (tree clauses) } goto check_dup_generic; + case OMP_CLAUSE_NUM_TASKS: + t = OMP_CLAUSE_NUM_TASKS_EXPR (c); + if (t == error_mark_node) + remove = true; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error ("%<num_tasks%> expression must be integral"); + remove = true; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<num_tasks%> value must be positive"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } + OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; + } + break; + + case OMP_CLAUSE_GRAINSIZE: + t = OMP_CLAUSE_GRAINSIZE_EXPR (c); + if (t == error_mark_node) + remove = true; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error ("%<grainsize%> expression must be integral"); + remove = true; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) != 1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<grainsize%> value must be positive"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } + OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; + } + break; + + case OMP_CLAUSE_PRIORITY: + t = OMP_CLAUSE_PRIORITY_EXPR (c); + if (t == error_mark_node) + remove = true; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error ("%<priority%> expression must be integral"); + remove = true; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + if (TREE_CODE (t) == INTEGER_CST + && tree_int_cst_sgn (t) == -1) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "%<priority%> value must be non-negative"); + t = integer_one_node; + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } + OMP_CLAUSE_PRIORITY_EXPR (c) = t; + } + break; + case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: @@ -5862,6 +5988,9 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_SECTIONS: case OMP_CLAUSE_TASKGROUP: case OMP_CLAUSE_PROC_BIND: + case OMP_CLAUSE_NOGROUP: + case OMP_CLAUSE_THREADS: + case OMP_CLAUSE_SIMD: case OMP_CLAUSE__CILK_FOR_COUNT_: break; @@ -5929,6 +6058,20 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_COPYIN: need_copy_assignment = true; break; + case OMP_CLAUSE_SIMDLEN: + if (safelen + && !processing_template_decl + && tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen), + OMP_CLAUSE_SIMDLEN_EXPR (c))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<simdlen%> clause value is bigger than " + "%<safelen%> clause value"); + OMP_CLAUSE_SIMDLEN_EXPR (c) + = OMP_CLAUSE_SAFELEN_EXPR (safelen); + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { --- gcc/cp/cp-gimplify.c.jj 2015-05-14 09:04:22.000000000 +0200 +++ gcc/cp/cp-gimplify.c 2015-05-26 20:36:41.606354220 +0200 @@ -703,6 +703,7 @@ cp_gimplify_expr (tree *expr_p, gimple_s case OMP_FOR: case OMP_SIMD: case OMP_DISTRIBUTE: + case OMP_TASKLOOP: ret = cp_gimplify_omp_for (expr_p, pre_p); break; @@ -1258,7 +1259,8 @@ cp_genericize_r (tree *stmt_p, int *walk genericize_break_stmt (stmt_p); else if (TREE_CODE (stmt) == OMP_FOR || TREE_CODE (stmt) == OMP_SIMD - || TREE_CODE (stmt) == OMP_DISTRIBUTE) + || TREE_CODE (stmt) == OMP_DISTRIBUTE + || TREE_CODE (stmt) == OMP_TASKLOOP) genericize_omp_for_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == SIZEOF_EXPR) { --- gcc/cp/cp-tree.h.jj 2015-05-14 09:04:27.000000000 +0200 +++ gcc/cp/cp-tree.h 2015-05-26 20:38:50.527372666 +0200 @@ -65,7 +65,8 @@ c-common.h, not after. STMT_EXPR_NO_SCOPE (in STMT_EXPR) BIND_EXPR_TRY_BLOCK (in BIND_EXPR) TYPENAME_IS_ENUM_P (in TYPENAME_TYPE) - OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD and OMP_DISTRIBUTE) + OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD, OMP_DISTRIBUTE, + and OMP_TASKLOOP) BASELINK_QUALIFIED_P (in BASELINK) TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) --- gcc/testsuite/gcc.dg/gomp/taskloop-1.c.jj 2015-05-21 11:12:09.006296255 +0200 +++ gcc/testsuite/gcc.dg/gomp/taskloop-1.c 2015-05-26 19:25:26.159104871 +0200 @@ -1,15 +0,0 @@ -/* { dg-do compile } */ - -int e; -int bar (int, int); -void baz (int, int, int, int *, int *, int *); - -void -foo (int a, int b, int c, int d, int f, int g, int h, int j, int k, int l) -{ - int i; - #pragma omp taskloop if (a) final (b) untied default(none) mergeable \ - private(c) firstprivate (e) shared (d) num_tasks(f) collapse(1) - for (i = bar (g, h) + j; i < k; i += l) - baz (i, d, e++, &c, &d, &e); -} --- gcc/testsuite/c-c++-common/taskloop-1.c.jj 2015-05-26 17:43:48.848895803 +0200 +++ gcc/testsuite/c-c++-common/taskloop-1.c 2015-05-21 11:12:09.006296255 +0200 @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +int e; +int bar (int, int); +void baz (int, int, int, int *, int *, int *); + +void +foo (int a, int b, int c, int d, int f, int g, int h, int j, int k, int l) +{ + int i; + #pragma omp taskloop if (a) final (b) untied default(none) mergeable \ + private(c) firstprivate (e) shared (d) num_tasks(f) collapse(1) + for (i = bar (g, h) + j; i < k; i += l) + baz (i, d, e++, &c, &d, &e); +} --- libgomp/testsuite/libgomp.c++/for-12.C.jj 2015-05-26 17:41:46.677775961 +0200 +++ libgomp/testsuite/libgomp.c++/for-12.C 2015-05-26 17:42:17.875295808 +0200 @@ -0,0 +1,42 @@ +/* { dg-options "-fopenmp" } */ + +extern "C" void abort (void); + +#define M(x, y, z) O(x, y, z) +#define O(x, y, z) x ## _ ## y ## _ ## z + +#define F taskloop +#define G taskloop +#define S +#define N(x) M(x, G, normal) +#include "../libgomp.c/for-2.h" +#undef S +#undef N +#undef F +#undef G + +#define F taskloop simd +#define G taskloop_simd +#define S +#define N(x) M(x, G, normal) +#include "../libgomp.c/for-2.h" +#undef S +#undef N +#undef F +#undef G + +int +main () +{ + int err = 0; + #pragma omp parallel reduction(|:err) + #pragma omp single + { + if (test_taskloop_normal () + || test_taskloop_simd_normal ()) + err = 1; + } + if (err) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c++/taskloop-1.C.jj 2015-05-26 17:39:00.704330417 +0200 +++ libgomp/testsuite/libgomp.c++/taskloop-1.C 2015-05-26 17:38:52.636454587 +0200 @@ -0,0 +1,4 @@ +// { dg-do run } +// { dg-options "-O2 -fopenmp" } + +#include "../libgomp.c/taskloop-1.c" --- libgomp/testsuite/libgomp.c++/taskloop-2.C.jj 2015-05-26 17:39:07.731222268 +0200 +++ libgomp/testsuite/libgomp.c++/taskloop-2.C 2015-05-26 17:39:40.773713719 +0200 @@ -0,0 +1,6 @@ +// { dg-do run } +// { dg-options "-O2" } +// { dg-additional-options "-msse2" { target sse2_runtime } } +// { dg-additional-options "-mavx" { target avx_runtime } } + +#include "../libgomp.c/taskloop-2.c" --- libgomp/testsuite/libgomp.c++/taskloop-3.C.jj 2015-05-26 17:39:56.670469056 +0200 +++ libgomp/testsuite/libgomp.c++/taskloop-3.C 2015-05-26 17:40:01.194399429 +0200 @@ -0,0 +1,4 @@ +// { dg-do run } +// { dg-options "-O2 -fopenmp" } + +#include "../libgomp.c/taskloop-3.c" --- libgomp/testsuite/libgomp.c++/taskloop-4.C.jj 2015-05-26 17:40:58.897511335 +0200 +++ libgomp/testsuite/libgomp.c++/taskloop-4.C 2015-05-26 17:41:07.589377561 +0200 @@ -0,0 +1,4 @@ +// { dg-do run } +// { dg-options "-O2 -fopenmp" } + +#include "../libgomp.c/taskloop-4.c" Jakub