]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/c/c-parser.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / c / c-parser.c
index d85bff0a2d982081773fa27ae194e7219c6aef9d..d08d1d0bcf1d83ff957a006b05ffb8f447103e1d 100644 (file)
@@ -1,7 +1,5 @@
 /* Parser for C and Objective-C.
-   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
-   2012 Free Software Foundation, Inc.
+   Copyright (C) 1987-2013 Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
    influenced by and fragments based on the C++ parser.
@@ -42,12 +40,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
 #include "tree.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "trans-mem.h"
 #include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
 #include "timevar.h"
 #include "c-family/c-pragma.h"
 #include "c-tree.h"
+#include "c-lang.h"
 #include "flags.h"
 #include "ggc.h"
 #include "c-family/c-common.h"
@@ -56,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "cgraph.h"
 #include "plugin.h"
+#include "omp-low.h"
 
 \f
 /* Initialization routine for this file.  */
@@ -164,9 +169,12 @@ typedef struct GTY (()) c_token {
    tokens of look-ahead; more are not needed for C.  */
 typedef struct GTY(()) c_parser {
   /* The look-ahead tokens.  */
-  c_token tokens[2];
-  /* How many look-ahead tokens are available (0, 1 or 2).  */
-  short tokens_avail;
+  c_token * GTY((skip)) tokens;
+  /* Buffer for look-ahead tokens.  */
+  c_token tokens_buf[2];
+  /* How many look-ahead tokens are available (0, 1 or 2, or
+     more if parsing from pre-lexed tokens).  */
+  unsigned int tokens_avail;
   /* True if a syntax error is being recovered from; false otherwise.
      c_parser_error sets this flag.  It should clear this flag when
      enough tokens have been consumed to recover from the error.  */
@@ -491,12 +499,14 @@ c_token_starts_typename (c_token *token)
        case RID_UNION:
        case RID_TYPEOF:
        case RID_CONST:
+       case RID_ATOMIC:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_FRACT:
        case RID_ACCUM:
        case RID_SAT:
+       case RID_AUTO_TYPE:
          return true;
        default:
          return false;
@@ -573,6 +583,7 @@ c_token_is_qualifier (c_token *token)
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
+       case RID_ATOMIC:
          return true;
        default:
          return false;
@@ -653,6 +664,8 @@ c_token_starts_declspecs (c_token *token)
        case RID_ACCUM:
        case RID_SAT:
        case RID_ALIGNAS:
+       case RID_ATOMIC:
+       case RID_AUTO_TYPE:
          return true;
        default:
          return false;
@@ -738,7 +751,9 @@ c_parser_consume_token (c_parser *parser)
   gcc_assert (parser->tokens[0].type != CPP_EOF);
   gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
   gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
-  if (parser->tokens_avail == 2)
+  if (parser->tokens != &parser->tokens_buf[0])
+    parser->tokens++;
+  else if (parser->tokens_avail == 2)
     parser->tokens[0] = parser->tokens[1];
   parser->tokens_avail--;
 }
@@ -752,7 +767,9 @@ c_parser_consume_pragma (c_parser *parser)
   gcc_assert (!parser->in_pragma);
   gcc_assert (parser->tokens_avail >= 1);
   gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
-  if (parser->tokens_avail == 2)
+  if (parser->tokens != &parser->tokens_buf[0])
+    parser->tokens++;
+  else if (parser->tokens_avail == 2)
     parser->tokens[0] = parser->tokens[1];
   parser->tokens_avail--;
   parser->in_pragma = true;
@@ -1114,11 +1131,11 @@ enum c_parser_prec {
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
-                                          bool, bool, tree *);
+                                          bool, bool, tree *, vec<c_token>);
 static void c_parser_static_assert_declaration_no_semi (c_parser *);
 static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
-                               bool, enum c_lookahead_kind);
+                               bool, bool, bool, enum c_lookahead_kind);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
 static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
 static tree c_parser_struct_declaration (c_parser *);
@@ -1150,18 +1167,19 @@ static void c_parser_statement (c_parser *);
 static void c_parser_statement_after_labels (c_parser *);
 static void c_parser_if_statement (c_parser *);
 static void c_parser_switch_statement (c_parser *);
-static void c_parser_while_statement (c_parser *);
-static void c_parser_do_statement (c_parser *);
-static void c_parser_for_statement (c_parser *);
+static void c_parser_while_statement (c_parser *, bool);
+static void c_parser_do_statement (c_parser *, bool);
+static void c_parser_for_statement (c_parser *, bool);
 static tree c_parser_asm_statement (c_parser *);
-static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_operands (c_parser *);
 static tree c_parser_asm_goto_operands (c_parser *);
 static tree c_parser_asm_clobbers (c_parser *);
-static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
+static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
+                                             tree = NULL_TREE);
 static struct c_expr c_parser_conditional_expression (c_parser *,
-                                                     struct c_expr *);
+                                                     struct c_expr *, tree);
 static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
-                                                enum c_parser_prec);
+                                                tree);
 static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
 static struct c_expr c_parser_unary_expression (c_parser *);
 static struct c_expr c_parser_sizeof_expression (c_parser *);
@@ -1187,9 +1205,15 @@ static void c_parser_omp_barrier (c_parser *);
 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 };
+enum pragma_context { pragma_external, pragma_struct, pragma_param,
+                     pragma_stmt, pragma_compound };
 static bool c_parser_pragma (c_parser *, enum pragma_context);
+static bool c_parser_omp_target (c_parser *, enum pragma_context);
+static void c_parser_omp_end_declare_target (c_parser *);
+static void c_parser_omp_declare (c_parser *, enum pragma_context);
 
 /* These Objective-C parser functions are only ever called when
    compiling Objective-C.  */
@@ -1218,6 +1242,11 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+/* Cilk Plus supporting routines.  */
+static void c_parser_cilk_simd (c_parser *);
+static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
+static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -1360,11 +1389,14 @@ c_parser_external_declaration (c_parser *parser)
         an @interface or @protocol with prefix attributes).  We can
         only tell which after parsing the declaration specifiers, if
         any, and the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+                                    NULL, vNULL);
       break;
     }
 }
 
+static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
    accepted; otherwise (old-style parameter declarations) only other
@@ -1440,7 +1472,8 @@ static void
 c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
                               bool static_assert_ok, bool empty_ok,
                               bool nested, bool start_attr_ok,
-                              tree *objc_foreach_object_declaration)
+                              tree *objc_foreach_object_declaration,
+                              vec<c_token> omp_declare_simd_clauses)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -1475,7 +1508,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       fndef_ok = !nested;
     }
 
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok,
+                     true, true, cla_nonabstract_decl);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1488,9 +1522,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       return;
     }
   finish_declspecs (specs);
+  bool auto_type_p = specs->typespec_word == cts_auto_type;
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
-      if (empty_ok)
+      if (auto_type_p)
+       error_at (here, "%<__auto_type%> in empty declaration");
+      else if (empty_ok)
        shadow_tag (specs);
       else
        {
@@ -1513,7 +1550,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       shadow_tag_warned (specs, 1);
       return;
     }
-  else if (c_dialect_objc ())
+  else if (c_dialect_objc () && !auto_type_p)
     {
       /* Prefix attributes are an error on method decls.  */
       switch (c_parser_peek_token (parser)->type)
@@ -1610,6 +1647,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
                                        C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
        {
+         if (omp_declare_simd_clauses.exists ())
+           c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
+                                      omp_declare_simd_clauses);
+         c_parser_skip_to_end_of_block_or_statement (parser);
+         return;
+       }
+      if (auto_type_p && declarator->kind != cdk_id)
+       {
+         error_at (here,
+                   "%<__auto_type%> requires a plain identifier"
+                   " as declarator");
          c_parser_skip_to_end_of_block_or_statement (parser);
          return;
        }
@@ -1640,16 +1688,72 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
              struct c_expr init;
              location_t init_loc;
              c_parser_consume_token (parser);
-             /* The declaration of the variable is in effect while
-                its initializer is parsed.  */
-             d = start_decl (declarator, specs, true,
-                             chainon (postfix_attrs, all_prefix_attrs));
-             if (!d)
-               d = error_mark_node;
-             start_init (d, asm_name, global_bindings_p ());
-             init_loc = c_parser_peek_token (parser)->location;
-             init = c_parser_initializer (parser);
-             finish_init ();
+             if (auto_type_p)
+               {
+                 start_init (NULL_TREE, asm_name, global_bindings_p ());
+                 init_loc = c_parser_peek_token (parser)->location;
+                 init = c_parser_expr_no_commas (parser, NULL);
+                 if (TREE_CODE (init.value) == COMPONENT_REF
+                     && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
+                   error_at (here,
+                             "%<__auto_type%> used with a bit-field"
+                             " initializer");
+                 init = convert_lvalue_to_rvalue (init_loc, init, true, true);
+                 tree init_type = TREE_TYPE (init.value);
+                 /* As with typeof, remove _Atomic and const
+                    qualifiers from atomic types.  */
+                 if (init_type != error_mark_node && TYPE_ATOMIC (init_type))
+                   init_type
+                     = c_build_qualified_type (init_type,
+                                               (TYPE_QUALS (init_type)
+                                                & ~(TYPE_QUAL_ATOMIC
+                                                    | TYPE_QUAL_CONST)));
+                 bool vm_type = variably_modified_type_p (init_type,
+                                                          NULL_TREE);
+                 if (vm_type)
+                   init.value = c_save_expr (init.value);
+                 finish_init ();
+                 specs->typespec_kind = ctsk_typeof;
+                 specs->locations[cdw_typedef] = init_loc;
+                 specs->typedef_p = true;
+                 specs->type = init_type;
+                 if (vm_type)
+                   {
+                     bool maybe_const = true;
+                     tree type_expr = c_fully_fold (init.value, false,
+                                                    &maybe_const);
+                     specs->expr_const_operands &= maybe_const;
+                     if (specs->expr)
+                       specs->expr = build2 (COMPOUND_EXPR,
+                                             TREE_TYPE (type_expr),
+                                             specs->expr, type_expr);
+                     else
+                       specs->expr = type_expr;
+                   }
+                 d = start_decl (declarator, specs, true,
+                                 chainon (postfix_attrs, all_prefix_attrs));
+                 if (!d)
+                   d = error_mark_node;
+                 if (omp_declare_simd_clauses.exists ())
+                   c_finish_omp_declare_simd (parser, d, NULL_TREE,
+                                              omp_declare_simd_clauses);
+               }
+             else
+               {
+                 /* The declaration of the variable is in effect while
+                    its initializer is parsed.  */
+                 d = start_decl (declarator, specs, true,
+                                 chainon (postfix_attrs, all_prefix_attrs));
+                 if (!d)
+                   d = error_mark_node;
+                 if (omp_declare_simd_clauses.exists ())
+                   c_finish_omp_declare_simd (parser, d, NULL_TREE,
+                                              omp_declare_simd_clauses);
+                 start_init (d, asm_name, global_bindings_p ());
+                 init_loc = c_parser_peek_token (parser)->location;
+                 init = c_parser_initializer (parser);
+                 finish_init ();
+               }
              if (d != error_mark_node)
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
@@ -1659,9 +1763,39 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
            }
          else
            {
+             if (auto_type_p)
+               {
+                 error_at (here,
+                           "%<__auto_type%> requires an initialized "
+                           "data declaration");
+                 c_parser_skip_to_end_of_block_or_statement (parser);
+                 return;
+               }
              tree d = start_decl (declarator, specs, false,
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
+             if (omp_declare_simd_clauses.exists ())
+               {
+                 tree parms = NULL_TREE;
+                 if (d && TREE_CODE (d) == FUNCTION_DECL)
+                   {
+                     struct c_declarator *ce = declarator;
+                     while (ce != NULL)
+                       if (ce->kind == cdk_function)
+                         {
+                           parms = ce->u.arg_info->parms;
+                           break;
+                         }
+                       else
+                         ce = ce->declarator;
+                   }
+                 if (parms)
+                   temp_store_parm_decls (d, parms);
+                 c_finish_omp_declare_simd (parser, d, parms,
+                                            omp_declare_simd_clauses);
+                 if (parms)
+                   temp_pop_parm_decls ();
+               }
              if (d)
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
                             NULL_TREE, asm_name);
@@ -1676,6 +1810,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
+             if (auto_type_p)
+               {
+                 error_at (here,
+                           "%<__auto_type%> may only be used with"
+                           " a single declarator");
+                 c_parser_skip_to_end_of_block_or_statement (parser);
+                 return;
+               }
              c_parser_consume_token (parser);
              if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
                all_prefix_attrs = chainon (c_parser_attributes (parser),
@@ -1705,6 +1847,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
              return;
            }
        }
+      else if (auto_type_p)
+       {
+         error_at (here,
+                   "%<__auto_type%> requires an initialized data declaration");
+         c_parser_skip_to_end_of_block_or_statement (parser);
+         return;
+       }
       else if (!fndef_ok)
        {
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
@@ -1751,11 +1900,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
        c_parser_declaration_or_fndef (parser, false, false, false,
-                                      true, false, NULL);
+                                      true, false, NULL, vNULL);
       store_parm_decls ();
+      if (omp_declare_simd_clauses.exists ())
+       c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
+                                  omp_declare_simd_clauses);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
+      if (flag_enable_cilkplus && contains_array_notation_expr (fnbody))
+       fnbody = expand_array_notation_exprs (fnbody);
       if (nested)
        {
          tree decl = current_function_decl;
@@ -1890,8 +2044,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
 /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
    6.7), adding them to SPECS (which may already include some).
    Storage class specifiers are accepted iff SCSPEC_OK; type
-   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
-   the start iff START_ATTR_OK.
+   specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
+   accepted iff ALIGNSPEC_OK; attributes are accepted at the start
+   iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK.
 
    declaration-specifiers:
      storage-class-specifier declaration-specifiers[opt]
@@ -1911,6 +2066,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
      static
      auto
      register
+     _Thread_local
+
+   (_Thread_local is new in C11.)
 
    C99 6.7.4:
    function-specifier:
@@ -1936,8 +2094,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
      struct-or-union-specifier
      enum-specifier
      typedef-name
+     atomic-type-specifier
 
    (_Bool and _Complex are new in C99.)
+   (atomic-type-specifier is new in C11.)
 
    C90 6.5.3, C99 6.7.3:
 
@@ -1946,8 +2106,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
      restrict
      volatile
      address-space-qualifier
+     _Atomic
 
    (restrict is new in C99.)
+   (_Atomic is new in C11.)
 
    GNU extensions:
 
@@ -1965,6 +2127,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
 
    type-specifier:
      typeof-specifier
+     __auto_type
      __int128
      _Decimal32
      _Decimal64
@@ -1976,6 +2139,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
   (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
 
+   atomic-type-specifier
+    _Atomic ( type-name )
+
    Objective-C:
 
    type-specifier:
@@ -1987,6 +2153,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
 static void
 c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
                    bool scspec_ok, bool typespec_ok, bool start_attr_ok,
+                   bool alignspec_ok, bool auto_type_ok,
                    enum c_lookahead_kind la)
 {
   bool attrs_ok = start_attr_ok;
@@ -2109,6 +2276,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
                                c_parser_peek_token (parser)->value);
          c_parser_consume_token (parser);
          break;
+       case RID_AUTO_TYPE:
+         if (!auto_type_ok)
+           goto out;
+         /* Fall through.  */
        case RID_UNSIGNED:
        case RID_LONG:
        case RID_INT128:
@@ -2169,6 +2340,64 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          t = c_parser_typeof_specifier (parser);
          declspecs_add_type (loc, specs, t);
          break;
+       case RID_ATOMIC:
+         /* C parser handling of Objective-C constructs needs
+            checking for correct lvalue-to-rvalue conversions, and
+            the code in build_modify_expr handling various
+            Objective-C cases, and that in build_unary_op handling
+            Objective-C cases for increment / decrement, also needs
+            updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
+            and objc_types_are_equivalent may also need updates.  */
+         if (c_dialect_objc ())
+           sorry ("%<_Atomic%> in Objective-C");
+         /* C parser handling of OpenMP constructs needs checking for
+            correct lvalue-to-rvalue conversions.  */
+         if (flag_openmp)
+           sorry ("%<_Atomic%> with OpenMP");
+         if (!flag_isoc11)
+           {
+             if (flag_isoc99)
+               pedwarn (loc, OPT_Wpedantic,
+                        "ISO C99 does not support the %<_Atomic%> qualifier");
+             else
+               pedwarn (loc, OPT_Wpedantic,
+                        "ISO C90 does not support the %<_Atomic%> qualifier");
+           }
+         attrs_ok = true;
+         tree value;
+         value = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+         if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+           {
+             /* _Atomic ( type-name ).  */
+             seen_type = true;
+             c_parser_consume_token (parser);
+             struct c_type_name *type = c_parser_type_name (parser);
+             t.kind = ctsk_typeof;
+             t.spec = error_mark_node;
+             t.expr = NULL_TREE;
+             t.expr_const_operands = true;
+             if (type != NULL)
+               t.spec = groktypename (type, &t.expr,
+                                      &t.expr_const_operands);
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                        "expected %<)%>");
+             if (t.spec != error_mark_node)
+               {
+                 if (TREE_CODE (t.spec) == ARRAY_TYPE)
+                   error_at (loc, "%<_Atomic%>-qualified array type");
+                 else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
+                   error_at (loc, "%<_Atomic%>-qualified function type");
+                 else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
+                   error_at (loc, "%<_Atomic%> applied to a qualified type");
+                 else
+                   t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
+               }
+             declspecs_add_type (loc, specs, t);
+           }
+         else
+           declspecs_add_qual (loc, specs, value);
+         break;
        case RID_CONST:
        case RID_VOLATILE:
        case RID_RESTRICT:
@@ -2183,6 +2412,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          declspecs_add_attrs (loc, specs, attrs);
          break;
        case RID_ALIGNAS:
+         if (!alignspec_ok)
+           goto out;
          align = c_parser_alignas_specifier (parser);
          declspecs_add_alignas (loc, specs, align);
          break;
@@ -2479,7 +2710,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          /* Accept #pragmas at struct scope.  */
          if (c_parser_next_token_is (parser, CPP_PRAGMA))
            {
-             c_parser_pragma (parser, pragma_external);
+             c_parser_pragma (parser, pragma_struct);
              continue;
            }
          /* Parse some comma-separated declarations, but not the
@@ -2588,7 +2819,13 @@ c_parser_struct_declaration (c_parser *parser)
     }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
-  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
+  /* Strictly by the standard, we shouldn't allow _Alignas here,
+     but it appears to have been intended to allow it there, so
+     we're keeping it as it is until WG14 reaches a conclusion
+     of N1731.
+     <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf>  */
+  c_parser_declspecs (parser, specs, false, true, true,
+                     true, false, cla_nonabstract_decl);
   if (parser->error)
     return NULL_TREE;
   if (!specs->declspecs_seen_p)
@@ -2763,6 +3000,16 @@ c_parser_typeof_specifier (c_parser *parser)
       if (was_vm)
        ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
       pop_maybe_used (was_vm);
+      /* For use in macros such as those in <stdatomic.h>, remove
+        _Atomic and const qualifiers from atomic types.  (Possibly
+        all qualifiers should be removed; const can be an issue for
+        more macros using typeof than just the <stdatomic.h>
+        ones.)  */
+      if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec))
+       ret.spec = c_build_qualified_type (ret.spec,
+                                          (TYPE_QUALS (ret.spec)
+                                           & ~(TYPE_QUAL_ATOMIC
+                                               | TYPE_QUAL_CONST)));
     }
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return ret;
@@ -2836,6 +3083,12 @@ c_parser_alignas_specifier (c_parser * parser)
      type-qualifier-list type-qualifier
      type-qualifier-list attributes
 
+   array-declarator:
+     [ type-qualifier-list[opt] assignment-expression[opt] ]
+     [ static type-qualifier-list[opt] assignment-expression ]
+     [ type-qualifier-list static assignment-expression ]
+     [ type-qualifier-list[opt] * ]
+
    parameter-type-list:
      parameter-list
      parameter-list , ...
@@ -2894,7 +3147,8 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       struct c_declarator *inner;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+      c_parser_declspecs (parser, quals_attrs, false, false, true,
+                         false, false, cla_prefer_id);
       inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
       if (inner == NULL)
        return NULL;
@@ -3044,14 +3298,19 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       bool static_seen;
       bool star_seen;
-      tree dimen;
+      struct c_expr dimen;
+      dimen.value = NULL_TREE;
+      dimen.original_code = ERROR_MARK;
+      dimen.original_type = NULL_TREE;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+      c_parser_declspecs (parser, quals_attrs, false, false, true,
+                         false, false, cla_prefer_id);
       static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
       if (static_seen)
        c_parser_consume_token (parser);
       if (static_seen && !quals_attrs->declspecs_seen_p)
