Merge in trunk.
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Oct 2013 23:47:35 +0000 (23:47 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Oct 2013 23:47:35 +0000 (23:47 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@203881 138bc75d-0d04-0410-961f-82ee72b054a4

173 files changed:
1  2 
gcc/Makefile.in
gcc/ada/gcc-interface/cuintp.c
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/trans.c
gcc/ada/gcc-interface/utils.c
gcc/alias.c
gcc/asan.c
gcc/builtins.c
gcc/c-family/c-common.c
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c/Make-lang.in
gcc/c/c-decl.c
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cfgexpand.c
gcc/cfgloop.c
gcc/cfgloop.h
gcc/cgraph.c
gcc/cgraphunit.c
gcc/combine.c
gcc/config/aarch64/aarch64.c
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/bfin/bfin.c
gcc/config/darwin.c
gcc/config/i386/i386.c
gcc/config/ia64/predicates.md
gcc/config/iq2000/iq2000.c
gcc/config/mep/mep.c
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/s390/s390.c
gcc/config/sh/sh.c
gcc/config/sparc/sparc.c
gcc/coretypes.h
gcc/coverage.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/cp/typeck2.c
gcc/cse.c
gcc/cselib.c
gcc/dbxout.c
gcc/defaults.h
gcc/doc/generic.texi
gcc/doc/rtl.texi
gcc/doc/tm.texi
gcc/dojump.c
gcc/dwarf2out.c
gcc/emit-rtl.c
gcc/except.c
gcc/expmed.c
gcc/expr.c
gcc/expr.h
gcc/final.c
gcc/fixed-value.c
gcc/fold-const.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-intrinsic.c
gcc/function.c
gcc/gcse.c
gcc/genemit.c
gcc/gengenrtl.c
gcc/gengtype-parse.c
gcc/gengtype-state.c
gcc/gengtype.c
gcc/genmodes.c
gcc/genpreds.c
gcc/genrecog.c
gcc/gensupport.c
gcc/gimple-fold.c
gcc/gimple-pretty-print.c
gcc/gimple-ssa-strength-reduction.c
gcc/gimple.c
gcc/gimplify.c
gcc/go/go-gcc.cc
gcc/go/gofrontend/expressions.cc
gcc/godump.c
gcc/graphite-clast-to-gimple.c
gcc/graphite-scop-detection.c
gcc/graphite-sese-to-poly.c
gcc/ipa-cp.c
gcc/ipa-devirt.c
gcc/ipa-prop.c
gcc/ipa-utils.h
gcc/loop-doloop.c
gcc/loop-iv.c
gcc/loop-unroll.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/lto/lto-lang.c
gcc/lto/lto.c
gcc/omp-low.c
gcc/optabs.c
gcc/postreload.c
gcc/predict.c
gcc/pretty-print.h
gcc/print-rtl.c
gcc/print-tree.c
gcc/real.c
gcc/real.h
gcc/recog.c
gcc/rtl.c
gcc/rtl.def
gcc/rtl.h
gcc/rtlanal.c
gcc/sched-vis.c
gcc/sdbout.c
gcc/sel-sched-ir.c
gcc/stmt.c
gcc/stor-layout.c
gcc/system.h
gcc/targhooks.c
gcc/trans-mem.c
gcc/tree-call-cdce.c
gcc/tree-cfg.c
gcc/tree-chrec.c
gcc/tree-core.h
gcc/tree-data-ref.c
gcc/tree-dfa.h
gcc/tree-dump.c
gcc/tree-inline.c
gcc/tree-mudflap.c
gcc/tree-object-size.c
gcc/tree-predcom.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-address.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-niter.h
gcc/tree-ssa-loop-prefetch.c
gcc/tree-ssa-loop.h
gcc/tree-ssa-math-opts.c
gcc/tree-ssa-phiopt.c
gcc/tree-ssa-pre.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-strlen.c
gcc/tree-ssa-structalias.c
gcc/tree-ssa.c
gcc/tree-ssanames.c
gcc/tree-ssanames.h
gcc/tree-stdarg.c
gcc/tree-switch-conversion.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-generic.c
gcc/tree-vect-loop-manip.c
gcc/tree-vect-loop.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h
gcc/tree-vrp.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/tsan.c
gcc/ubsan.c
gcc/value-prof.c
gcc/var-tracking.c
gcc/varasm.c

diff --cc gcc/Makefile.in
@@@ -864,8 -868,7 +868,7 @@@ RTL_BASE_H = coretypes.h rtl.h rtl.def 
    insn-notes.def $(INPUT_H) $(REAL_H) statistics.h $(VEC_H) \
    $(FIXED_VALUE_H) alias.h $(HASHTAB_H)
  FIXED_VALUE_H = fixed-value.h $(MACHMODE_H) double-int.h
 -RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
 +RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h wide-int.h
- RTL_ERROR_H = rtl-error.h $(RTL_H) $(DIAGNOSTIC_CORE_H)
  READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
  PARAMS_H = params.h params.def
  BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
@@@ -899,12 -898,7 +898,7 @@@ FUNCTION_H = function.h $(HASHTAB_H) $(
  EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
  OPTABS_H = optabs.h insn-codes.h insn-opinit.h
  REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
- SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) \
-       $(REGSET_H)
- SEL_SCHED_IR_H = sel-sched-ir.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) \
-       $(GGC_H) $(BITMAP_H) $(SCHED_INT_H) $(CFGLOOP_H) $(REGSET_H)
- SEL_SCHED_DUMP_H = sel-sched-dump.h $(SEL_SCHED_IR_H)
 -CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \
 +CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h wide-int.h \
        $(BITMAP_H) sbitmap.h
  IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
  IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
@@@ -923,9 -913,9 +913,9 @@@ TIMEVAR_H = timevar.h timevar.de
  INSN_ATTR_H = insn-attr.h insn-attr-common.h $(INSN_ADDR_H)
  INSN_ADDR_H = $(srcdir)/insn-addr.h
  C_COMMON_H = c-family/c-common.h c-family/c-common.def $(TREE_H) \
 -      $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) $(DIAGNOSTIC_CORE_H)
 +      $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) $(DIAGNOSTIC_CORE_H) wide-int.h
  C_PRAGMA_H = c-family/c-pragma.h $(CPPLIB_H)
- C_TREE_H = c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
+ C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
  SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \
        $(srcdir)/../include/safe-ctype.h $(srcdir)/../include/filenames.h
  PREDICT_H = predict.h predict.def
@@@ -946,28 -931,17 +931,17 @@@ TREE_PASS_H = tree-pass.h $(TIMEVAR_H) 
  TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
                $(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \
                $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
 -              tree-ssa-alias.h
 +              tree-ssa-alias.h wide-int.h
  TREE_SSA_H = tree-ssa.h $(TREE_FLOW_H)
- TREE_HASHER_H = tree-hasher.h $(HASH_TABLE_H) $(TREE_FLOW_H)
- TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H)
- SSAEXPAND_H = ssaexpand.h $(TREE_SSA_LIVE_H)
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
  TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H)
  GIMPLE_PRETTY_PRINT_H = gimple-pretty-print.h $(TREE_PRETTY_PRINT_H)
  DIAGNOSTIC_CORE_H = diagnostic-core.h $(INPUT_H) bversion.h diagnostic.def
  DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
- DWARF2OUT_H = dwarf2out.h $(DWARF2_H) wide-int.h
  C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
        $(C_COMMON_H) $(TREE_H)
- SCEV_H = tree-scalar-evolution.h $(GGC_H) tree-chrec.h $(PARAMS_H)
- OMEGA_H = omega.h $(PARAMS_H)
- TREE_DATA_REF_H = tree-data-ref.h $(OMEGA_H) graphds.h $(SCEV_H)
  TREE_INLINE_H = tree-inline.h
 -REAL_H = real.h $(MACHMODE_H)
 +REAL_H = real.h $(MACHMODE_H) signop.h
- IRA_INT_H = ira.h ira-int.h $(CFGLOOP_H) alloc-pool.h
- LRA_INT_H = lra.h $(BITMAP_H) $(RECOG_H) $(INSN_ATTR_H) insn-codes.h \
-    insn-config.h $(REGS_H) lra-int.h
- DBGCNT_H = dbgcnt.h dbgcnt.def
  LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
                $(CGRAPH_H) $(VEC_H) $(HASH_TABLE_H) $(TREE_H) $(GIMPLE_H) \
                $(GCOV_IO_H) $(DIAGNOSTIC_H) alloc-pool.h pointer-set.h
Simple merge
Simple merge
Simple merge
@@@ -1725,52 -1739,38 +1739,38 @@@ rest_of_record_type_compilation (tree r
          else
            pos = compute_related_constant (curpos, last_pos);
  
-         if (!pos && TREE_CODE (curpos) == MULT_EXPR
+         if (!pos
+             && TREE_CODE (curpos) == MULT_EXPR
 -            && host_integerp (TREE_OPERAND (curpos, 1), 1))
 +            && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1)))
            {
              tree offset = TREE_OPERAND (curpos, 0);
 -            align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
 +            align = tree_to_uhwi (TREE_OPERAND (curpos, 1));
-             /* An offset which is a bitwise AND with a mask increases the
-                alignment according to the number of trailing zeros.  */
-             offset = remove_conversions (offset, true);
-             if (TREE_CODE (offset) == BIT_AND_EXPR
-                 && TREE_CODE (TREE_OPERAND (offset, 1)) == INTEGER_CST)
-               {
-                 unsigned HOST_WIDE_INT mask
-                   = tree_to_hwi (TREE_OPERAND (offset, 1));
-                 unsigned int i;
-                 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
-                   {
-                     if (mask & 1)
-                       break;
-                     mask >>= 1;
-                     align *= 2;
-                   }
-               }
-             pos = compute_related_constant (curpos,
-                                             round_up (last_pos, align));
+             align = scale_by_factor_of (offset, align);
+             last_pos = round_up (last_pos, align);
+             pos = compute_related_constant (curpos, last_pos);
            }
-         else if (!pos && TREE_CODE (curpos) == PLUS_EXPR
-                  && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST
+         else if (!pos
+                  && TREE_CODE (curpos) == PLUS_EXPR
 -                 && host_integerp (TREE_OPERAND (curpos, 1), 1)
++                 && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1))
                   && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
-                  && tree_fits_uhwi_p (TREE_OPERAND
-                                    (TREE_OPERAND (curpos, 0), 1)))
 -                 && host_integerp
 -                    (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1))
++                 && tree_fits_uhwi_p
++                    (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1)))
            {
 -              = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
+             tree offset = TREE_OPERAND (TREE_OPERAND (curpos, 0), 0);
+             unsigned HOST_WIDE_INT addend
++              = tree_to_uhwi (TREE_OPERAND (curpos, 1));
              align
-               = tree_to_uhwi
-               (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1));
-             pos = compute_related_constant (curpos,
-                                             round_up (last_pos, align));
 -              = tree_low_cst (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
++              = tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1));
+             align = scale_by_factor_of (offset, align);
+             align = MIN (align, addend & -addend);
+             last_pos = round_up (last_pos, align);
+             pos = compute_related_constant (curpos, last_pos);
            }
-         else if (potential_alignment_gap (prev_old_field, old_field,
-                                           pos))
+         else if (potential_alignment_gap (prev_old_field, old_field, pos))
            {
              align = TYPE_ALIGN (field_type);
-             pos = compute_related_constant (curpos,
-                                             round_up (last_pos, align));
+             last_pos = round_up (last_pos, align);
+             pos = compute_related_constant (curpos, last_pos);
            }
  
          /* If we can't compute a position, set it to zero.
@@@ -2559,6 -2558,32 +2558,32 @@@ value_factor_p (tree value, HOST_WIDE_I
    return false;
  }
  
 -      unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1));
+ /* Return VALUE scaled by the biggest power-of-2 factor of EXPR.  */
+ static unsigned int
+ scale_by_factor_of (tree expr, unsigned int value)
+ {
+   expr = remove_conversions (expr, true);
+   /* An expression which is a bitwise AND with a mask has a power-of-2 factor
+      corresponding to the number of trailing zeros of the mask.  */
+   if (TREE_CODE (expr) == BIT_AND_EXPR
+       && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
+     {
++      unsigned HOST_WIDE_INT mask = tree_to_hwi (TREE_OPERAND (expr, 1));
+       unsigned int i = 0;
+       while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT)
+       {
+         mask >>= 1;
+         value *= 2;
+         i++;
+       }
+     }
+   return value;
+ }
  /* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true
     unless we can prove these 2 fields are laid out in such a way that no gap
     exist between the end of PREV_FIELD and the beginning of CURR_FIELD.  OFFSET
diff --cc gcc/alias.c
Simple merge
diff --cc gcc/asan.c
Simple merge
diff --cc gcc/builtins.c
Simple merge
Simple merge
Simple merge
@@@ -627,6 -885,101 +885,101 @@@ c_omp_split_clauses (location_t loc, en
      }
  }
  
 -      int c = tree_low_cst (OMP_CLAUSE_DECL (a), 0);
 -      int d = tree_low_cst (OMP_CLAUSE_DECL (b), 0);
+ /* qsort callback to compare #pragma omp declare simd clauses.  */
+ static int
+ c_omp_declare_simd_clause_cmp (const void *p, const void *q)
+ {
+   tree a = *(const tree *) p;
+   tree b = *(const tree *) q;
+   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
+     {
+       if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
+       return -1;
+       return 1;
+     }
+   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
+       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
+       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
+     {
 -      int idx = tree_low_cst (OMP_CLAUSE_DECL (c), 0), i;
++      int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
++      int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
+       if (c < d)
+       return 1;
+       if (c > d)
+       return -1;
+     }
+   return 0;
+ }
+ /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
+    CLAUSES on FNDECL into argument indexes and sort them.  */
+ tree
+ c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
+ {
+   tree c;
+   vec<tree> clvec = vNULL;
+   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+     {
+       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+         && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+       {
+         tree decl = OMP_CLAUSE_DECL (c);
+         tree arg;
+         int idx;
+         for (arg = parms, idx = 0; arg;
+              arg = TREE_CHAIN (arg), idx++)
+           if (arg == decl)
+             break;
+         if (arg == NULL_TREE)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD is not an function argument", decl);
+             continue;
+           }
+         OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
+       }
+       clvec.safe_push (c);
+     }
+   if (!clvec.is_empty ())
+     {
+       unsigned int len = clvec.length (), i;
+       clvec.qsort (c_omp_declare_simd_clause_cmp);
+       clauses = clvec[0];
+       for (i = 0; i < len; i++)
+       OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
+     }
+   clvec.release ();
+   return clauses;
+ }
+ /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs.  */
+ void
+ c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
+ {
+   tree c;
+   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+     if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+       && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+       && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+       {
++      int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
+       tree arg;
+       for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
+            arg = TREE_CHAIN (arg), i++)
+         if (i == idx)
+           break;
+       gcc_assert (arg);
+       OMP_CLAUSE_DECL (c) = arg;
+       }
+ }
  /* True if OpenMP sharing attribute of DECL is predetermined.  */
  
  enum omp_clause_default_kind
Simple merge
@@@ -144,56 -137,4 +137,3 @@@ c.stageprofile: stageprofile-star
        -mv c/*$(objext) stageprofile/c
  c.stagefeedback: stagefeedback-start
        -mv c/*$(objext) stagefeedback/c
- #\f
- # .o: .h dependencies.
- # C language specific files.
- C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
- c/c-aux-info.o : c/c-aux-info.c  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(C_TREE_H) $(TREE_H) $(FLAGS_H)
- c/c-convert.o : c/c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(C_COMMON_H) convert.h \
-       langhooks.h $(TARGET_H)
- c/c-decl.o : c/c-decl.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) \
-       output.h debug.h toplev.h intl.h $(TM_P_H) $(TREE_INLINE_H) \
-       $(TIMEVAR_H) $(OPTS_H) $(C_PRAGMA_H) gt-c-c-decl.h $(CGRAPH_H) \
-       $(HASH_TABLE_H) $(LANGHOOKS_DEF_H) \
-       dumpfile.h $(C_COMMON_H) $(CPPLIB_H) $(DIAGNOSTIC_CORE_H) \
-       $(INPUT_H) langhooks.h pointer-set.h tree-iterator.h \
-       $(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h
- c/c-errors.o: c/c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-       $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
- c/c-lang.o : c/c-lang.c c/c-objc-common.h \
-       $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-       $(C_TREE_H) $(DIAGNOSTIC_CORE_H) \
-       langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h \
-       $(C_PRAGMA_H) $(TREE_INLINE_H)
- c/c-objc-common.o : c/c-objc-common.c c/c-objc-common.h \
-       $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
-       langhooks.h $(GGC_H) $(C_PRETTY_PRINT_H) intl.h \
-       $(TREE_PRETTY_PRINT_H)
- c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-       $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
-       $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
-       gt-c-c-parser.h langhooks.h \
-       $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
-       c-family/c-objc.h
- c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
-       langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
-       c-family/c-objc.h c-family/c-common.h wide-int.h
- c/c-array-notation.o: c/c-array-notation.c c/c-lang.h $(CONFIG_H) \
-       $(SYSTEM_H) coretypes.h $(TREE_H) $(C_TREE_H) $(TARGET_H) \
-       intl.h output.h $(EXPR_H) langhooks.h tree-iterator.h $(BITMAP_H) \
-       $(GIMPLE_H) c-family/c-objc.h
--
diff --cc gcc/c/c-decl.c
Simple merge
@@@ -9209,9 -9439,11 +9439,11 @@@ c_parser_omp_clause_collapse (c_parser 
      }
    if (num == error_mark_node)
      return list;
+   mark_exp_read (num);
+   num = c_fully_fold (num, false, NULL);
    if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
 -      || !host_integerp (num, 0)
 -      || (n = tree_low_cst (num, 0)) <= 0
 +      || !tree_fits_shwi_p (num)
 +      || (n = tree_to_shwi (num)) <= 0
        || (int) n != n)
      {
        error_at (loc,
@@@ -9864,612 -10219,1568 +10219,1568 @@@ c_parser_omp_clause_depend (c_parser *p
    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;
-       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;
-       }
+       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
        {
-         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;
+         c_parser_error (parser, "invalid map kind");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return list;
        }
-       break;
-     default:
-       break;
+       c_parser_consume_token (parser);
+       c_parser_consume_token (parser);
      }
  
-   /* 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))
+   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 %<(%>"))
      {
-     case ERROR_MARK:
-     saw_error:
-       c_parser_skip_to_end_of_block_or_statement (parser);
-       if (structured_block)
+       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)))
        {
-         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);
-           }
+         c_parser_error (parser, "expected integer expression");
+         return list;
        }
-       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);
-       opcode = PLUS_EXPR;
-       rhs = integer_one_node;
-       break;
+       check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
  
-     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;
+       c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
+       OMP_CLAUSE_DEVICE_ID (c) = t;
+       OMP_CLAUSE_CHAIN (c) = list;
+       list = c;
+     }
  
-     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);
-             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;
-           }
-       }
-       /* 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:
-         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;
+   return list;
+ }
  
-             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;
-       }
+ /* OpenMP 4.0:
+    dist_schedule ( static )
+    dist_schedule ( static , expression ) */
  
-       /* 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)
+ 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_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-       c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+       c_parser_error (parser, "invalid dist_schedule kind");
+       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                "expected %<)%>");
+       return list;
      }
- done:
-   stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
-   if (stmt != error_mark_node)
-     add_stmt (stmt);
-   if (!structured_block)
-     c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
  
+   c_parser_consume_token (parser);
+   if (c_parser_next_token_is (parser, CPP_COMMA))
+     {
+       c_parser_consume_token (parser);
  
- /* OpenMP 2.5:
-    # pragma omp barrier new-line
- */
+       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 %<)%>");
  
