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

Reply via email to