-       c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+       c_parser_declspecs (parser, quals_attrs, false, false, true,
+                           false, false, cla_prefer_id);
       if (!quals_attrs->declspecs_seen_p)
        quals_attrs = NULL;
       /* If "static" is present, there must be an array dimension.
@@ -3060,46 +3319,63 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
       if (static_seen)
        {
          star_seen = false;
-         dimen = c_parser_expr_no_commas (parser, NULL).value;
+         dimen = c_parser_expr_no_commas (parser, NULL);
        }
       else
        {
          if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
            {
-             dimen = NULL_TREE;
+             dimen.value = NULL_TREE;
              star_seen = false;
            }
+         else if (flag_enable_cilkplus
+                  && c_parser_next_token_is (parser, CPP_COLON))
+           {
+             dimen.value = error_mark_node;
+             star_seen = false;
+             error_at (c_parser_peek_token (parser)->location,
+                       "array notations cannot be used in declaration");
+             c_parser_consume_token (parser);
+           }   
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
              if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
                {
-                 dimen = NULL_TREE;
+                 dimen.value = NULL_TREE;
                  star_seen = true;
                  c_parser_consume_token (parser);
                }
              else
                {
                  star_seen = false;
-                 dimen = c_parser_expr_no_commas (parser, NULL).value;
+                 dimen = c_parser_expr_no_commas (parser, NULL);
                }
            }
          else
            {
              star_seen = false;
-             dimen = c_parser_expr_no_commas (parser, NULL).value;
+             dimen = c_parser_expr_no_commas (parser, NULL);
            }
        }
       if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
        c_parser_consume_token (parser);
+      else if (flag_enable_cilkplus
+              && c_parser_next_token_is (parser, CPP_COLON))
+       {
+         error_at (c_parser_peek_token (parser)->location,
+                   "array notations cannot be used in declaration");
+         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+         return NULL;
+       }
       else
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
          return NULL;
        }
-      if (dimen)
-       mark_exp_read (dimen);
-      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+      if (dimen.value)
+       dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
+      declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
                                           static_seen, star_seen);
       if (declarator == NULL)
        return NULL;
@@ -3310,7 +3586,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
 
   /* Accept #pragmas between parameter declarations.  */
   while (c_parser_next_token_is (parser, CPP_PRAGMA))
-    c_parser_pragma (parser, pragma_external);
+    c_parser_pragma (parser, pragma_param);
 
   if (!c_parser_next_token_starts_declspecs (parser))
     {
@@ -3337,7 +3613,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       declspecs_add_attrs (input_location, specs, attrs);
       attrs = NULL_TREE;
     }
-  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
+  c_parser_declspecs (parser, specs, true, true, true, true, false,
+                     cla_nonabstract_decl);
   finish_declspecs (specs);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
@@ -3468,6 +3745,8 @@ c_parser_attribute_any_word (c_parser *parser)
        case RID_SAT:
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_CANCEL:
+       case RID_ATOMIC:
+       case RID_AUTO_TYPE:
          ok = true;
          break;
        default:
@@ -3646,7 +3925,8 @@ c_parser_type_name (c_parser *parser)
   struct c_declarator *declarator;
   struct c_type_name *ret;
   bool dummy = false;
-  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
+  c_parser_declspecs (parser, specs, false, true, true, false, false,
+                     cla_prefer_type);
   if (!specs->declspecs_seen_p)
     {
       c_parser_error (parser, "expected specifier-qualifier-list");
@@ -3723,7 +4003,7 @@ c_parser_initializer (c_parser *parser)
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-       ret = default_function_array_read_conversion (loc, ret);
+       ret = convert_lvalue_to_rvalue (loc, ret, true, true);
       return ret;
     }
 }
@@ -3902,8 +4182,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
                      c_parser_consume_token (parser);
                      exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
-                     next = default_function_array_read_conversion (exp_loc,
-                                                                    next);
+                     next = convert_lvalue_to_rvalue (exp_loc, next,
+                                                      true, true);
                      rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                parse_message_args:
@@ -3999,7 +4279,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-       init = default_function_array_read_conversion (loc, init);
+       init = convert_lvalue_to_rvalue (loc, init, true, true);
     }
   process_init_element (init, false, braced_init_obstack);
 }
@@ -4055,7 +4335,11 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
 
    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)
@@ -4073,6 +4357,10 @@ c_parser_compound_statement (c_parser *parser)
     }
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
+
+  /* If the compound stmt contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (stmt))
+    stmt = expand_array_notation_exprs (stmt);
   return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
@@ -4156,7 +4444,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
        {
          last_label = false;
          mark_valid_location_for_stdc_pragma (false);
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                        true, NULL, vNULL);
          if (last_stmt)
            pedwarn_c90 (loc,
                         (pedantic && !flag_isoc99)
@@ -4184,7 +4473,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              last_label = false;
              mark_valid_location_for_stdc_pragma (false);
              c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true, NULL);
+                                            true, NULL, vNULL);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
@@ -4322,7 +4611,8 @@ c_parser_label (c_parser *parser)
          c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
                                         /*static_assert_ok*/ true,
                                         /*empty_ok*/ true, /*nested*/ true,
-                                        /*start_attr_ok*/ true, NULL);
+                                        /*start_attr_ok*/ true, NULL,
+                                        vNULL);
        }
     }
 }
@@ -4385,9 +4675,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
@@ -4400,6 +4693,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
 
@@ -4409,6 +4708,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
 
@@ -4466,13 +4768,21 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_switch_statement (parser);
          break;
        case RID_WHILE:
-         c_parser_while_statement (parser);
+         c_parser_while_statement (parser, false);
          break;
        case RID_DO:
-         c_parser_do_statement (parser);
+         c_parser_do_statement (parser, false);
          break;
        case RID_FOR:
-         c_parser_for_statement (parser);
+         c_parser_for_statement (parser, false);
+         break;
+       case RID_CILK_SYNC:
+         c_parser_consume_token (parser);
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         if (!flag_enable_cilkplus) 
+           error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>");
+         else 
+           add_stmt (build_cilk_sync ());
          break;
        case RID_GOTO:
          c_parser_consume_token (parser);
@@ -4484,12 +4794,12 @@ c_parser_statement_after_labels (c_parser *parser)
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
-             tree val;
+             struct c_expr val;
 
              c_parser_consume_token (parser);
-             val = c_parser_expression (parser).value;
-             mark_exp_read (val);
-             stmt = c_finish_goto_ptr (loc, val);
+             val = c_parser_expression (parser);
+             val = convert_lvalue_to_rvalue (loc, val, false, true);
+             stmt = c_finish_goto_ptr (loc, val.value);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
@@ -4538,9 +4848,10 @@ c_parser_statement_after_labels (c_parser *parser)
            }
          else
            {
-             tree expr = c_parser_expression (parser).value;
-             expr = c_fully_fold (expr, false, NULL);
-             stmt = objc_build_throw_stmt (loc, expr);
+             struct c_expr expr = c_parser_expression (parser);
+             expr = convert_lvalue_to_rvalue (loc, expr, false, false);
+             expr.value = c_fully_fold (expr.value, false, NULL);
+             stmt = objc_build_throw_stmt (loc, expr.value);
              goto expect_semicolon;
            }
          break;
@@ -4716,6 +5027,7 @@ c_parser_if_statement (c_parser *parser)
   bool first_if = false;
   tree first_body, second_body;
   bool in_if_block;
+  tree if_stmt;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
   c_parser_consume_token (parser);
@@ -4734,7 +5046,12 @@ c_parser_if_statement (c_parser *parser)
   else
     second_body = NULL_TREE;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  if_stmt = c_end_compound_stmt (loc, block, flag_isoc99);
+
+  /* If the if statement contains array notations, then we expand them.  */
+  if (flag_enable_cilkplus && contains_array_notation_expr (if_stmt))
+    if_stmt = fix_conditional_array_notations (if_stmt);
+  add_stmt (if_stmt);
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
@@ -4746,6 +5063,7 @@ c_parser_if_statement (c_parser *parser)
 static void
 c_parser_switch_statement (c_parser *parser)
 {
+  struct c_expr ce;
   tree block, expr, body, save_break;
   location_t switch_loc = c_parser_peek_token (parser)->location;
   location_t switch_cond_loc;
@@ -4755,7 +5073,16 @@ c_parser_switch_statement (c_parser *parser)
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       switch_cond_loc = c_parser_peek_token (parser)->location;
-      expr = c_parser_expression (parser).value;
+      ce = c_parser_expression (parser);
+      ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false);
+      expr = ce.value;
+      if (flag_enable_cilkplus && contains_array_notation_expr (expr))
+       {
+         error_at (switch_cond_loc,
+                   "array notations cannot be used as a condition for switch "
+                   "statement");
+         expr = error_mark_node;
+       }
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -4786,7 +5113,7 @@ c_parser_switch_statement (c_parser *parser)
 */
 
 static void
-c_parser_while_statement (c_parser *parser)
+c_parser_while_statement (c_parser *parser, bool ivdep)
 {
   tree block, cond, body, save_break, save_cont;
   location_t loc;
@@ -4795,6 +5122,17 @@ c_parser_while_statement (c_parser *parser)
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   cond = c_parser_paren_condition (parser);
+  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+    {
+      error_at (loc, "array notations cannot be used as a condition for while "
+               "statement");
+      cond = error_mark_node;
+    }
+
+  if (ivdep && cond != error_mark_node)
+    cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                  build_int_cst (integer_type_node,
+                  annot_expr_ivdep_kind));
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   save_cont = c_cont_label;
@@ -4813,7 +5151,7 @@ c_parser_while_statement (c_parser *parser)
 */
 
 static void
-c_parser_do_statement (c_parser *parser)
+c_parser_do_statement (c_parser *parser, bool ivdep)
 {
   tree block, cond, body, save_break, save_cont, new_break, new_cont;
   location_t loc;
@@ -4836,6 +5174,16 @@ c_parser_do_statement (c_parser *parser)
   new_cont = c_cont_label;
   c_cont_label = save_cont;
   cond = c_parser_paren_condition (parser);
+  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+    {
+      error_at (loc, "array notations cannot be used as a condition for a "
+               "do-while statement");
+      cond = error_mark_node;
+    }
+  if (ivdep && cond != error_mark_node)
+    cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                  build_int_cst (integer_type_node,
+                  annot_expr_ivdep_kind));
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
@@ -4899,7 +5247,7 @@ c_parser_do_statement (c_parser *parser)
 */
 
 static void
-c_parser_for_statement (c_parser *parser)
+c_parser_for_statement (c_parser *parser, bool ivdep)
 {
   tree block, cond, incr, save_break, save_cont, body;
   /* The following are only used when parsing an ObjC foreach statement.  */
@@ -4930,7 +5278,7 @@ c_parser_for_statement (c_parser *parser)
       else if (c_parser_next_tokens_start_declaration (parser))
        {
          c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
-                                        &object_expression);
+                                        &object_expression, vNULL);
          parser->objc_could_be_foreach_context = false;
          
          if (c_parser_next_token_is_keyword (parser, RID_IN))
@@ -4959,7 +5307,7 @@ c_parser_for_statement (c_parser *parser)
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true, &object_expression);
+                                            true, &object_expression, vNULL);
              parser->objc_could_be_foreach_context = false;
              
              restore_extension_diagnostics (ext);
@@ -4980,8 +5328,10 @@ c_parser_for_statement (c_parser *parser)
        {
        init_expr:
          {
+           struct c_expr ce;
            tree init_expression;
-           init_expression = c_parser_expression (parser).value;
+           ce = c_parser_expression (parser);
+           init_expression = ce.value;
            parser->objc_could_be_foreach_context = false;
            if (c_parser_next_token_is_keyword (parser, RID_IN))
              {
@@ -4993,6 +5343,8 @@ c_parser_for_statement (c_parser *parser)
              }
            else
              {
+               ce = convert_lvalue_to_rvalue (loc, ce, true, false);
+               init_expression = ce.value;
                c_finish_expr_stmt (loc, init_expression);
                c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
              }
@@ -5005,14 +5357,34 @@ c_parser_for_statement (c_parser *parser)
        {
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             c_parser_consume_token (parser);
-             cond = NULL_TREE;
+             if (ivdep)
+               {
+                 c_parser_error (parser, "missing loop condition in loop with "
+                                 "%<GCC ivdep%> pragma");
+                 cond = error_mark_node;
+               }
+             else
+               {
+                 c_parser_consume_token (parser);
+                 cond = NULL_TREE;
+               }
            }
          else
            {
              cond = c_parser_condition (parser);
-             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+             if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+               {
+                 error_at (loc, "array notations cannot be used in a "
+                           "condition for a for-loop");
+                 cond = error_mark_node;
+               }
+             c_parser_skip_until_found (parser, CPP_SEMICOLON,
+                                        "expected %<;%>");
            }
+         if (ivdep && cond != error_mark_node)
+           cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                          build_int_cst (integer_type_node,
+                          annot_expr_ivdep_kind));
        }
       /* Parse the increment expression (the third expression in a
         for-statement).  In the case of a foreach-statement, this is
@@ -5033,7 +5405,11 @@ c_parser_for_statement (c_parser *parser)
            collection_expression = c_fully_fold (c_parser_expression (parser).value,
                                                  false, NULL);
          else
-           incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+           {
+             struct c_expr ce = c_parser_expression (parser);
+             ce = convert_lvalue_to_rvalue (loc, ce, true, false);
+             incr = c_process_expr_stmt (loc, ce.value);
+           }
        }
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
@@ -5150,10 +5526,10 @@ c_parser_asm_statement (c_parser *parser)
            /* For asm goto, we don't allow output operands, but reserve
               the slot for a future extension that does allow them.  */
            if (!is_goto)
-             outputs = c_parser_asm_operands (parser, false);
+             outputs = c_parser_asm_operands (parser);
            break;
          case 1:
-           inputs = c_parser_asm_operands (parser, true);
+           inputs = c_parser_asm_operands (parser);
            break;
          case 2:
            clobbers = c_parser_asm_clobbers (parser);
@@ -5191,9 +5567,7 @@ c_parser_asm_statement (c_parser *parser)
   goto error;
 }
 
-/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
-   not outputs), apply the default conversion of functions and arrays
-   to pointers.
+/* Parse asm operands, a GNU extension.
 
    asm-operands:
      asm-operand
@@ -5205,10 +5579,9 @@ c_parser_asm_statement (c_parser *parser)
 */
 
 static tree