- 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);
+   check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+   if (t == error_mark_node)
+     return list;
  
-   c_finish_omp_barrier (loc);
+   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 2.5:
-    # pragma omp critical [(name)] new-line
-      structured-block
+ /* OpenMP 4.0:
+    proc_bind ( proc-bind-kind )
  
-   LOC is the location of the #pragma itself.  */
+    proc-bind-kind:
+      master | close | spread  */
  
  static tree
- c_parser_omp_critical (location_t loc, c_parser *parser)
+ c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
  {
-   tree stmt, name = NULL;
+   location_t clause_loc = c_parser_peek_token (parser)->location;
+   enum omp_clause_proc_bind_kind kind;
+   tree c;
  
-   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+     return list;
+   if (c_parser_next_token_is (parser, CPP_NAME))
      {
-       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 %<)%>");
-       }
+       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
-       c_parser_error (parser, "expected identifier");
+       goto invalid_kind;
      }
-   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);
+   else
+     goto invalid_kind;
  
-   stmt = c_parser_omp_structured_block (parser);
-   return c_finish_omp_critical (loc, stmt, name);
- }
+   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;
  
- /* OpenMP 2.5:
-    # pragma omp flush flush-vars[opt] new-line
+  invalid_kind:
+   c_parser_error (parser, "invalid proc_bind kind");
+   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+   return list;
+ }
  
   flush-vars:
-      ( variable-list ) */
/* OpenMP 4.0:
+    to ( variable-list ) */
  
- static void
- c_parser_omp_flush (c_parser *parser)
+ static tree
+ c_parser_omp_clause_to (c_parser *parser, tree list)
  {
-   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);
+   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list);
  }
  
- /* 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".  */
+ /* OpenMP 4.0:
+    from ( variable-list ) */
  
  static tree
- c_parser_omp_for_loop (location_t loc,
-                      c_parser *parser, tree clauses, tree *par_clauses)
+ c_parser_omp_clause_from (c_parser *parser, tree list)
  {
-   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));
+   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list);
+ }
  
-   gcc_assert (collapse >= 1);
+ /* OpenMP 4.0:
+    uniform ( variable-list ) */
  
-   declv = make_tree_vec (collapse);
-   initv = make_tree_vec (collapse);
-   condv = make_tree_vec (collapse);
-   incrv = make_tree_vec (collapse);
+ 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_next_token_is_keyword (parser, RID_FOR))
+   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      {
-       c_parser_error (parser, "for statement expected");
-       return NULL;
+       list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
+                                        list);
+       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      }
-   for_loc = c_parser_peek_token (parser)->location;
-   c_parser_consume_token (parser);
+   return list;
+ }
  
-   for (i = 0; i < collapse; i++)
-     {
-       int bracecount = 0;
+ /* 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.  */
  
-       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       goto pop_scopes;
+ 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;
  
-       /* Parse the initialization declaration or expression.  */
-       if (c_parser_next_tokens_start_declaration (parser))
+   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)
        {
-         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;
+       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;
        }
-       else if (c_parser_next_token_is (parser, CPP_NAME)
-              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+       first = false;
+       if (((mask >> c_kind) & 1) == 0 && !parser->error)
        {
-         struct c_expr decl_exp;
-         struct c_expr init_exp;
-         location_t init_loc;
+         /* 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);
+       }
+     }
  
-         decl_exp = c_parser_postfix_expression (parser);
-         decl = decl_exp.value;
+  saw_error:
+   c_parser_skip_to_pragma_eol (parser);
  
-         c_parser_require (parser, CPP_EQ, "expected %<=%>");
+   if (finish_p)
+     return c_finish_omp_clauses (clauses);
  
-         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);
+   return clauses;
+ }
  
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-       }
+ /* 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"))
        {
-       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;
+         seq_cst = true;
+         c_parser_consume_token (parser);
        }
 -      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+     }
+   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;
+           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;
+   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);
+         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;
+       }
+     }
+   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
+     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 %<{%>"))
+     {
+       /* Avoid skipping until the end of the block.  */
+       parser->error = false;
+       return NULL_TREE;
+     }
+   stmt = push_stmt_list ();
+   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);
+     }
+   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)
+       {
+         c_parser_consume_pragma (parser);
+         c_parser_skip_to_pragma_eol (parser);
+         error_suppress = false;
+       }
+       else if (!error_suppress)
+       {
+         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
+         error_suppress = true;
+       }
+       substmt = c_parser_omp_structured_block (parser);
+       substmt = build1 (OMP_SECTION, void_type_node, substmt);
+       SET_EXPR_LOCATION (substmt, loc);
+       add_stmt (substmt);
+     }
+   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);
+ }
+ /* OpenMP 2.5:
+    # pragma omp sections sections-clause[optseq] newline
+      sections-scope
+    LOC is the location of the #pragma token.
+ */
  
-       /* 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);
+ #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))
  
-         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 tree
+ c_parser_omp_sections (location_t loc, c_parser *parser,
+                      char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree block, clauses, ret;
  
-       /* 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;
+   strcat (p_name, " sections");
+   mask |= OMP_SECTIONS_CLAUSE_MASK;
+   if (cclauses)
+     mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
  
-         incr = c_process_expr_stmt (incr_loc,
-                                     c_parser_expression (parser).value);
-       }
-       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+   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];
+     }
  
-       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;
-       }
+   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);
  
-     parse_next:
-       if (i == collapse - 1)
-       break;
+   return ret;
+ }
  
-       /* 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);
+ /* 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
  
-       nbraces += bracecount;
-     }
+    LOC is the location of the #pragma token.
+ */
  
-   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 ();
+ #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))
  
-   if (open_brace_parsed)
+ static tree
+ c_parser_omp_parallel (location_t loc, c_parser *parser,
+                      char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree stmt, clauses, block;
+   strcat (p_name, " parallel");
+   mask |= OMP_PARALLEL_CLAUSE_MASK;
+   if (c_parser_next_token_is_keyword (parser, RID_FOR))
      {
-       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));
+       tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+       if (cclauses == NULL)
+       cclauses = cclauses_buf;
+       c_parser_consume_token (parser);
+       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
-     add_stmt (c_parser_c99_block_statement (parser));
-   if (c_cont_label)
+   else if (cclauses)
      {
-       tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
-       SET_EXPR_LOCATION (t, loc);
-       add_stmt (t);
+       error_at (loc, "expected %<for%> after %qs", p_name);
+       c_parser_skip_to_pragma_eol (parser);
+       return NULL_TREE;
      }
-   body = pop_stmt_list (body);
-   c_break_label = save_break;
-   c_cont_label = save_cont;
-   while (nbraces)
+   else if (c_parser_next_token_is (parser, CPP_NAME))
      {
-       if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+       if (strcmp (p, "sections") == 0)
        {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
          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;
+         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;
        }
      }
  
@@@ -11018,3 -11793,205 +11795,204 @@@ c_build_va_arg (location_t loc, tree ex
                "C++ requires promoted type, not enum type, in %<va_arg%>");
    return build_va_arg (loc, expr, type);
  }
 -      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
 -      && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+ /* Return truthvalue of whether T1 is the same tree structure as T2.
+    Return 1 if they are the same. Return 0 if they are different.  */
+ bool
+ c_tree_equal (tree t1, tree t2)
+ {
+   enum tree_code code1, code2;
+   if (t1 == t2)
+     return true;
+   if (!t1 || !t2)
+     return false;
+   for (code1 = TREE_CODE (t1);
+        CONVERT_EXPR_CODE_P (code1)
+        || code1 == NON_LVALUE_EXPR;
+        code1 = TREE_CODE (t1))
+     t1 = TREE_OPERAND (t1, 0);
+   for (code2 = TREE_CODE (t2);
+        CONVERT_EXPR_CODE_P (code2)
+        || code2 == NON_LVALUE_EXPR;
+        code2 = TREE_CODE (t2))
+     t2 = TREE_OPERAND (t2, 0);
+   /* They might have become equal now.  */
+   if (t1 == t2)
+     return true;
+   if (code1 != code2)
+     return false;
+   switch (code1)
+     {
+     case INTEGER_CST:
++      return wi::eq_p (t1, t2);
+     case REAL_CST:
+       return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+     case STRING_CST:
+       return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+       && !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+                   TREE_STRING_LENGTH (t1));
+     case FIXED_CST:
+       return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
+                                    TREE_FIXED_CST (t2));
+     case COMPLEX_CST:
+       return c_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
+            && c_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
+     case VECTOR_CST:
+       return operand_equal_p (t1, t2, OEP_ONLY_CONST);
+     case CONSTRUCTOR:
+       /* We need to do this when determining whether or not two
+        non-type pointer to member function template arguments
+        are the same.  */
+       if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2))
+         || CONSTRUCTOR_NELTS (t1) != CONSTRUCTOR_NELTS (t2))
+       return false;
+       {
+       tree field, value;
+       unsigned int i;
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t1), i, field, value)
+         {
+           constructor_elt *elt2 = CONSTRUCTOR_ELT (t2, i);
+           if (!c_tree_equal (field, elt2->index)
+               || !c_tree_equal (value, elt2->value))
+             return false;
+         }
+       }
+       return true;
+     case TREE_LIST:
+       if (!c_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+       return false;
+       if (!c_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+       return false;
+       return c_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
+     case SAVE_EXPR:
+       return c_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+     case CALL_EXPR:
+       {
+       tree arg1, arg2;
+       call_expr_arg_iterator iter1, iter2;
+       if (!c_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+         return false;
+       for (arg1 = first_call_expr_arg (t1, &iter1),
+              arg2 = first_call_expr_arg (t2, &iter2);
+            arg1 && arg2;
+            arg1 = next_call_expr_arg (&iter1),
+              arg2 = next_call_expr_arg (&iter2))
+         if (!c_tree_equal (arg1, arg2))
+           return false;
+       if (arg1 || arg2)
+         return false;
+       return true;
+       }
+     case TARGET_EXPR:
+       {
+       tree o1 = TREE_OPERAND (t1, 0);
+       tree o2 = TREE_OPERAND (t2, 0);
+       /* Special case: if either target is an unallocated VAR_DECL,
+          it means that it's going to be unified with whatever the
+          TARGET_EXPR is really supposed to initialize, so treat it
+          as being equivalent to anything.  */
+       if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE
+           && !DECL_RTL_SET_P (o1))
+         /*Nop*/;
+       else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
+                && !DECL_RTL_SET_P (o2))
+         /*Nop*/;
+       else if (!c_tree_equal (o1, o2))
+         return false;
+       return c_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+       }
+     case COMPONENT_REF:
+       if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
+       return false;
+       return c_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+     case PARM_DECL:
+     case VAR_DECL:
+     case CONST_DECL:
+     case FIELD_DECL:
+     case FUNCTION_DECL:
+     case IDENTIFIER_NODE:
+     case SSA_NAME:
+       return false;
+     case TREE_VEC:
+       {
+       unsigned ix;
+       if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
+         return false;
+       for (ix = TREE_VEC_LENGTH (t1); ix--;)
+         if (!c_tree_equal (TREE_VEC_ELT (t1, ix),
+                            TREE_VEC_ELT (t2, ix)))
+           return false;
+       return true;
+       }
+     default:
+       break;
+     }
+   switch (TREE_CODE_CLASS (code1))
+     {
+     case tcc_unary:
+     case tcc_binary:
+     case tcc_comparison:
+     case tcc_expression:
+     case tcc_vl_exp:
+     case tcc_reference:
+     case tcc_statement:
+       {
+       int i, n = TREE_OPERAND_LENGTH (t1);
+       switch (code1)
+         {
+         case PREINCREMENT_EXPR:
+         case PREDECREMENT_EXPR:
+         case POSTINCREMENT_EXPR:
+         case POSTDECREMENT_EXPR:
+           n = 1;
+           break;
+         case ARRAY_REF:
+           n = 2;
+           break;
+         default:
+           break;
+         }
+       if (TREE_CODE_CLASS (code1) == tcc_vl_exp
+           && n != TREE_OPERAND_LENGTH (t2))
+         return false;
+       for (i = 0; i < n; ++i)
+         if (!c_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
+           return false;
+       return true;
+       }
+     case tcc_type:
+       return comptypes (t1, t2);
+     default:
+       gcc_unreachable ();
+     }
+   /* We can get here with --disable-checking.  */
+   return false;
+ }
diff --cc gcc/cfgexpand.c
@@@ -1131,7 -1132,9 +1132,9 @@@ defer_stack_allocation (tree var, bool 
       other hand, we don't want the function's stack frame size to
       get completely out of hand.  So we avoid adding scalars and
       "small" aggregates to the list at all.  */
-   if (optimize == 0 && tree_to_uhwi (DECL_SIZE_UNIT (var)) < 32)
+   if (optimize == 0
 -      && (tree_low_cst (DECL_SIZE_UNIT (var), 1)
++      && (tree_to_uhwi (DECL_SIZE_UNIT (var))
+           < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)))
      return false;
  
    return true;
diff --cc gcc/cfgloop.c
@@@ -1782,3 -1781,141 +1782,142 @@@ get_loop_location (struct loop *loop
    return DECL_SOURCE_LOCATION (current_function_decl);
  }
  
 -record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
 -                  bool upper)
+ /* Records that every statement in LOOP is executed I_BOUND times.
+    REALISTIC is true if I_BOUND is expected to be close to the real number
+    of iterations.  UPPER is true if we are sure the loop iterates at most
+    I_BOUND times.  */
+ void
 -        || i_bound.ult (loop->nb_iterations_upper_bound)))
++record_niter_bound (struct loop *loop, const max_wide_int &i_bound,
++                  bool realistic, bool upper)
+ {
+   /* Update the bounds only when there is no previous estimation, or when the
+      current estimation is smaller.  */
+   if (upper
+       && (!loop->any_upper_bound
 -        || i_bound.ult (loop->nb_iterations_estimate)))
++        || wi::ltu_p (i_bound, loop->nb_iterations_upper_bound)))
+     {
+       loop->any_upper_bound = true;
+       loop->nb_iterations_upper_bound = i_bound;
+     }
+   if (realistic
+       && (!loop->any_estimate
 -      && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
++        || wi::ltu_p (i_bound, loop->nb_iterations_estimate)))
+     {
+       loop->any_estimate = true;
+       loop->nb_iterations_estimate = i_bound;
+     }
+   /* If an upper bound is smaller than the realistic estimate of the
+      number of iterations, use the upper bound instead.  */
+   if (loop->any_upper_bound
+       && loop->any_estimate
 -  double_int nit;
++      && wi::ltu_p (loop->nb_iterations_upper_bound,
++                  loop->nb_iterations_estimate))
+     loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
+ }
+ /* Similar to get_estimated_loop_iterations, but returns the estimate only
+    if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
+    on the number of iterations of LOOP could not be derived, returns -1.  */
+ HOST_WIDE_INT
+ get_estimated_loop_iterations_int (struct loop *loop)
+ {
 -  if (!nit.fits_shwi ())
++  max_wide_int nit;
+   HOST_WIDE_INT hwi_nit;
+   if (!get_estimated_loop_iterations (loop, &nit))
+     return -1;
 -get_estimated_loop_iterations (struct loop *loop, double_int *nit)
++  if (!wi::fits_shwi_p (nit))
+     return -1;
+   hwi_nit = nit.to_shwi ();
+   return hwi_nit < 0 ? -1 : hwi_nit;
+ }
+ /* Returns an upper bound on the number of executions of statements
+    in the LOOP.  For statements before the loop exit, this exceeds
+    the number of execution of the latch by one.  */
+ HOST_WIDE_INT
+ max_stmt_executions_int (struct loop *loop)
+ {
+   HOST_WIDE_INT nit = get_max_loop_iterations_int (loop);
+   HOST_WIDE_INT snit;
+   if (nit == -1)
+     return -1;
+   snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
+   /* If the computation overflows, return -1.  */
+   return snit < 0 ? -1 : snit;
+ }
+ /* Sets NIT to the estimated number of executions of the latch of the
+    LOOP.  If we have no reliable estimate, the function returns false, otherwise
+    returns true.  */
+ bool
 -          *nit = gcov_type_to_double_int
++get_estimated_loop_iterations (struct loop *loop, max_wide_int *nit)
+ {
+   /* Even if the bound is not recorded, possibly we can derrive one from
+      profile.  */
+   if (!loop->any_estimate)
+     {
+       if (loop->header->count)
+       {
 -get_max_loop_iterations (struct loop *loop, double_int *nit)
++          *nit = gcov_type_to_wide_int
+                  (expected_loop_iterations_unbounded (loop) + 1);
+         return true;
+       }
+       return false;
+     }
+   *nit = loop->nb_iterations_estimate;
+   return true;
+ }
+ /* Sets NIT to an upper bound for the maximum number of executions of the
+    latch of the LOOP.  If we have no reliable estimate, the function returns
+    false, otherwise returns true.  */
+ bool
 -  double_int nit;
++get_max_loop_iterations (struct loop *loop, max_wide_int *nit)
+ {
+   if (!loop->any_upper_bound)
+     return false;
+   *nit = loop->nb_iterations_upper_bound;
+   return true;
+ }
+ /* Similar to get_max_loop_iterations, but returns the estimate only
+    if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
+    on the number of iterations of LOOP could not be derived, returns -1.  */
+ HOST_WIDE_INT
+ get_max_loop_iterations_int (struct loop *loop)
+ {
 -  if (!nit.fits_shwi ())
++  max_wide_int nit;
+   HOST_WIDE_INT hwi_nit;
+   if (!get_max_loop_iterations (loop, &nit))
+     return -1;
++  if (!wi::fits_shwi_p (nit))
+     return -1;
+   hwi_nit = nit.to_shwi ();
+   return hwi_nit < 0 ? -1 : hwi_nit;
+ }
+ /* Returns the loop depth of the loop BB belongs to.  */
+ int
+ bb_loop_depth (const_basic_block bb)
+ {
+   return bb->loop_father ? loop_depth (bb->loop_father) : 0;
+ }
diff --cc gcc/cfgloop.h
@@@ -20,12 -20,10 +20,11 @@@ along with GCC; see the file COPYING3
  #ifndef GCC_CFGLOOP_H
  #define GCC_CFGLOOP_H
  
- #include "basic-block.h"
  #include "double-int.h"
 +#include "wide-int.h"
  #include "bitmap.h"
  #include "sbitmap.h"
+ #include "function.h"
  
  /* Structure to hold decision about unrolling/peeling.  */
  enum lpt_dec
@@@ -752,5 -730,27 +731,27 @@@ loop_outermost (struct loop *loop
    return (*loop->superloops)[1];
  }
  
 -extern void record_niter_bound (struct loop *, double_int, bool, bool);
++extern void record_niter_bound (struct loop *, const max_wide_int &, bool, bool);
+ extern HOST_WIDE_INT get_estimated_loop_iterations_int (struct loop *);
+ extern HOST_WIDE_INT get_max_loop_iterations_int (struct loop *);
 -extern bool get_estimated_loop_iterations (struct loop *loop, double_int *nit);
 -extern bool get_max_loop_iterations (struct loop *loop, double_int *nit);
++extern bool get_estimated_loop_iterations (struct loop *loop, max_wide_int *nit);
++extern bool get_max_loop_iterations (struct loop *loop, max_wide_int *nit);
+ extern int bb_loop_depth (const_basic_block);
  
 -/* Converts VAL to double_int.  */
++/* Converts VAL to max_wide_int.  */
 -static inline double_int
 -gcov_type_to_double_int (gcov_type val)
