Hi!

This patch brings the C FE roughly on feature parity with what
has been done earlier to the C++ FE only.
Thus, #pragma omp simd should work with C FE now, etc.

2013-04-24  Jakub Jelinek  <ja...@redhat.com>

c/
        * c-parser.c (c_parser_compound_statement,
        c_parser_statement): Adjust comments for OpenMP 3.0+
        additions.
        (c_parser_pragma): Handle PRAGMA_OMP_CANCEL and
        PRAGMA_OMP_CANCELLATION_POINT.
        (c_parser_omp_clause_name): Handle new OpenMP 4.0 clauses.
        (c_parser_omp_clause_collapse): Fully fold collapse
        expression.
        (c_parser_omp_clause_branch, c_parser_omp_clause_cancelkind,
        c_parser_omp_clause_num_teams, c_parser_omp_clause_aligned,
        c_parser_omp_clause_linear, c_parser_omp_clause_safelen,
        c_parser_omp_clause_simdlen, c_parser_omp_clause_depend,
        c_parser_omp_clause_map, c_parser_omp_clause_device,
        c_parser_omp_clause_dist_schedule, c_parser_omp_clause_proc_bind,
        c_parser_omp_clause_to, c_parser_omp_clause_from,
        c_parser_omp_clause_uniform): New functions.
        (c_parser_omp_all_clauses): Handle new OpenMP 4.0 clauses.
        (c_parser_omp_for_loop): Add CODE argument, pass it through
        to c_finish_omp_for.
        (OMP_SIMD_CLAUSE_MASK): Define.
        (c_parser_omp_simd): New function.
        (c_parser_omp_for): Parse #pragma omp for simd.
        (OMP_PARALLEL_CLAUSE_MASK): Add OMP_CLAUSE_PROC_BIND.
        (c_parser_omp_parallel): Parse #pragma omp parallel for simd.
        (OMP_TASK_CLAUSE_MASK): Add OMP_CLAUSE_DEPEND.
        (c_parser_omp_taskgroup): New function.
        (OMP_CANCEL_CLAUSE_MASK, OMP_CANCELLATION_POINT_CLAUSE_MASK): Define.
        (c_parser_omp_cancel, c_parser_omp_cancellation_point): New functions.
        (c_parser_omp_construct): Handle PRAGMA_OMP_SIMD and
        PRAGMA_OMP_TASKGROUP.
        (c_parser_transaction_cancel): Formatting fix.
        * c-tree.h (c_begin_omp_taskgroup, c_finish_omp_taskgroup,
        c_finish_omp_cancel, c_finish_omp_cancellation_point): New prototypes.
        * c-typeck.c (c_begin_omp_taskgroup, c_finish_omp_taskgroup,
        c_finish_omp_cancel, c_finish_omp_cancellation_point): New functions.
        (c_finish_omp_clauses): Handle new OpenMP 4.0 clauses.
cp/
        * parser.c (cp_parser_omp_clause_name): Add missing break after
        case 'i'.
        (cp_parser_omp_cancellation_point): Diagnose error if
        #pragma omp cancellation isn't followed by point.
        * semantics.c (finish_omp_clauses): Complain also about zero
        in alignment of aligned directive or safelen/simdlen expressions.
        (finish_omp_cancel): Fix up diagnostics wording.
testsuite/
        * c-c++-common/gomp/simd1.c: Enable also for C.
        * c-c++-common/gomp/simd2.c: Likewise.
        * c-c++-common/gomp/simd3.c: Likewise.
        * c-c++-common/gomp/simd4.c: Likewise.  Adjust expected
        diagnostics for C.
        * c-c++-common/gomp/simd5.c: Enable also for C.

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

        Jakub

Reply via email to