-c_parser_asm_operands (c_parser *parser, bool convert_p)
+c_parser_asm_operands (c_parser *parser)
 {
   tree list = NULL_TREE;
-  location_t loc;
   while (true)
     {
       tree name, str;
@@ -5243,12 +5616,8 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
          parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
-      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
       mark_exp_read (expr.value);
-      if (convert_p)
-       expr = default_function_array_conversion (loc, expr);
-      expr.value = c_fully_fold (expr.value, false, NULL);
       parser->lex_untranslated_string = true;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
@@ -5347,13 +5716,14 @@ c_parser_asm_goto_operands (c_parser *parser)
    error.  */
 
 static struct c_expr
-c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
+c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
+                        tree omp_atomic_lhs)
 {
   struct c_expr lhs, rhs, ret;
   enum tree_code code;
   location_t op_location, exp_location;
   gcc_assert (!after || c_dialect_objc ());
-  lhs = c_parser_conditional_expression (parser, after);
+  lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
   op_location = c_parser_peek_token (parser)->location;
   switch (c_parser_peek_token (parser)->type)
     {
@@ -5396,7 +5766,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   c_parser_consume_token (parser);
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_read_conversion (exp_location, rhs);
+  rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
+  
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
                                 code, exp_location, rhs.value,
                                 rhs.original_type);
@@ -5426,19 +5797,20 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
 */
 
 static struct c_expr
-c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
+c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
+                                tree omp_atomic_lhs)
 {
   struct c_expr cond, exp1, exp2, ret;
   location_t cond_loc, colon_loc, middle_loc;
 
   gcc_assert (!after || c_dialect_objc ());
 
-  cond = c_parser_binary_expression (parser, after, PREC_NONE);
+  cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
   cond_loc = c_parser_peek_token (parser)->location;
-  cond = default_function_array_read_conversion (cond_loc, cond);
+  cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
@@ -5485,8 +5857,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
     }
   {
     location_t exp2_loc = c_parser_peek_token (parser)->location;
-    exp2 = c_parser_conditional_expression (parser, NULL);
-    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+    exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
+    exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
   }
   c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
   ret.value = build_conditional_expr (colon_loc, cond.value,
@@ -5518,8 +5890,13 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 /* Parse a binary expression; that is, a logical-OR-expression (C90
    6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
    an Objective-C message expression which is the primary-expression
-   starting the expression as an initializer.  PREC is the starting
-   precedence, usually PREC_NONE.
+   starting the expression as an initializer.
+
+   OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
+   when it should be the unfolded lhs.  In a valid OpenMP source,
+   one of the operands of the toplevel binary expression must be equal
+   to it.  In that case, just return a build2 created binary operation
+   rather than result of parser_build_binary_op.
 
    multiplicative-expression:
      cast-expression
@@ -5572,7 +5949,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 
 static struct c_expr
 c_parser_binary_expression (c_parser *parser, struct c_expr *after,
-                           enum c_parser_prec prec)
+                           tree omp_atomic_lhs)
 {
   /* A binary expression is parsed using operator-precedence parsing,
      with the operands being cast expressions.  All the binary
@@ -5625,21 +6002,35 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
-      = default_function_array_read_conversion (stack[sp - 1].loc,           \
-                                               stack[sp - 1].expr);          \
+      = convert_lvalue_to_rvalue (stack[sp - 1].loc,                         \
+                                 stack[sp - 1].expr, true, true);            \
     stack[sp].expr                                                           \
-      = default_function_array_read_conversion (stack[sp].loc,               \
-                                               stack[sp].expr);              \
-    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
-                                                stack[sp].op,                \
-                                                stack[sp - 1].expr,          \
-                                                stack[sp].expr);             \
+      = convert_lvalue_to_rvalue (stack[sp].loc,                             \
+                                 stack[sp].expr, true, true);                \
+    if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1         \
+       && c_parser_peek_token (parser)->type == CPP_SEMICOLON                \
+       && ((1 << stack[sp].prec)                                             \
+           & (1 << (PREC_BITOR | PREC_BITXOR | PREC_BITAND | PREC_SHIFT      \
+                    | PREC_ADD | PREC_MULT)))                                \
+       && stack[sp].op != TRUNC_MOD_EXPR                                     \
+       && stack[0].expr.value != error_mark_node                             \
+       && stack[1].expr.value != error_mark_node                             \
+       && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs)                \
+           || c_tree_equal (stack[1].expr.value, omp_atomic_lhs)))           \
+      stack[0].expr.value                                                    \
+       = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),               \
+                 stack[0].expr.value, stack[1].expr.value);                  \
+    else                                                                     \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,            \
+                                                  stack[sp].op,              \
+                                                  stack[sp - 1].expr,        \
+                                                  stack[sp].expr);           \
     sp--;                                                                    \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
   stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
-  stack[0].prec = prec;
+  stack[0].prec = PREC_NONE;
   sp = 0;
   while (true)
     {
@@ -5728,18 +6119,14 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
        }
       binary_loc = c_parser_peek_token (parser)->location;
       while (oprec <= stack[sp].prec)
-       {
-         if (sp == 0)
-           goto out;
-         POP;
-       }
+       POP;
       c_parser_consume_token (parser);
       switch (ocode)
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
-           = default_function_array_read_conversion (stack[sp].loc,
-                                                     stack[sp].expr);
+           = convert_lvalue_to_rvalue (stack[sp].loc,
+                                       stack[sp].expr, true, true);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -5747,8 +6134,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
-           = default_function_array_read_conversion (stack[sp].loc,
-                                                     stack[sp].expr);
+           = convert_lvalue_to_rvalue (stack[sp].loc,
+                                       stack[sp].expr, true, true);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -5819,7 +6206,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
       {
        location_t expr_loc = c_parser_peek_token (parser)->location;
        expr = c_parser_cast_expression (parser, NULL);
-       expr = default_function_array_read_conversion (expr_loc, expr);
+       expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
       }
       ret.value = c_cast_expr (cast_loc, type_name, expr.value);
       ret.original_code = ERROR_MARK;
@@ -5879,14 +6266,28 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+
+      /* If there is array notations in op, we expand them.  */
+      if (flag_enable_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF)
+       return fix_array_notation_expr (exp_loc, PREINCREMENT_EXPR, op);
+      else
+       {
+         op = default_function_array_read_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+       }
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+      
+      /* If there is array notations in op, we expand them.  */
+      if (flag_enable_cilkplus && TREE_CODE (op.value) == ARRAY_NOTATION_REF)
+       return fix_array_notation_expr (exp_loc, PREDECREMENT_EXPR, op);
+      else
+       {
+         op = default_function_array_read_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+       }
     case CPP_AND:
       c_parser_consume_token (parser);
       op = c_parser_cast_expression (parser, NULL);
@@ -5896,7 +6297,7 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
       ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
@@ -5907,25 +6308,25 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
       return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
       return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
       return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
+      op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
       return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
@@ -6123,11 +6524,13 @@ c_parser_alignof_expression (c_parser *parser)
    stores the arguments in CEXPR_LIST.  */
 static bool
 c_parser_get_builtin_args (c_parser *parser, const char *bname,
-                          vec<c_expr_t, va_gc> **ret_cexpr_list)
+                          vec<c_expr_t, va_gc> **ret_cexpr_list,
+                          bool choose_expr_p)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   vec<c_expr_t, va_gc> *cexpr_list;
   c_expr_t expr;
+  bool saved_force_folding_builtin_constant_p;
 
   *ret_cexpr_list = NULL;
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
@@ -6144,7 +6547,12 @@ c_parser_get_builtin_args (c_parser *parser, const char *bname,
       return true;
     }
 
+  saved_force_folding_builtin_constant_p
+    = force_folding_builtin_constant_p;
+  force_folding_builtin_constant_p |= choose_expr_p;
   expr = c_parser_expr_no_commas (parser, NULL);
+  force_folding_builtin_constant_p
+    = saved_force_folding_builtin_constant_p;
   vec_alloc (cexpr_list, 1);
   C_EXPR_APPEND (cexpr_list, expr);
   while (c_parser_next_token_is (parser, CPP_COMMA))
@@ -6161,6 +6569,225 @@ c_parser_get_builtin_args (c_parser *parser, const char *bname,
   return true;
 }
 
+/* This represents a single generic-association.  */
+
+struct c_generic_association
+{
+  /* The location of the starting token of the type.  */
+  location_t type_location;
+  /* The association's type, or NULL_TREE for 'default'.  */
+  tree type;
+  /* The association's expression.  */
+  struct c_expr expression;
+};
+
+/* Parse a generic-selection.  (C11 6.5.1.1).
+   
+   generic-selection:
+     _Generic ( assignment-expression , generic-assoc-list )
+     
+   generic-assoc-list:
+     generic-association
+     generic-assoc-list , generic-association
+   
+   generic-association:
+     type-name : assignment-expression
+     default : assignment-expression
+*/
+
+static struct c_expr
+c_parser_generic_selection (c_parser *parser)
+{
+  vec<c_generic_association> associations = vNULL;
+  struct c_expr selector, error_expr;
+  tree selector_type;
+  struct c_generic_association matched_assoc;
+  bool match_found = false;
+  location_t generic_loc, selector_loc;
+
+  error_expr.original_code = ERROR_MARK;
+  error_expr.original_type = NULL;
+  error_expr.value = error_mark_node;
+  matched_assoc.type_location = UNKNOWN_LOCATION;
+  matched_assoc.type = NULL_TREE;
+  matched_assoc.expression = error_expr;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
+  generic_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  if (!flag_isoc11)
+    {
+      if (flag_isoc99)
+       pedwarn (generic_loc, OPT_Wpedantic,
+                "ISO C99 does not support %<_Generic%>");
+      else
+       pedwarn (generic_loc, OPT_Wpedantic,
+                "ISO C90 does not support %<_Generic%>");
+    }
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_expr;
+
+  c_inhibit_evaluation_warnings++;
+  selector_loc = c_parser_peek_token (parser)->location;
+  selector = c_parser_expr_no_commas (parser, NULL);
+  selector = default_function_array_conversion (selector_loc, selector);
+  c_inhibit_evaluation_warnings--;
+
+  if (selector.value == error_mark_node)
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return selector;
+    }
+  selector_type = TREE_TYPE (selector.value);
+  /* In ISO C terms, rvalues (including the controlling expression of
+     _Generic) do not have qualified types.  */
+  if (TREE_CODE (selector_type) != ARRAY_TYPE)
+    selector_type = TYPE_MAIN_VARIANT (selector_type);
+  /* In ISO C terms, _Noreturn is not part of the type of expressions
+     such as &abort, but in GCC it is represented internally as a type
+     qualifier.  */
+  if (FUNCTION_POINTER_TYPE_P (selector_type)
+      && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
+    selector_type
+      = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
+
+  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return error_expr;
+    }
+
+  while (1)
+    {
+      struct c_generic_association assoc, *iter;
+      unsigned int ix;
+      c_token *token = c_parser_peek_token (parser);
+
+      assoc.type_location = token->location;
+      if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
+       {
+         c_parser_consume_token (parser);
+         assoc.type = NULL_TREE;
+       }
+      else
+       {
+         struct c_type_name *type_name;
+
+         type_name = c_parser_type_name (parser);
+         if (type_name == NULL)
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             goto error_exit;
+           }
+         assoc.type = groktypename (type_name, NULL, NULL);
+         if (assoc.type == error_mark_node)
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             goto error_exit;
+           }
+
+         if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
+           error_at (assoc.type_location,
+                     "%<_Generic%> association has function type");
+         else if (!COMPLETE_TYPE_P (assoc.type))
+           error_at (assoc.type_location,
+                     "%<_Generic%> association has incomplete type");
+
+         if (variably_modified_type_p (assoc.type, NULL_TREE))
+           error_at (assoc.type_location,
+                     "%<_Generic%> association has "
+                     "variable length type");
+       }
+
+      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         goto error_exit;
+       }
+
+      assoc.expression = c_parser_expr_no_commas (parser, NULL);
+      if (assoc.expression.value == error_mark_node)
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         goto error_exit;
+       }
+
+      for (ix = 0; associations.iterate (ix, &iter); ++ix)
+       {
+         if (assoc.type == NULL_TREE)
+           {
+             if (iter->type == NULL_TREE)
+               {
+                 error_at (assoc.type_location,
+                           "duplicate %<default%> case in %<_Generic%>");
+                 inform (iter->type_location, "original %<default%> is here");
+               }
+           }
+         else if (iter->type != NULL_TREE)
+           {
+             if (comptypes (assoc.type, iter->type))
+               {
+                 error_at (assoc.type_location,
+                           "%<_Generic%> specifies two compatible types");
+                 inform (iter->type_location, "compatible type is here");
+               }
+           }
+       }
+
+      if (assoc.type == NULL_TREE)
+       {
+         if (!match_found)
+           {
+             matched_assoc = assoc;
+             match_found = true;
+           }
+       }
+      else if (comptypes (assoc.type, selector_type))
+       {
+         if (!match_found || matched_assoc.type == NULL_TREE)
+           {
+             matched_assoc = assoc;
+             match_found = true;
+           }
+         else
+           {
+             error_at (assoc.type_location,
+                       "%<_Generic> selector matches multiple associations");
+             inform (matched_assoc.type_location,
+                     "other match is here");
+           }
+       }
+
+      associations.safe_push (assoc);
+
+      if (c_parser_peek_token (parser)->type != CPP_COMMA)
+       break;
+      c_parser_consume_token (parser);
+    }
+
+  associations.release ();
+
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return error_expr;
+    }
+
+  if (!match_found)
+    {
+      error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
+               "compatible with any association",
+               selector_type);
+      return error_expr;
+    }
+
+  return matched_assoc.expression;
+
+ error_exit:
+  associations.release ();
+  return error_expr;
+}
 
 /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
 
@@ -6184,6 +6811,7 @@ c_parser_get_builtin_args (c_parser *parser, const char *bname,
      constant
      string-literal
      ( expression )
+     generic-selection
 
    GNU extensions:
 
@@ -6491,10 +7119,13 @@ c_parser_postfix_expression (c_parser *parser)
                      }
                    else
                      {
+                       struct c_expr ce;
                        tree idx;
                        loc = c_parser_peek_token (parser)->location;
                        c_parser_consume_token (parser);
-                       idx = c_parser_expression (parser).value;
+                       ce = c_parser_expression (parser);
+                       ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+                       idx = ce.value;
                        idx = c_fully_fold (idx, false, NULL);
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                                   "expected %<]%>");
@@ -6518,7 +7149,7 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_choose_expr",
-                                           &cexpr_list))
+                                           &cexpr_list, true))
              {
                expr.value = error_mark_node;
                break;
@@ -6600,7 +7231,7 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_complex",
-                                           &cexpr_list))
+                                           &cexpr_list, false))
              {
                expr.value = error_mark_node;
                break;
@@ -6617,11 +7248,11 @@ c_parser_postfix_expression (c_parser *parser)
            e1_p = &(*cexpr_list)[0];
            e2_p = &(*cexpr_list)[1];
 
-           mark_exp_read (e1_p->value);
+           *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
            if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
              e1_p->value = convert (TREE_TYPE (e1_p->value),
                                     TREE_OPERAND (e1_p->value, 0));
-           mark_exp_read (e2_p->value);
+           *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
            if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
              e2_p->value = convert (TREE_TYPE (e2_p->value),
                                     TREE_OPERAND (e2_p->value, 0));
@@ -6662,14 +7293,14 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_shuffle",
-                                           &cexpr_list))
+                                           &cexpr_list, false))
              {
                expr.value = error_mark_node;
                break;
              }
 
            FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
-             mark_exp_read (p->value);
+             *p = convert_lvalue_to_rvalue (loc, *p, true, true);
 
            if (vec_safe_length (cexpr_list) == 2)
              expr.value =
@@ -6752,6 +7383,33 @@ c_parser_postfix_expression (c_parser *parser)
            expr.value = objc_build_encode_expr (type);
          }
          break;
+       case RID_GENERIC:
+         expr = c_parser_generic_selection (parser);
+         break;
+       case RID_CILK_SPAWN:
+         c_parser_consume_token (parser);
+         if (!flag_enable_cilkplus)
+           {
+             error_at (loc, "-fcilkplus must be enabled to use "
+                       "%<_Cilk_spawn%>");
+             expr = c_parser_postfix_expression (parser);
+             expr.value = error_mark_node;           
+           }
+         if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+           {
+             error_at (loc, "consecutive %<_Cilk_spawn%> keywords "
+                       "are not permitted");
+             /* Now flush out all the _Cilk_spawns.  */
+             while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+               c_parser_consume_token (parser);
+             expr = c_parser_postfix_expression (parser);
+           }
+         else
+           {
+             expr = c_parser_postfix_expression (parser);
+             expr.value = build_cilk_spawn (loc, expr.value);
+           }
+         break; 
        default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
@@ -6873,7 +7531,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
   tree sizeof_arg[3];
   unsigned int i;
   vec<tree, va_gc> *exprlist;
-  vec<tree, va_gc> *origtypes;
+  vec<tree, va_gc> *origtypes = NULL;
   while (true)
     {
       location_t op_loc = c_parser_peek_token (parser)->location;
@@ -6882,10 +7540,36 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_OPEN_SQUARE:
          /* Array reference.  */
          c_parser_consume_token (parser);
-         idx = c_parser_expression (parser).value;
-         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                    "expected %<]%>");
-         expr.value = build_array_ref (op_loc, expr.value, idx);
+         if (flag_enable_cilkplus
+             && c_parser_peek_token (parser)->type == CPP_COLON)
+           /* If we are here, then we have something like this:
+              Array [ : ]
+           */
+           expr.value = c_parser_array_notation (expr_loc, parser, NULL_TREE,
+                                                 expr.value);
+         else
+           {         
+             idx = c_parser_expression (parser).value;
+             /* Here we have 3 options:
+                1. Array [EXPR] -- Normal Array call.
+                2. Array [EXPR : EXPR] -- Array notation without stride.
+                3. Array [EXPR : EXPR : EXPR] -- Array notation with stride.
+
+                For 1, we just handle it just like a normal array expression.
+                For 2 and 3 we handle it like we handle array notations.  The
+                idx value we have above becomes the initial/start index.
+             */
+             if (flag_enable_cilkplus
+                 && c_parser_peek_token (parser)->type == CPP_COLON)
+               expr.value = c_parser_array_notation (expr_loc, parser, idx, 
+                                                     expr.value);
+             else
+               {
+                 c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                            "expected %<]%>");
+                 expr.value = build_array_ref (op_loc, expr.value, idx);
+               }
+           }
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          break;
@@ -6960,7 +7644,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_DEREF:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr_loc, expr);
+         expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
@@ -6993,18 +7677,32 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
-         expr.value = build_unary_op (op_loc,
-                                      POSTINCREMENT_EXPR, expr.value, 0);
+         /* If the expressions have array notations, we expand them.  */
+         if (flag_enable_cilkplus
+             && TREE_CODE (expr.value) == ARRAY_NOTATION_REF)
+           expr = fix_array_notation_expr (expr_loc, POSTINCREMENT_EXPR, expr);
+         else
+           {
+             expr = default_function_array_read_conversion (expr_loc, expr);
+             expr.value = build_unary_op (op_loc,
+                                          POSTINCREMENT_EXPR, expr.value, 0);
+           }
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          break;
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
-         expr.value = build_unary_op (op_loc,
-                                      POSTDECREMENT_EXPR, expr.value, 0);
+         /* If the expressions have array notations, we expand them.  */
+         if (flag_enable_cilkplus
+             && TREE_CODE (expr.value) == ARRAY_NOTATION_REF)
+           expr = fix_array_notation_expr (expr_loc, POSTDECREMENT_EXPR, expr);
+         else
+           {
+             expr = default_function_array_read_conversion (expr_loc, expr);
+             expr.value = build_unary_op (op_loc,
+                                          POSTDECREMENT_EXPR, expr.value, 0);
+           }
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          break;
@@ -7024,8 +7722,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
 static struct c_expr
 c_parser_expression (c_parser *parser)
 {
+  location_t tloc = c_parser_peek_token (parser)->location;
   struct c_expr expr;
   expr = c_parser_expr_no_commas (parser, NULL);
+  if (c_parser_next_token_is (parser, CPP_COMMA))
+    expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
@@ -7040,7 +7741,7 @@ c_parser_expression (c_parser *parser)
       if (DECL_P (lhsval) || handled_component_p (lhsval))
        mark_exp_read (lhsval);
       next = c_parser_expr_no_commas (parser, NULL);
-      next = default_function_array_conversion (expr_loc, next);
+      next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
       expr.value = build_compound_expr (loc, expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
       expr.original_type = next.original_type;
@@ -7048,8 +7749,8 @@ c_parser_expression (c_parser *parser)
   return expr;
 }
 
-/* Parse an expression and convert functions or arrays to
-   pointers.  */
+/* Parse an expression and convert functions or arrays to pointers and
+   lvalues to rvalues.  */
 
 static struct c_expr
 c_parser_expression_conv (c_parser *parser)
@@ -7057,12 +7758,13 @@ c_parser_expression_conv (c_parser *parser)
   struct c_expr expr;
   location_t loc = c_parser_peek_token (parser)->location;
   expr = c_parser_expression (parser);
-  expr = default_function_array_conversion (loc, expr);
+  expr = convert_lvalue_to_rvalue (loc, expr, true, false);
   return expr;
 }
 
 /* Parse a non-empty list of expressions.  If CONVERT_P, convert
-   functions and arrays to pointers.  If FOLD_P, fold the expressions.
+   functions and arrays to pointers and lvalues to rvalues.  If
+   FOLD_P, fold the expressions.
 
    nonempty-expr-list:
      assignment-expression
@@ -7092,7 +7794,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
     cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
-    expr = default_function_array_read_conversion (loc, expr);
+    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
   ret->quick_push (expr.value);
@@ -7116,7 +7818,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
        cur_sizeof_arg_loc = UNKNOWN_LOCATION;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
-       expr = default_function_array_read_conversion (loc, expr);
+       expr = convert_lvalue_to_rvalue (loc, expr, true, true);
       if (fold_p)
        expr.value = c_fully_fold (expr.value, false, NULL);
       vec_safe_push (ret, expr.value);
@@ -7621,7 +8323,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
            }
          else
            c_parser_declaration_or_fndef (parser, false, false, true,
-                                          false, true, NULL);
+                                          false, true, NULL, vNULL);
          break;
        }
     }
@@ -8022,7 +8724,9 @@ c_parser_objc_synchronized_statement (c_parser *parser)
   objc_maybe_warn_exceptions (loc);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      expr = c_parser_expression (parser).value;
+      struct c_expr ce = c_parser_expression (parser);
+      ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+      expr = ce.value;
       expr = c_fully_fold (expr, false, NULL);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
@@ -8042,6 +8746,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
        break continue return goto asm sizeof typeof __alignof
        unsigned long const short volatile signed restrict _Complex
        in out inout bycopy byref oneway int char float double void _Bool
+       _Atomic
 
    ??? Why this selection of keywords but not, for example, storage
    class specifiers?  */
@@ -8100,6 +8805,8 @@ c_parser_objc_selector (c_parser *parser)
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
+    case RID_ATOMIC:
+    case RID_AUTO_TYPE:
       c_parser_consume_token (parser);
       return value;
     default:
@@ -8152,6 +8859,8 @@ c_parser_objc_selector_arg (c_parser *parser)
 static tree
 c_parser_objc_receiver (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
+
   if (c_parser_peek_token (parser)->type == CPP_NAME
       && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
          || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
@@ -8160,7 +8869,9 @@ c_parser_objc_receiver (c_parser *parser)
       c_parser_consume_token (parser);
       return objc_get_class_reference (id);
     }
-  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
+  struct c_expr ce = c_parser_expression (parser);
+  ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+  return c_fully_fold (ce.value, false, NULL);
 }
 
 /* Parse objc-message-args.
@@ -8602,10 +9313,39 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       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;
 
+    case PRAGMA_OMP_TARGET:
+      return c_parser_omp_target (parser, context);
+
+    case PRAGMA_OMP_END_DECLARE_TARGET:
+      c_parser_omp_end_declare_target (parser);
+      return false;
+
     case PRAGMA_OMP_SECTION:
       error_at (c_parser_peek_token (parser)->location,
                "%<#pragma omp section%> may only be used in "
@@ -8613,15 +9353,43 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
-    case PRAGMA_GCC_PCH_PREPROCESS:
-      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
-      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+    case PRAGMA_OMP_DECLARE_REDUCTION:
+      c_parser_omp_declare (parser, context);
       return false;
-
+    case PRAGMA_IVDEP:
+      c_parser_consume_pragma (parser);
+      c_parser_skip_to_pragma_eol (parser);
+      if (!c_parser_next_token_is_keyword (parser, RID_FOR)
+         && !c_parser_next_token_is_keyword (parser, RID_WHILE)
+         && !c_parser_next_token_is_keyword (parser, RID_DO))
+       {
+         c_parser_error (parser, "for, while or do statement expected");
+         return false;
+       }
+      if (c_parser_next_token_is_keyword (parser, RID_FOR))
+       c_parser_for_statement (parser, true);
+      else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
+       c_parser_while_statement (parser, true);
+      else
+       c_parser_do_statement (parser, true);
+      return false;
+
+    case PRAGMA_GCC_PCH_PREPROCESS:
+      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+
+    case PRAGMA_CILK_SIMD:
+      if (!c_parser_cilk_verify_simd (parser, context))
+       return false;
+      c_parser_consume_pragma (parser);
+      c_parser_cilk_simd (parser);
+      return false;
+
     default:
       if (id < PRAGMA_FIRST_EXTERNAL)
        {
-         if (context == pragma_external)
+         if (context != pragma_stmt && context != pragma_compound)
            {
            bad_stmt:
              c_parser_error (parser, "expected declaration specifiers");
@@ -8686,7 +9454,7 @@ c_parser_pragma_pch_preprocess (c_parser *parser)
     c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
 }
 \f
-/* 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
@@ -8702,12 +9470,18 @@ c_parser_omp_clause_name (c_parser *parser)
     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;
@@ -8716,23 +9490,45 @@ c_parser_omp_clause_name (c_parser *parser)
           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;
@@ -8741,21 +9537,41 @@ c_parser_omp_clause_name (c_parser *parser)
            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 ("thread_limit", p))
+           result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
+         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;
        }
@@ -8799,8 +9615,7 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
 static tree
 c_parser_omp_variable_list (c_parser *parser,
                            location_t clause_loc,
-                           enum omp_clause_code kind,
-                            tree list)
+                           enum omp_clause_code kind, tree list)
 {
   if (c_parser_next_token_is_not (parser, CPP_NAME)
       || c_parser_peek_token (parser)->id_kind != C_ID_ID)
@@ -8812,22 +9627,70 @@ c_parser_omp_variable_list (c_parser *parser,
       tree t = lookup_name (c_parser_peek_token (parser)->value);
 
       if (t == NULL_TREE)
-       undeclared_variable (c_parser_peek_token (parser)->location,
-                            c_parser_peek_token (parser)->value);
-      else if (t == error_mark_node)
+       {
+         undeclared_variable (c_parser_peek_token (parser)->location,
+                              c_parser_peek_token (parser)->value);
+         t = error_mark_node;
+       }
+
+      c_parser_consume_token (parser);
+
+      if (t == error_mark_node)
        ;
       else if (kind != 0)
        {
-         tree u = build_omp_clause (clause_loc, kind);
-         OMP_CLAUSE_DECL (u) = t;
-         OMP_CLAUSE_CHAIN (u) = list;
-         list = u;
+         switch (kind)
+           {
+           case OMP_CLAUSE_MAP:
+           case OMP_CLAUSE_FROM:
+           case OMP_CLAUSE_TO:
+           case OMP_CLAUSE_DEPEND:
+             while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+               {
+                 tree low_bound = NULL_TREE, length = NULL_TREE;
+
+                 c_parser_consume_token (parser);
+                 if (!c_parser_next_token_is (parser, CPP_COLON))
+                   low_bound = c_parser_expression (parser).value;
+                 if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+                   length = integer_one_node;
+                 else
+                   {
+                     /* Look for `:'.  */
+                     if (!c_parser_require (parser, CPP_COLON,
+                                            "expected %<:%>"))
+                       {
+                         t = error_mark_node;
+                         break;
+                       }
+                     if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+                       length = c_parser_expression (parser).value;
+                   }
+                 /* Look for the closing `]'.  */
+                 if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
+                                        "expected %<]%>"))
+                   {
+                     t = error_mark_node;
+                     break;
+                   }
+                 t = tree_cons (low_bound, length, t);
+               }
+             break;
+           default:
+             break;
+           }
+
+         if (t != error_mark_node)
+           {
+             tree u = build_omp_clause (clause_loc, kind);
+             OMP_CLAUSE_DECL (u) = t;
+             OMP_CLAUSE_CHAIN (u) = list;
+             list = u;
+           }
        }
       else
        list = tree_cons (t, NULL_TREE, list);
 