++static inline max_wide_int
++gcov_type_to_wide_int (gcov_type val)
+ {
 -  double_int ret;
++  HOST_WIDE_INT a[2];
 -  ret.low = (unsigned HOST_WIDE_INT) val;
++  a[0] = (unsigned HOST_WIDE_INT) val;
+   /* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
+      the size of type.  */
+   val >>= HOST_BITS_PER_WIDE_INT - 1;
+   val >>= 1;
 -  ret.high = (unsigned HOST_WIDE_INT) val;
++  a[1] = (unsigned HOST_WIDE_INT) val;
 -  return ret;
++  return max_wide_int::from_array (a, 2);
+ }
  #endif /* GCC_CFGLOOP_H */
diff --cc gcc/cgraph.c
Simple merge
Simple merge
diff --cc gcc/combine.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -61,8 -61,6 +61,7 @@@ along with GCC; see the file COPYING3
  #include "diagnostic.h"
  #include "dumpfile.h"
  #include "tree-pass.h"
- #include "tree-flow.h"
 +#include "wide-int.h"
  #include "context.h"
  #include "pass_manager.h"
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/coretypes.h
Simple merge
diff --cc gcc/coverage.c
Simple merge
diff --cc gcc/cp/class.c
Simple merge
Simple merge
diff --cc gcc/cp/decl.c
Simple merge
diff --cc gcc/cp/error.c
Simple merge
diff --cc gcc/cp/init.c
Simple merge
diff --cc gcc/cp/mangle.c
Simple merge
diff --cc gcc/cp/parser.c
@@@ -27153,878 -27461,2025 +27461,2025 @@@ cp_parser_omp_clause_depend (cp_parser 
        tree id = cp_lexer_peek_token (parser->lexer)->u.value;
        const char *p = IDENTIFIER_POINTER (id);
  
-       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)
-       cp_lexer_consume_token (parser->lexer);
+       goto invalid_kind;
      }
-   cp_parser_require_pragma_eol (parser, pragma_tok);
+   else
+     goto invalid_kind;
  
-   switch (code)
-     {
-     case OMP_ATOMIC_READ:
-     case NOP_EXPR: /* atomic write */
-       v = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                     /*cast_p=*/false, NULL);
-       if (v == error_mark_node)
-       goto saw_error;
-       if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
-       goto saw_error;
-       if (code == NOP_EXPR)
-       lhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-       else
-       lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                         /*cast_p=*/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 (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-       {
-         cp_lexer_consume_token (parser->lexer);
-         structured_block = true;
-       }
-       else
-       {
-         v = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                         /*cast_p=*/false, NULL);
-         if (v == error_mark_node)
-           goto saw_error;
-         if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
-           goto saw_error;
-       }
-     default:
-       break;
-     }
+   cp_lexer_consume_token (parser->lexer);
+   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+     goto resync_fail;
  
- restart:
-   lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                   /*cast_p=*/false, NULL);
-   orig_lhs = lhs;
-   switch (TREE_CODE (lhs))
-     {
-     case ERROR_MARK:
-       goto saw_error;
+   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND, list,
+                                         NULL);
  
-     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;
+   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+     OMP_CLAUSE_DEPEND_KIND (c) = kind;
  
-     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;
+   return nlist;
  
-     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);
-             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 (cp_lexer_peek_token (parser->lexer)->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:
-         if (structured_block || code == OMP_ATOMIC)
-           {
-             enum cp_parser_prec oprec;
-             cp_token *token;
-             cp_lexer_consume_token (parser->lexer);
-             rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                                /*cast_p=*/false, NULL);
-             if (rhs1 == error_mark_node)
-               goto saw_error;
-             token = cp_lexer_peek_token (parser->lexer);
-             switch (token->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;
-                     cp_lexer_consume_token (parser->lexer);
-                     goto restart;
-                   }
-                 cp_parser_error (parser,
-                                  "invalid form of %<#pragma omp atomic%>");
-                 goto saw_error;
-               case CPP_MULT:
-                 opcode = MULT_EXPR;
-                 break;
-               case CPP_DIV:
-                 opcode = TRUNC_DIV_EXPR;
-                 break;
-               case CPP_PLUS:
-                 opcode = PLUS_EXPR;
-                 break;
-               case CPP_MINUS:
-                 opcode = MINUS_EXPR;
-                 break;
-               case CPP_LSHIFT:
-                 opcode = LSHIFT_EXPR;
-                 break;
-               case CPP_RSHIFT:
-                 opcode = RSHIFT_EXPR;
-                 break;
-               case CPP_AND:
-                 opcode = BIT_AND_EXPR;
-                 break;
-               case CPP_OR:
-                 opcode = BIT_IOR_EXPR;
-                 break;
-               case CPP_XOR:
-                 opcode = BIT_XOR_EXPR;
-                 break;
-               default:
-                 cp_parser_error (parser,
-                                  "invalid operator for %<#pragma omp atomic%>");
-                 goto saw_error;
-               }
-             oprec = TOKEN_PRECEDENCE (token);
-             gcc_assert (oprec != PREC_NOT_OPERATOR);
-             if (commutative_tree_code (opcode))
-               oprec = (enum cp_parser_prec) (oprec - 1);
-             cp_lexer_consume_token (parser->lexer);
-             rhs = cp_parser_binary_expression (parser, false, false,
-                                                oprec, NULL);
-             if (rhs == error_mark_node)
-               goto saw_error;
-             goto stmt_done;
-           }
-         /* FALLTHROUGH */
-       default:
-         cp_parser_error (parser,
-                          "invalid operator for %<#pragma omp atomic%>");
-         goto saw_error;
-       }
-       cp_lexer_consume_token (parser->lexer);
+  invalid_kind:
+   cp_parser_error (parser, "invalid depend kind");
+  resync_fail:
+   cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+   return list;
+ }
  
-       rhs = cp_parser_expression (parser, false, NULL);
-       if (rhs == error_mark_node)
-       goto saw_error;
-       break;
-     }
- stmt_done:
-   if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
-     {
-       if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
-       goto saw_error;
-       v = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                     /*cast_p=*/false, NULL);
-       if (v == error_mark_node)
-       goto saw_error;
-       if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
-       goto saw_error;
-       lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                        /*cast_p=*/false, NULL);
-       if (lhs1 == error_mark_node)
-       goto saw_error;
-     }
-   if (structured_block)
-     {
-       cp_parser_consume_semicolon_at_end_of_statement (parser);
-       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
-     }
- done:
-   finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
-   if (!structured_block)
-     cp_parser_consume_semicolon_at_end_of_statement (parser);
-   return;
+ /* OpenMP 4.0:
+    map ( map-kind : variable-list )
+    map ( variable-list )
  
-  saw_error:
-   cp_parser_skip_to_end_of_block_or_statement (parser);
-   if (structured_block)
+    map-kind:
+      alloc | to | from | tofrom  */
+ static tree
+ cp_parser_omp_clause_map (cp_parser *parser, tree list)
+ {
+   tree nlist, c;
+   enum omp_clause_map_kind kind = OMP_CLAUSE_MAP_TOFROM;
+   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+     return list;
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+       && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
      {
-       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
-         cp_lexer_consume_token (parser->lexer);
-       else if (code == OMP_ATOMIC_CAPTURE_NEW)
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       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
        {
-         cp_parser_skip_to_end_of_block_or_statement (parser);
-         if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
-           cp_lexer_consume_token (parser->lexer);
+         cp_parser_error (parser, "invalid map kind");
+         cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                                /*or_comma=*/false,
+                                                /*consume_paren=*/true);
+         return list;
        }
+       cp_lexer_consume_token (parser->lexer);
+       cp_lexer_consume_token (parser->lexer);
      }
- }
  
+   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
+                                         NULL);
  
- /* OpenMP 2.5:
-    # pragma omp barrier new-line  */
+   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+     OMP_CLAUSE_MAP_KIND (c) = kind;
  
- static void
- cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok)
- {
-   cp_parser_require_pragma_eol (parser, pragma_tok);
-   finish_omp_barrier ();
+   return nlist;
  }
  
- /* OpenMP 2.5:
-    # pragma omp critical [(name)] new-line
-      structured-block  */
+ /* OpenMP 4.0:
+    device ( expression ) */
  
  static tree
- cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
+ cp_parser_omp_clause_device (cp_parser *parser, tree list,
+                            location_t location)
  {
-   tree stmt, name = NULL;
+   tree t, c;
  
-   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-     {
-       cp_lexer_consume_token (parser->lexer);
+   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+     return list;
  
-       name = cp_parser_identifier (parser);
+   t = cp_parser_expression (parser, false, NULL);
  
-       if (name == error_mark_node
-         || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-                                              /*or_comma=*/false,
-                                              /*consume_paren=*/true);
-       if (name == error_mark_node)
-       name = NULL;
-     }
-   cp_parser_require_pragma_eol (parser, pragma_tok);
+   if (t == error_mark_node
+       || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
  
-   stmt = cp_parser_omp_structured_block (parser);
-   return c_finish_omp_critical (input_location, stmt, name);
- }
- /* OpenMP 2.5:
-    # pragma omp flush flush-vars[opt] new-line
-    flush-vars:
-      ( variable-list ) */
+   check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE,
+                            "device", location);
  
- static void
- cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
- {
-   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-     (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
-   cp_parser_require_pragma_eol (parser, pragma_tok);
+   c = build_omp_clause (location, OMP_CLAUSE_DEVICE);
+   OMP_CLAUSE_DEVICE_ID (c) = t;
+   OMP_CLAUSE_CHAIN (c) = list;
  
-   finish_omp_flush ();
+   return c;
  }
  
- /* Helper function, to parse omp for increment expression.  */
+ /* OpenMP 4.0:
+    dist_schedule ( static )
+    dist_schedule ( static , expression )  */
  
  static tree
- cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
+                                   location_t location)
  {
-   tree cond = cp_parser_binary_expression (parser, false, true,
-                                          PREC_NOT_OPERATOR, NULL);
-   if (cond == error_mark_node
-       || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-     {
-       cp_parser_skip_to_end_of_statement (parser);
-       return error_mark_node;
-     }
-   switch (TREE_CODE (cond))
-     {
-     case GT_EXPR:
-     case GE_EXPR:
-     case LT_EXPR:
-     case LE_EXPR:
-       break;
-     default:
-       return error_mark_node;
-     }
-   /* If decl is an iterator, preserve LHS and RHS of the relational
-      expr until finish_omp_for.  */
-   if (decl
-       && (type_dependent_expression_p (decl)
-         || CLASS_TYPE_P (TREE_TYPE (decl))))
-     return cond;
-   return build_x_binary_op (input_location, TREE_CODE (cond),
-                           TREE_OPERAND (cond, 0), ERROR_MARK,
-                           TREE_OPERAND (cond, 1), ERROR_MARK,
-                           /*overload=*/NULL, tf_warning_or_error);
- }
- /* Helper function, to parse omp for increment expression.  */
+   tree c, t;
  
- static tree
- cp_parser_omp_for_incr (cp_parser *parser, tree decl)
- {
-   cp_token *token = cp_lexer_peek_token (parser->lexer);
-   enum tree_code op;
-   tree lhs, rhs;
-   cp_id_kind idk;
-   bool decl_first;
+   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+     return list;
  
-   if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
-     {
-       op = (token->type == CPP_PLUS_PLUS
-           ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
-       cp_lexer_consume_token (parser->lexer);
-       lhs = cp_parser_simple_cast_expression (parser);
-       if (lhs != decl)
-       return error_mark_node;
-       return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
-     }
+   c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE);
  
-   lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
-   if (lhs != decl)
-     return error_mark_node;
+   if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
+     goto invalid_kind;
+   cp_lexer_consume_token (parser->lexer);
  
-   token = cp_lexer_peek_token (parser->lexer);
-   if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
      {
-       op = (token->type == CPP_PLUS_PLUS
-           ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
        cp_lexer_consume_token (parser->lexer);
-       return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
-     }
-   op = cp_parser_assignment_operator_opt (parser);
-   if (op == ERROR_MARK)
-     return error_mark_node;
  
-   if (op != NOP_EXPR)
-     {
-       rhs = cp_parser_assignment_expression (parser, false, NULL);
-       rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
-       return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
-     }
+       t = cp_parser_assignment_expression (parser, false, NULL);
  
-   lhs = cp_parser_binary_expression (parser, false, false,
-                                    PREC_ADDITIVE_EXPRESSION, NULL);
-   token = cp_lexer_peek_token (parser->lexer);
-   decl_first = lhs == decl;
-   if (decl_first)
-     lhs = NULL_TREE;
-   if (token->type != CPP_PLUS
-       && token->type != CPP_MINUS)
-     return error_mark_node;
+       if (t == error_mark_node)
+       goto resync_fail;
+       OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
  
-   do
-     {
-       op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
-       cp_lexer_consume_token (parser->lexer);
-       rhs = cp_parser_binary_expression (parser, false, false,
-                                        PREC_ADDITIVE_EXPRESSION, NULL);
-       token = cp_lexer_peek_token (parser->lexer);
-       if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
-       {
-         if (lhs == NULL_TREE)
-           {
-             if (op == PLUS_EXPR)
-               lhs = rhs;
-             else
-               lhs = build_x_unary_op (input_location, NEGATE_EXPR, rhs,
-                                       tf_warning_or_error);
-           }
-         else
-           lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
-                                    ERROR_MARK, NULL, tf_warning_or_error);
-       }
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       goto resync_fail;
      }
-   while (token->type == CPP_PLUS || token->type == CPP_MINUS);
+   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+     goto resync_fail;
  
-   if (!decl_first)
-     {
-       if (rhs != decl || op == MINUS_EXPR)
-       return error_mark_node;
-       rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
-     }
-   else
-     rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+   check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule",
+                            location);
+   OMP_CLAUSE_CHAIN (c) = list;
+   return c;
  
-   return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+  invalid_kind:
+   cp_parser_error (parser, "invalid dist_schedule kind");
+  resync_fail:
+   cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+   return list;
  }
  
- /* Parse the restricted form of the for statement allowed by OpenMP.  */
+ /* OpenMP 4.0:
+    proc_bind ( proc-bind-kind )
+    proc-bind-kind:
+      master | close | spread  */
  
  static tree
- cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
+                               location_t location)
  {
-   tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
-   tree real_decl, initv, condv, incrv, declv;
-   tree this_pre_body, cl;
-   location_t loc_first;
-   bool collapse_err = false;
-   int i, collapse = 1, nbraces = 0;
-   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);
+   tree c;
+   enum omp_clause_proc_bind_kind kind;
  
-   loc_first = cp_lexer_peek_token (parser->lexer)->location;
+   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+     return list;
  
-   for (i = 0; i < collapse; i++)
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
      {
-       int bracecount = 0;
-       bool add_private_clause = false;
-       location_t loc;
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
  
-       if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
-       {
-         cp_parser_error (parser, "for statement expected");
-         return NULL;
-       }
-       loc = cp_lexer_consume_token (parser->lexer)->location;
+       if (strcmp ("master", p) == 0)
+       kind = OMP_CLAUSE_PROC_BIND_MASTER;
+       else if (strcmp ("close", p) == 0)
+       kind = OMP_CLAUSE_PROC_BIND_CLOSE;
+       else if (strcmp ("spread", p) == 0)
+       kind = OMP_CLAUSE_PROC_BIND_SPREAD;
+       else
+       goto invalid_kind;
+     }
+   else
+     goto invalid_kind;
  
-       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-       return NULL;
+   cp_lexer_consume_token (parser->lexer);
+   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+     goto resync_fail;
  
-       init = decl = real_decl = NULL;
-       this_pre_body = push_stmt_list ();
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       {
-         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+   c = build_omp_clause (location, OMP_CLAUSE_PROC_BIND);
+   check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind",
+                            location);
+   OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
+   OMP_CLAUSE_CHAIN (c) = list;
+   return c;
  
-            init-expr:
-                      var = lb
-                      integer-type var = lb
-                      random-access-iterator-type var = lb
-                      pointer-type var = lb
-         */
-         cp_decl_specifier_seq type_specifiers;
+  invalid_kind:
+   cp_parser_error (parser, "invalid depend kind");
+  resync_fail:
+   cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+   return list;
+ }
  
-         /* First, try to parse as an initialized declaration.  See
-            cp_parser_condition, from whence the bulk of this is copied.  */
+ /* 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.  */
  