-      c_parser_consume_token (parser);
-
       if (c_parser_next_token_is_not (parser, CPP_COMMA))
        break;
 
@@ -8875,9 +9738,11 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list)
     }
   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
+      || !tree_fits_shwi_p (num)
+      || (n = tree_to_shwi (num)) <= 0
       || (int) n != n)
     {
       error_at (loc,
@@ -9140,11 +10005,17 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
 
    reduction-operator:
      One of: + * - & ^ | && ||
-     
+
    OpenMP 3.1:
    
    reduction-operator:
-     One of: + * - & ^ | && || max min  */
+     One of: + * - & ^ | && || max min
+
+   OpenMP 4.0:
+
+   reduction-operator:
+     One of: + * - & ^ | && ||
+     identifier  */
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
@@ -9152,7 +10023,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
   location_t clause_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      enum tree_code code;
+      enum tree_code code = ERROR_MARK;
+      tree reduc_id = NULL_TREE;
 
       switch (c_parser_peek_token (parser)->type)
        {
@@ -9194,8 +10066,9 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
                code = MAX_EXPR;
                break;
              }
+           reduc_id = c_parser_peek_token (parser)->value;
+           break;
          }
-         /* FALLTHRU */
        default:
          c_parser_error (parser,
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
@@ -9204,6 +10077,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
          return list;
        }
       c_parser_consume_token (parser);
+      reduc_id = c_omp_reduction_id (code, reduc_id);
       if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        {
          tree nl, c;
@@ -9211,7 +10085,17 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
          nl = c_parser_omp_variable_list (parser, clause_loc,
                                           OMP_CLAUSE_REDUCTION, list);
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
-           OMP_CLAUSE_REDUCTION_CODE (c) = code;
+           {
+             tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
+             OMP_CLAUSE_REDUCTION_CODE (c) = code;
+             if (code == ERROR_MARK
+                 || !(INTEGRAL_TYPE_P (type)
+                      || TREE_CODE (type) == REAL_TYPE
+                      || TREE_CODE (type) == COMPLEX_TYPE))
+               OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
+                 = c_omp_reduction_lookup (reduc_id,
+                                           TYPE_MAIN_VARIANT (type));
+           }
 
          list = nl;
        }
@@ -9341,1209 +10225,2988 @@ c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
   return c;
 }
 
-/* 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.  */
+/* OpenMP 4.0:
+   inbranch
+   notinbranch */
 
 static tree
-c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
-                         const char *where)
+c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
+                           enum omp_clause_code code, tree list)
 {
-  tree clauses = NULL;
-  bool first = true;
+  check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
 
-  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    {
-      location_t here;
-      pragma_omp_clause c_kind;
-      const char *c_name;
-      tree prev = clauses;
+  tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
+  OMP_CLAUSE_CHAIN (c) = list;
 
-      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
+  return c;
+}
 
-      first = false;
-      here = c_parser_peek_token (parser)->location;
-      c_kind = c_parser_omp_clause_name (parser);
+/* OpenMP 4.0:
+   parallel
+   for
+   sections
+   taskgroup */
 
-      switch (c_kind)
+static tree
+c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
+                               enum omp_clause_code code, tree list)
+{
+  tree c = build_omp_clause (c_parser_peek_token (parser)->location, 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)))
        {
-       case PRAGMA_OMP_CLAUSE_COLLAPSE:
-         clauses = c_parser_omp_clause_collapse (parser, clauses);
-         c_name = "collapse";
-         break;
-       case PRAGMA_OMP_CLAUSE_COPYIN:
-         clauses = c_parser_omp_clause_copyin (parser, clauses);
-         c_name = "copyin";
-         break;
-       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
-         clauses = c_parser_omp_clause_copyprivate (parser, clauses);
-         c_name = "copyprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_DEFAULT:
-         clauses = c_parser_omp_clause_default (parser, clauses);
-         c_name = "default";
-         break;
-       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
-         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
-         c_name = "firstprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_FINAL:
-         clauses = c_parser_omp_clause_final (parser, clauses);
-         c_name = "final";
-         break;
-       case PRAGMA_OMP_CLAUSE_IF:
-         clauses = c_parser_omp_clause_if (parser, clauses);
-         c_name = "if";
-         break;
-       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
-         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
-         c_name = "lastprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_MERGEABLE:
-         clauses = c_parser_omp_clause_mergeable (parser, clauses);
-         c_name = "mergeable";
-         break;
-       case PRAGMA_OMP_CLAUSE_NOWAIT:
-         clauses = c_parser_omp_clause_nowait (parser, clauses);
-         c_name = "nowait";
-         break;
-       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-         clauses = c_parser_omp_clause_num_threads (parser, clauses);
-         c_name = "num_threads";
-         break;
-       case PRAGMA_OMP_CLAUSE_ORDERED:
-         clauses = c_parser_omp_clause_ordered (parser, clauses);
-         c_name = "ordered";
-         break;
-       case PRAGMA_OMP_CLAUSE_PRIVATE:
-         clauses = c_parser_omp_clause_private (parser, clauses);
-         c_name = "private";
-         break;
-       case PRAGMA_OMP_CLAUSE_REDUCTION:
-         clauses = c_parser_omp_clause_reduction (parser, clauses);
-         c_name = "reduction";
-         break;
-       case PRAGMA_OMP_CLAUSE_SCHEDULE:
-         clauses = c_parser_omp_clause_schedule (parser, clauses);
-         c_name = "schedule";
-         break;
-       case PRAGMA_OMP_CLAUSE_SHARED:
-         clauses = c_parser_omp_clause_shared (parser, clauses);
-         c_name = "shared";
-         break;
-       case PRAGMA_OMP_CLAUSE_UNTIED:
-         clauses = c_parser_omp_clause_untied (parser, clauses);
-         c_name = "untied";
-         break;
-       default:
-         c_parser_error (parser, "expected %<#pragma omp%> clause");
-         goto saw_error;
+         c_parser_error (parser, "expected integer expression");
+         return list;
        }
 
-      if (((mask >> c_kind) & 1) == 0 && !parser->error)
+      /* 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)
        {
-         /* Remove the invalid clause(s) from the list to avoid
-            confusing the rest of the compiler.  */
-         clauses = prev;
-         error_at (here, "%qs is not valid for %qs", c_name, where);
+         warning_at (expr_loc, 0, "%<num_teams%> value must be positive");
+         t = integer_one_node;
        }
-    }
 
- saw_error:
-  c_parser_skip_to_pragma_eol (parser);
+      check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
 
-  return c_finish_omp_clauses (clauses);
-}
+      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;
+    }
 
-/* OpenMP 2.5:
-   structured-block:
-     statement
+  return list;
+}
 
-   In practice, we're also interested in adding the statement to an
-   outer node.  So it is convenient if we work around the fact that
-   c_parser_statement calls add_stmt.  */
+/* OpenMP 4.0:
+   thread_limit ( expression ) */
 
 static tree
-c_parser_omp_structured_block (c_parser *parser)
+c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
 {
-  tree stmt = push_stmt_list ();
-  c_parser_statement (parser);
-  return pop_stmt_list (stmt);
-}
-
-/* OpenMP 2.5:
-   # pragma omp atomic new-line
-     expression-stmt
+  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);
 
-   expression-stmt:
-     x binop= expr | x++ | ++x | x-- | --x
-   binop:
-     +, *, -, /, &, ^, |, <<, >>
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
-  where x is an lvalue expression with scalar type.
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+       {
+         c_parser_error (parser, "expected integer expression");
+         return list;
+       }
 
-   OpenMP 3.1:
-   # pragma omp atomic new-line
-     update-stmt
+      /* 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, "%<thread_limit%> value must be positive");
+         t = integer_one_node;
+       }
 
-   # pragma omp atomic read new-line
-     read-stmt
+      check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
+                                "thread_limit");
 
-   # pragma omp atomic write new-line
-     write-stmt
+      c = build_omp_clause (num_teams_loc, OMP_CLAUSE_THREAD_LIMIT);
+      OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
 
-   # pragma omp atomic update new-line
-     update-stmt
+  return list;
+}
 
-   # pragma omp atomic capture new-line
-     capture-stmt
+/* OpenMP 4.0:
+   aligned ( variable-list )
+   aligned ( variable-list : constant-expression ) */
 
-   # pragma omp atomic capture new-line
-     capture-block
+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;
 
-   read-stmt:
-     v = x
-   write-stmt:
-     x = expr
-   update-stmt:
-     expression-stmt | x = x binop expr
-   capture-stmt:
-     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
-   capture-block:
-     { v = x; update-stmt; } | { update-stmt; v = x; }
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return list;
 
-  where x and v are lvalue expressions with scalar type.
+  nl = c_parser_omp_variable_list (parser, clause_loc,
+                                  OMP_CLAUSE_ALIGNED, list);
 
-  LOC is the location of the #pragma token.  */
+  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;
+       }
 
-static void
-c_parser_omp_atomic (location_t loc, c_parser *parser)
+      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)
 {
-  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
-  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
-  tree stmt, orig_lhs;
-  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
-  struct c_expr rhs_expr;
-  bool structured_block = false;
+  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))
+    {
+      OMP_CLAUSE_LINEAR_STEP (c) = step;
+    }
+
+  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 (p, "read"))
-       code = OMP_ATOMIC_READ;
-      else if (!strcmp (p, "write"))
-       code = NOP_EXPR;
-      else if (!strcmp (p, "update"))
-       code = OMP_ATOMIC;
-      else if (!strcmp (p, "capture"))
-       code = OMP_ATOMIC_CAPTURE_NEW;
+      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
-       p = NULL;
-      if (p)
-       c_parser_consume_token (parser);
+       goto invalid_kind;
     }
-  c_parser_skip_to_pragma_eol (parser);
+  else
+    goto invalid_kind;
 
-  switch (code)
+  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)
     {
-    case OMP_ATOMIC_READ:
-    case NOP_EXPR: /* atomic write */
-      v = c_parser_unary_expression (parser).value;
-      v = c_fully_fold (v, false, NULL);
-      if (v == error_mark_node)
-       goto saw_error;
-      loc = c_parser_peek_token (parser)->location;
-      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-       goto saw_error;
-      if (code == NOP_EXPR)
-       lhs = c_parser_expression (parser).value;
+      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
-       lhs = c_parser_unary_expression (parser).value;
-      lhs = c_fully_fold (lhs, false, NULL);
-      if (lhs == error_mark_node)
-       goto saw_error;
-      if (code == NOP_EXPR)
        {
-         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
-            opcode.  */
-         code = OMP_ATOMIC;
-         rhs = lhs;
-         lhs = v;
-         v = NULL_TREE;
+         c_parser_error (parser, "invalid map kind");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return list;
        }
-      goto done;
-    case OMP_ATOMIC_CAPTURE_NEW:
-      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+      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_consume_token (parser);
-         structured_block = true;
+         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
-       {
-         v = c_parser_unary_expression (parser).value;
-         v = c_fully_fold (v, false, NULL);
-         if (v == error_mark_node)
-           goto saw_error;
-         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-           goto saw_error;
-       }
-      break;
-    default:
-      break;
+       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)
+{
+  /* The clauses location.  */
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
+                                        list);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  return 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.  */
+
+static tree
+c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
+                         const char *where, bool finish_p = true)
+{
+  tree clauses = NULL;
+  bool first = true;
+
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      location_t here;
+      pragma_omp_clause c_kind;
+      const char *c_name;
+      tree prev = clauses;
+
+      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+
+      here = c_parser_peek_token (parser)->location;
+      c_kind = c_parser_omp_clause_name (parser);
+
+      switch (c_kind)
+       {
+       case PRAGMA_OMP_CLAUSE_COLLAPSE:
+         clauses = c_parser_omp_clause_collapse (parser, clauses);
+         c_name = "collapse";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYIN:
+         clauses = c_parser_omp_clause_copyin (parser, clauses);
+         c_name = "copyin";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
+         clauses = c_parser_omp_clause_copyprivate (parser, clauses);
+         c_name = "copyprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEFAULT:
+         clauses = c_parser_omp_clause_default (parser, clauses);
+         c_name = "default";
+         break;
+       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
+         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+         c_name = "firstprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = c_parser_omp_clause_final (parser, clauses);
+         c_name = "final";
+         break;
+       case PRAGMA_OMP_CLAUSE_IF:
+         clauses = c_parser_omp_clause_if (parser, clauses);
+         c_name = "if";
+         break;
+       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
+         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+         c_name = "lastprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = c_parser_omp_clause_mergeable (parser, clauses);
+         c_name = "mergeable";
+         break;
+       case PRAGMA_OMP_CLAUSE_NOWAIT:
+         clauses = c_parser_omp_clause_nowait (parser, clauses);
+         c_name = "nowait";
+         break;
+       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
+         clauses = c_parser_omp_clause_num_threads (parser, clauses);
+         c_name = "num_threads";
+         break;
+       case PRAGMA_OMP_CLAUSE_ORDERED:
+         clauses = c_parser_omp_clause_ordered (parser, clauses);
+         c_name = "ordered";
+         break;
+       case PRAGMA_OMP_CLAUSE_PRIVATE:
+         clauses = c_parser_omp_clause_private (parser, clauses);
+         c_name = "private";
+         break;
+       case PRAGMA_OMP_CLAUSE_REDUCTION:
+         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         c_name = "reduction";
+         break;
+       case PRAGMA_OMP_CLAUSE_SCHEDULE:
+         clauses = c_parser_omp_clause_schedule (parser, clauses);
+         c_name = "schedule";
+         break;
+       case PRAGMA_OMP_CLAUSE_SHARED:
+         clauses = c_parser_omp_clause_shared (parser, clauses);
+         c_name = "shared";
+         break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         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";
+         if (!first)
+           {
+            clause_not_first:
+             error_at (here, "%qs must be the first clause of %qs",
+                       c_name, where);
+             clauses = prev;
+           }
+         break;
+       case PRAGMA_OMP_CLAUSE_FOR:
+         clauses
+           = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
+                                             clauses);
+         c_name = "for";
+         if (!first)
+           goto clause_not_first;
+         break;
+       case PRAGMA_OMP_CLAUSE_SECTIONS:
+         clauses
+           = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
+                                             clauses);
+         c_name = "sections";
+         if (!first)
+           goto clause_not_first;
+         break;
+       case PRAGMA_OMP_CLAUSE_TASKGROUP:
+         clauses
+           = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
+                                             clauses);
+         c_name = "taskgroup";
+         if (!first)
+           goto clause_not_first;
+         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_THREAD_LIMIT:
+         clauses = c_parser_omp_clause_thread_limit (parser, clauses);
+         c_name = "thread_limit";
+         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;
+       }
+
+      first = false;
+
+      if (((mask >> c_kind) & 1) == 0 && !parser->error)
+       {
+         /* Remove the invalid clause(s) from the list to avoid
+            confusing the rest of the compiler.  */
+         clauses = prev;
+         error_at (here, "%qs is not valid for %qs", c_name, where);
+       }
+    }
+
+ saw_error:
+  c_parser_skip_to_pragma_eol (parser);
+
+  if (finish_p)
+    return c_finish_omp_clauses (clauses);
+
+  return clauses;
+}
+
+/* OpenMP 2.5:
+   structured-block:
+     statement
+
+   In practice, we're also interested in adding the statement to an
+   outer node.  So it is convenient if we work around the fact that
+   c_parser_statement calls add_stmt.  */
+
+static tree
+c_parser_omp_structured_block (c_parser *parser)
+{
+  tree stmt = push_stmt_list ();
+  c_parser_statement (parser);
+  return pop_stmt_list (stmt);
+}
+
+/* OpenMP 2.5:
+   # pragma omp atomic new-line
+     expression-stmt
+
+   expression-stmt:
+     x binop= expr | x++ | ++x | x-- | --x
+   binop:
+     +, *, -, /, &, ^, |, <<, >>
+
+  where x is an lvalue expression with scalar type.
+
+   OpenMP 3.1:
+   # pragma omp atomic new-line
+     update-stmt
+
+   # pragma omp atomic read new-line
+     read-stmt
+
+   # pragma omp atomic write new-line
+     write-stmt
+
+   # pragma omp atomic update new-line
+     update-stmt
+
+   # pragma omp atomic capture new-line
+     capture-stmt
+
+   # pragma omp atomic capture new-line
+     capture-block
+
+   read-stmt:
+     v = x
+   write-stmt:
+     x = expr
+   update-stmt:
+     expression-stmt | x = x binop expr
+   capture-stmt:
+     v = expression-stmt
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; }
+
+   OpenMP 4.0:
+   update-stmt:
+     expression-stmt | x = x binop expr | x = expr binop x
+   capture-stmt:
+     v = update-stmt
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
+
+  where x and v are lvalue expressions with scalar type.
+
+  LOC is the location of the #pragma token.  */
+
+static void
+c_parser_omp_atomic (location_t loc, c_parser *parser)
+{
+  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
+  tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
+  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  struct c_expr expr;
+  location_t eloc;
+  bool structured_block = false;
+  bool swapped = false;
+  bool seq_cst = false;
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      if (!strcmp (p, "read"))
+       code = OMP_ATOMIC_READ;
+      else if (!strcmp (p, "write"))
+       code = NOP_EXPR;
+      else if (!strcmp (p, "update"))
+       code = OMP_ATOMIC;
+      else if (!strcmp (p, "capture"))
+       code = OMP_ATOMIC_CAPTURE_NEW;
+      else
+       p = NULL;
+      if (p)
+       c_parser_consume_token (parser);
+    }
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp (p, "seq_cst"))
+       {
+         seq_cst = true;
+         c_parser_consume_token (parser);
+       }
+    }
+  c_parser_skip_to_pragma_eol (parser);
+
+  switch (code)
+    {
+    case OMP_ATOMIC_READ:
+    case NOP_EXPR: /* atomic write */
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      loc = c_parser_peek_token (parser)->location;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      if (code == NOP_EXPR)
+       lhs = c_parser_expression (parser).value;
+      else
+       lhs = c_parser_unary_expression (parser).value;
+      lhs = c_fully_fold (lhs, false, NULL);
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (code == NOP_EXPR)
+       {
+         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+            opcode.  */
+         code = OMP_ATOMIC;
+         rhs = lhs;
+         lhs = v;
+         v = NULL_TREE;
+       }
+      goto done;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         c_parser_consume_token (parser);
+         structured_block = true;
+       }
+      else
+       {
+         v = c_parser_unary_expression (parser).value;
+         v = c_fully_fold (v, false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+           goto saw_error;
+       }
+      break;
+    default:
+      break;
+    }
+
+  /* For structured_block case we don't know yet whether
+     old or new x should be captured.  */
+restart:
+  eloc = c_parser_peek_token (parser)->location;
+  expr = c_parser_unary_expression (parser);
+  lhs = expr.value;
+  expr = default_function_array_conversion (eloc, expr);
+  unfolded_lhs = expr.value;
+  lhs = c_fully_fold (lhs, false, NULL);
+  orig_lhs = lhs;
+  switch (TREE_CODE (lhs))
+    {
+    case ERROR_MARK:
+    saw_error:
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      if (structured_block)
+       {
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           c_parser_consume_token (parser);
+         else if (code == OMP_ATOMIC_CAPTURE_NEW)
+           {
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+               c_parser_consume_token (parser);
+           }
+       }
+      return;
+
+    case POSTINCREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREINCREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      unfolded_lhs = NULL_TREE;
+      opcode = PLUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    case POSTDECREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREDECREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      unfolded_lhs = NULL_TREE;
+      opcode = MINUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+         && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+         && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+                                             (TREE_OPERAND (lhs, 1), 0), 0)))
+            == BOOLEAN_TYPE)
+       /* Undo effects of boolean_increment for post {in,de}crement.  */
+       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+       {
+         /* Undo effects of boolean_increment.  */
+         if (integer_onep (TREE_OPERAND (lhs, 1)))
+           {
+             /* This is pre or post increment.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             unfolded_lhs = NULL_TREE;
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+         if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
+             && TREE_OPERAND (lhs, 0)
+                == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
+           {
+             /* This is pre or post decrement.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             unfolded_lhs = NULL_TREE;
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+       }
+      /* FALLTHRU */
+    default:
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_MULT_EQ:
+         opcode = MULT_EXPR;
+         break;
+       case CPP_DIV_EQ:
+         opcode = TRUNC_DIV_EXPR;
+         break;
+       case CPP_PLUS_EQ:
+         opcode = PLUS_EXPR;
+         break;
+       case CPP_MINUS_EQ:
+         opcode = MINUS_EXPR;
+         break;
+       case CPP_LSHIFT_EQ:
+         opcode = LSHIFT_EXPR;
+         break;
+       case CPP_RSHIFT_EQ:
+         opcode = RSHIFT_EXPR;
+         break;
+       case CPP_AND_EQ:
+         opcode = BIT_AND_EXPR;
+         break;
+       case CPP_OR_EQ:
+         opcode = BIT_IOR_EXPR;
+         break;
+       case CPP_XOR_EQ:
+         opcode = BIT_XOR_EXPR;
+         break;
+       case CPP_EQ:
+         c_parser_consume_token (parser);
+         eloc = c_parser_peek_token (parser)->location;
+         expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
+         rhs1 = expr.value;
+         switch (TREE_CODE (rhs1))
+           {
+           case MULT_EXPR:
+           case TRUNC_DIV_EXPR:
+           case PLUS_EXPR:
+           case MINUS_EXPR:
+           case LSHIFT_EXPR:
+           case RSHIFT_EXPR:
+           case BIT_AND_EXPR:
+           case BIT_IOR_EXPR:
+           case BIT_XOR_EXPR:
+             if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
+               {
+                 opcode = TREE_CODE (rhs1);
+                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+                 goto stmt_done;
+               }
+             if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
+               {
+                 opcode = TREE_CODE (rhs1);
+                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+                 swapped = !commutative_tree_code (opcode);
+                 goto stmt_done;
+               }
+             break;
+           case ERROR_MARK:
+             goto saw_error;
+           default:
+             break;
+           }
+         if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
+           {
+             if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+               {
+                 code = OMP_ATOMIC_CAPTURE_OLD;
+                 v = lhs;
+                 lhs = NULL_TREE;
+                 expr = default_function_array_read_conversion (eloc, expr);
+                 unfolded_lhs1 = expr.value;
+                 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL);
+                 rhs1 = NULL_TREE;
+                 c_parser_consume_token (parser);
+                 goto restart;
+               }
+             if (structured_block)
+               {
+                 opcode = NOP_EXPR;
+                 expr = default_function_array_read_conversion (eloc, expr);
+                 rhs = c_fully_fold (expr.value, false, NULL);
+                 rhs1 = NULL_TREE;
+                 goto stmt_done;
+               }
+           }
+         c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
+         goto saw_error;
+       default:
+         c_parser_error (parser,
+                         "invalid operator for %<#pragma omp atomic%>");
+         goto saw_error;
+       }
+
+      /* Arrange to pass the location of the assignment operator to
+        c_finish_omp_atomic.  */
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      eloc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expression (parser);
+      expr = default_function_array_read_conversion (eloc, expr);
+      rhs = expr.value;
+      rhs = c_fully_fold (rhs, false, NULL);
+      break;
+    }
+stmt_done:
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+    {
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+       goto saw_error;
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      eloc = c_parser_peek_token (parser)->location;
+      expr = c_parser_unary_expression (parser);
+      lhs1 = expr.value;
+      expr = default_function_array_read_conversion (eloc, expr);
+      unfolded_lhs1 = expr.value;
+      lhs1 = c_fully_fold (lhs1, false, NULL);
+      if (lhs1 == error_mark_node)
+       goto saw_error;
+    }
+  if (structured_block)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+    }
+done:
+  if (unfolded_lhs && unfolded_lhs1
+      && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
+    {
+      error ("%<#pragma omp atomic capture%> uses two different "
+            "expressions for memory");
+      stmt = error_mark_node;
+    }
+  else
+    stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
+                               swapped, seq_cst);
+  if (stmt != error_mark_node)
+    add_stmt (stmt);
+
+  if (!structured_block)
+    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+
+/* OpenMP 2.5:
+   # pragma omp barrier new-line
+*/
+
+static void
+c_parser_omp_barrier (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_barrier (loc);
+}
+
+/* OpenMP 2.5:
+   # pragma omp critical [(name)] new-line
+     structured-block
+
+  LOC is the location of the #pragma itself.  */
+
+static tree
+c_parser_omp_critical (location_t loc, c_parser *parser)
+{
+  tree stmt, name = NULL;
+
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         name = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+         c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+       }
+      else
+       c_parser_error (parser, "expected identifier");
+    }
+  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    c_parser_error (parser, "expected %<(%> or end of line");
+  c_parser_skip_to_pragma_eol (parser);
+
+  stmt = c_parser_omp_structured_block (parser);
+  return c_finish_omp_critical (loc, stmt, name);
+}
+
+/* OpenMP 2.5:
+   # pragma omp flush flush-vars[opt] new-line
+
+   flush-vars:
+     ( variable-list ) */
+
+static void
+c_parser_omp_flush (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    c_parser_error (parser, "expected %<(%> or end of line");
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_flush (loc);
+}
+
+/* Parse the restricted form of the for statement allowed by OpenMP.
+   The real trick here is to determine the loop control variable early
+   so that we can push a new decl if necessary to make it private.
+   LOC is the location of the OMP in "#pragma omp".  */
+
+static tree
+c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
+                      tree clauses, tree *cclauses)
+{
+  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
+  tree declv, condv, incrv, initv, ret = NULL;
+  bool fail = false, open_brace_parsed = false;
+  int i, collapse = 1, nbraces = 0;
+  location_t for_loc;
+  vec<tree, va_gc> *for_block = make_tree_vector ();
+
+  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+      collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
+
+  gcc_assert (collapse >= 1);
+
+  declv = make_tree_vec (collapse);
+  initv = make_tree_vec (collapse);
+  condv = make_tree_vec (collapse);
+  incrv = make_tree_vec (collapse);
+
+  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+    {
+      c_parser_error (parser, "for statement expected");
+      return NULL;
+    }
+  for_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+
+  for (i = 0; i < collapse; i++)
+    {
+      int bracecount = 0;
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       goto pop_scopes;
+
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_tokens_start_declaration (parser))
+       {
+         if (i > 0)
+           vec_safe_push (for_block, c_begin_compound_stmt (true));
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true,
+                                        NULL, vNULL);
+         decl = check_for_loop_decls (for_loc, flag_isoc99);
+         if (decl == NULL)
+           goto error_init;
+         if (DECL_INITIAL (decl) == error_mark_node)
+           decl = error_mark_node;
+         init = decl;
+       }
+      else if (c_parser_next_token_is (parser, CPP_NAME)
+              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+       {
+         struct c_expr decl_exp;
+         struct c_expr init_exp;
+         location_t init_loc;
+
+         decl_exp = c_parser_postfix_expression (parser);
+         decl = decl_exp.value;
+
+         c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+         init_loc = c_parser_peek_token (parser)->location;
+         init_exp = c_parser_expr_no_commas (parser, NULL);
+         init_exp = default_function_array_read_conversion (init_loc,
+                                                            init_exp);
+         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+                                   NOP_EXPR, init_loc, init_exp.value,
+                                   init_exp.original_type);
+         init = c_process_expr_stmt (init_loc, init);
+
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+       }
+      else
+       {
+       error_init:
+         c_parser_error (parser,
+                         "expected iteration declaration or initialization");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         fail = true;
+         goto parse_next;
+       }
+
+      /* Parse the loop condition.  */
+      cond = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+       {
+         location_t cond_loc = c_parser_peek_token (parser)->location;
+         struct c_expr cond_expr
+           = c_parser_binary_expression (parser, NULL, NULL_TREE);
+
+         cond = cond_expr.value;
+         cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+         cond = c_fully_fold (cond, false, NULL);
+         switch (cond_expr.original_code)
+           {
+           case GT_EXPR:
+           case GE_EXPR:
+           case LT_EXPR:
+           case LE_EXPR:
+             break;
+           case NE_EXPR:
+             if (code == CILK_SIMD)
+               break;
+             /* FALLTHRU.  */
+           default:
+             /* Can't be cond = error_mark_node, because we want to preserve
+                the location until c_finish_omp_for.  */
+             cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
+             break;
+           }
+         protected_set_expr_location (cond, cond_loc);
+       }
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+      /* Parse the increment expression.  */
+      incr = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+       {
+         location_t incr_loc = c_parser_peek_token (parser)->location;
+
+         incr = c_process_expr_stmt (incr_loc,
+                                     c_parser_expression (parser).value);
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
+       fail = true;
+      else
+       {
+         TREE_VEC_ELT (declv, i) = decl;
+         TREE_VEC_ELT (initv, i) = init;
+         TREE_VEC_ELT (condv, i) = cond;
+         TREE_VEC_ELT (incrv, i) = incr;
+       }
+
+    parse_next:
+      if (i == collapse - 1)
+       break;
+
+      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+        in between the collapsed for loops to be still considered perfectly
+        nested.  Hopefully the final version clarifies this.
+        For now handle (multiple) {'s and empty statements.  */
+      do
+       {
+         if (c_parser_next_token_is_keyword (parser, RID_FOR))
+           {
+             c_parser_consume_token (parser);
+             break;
+           }
+         else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+           {
+             c_parser_consume_token (parser);
+             bracecount++;
+           }
+         else if (bracecount
+                  && c_parser_next_token_is (parser, CPP_SEMICOLON))
+           c_parser_consume_token (parser);
+         else
+           {
+             c_parser_error (parser, "not enough perfectly nested loops");
+             if (bracecount)
+               {
+                 open_brace_parsed = true;
+                 bracecount--;
+               }
+             fail = true;
+             collapse = 0;
+             break;
+           }
+       }
+      while (1);
+
+      nbraces += bracecount;
+    }
+
+  save_break = c_break_label;
+  if (code == CILK_SIMD)
+    c_break_label = build_int_cst (size_type_node, 2);
+  else
+    c_break_label = size_one_node;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = push_stmt_list ();
+
+  if (open_brace_parsed)
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      stmt = c_begin_compound_stmt (true);
+      c_parser_compound_statement_nostart (parser);
+      add_stmt (c_end_compound_stmt (here, stmt, true));
+    }
+  else
+    add_stmt (c_parser_c99_block_statement (parser));
+  if (c_cont_label)
+    {
+      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
+      SET_EXPR_LOCATION (t, loc);
+      add_stmt (t);
+    }
+
+  body = pop_stmt_list (body);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+
+  while (nbraces)
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       {
+         c_parser_consume_token (parser);
+         nbraces--;
+       }
+      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       c_parser_consume_token (parser);
+      else
+       {
+         c_parser_error (parser, "collapsed loops not perfectly nested");
+         while (nbraces)
+           {
+             location_t here = c_parser_peek_token (parser)->location;
+             stmt = c_begin_compound_stmt (true);
+             add_stmt (body);
+             c_parser_compound_statement_nostart (parser);
+             body = c_end_compound_stmt (here, stmt, true);
+             nbraces--;
+           }
+         goto pop_scopes;
+       }
+    }
+
+  /* Only bother calling c_finish_omp_for if we haven't already generated
+     an error from the initialization parsing.  */
+  if (!fail)
+    {
+      stmt = c_finish_omp_for (loc, code, declv, initv, condv,
+                              incrv, body, NULL);
+      if (stmt)
+       {
+         if (cclauses != NULL
+             && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
+           {
+             tree *c;
+             for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
+               if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
+                   && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
+                 c = &OMP_CLAUSE_CHAIN (*c);
+               else
+                 {
+                   for (i = 0; i < collapse; i++)
+                     if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
+                       break;
+                   if (i == collapse)
+                     c = &OMP_CLAUSE_CHAIN (*c);
+                   else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
+                     {
+                       error_at (loc,
+                                 "iteration variable %qD should not be firstprivate",
+                                 OMP_CLAUSE_DECL (*c));
+                       *c = OMP_CLAUSE_CHAIN (*c);
+                     }
+                   else
+                     {
+                       /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                          change it to shared (decl) in
+                          OMP_PARALLEL_CLAUSES.  */
+                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
+                                                  OMP_CLAUSE_LASTPRIVATE);
+                       OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
+                       OMP_CLAUSE_CHAIN (l) = clauses;
+                       clauses = l;
+                       OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+                     }
+                 }
+           }
+         OMP_FOR_CLAUSES (stmt) = clauses;
+       }
+      ret = stmt;
+    }
+pop_scopes:
+  while (!for_block->is_empty ())
+    {
+      /* FIXME diagnostics: LOC below should be the actual location of
+        this particular for block.  We need to build a list of
+        locations to go along with FOR_BLOCK.  */
+      stmt = c_end_compound_stmt (loc, for_block->pop (), true);
+      add_stmt (stmt);
+    }
+  release_tree_vector (for_block);
+  return ret;
+}
+
+/* Helper function for OpenMP parsing, split clauses and call
+   finish_omp_clauses on each of the set of clauses afterwards.  */
+
+static void
+omp_split_clauses (location_t loc, enum tree_code code,
+                  omp_clause_mask mask, tree clauses, tree *cclauses)
+{
+  int i;
+  c_omp_split_clauses (loc, code, mask, clauses, cclauses);
+  for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+    if (cclauses[i])
+      cclauses[i] = c_finish_omp_clauses (cclauses[i]);
+}
+
+/* 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,
+                  char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+  tree block, clauses, ret;
+
+  strcat (p_name, " simd");
+  mask |= OMP_SIMD_CLAUSE_MASK;
+  mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+  if (cclauses)
+    {
+      omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+    }
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses);
+  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.
+*/
+
+#define OMP_FOR_CLAUSE_MASK                                    \
+       ( (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_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_for (location_t loc, c_parser *parser,
+                 char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+  tree block, clauses, ret;
+
+  strcat (p_name, " for");
+  mask |= OMP_FOR_CLAUSE_MASK;
+  if (cclauses)
+    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)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
+
+         c_parser_consume_token (parser);
+         if (!flag_openmp)  /* flag_openmp_simd  */
+           return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+         block = c_begin_compound_stmt (true);
+         ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+         block = c_end_compound_stmt (loc, block, true);
+         if (ret == NULL_TREE)
+           return ret;
+         ret = make_node (OMP_FOR);
+         TREE_TYPE (ret) = void_type_node;
+         OMP_FOR_BODY (ret) = block;
+         OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+         SET_EXPR_LOCATION (ret, loc);
+         add_stmt (ret);
+         return ret;
+       }
+    }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+  if (cclauses)
+    {
+      omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+    }
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses);
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+
+  return ret;
+}
+
+/* OpenMP 2.5:
+   # pragma omp master new-line
+     structured-block
+
+   LOC is the location of the #pragma token.
+*/
+
+static tree
+c_parser_omp_master (location_t loc, c_parser *parser)
+{
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+   # pragma omp ordered new-line
+     structured-block
+
+   LOC is the location of the #pragma itself.
+*/
+
+static tree
+c_parser_omp_ordered (location_t loc, c_parser *parser)
+{
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+
+   section-scope:
+     { section-sequence }
+
+   section-sequence:
+     section-directive[opt] structured-block
+     section-sequence section-directive structured-block
 
-  /* For structured_block case we don't know yet whether
-     old or new x should be captured.  */
-restart:
-  lhs = c_parser_unary_expression (parser).value;
-  lhs = c_fully_fold (lhs, false, NULL);
-  orig_lhs = lhs;
-  switch (TREE_CODE (lhs))
+    SECTIONS_LOC is the location of the #pragma omp sections.  */
+
+static tree
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
+{
+  tree stmt, substmt;
+  bool error_suppress = false;
+  location_t loc;
+
+  loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
-    case ERROR_MARK:
-    saw_error:
-      c_parser_skip_to_end_of_block_or_statement (parser);
-      if (structured_block)
-       {
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           c_parser_consume_token (parser);
-         else if (code == OMP_ATOMIC_CAPTURE_NEW)
-           {
-             c_parser_skip_to_end_of_block_or_statement (parser);
-             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               c_parser_consume_token (parser);
-           }
-       }
-      return;
+      /* Avoid skipping until the end of the block.  */
+      parser->error = false;
+      return NULL_TREE;
+    }
 
-    case POSTINCREMENT_EXPR:
-      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
-       code = OMP_ATOMIC_CAPTURE_OLD;
-      /* FALLTHROUGH */
-    case PREINCREMENT_EXPR:
-      lhs = TREE_OPERAND (lhs, 0);
-      opcode = PLUS_EXPR;
-      rhs = integer_one_node;
-      break;
+  stmt = push_stmt_list ();
 
-    case POSTDECREMENT_EXPR:
-      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
-       code = OMP_ATOMIC_CAPTURE_OLD;
-      /* FALLTHROUGH */
-    case PREDECREMENT_EXPR:
-      lhs = TREE_OPERAND (lhs, 0);
-      opcode = MINUS_EXPR;
-      rhs = integer_one_node;
-      break;
+  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
+    {
+      substmt = c_parser_omp_structured_block (parser);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      SET_EXPR_LOCATION (substmt, loc);
+      add_stmt (substmt);
+    }
 
-    case COMPOUND_EXPR:
-      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
-         && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
-         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
-         && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
-                                             (TREE_OPERAND (lhs, 1), 0), 0)))
-            == BOOLEAN_TYPE)
-       /* Undo effects of boolean_increment for post {in,de}crement.  */
-       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
-      /* FALLTHRU */
-    case MODIFY_EXPR:
-      if (TREE_CODE (lhs) == MODIFY_EXPR
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+  while (1)
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       break;
+      if (c_parser_next_token_is (parser, CPP_EOF))
+       break;
+
+      loc = c_parser_peek_token (parser)->location;
+      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
        {
-         /* Undo effects of boolean_increment.  */
-         if (integer_onep (TREE_OPERAND (lhs, 1)))
-           {
-             /* This is pre or post increment.  */
-             rhs = TREE_OPERAND (lhs, 1);
-             lhs = TREE_OPERAND (lhs, 0);
-             opcode = NOP_EXPR;
-             if (code == OMP_ATOMIC_CAPTURE_NEW
-                 && !structured_block
-                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
-               code = OMP_ATOMIC_CAPTURE_OLD;
-             break;
-           }
-         if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
-             && TREE_OPERAND (lhs, 0)
-                == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
-           {
-             /* This is pre or post decrement.  */
-             rhs = TREE_OPERAND (lhs, 1);
-             lhs = TREE_OPERAND (lhs, 0);
-             opcode = NOP_EXPR;
-             if (code == OMP_ATOMIC_CAPTURE_NEW
-                 && !structured_block
-                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
-               code = OMP_ATOMIC_CAPTURE_OLD;
-             break;
-           }
+         c_parser_consume_pragma (parser);
+         c_parser_skip_to_pragma_eol (parser);
+         error_suppress = false;
        }
-      /* FALLTHRU */
-    default:
-      switch (c_parser_peek_token (parser)->type)
+      else if (!error_suppress)
        {
-       case CPP_MULT_EQ:
-         opcode = MULT_EXPR;
-         break;
-       case CPP_DIV_EQ:
-         opcode = TRUNC_DIV_EXPR;
-         break;
-       case CPP_PLUS_EQ:
-         opcode = PLUS_EXPR;
-         break;
-       case CPP_MINUS_EQ:
-         opcode = MINUS_EXPR;
-         break;
-       case CPP_LSHIFT_EQ:
-         opcode = LSHIFT_EXPR;
-         break;
-       case CPP_RSHIFT_EQ:
-         opcode = RSHIFT_EXPR;
-         break;
-       case CPP_AND_EQ:
-         opcode = BIT_AND_EXPR;
-         break;
-       case CPP_OR_EQ:
-         opcode = BIT_IOR_EXPR;
-         break;
-       case CPP_XOR_EQ:
-         opcode = BIT_XOR_EXPR;
-         break;
-       case CPP_EQ:
-         if (structured_block || code == OMP_ATOMIC)
-           {
-             location_t aloc = c_parser_peek_token (parser)->location;
-             location_t rhs_loc;
-             enum c_parser_prec oprec = PREC_NONE;
-
-             c_parser_consume_token (parser);
-             rhs1 = c_parser_unary_expression (parser).value;
-             rhs1 = c_fully_fold (rhs1, false, NULL);
-             if (rhs1 == error_mark_node)
-               goto saw_error;
-             switch (c_parser_peek_token (parser)->type)
-               {
-               case CPP_SEMICOLON:
-                 if (code == OMP_ATOMIC_CAPTURE_NEW)
-                   {
-                     code = OMP_ATOMIC_CAPTURE_OLD;
-                     v = lhs;
-                     lhs = NULL_TREE;
-                     lhs1 = rhs1;
-                     rhs1 = NULL_TREE;
-                     c_parser_consume_token (parser);
-                     goto restart;
-                   }
-                 c_parser_error (parser,
-                                 "invalid form of %<#pragma omp atomic%>");
-                 goto saw_error;
-               case CPP_MULT:
-                 opcode = MULT_EXPR;
-                 oprec = PREC_MULT;
-                 break;
-               case CPP_DIV:
-                 opcode = TRUNC_DIV_EXPR;
-                 oprec = PREC_MULT;
-                 break;
-               case CPP_PLUS:
-                 opcode = PLUS_EXPR;
-                 oprec = PREC_ADD;
-                 break;
-               case CPP_MINUS:
-                 opcode = MINUS_EXPR;
-                 oprec = PREC_ADD;
-                 break;
-               case CPP_LSHIFT:
-                 opcode = LSHIFT_EXPR;
-                 oprec = PREC_SHIFT;
-                 break;
-               case CPP_RSHIFT:
-                 opcode = RSHIFT_EXPR;
-                 oprec = PREC_SHIFT;
-                 break;
-               case CPP_AND:
-                 opcode = BIT_AND_EXPR;
-                 oprec = PREC_BITAND;
-                 break;
-               case CPP_OR:
-                 opcode = BIT_IOR_EXPR;
-                 oprec = PREC_BITOR;
-                 break;
-               case CPP_XOR:
-                 opcode = BIT_XOR_EXPR;
-                 oprec = PREC_BITXOR;
-                 break;
-               default:
-                 c_parser_error (parser,
-                                 "invalid operator for %<#pragma omp atomic%>");
-                 goto saw_error;
-               }
-             loc = aloc;
-             c_parser_consume_token (parser);
-             rhs_loc = c_parser_peek_token (parser)->location;
-             if (commutative_tree_code (opcode))
-               oprec = (enum c_parser_prec) (oprec - 1);
-             rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
-             rhs_expr = default_function_array_read_conversion (rhs_loc,
-                                                                rhs_expr);
-             rhs = rhs_expr.value;
-             rhs = c_fully_fold (rhs, false, NULL);
-             goto stmt_done; 
-           }
-         /* FALLTHROUGH */
-       default:
-         c_parser_error (parser,
-                         "invalid operator for %<#pragma omp atomic%>");
-         goto saw_error;
+         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
+         error_suppress = true;
        }
 
-      /* Arrange to pass the location of the assignment operator to
-        c_finish_omp_atomic.  */
-      loc = c_parser_peek_token (parser)->location;
-      c_parser_consume_token (parser);
-      {
-       location_t rhs_loc = c_parser_peek_token (parser)->location;
-       rhs_expr = c_parser_expression (parser);
-       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
-      }
-      rhs = rhs_expr.value;
-      rhs = c_fully_fold (rhs, false, NULL);
-      break;
-    }
-stmt_done:
-  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
-    {
-      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-       goto saw_error;
-      v = c_parser_unary_expression (parser).value;
-      v = c_fully_fold (v, false, NULL);
-      if (v == error_mark_node)
-       goto saw_error;
-      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-       goto saw_error;
-      lhs1 = c_parser_unary_expression (parser).value;
-      lhs1 = c_fully_fold (lhs1, false, NULL);
-      if (lhs1 == error_mark_node)
-       goto saw_error;
-    }
-  if (structured_block)
-    {
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+      substmt = c_parser_omp_structured_block (parser);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      SET_EXPR_LOCATION (substmt, loc);
+      add_stmt (substmt);
     }
-done:
-  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
-  if (stmt != error_mark_node)
-    add_stmt (stmt);
+  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+                            "expected %<#pragma omp section%> or %<}%>");
 
-  if (!structured_block)
-    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
+  substmt = pop_stmt_list (stmt);
+
+  stmt = make_node (OMP_SECTIONS);
+  SET_EXPR_LOCATION (stmt, sections_loc);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_SECTIONS_BODY (stmt) = substmt;
 
+  return add_stmt (stmt);
+}
 
 /* OpenMP 2.5:
-   # pragma omp barrier new-line
+   # pragma omp sections sections-clause[optseq] newline
+     sections-scope
+
+   LOC is the location of the #pragma token.
 */
 