-         cp_parser_parse_tentatively (parser);
-         cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
-                                       /*is_trailing_return=*/false,
-                                       &type_specifiers);
-         if (cp_parser_parse_definitely (parser))
-           {
-             /* If parsing a type specifier seq succeeded, then this
-                MUST be a initialized declaration.  */
-             tree asm_specification, attributes;
-             cp_declarator *declarator;
+ static tree
+ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
+                          const char *where, cp_token *pragma_tok,
+                          bool finish_p = true)
+ {
+   tree clauses = NULL;
+   bool first = true;
+   cp_token *token = NULL;
  
-             declarator = cp_parser_declarator (parser,
-                                                CP_PARSER_DECLARATOR_NAMED,
-                                                /*ctor_dtor_or_conv_p=*/NULL,
-                                                /*parenthesized_p=*/NULL,
-                                                /*member_p=*/false);
-             attributes = cp_parser_attributes_opt (parser);
-             asm_specification = cp_parser_asm_specification_opt (parser);
+   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+     {
+       pragma_omp_clause c_kind;
+       const char *c_name;
+       tree prev = clauses;
  
-             if (declarator == cp_error_declarator) 
-               cp_parser_skip_to_end_of_statement (parser);
+       if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
  
-             else 
+       token = cp_lexer_peek_token (parser->lexer);
+       c_kind = cp_parser_omp_clause_name (parser);
+       switch (c_kind)
+       {
+       case PRAGMA_OMP_CLAUSE_COLLAPSE:
+         clauses = cp_parser_omp_clause_collapse (parser, clauses,
+                                                  token->location);
+         c_name = "collapse";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYIN:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
+         c_name = "copyin";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYPRIVATE,
+                                           clauses);
+         c_name = "copyprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEFAULT:
+         clauses = cp_parser_omp_clause_default (parser, clauses,
+                                                 token->location);
+         c_name = "default";
+         break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = cp_parser_omp_clause_final (parser, clauses, token->location);
+         c_name = "final";
+         break;
+       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
+                                           clauses);
+         c_name = "firstprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_IF:
+         clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
+         c_name = "if";
+         break;
+       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
+                                           clauses);
+         c_name = "lastprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = cp_parser_omp_clause_mergeable (parser, clauses,
+                                                   token->location);
+         c_name = "mergeable";
+         break;
+       case PRAGMA_OMP_CLAUSE_NOWAIT:
+         clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
+         c_name = "nowait";
+         break;
+       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
+         clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+                                                     token->location);
+         c_name = "num_threads";
+         break;
+       case PRAGMA_OMP_CLAUSE_ORDERED:
+         clauses = cp_parser_omp_clause_ordered (parser, clauses,
+                                                 token->location);
+         c_name = "ordered";
+         break;
+       case PRAGMA_OMP_CLAUSE_PRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE,
+                                           clauses);
+         c_name = "private";
+         break;
+       case PRAGMA_OMP_CLAUSE_REDUCTION:
+         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         c_name = "reduction";
+         break;
+       case PRAGMA_OMP_CLAUSE_SCHEDULE:
+         clauses = cp_parser_omp_clause_schedule (parser, clauses,
+                                                  token->location);
+         c_name = "schedule";
+         break;
+       case PRAGMA_OMP_CLAUSE_SHARED:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_SHARED,
+                                           clauses);
+         c_name = "shared";
+         break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         clauses = cp_parser_omp_clause_untied (parser, clauses,
+                                                token->location);
+         c_name = "untied";
+         break;
+       case PRAGMA_OMP_CLAUSE_INBRANCH:
+         clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
+                                                clauses, token->location);
+         c_name = "inbranch";
+         break;
+       case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+         clauses = cp_parser_omp_clause_branch (parser,
+                                                OMP_CLAUSE_NOTINBRANCH,
+                                                clauses, token->location);
+         c_name = "notinbranch";
+         break;
+       case PRAGMA_OMP_CLAUSE_PARALLEL:
+         clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
+                                                    clauses, token->location);
+         c_name = "parallel";
+         if (!first)
+           {
+            clause_not_first:
+             error_at (token->location, "%qs must be the first clause of %qs",
+                       c_name, where);
+             clauses = prev;
+           }
+         break;
+       case PRAGMA_OMP_CLAUSE_FOR:
+         clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
+                                                    clauses, token->location);
+         c_name = "for";
+         if (!first)
+           goto clause_not_first;
+         break;
+       case PRAGMA_OMP_CLAUSE_SECTIONS:
+         clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
+                                                    clauses, token->location);
+         c_name = "sections";
+         if (!first)
+           goto clause_not_first;
+         break;
+       case PRAGMA_OMP_CLAUSE_TASKGROUP:
+         clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
+                                                    clauses, token->location);
+         c_name = "taskgroup";
+         if (!first)
+           goto clause_not_first;
+         break;
+       case PRAGMA_OMP_CLAUSE_TO:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO,
+                                           clauses);
+         c_name = "to";
+         break;
+       case PRAGMA_OMP_CLAUSE_FROM:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM,
+                                           clauses);
+         c_name = "from";
+         break;
+       case PRAGMA_OMP_CLAUSE_UNIFORM:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_UNIFORM,
+                                           clauses);
+         c_name = "uniform";
+         break;
+       case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
+         clauses = cp_parser_omp_clause_num_teams (parser, clauses,
+                                                   token->location);
+         c_name = "num_teams";
+         break;
+       case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
+         clauses = cp_parser_omp_clause_thread_limit (parser, clauses,
+                                                      token->location);
+         c_name = "thread_limit";
+         break;
+       case PRAGMA_OMP_CLAUSE_ALIGNED:
+         clauses = cp_parser_omp_clause_aligned (parser, clauses);
+         c_name = "aligned";
+         break;
+       case PRAGMA_OMP_CLAUSE_LINEAR:
+         clauses = cp_parser_omp_clause_linear (parser, clauses);
+         c_name = "linear";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEPEND:
+         clauses = cp_parser_omp_clause_depend (parser, clauses);
+         c_name = "depend";
+         break;
+       case PRAGMA_OMP_CLAUSE_MAP:
+         clauses = cp_parser_omp_clause_map (parser, clauses);
+         c_name = "map";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEVICE:
+         clauses = cp_parser_omp_clause_device (parser, clauses,
+                                                token->location);
+         c_name = "device";
+         break;
+       case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
+         clauses = cp_parser_omp_clause_dist_schedule (parser, clauses,
+                                                       token->location);
+         c_name = "dist_schedule";
+         break;
+       case PRAGMA_OMP_CLAUSE_PROC_BIND:
+         clauses = cp_parser_omp_clause_proc_bind (parser, clauses,
+                                                   token->location);
+         c_name = "proc_bind";
+         break;
+       case PRAGMA_OMP_CLAUSE_SAFELEN:
+         clauses = cp_parser_omp_clause_safelen (parser, clauses,
+                                                 token->location);
+         c_name = "safelen";
+         break;
+       case PRAGMA_OMP_CLAUSE_SIMDLEN:
+         clauses = cp_parser_omp_clause_simdlen (parser, clauses,
+                                                 token->location);
+         c_name = "simdlen";
+         break;
+       default:
+         cp_parser_error (parser, "expected %<#pragma omp%> clause");
+         goto saw_error;
+       }
+       first = false;
+       if (((mask >> c_kind) & 1) == 0)
+       {
+         /* Remove the invalid clause(s) from the list to avoid
+            confusing the rest of the compiler.  */
+         clauses = prev;
+         error_at (token->location, "%qs is not valid for %qs", c_name, where);
+       }
+     }
+  saw_error:
+   cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+   if (finish_p)
+     return 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
+    cp_parser_statement calls add_stmt.  */
+ static unsigned
+ cp_parser_begin_omp_structured_block (cp_parser *parser)
+ {
+   unsigned save = parser->in_statement;
+   /* Only move the values to IN_OMP_BLOCK if they weren't false.
+      This preserves the "not within loop or switch" style error messages
+      for nonsense cases like
+       void foo() {
+       #pragma omp single
+         break;
+       }
+   */
+   if (parser->in_statement)
+     parser->in_statement = IN_OMP_BLOCK;
+   return save;
+ }
+ static void
+ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
+ {
+   parser->in_statement = save;
+ }
+ static tree
+ cp_parser_omp_structured_block (cp_parser *parser)
+ {
+   tree stmt = begin_omp_structured_block ();
+   unsigned int save = cp_parser_begin_omp_structured_block (parser);
+   cp_parser_statement (parser, NULL_TREE, false, NULL);
+   cp_parser_end_omp_structured_block (parser, save);
+   return finish_omp_structured_block (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.  */
+ static void
+ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
+   tree rhs1 = NULL_TREE, orig_lhs;
+   enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+   bool structured_block = false;
+   bool seq_cst = false;
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+     {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       if (!strcmp (p, "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)
+       cp_lexer_consume_token (parser->lexer);
+     }
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+     {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       if (!strcmp (p, "seq_cst"))
+       {
+         seq_cst = true;
+         cp_lexer_consume_token (parser->lexer);
+       }
+     }
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   switch (code)
+     {
+     case OMP_ATOMIC_READ:
+     case NOP_EXPR: /* atomic write */
+       v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                     /*cast_p=*/false, NULL);
+       if (v == error_mark_node)
+       goto saw_error;
+       if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+       goto saw_error;
+       if (code == NOP_EXPR)
+       lhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+       else
+       lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                         /*cast_p=*/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 (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         structured_block = true;
+       }
+       else
+       {
+         v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                         /*cast_p=*/false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+           goto saw_error;
+       }
+     default:
+       break;
+     }
+ restart:
+   lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                   /*cast_p=*/false, NULL);
+   orig_lhs = lhs;
+   switch (TREE_CODE (lhs))
+     {
+     case ERROR_MARK:
+       goto saw_error;
+     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;
+     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;
+     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);
+             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 (cp_lexer_peek_token (parser->lexer)->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:
+         enum cp_parser_prec oprec;
+         cp_token *token;
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_parse_tentatively (parser);
+         rhs1 = cp_parser_simple_cast_expression (parser);
+         if (rhs1 == error_mark_node)
+           {
+             cp_parser_abort_tentative_parse (parser);
+             cp_parser_simple_cast_expression (parser);
+             goto saw_error;
+           }
+         token = cp_lexer_peek_token (parser->lexer);
+         if (token->type != CPP_SEMICOLON && !cp_tree_equal (lhs, rhs1))
+           {
+             cp_parser_abort_tentative_parse (parser);
+             cp_parser_parse_tentatively (parser);
+             rhs = cp_parser_binary_expression (parser, false, true,
+                                                PREC_NOT_OPERATOR, NULL);
+             if (rhs == error_mark_node)
+               {
+                 cp_parser_abort_tentative_parse (parser);
+                 cp_parser_binary_expression (parser, false, true,
+                                              PREC_NOT_OPERATOR, NULL);
+                 goto saw_error;
+               }
+             switch (TREE_CODE (rhs))
+               {
+               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 (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)))
+                   {
+                     if (cp_parser_parse_definitely (parser))
+                       {
+                         opcode = TREE_CODE (rhs);
+                         rhs1 = TREE_OPERAND (rhs, 0);
+                         rhs = TREE_OPERAND (rhs, 1);
+                         goto stmt_done;
+                       }
+                     else
+                       goto saw_error;
+                   }
+                 break;
+               default:
+                 break;
+               }
+             cp_parser_abort_tentative_parse (parser);
+             if (structured_block && code == OMP_ATOMIC_CAPTURE_OLD)
+               {
+                 rhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+                 if (rhs == error_mark_node)
+                   goto saw_error;
+                 opcode = NOP_EXPR;
+                 rhs1 = NULL_TREE;
+                 goto stmt_done;
+               }
+             cp_parser_error (parser,
+                              "invalid form of %<#pragma omp atomic%>");
+             goto saw_error;
+           }
+         if (!cp_parser_parse_definitely (parser))
+           goto saw_error;
+         switch (token->type)
+           {
+           case CPP_SEMICOLON:
+             if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+               {
+                 code = OMP_ATOMIC_CAPTURE_OLD;
+                 v = lhs;
+                 lhs = NULL_TREE;
+                 lhs1 = rhs1;
+                 rhs1 = NULL_TREE;
+                 cp_lexer_consume_token (parser->lexer);
+                 goto restart;
+               }
+             else if (structured_block)
+               {
+                 opcode = NOP_EXPR;
+                 rhs = rhs1;
+                 rhs1 = NULL_TREE;
+                 goto stmt_done;
+               }
+             cp_parser_error (parser,
+                              "invalid form of %<#pragma omp atomic%>");
+             goto saw_error;
+           case CPP_MULT:
+             opcode = MULT_EXPR;
+             break;
+           case CPP_DIV:
+             opcode = TRUNC_DIV_EXPR;
+             break;
+           case CPP_PLUS:
+             opcode = PLUS_EXPR;
+             break;
+           case CPP_MINUS:
+             opcode = MINUS_EXPR;
+             break;
+           case CPP_LSHIFT:
+             opcode = LSHIFT_EXPR;
+             break;
+           case CPP_RSHIFT:
+             opcode = RSHIFT_EXPR;
+             break;
+           case CPP_AND:
+             opcode = BIT_AND_EXPR;
+             break;
+           case CPP_OR:
+             opcode = BIT_IOR_EXPR;
+             break;
+           case CPP_XOR:
+             opcode = BIT_XOR_EXPR;
+             break;
+           default:
+             cp_parser_error (parser,
+                              "invalid operator for %<#pragma omp atomic%>");
+             goto saw_error;
+           }
+         oprec = TOKEN_PRECEDENCE (token);
+         gcc_assert (oprec != PREC_NOT_OPERATOR);
+         if (commutative_tree_code (opcode))
+           oprec = (enum cp_parser_prec) (oprec - 1);
+         cp_lexer_consume_token (parser->lexer);
+         rhs = cp_parser_binary_expression (parser, false, false,
+                                            oprec, NULL);
+         if (rhs == error_mark_node)
+           goto saw_error;
+         goto stmt_done;
+         /* FALLTHROUGH */
+       default:
+         cp_parser_error (parser,
+                          "invalid operator for %<#pragma omp atomic%>");
+         goto saw_error;
+       }
+       cp_lexer_consume_token (parser->lexer);
+       rhs = cp_parser_expression (parser, false, NULL);
+       if (rhs == error_mark_node)
+       goto saw_error;
+       break;
+     }
+ stmt_done:
+   if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+     {
+       if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+       goto saw_error;
+       v = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                     /*cast_p=*/false, NULL);
+       if (v == error_mark_node)
+       goto saw_error;
+       if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+       goto saw_error;
+       lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                        /*cast_p=*/false, NULL);
+       if (lhs1 == error_mark_node)
+       goto saw_error;
+     }
+   if (structured_block)
+     {
+       cp_parser_consume_semicolon_at_end_of_statement (parser);
+       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+     }
+ done:
+   finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
+   if (!structured_block)
+     cp_parser_consume_semicolon_at_end_of_statement (parser);
+   return;
+  saw_error:
+   cp_parser_skip_to_end_of_block_or_statement (parser);
+   if (structured_block)
+     {
+       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+         cp_lexer_consume_token (parser->lexer);
+       else if (code == OMP_ATOMIC_CAPTURE_NEW)
+       {
+         cp_parser_skip_to_end_of_block_or_statement (parser);
+         if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+           cp_lexer_consume_token (parser->lexer);
+       }
+     }
+ }
+ /* OpenMP 2.5:
+    # pragma omp barrier new-line  */
+ static void
+ cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok)
+ {
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   finish_omp_barrier ();
+ }
+ /* OpenMP 2.5:
+    # pragma omp critical [(name)] new-line
+      structured-block  */
+ static tree
+ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree stmt, name = NULL;
+   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+     {
+       cp_lexer_consume_token (parser->lexer);
+       name = cp_parser_identifier (parser);
+       if (name == error_mark_node
+         || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+       if (name == error_mark_node)
+       name = NULL;
+     }
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   stmt = cp_parser_omp_structured_block (parser);
+   return c_finish_omp_critical (input_location, stmt, name);
+ }
+ /* OpenMP 2.5:
+    # pragma omp flush flush-vars[opt] new-line
+    flush-vars:
+      ( variable-list ) */
+ static void
+ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
+ {
+   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+     (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   finish_omp_flush ();
+ }
+ /* Helper function, to parse omp for increment expression.  */
+ static tree
+ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+ {
+   tree cond = cp_parser_binary_expression (parser, false, true,
+                                          PREC_NOT_OPERATOR, NULL);
+   if (cond == error_mark_node
+       || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+     {
+       cp_parser_skip_to_end_of_statement (parser);
+       return error_mark_node;
+     }
+   switch (TREE_CODE (cond))
+     {
+     case GT_EXPR:
+     case GE_EXPR:
+     case LT_EXPR:
+     case LE_EXPR:
+       break;
+     default:
+       return error_mark_node;
+     }
+   /* If decl is an iterator, preserve LHS and RHS of the relational
+      expr until finish_omp_for.  */
+   if (decl
+       && (type_dependent_expression_p (decl)
+         || CLASS_TYPE_P (TREE_TYPE (decl))))
+     return cond;
+   return build_x_binary_op (input_location, TREE_CODE (cond),
+                           TREE_OPERAND (cond, 0), ERROR_MARK,
+                           TREE_OPERAND (cond, 1), ERROR_MARK,
+                           /*overload=*/NULL, tf_warning_or_error);
+ }
+ /* Helper function, to parse omp for increment expression.  */
+ static tree
+ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
+ {
+   cp_token *token = cp_lexer_peek_token (parser->lexer);
+   enum tree_code op;
+   tree lhs, rhs;
+   cp_id_kind idk;
+   bool decl_first;
+   if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+     {
+       op = (token->type == CPP_PLUS_PLUS
+           ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
+       cp_lexer_consume_token (parser->lexer);
+       lhs = cp_parser_simple_cast_expression (parser);
+       if (lhs != decl)
+       return error_mark_node;
+       return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+     }
+   lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+   if (lhs != decl)
+     return error_mark_node;
+   token = cp_lexer_peek_token (parser->lexer);
+   if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+     {
+       op = (token->type == CPP_PLUS_PLUS
+           ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
+       cp_lexer_consume_token (parser->lexer);
+       return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+     }
+   op = cp_parser_assignment_operator_opt (parser);
+   if (op == ERROR_MARK)
+     return error_mark_node;
+   if (op != NOP_EXPR)
+     {
+       rhs = cp_parser_assignment_expression (parser, false, NULL);
+       rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
+       return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+     }
+   lhs = cp_parser_binary_expression (parser, false, false,
+                                    PREC_ADDITIVE_EXPRESSION, NULL);
+   token = cp_lexer_peek_token (parser->lexer);
+   decl_first = lhs == decl;
+   if (decl_first)
+     lhs = NULL_TREE;
+   if (token->type != CPP_PLUS
+       && token->type != CPP_MINUS)
+     return error_mark_node;
+   do
+     {
+       op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
+       cp_lexer_consume_token (parser->lexer);
+       rhs = cp_parser_binary_expression (parser, false, false,
+                                        PREC_ADDITIVE_EXPRESSION, NULL);
+       token = cp_lexer_peek_token (parser->lexer);
+       if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
+       {
+         if (lhs == NULL_TREE)
+           {
+             if (op == PLUS_EXPR)
+               lhs = rhs;
+             else
+               lhs = build_x_unary_op (input_location, NEGATE_EXPR, rhs,
+                                       tf_warning_or_error);
+           }
+         else
+           lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
+                                    ERROR_MARK, NULL, tf_warning_or_error);
+       }
+     }
+   while (token->type == CPP_PLUS || token->type == CPP_MINUS);
+   if (!decl_first)
+     {
+       if (rhs != decl || op == MINUS_EXPR)
+       return error_mark_node;
+       rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
+     }
+   else
+     rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+   return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+ }
+ /* Parse the restricted form of the for statement allowed by OpenMP.  */
+ static tree
+ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
+                       tree *cclauses)
+ {
+   tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
+   tree real_decl, initv, condv, incrv, declv;
+   tree this_pre_body, cl;
+   location_t loc_first;
+   bool collapse_err = false;
+   int i, collapse = 1, nbraces = 0;
+   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_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
++      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);
+   loc_first = cp_lexer_peek_token (parser->lexer)->location;
+   for (i = 0; i < collapse; i++)
+     {
+       int bracecount = 0;
+       bool add_private_clause = false;
+       location_t loc;
+       if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+       {
+         cp_parser_error (parser, "for statement expected");
+         return NULL;
+       }
+       loc = cp_lexer_consume_token (parser->lexer)->location;
+       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+       return NULL;
+       init = decl = real_decl = NULL;
+       this_pre_body = push_stmt_list ();
+       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+            init-expr:
+                      var = lb
+                      integer-type var = lb
+                      random-access-iterator-type var = lb
+                      pointer-type var = lb
+         */
+         cp_decl_specifier_seq type_specifiers;
+         /* First, try to parse as an initialized declaration.  See
+            cp_parser_condition, from whence the bulk of this is copied.  */
+         cp_parser_parse_tentatively (parser);
+         cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+                                       /*is_trailing_return=*/false,
+                                       &type_specifiers);
+         if (cp_parser_parse_definitely (parser))
+           {
+             /* If parsing a type specifier seq succeeded, then this
+                MUST be a initialized declaration.  */
+             tree asm_specification, attributes;
+             cp_declarator *declarator;
+             declarator = cp_parser_declarator (parser,
+                                                CP_PARSER_DECLARATOR_NAMED,
+                                                /*ctor_dtor_or_conv_p=*/NULL,
+                                                /*parenthesized_p=*/NULL,
+                                                /*member_p=*/false);
+             attributes = cp_parser_attributes_opt (parser);
+             asm_specification = cp_parser_asm_specification_opt (parser);
+             if (declarator == cp_error_declarator) 
+               cp_parser_skip_to_end_of_statement (parser);
+             else 
+               {
+                 tree pushed_scope, auto_node;
+                 decl = start_decl (declarator, &type_specifiers,
+                                    SD_INITIALIZED, attributes,
+                                    /*prefix_attributes=*/NULL_TREE,
+                                    &pushed_scope);
+                 auto_node = type_uses_auto (TREE_TYPE (decl));
+                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+                   {
+                     if (cp_lexer_next_token_is (parser->lexer, 
+                                                 CPP_OPEN_PAREN))
+                       error ("parenthesized initialization is not allowed in "
+                              "OpenMP %<for%> loop");
+                     else
+                       /* Trigger an error.  */
+                       cp_parser_require (parser, CPP_EQ, RT_EQ);
+                     init = error_mark_node;
+                     cp_parser_skip_to_end_of_statement (parser);
+                   }
+                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
+                          || type_dependent_expression_p (decl)
+                          || auto_node)
+                   {
+                     bool is_direct_init, is_non_constant_init;
+                     init = cp_parser_initializer (parser,
+                                                   &is_direct_init,
+                                                   &is_non_constant_init);
+                     if (auto_node)
+                       {
+                         TREE_TYPE (decl)
+                           = do_auto_deduction (TREE_TYPE (decl), init,
+                                                auto_node);
+                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
+                             && !type_dependent_expression_p (decl))
+                           goto non_class;
+                       }
+                     
+                     cp_finish_decl (decl, init, !is_non_constant_init,
+                                     asm_specification,
+                                     LOOKUP_ONLYCONVERTING);
+                     if (CLASS_TYPE_P (TREE_TYPE (decl)))
+                       {
+                         vec_safe_push (for_block, this_pre_body);
+                         init = NULL_TREE;
+                       }
+                     else
+                       init = pop_stmt_list (this_pre_body);
+                     this_pre_body = NULL_TREE;
+                   }
+                 else
+                   {
+                     /* Consume '='.  */
+                     cp_lexer_consume_token (parser->lexer);
+                     init = cp_parser_assignment_expression (parser, false, NULL);
+                   non_class:
+                     if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+                       init = error_mark_node;
+                     else
+                       cp_finish_decl (decl, NULL_TREE,
+                                       /*init_const_expr_p=*/false,
+                                       asm_specification,
+                                       LOOKUP_ONLYCONVERTING);
+                   }
+                 if (pushed_scope)
+                   pop_scope (pushed_scope);
+               }
+           }
+         else 
+           {
+             cp_id_kind idk;
+             /* If parsing a type specifier sequence failed, then
+                this MUST be a simple expression.  */
+             cp_parser_parse_tentatively (parser);
+             decl = cp_parser_primary_expression (parser, false, false,
+                                                  false, &idk);
+             if (!cp_parser_error_occurred (parser)
+                 && decl
+                 && DECL_P (decl)
+                 && CLASS_TYPE_P (TREE_TYPE (decl)))
                {
-                 tree pushed_scope, auto_node;
+                 tree rhs;
+                 cp_parser_parse_definitely (parser);
+                 cp_parser_require (parser, CPP_EQ, RT_EQ);
+                 rhs = cp_parser_assignment_expression (parser, false, NULL);
+                 finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
+                                                        decl, NOP_EXPR,
+                                                        rhs,
+                                                        tf_warning_or_error));
+                 add_private_clause = true;
+               }
+             else
+               {
+                 decl = NULL;
+                 cp_parser_abort_tentative_parse (parser);
+                 init = cp_parser_expression (parser, false, NULL);
+                 if (init)
+                   {
+                     if (TREE_CODE (init) == MODIFY_EXPR
+                         || TREE_CODE (init) == MODOP_EXPR)
+                       real_decl = TREE_OPERAND (init, 0);
+                   }
+               }
+           }
+       }
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+       if (this_pre_body)
+       {
+         this_pre_body = pop_stmt_list (this_pre_body);
+         if (pre_body)
+           {
+             tree t = pre_body;
+             pre_body = push_stmt_list ();
+             add_stmt (t);
+             add_stmt (this_pre_body);
+             pre_body = pop_stmt_list (pre_body);
+           }
+         else
+           pre_body = this_pre_body;
+       }
+       if (decl)
+       real_decl = decl;
+       if (cclauses != NULL
+         && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL
+         && real_decl != NULL_TREE)
+       {
+         tree *c;
+         for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
+           if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
+               && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               error_at (loc, "iteration variable %qD"
+                         " should not be firstprivate", real_decl);
+               *c = OMP_CLAUSE_CHAIN (*c);
+             }
+           else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
+                    && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                  change it to shared (decl) in OMP_PARALLEL_CLAUSES.  */
+               tree l = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
+               OMP_CLAUSE_DECL (l) = real_decl;
+               OMP_CLAUSE_CHAIN (l) = clauses;
+               CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
+               clauses = l;
+               OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+               CP_OMP_CLAUSE_INFO (*c) = NULL;
+               add_private_clause = false;
+             }
+           else
+             {
+               if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
+                   && OMP_CLAUSE_DECL (*c) == real_decl)
+                 add_private_clause = false;
+               c = &OMP_CLAUSE_CHAIN (*c);
+             }
+       }
+       if (add_private_clause)
+       {
+         tree c;
+         for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+           {
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+                 && OMP_CLAUSE_DECL (c) == decl)
+               break;
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error_at (loc, "iteration variable %qD "
+                         "should not be firstprivate",
+                         decl);
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error_at (loc, "iteration variable %qD should not be reduction",
+                         decl);
+           }
+         if (c == NULL)
+           {
+             c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
+             OMP_CLAUSE_DECL (c) = decl;
+             c = finish_omp_clauses (c);
+             if (c)
+               {
+                 OMP_CLAUSE_CHAIN (c) = clauses;
+                 clauses = c;
+               }
+           }
+       }
+       cond = NULL;
+       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       cond = cp_parser_omp_for_cond (parser, decl);
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+       incr = NULL;
+       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+       {
+         /* If decl is an iterator, preserve the operator on decl
+            until finish_omp_for.  */
+         if (real_decl
+             && ((processing_template_decl
+                  && !POINTER_TYPE_P (TREE_TYPE (real_decl)))
+                 || CLASS_TYPE_P (TREE_TYPE (real_decl))))
+           incr = cp_parser_omp_for_incr (parser, real_decl);
+         else
+           incr = cp_parser_expression (parser, false, NULL);
+         if (CAN_HAVE_LOCATION_P (incr) && !EXPR_HAS_LOCATION (incr))
+           SET_EXPR_LOCATION (incr, input_location);
+       }
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+       TREE_VEC_ELT (declv, i) = decl;
+       TREE_VEC_ELT (initv, i) = init;
+       TREE_VEC_ELT (condv, i) = cond;
+       TREE_VEC_ELT (incrv, i) = incr;
+       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.  */
+       cp_parser_parse_tentatively (parser);
+       do
+       {
+         if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+           break;
+         else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             bracecount++;
+           }
+         else if (bracecount
+                  && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           {
+             loc = cp_lexer_peek_token (parser->lexer)->location;
+             error_at (loc, "not enough collapsed for loops");
+             collapse_err = true;
+             cp_parser_abort_tentative_parse (parser);
+             declv = NULL_TREE;
+             break;
+           }
+       }
+       while (1);
+       if (declv)
+       {
+         cp_parser_parse_definitely (parser);
+         nbraces += bracecount;
+       }
+     }
+   /* Note that we saved the original contents of this flag when we entered
+      the structured block, and so we don't need to re-save it here.  */
+   parser->in_statement = IN_OMP_FOR;
+   /* Note that the grammar doesn't call for a structured block here,
+      though the loop as a whole is a structured block.  */
+   body = push_stmt_list ();
+   cp_parser_statement (parser, NULL_TREE, false, NULL);
+   body = pop_stmt_list (body);
+   if (declv == NULL_TREE)
+     ret = NULL_TREE;
+   else
+     ret = finish_omp_for (loc_first, code, declv, initv, condv, incrv, body,
+                         pre_body, clauses);
+   while (nbraces)
+     {
+       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         nbraces--;
+       }
+       else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
+       else
+       {
+         if (!collapse_err)
+           {
+             error_at (cp_lexer_peek_token (parser->lexer)->location,
+                       "collapsed loops not perfectly nested");
+           }
+         collapse_err = true;
+         cp_parser_statement_seq_opt (parser, NULL);
+         if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+           break;
+       }
+     }
+   while (!for_block->is_empty ())
+     add_stmt (pop_stmt_list (for_block->pop ()));
+   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
+ cp_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] = finish_omp_clauses (cclauses[i]);
+ }
+ /* OpenMP 4.0:
+    #pragma omp simd simd-clause[optseq] new-line
+      for-loop  */
+ #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
+ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
+                   char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree clauses, sb, ret;
+   unsigned int save;
+   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
  