-static void
-c_parser_omp_barrier (c_parser *parser)
+#define OMP_SECTIONS_CLAUSE_MASK                               \
+       ( (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_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_sections (location_t loc, c_parser *parser,
+                      char *p_name, omp_clause_mask mask, tree *cclauses)
 {
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
+  tree block, clauses, ret;
 
-  c_finish_omp_barrier (loc);
+  strcat (p_name, " sections");
+  mask |= OMP_SECTIONS_CLAUSE_MASK;
+  if (cclauses)
+    mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+  if (cclauses)
+    {
+      omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+    }
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_sections_scope (loc, parser);
+  if (ret)
+    OMP_SECTIONS_CLAUSES (ret) = clauses;
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+
+  return ret;
 }
 
 /* OpenMP 2.5:
-   # pragma omp critical [(name)] new-line
-     structured-block
+   # pragma parallel parallel-clause new-line
+   # pragma parallel for parallel-for-clause new-line
+   # pragma parallel sections parallel-sections-clause new-line
 
-  LOC is the location of the #pragma itself.  */
+   LOC is the location of the #pragma token.
+*/
+
+#define OMP_PARALLEL_CLAUSE_MASK                               \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)      \
+       | (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_PROC_BIND))
 
 static tree
-c_parser_omp_critical (location_t loc, c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser,
+                      char *p_name, omp_clause_mask mask, tree *cclauses)
 {
-  tree stmt, name = NULL;
+  tree stmt, clauses, block;
 
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+  strcat (p_name, " parallel");
+  mask |= OMP_PARALLEL_CLAUSE_MASK;
+
+  if (c_parser_next_token_is_keyword (parser, RID_FOR))
     {
+      tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+      if (cclauses == NULL)
+       cclauses = cclauses_buf;
+
       c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_NAME))
+      if (!flag_openmp)  /* flag_openmp_simd  */
+       return c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+      block = c_begin_omp_parallel ();
+      c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+      stmt
+       = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+                                block);
+      OMP_PARALLEL_COMBINED (stmt) = 1;
+      return stmt;
+    }
+  else if (cclauses)
+    {
+      error_at (loc, "expected %<for%> after %qs", p_name);
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
+  else if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "sections") == 0)
        {
-         name = c_parser_peek_token (parser)->value;
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
+
          c_parser_consume_token (parser);
-         c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+         block = c_begin_omp_parallel ();
+         c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
+         stmt = c_finish_omp_parallel (loc,
+                                       cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+                                       block);
+         OMP_PARALLEL_COMBINED (stmt) = 1;
+         return stmt;
        }
-      else
-       c_parser_error (parser, "expected identifier");
     }
-  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    c_parser_error (parser, "expected %<(%> or end of line");
-  c_parser_skip_to_pragma_eol (parser);
 
-  stmt = c_parser_omp_structured_block (parser);
-  return c_finish_omp_critical (loc, stmt, name);
-}
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
 
-/* OpenMP 2.5:
-   # pragma omp flush flush-vars[opt] new-line
+  block = c_begin_omp_parallel ();
+  c_parser_statement (parser);
+  stmt = c_finish_omp_parallel (loc, clauses, block);
 
-   flush-vars:
-     ( variable-list ) */
+  return stmt;
+}
 
-static void
-c_parser_omp_flush (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
-  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    c_parser_error (parser, "expected %<(%> or end of line");
-  c_parser_skip_to_pragma_eol (parser);
+/* OpenMP 2.5:
+   # pragma omp single single-clause[optseq] new-line
+     structured-block
 
-  c_finish_omp_flush (loc);
-}
+   LOC is the location of the #pragma.
+*/
 
-/* Parse the restricted form of the for statement allowed by OpenMP.
-   The real trick here is to determine the loop control variable early
-   so that we can push a new decl if necessary to make it private.
-   LOC is the location of the OMP in "#pragma omp".  */
+#define OMP_SINGLE_CLAUSE_MASK                                 \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE)  \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_for_loop (location_t loc,
-                      c_parser *parser, tree clauses, tree *par_clauses)
+c_parser_omp_single (location_t loc, c_parser *parser)
 {
-  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
-  tree declv, condv, incrv, initv, ret = NULL;
-  bool fail = false, open_brace_parsed = false;
-  int i, collapse = 1, nbraces = 0;
-  location_t for_loc;
-  vec<tree, va_gc> *for_block = make_tree_vector ();
+  tree stmt = make_node (OMP_SINGLE);
+  SET_EXPR_LOCATION (stmt, loc);
+  TREE_TYPE (stmt) = void_type_node;
 
-  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
-    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
-      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+  OMP_SINGLE_CLAUSES (stmt)
+    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
+                               "#pragma omp single");
+  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
 
-  gcc_assert (collapse >= 1);
+  return add_stmt (stmt);
+}
 
-  declv = make_tree_vec (collapse);
-  initv = make_tree_vec (collapse);
-  condv = make_tree_vec (collapse);
-  incrv = make_tree_vec (collapse);
+/* OpenMP 3.0:
+   # pragma omp task task-clause[optseq] new-line
 
-  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
-    {
-      c_parser_error (parser, "for statement expected");
-      return NULL;
-    }
-  for_loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_token (parser);
+   LOC is the location of the #pragma.
+*/
 
-  for (i = 0; i < collapse; i++)
-    {
-      int bracecount = 0;
+#define OMP_TASK_CLAUSE_MASK                                   \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (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_DEPEND))
 
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       goto pop_scopes;
+static tree
+c_parser_omp_task (location_t loc, c_parser *parser)
+{
+  tree clauses, block;
 
-      /* Parse the initialization declaration or expression.  */
-      if (c_parser_next_tokens_start_declaration (parser))
-       {
-         if (i > 0)
-           vec_safe_push (for_block, c_begin_compound_stmt (true));
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
-         decl = check_for_loop_decls (for_loc, flag_isoc99);
-         if (decl == NULL)
-           goto error_init;
-         if (DECL_INITIAL (decl) == error_mark_node)
-           decl = error_mark_node;
-         init = decl;
-       }
-      else if (c_parser_next_token_is (parser, CPP_NAME)
-              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
-       {
-         struct c_expr decl_exp;
-         struct c_expr init_exp;
-         location_t init_loc;
+  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                     "#pragma omp task");
 
-         decl_exp = c_parser_postfix_expression (parser);
-         decl = decl_exp.value;
+  block = c_begin_omp_task ();
+  c_parser_statement (parser);
+  return c_finish_omp_task (loc, clauses, block);
+}
 
-         c_parser_require (parser, CPP_EQ, "expected %<=%>");
+/* OpenMP 3.0:
+   # pragma omp taskwait new-line
+*/
 
-         init_loc = c_parser_peek_token (parser)->location;
-         init_exp = c_parser_expr_no_commas (parser, NULL);
-         init_exp = default_function_array_read_conversion (init_loc,
-                                                            init_exp);
-         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
-                                   NOP_EXPR, init_loc, init_exp.value,
-                                   init_exp.original_type);
-         init = c_process_expr_stmt (init_loc, init);
+static void
+c_parser_omp_taskwait (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
 
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-       }
-      else
-       {
-       error_init:
-         c_parser_error (parser,
-                         "expected iteration declaration or initialization");
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         fail = true;
-         goto parse_next;
-       }
+  c_finish_omp_taskwait (loc);
+}
 
-      /* Parse the loop condition.  */
-      cond = NULL_TREE;
-      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
-       {
-         location_t cond_loc = c_parser_peek_token (parser)->location;
-         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
-                                                               PREC_NONE);
+/* OpenMP 3.1:
+   # pragma omp taskyield new-line
+*/
 
-         cond = cond_expr.value;
-         cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
-         cond = c_fully_fold (cond, false, NULL);
-         switch (cond_expr.original_code)
-           {
-           case GT_EXPR:
-           case GE_EXPR:
-           case LT_EXPR:
-           case LE_EXPR:
-             break;
-           default:
-             /* Can't be cond = error_mark_node, because we want to preserve
-                the location until c_finish_omp_for.  */
-             cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
-             break;
-           }
-         protected_set_expr_location (cond, cond_loc);
-       }
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+static void
+c_parser_omp_taskyield (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
 
-      /* Parse the increment expression.  */
-      incr = NULL_TREE;
-      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
-       {
-         location_t incr_loc = c_parser_peek_token (parser)->location;
+  c_finish_omp_taskyield (loc);
+}
 
-         incr = c_process_expr_stmt (incr_loc,
-                                     c_parser_expression (parser).value);
-       }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+/* OpenMP 4.0:
+   # pragma omp taskgroup new-line
+*/
 
-      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
-       fail = true;
-      else
-       {
-         TREE_VEC_ELT (declv, i) = decl;
-         TREE_VEC_ELT (initv, i) = init;
-         TREE_VEC_ELT (condv, i) = cond;
-         TREE_VEC_ELT (incrv, i) = incr;
-       }
+static tree
+c_parser_omp_taskgroup (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser));
+}
 
-    parse_next:
-      if (i == collapse - 1)
-       break;
+/* OpenMP 4.0:
+   # pragma omp cancel cancel-clause[optseq] new-line
 
-      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
-        in between the collapsed for loops to be still considered perfectly
-        nested.  Hopefully the final version clarifies this.
-        For now handle (multiple) {'s and empty statements.  */
-      do
-       {
-         if (c_parser_next_token_is_keyword (parser, RID_FOR))
-           {
-             c_parser_consume_token (parser);
-             break;
-           }
-         else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-           {
-             c_parser_consume_token (parser);
-             bracecount++;
-           }
-         else if (bracecount
-                  && c_parser_next_token_is (parser, CPP_SEMICOLON))
-           c_parser_consume_token (parser);
-         else
-           {
-             c_parser_error (parser, "not enough perfectly nested loops");
-             if (bracecount)
-               {
-                 open_brace_parsed = true;
-                 bracecount--;
-               }
-             fail = true;
-             collapse = 0;
-             break;
-           }
-       }
-      while (1);
+   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))
 
-      nbraces += bracecount;
-    }
+static void
+c_parser_omp_cancel (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
 
-  save_break = c_break_label;
-  c_break_label = size_one_node;
-  save_cont = c_cont_label;
-  c_cont_label = NULL_TREE;
-  body = push_stmt_list ();
+  c_parser_consume_pragma (parser);
+  tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
+                                          "#pragma omp cancel");
 
-  if (open_brace_parsed)
+  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))
     {
-      location_t here = c_parser_peek_token (parser)->location;
-      stmt = c_begin_compound_stmt (true);
-      c_parser_compound_statement_nostart (parser);
-      add_stmt (c_end_compound_stmt (here, stmt, true));
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "point") == 0)
+       {
+         c_parser_consume_token (parser);
+         point_seen = true;
+       }
     }
-  else
-    add_stmt (c_parser_c99_block_statement (parser));
-  if (c_cont_label)
+  if (!point_seen)
     {
-      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
-      SET_EXPR_LOCATION (t, loc);
-      add_stmt (t);
+      c_parser_error (parser, "expected %<point%>");
+      c_parser_skip_to_pragma_eol (parser);
+      return;
     }
 
-  body = pop_stmt_list (body);
-  c_break_label = save_break;
-  c_cont_label = save_cont;
+  clauses
+    = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
+                               "#pragma omp cancellation point");
 
-  while (nbraces)
+  c_finish_omp_cancellation_point (loc, clauses);
+}
+
+/* OpenMP 4.0:
+   #pragma omp distribute distribute-clause[optseq] new-line
+     for-loop  */
+
+#define OMP_DISTRIBUTE_CLAUSE_MASK                             \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+c_parser_omp_distribute (location_t loc, c_parser *parser,
+                        char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+  tree clauses, block, ret;
+
+  strcat (p_name, " distribute");
+  mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
     {
-      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-       {
-         c_parser_consume_token (parser);
-         nbraces--;
-       }
-      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-       c_parser_consume_token (parser);
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      bool simd = false;
+      bool parallel = false;
+
+      if (strcmp (p, "simd") == 0)
+       simd = true;
       else
+       parallel = strcmp (p, "parallel") == 0;
+      if (parallel || simd)
        {
-         c_parser_error (parser, "collapsed loops not perfectly nested");
-         while (nbraces)
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
+         c_parser_consume_token (parser);
+         if (!flag_openmp)  /* flag_openmp_simd  */
            {
-             location_t here = c_parser_peek_token (parser)->location;
-             stmt = c_begin_compound_stmt (true);
-             add_stmt (body);
-             c_parser_compound_statement_nostart (parser);
-             body = c_end_compound_stmt (here, stmt, true);
-             nbraces--;
+             if (simd)
+               return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+             else
+               return c_parser_omp_parallel (loc, parser, p_name, mask,
+                                             cclauses);
            }
-         goto pop_scopes;
+         block = c_begin_compound_stmt (true);
+         if (simd)
+           ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+         else
+           ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses);
+         block = c_end_compound_stmt (loc, block, true);
+         if (ret == NULL)
+           return ret;
+         ret = make_node (OMP_DISTRIBUTE);
+         TREE_TYPE (ret) = void_type_node;
+         OMP_FOR_BODY (ret) = block;
+         OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+         SET_EXPR_LOCATION (ret, loc);
+         add_stmt (ret);
+         return ret;
        }
     }
-
-  /* Only bother calling c_finish_omp_for if we haven't already generated
-     an error from the initialization parsing.  */
-  if (!fail)
+  if (!flag_openmp)  /* flag_openmp_simd  */
     {
-      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
-      if (stmt)
-       {
-         if (par_clauses != NULL)
-           {
-             tree *c;
-             for (c = par_clauses; *c ; )
-               if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
-                   && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
-                 c = &OMP_CLAUSE_CHAIN (*c);
-               else
-                 {
-                   for (i = 0; i < collapse; i++)
-                     if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
-                       break;
-                   if (i == collapse)
-                     c = &OMP_CLAUSE_CHAIN (*c);
-                   else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
-                     {
-                       error_at (loc,
-                                 "iteration variable %qD should not be firstprivate",
-                                 OMP_CLAUSE_DECL (*c));
-                       *c = OMP_CLAUSE_CHAIN (*c);
-                     }
-                   else
-                     {
-                       /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
-                          change it to shared (decl) in
-                          OMP_PARALLEL_CLAUSES.  */
-                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
-                                                  OMP_CLAUSE_LASTPRIVATE);
-                       OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
-                       OMP_CLAUSE_CHAIN (l) = clauses;
-                       clauses = l;
-                       OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
-                     }
-                 }
-           }
-         OMP_FOR_CLAUSES (stmt) = clauses;
-       }
-      ret = stmt;
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
     }
-pop_scopes:
-  while (!for_block->is_empty ())
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+  if (cclauses)
     {
-      /* FIXME diagnostics: LOC below should be the actual location of
-        this particular for block.  We need to build a list of
-        locations to go along with FOR_BLOCK.  */
-      stmt = c_end_compound_stmt (loc, for_block->pop (), true);
-      add_stmt (stmt);
+      omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
     }
-  release_tree_vector (for_block);
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, 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
-
-   LOC is the location of the #pragma token.
-*/
+/* OpenMP 4.0:
+   # pragma omp teams teams-clause[optseq] new-line
+     structured-block  */
 
-#define OMP_FOR_CLAUSE_MASK                            \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
-       | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_TEAMS_CLAUSE_MASK                                  \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
 
 static tree
-c_parser_omp_for (location_t loc, c_parser *parser)
+c_parser_omp_teams (location_t loc, c_parser *parser,
+                   char *p_name, omp_clause_mask mask, tree *cclauses)
 {
-  tree block, clauses, ret;
+  tree clauses, block, ret;
 
-  clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
-                                     "#pragma omp for");
+  strcat (p_name, " teams");
+  mask |= OMP_TEAMS_CLAUSE_MASK;
 