-                 decl = start_decl (declarator, &type_specifiers,
-                                    SD_INITIALIZED, attributes,
-                                    /*prefix_attributes=*/NULL_TREE,
-                                    &pushed_scope);
+   strcat (p_name, " simd");
+   mask |= OMP_SIMD_CLAUSE_MASK;
+   mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
  
-                 auto_node = type_uses_auto (TREE_TYPE (decl));
-                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
-                   {
-                     if (cp_lexer_next_token_is (parser->lexer, 
-                                                 CPP_OPEN_PAREN))
-                       error ("parenthesized initialization is not allowed in "
-                              "OpenMP %<for%> loop");
-                     else
-                       /* Trigger an error.  */
-                       cp_parser_require (parser, CPP_EQ, RT_EQ);
+   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+                                      cclauses == NULL);
+   if (cclauses)
+     {
+       cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+       clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+     }
  
-                     init = error_mark_node;
-                     cp_parser_skip_to_end_of_statement (parser);
-                   }
-                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
-                          || type_dependent_expression_p (decl)
-                          || auto_node)
-                   {
-                     bool is_direct_init, is_non_constant_init;
+   sb = begin_omp_structured_block ();
+   save = cp_parser_begin_omp_structured_block (parser);
  
-                     init = cp_parser_initializer (parser,
-                                                   &is_direct_init,
-                                                   &is_non_constant_init);
+   ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses);
+   cp_parser_end_omp_structured_block (parser, save);
+   add_stmt (finish_omp_structured_block (sb));
+   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  */
+ #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_NOWAIT)       \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+ static tree
+ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
+                  char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree clauses, sb, ret;
+   unsigned int save;
+   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+   strcat (p_name, " for");
+   mask |= OMP_FOR_CLAUSE_MASK;
+   if (cclauses)
+     mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+     {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       if (strcmp (p, "simd") == 0)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
+         cp_lexer_consume_token (parser->lexer);
+         sb = begin_omp_structured_block ();
+         save = cp_parser_begin_omp_structured_block (parser);
+         ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+                                   cclauses);
+         cp_parser_end_omp_structured_block (parser, save);
+         tree body = finish_omp_structured_block (sb);
+         if (ret == NULL)
+           return ret;
+         ret = make_node (OMP_FOR);
+         TREE_TYPE (ret) = void_type_node;
+         OMP_FOR_BODY (ret) = body;
+         OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+         SET_EXPR_LOCATION (ret, loc);
+         add_stmt (ret);
+         return ret;
+       }
+     }
+   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+                                      cclauses == NULL);
+   if (cclauses)
+     {
+       cp_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+       clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+     }
+   sb = begin_omp_structured_block ();
+   save = cp_parser_begin_omp_structured_block (parser);
+   ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses);
+   cp_parser_end_omp_structured_block (parser, save);
+   add_stmt (finish_omp_structured_block (sb));
+   return ret;
+ }
+ /* OpenMP 2.5:
+    # pragma omp master new-line
+      structured-block  */
+ static tree
+ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
+ {
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   return c_finish_omp_master (input_location,
+                             cp_parser_omp_structured_block (parser));
+ }
+ /* OpenMP 2.5:
+    # pragma omp ordered new-line
+      structured-block  */
+ static tree
+ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok)
+ {
+   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   return c_finish_omp_ordered (loc, cp_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  */
+ static tree
+ cp_parser_omp_sections_scope (cp_parser *parser)
+ {
+   tree stmt, substmt;
+   bool error_suppress = false;
+   cp_token *tok;
+   if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+     return NULL_TREE;
+   stmt = push_stmt_list ();
+   if (cp_lexer_peek_token (parser->lexer)->pragma_kind != PRAGMA_OMP_SECTION)
+     {
+       substmt = cp_parser_omp_structured_block (parser);
+       substmt = build1 (OMP_SECTION, void_type_node, substmt);
+       add_stmt (substmt);
+     }
+   while (1)
+     {
+       tok = cp_lexer_peek_token (parser->lexer);
+       if (tok->type == CPP_CLOSE_BRACE)
+       break;
+       if (tok->type == CPP_EOF)
+       break;
+       if (tok->pragma_kind == PRAGMA_OMP_SECTION)
+       {
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_require_pragma_eol (parser, tok);
+         error_suppress = false;
+       }
+       else if (!error_suppress)
+       {
+         cp_parser_error (parser, "expected %<#pragma omp section%> or %<}%>");
+         error_suppress = true;
+       }
+       substmt = cp_parser_omp_structured_block (parser);
+       substmt = build1 (OMP_SECTION, void_type_node, substmt);
+       add_stmt (substmt);
+     }
+   cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+   substmt = pop_stmt_list (stmt);
+   stmt = make_node (OMP_SECTIONS);
+   TREE_TYPE (stmt) = void_type_node;
+   OMP_SECTIONS_BODY (stmt) = substmt;
+   add_stmt (stmt);
+   return stmt;
+ }
+ /* OpenMP 2.5:
+    # pragma omp sections sections-clause[optseq] newline
+      sections-scope  */
+ #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
+ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
+                       char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree clauses, ret;
+   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+   strcat (p_name, " sections");
+   mask |= OMP_SECTIONS_CLAUSE_MASK;
+   if (cclauses)
+     mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+                                      cclauses == NULL);
+   if (cclauses)
+     {
+       cp_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+       clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+     }
+   ret = cp_parser_omp_sections_scope (parser);
+   if (ret)
+     OMP_SECTIONS_CLAUSES (ret) = clauses;
+   return ret;
+ }
+ /* 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
+    OpenMP 4.0:
+    # pragma parallel for simd parallel-for-simd-clause new-line */
+ #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
+ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
+                       char *p_name, omp_clause_mask mask, tree *cclauses)
+ {
+   tree stmt, clauses, block;
+   unsigned int save;
+   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+   strcat (p_name, " parallel");
+   mask |= OMP_PARALLEL_CLAUSE_MASK;
+   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+     {
+       tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+       if (cclauses == NULL)
+       cclauses = cclauses_buf;
+       cp_lexer_consume_token (parser->lexer);
+       block = begin_omp_parallel ();
+       save = cp_parser_begin_omp_structured_block (parser);
+       cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+       cp_parser_end_omp_structured_block (parser, save);
+       stmt = finish_omp_parallel (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);
+       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+       return NULL_TREE;
+     }
+   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+     {
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       if (strcmp (p, "sections") == 0)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         cclauses = cclauses_buf;
+         cp_lexer_consume_token (parser->lexer);
+         block = begin_omp_parallel ();
+         save = cp_parser_begin_omp_structured_block (parser);
+         cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses);
+         cp_parser_end_omp_structured_block (parser, save);
+         stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+                                     block);
+         OMP_PARALLEL_COMBINED (stmt) = 1;
+         return stmt;
+       }
+     }
+   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
+   block = begin_omp_parallel ();
+   save = cp_parser_begin_omp_structured_block (parser);
+   cp_parser_statement (parser, NULL_TREE, false, NULL);
+   cp_parser_end_omp_structured_block (parser, save);
+   stmt = finish_omp_parallel (clauses, block);
+   return stmt;
+ }
+ /* OpenMP 2.5:
+    # pragma omp single single-clause[optseq] new-line
+      structured-block  */
+ #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
+ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree stmt = make_node (OMP_SINGLE);
+   TREE_TYPE (stmt) = void_type_node;
+   OMP_SINGLE_CLAUSES (stmt)
+     = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
+                                "#pragma omp single", pragma_tok);
+   OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser);
+   return add_stmt (stmt);
+ }
+ /* OpenMP 3.0:
+    # pragma omp task task-clause[optseq] new-line
+      structured-block  */
+ #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))
+ static tree
+ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree clauses, block;
+   unsigned int save;
+   clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                      "#pragma omp task", pragma_tok);
+   block = begin_omp_task ();
+   save = cp_parser_begin_omp_structured_block (parser);
+   cp_parser_statement (parser, NULL_TREE, false, NULL);
+   cp_parser_end_omp_structured_block (parser, save);
+   return finish_omp_task (clauses, block);
+ }
  
-                     if (auto_node)
-                       {
-                         TREE_TYPE (decl)
-                           = do_auto_deduction (TREE_TYPE (decl), init,
-                                                auto_node);
+ /* OpenMP 3.0:
+    # pragma omp taskwait new-line  */
  
-                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
-                             && !type_dependent_expression_p (decl))
-                           goto non_class;
-                       }
-                     
-                     cp_finish_decl (decl, init, !is_non_constant_init,
-                                     asm_specification,
-                                     LOOKUP_ONLYCONVERTING);
-                     if (CLASS_TYPE_P (TREE_TYPE (decl)))
-                       {
-                         vec_safe_push (for_block, this_pre_body);
-                         init = NULL_TREE;
-                       }
-                     else
-                       init = pop_stmt_list (this_pre_body);
-                     this_pre_body = NULL_TREE;
-                   }
-                 else
-                   {
-                     /* Consume '='.  */
-                     cp_lexer_consume_token (parser->lexer);
-                     init = cp_parser_assignment_expression (parser, false, NULL);
+ static void
+ cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
+ {
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   finish_omp_taskwait ();
+ }
  
-                   non_class:
-                     if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
-                       init = error_mark_node;
-                     else
-                       cp_finish_decl (decl, NULL_TREE,
-                                       /*init_const_expr_p=*/false,
-                                       asm_specification,
-                                       LOOKUP_ONLYCONVERTING);
-                   }
+ /* OpenMP 3.1:
+    # pragma omp taskyield new-line  */
  
-                 if (pushed_scope)
-                   pop_scope (pushed_scope);
-               }
-           }
-         else 
-           {
-             cp_id_kind idk;
-             /* If parsing a type specifier sequence failed, then
-                this MUST be a simple expression.  */
-             cp_parser_parse_tentatively (parser);
-             decl = cp_parser_primary_expression (parser, false, false,
-                                                  false, &idk);
-             if (!cp_parser_error_occurred (parser)
-                 && decl
-                 && DECL_P (decl)
-                 && CLASS_TYPE_P (TREE_TYPE (decl)))
-               {
-                 tree rhs;
+ static void
+ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
+ {
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   finish_omp_taskyield ();
+ }
  
-                 cp_parser_parse_definitely (parser);
-                 cp_parser_require (parser, CPP_EQ, RT_EQ);
-                 rhs = cp_parser_assignment_expression (parser, false, NULL);
-                 finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
-                                                        decl, NOP_EXPR,
-                                                        rhs,
-                                                        tf_warning_or_error));
-                 add_private_clause = true;
-               }
-             else
-               {
-                 decl = NULL;
-                 cp_parser_abort_tentative_parse (parser);
-                 init = cp_parser_expression (parser, false, NULL);
-                 if (init)
-                   {
-                     if (TREE_CODE (init) == MODIFY_EXPR
-                         || TREE_CODE (init) == MODOP_EXPR)
-                       real_decl = TREE_OPERAND (init, 0);
-                   }
-               }
-           }
-       }
-       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-       if (this_pre_body)
-       {
-         this_pre_body = pop_stmt_list (this_pre_body);
-         if (pre_body)
-           {
-             tree t = pre_body;
-             pre_body = push_stmt_list ();
-             add_stmt (t);
-             add_stmt (this_pre_body);
-             pre_body = pop_stmt_list (pre_body);
-           }
-         else
-           pre_body = this_pre_body;
-       }
+ /* OpenMP 4.0:
+    # pragma omp taskgroup new-line
+      structured-block  */
  
-       if (decl)
-       real_decl = decl;
-       if (par_clauses != NULL && real_decl != NULL_TREE)
-       {
-         tree *c;
-         for (c = par_clauses; *c ; )
-           if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
-               && OMP_CLAUSE_DECL (*c) == real_decl)
-             {
-               error_at (loc, "iteration variable %qD"
-                         " should not be firstprivate", real_decl);
-               *c = OMP_CLAUSE_CHAIN (*c);
-             }
-           else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
-                    && OMP_CLAUSE_DECL (*c) == real_decl)
-             {
-               /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
-                  change it to shared (decl) in OMP_PARALLEL_CLAUSES.  */
-               tree l = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
-               OMP_CLAUSE_DECL (l) = real_decl;
-               OMP_CLAUSE_CHAIN (l) = clauses;
-               CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
-               clauses = l;
-               OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
-               CP_OMP_CLAUSE_INFO (*c) = NULL;
-               add_private_clause = false;
-             }
-           else
-             {
-               if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
-                   && OMP_CLAUSE_DECL (*c) == real_decl)
-                 add_private_clause = false;
-               c = &OMP_CLAUSE_CHAIN (*c);
-             }
-       }
+ static tree
+ cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok)
+ {
+   cp_parser_require_pragma_eol (parser, pragma_tok);
+   return c_finish_omp_taskgroup (input_location,
+                                cp_parser_omp_structured_block (parser));
+ }
  