-  block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
-  block = c_end_compound_stmt (loc, block, true);
-  add_stmt (block);
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "distribute") == 0)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
 
-  return ret;
+         c_parser_consume_token (parser);
+         if (!flag_openmp)  /* flag_openmp_simd  */
+           return c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+         block = c_begin_compound_stmt (true);
+         ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+         block = c_end_compound_stmt (loc, block, true);
+         if (ret == NULL)
+           return ret;
+         clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+         ret = make_node (OMP_TEAMS);
+         TREE_TYPE (ret) = void_type_node;
+         OMP_TEAMS_CLAUSES (ret) = clauses;
+         OMP_TEAMS_BODY (ret) = block;
+         return add_stmt (ret);
+       }
+    }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      c_parser_skip_to_pragma_eol (parser);
+      return NULL_TREE;
+    }
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+  if (cclauses)
+    {
+      omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+    }
+
+  tree stmt = make_node (OMP_TEAMS);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TEAMS_CLAUSES (stmt) = clauses;
+  OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+  return add_stmt (stmt);
 }
 
-/* OpenMP 2.5:
-   # pragma omp master new-line
-     structured-block
+/* OpenMP 4.0:
+   # pragma omp target data target-data-clause[optseq] new-line
+     structured-block  */
 
-   LOC is the location of the #pragma token.
-*/
+#define OMP_TARGET_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))
 
 static tree
-c_parser_omp_master (location_t loc, c_parser *parser)
+c_parser_omp_target_data (location_t loc, c_parser *parser)
 {
-  c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
+  tree stmt = make_node (OMP_TARGET_DATA);
+  TREE_TYPE (stmt) = void_type_node;
+
+  OMP_TARGET_DATA_CLAUSES (stmt)
+    = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
+                               "#pragma omp target data");
+  keep_next_level ();
+  tree block = c_begin_compound_stmt (true);
+  add_stmt (c_parser_omp_structured_block (parser));
+  OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
+
+  SET_EXPR_LOCATION (stmt, loc);
+  return add_stmt (stmt);
 }
 
-/* OpenMP 2.5:
-   # pragma omp ordered new-line
-     structured-block
+/* OpenMP 4.0:
+   # pragma omp target update target-update-clause[optseq] new-line */
 
-   LOC is the location of the #pragma itself.
-*/
+#define OMP_TARGET_UPDATE_CLAUSE_MASK                          \
+       ( (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))
 
-static tree
-c_parser_omp_ordered (location_t loc, c_parser *parser)
+static bool
+c_parser_omp_target_update (location_t loc, c_parser *parser,
+                           enum pragma_context context)
 {
-  c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
-}
+  if (context == pragma_stmt)
+    {
+      error_at (loc,
+               "%<#pragma omp target update%> may only be "
+               "used in compound statements");
+      c_parser_skip_to_pragma_eol (parser);
+      return false;
+    }
 
-/* OpenMP 2.5:
+  tree clauses
+    = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
+                               "#pragma omp target update");
+  if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+      && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+    {
+      error_at (loc,
+               "%<#pragma omp target update must contain at least one "
+               "%<from%> or %<to%> clauses");
+      return false;
+    }
 
-   section-scope:
-     { section-sequence }
+  tree stmt = make_node (OMP_TARGET_UPDATE);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
+  SET_EXPR_LOCATION (stmt, loc);
+  add_stmt (stmt);
+  return false;
+}
 
-   section-sequence:
-     section-directive[opt] structured-block
-     section-sequence section-directive structured-block
+/* OpenMP 4.0:
+   # pragma omp target target-clause[optseq] new-line
+     structured-block  */
 
-    SECTIONS_LOC is the location of the #pragma omp sections.  */
+#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))
 
-static tree
-c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
+static bool
+c_parser_omp_target (c_parser *parser, enum pragma_context context)
 {
-  tree stmt, substmt;
-  bool error_suppress = false;
-  location_t loc;
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
 
-  loc = c_parser_peek_token (parser)->location;
-  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+  if (context != pragma_stmt && context != pragma_compound)
     {
-      /* Avoid skipping until the end of the block.  */
-      parser->error = false;
-      return NULL_TREE;
+      c_parser_error (parser, "expected declaration specifiers");
+      c_parser_skip_to_pragma_eol (parser);
+      return false;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      if (strcmp (p, "teams") == 0)
+       {
+         tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+         char p_name[sizeof ("#pragma omp target teams distribute "
+                             "parallel for simd")];
+
+         c_parser_consume_token (parser);
+         if (!flag_openmp)  /* flag_openmp_simd  */
+           return c_parser_omp_teams (loc, parser, p_name,
+                                      OMP_TARGET_CLAUSE_MASK, cclauses);
+         strcpy (p_name, "#pragma omp target");
+         keep_next_level ();
+         tree block = c_begin_compound_stmt (true);
+         tree ret = c_parser_omp_teams (loc, parser, p_name,
+                                        OMP_TARGET_CLAUSE_MASK, cclauses);
+         block = c_end_compound_stmt (loc, block, true);
+         if (ret == NULL)
+           return ret;
+         tree stmt = make_node (OMP_TARGET);
+         TREE_TYPE (stmt) = void_type_node;
+         OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+         OMP_TARGET_BODY (stmt) = block;
+         add_stmt (stmt);
+         return true;
+       }
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+       {
+         c_parser_skip_to_pragma_eol (parser);
+         return NULL_TREE;
+       }
+      else if (strcmp (p, "data") == 0)
+       {
+         c_parser_consume_token (parser);
+         c_parser_omp_target_data (loc, parser);
+         return true;
+       }
+      else if (strcmp (p, "update") == 0)
+       {
+         c_parser_consume_token (parser);
+         return c_parser_omp_target_update (loc, parser, context);
+       }
+    }
+
+  tree stmt = make_node (OMP_TARGET);
+  TREE_TYPE (stmt) = void_type_node;
+
+  OMP_TARGET_CLAUSES (stmt)
+    = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+                               "#pragma omp target");
+  keep_next_level ();
+  tree block = c_begin_compound_stmt (true);
+  add_stmt (c_parser_omp_structured_block (parser));
+  OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
+
+  SET_EXPR_LOCATION (stmt, loc);
+  add_stmt (stmt);
+  return true;
+}
+
+/* OpenMP 4.0:
+   # pragma omp declare simd declare-simd-clauses[optseq] new-line  */
+
+#define OMP_DECLARE_SIMD_CLAUSE_MASK                           \
+       ( (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_UNIFORM)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
+
+static void
+c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
+{
+  vec<c_token> clauses = vNULL;
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (token->type == CPP_EOF)
+       {
+         c_parser_skip_to_pragma_eol (parser);
+         clauses.release ();
+         return;
+       }
+      clauses.safe_push (*token);
+      c_parser_consume_token (parser);
     }
+  clauses.safe_push (*c_parser_peek_token (parser));
+  c_parser_skip_to_pragma_eol (parser);
 
-  stmt = push_stmt_list ();
-
-  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
+  while (c_parser_next_token_is (parser, CPP_PRAGMA))
     {
-      substmt = push_stmt_list ();
-
-      while (1)
+      if (c_parser_peek_token (parser)->pragma_kind
+         != PRAGMA_OMP_DECLARE_REDUCTION
+         || c_parser_peek_2nd_token (parser)->type != CPP_NAME
+         || strcmp (IDENTIFIER_POINTER
+                               (c_parser_peek_2nd_token (parser)->value),
+                    "simd") != 0)
        {
-          c_parser_statement (parser);
-
-         if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
-           break;
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           break;
-         if (c_parser_next_token_is (parser, CPP_EOF))
-           break;
+         c_parser_error (parser,
+                         "%<#pragma omp declare simd%> must be followed by "
+                         "function declaration or definition or another "
+                         "%<#pragma omp declare simd%>");
+         clauses.release ();
+         return;
        }
-
-      substmt = pop_stmt_list (substmt);
-      substmt = build1 (OMP_SECTION, void_type_node, substmt);
-      SET_EXPR_LOCATION (substmt, loc);
-      add_stmt (substmt);
+      c_parser_consume_pragma (parser);
+      while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+       {
+         c_token *token = c_parser_peek_token (parser);
+         if (token->type == CPP_EOF)
+           {
+             c_parser_skip_to_pragma_eol (parser);
+             clauses.release ();
+             return;
+           }
+         clauses.safe_push (*token);
+         c_parser_consume_token (parser);
+       }
+      clauses.safe_push (*c_parser_peek_token (parser));
+      c_parser_skip_to_pragma_eol (parser);
     }
 
-  while (1)
-    {
-      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-       break;
-      if (c_parser_next_token_is (parser, CPP_EOF))
-       break;
+  /* Make sure nothing tries to read past the end of the tokens.  */
+  c_token eof_token;
+  memset (&eof_token, 0, sizeof (eof_token));
+  eof_token.type = CPP_EOF;
+  clauses.safe_push (eof_token);
+  clauses.safe_push (eof_token);
 
-      loc = c_parser_peek_token (parser)->location;
-      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
+  switch (context)
+    {
+    case pragma_external:
+      if (c_parser_next_token_is (parser, CPP_KEYWORD)
+         && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
        {
-         c_parser_consume_pragma (parser);
-         c_parser_skip_to_pragma_eol (parser);
-         error_suppress = false;
+         int ext = disable_extension_diagnostics ();
+         do
+           c_parser_consume_token (parser);
+         while (c_parser_next_token_is (parser, CPP_KEYWORD)
+                && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+         c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+                                        NULL, clauses);
+         restore_extension_diagnostics (ext);
        }
-      else if (!error_suppress)
+      else
+       c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+                                      NULL, clauses);
+      break;
+    case pragma_struct:
+    case pragma_param:
+      c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by "
+                             "function declaration or definition");
+      break;
+    case pragma_compound:
+    case pragma_stmt:
+      if (c_parser_next_token_is (parser, CPP_KEYWORD)
+         && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
        {
-         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
-         error_suppress = true;
+         int ext = disable_extension_diagnostics ();
+         do
+           c_parser_consume_token (parser);
+         while (c_parser_next_token_is (parser, CPP_KEYWORD)
+                && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+         if (c_parser_next_tokens_start_declaration (parser))
+           {
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true, NULL, clauses);
+             restore_extension_diagnostics (ext);
+             break;
+           }
+         restore_extension_diagnostics (ext);
        }
-
-      substmt = c_parser_omp_structured_block (parser);
-      substmt = build1 (OMP_SECTION, void_type_node, substmt);
-      SET_EXPR_LOCATION (substmt, loc);
-      add_stmt (substmt);
+      else if (c_parser_next_tokens_start_declaration (parser))
+       {
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true,
+                                        NULL, clauses);
+         break;
+       }
+      c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by "
+                             "function declaration or definition");
+      break;
+    default:
+      gcc_unreachable ();
     }
-  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
-                            "expected %<#pragma omp section%> or %<}%>");
-
-  substmt = pop_stmt_list (stmt);
-
-  stmt = make_node (OMP_SECTIONS);
-  SET_EXPR_LOCATION (stmt, sections_loc);
-  TREE_TYPE (stmt) = void_type_node;
-  OMP_SECTIONS_BODY (stmt) = substmt;
-
-  return add_stmt (stmt);
+  clauses.release ();
 }
 
-/* OpenMP 2.5:
-   # pragma omp sections sections-clause[optseq] newline
-     sections-scope
+/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
+   and put that into "omp declare simd" attribute.  */
 
-   LOC is the location of the #pragma token.
-*/
+static void
+c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
+                          vec<c_token> clauses)
+{
+  /* Normally first token is CPP_NAME "simd".  CPP_EOF there indicates
+     error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd
+     has already processed the tokens.  */
+  if (clauses[0].type == CPP_EOF)
+    return;
+  if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
+    {
+      error ("%<#pragma omp declare simd%> not immediately followed by "
+            "a function declaration or definition");
+      clauses[0].type = CPP_EOF;
+      return;
+    }
+  if (clauses[0].type != CPP_NAME)
+    {
+      error_at (DECL_SOURCE_LOCATION (fndecl),
+               "%<#pragma omp declare simd%> not immediately followed by "
+               "a single function declaration or definition");
+      clauses[0].type = CPP_EOF;
+      return;
+    }
 
-#define OMP_SECTIONS_CLAUSE_MASK                       \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+  if (parms == NULL_TREE)
+    parms = DECL_ARGUMENTS (fndecl);
 
-static tree
-c_parser_omp_sections (location_t loc, c_parser *parser)
-{
-  tree block, clauses, ret;
+  unsigned int tokens_avail = parser->tokens_avail;
+  gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+  parser->tokens = clauses.address ();
+  parser->tokens_avail = clauses.length ();
 
-  clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
-                                     "#pragma omp sections");
+  /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end.  */
+  while (parser->tokens_avail > 3)
+    {
+      c_token *token = c_parser_peek_token (parser);
+      gcc_assert (token->type == CPP_NAME
+                 && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
+      c_parser_consume_token (parser);
+      parser->in_pragma = true;
 
-  block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_sections_scope (loc, parser);
-  if (ret)
-    OMP_SECTIONS_CLAUSES (ret) = clauses;
-  block = c_end_compound_stmt (loc, block, true);
-  add_stmt (block);
+      tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+                                        "#pragma omp declare simd");
+      c = c_omp_declare_simd_clauses_to_numbers (parms, c);
+      if (c != NULL_TREE)
+       c = tree_cons (NULL_TREE, c, NULL_TREE);
+      c = build_tree_list (get_identifier ("omp declare simd"), c);
+      TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
+      DECL_ATTRIBUTES (fndecl) = c;
+    }
 
-  return ret;
+  parser->tokens = &parser->tokens_buf[0];
+  parser->tokens_avail = tokens_avail;
+  clauses[0].type = CPP_PRAGMA;
 }
 
-/* OpenMP 2.5:
-   # pragma parallel parallel-clause new-line
-   # pragma parallel for parallel-for-clause new-line
-   # pragma parallel sections parallel-sections-clause new-line
 
-   LOC is the location of the #pragma token.
-*/
+/* OpenMP 4.0:
+   # pragma omp declare target new-line
+   declarations and definitions
+   # pragma omp end declare target new-line  */
 
-#define OMP_PARALLEL_CLAUSE_MASK                       \
-       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
-       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
-
-static tree
-c_parser_omp_parallel (location_t loc, c_parser *parser)
+static void
+c_parser_omp_declare_target (c_parser *parser)
 {
-  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
-  const char *p_name = "#pragma omp parallel";
-  tree stmt, clauses, par_clause, ws_clause, block;
-  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+  c_parser_skip_to_pragma_eol (parser);
+  current_omp_declare_target_attribute++;
+}
 
-  if (c_parser_next_token_is_keyword (parser, RID_FOR))
+static void
+c_parser_omp_end_declare_target (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  if (c_parser_next_token_is (parser, CPP_NAME)
+      && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+                "declare") == 0)
     {
       c_parser_consume_token (parser);
-      p_kind = PRAGMA_OMP_PARALLEL_FOR;
-      p_name = "#pragma omp parallel for";
-      mask |= OMP_FOR_CLAUSE_MASK;
-      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
-    }
-  else if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-      if (strcmp (p, "sections") == 0)
+      if (c_parser_next_token_is (parser, CPP_NAME)
+         && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+                    "target") == 0)
+       c_parser_consume_token (parser);
+      else
        {
-         c_parser_consume_token (parser);
-         p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
-         p_name = "#pragma omp parallel sections";
-         mask |= OMP_SECTIONS_CLAUSE_MASK;
-         mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+         c_parser_error (parser, "expected %<target%>");
+         c_parser_skip_to_pragma_eol (parser);
+         return;
        }
     }
+  else
+    {
+      c_parser_error (parser, "expected %<declare%>");
+      c_parser_skip_to_pragma_eol (parser);
+      return;
+    }
+  c_parser_skip_to_pragma_eol (parser);
+  if (!current_omp_declare_target_attribute)
+    error_at (loc, "%<#pragma omp end declare target%> without corresponding "
+                  "%<#pragma omp declare target%>");
+  else
+    current_omp_declare_target_attribute--;
+}
 
-  clauses = c_parser_omp_all_clauses (parser, mask, p_name);
 
-  switch (p_kind)
+/* OpenMP 4.0
+   #pragma omp declare reduction (reduction-id : typename-list : expression) \
+      initializer-clause[opt] new-line
+
+   initializer-clause:
+      initializer (omp_priv = initializer)
+      initializer (function-name (argument-list))  */
+
+static void
+c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
+{
+  unsigned int tokens_avail = 0, i;
+  vec<tree> types = vNULL;
+  vec<c_token> clauses = vNULL;
+  enum tree_code reduc_code = ERROR_MARK;
+  tree reduc_id = NULL_TREE;
+  tree type;
+  location_t rloc = c_parser_peek_token (parser)->location;
+
+  if (context == pragma_struct || context == pragma_param)
     {
-    case PRAGMA_OMP_PARALLEL:
-      block = c_begin_omp_parallel ();
-      c_parser_statement (parser);
-      stmt = c_finish_omp_parallel (loc, clauses, block);
-      break;
+      error ("%<#pragma omp declare reduction%> not at file or block scope");
+      goto fail;
+    }
 
-    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);
-      stmt = c_finish_omp_parallel (loc, par_clause, block);
-      OMP_PARALLEL_COMBINED (stmt) = 1;
-      break;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    goto fail;
 
-    case PRAGMA_OMP_PARALLEL_SECTIONS:
-      block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
-      stmt = c_parser_omp_sections_scope (loc, parser);
-      if (stmt)
-       OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
-      stmt = c_finish_omp_parallel (loc, par_clause, block);
-      OMP_PARALLEL_COMBINED (stmt) = 1;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_PLUS:
+      reduc_code = PLUS_EXPR;
+      break;
+    case CPP_MULT:
+      reduc_code = MULT_EXPR;
+      break;
+    case CPP_MINUS:
+      reduc_code = MINUS_EXPR;
+      break;
+    case CPP_AND:
+      reduc_code = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      reduc_code = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      reduc_code = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      reduc_code = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      reduc_code = TRUTH_ORIF_EXPR;
+      break;
+    case CPP_NAME:
+      const char *p;
+      p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "min") == 0)
+       {
+         reduc_code = MIN_EXPR;
+         break;
+       }
+      if (strcmp (p, "max") == 0)
+       {
+         reduc_code = MAX_EXPR;
+         break;
+       }
+      reduc_id = c_parser_peek_token (parser)->value;
       break;
-
     default:
-      gcc_unreachable ();
+      c_parser_error (parser,
+                     "expected %<+%>, %<*%>, %<-%>, %<&%>, "
+                     "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or identifier");
+      goto fail;
     }
 
-  return stmt;
-}
+  tree orig_reduc_id, reduc_decl;
+  orig_reduc_id = reduc_id;
+  reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
+  reduc_decl = c_omp_reduction_decl (reduc_id);
+  c_parser_consume_token (parser);
 
-/* OpenMP 2.5:
-   # pragma omp single single-clause[optseq] new-line
-     structured-block
+  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+    goto fail;
 
-   LOC is the location of the #pragma.
-*/
+  while (true)
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      struct c_type_name *ctype = c_parser_type_name (parser);
+      if (ctype != NULL)
+       {
+         type = groktypename (ctype, NULL, NULL);
+         if (type == error_mark_node)
+           ;
+         else if ((INTEGRAL_TYPE_P (type)
+                   || TREE_CODE (type) == REAL_TYPE
+                   || TREE_CODE (type) == COMPLEX_TYPE)
+                  && orig_reduc_id == NULL_TREE)
+           error_at (loc, "predeclared arithmetic type in "
+                          "%<#pragma omp declare reduction%>");
+         else if (TREE_CODE (type) == FUNCTION_TYPE
+                  || TREE_CODE (type) == ARRAY_TYPE)
+           error_at (loc, "function or array type in "
+                     "%<#pragma omp declare reduction%>");
+         else if (TYPE_QUALS_NO_ADDR_SPACE (type))
+           error_at (loc, "const, volatile or restrict qualified type in "
+                          "%<#pragma omp declare reduction%>");
+         else
+           {
+             tree t;
+             for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
+               if (comptypes (TREE_PURPOSE (t), type))
+                 {
+                   error_at (loc, "redeclaration of %qs "
+                                  "%<#pragma omp declare reduction%> for "
+                                  "type %qT",
+                                  IDENTIFIER_POINTER (reduc_id)
+                                  + sizeof ("omp declare reduction ") - 1,
+                                  type);
+                   location_t ploc
+                     = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
+                                                           0));
+                   error_at (ploc, "previous %<#pragma omp declare "
+                                   "reduction%>");
+                   break;
+                 }
+             if (t == NULL_TREE)
+               types.safe_push (type);
+           }
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+       }
+      else
+       break;
+    }
 