-       if (add_private_clause)
-       {
-         tree c;
-         for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
-           {
-             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
-                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
-                 && OMP_CLAUSE_DECL (c) == decl)
-               break;
-             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
-                      && OMP_CLAUSE_DECL (c) == decl)
-               error_at (loc, "iteration variable %qD "
-                         "should not be firstprivate",
-                         decl);
-             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
-                      && OMP_CLAUSE_DECL (c) == decl)
-               error_at (loc, "iteration variable %qD should not be reduction",
-                         decl);
-           }
-         if (c == NULL)
-           {
-             c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
-             OMP_CLAUSE_DECL (c) = decl;
-             c = finish_omp_clauses (c);
-             if (c)
-               {
-                 OMP_CLAUSE_CHAIN (c) = clauses;
-                 clauses = c;
-               }
-           }
-       }
  
-       cond = NULL;
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       cond = cp_parser_omp_for_cond (parser, decl);
-       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+ /* OpenMP 2.5:
+    # pragma omp threadprivate (variable-list) */
  
-       incr = NULL;
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-       {
-         /* If decl is an iterator, preserve the operator on decl
-            until finish_omp_for.  */
-         if (real_decl
-             && ((processing_template_decl
-                  && !POINTER_TYPE_P (TREE_TYPE (real_decl)))
-                 || CLASS_TYPE_P (TREE_TYPE (real_decl))))
-           incr = cp_parser_omp_for_incr (parser, real_decl);
-         else
-           incr = cp_parser_expression (parser, false, NULL);
-         if (CAN_HAVE_LOCATION_P (incr) && !EXPR_HAS_LOCATION (incr))
-           SET_EXPR_LOCATION (incr, input_location);
-       }
+ static void
+ cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree vars;
  
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-                                              /*or_comma=*/false,
-                                              /*consume_paren=*/true);
+   vars = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+   cp_parser_require_pragma_eol (parser, pragma_tok);
  
-       TREE_VEC_ELT (declv, i) = decl;
-       TREE_VEC_ELT (initv, i) = init;
-       TREE_VEC_ELT (condv, i) = cond;
-       TREE_VEC_ELT (incrv, i) = incr;
+   finish_omp_threadprivate (vars);
+ }
  
-       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.  */
-       cp_parser_parse_tentatively (parser);
-       do
-       {
-         if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
-           break;
-         else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-           {
-             cp_lexer_consume_token (parser->lexer);
-             bracecount++;
-           }
-         else if (bracecount
-                  && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-           cp_lexer_consume_token (parser->lexer);
-         else
-           {
-             loc = cp_lexer_peek_token (parser->lexer)->location;
-             error_at (loc, "not enough collapsed for loops");
-             collapse_err = true;
-             cp_parser_abort_tentative_parse (parser);
-             declv = NULL_TREE;
-             break;
-           }
-       }
-       while (1);
+ #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))
  
-       if (declv)
-       {
-         cp_parser_parse_definitely (parser);
-         nbraces += bracecount;
-       }
-     }
+ static void
+ cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree clauses = cp_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
+                                           "#pragma omp cancel", pragma_tok);
+   finish_omp_cancel (clauses);
+ }
  
-   /* Note that we saved the original contents of this flag when we entered
-      the structured block, and so we don't need to re-save it here.  */
-   parser->in_statement = IN_OMP_FOR;
+ /* OpenMP 4.0:
+    # pragma omp cancellation point cancelpt-clause[optseq] new-line  */
  
-   /* Note that the grammar doesn't call for a structured block here,
-      though the loop as a whole is a structured block.  */
-   body = push_stmt_list ();
-   cp_parser_statement (parser, NULL_TREE, false, NULL);
-   body = pop_stmt_list (body);
+ #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))
  
-   if (declv == NULL_TREE)
-     ret = NULL_TREE;
-   else
-     ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
-                         pre_body, clauses);
+ static void
+ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok)
+ {
+   tree clauses;
+   bool point_seen = false;
  
-   while (nbraces)
+   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
      {
-       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+       const char *p = IDENTIFIER_POINTER (id);
+       if (strcmp (p, "point") == 0)
        {
          cp_lexer_consume_token (parser->lexer);
-         nbraces--;
-       }
-       else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-       cp_lexer_consume_token (parser->lexer);
-       else
-       {
-         if (!collapse_err)
-           {
-             error_at (cp_lexer_peek_token (parser->lexer)->location,
-                       "collapsed loops not perfectly nested");
-           }
-         collapse_err = true;
-         cp_parser_statement_seq_opt (parser, NULL);
-         if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
-           break;
+         point_seen = true;
        }
      }
+   if (!point_seen)
+     {
+       cp_parser_error (parser, "expected %<point%>");
+       cp_parser_require_pragma_eol (parser, pragma_tok);
+       return;
+     }
  
-   while (!for_block->is_empty ())
-     add_stmt (pop_stmt_list (for_block->pop ()));
-   release_tree_vector (for_block);
-   return ret;
+   clauses = cp_parser_omp_all_clauses (parser,
+                                      OMP_CANCELLATION_POINT_CLAUSE_MASK,
+                                      "#pragma omp cancellation point",
+                                      pragma_tok);
+   finish_omp_cancellation_point (clauses);
  }
  
- /* OpenMP 2.5:
-    #pragma omp for for-clause[optseq] new-line
+ /* OpenMP 4.0:
+    #pragma omp distribute distribute-clause[optseq] new-line
       for-loop  */
  
- #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_NOWAIT)              \
-       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
+ #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
- cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
+ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
+                         char *p_name, omp_clause_mask mask, tree *cclauses)
  {
    tree clauses, sb, ret;
    unsigned int save;
Simple merge
Simple merge
diff --cc gcc/cse.c
Simple merge
diff --cc gcc/cselib.c
Simple merge
diff --cc gcc/dbxout.c
Simple merge
diff --cc gcc/defaults.h
Simple merge
Simple merge
Simple merge
diff --cc gcc/doc/tm.texi
Simple merge
diff --cc gcc/dojump.c
Simple merge
diff --cc gcc/dwarf2out.c
Simple merge
diff --cc gcc/emit-rtl.c
Simple merge
diff --cc gcc/except.c
Simple merge
diff --cc gcc/expmed.c
@@@ -54,7 -54,8 +54,7 @@@ static void store_split_bit_field (rtx
                                   rtx);
  static rtx extract_fixed_bit_field (enum machine_mode, rtx,
                                    unsigned HOST_WIDE_INT,
-                                   unsigned HOST_WIDE_INT, rtx, int, bool);
+                                   unsigned HOST_WIDE_INT, rtx, int);
 -static rtx mask_rtx (enum machine_mode, int, int, int);
  static rtx lshift_value (enum machine_mode, unsigned HOST_WIDE_INT, int);
  static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
                                    unsigned HOST_WIDE_INT, int);
diff --cc gcc/expr.c
Simple merge
diff --cc gcc/expr.h
Simple merge
diff --cc gcc/final.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/function.c
Simple merge
diff --cc gcc/gcse.c
Simple merge
diff --cc gcc/genemit.c
Simple merge
diff --cc gcc/gengenrtl.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/gengtype.c
Simple merge
diff --cc gcc/genmodes.c
Simple merge
diff --cc gcc/genpreds.c
Simple merge
diff --cc gcc/genrecog.c
Simple merge
Simple merge
@@@ -2801,14 -2820,16 +2821,14 @@@ fold_array_ctor_reference (tree type, t
        /* Static constructors for variably sized objects makes no sense.  */
        gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
        index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
 -      low_bound = tree_to_double_int (TYPE_MIN_VALUE (domain_type));
 +      low_bound = TYPE_MIN_VALUE (domain_type);
      }
    else
 -    low_bound = double_int_zero;
 +    low_bound = 0;
    /* Static constructors for variably sized objects makes no sense.  */
-   gcc_assert (TREE_CODE(TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))))
+   gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))))
              == INTEGER_CST);
 -  elt_size =
 -    tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))));
 -
 +  elt_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor)));
  
    /* We can handle only constantly sized accesses that are known to not
       be larger than size of array element.  */
@@@ -3303,3 -3322,125 +3323,123 @@@ gimple_val_nonnegative_real_p (tree val
  
    return false;
  }
 -        && host_integerp (off, 1))
+ /* Given a pointer value OP0, return a simplified version of an
+    indirection through OP0, or NULL_TREE if no simplification is
+    possible.  Note that the resulting type may be different from
+    the type pointed to in the sense that it is still compatible
+    from the langhooks point of view. */
+ tree
+ gimple_fold_indirect_ref (tree t)
+ {
+   tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
+   tree sub = t;
+   tree subtype;
+   STRIP_NOPS (sub);
+   subtype = TREE_TYPE (sub);
+   if (!POINTER_TYPE_P (subtype))
+     return NULL_TREE;
+   if (TREE_CODE (sub) == ADDR_EXPR)
+     {
+       tree op = TREE_OPERAND (sub, 0);
+       tree optype = TREE_TYPE (op);
+       /* *&p => p */
+       if (useless_type_conversion_p (type, optype))
+         return op;
+       /* *(foo *)&fooarray => fooarray[0] */
+       if (TREE_CODE (optype) == ARRAY_TYPE
+         && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
+         && useless_type_conversion_p (type, TREE_TYPE (optype)))
+        {
+          tree type_domain = TYPE_DOMAIN (optype);
+          tree min_val = size_zero_node;
+          if (type_domain && TYPE_MIN_VALUE (type_domain))
+            min_val = TYPE_MIN_VALUE (type_domain);
+        if (TREE_CODE (min_val) == INTEGER_CST)
+          return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+        }
+       /* *(foo *)&complexfoo => __real__ complexfoo */
+       else if (TREE_CODE (optype) == COMPLEX_TYPE
+                && useless_type_conversion_p (type, TREE_TYPE (optype)))
+         return fold_build1 (REALPART_EXPR, type, op);
+       /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
+       else if (TREE_CODE (optype) == VECTOR_TYPE
+                && useless_type_conversion_p (type, TREE_TYPE (optype)))
+         {
+           tree part_width = TYPE_SIZE (type);
+           tree index = bitsize_int (0);
+           return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
+         }
+     }
+   /* *(p + CST) -> ...  */
+   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+     {
+       tree addr = TREE_OPERAND (sub, 0);
+       tree off = TREE_OPERAND (sub, 1);
+       tree addrtype;
+       STRIP_NOPS (addr);
+       addrtype = TREE_TYPE (addr);
+       /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
+       if (TREE_CODE (addr) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
 -          unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
++        && tree_fits_uhwi_p (off))
+       {
 -            = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
++          unsigned HOST_WIDE_INT offset = tree_to_uhwi (off);
+           tree part_width = TYPE_SIZE (type);
+           unsigned HOST_WIDE_INT part_widthi
 -                          build_int_cst_wide (ptype,
 -                                              TREE_INT_CST_LOW (off),
 -                                              TREE_INT_CST_HIGH (off)));
++            = tree_to_shwi (part_width) / BITS_PER_UNIT;
+           unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+           tree index = bitsize_int (indexi);
+           if (offset / part_widthi
+               <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+             return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
+                                 part_width, index);
+       }
+       /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
+       if (TREE_CODE (addr) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
+         {
+           tree size = TYPE_SIZE_UNIT (type);
+           if (tree_int_cst_equal (size, off))
+             return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
+         }
+       /* *(p + CST) -> MEM_REF <p, CST>.  */
+       if (TREE_CODE (addr) != ADDR_EXPR
+         || DECL_P (TREE_OPERAND (addr, 0)))
+       return fold_build2 (MEM_REF, type,
+                           addr,
++                          wide_int_to_tree (ptype, off));
+     }
+   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
+   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+       && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
+       && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
+     {
+       tree type_domain;
+       tree min_val = size_zero_node;
+       tree osub = sub;
+       sub = gimple_fold_indirect_ref (sub);
+       if (! sub)
+       sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub);
+       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+       if (type_domain && TYPE_MIN_VALUE (type_domain))
+         min_val = TYPE_MIN_VALUE (type_domain);
+       if (TREE_CODE (min_val) == INTEGER_CST)
+       return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+     }
+   return NULL_TREE;
+ }
@@@ -1628,9 -1725,44 +1725,44 @@@ dump_ssaname_info (pretty_printer *buff
        pp_string (buffer, "# ");
      }
  
 -      double_int min, max;
+   if (!POINTER_TYPE_P (TREE_TYPE (node))
+       && SSA_NAME_RANGE_INFO (node))
+     {
 -        pp_double_int (buffer, min, TYPE_UNSIGNED (TREE_TYPE (node)));
++      max_wide_int min, max;
+       value_range_type range_type = get_range_info (node, &min, &max);
+       if (range_type == VR_VARYING)
+       pp_printf (buffer, "# RANGE  VR_VARYING");
+       else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
+       {
+         pp_printf (buffer, "# RANGE ");
+         pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~");
 -        pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node)));
++        pp_wide_int (buffer, min, TYPE_SIGN (TREE_TYPE (node)));
+         pp_printf (buffer, ", ");
++        pp_wide_int (buffer, max, TYPE_SIGN (TREE_TYPE (node)));
+         pp_printf (buffer, "]");
+         newline_and_indent (buffer, spc);
+       }
+     }
+ }
+ /* Dump a PHI node PHI.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.
+    The caller is responsible for calling pp_flush on BUFFER to finalize
+    pretty printer.  */
+ static void
+ dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags)
+ {
+   size_t i;
+   tree lhs = gimple_phi_result (phi);
+   if (flags & TDF_ALIAS)
+     dump_ssaname_info (buffer, lhs, spc);
    if (flags & TDF_RAW)
-       dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
-                        gimple_phi_result (phi));
+     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
+                    gimple_phi_result (phi));
    else
      {
        dump_generic_node (buffer, lhs, spc, flags, false);
@@@ -48,8 -48,7 +48,8 @@@ along with GCC; see the file COPYING3
  #include "expmed.h"
  #include "params.h"
  #include "hash-table.h"
+ #include "tree-ssa-address.h"
 +#include "wide-int-print.h"
  \f
  /* Information about a strength reduction candidate.  Each statement
     in the candidate table represents an expression of one of the
@@@ -770,8 -770,16 +771,16 @@@ backtrace_base_for_ref (tree *pbase
    slsr_cand_t base_cand;
  
    STRIP_NOPS (base_in);
+   /* Strip off widening conversion(s) to handle cases where
+      e.g. 'B' is widened from an 'int' in order to calculate
+      a 64-bit address.  */
+   if (CONVERT_EXPR_P (base_in)
+       && legal_cast_p_1 (base_in, TREE_OPERAND (base_in, 0)))
+     base_in = get_unwidened (base_in, NULL_TREE);
    if (TREE_CODE (base_in) != SSA_NAME)
 -    return tree_to_double_int (integer_zero_node);
 +    return 0;
  
    base_cand = base_cand_from_table (base_in);
  
diff --cc gcc/gimple.c
Simple merge
diff --cc gcc/gimplify.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/godump.c
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/ipa-cp.c
Simple merge
Simple merge
diff --cc gcc/ipa-prop.c
@@@ -2194,8 -2194,13 +2194,13 @@@ ipa_intraprocedural_devirtualization (g
    if (!binfo)
      return NULL_TREE;
    token = OBJ_TYPE_REF_TOKEN (otr);
 -  fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
 +  fndecl = gimple_get_virt_method_for_binfo (tree_to_uhwi (token),
                                             binfo);
+ #ifdef ENABLE_CHECKING
+   if (fndecl)
+     gcc_assert (possible_polymorphic_call_target_p
+                 (otr, cgraph_get_node (fndecl)));
+ #endif
    return fndecl;
  }
  
diff --cc gcc/ipa-utils.h
@@@ -108,6 -109,19 +109,19 @@@ possible_polymorphic_call_target_p (str
    return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
                                             e->indirect_info->otr_token, n);
  }
 -                                           tree_low_cst
 -                                              (OBJ_TYPE_REF_TOKEN (call), 1),
+ /* Return true if N can be possibly target of a polymorphic call of
+    OBJ_TYPE_REF expression CALL.  */
+ inline bool
+ possible_polymorphic_call_target_p (tree call,
+                                   struct cgraph_node *n)
+ {
+   return possible_polymorphic_call_target_p (obj_type_ref_class (call),
++                                           tree_to_uhwi
++                                              (OBJ_TYPE_REF_TOKEN (call)),
+                                            n);
+ }
  #endif  /* GCC_IPA_UTILS_H  */
  
  
@@@ -460,10 -460,10 +460,10 @@@ doloop_modify (struct loop *loop, struc
  
        /* Determine if the iteration counter will be non-negative.
         Note that the maximum value loaded is iterations_max - 1.  */
-       if (max_loop_iterations (loop, &iterations)
+       if (get_max_loop_iterations (loop, &iterations)
 -        && (iterations.ule (double_int_one.llshift
 -                             (GET_MODE_PRECISION (mode) - 1,
 -                              GET_MODE_PRECISION (mode)))))
 +        && wi::leu_p (iterations,
 +                      wi::set_bit_in_zero (GET_MODE_PRECISION (mode) - 1,
 +                                           GET_MODE_PRECISION (mode))))
        nonneg = 1;
        break;
  
    {
      rtx init;
      unsigned level = get_loop_level (loop) + 1;
 -    double_int iter;
 +    wide_int iter;
      rtx iter_rtx;
  
-     if (!max_loop_iterations (loop, &iter)
+     if (!get_max_loop_iterations (loop, &iter)
 -      || !iter.fits_shwi ())
 +      || !wi::fits_shwi_p (iter))
        iter_rtx = const0_rtx;
      else
        iter_rtx = GEN_INT (iter.to_shwi ());
@@@ -670,11 -669,11 +669,11 @@@ doloop_optimize (struct loop *loop
  
    count = copy_rtx (desc->niter_expr);
    iterations = desc->const_iter ? desc->niter_expr : const0_rtx;
-   if (!max_loop_iterations (loop, &iter)
+   if (!get_max_loop_iterations (loop, &iter)
 -      || !iter.fits_shwi ())
 +      || !wi::fits_shwi_p (iter))
      iterations_max = const0_rtx;
    else
 -    iterations_max = GEN_INT (iter.to_shwi ());
 +    iterations_max = immed_wide_int_const (iter, mode);
    level = get_loop_level (loop) + 1;
  
    /* Generate looping insn.  If the pattern FAILs then give up trying
diff --cc gcc/loop-iv.c
Simple merge
@@@ -694,9 -694,9 +694,9 @@@ decide_unroll_constant_iterations (stru
       than one exit it may well loop less than determined maximal number
       of iterations.  */
    if (desc->niter < 2 * nunroll
-       || ((estimated_loop_iterations (loop, &iterations)
-          || max_loop_iterations (loop, &iterations))
+       || ((get_estimated_loop_iterations (loop, &iterations)
+          || get_max_loop_iterations (loop, &iterations))
 -        && iterations.ult (double_int::from_shwi (2 * nunroll))))
 +        && wi::ltu_p (iterations, 2 * nunroll)))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@@ -993,9 -999,9 +993,9 @@@ decide_unroll_runtime_iterations (struc
      }
  
    /* Check whether the loop rolls.  */
-   if ((estimated_loop_iterations (loop, &iterations)
-        || max_loop_iterations (loop, &iterations))
+   if ((get_estimated_loop_iterations (loop, &iterations)
+        || get_max_loop_iterations (loop, &iterations))
 -      && iterations.ult (double_int::from_shwi (2 * nunroll)))
 +      && wi::ltu_p (iterations, 2 * nunroll))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@@ -1378,10 -1388,9 +1378,10 @@@ decide_peel_simple (struct loop *loop, 
      }
  
    /* If we have realistic estimate on number of iterations, use it.  */
-   if (estimated_loop_iterations (loop, &iterations))
+   if (get_estimated_loop_iterations (loop, &iterations))
      {
 -      if (double_int::from_shwi (npeel).ule (iterations))
 +      /* TODO: unsigned/signed confusion */
 +      if (wi::leu_p (npeel, iterations))
        {
          if (dump_file)
            {
      }
    /* If we have small enough bound on iterations, we can still peel (completely
       unroll).  */
-   else if (max_loop_iterations (loop, &iterations)
+   else if (get_max_loop_iterations (loop, &iterations)
 -           && iterations.ult (double_int::from_shwi (npeel)))
 +           && wi::ltu_p (iterations, npeel))
      npeel = iterations.to_shwi () + 1;
    else
      {
@@@ -1547,9 -1556,9 +1547,9 @@@ decide_unroll_stupid (struct loop *loop
      }
  
    /* Check whether the loop rolls.  */
-   if ((estimated_loop_iterations (loop, &iterations)
-        || max_loop_iterations (loop, &iterations))
+   if ((get_estimated_loop_iterations (loop, &iterations)
+        || get_max_loop_iterations (loop, &iterations))
 -      && iterations.ult (double_int::from_shwi (2 * nunroll)))
 +      && wi::ltu_p (iterations, 2 * nunroll))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
Simple merge
Simple merge
Simple merge
diff --cc gcc/lto/lto.c
Simple merge
diff --cc gcc/omp-low.c
@@@ -1878,6 -2243,127 +2243,127 @@@ check_omp_nesting_restrictions (gimple 
      case GIMPLE_OMP_FOR:
        if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
        return true;
 -        switch (host_integerp (gimple_call_arg (stmt, 0), 0)
 -                ? tree_low_cst (gimple_call_arg (stmt, 0), 0)
+       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
+       {
+         if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
+           {
+             error_at (gimple_location (stmt),
+                       "distribute construct must be closely nested inside "
+                       "teams construct");
+             return false;
+           }
+         return true;
+       }
+       /* FALLTHRU */
+     case GIMPLE_CALL:
+       if (is_gimple_call (stmt)
+         && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+             == BUILT_IN_GOMP_CANCEL
+             || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                == BUILT_IN_GOMP_CANCELLATION_POINT))
+       {
+         const char *bad = NULL;
+         const char *kind = NULL;
+         if (ctx == NULL)
+           {
+             error_at (gimple_location (stmt), "orphaned %qs construct",
+                       DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                       == BUILT_IN_GOMP_CANCEL
+                       ? "#pragma omp cancel"
+                       : "#pragma omp cancellation point");
+             return false;
+           }
++        switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
++                ? tree_to_shwi (gimple_call_arg (stmt, 0))
+                 : 0)
+           {
+           case 1:
+             if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
+               bad = "#pragma omp parallel";
+             else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                      == BUILT_IN_GOMP_CANCEL
+                      && !integer_zerop (gimple_call_arg (stmt, 1)))
+               ctx->cancellable = true;
+             kind = "parallel";
+             break;
+           case 2:
+             if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
+                 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
+               bad = "#pragma omp for";
+             else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                      == BUILT_IN_GOMP_CANCEL
+                      && !integer_zerop (gimple_call_arg (stmt, 1)))
+               {
+                 ctx->cancellable = true;
+                 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
+                                      OMP_CLAUSE_NOWAIT))
+                   warning_at (gimple_location (stmt), 0,
+                               "%<#pragma omp cancel for%> inside "
+                               "%<nowait%> for construct");
+                 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
+                                      OMP_CLAUSE_ORDERED))
+                   warning_at (gimple_location (stmt), 0,
+                               "%<#pragma omp cancel for%> inside "
+                               "%<ordered%> for construct");
+               }
+             kind = "for";
+             break;
+           case 4:
+             if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
+                 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
+               bad = "#pragma omp sections";
+             else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                      == BUILT_IN_GOMP_CANCEL
+                      && !integer_zerop (gimple_call_arg (stmt, 1)))
+               {
+                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
+                   {
+                     ctx->cancellable = true;
+                     if (find_omp_clause (gimple_omp_sections_clauses
+                                                               (ctx->stmt),
+                                          OMP_CLAUSE_NOWAIT))
+                       warning_at (gimple_location (stmt), 0,
+                                   "%<#pragma omp cancel sections%> inside "
+                                   "%<nowait%> sections construct");
+                   }
+                 else
+                   {
+                     gcc_assert (ctx->outer
+                                 && gimple_code (ctx->outer->stmt)
+                                    == GIMPLE_OMP_SECTIONS);
+                     ctx->outer->cancellable = true;
+                     if (find_omp_clause (gimple_omp_sections_clauses
+                                                       (ctx->outer->stmt),
+                                          OMP_CLAUSE_NOWAIT))
+                       warning_at (gimple_location (stmt), 0,
+                                   "%<#pragma omp cancel sections%> inside "
+                                   "%<nowait%> sections construct");
+                   }
+               }
+             kind = "sections";
+             break;
+           case 8:
+             if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
+               bad = "#pragma omp task";
+             else
+               ctx->cancellable = true;
+             kind = "taskgroup";
+             break;
+           default:
+             error_at (gimple_location (stmt), "invalid arguments");
+             return false;
+           }
+         if (bad)
+           {
+             error_at (gimple_location (stmt),
+                       "%<%s %s%> construct not closely nested inside of %qs",
+                       DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+                       == BUILT_IN_GOMP_CANCEL
+                       ? "#pragma omp cancel"
+                       : "#pragma omp cancellation point", kind, bad);
+             return false;
+           }
+       }
        /* FALLTHRU */
      case GIMPLE_OMP_SECTIONS:
      case GIMPLE_OMP_SINGLE:
diff --cc gcc/optabs.c
Simple merge
Simple merge
diff --cc gcc/predict.c
Simple merge
@@@ -23,6 -23,6 +23,7 @@@ along with GCC; see the file COPYING3
  
  #include "obstack.h"
  #include "input.h"
++#include "wide-int-print.h"
  
  /* Maximum number of format string arguments.  */
  #define PP_NL_ARGMAX   30
@@@ -261,6 -261,6 +262,13 @@@ pp_get_prefix (const pretty_printer *pp
  #define pp_decimal_int(PP, I)  pp_scalar (PP, "%d", I)
  #define pp_unsigned_wide_integer(PP, I) \
     pp_scalar (PP, HOST_WIDE_INT_PRINT_UNSIGNED, (unsigned HOST_WIDE_INT) I)
++#define pp_wide_int(PP, W, SGN)                                       \
++  do                                                          \
++    {                                                         \
++      print_dec (W, pp_buffer (PP)->digit_buffer, SGN);               \
++      pp_string (PP, pp_buffer (PP)->digit_buffer);           \
++    }                                                         \
++  while (0)
  #define pp_wide_integer(PP, I) \
     pp_scalar (PP, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
  #define pp_widest_integer(PP, I) \
diff --cc gcc/print-rtl.c
Simple merge
Simple merge
diff --cc gcc/real.c
Simple merge
diff --cc gcc/real.h
Simple merge
diff --cc gcc/recog.c
Simple merge
diff --cc gcc/rtl.c
Simple merge
diff --cc gcc/rtl.def
Simple merge
diff --cc gcc/rtl.h
+++ b/gcc/rtl.h
@@@ -1227,22 -1151,12 +1229,22 @@@ rhs_regno (const_rtx x
  #define HARD_REGISTER_NUM_P(REG_NO) ((REG_NO) < FIRST_PSEUDO_REGISTER)
  
  /* For a CONST_INT rtx, INTVAL extracts the integer.  */
- #define INTVAL(RTX) XCWINT(RTX, 0, CONST_INT)
+ #define INTVAL(RTX) XCWINT (RTX, 0, CONST_INT)
  #define UINTVAL(RTX) ((unsigned HOST_WIDE_INT) INTVAL (RTX))
  
 +/* For a CONST_WIDE_INT, CONST_WIDE_INT_NUNITS is the number of
 +   elements actually needed to represent the constant.
 +   CONST_WIDE_INT_ELT gets one of the elements.  0 is the least
 +   significant HOST_WIDE_INT.  */
 +#define CONST_WIDE_INT_VEC(RTX) HWIVEC_CHECK (RTX, CONST_WIDE_INT)
 +#define CONST_WIDE_INT_NUNITS(RTX) CWI_GET_NUM_ELEM (RTX)
 +#define CONST_WIDE_INT_ELT(RTX, N) CWI_ELT (RTX, N)
 +
  /* For a CONST_DOUBLE:
 +#if TARGET_SUPPORTS_WIDE_INT == 0
     For a VOIDmode, there are two integers CONST_DOUBLE_LOW is the
       low-order word and ..._HIGH the high-order.
 +#endif
     For a float, there is a REAL_VALUE_TYPE structure, and
       CONST_DOUBLE_REAL_VALUE(r) is a pointer to it.  */
  #define CONST_DOUBLE_LOW(r) XCMWINT (r, 0, CONST_DOUBLE, VOIDmode)
diff --cc gcc/rtlanal.c
Simple merge
diff --cc gcc/sched-vis.c
Simple merge
diff --cc gcc/sdbout.c
Simple merge
Simple merge
diff --cc gcc/stmt.c
Simple merge
@@@ -2514,12 -2506,58 +2505,18 @@@ initialize_sizetypes (void
  void
  set_min_and_max_values_for_integral_type (tree type,
                                          int precision,
 -                                        bool is_unsigned)
 +                                        signop sgn)
  {
 -  tree min_value;
 -  tree max_value;
 -
+   /* For bitfields with zero width we end up creating integer types
+      with zero precision.  Don't assign any minimum/maximum values
+      to those types, they don't have any valid value.  */
+   if (precision < 1)
+     return;
 -  if (is_unsigned)
 -    {
 -      min_value = build_int_cst (type, 0);
 -      max_value
 -      = build_int_cst_wide (type, precision - HOST_BITS_PER_WIDE_INT >= 0
 -                            ? -1
 -                            : ((HOST_WIDE_INT) 1 << precision) - 1,
 -                            precision - HOST_BITS_PER_WIDE_INT > 0
 -                            ? ((unsigned HOST_WIDE_INT) ~0
 -                               >> (HOST_BITS_PER_WIDE_INT
 -                                   - (precision - HOST_BITS_PER_WIDE_INT)))
 -                            : 0);
 -    }
 -  else
 -    {
 -      min_value
 -      = build_int_cst_wide (type,
 -                            (precision - HOST_BITS_PER_WIDE_INT > 0
 -                             ? 0
 -                             : (HOST_WIDE_INT) (-1) << (precision - 1)),
 -                            (((HOST_WIDE_INT) (-1)
 -                              << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
 -                                  ? precision - HOST_BITS_PER_WIDE_INT - 1
 -                                  : 0))));
 -      max_value
 -      = build_int_cst_wide (type,
 -                            (precision - HOST_BITS_PER_WIDE_INT > 0
 -                             ? -1
 -                             : (HOST_WIDE_INT)
 -                               (((unsigned HOST_WIDE_INT) 1
 -                                 << (precision - 1)) - 1)),
 -                            (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
 -                             ? (HOST_WIDE_INT)
 -                               ((((unsigned HOST_WIDE_INT) 1
 -                                  << (precision - HOST_BITS_PER_WIDE_INT
 -                                      - 1))) - 1)
 -                             : 0));
 -    }
 -
 -  TYPE_MIN_VALUE (type) = min_value;
 -  TYPE_MAX_VALUE (type) = max_value;
 +  TYPE_MIN_VALUE (type)
 +    = wide_int_to_tree (type, wi::min_value (precision, sgn));
 +  TYPE_MAX_VALUE (type)
 +    = wide_int_to_tree (type, wi::max_value (precision, sgn));
  }
  
  /* Set the extreme values of TYPE based on its precision in bits,
diff --cc gcc/system.h
Simple merge
diff --cc gcc/targhooks.c
Simple merge
diff --cc gcc/trans-mem.c
Simple merge
Simple merge
diff --cc gcc/tree-cfg.c
@@@ -41,8 -41,9 +41,11 @@@ along with GCC; see the file COPYING3
  #include "pointer-set.h"
  #include "tree-inline.h"
  #include "target.h"
+ #include "tree-ssa-live.h"
+ #include "omp-low.h"
+ #include "tree-cfgcleanup.h"
 +#include "wide-int.h"
 +#include "wide-int-print.h"
  
  /* This file contains functions for building the Control Flow Graph (CFG)
     for a function tree.  */
Simple merge
diff --cc gcc/tree-core.h
Simple merge
Simple merge
diff --cc gcc/tree-dfa.h
index 0000000,7d0a470..017cb82
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,184 +1,182 @@@
 -          HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2));
+ /* Header file for tree data flow functions.
+    Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #ifndef GCC_TREE_DFA_H
+ #define GCC_TREE_DFA_H
+ extern void renumber_gimple_stmt_uids (void);
+ extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int);
+ extern void dump_variable (FILE *, tree);
+ extern void debug_variable (tree);
+ extern void dump_dfa_stats (FILE *);
+ extern void debug_dfa_stats (void);
+ extern tree ssa_default_def (struct function *, tree);
+ extern void set_ssa_default_def (struct function *, tree, tree);
+ extern tree get_or_create_ssa_default_def (struct function *, tree);
+ extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
+                                    HOST_WIDE_INT *, HOST_WIDE_INT *);
+ extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
+ extern bool stmt_references_abnormal_ssa_name (gimple);
+ extern void dump_enumerated_decls (FILE *, int);
+ /* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
+    denotes the starting address of the memory access EXP.
+    Returns NULL_TREE if the offset is not constant or any component
+    is not BITS_PER_UNIT-aligned.
+    VALUEIZE if non-NULL is used to valueize SSA names.  It should return
+    its argument or a constant if the argument is known to be constant.  */
+ /* ??? This is a static inline here to avoid the overhead of the indirect calls
+    to VALUEIZE.  But is this overhead really that significant?  And should we
+    perhaps just rely on WHOPR to specialize the function?  */
+ static inline tree
+ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
+                                tree (*valueize) (tree))
+ {
+   HOST_WIDE_INT byte_offset = 0;
+   /* Compute cumulative byte-offset for nested component-refs and array-refs,
+      and find the ultimate containing object.  */
+   while (1)
+     {
+       switch (TREE_CODE (exp))
+       {
+       case BIT_FIELD_REF:
+         {
 -              || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
++          HOST_WIDE_INT this_off = tree_to_hwi (TREE_OPERAND (exp, 2));
+           if (this_off % BITS_PER_UNIT)
+             return NULL_TREE;
+           byte_offset += this_off / BITS_PER_UNIT;
+         }
+         break;
+       case COMPONENT_REF:
+         {
+           tree field = TREE_OPERAND (exp, 1);
+           tree this_offset = component_ref_field_offset (exp);
+           HOST_WIDE_INT hthis_offset;
+           if (!this_offset
+               || TREE_CODE (this_offset) != INTEGER_CST
 -          hthis_offset = TREE_INT_CST_LOW (this_offset);
 -          hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
++              || (tree_to_hwi (DECL_FIELD_BIT_OFFSET (field))
+                   % BITS_PER_UNIT))
+             return NULL_TREE;
 -              HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
++          hthis_offset = tree_to_hwi (this_offset);
++          hthis_offset += (tree_to_hwi (DECL_FIELD_BIT_OFFSET (field))
+                            / BITS_PER_UNIT);
+           byte_offset += hthis_offset;
+         }
+         break;
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         {
+           tree index = TREE_OPERAND (exp, 1);
+           tree low_bound, unit_size;
+           if (valueize
+               && TREE_CODE (index) == SSA_NAME)
+             index = (*valueize) (index);
+           /* If the resulting bit-offset is constant, track it.  */
+           if (TREE_CODE (index) == INTEGER_CST
+               && (low_bound = array_ref_low_bound (exp),
+                   TREE_CODE (low_bound) == INTEGER_CST)
+               && (unit_size = array_ref_element_size (exp),
+                   TREE_CODE (unit_size) == INTEGER_CST))
+             {
 -              hindex -= TREE_INT_CST_LOW (low_bound);
 -              hindex *= TREE_INT_CST_LOW (unit_size);
++              HOST_WIDE_INT hindex = tree_to_hwi (index);
 -        byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
++              hindex -= tree_to_hwi (low_bound);
++              hindex *= tree_to_hwi (unit_size);
+               byte_offset += hindex;
+             }
+           else
+             return NULL_TREE;
+         }
+         break;
+       case REALPART_EXPR:
+         break;
+       case IMAGPART_EXPR:
 -                  double_int off = mem_ref_offset (exp);
 -                  gcc_assert (off.high == -1 || off.high == 0);
 -                  byte_offset += off.to_shwi ();
++        byte_offset += tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+         break;
+       case VIEW_CONVERT_EXPR:
+         break;
+       case MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (!integer_zerop (TREE_OPERAND (exp, 1)))
+                 {
 -                  double_int off = mem_ref_offset (exp);
 -                  gcc_assert (off.high == -1 || off.high == 0);
 -                  byte_offset += off.to_shwi ();
++                  addr_wide_int off = mem_ref_offset (exp);
++                  byte_offset += off.to_short_addr ();
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+       case TARGET_MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+                 return NULL_TREE;
+               if (!integer_zerop (TMR_OFFSET (exp)))
+                 {
++                  addr_wide_int off = mem_ref_offset (exp);
++                  byte_offset += off.to_short_addr ();
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+       default:
+         goto done;
+       }
+       exp = TREE_OPERAND (exp, 0);
+     }
+ done:
+   *poffset = byte_offset;
+   return exp;
+ }
+ #endif /* GCC_TREE_DFA_H */
diff --cc gcc/tree-dump.c
@@@ -29,8 -29,7 +29,9 @@@ along with GCC; see the file COPYING3
  #include "langhooks.h"
  #include "tree-iterator.h"
  #include "tree-pretty-print.h"
+ #include "tree-cfg.h"
 +#include "wide-int.h"
 +#include "wide-int-print.h"
  
  static unsigned int queue (dump_info_p, const_tree, int);
  static void dump_index (dump_info_p, unsigned int);
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1058,27 -1225,16 +1226,29 @@@ dump_generic_node (pretty_printer *buff
               NB: Neither of the following divisors can be trivially
               used to recover the original literal:
  
 -             TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (node)))
 +             tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (node)))
             TYPE_PRECISION (TREE_TYPE (TREE_TYPE (node)))  */
 -        pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
 +        pp_wide_integer (buffer, tree_to_hwi (node));
          pp_string (buffer, "B"); /* pseudo-unit */
        }
 +      else if (tree_fits_shwi_p (node))
 +      pp_wide_integer (buffer, tree_to_shwi (node));
 +      else if (tree_fits_uhwi_p (node))
 +      pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
        else
 -      pp_double_int (buffer, tree_to_double_int (node),
 -                     TYPE_UNSIGNED (TREE_TYPE (node)));
 +      {
 +        wide_int val = node;
 +
 +        if (wi::neg_p (val, TYPE_SIGN (TREE_TYPE (node))))
 +          {
 +            pp_minus (buffer);
 +            val = -val;
 +          }
 +        print_hex (val, pp_buffer (buffer)->digit_buffer);
 +        pp_string (buffer, pp_buffer (buffer)->digit_buffer);
 +      }