-#define OMP_SINGLE_CLAUSE_MASK                         \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
+      || types.is_empty ())
+    {
+     fail:
+      clauses.release ();
+      types.release ();
+      while (true)
+       {
+         c_token *token = c_parser_peek_token (parser);
+         if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
+           break;
+         c_parser_consume_token (parser);
+       }
+      c_parser_skip_to_pragma_eol (parser);
+      return;
+    }
 
-static tree
-c_parser_omp_single (location_t loc, c_parser *parser)
-{
-  tree stmt = make_node (OMP_SINGLE);
-  SET_EXPR_LOCATION (stmt, loc);
-  TREE_TYPE (stmt) = void_type_node;
+  if (types.length () > 1)
+    {
+      while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+       {
+         c_token *token = c_parser_peek_token (parser);
+         if (token->type == CPP_EOF)
+           goto fail;
+         clauses.safe_push (*token);
+         c_parser_consume_token (parser);
+       }
+      clauses.safe_push (*c_parser_peek_token (parser));
+      c_parser_skip_to_pragma_eol (parser);
 
-  OMP_SINGLE_CLAUSES (stmt)
-    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
-                               "#pragma omp single");
-  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
+      /* Make sure nothing tries to read past the end of the tokens.  */
+      c_token eof_token;
+      memset (&eof_token, 0, sizeof (eof_token));
+      eof_token.type = CPP_EOF;
+      clauses.safe_push (eof_token);
+      clauses.safe_push (eof_token);
+    }
 
-  return add_stmt (stmt);
-}
+  int errs = errorcount;
+  FOR_EACH_VEC_ELT (types, i, type)
+    {
+      tokens_avail = parser->tokens_avail;
+      gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+      if (!clauses.is_empty ())
+       {
+         parser->tokens = clauses.address ();
+         parser->tokens_avail = clauses.length ();
+         parser->in_pragma = true;
+       }
 
-/* OpenMP 3.0:
-   # pragma omp task task-clause[optseq] new-line
+      bool nested = current_function_decl != NULL_TREE;
+      if (nested)
+       c_push_function_context ();
+      tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+                               reduc_id, default_function_type);
+      current_function_decl = fndecl;
+      allocate_struct_function (fndecl, true);
+      push_scope ();
+      tree stmt = push_stmt_list ();
+      /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
+        warn about these.  */
+      tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
+                                get_identifier ("omp_out"), type);
+      DECL_ARTIFICIAL (omp_out) = 1;
+      DECL_CONTEXT (omp_out) = fndecl;
+      pushdecl (omp_out);
+      tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
+                               get_identifier ("omp_in"), type);
+      DECL_ARTIFICIAL (omp_in) = 1;
+      DECL_CONTEXT (omp_in) = fndecl;
+      pushdecl (omp_in);
+      struct c_expr combiner = c_parser_expression (parser);
+      struct c_expr initializer;
+      tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
+      bool bad = false;
+      initializer.value = error_mark_node;
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+       bad = true;
+      else if (c_parser_next_token_is (parser, CPP_NAME)
+              && strcmp (IDENTIFIER_POINTER
+                               (c_parser_peek_token (parser)->value),
+                         "initializer") == 0)
+       {
+         c_parser_consume_token (parser);
+         pop_scope ();
+         push_scope ();
+         omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
+                                get_identifier ("omp_priv"), type);
+         DECL_ARTIFICIAL (omp_priv) = 1;
+         DECL_INITIAL (omp_priv) = error_mark_node;
+         DECL_CONTEXT (omp_priv) = fndecl;
+         pushdecl (omp_priv);
+         omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
+                                get_identifier ("omp_orig"), type);
+         DECL_ARTIFICIAL (omp_orig) = 1;
+         DECL_CONTEXT (omp_orig) = fndecl;
+         pushdecl (omp_orig);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           bad = true;
+         else if (!c_parser_next_token_is (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected %<omp_priv%> or "
+                                     "function-name");
+             bad = true;
+           }
+         else if (strcmp (IDENTIFIER_POINTER
+                               (c_parser_peek_token (parser)->value),
+                          "omp_priv") != 0)
+           {
+             if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+                 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+               {
+                 c_parser_error (parser, "expected function-name %<(%>");
+                 bad = true;
+               }
+             else
+               initializer = c_parser_postfix_expression (parser);
+             if (initializer.value
+                 && TREE_CODE (initializer.value) == CALL_EXPR)
+               {
+                 int j;
+                 tree c = initializer.value;
+                 for (j = 0; j < call_expr_nargs (c); j++)
+                   if (TREE_CODE (CALL_EXPR_ARG (c, j)) == ADDR_EXPR
+                       && TREE_OPERAND (CALL_EXPR_ARG (c, j), 0) == omp_priv)
+                     break;
+                 if (j == call_expr_nargs (c))
+                   error ("one of the initializer call arguments should be "
+                          "%<&omp_priv%>");
+               }
+           }
+         else
+           {
+             c_parser_consume_token (parser);
+             if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+               bad = true;
+             else
+               {
+                 tree st = push_stmt_list ();
+                 start_init (omp_priv, NULL_TREE, 0);
+                 location_t loc = c_parser_peek_token (parser)->location;
+                 struct c_expr init = c_parser_initializer (parser);
+                 finish_init ();
+                 finish_decl (omp_priv, loc, init.value,
+                              init.original_type, NULL_TREE);
+                 pop_stmt_list (st);
+               }
+           }
+         if (!bad
+             && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+           bad = true;
+       }
 
-   LOC is the location of the #pragma.
-*/
+      if (!bad)
+       {
+         c_parser_skip_to_pragma_eol (parser);
 
-#define OMP_TASK_CLAUSE_MASK                           \
-       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
-       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
-       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
-       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+         tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
+                             DECL_INITIAL (reduc_decl));
+         DECL_INITIAL (reduc_decl) = t;
+         DECL_SOURCE_LOCATION (omp_out) = rloc;
+         TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
+         TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
+         TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
+         walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
+                    &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
+         if (omp_priv)
+           {
+             DECL_SOURCE_LOCATION (omp_priv) = rloc;
+             TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
+             TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
+             TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
+             walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
+                        &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
+             walk_tree (&DECL_INITIAL (omp_priv),
+                        c_check_omp_declare_reduction_r,
+                        &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
+           }
+       }
 
-static tree
-c_parser_omp_task (location_t loc, c_parser *parser)
-{
-  tree clauses, block;
+      pop_stmt_list (stmt);
+      pop_scope ();
+      if (cfun->language != NULL)
+       {
+         ggc_free (cfun->language);
+         cfun->language = NULL;
+       }
+      set_cfun (NULL);
+      current_function_decl = NULL_TREE;
+      if (nested)
+       c_pop_function_context ();
 
-  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
-                                     "#pragma omp task");
+      if (!clauses.is_empty ())
+       {
+         parser->tokens = &parser->tokens_buf[0];
+         parser->tokens_avail = tokens_avail;
+       }
+      if (bad)
+       goto fail;
+      if (errs != errorcount)
+       break;
+    }
 
-  block = c_begin_omp_task ();
-  c_parser_statement (parser);
-  return c_finish_omp_task (loc, clauses, block);
+  clauses.release ();
+  types.release ();
 }
 
-/* OpenMP 3.0:
-   # pragma omp taskwait new-line
-*/
-
-static void
-c_parser_omp_taskwait (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
-
-  c_finish_omp_taskwait (loc);
-}
 
-/* OpenMP 3.1:
-   # pragma omp taskyield new-line
-*/
+/* OpenMP 4.0
+   #pragma omp declare simd declare-simd-clauses[optseq] new-line
+   #pragma omp declare reduction (reduction-id : typename-list : expression) \
+      initializer-clause[opt] new-line
+   #pragma omp declare target new-line  */
 
 static void
-c_parser_omp_taskyield (c_parser *parser)
+c_parser_omp_declare (c_parser *parser, enum pragma_context context)
 {
-  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
+  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); done in
+            c_parser_omp_declare_simd.  */
+         c_parser_omp_declare_simd (parser, context);
+         return;
+       }
+      if (strcmp (p, "reduction") == 0)
+       {
+         c_parser_consume_token (parser);
+         c_parser_omp_declare_reduction (parser, context);
+         return;
+       }
+      if (!flag_openmp)  /* flag_openmp_simd  */
+       {
+         c_parser_skip_to_pragma_eol (parser);
+         return;
+       }
+      if (strcmp (p, "target") == 0)
+       {
+         c_parser_consume_token (parser);
+         c_parser_omp_declare_target (parser);
+         return;
+       }
+    }
 
-  c_finish_omp_taskyield (loc);
+  c_parser_error (parser, "expected %<simd%> or %<reduction%> "
+                         "or %<target%>");
+  c_parser_skip_to_pragma_eol (parser);
 }
 
 /* Main entry point to parsing most OpenMP pragmas.  */
@@ -10554,6 +13217,8 @@ c_parser_omp_construct (c_parser *parser)
   enum pragma_kind p_kind;
   location_t loc;
   tree stmt;
+  char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
+  omp_clause_mask mask (0);
 
   loc = c_parser_peek_token (parser)->location;
   p_kind = c_parser_peek_token (parser)->pragma_kind;
@@ -10567,8 +13232,13 @@ c_parser_omp_construct (c_parser *parser)
     case PRAGMA_OMP_CRITICAL:
       stmt = c_parser_omp_critical (loc, parser);
       break;
+    case PRAGMA_OMP_DISTRIBUTE:
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL);
+      break;
     case PRAGMA_OMP_FOR:
-      stmt = c_parser_omp_for (loc, parser);
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL);
       break;
     case PRAGMA_OMP_MASTER:
       stmt = c_parser_omp_master (loc, parser);
@@ -10577,10 +13247,16 @@ c_parser_omp_construct (c_parser *parser)
       stmt = c_parser_omp_ordered (loc, parser);
       break;
     case PRAGMA_OMP_PARALLEL:
-      stmt = c_parser_omp_parallel (loc, parser);
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL);
       break;
     case PRAGMA_OMP_SECTIONS:
-      stmt = c_parser_omp_sections (loc, parser);
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
+      break;
+    case PRAGMA_OMP_SIMD:
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL);
       break;
     case PRAGMA_OMP_SINGLE:
       stmt = c_parser_omp_single (loc, parser);
@@ -10588,6 +13264,13 @@ c_parser_omp_construct (c_parser *parser)
     case PRAGMA_OMP_TASK:
       stmt = c_parser_omp_task (loc, parser);
       break;
+    case PRAGMA_OMP_TASKGROUP:
+      stmt = c_parser_omp_taskgroup (parser);
+      break;
+    case PRAGMA_OMP_TEAMS:
+      strcpy (p_name, "#pragma omp");
+      stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -10650,7 +13333,252 @@ c_parser_omp_threadprivate (c_parser *parser)
 
   c_parser_skip_to_pragma_eol (parser);
 }
+\f
+/* Cilk Plus <#pragma simd> parsing routines.  */
+
+/* Helper function for c_parser_pragma.  Perform some sanity checking
+   for <#pragma simd> constructs.  Returns FALSE if there was a
+   problem.  */
+
+static bool
+c_parser_cilk_verify_simd (c_parser *parser,
+                                 enum pragma_context context)
+{
+  if (!flag_enable_cilkplus)
+    {
+      warning (0, "pragma simd ignored because -fcilkplus is not enabled");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  if (context == pragma_external)
+    {
+      c_parser_error (parser,"pragma simd must be inside a function");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  return true;
+}
+
+/* Cilk Plus:
+   vectorlength ( constant-expression ) */
+
+static tree
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+{
+  /* The vectorlength clause behaves exactly like OpenMP's safelen
+     clause.  Represent it in OpenMP terms.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree expr = c_parser_expr_no_commas (parser, NULL).value;
+  expr = c_fully_fold (expr, false, NULL);
+
+  if (!TREE_TYPE (expr)
+      || !TREE_CONSTANT (expr)
+      || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    error_at (loc, "vectorlength must be an integer constant");
+  else if (wi::exact_log2 (expr) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else
+    {
+      tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
+      OMP_CLAUSE_CHAIN (u) = clauses;
+      clauses = u;
+    }
+
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  return clauses;
+}
+
+/* Cilk Plus:
+   linear ( simd-linear-variable-list )
+
+   simd-linear-variable-list:
+     simd-linear-variable
+     simd-linear-variable-list , simd-linear-variable
+
+   simd-linear-variable:
+     id-expression
+     id-expression : simd-linear-step
+
+   simd-linear-step:
+   conditional-expression */
+
+static tree
+c_parser_cilk_clause_linear (c_parser *parser, tree clauses)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  if (c_parser_next_token_is_not (parser, CPP_NAME)
+      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+    c_parser_error (parser, "expected identifier");
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
+        && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+    {
+      tree var = lookup_name (c_parser_peek_token (parser)->value);
+
+      if (var == NULL)
+       {
+         undeclared_variable (c_parser_peek_token (parser)->location,
+                              c_parser_peek_token (parser)->value);
+       c_parser_consume_token (parser);
+       }
+      else if (var == error_mark_node)
+       c_parser_consume_token (parser);
+      else
+       {
+         tree step = integer_one_node;
+
+         /* Parse the linear step if present.  */
+         if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+           {
+             c_parser_consume_token (parser);
+             c_parser_consume_token (parser);
+
+             tree expr = c_parser_expr_no_commas (parser, NULL).value;
+             expr = c_fully_fold (expr, false, NULL);
+
+             if (TREE_TYPE (expr)
+                 && INTEGRAL_TYPE_P (TREE_TYPE (expr))
+                 && (TREE_CONSTANT (expr)
+                     || DECL_P (expr)))
+               step = expr;
+             else
+               c_parser_error (parser,
+                               "step size must be an integer constant "
+                               "expression or an integer variable");
+           }
+         else
+           c_parser_consume_token (parser);
+
+         /* Use OMP_CLAUSE_LINEAR, which has the same semantics.  */
+         tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+         OMP_CLAUSE_DECL (u) = var;
+         OMP_CLAUSE_LINEAR_STEP (u) = step;
+         OMP_CLAUSE_CHAIN (u) = clauses;
+         clauses = u;
+       }
+
+      if (c_parser_next_token_is_not (parser, CPP_COMMA))
+       break;
+
+      c_parser_consume_token (parser);
+    }
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not
+   recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is
+   not consumed.  Otherwise, the appropriate pragma_simd_clause is
+   returned and the token is consumed.  */
+
+static pragma_cilk_clause
+c_parser_cilk_clause_name (c_parser *parser)
+{
+  pragma_cilk_clause result;
+  c_token *token = c_parser_peek_token (parser);
+
+  if (!token->value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  const char *p = IDENTIFIER_POINTER (token->value);
+
+  if (!strcmp (p, "vectorlength"))
+    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (p, "linear"))
+    result = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (p, "private"))
+    result = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!strcmp (p, "firstprivate"))
+    result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (p, "lastprivate"))
+    result = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (p, "reduction"))
+    result = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  c_parser_consume_token (parser);
+  return result;
+}
+
+/* Parse all #<pragma simd> clauses.  Return the list of clauses
+   found.  */
+
+static tree
+c_parser_cilk_all_clauses (c_parser *parser)
+{
+  tree clauses = NULL;
+
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      pragma_cilk_clause c_kind;
+
+      c_kind = c_parser_cilk_clause_name (parser);
+
+      switch (c_kind)
+       {
+       case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
+         clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_LINEAR:
+         clauses = c_parser_cilk_clause_linear (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_PRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_private (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_LASTPRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_REDUCTION:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         break;
+       default:
+         c_parser_error (parser, "expected %<#pragma simd%> clause");
+         goto saw_error;
+       }
+    }
+
+ saw_error:
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_cilk_clauses (clauses);
+}
+
+/* Main entry point for parsing Cilk Plus <#pragma simd> for
+   loops.  */
 
+static void
+c_parser_cilk_simd (c_parser *parser ATTRIBUTE_UNUSED)
+{
+  char p_name[100];
+  strcpy (p_name, "#pragma omp");
+  tree clauses = c_parser_cilk_all_clauses (parser);
+  tree block = c_begin_compound_stmt (true);
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+}
+\f
 /* Parse a transaction attribute (GCC Extension).
 
    transaction-attribute:
@@ -10814,7 +13742,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
 */
 
 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;
@@ -10874,6 +13802,7 @@ c_parse_file (void)
   c_parser tparser;
 
   memset (&tparser, 0, sizeof tparser);
+  tparser.tokens = &tparser.tokens_buf[0];
   the_parser = &tparser;
 
   if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
@@ -10881,6 +13810,8 @@ c_parse_file (void)
 
   the_parser = ggc_alloc_c_parser ();
   *the_parser = tparser;
+  if (tparser.tokens == &tparser.tokens_buf[0])
+    the_parser->tokens = &the_parser->tokens_buf[0];
 
   /* Initialize EH, if we've been told to do so.  */
   if (flag_exceptions)
@@ -10890,4 +13821,136 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
+/* This function parses Cilk Plus array notation.  The starting index is
+   passed in INITIAL_INDEX and the array name is passes in ARRAY_VALUE.  The
+   return value of this function is a tree_node called VALUE_TREE of type
+   ARRAY_NOTATION_REF.  */
+
+static tree 
+c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, 
+                        tree array_value)
+{
+  c_token *token = NULL;
+  tree start_index = NULL_TREE, end_index = NULL_TREE, stride = NULL_TREE;
+  tree value_tree = NULL_TREE, type = NULL_TREE, array_type = NULL_TREE;
+  tree array_type_domain = NULL_TREE; 
+
+  if (array_value == error_mark_node)
+    {
+      /* No need to continue.  If either of these 2 were true, then an error
+        must be emitted already.  Thus, no need to emit them twice.  */
+      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+      return error_mark_node;
+    }
+  
+  array_type = TREE_TYPE (array_value);
+  gcc_assert (array_type);
+  type = TREE_TYPE (array_type);
+  token = c_parser_peek_token (parser);
+   
+  if (token->type == CPP_EOF)
+    {
+      c_parser_error (parser, "expected %<:%> or numeral");
+      return value_tree;
+    }
+  else if (token->type == CPP_COLON)
+    {
+      if (!initial_index)
+       {
+         /* If we are here, then we have a case like this A[:].  */
+         c_parser_consume_token (parser);
+         if (TREE_CODE (array_type) == POINTER_TYPE)
+           {
+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in pointers");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return error_mark_node;
+           }
+         if (TREE_CODE (array_type) == FUNCTION_TYPE)
+           {
+             error_at (loc, "array notations cannot be used with function "
+                       "type");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return error_mark_node;
+           }
+         array_type_domain = TYPE_DOMAIN (array_type);
+
+         if (!array_type_domain)
+           {
+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in dimensionless arrays");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return error_mark_node;
+           }
+
+         start_index = TYPE_MINVAL (array_type_domain);
+         start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
+                                    start_index);
+         if (!TYPE_MAXVAL (array_type_domain)
+             || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
+           {
+             error_at (loc, "start-index and length fields necessary for "
+                       "using array notations in variable-length arrays");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return error_mark_node;
+           }
+         end_index = TYPE_MAXVAL (array_type_domain);
+         end_index = fold_build2 (PLUS_EXPR, TREE_TYPE (end_index),
+                                  end_index, integer_one_node);
+         end_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, end_index);
+         stride = build_int_cst (integer_type_node, 1);
+         stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride);
+       }
+      else if (initial_index != error_mark_node)
+       {
+         /* If we are here, then there should be 2 possibilities:
+            1. Array [EXPR : EXPR]
+            2. Array [EXPR : EXPR : EXPR]
+         */
+         start_index = initial_index;
+
+         if (TREE_CODE (array_type) == FUNCTION_TYPE)
+           {
+             error_at (loc, "array notations cannot be used with function "
+                       "type");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return error_mark_node;
+           }
+         c_parser_consume_token (parser); /* consume the ':' */
+         struct c_expr ce = c_parser_expression (parser);
+         ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+         end_index = ce.value;
+         if (!end_index || end_index == error_mark_node)
+           {
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             return error_mark_node;
+           }
+         if (c_parser_peek_token (parser)->type == CPP_COLON)
+           {
+             c_parser_consume_token (parser);
+             ce = c_parser_expression (parser);
+             ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+             stride = ce.value;
+             if (!stride || stride == error_mark_node)
+               {
+                 c_parser_skip_to_end_of_block_or_statement (parser);
+                 return error_mark_node;
+               }
+           }
+       }
+      else
+       c_parser_error (parser, "expected array notation expression");
+    }
+  else
+    c_parser_error (parser, "expected array notation expression");
+  
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+
+  value_tree = build_array_notation_ref (loc, array_value, start_index,
+                                        end_index, stride, type);
+  if (value_tree != error_mark_node)
+    SET_EXPR_LOCATION (value_tree, loc);
+  return value_tree;
+}
+
 #include "gt-c-c-parser.h"