+       if (TREE_OVERFLOW (node))
+       pp_string (buffer, "(OVF)");
        break;
  
      case REAL_CST:
diff --cc gcc/tree-sra.c
Simple merge
Simple merge
Simple merge
@@@ -136,10 -127,9 +136,9 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "diagnostic-core.h"
  #include "dbgcnt.h"
- #include "gimple-fold.h"
  #include "params.h"
  #include "hash-table.h"
 -
 +#include "wide-int-print.h"
  
  /* Possible lattice values.  */
  typedef enum
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -38,8 -38,8 +38,9 @@@ along with GCC; see the file COPYING3
  #include "diagnostic-core.h"
  #include "tree-inline.h"
  #include "tree-pass.h"
 +#include "wide-int-print.h"
  
  #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
  
  /* The maximum number of dominator BBs we search for conditions
@@@ -3011,38 -2975,27 +2977,21 @@@ infer_loop_bounds_from_undefined (struc
    free (bbs);
  }
  
- /* Converts VAL to max_wide_int.  */
- static max_wide_int
- gcov_type_to_wide_int (gcov_type val)
- {
-   HOST_WIDE_INT a[2];
-   a[0] = (unsigned HOST_WIDE_INT) val;
-   /* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
-      the size of type.  */
-   val >>= HOST_BITS_PER_WIDE_INT - 1;
-   val >>= 1;
-   a[1] = (unsigned HOST_WIDE_INT) val;
--
-   return max_wide_int::from_array (a, 2);
- }
--
 -/* Compare double ints, callback for qsort.  */
 +/* Compare wide ints, callback for qsort.  */
  
- int
static int
 -double_int_cmp (const void *p1, const void *p2)
 +wide_int_cmp (const void *p1, const void *p2)
  {
 -  const double_int *d1 = (const double_int *)p1;
 -  const double_int *d2 = (const double_int *)p2;
 -  if (*d1 == *d2)
 -    return 0;
 -  if (d1->ult (*d2))
 -    return -1;
 -  return 1;
 +  const max_wide_int *d1 = (const max_wide_int *)p1;
 +  const max_wide_int *d2 = (const max_wide_int *)p2;
 +  return wi::cmpu (*d1, *d2);
  }
  
  /* Return index of BOUND in BOUNDS array sorted in increasing order.
     Lookup by binary search.  */
  
- int
static int
 -bound_index (vec<double_int> bounds, double_int bound)
 +bound_index (vec<max_wide_int> bounds, const max_wide_int &bound)
  {
    unsigned int end = bounds.length ();
    unsigned int begin = 0;
@@@ -3486,6 -3408,22 +3403,22 @@@ estimated_loop_iterations_int (struct l
    return hwi_nit < 0 ? -1 : hwi_nit;
  }
  
 -max_loop_iterations (struct loop *loop, double_int *nit)
+ /* Sets NIT to an upper bound for the maximum number of executions of the
+    latch of the LOOP.  If we have no reliable estimate, the function returns
+    false, otherwise returns true.  */
+ bool
++max_loop_iterations (struct loop *loop, max_wide_int *nit)
+ {
+   /* When SCEV information is available, try to update loop iterations
+      estimate.  Otherwise just return whatever we recorded earlier.  */
+   if (scev_initialized_p ())
+     estimate_numbers_of_iterations_loop (loop);
+   return get_max_loop_iterations (loop, nit);
+ }
  /* Similar to max_loop_iterations, but returns the estimate only
     if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
     on the number of iterations of LOOP could not be derived, returns -1.  */
index 0000000,1945507..a794843
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,48 +1,48 @@@
 -extern bool estimated_loop_iterations (struct loop *, double_int *);
+ /* Header file for loop interation estimates.
+    Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #ifndef GCC_TREE_SSA_LOOP_NITER_H
+ #define GCC_TREE_SSA_LOOP_NITER_H
+ extern tree expand_simple_operations (tree);
+ extern bool loop_only_exit_p (const struct loop *, const_edge);
+ extern bool number_of_iterations_exit (struct loop *, edge,
+                                      struct tree_niter_desc *niter, bool,
+                                      bool every_iteration = true);
+ extern tree find_loop_niter (struct loop *, edge *);
+ extern bool finite_loop_p (struct loop *);
+ extern tree loop_niter_by_eval (struct loop *, edge);
+ extern tree find_loop_niter_by_eval (struct loop *, edge *);
 -extern bool max_loop_iterations (struct loop *, double_int *);
++extern bool estimated_loop_iterations (struct loop *, max_wide_int *);
+ extern HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
 -extern bool max_stmt_executions (struct loop *, double_int *);
 -extern bool estimated_stmt_executions (struct loop *, double_int *);
++extern bool max_loop_iterations (struct loop *, max_wide_int *);
+ extern HOST_WIDE_INT max_loop_iterations_int (struct loop *);
+ extern HOST_WIDE_INT max_stmt_executions_int (struct loop *);
+ extern HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
++extern bool max_stmt_executions (struct loop *, max_wide_int *);
++extern bool estimated_stmt_executions (struct loop *, max_wide_int *);
+ extern void estimate_numbers_of_iterations (void);
+ extern bool stmt_dominates_stmt_p (gimple, gimple);
+ extern bool nowrap_type_p (tree);
+ extern bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
+ extern void free_numbers_of_iterations_estimates_loop (struct loop *);
+ extern void free_numbers_of_iterations_estimates (void);
+ extern void substitute_in_loop_info (struct loop *, tree, tree);
+ #endif /* GCC_TREE_SSA_LOOP_NITER_H */
Simple merge
index 0000000,1c96d9c..d8fc0ed
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,85 +1,86 @@@
 -  double_int max;     /* The upper bound on the number of iterations of
+ /* Header file for SSA loop optimizations.
+    Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #ifndef GCC_TREE_SSA_LOOP_H
+ #define GCC_TREE_SSA_LOOP_H
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
++#include "wide-int.h"
+ /* Affine iv.  */
+ typedef struct affine_iv_d
+ {
+   /* Iv = BASE + STEP * i.  */
+   tree base, step;
+   /* True if this iv does not overflow.  */
+   bool no_overflow;
+ } affine_iv;
+ /* Description of number of iterations of a loop.  All the expressions inside
+    the structure can be evaluated at the end of the loop's preheader
+    (and due to ssa form, also anywhere inside the body of the loop).  */
+ struct tree_niter_desc
+ {
+   tree assumptions;   /* The boolean expression.  If this expression evaluates
+                          to false, then the other fields in this structure
+                          should not be used; there is no guarantee that they
+                          will be correct.  */
+   tree may_be_zero;   /* The boolean expression.  If it evaluates to true,
+                          the loop will exit in the first iteration (i.e.
+                          its latch will not be executed), even if the niter
+                          field says otherwise.  */
+   tree niter;         /* The expression giving the number of iterations of
+                          a loop (provided that assumptions == true and
+                          may_be_zero == false), more precisely the number
+                          of executions of the latch of the loop.  */
++  max_wide_int max;   /* The upper bound on the number of iterations of
+                          the loop.  */
+   /* The simplified shape of the exit condition.  The loop exits if
+      CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
+      LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
+      LE_EXPR and negative if CMP is GE_EXPR.  This information is used
+      by loop unrolling.  */
+   affine_iv control;
+   tree bound;
+   enum tree_code cmp;
+ };
+ extern bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
+ extern char *get_lsm_tmp_name (tree ref, unsigned n, const char *suffix = NULL);
+ extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights_d *);
+ /* Returns the loop of the statement STMT.  */
+ static inline struct loop *
+ loop_containing_stmt (gimple stmt)
+ {
+   basic_block bb = gimple_bb (stmt);
+   if (!bb)
+     return NULL;
+   return bb->loop_father;
+ }
+ #endif /* GCC_TREE_SSA_LOOP_H */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/tree-ssa.c
Simple merge
@@@ -166,6 -170,62 +170,62 @@@ make_ssa_name_fn (struct function *fn, 
    return t;
  }
  
 -set_range_info (tree name, double_int min, double_int max)
+ /* Store range information MIN, and MAX to tree ssa_name NAME.  */
+ void
 -get_range_info (tree name, double_int *min, double_int *max)
++set_range_info (tree name, max_wide_int min, max_wide_int max)
+ {
+   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+   /* Allocate if not available.  */
+   if (ri == NULL)
+     {
+       ri = ggc_alloc_cleared_range_info_def ();
+       SSA_NAME_RANGE_INFO (name) = ri;
+     }
+   /* Set the values.  */
+   ri->min = min;
+   ri->max = max;
+ }
+ /* Gets range information MIN, MAX and returns enum value_range_type
+    corresponding to tree ssa_name NAME.  enum value_range_type returned
+    is used to determine if MIN and MAX are valid values.  */
+ enum value_range_type
 -  if (ri->min.cmp (ri->max, TYPE_UNSIGNED (TREE_TYPE (name))) == 1)
++get_range_info (tree name, max_wide_int *min, max_wide_int *max)
+ {
+   enum value_range_type range_type;
+   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+   gcc_assert (min && max);
+   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+   /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
+      with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
+   if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+             > 2 * HOST_BITS_PER_WIDE_INT))
+     return VR_VARYING;
+   /* If min > max, it is VR_ANTI_RANGE.  */
 -      *min = ri->max + double_int_one;
 -      *max = ri->min - double_int_one;
++  if (wi::cmp (ri->min, ri->max, TYPE_SIGN (TREE_TYPE (name))) == 1)
+     {
+       /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1].  */
+       range_type = VR_ANTI_RANGE;
++      *min = ri->max + 1;
++      *max = ri->min - 1;
+     }
+   else
+   {
+     /* Otherwise (when min <= max), it is VR_RANGE.  */
+     range_type = VR_RANGE;
+     *min = ri->min;
+     *max = ri->max;
+   }
+   return range_type;
+ }
  
  /* We no longer need the SSA_NAME expression VAR, release it so that
     it may be reused.
@@@ -45,6 -45,15 +45,15 @@@ struct GTY(()) ptr_info_de
    unsigned int misalign;
  };
  
 -  double_int min;
+ /* Value range information for SSA_NAMEs representing non-pointer variables.  */
+ struct GTY (()) range_info_def {
+   /* Minimum for value range.  */
 -  double_int max;
++  max_wide_int min;
+   /* Maximum for value range.  */
++  max_wide_int max;
+ };
  
  #define SSANAMES(fun) (fun)->gimple_df->ssa_names
  #define MODIFIED_NORETURN_CALLS(fun) (fun)->gimple_df->modified_noreturn_calls
  #define ssa_name(i) ((*cfun->gimple_df->ssa_names)[(i)])
  
  
 -extern void set_range_info (tree ssa, double_int min, double_int max);
+ /* Type of value ranges.  See value_range_d In tree-vrp.c for a
+    description of these types.  */
+ enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
+ /* Sets the value range to SSA.  */
 -extern enum value_range_type  get_range_info (tree name, double_int *min,
 -                                            double_int *max);
++extern void set_range_info (tree ssa, max_wide_int min, max_wide_int max);
+ /* Gets the value range from SSA.  */
++extern enum value_range_type  get_range_info (tree name, max_wide_int *min,
++                                            max_wide_int *max);
  extern void init_ssanames (struct function *, int);
  extern void fini_ssanames (void);
  extern void ssanames_print_statistics (void);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -352,11 -352,11 +352,11 @@@ typedef struct _loop_vec_info 
  (L)->may_alias_ddrs.length () > 0
  
  #define NITERS_KNOWN_P(n)                     \
 -(host_integerp ((n),0)                        \
 -&& TREE_INT_CST_LOW ((n)) > 0)
 +(tree_fits_shwi_p ((n))                        \
 +&& tree_to_shwi ((n)) > 0)
  
  #define LOOP_VINFO_NITERS_KNOWN_P(L)          \
- NITERS_KNOWN_P((L)->num_iters)
+ NITERS_KNOWN_P ((L)->num_iters)
  
  static inline loop_vec_info
  loop_vec_info_for_loop (struct loop *loop)
diff --cc gcc/tree-vrp.c
@@@ -36,14 -36,12 +36,13 @@@ along with GCC; see the file COPYING3
  #include "tree-scalar-evolution.h"
  #include "tree-ssa-propagate.h"
  #include "tree-chrec.h"
- #include "gimple-fold.h"
+ #include "tree-ssa-threadupdate.h"
  #include "expr.h"
  #include "optabs.h"
+ #include "tree-ssa-threadedge.h"
++#include "wide-int.h"
  
  
- /* Type of value ranges.  See value_range_d for a description of these
-    types.  */
- enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
  
  /* Range of values that can be associated with an SSA_NAME after VRP
     has executed.  */
@@@ -4415,6 -4467,56 +4426,56 @@@ fp_predicate (gimple stmt
  }
  
  
 -            int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
+ /* If OP can be inferred to be non-zero after STMT executes, return true.  */
+ static bool
+ infer_nonnull_range (gimple stmt, tree op)
+ {
+   /* We can only assume that a pointer dereference will yield
+      non-NULL if -fdelete-null-pointer-checks is enabled.  */
+   if (!flag_delete_null_pointer_checks
+       || !POINTER_TYPE_P (TREE_TYPE (op))
+       || gimple_code (stmt) == GIMPLE_ASM)
+     return false;
+   unsigned num_uses, num_loads, num_stores;
+   count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
+   if (num_loads + num_stores > 0)
+     return true;
+   if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
+     {
+       tree fntype = gimple_call_fntype (stmt);
+       tree attrs = TYPE_ATTRIBUTES (fntype);
+       for (; attrs; attrs = TREE_CHAIN (attrs))
+       {
+         attrs = lookup_attribute ("nonnull", attrs);
+         /* If "nonnull" wasn't specified, we know nothing about
+            the argument.  */
+         if (attrs == NULL_TREE)
+           return false;
+         /* If "nonnull" applies to all the arguments, then ARG
+            is non-null.  */
+         if (TREE_VALUE (attrs) == NULL_TREE)
+           return true;
+         /* Now see if op appears in the nonnull list.  */
+         for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+           {
++            int idx = tree_to_shwi (TREE_VALUE (t)) - 1;
+             tree arg = gimple_call_arg (stmt, idx);
+             if (op == arg)
+               return true;
+           }
+       }
+     }
+   return false;
+ }
  /* If the range of values taken by OP can be inferred after STMT executes,
     return the comparison code (COMP_CODE_P) and value (VAL_P) that
     describes the inferred range.  Return true if a range could be
@@@ -9426,6 -9491,51 +9466,50 @@@ vrp_finalize (void
       the datastructures built by VRP.  */
    identify_jump_threads ();
  
 -            set_range_info (name,
 -                            tree_to_double_int (vr_value[i]->min),
 -                            tree_to_double_int (vr_value[i]->max));
+   /* Set value range to non pointer SSA_NAMEs.  */
+   for (i  = 0; i < num_vr_values; i++)
+     if (vr_value[i])
+       {
+       tree name = ssa_name (i);
+       if (!name
+         || POINTER_TYPE_P (TREE_TYPE (name))
+         || (vr_value[i]->type == VR_VARYING)
+         || (vr_value[i]->type == VR_UNDEFINED))
+       continue;
+       if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+           && (TREE_CODE (vr_value[i]->max) == INTEGER_CST))
+         {
+           if (vr_value[i]->type == VR_RANGE)
 -                set_range_info (name,
 -                                double_int_one,
 -                                double_int::max_value
 -                                (TYPE_PRECISION (TREE_TYPE (name)), true));
++            set_range_info (name, vr_value[i]->min, vr_value[i]->max);
+           else if (vr_value[i]->type == VR_ANTI_RANGE)
+             {
+               /* VR_ANTI_RANGE ~[min, max] is encoded compactly as
+                  [max + 1, min - 1] without additional attributes.
+                  When min value > max value, we know that it is
+                  VR_ANTI_RANGE; it is VR_RANGE otherwise.  */
+               /* ~[0,0] anti-range is represented as
+                  range.  */
+               if (TYPE_UNSIGNED (TREE_TYPE (name))
+                   && integer_zerop (vr_value[i]->min)
+                   && integer_zerop (vr_value[i]->max))
 -                                tree_to_double_int (vr_value[i]->max)
 -                                + double_int_one,
 -                                tree_to_double_int (vr_value[i]->min)
 -                                - double_int_one);
++                {
++                  max_wide_int tmmwi
++                    = max_wide_int::from (wi::max_value (TYPE_PRECISION (TREE_TYPE (name)),
++                                                         UNSIGNED),
++                                          UNSIGNED);
++                  set_range_info (name, 1, tmmwi);
++                }
+               else
+                 set_range_info (name,
++                                vr_value[i]->max + 1,
++                                vr_value[i]->min - 1);
+             }
+         }
+       }
    /* Free allocated memory.  */
    for (i = 0; i < num_vr_values; i++)
      if (vr_value[i])
diff --cc gcc/tree.c
@@@ -4282,27 -4296,9 +4318,9 @@@ addr_wide_in
  mem_ref_offset (const_tree t)
  {
    tree toff = TREE_OPERAND (t, 1);
 -  return tree_to_double_int (toff).sext (TYPE_PRECISION (TREE_TYPE (toff)));
 +  return wi::sext (addr_wide_int (toff), TYPE_PRECISION (TREE_TYPE (toff)));
  }
  
- /* Return the pointer-type relevant for TBAA purposes from the
-    gimple memory reference tree T.  This is the type to be used for
-    the offset operand of MEM_REF or TARGET_MEM_REF replacements of T.  */
- tree
- reference_alias_ptr_type (const_tree t)
- {
-   const_tree base = t;
-   while (handled_component_p (base))
-     base = TREE_OPERAND (base, 0);
-   if (TREE_CODE (base) == MEM_REF)
-     return TREE_TYPE (TREE_OPERAND (base, 1));
-   else if (TREE_CODE (base) == TARGET_MEM_REF)
-     return TREE_TYPE (TMR_OFFSET (base)); 
-   else
-     return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base)));
- }
  /* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE
     offsetted by OFFSET units.  */
  
diff --cc gcc/tree.def
Simple merge
diff --cc gcc/tree.h
@@@ -595,11 -585,11 +595,11 @@@ extern void omp_clause_range_check_fail
    (CASE_LABEL_EXPR_CHECK (NODE)->base.addressable_flag)
  
  #define PREDICT_EXPR_OUTCOME(NODE) \
-   ((enum prediction) (PREDICT_EXPR_CHECK(NODE)->base.addressable_flag))
+   ((enum prediction) (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag))
  #define SET_PREDICT_EXPR_OUTCOME(NODE, OUTCOME) \
-   (PREDICT_EXPR_CHECK(NODE)->base.addressable_flag = (int) OUTCOME)
+   (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag = (int) OUTCOME)
  #define PREDICT_EXPR_PREDICTOR(NODE) \
 -  ((enum br_predictor)tree_low_cst (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0), 0))
 +  ((enum br_predictor)tree_to_shwi (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0)))
  
  /* In a VAR_DECL, nonzero means allocate static storage.
     In a FUNCTION_DECL, nonzero if function has been defined.
@@@ -4512,10 -4403,10 +4575,9 @@@ extern tree fold_indirect_ref_loc (loca
  extern tree build_simple_mem_ref_loc (location_t, tree);
  #define build_simple_mem_ref(T)\
        build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
- extern tree reference_alias_ptr_type (const_tree);
 -extern double_int mem_ref_offset (const_tree);
  extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
  extern tree constant_boolean_node (bool, tree);
 -extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
 +extern tree div_if_zero_remainder (const_tree, const_tree);
  
  extern bool tree_swap_operands_p (const_tree, const_tree, bool);
  extern enum tree_code swap_tree_comparison (enum tree_code);
diff --cc gcc/tsan.c
Simple merge
diff --cc gcc/ubsan.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/varasm.c
Simple merge