]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/semantics.c
c++: Fix handling of internal fn calls in statement expressions [PR94385]
[gcc.git] / gcc / cp / semantics.c
index e00331a3ea4a6c1aa1979f7ecaa08798f93cb56b..559e38dbc14e843635dd6ca9f41ad78b70769e6f 100644 (file)
@@ -3,7 +3,7 @@
    building RTL.  These routines are used both during actual parsing
    and during the instantiation of template functions.
 
-   Copyright (C) 1998-2018 Free Software Foundation, Inc.
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
 
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "gomp-constants.h"
 #include "predict.h"
+#include "memmodel.h"
 
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
@@ -379,7 +380,8 @@ add_stmt (tree t)
 
       /* When we expand a statement-tree, we must know whether or not the
         statements are full-expressions.  We record that fact here.  */
-      STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
+      if (STATEMENT_CODE_P (TREE_CODE (t)))
+       STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
     }
 
   if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
@@ -645,10 +647,10 @@ maybe_convert_cond (tree cond)
     return NULL_TREE;
 
   /* Wait until we instantiate templates before doing conversion.  */
-  if (processing_template_decl)
+  if (type_dependent_expression_p (cond))
     return cond;
 
-  if (warn_sequence_point)
+  if (warn_sequence_point && !processing_template_decl)
     verify_sequence_points (cond);
 
   /* Do the conversion.  */
@@ -656,12 +658,11 @@ maybe_convert_cond (tree cond)
 
   if (TREE_CODE (cond) == MODIFY_EXPR
       && !TREE_NO_WARNING (cond)
-      && warn_parentheses)
-    {
-      warning_at (EXPR_LOC_OR_LOC (cond, input_location), OPT_Wparentheses,
-                 "suggest parentheses around assignment used as truth value");
-      TREE_NO_WARNING (cond) = 1;
-    }
+      && warn_parentheses
+      && warning_at (cp_expr_loc_or_loc (cond, input_location),
+                    OPT_Wparentheses, "suggest parentheses around "
+                                      "assignment used as truth value"))
+    TREE_NO_WARNING (cond) = 1;
 
   return condition_conversion (cond);
 }
@@ -1060,7 +1061,35 @@ finish_for_stmt (tree for_stmt)
                     : &FOR_SCOPE (for_stmt));
   tree scope = *scope_ptr;
   *scope_ptr = NULL;
+
+  /* During parsing of the body, range for uses "__for_{range,begin,end} "
+     decl names to make those unaccessible by code in the body.
+     Change it to ones with underscore instead of space, so that it can
+     be inspected in the debugger.  */
+  tree range_for_decl[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
+  gcc_assert (CPTI_FOR_BEGIN__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 1
+             && CPTI_FOR_END__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 2
+             && CPTI_FOR_RANGE_IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 3
+             && CPTI_FOR_BEGIN_IDENTIFIER == CPTI_FOR_BEGIN__IDENTIFIER + 3
+             && CPTI_FOR_END_IDENTIFIER == CPTI_FOR_END__IDENTIFIER + 3);
+  for (int i = 0; i < 3; i++)
+    {
+      tree id = cp_global_trees[CPTI_FOR_RANGE__IDENTIFIER + i];
+      if (IDENTIFIER_BINDING (id)
+         && IDENTIFIER_BINDING (id)->scope == current_binding_level)
+       {
+         range_for_decl[i] = IDENTIFIER_BINDING (id)->value;
+         gcc_assert (VAR_P (range_for_decl[i])
+                     && DECL_ARTIFICIAL (range_for_decl[i]));
+       }
+    }
+
   add_stmt (do_poplevel (scope));
+
+  for (int i = 0; i < 3; i++)
+    if (range_for_decl[i])
+      DECL_NAME (range_for_decl[i])
+       = cp_global_trees[CPTI_FOR_RANGE_IDENTIFIER + i];
 }
 
 /* Begin a range-for-statement.  Returns a new RANGE_FOR_STMT.
@@ -1073,8 +1102,8 @@ begin_range_for_stmt (tree scope, tree init)
 {
   begin_maybe_infinite_loop (boolean_false_node);
 
-  tree r = build_stmt (input_location, RANGE_FOR_STMT,
-                      NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
+  tree r = build_stmt (input_location, RANGE_FOR_STMT, NULL_TREE, NULL_TREE,
+                      NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
 
   if (scope == NULL_TREE)
     {
@@ -1082,22 +1111,23 @@ begin_range_for_stmt (tree scope, tree init)
       scope = begin_for_scope (&init);
     }
 
-  /* RANGE_FOR_STMTs do not use nor save the init tree, so we
-     pop it now.  */
-  if (init)
-    pop_stmt_list (init);
+  /* Since C++20, RANGE_FOR_STMTs can use the init tree, so save it.  */
+  RANGE_FOR_INIT_STMT (r) = init;
   RANGE_FOR_SCOPE (r) = scope;
 
   return r;
 }
 
 /* Finish the head of a range-based for statement, which may
-   be given by RANGE_FOR_STMT. DECL must be the declaration
+   be given by RANGE_FOR_STMT.  DECL must be the declaration
    and EXPR must be the loop expression. */
 
 void
 finish_range_for_decl (tree range_for_stmt, tree decl, tree expr)
 {
+  if (processing_template_decl)
+    RANGE_FOR_INIT_STMT (range_for_stmt)
+      = pop_stmt_list (RANGE_FOR_INIT_STMT (range_for_stmt));
   RANGE_FOR_DECL (range_for_stmt) = decl;
   RANGE_FOR_EXPR (range_for_stmt) = expr;
   add_stmt (range_for_stmt);
@@ -1452,11 +1482,11 @@ finish_compound_stmt (tree stmt)
 /* Finish an asm-statement, whose components are a STRING, some
    OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some
    LABELS.  Also note whether the asm-statement should be
-   considered volatile.  */
+   considered volatile, and whether it is asm inline.  */
 
 tree
 finish_asm_stmt (int volatile_p, tree string, tree output_operands,
-                tree input_operands, tree clobbers, tree labels)
+                tree input_operands, tree clobbers, tree labels, bool inline_p)
 {
   tree r;
   tree t;
@@ -1504,7 +1534,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                     effectively const.  */
                  || (CLASS_TYPE_P (TREE_TYPE (operand))
                      && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
-           cxx_readonly_error (operand, lv_asm);
+           cxx_readonly_error (input_location, operand, lv_asm);
 
          tree *op = &operand;
          while (TREE_CODE (*op) == COMPOUND_EXPR)
@@ -1610,6 +1640,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                  output_operands, input_operands,
                  clobbers, labels);
   ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
+  ASM_INLINE_P (r) = inline_p;
   r = maybe_cleanup_point_expr_void (r);
   return add_stmt (r);
 }
@@ -1711,7 +1742,8 @@ force_paren_expr (tree expr)
   if (cp_unevaluated_operand)
     return expr;
 
-  if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
+  if (!DECL_P (tree_strip_any_location_wrapper (expr))
+      && TREE_CODE (expr) != COMPONENT_REF
       && TREE_CODE (expr) != SCOPE_REF)
     return expr;
 
@@ -1720,23 +1752,10 @@ force_paren_expr (tree expr)
     REF_PARENTHESIZED_P (expr) = true;
   else if (processing_template_decl)
     expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
-  else if (VAR_P (expr) && DECL_HARD_REGISTER (expr))
-    /* We can't bind a hard register variable to a reference.  */;
   else
     {
-      cp_lvalue_kind kind = lvalue_kind (expr);
-      if ((kind & ~clk_class) != clk_none)
-       {
-         tree type = unlowered_expr_type (expr);
-         bool rval = !!(kind & clk_rvalueref);
-         type = cp_build_reference_type (type, rval);
-         /* This inhibits warnings in, eg, cxx_mark_addressable
-            (c++/60955).  */
-         warning_sentinel s (extra_warnings);
-         expr = build_static_cast (type, expr, tf_error);
-         if (expr != error_mark_node)
-           REF_PARENTHESIZED_P (expr) = true;
-       }
+      expr = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+      REF_PARENTHESIZED_P (expr) = true;
     }
 
   return expr;
@@ -1765,6 +1784,9 @@ maybe_undo_parenthesized_ref (tree t)
     }
   else if (TREE_CODE (t) == PAREN_EXPR)
     t = TREE_OPERAND (t, 0);
+  else if (TREE_CODE (t) == VIEW_CONVERT_EXPR
+          && REF_PARENTHESIZED_P (t))
+    t = TREE_OPERAND (t, 0);
 
   return t;
 }
@@ -1784,8 +1806,9 @@ finish_parenthesized_expr (cp_expr expr)
        enclosed in parentheses.  */
     PTRMEM_OK_P (expr) = 0;
 
-  if (TREE_CODE (expr) == STRING_CST)
-    PAREN_STRING_LITERAL_P (expr) = 1;
+  tree stripped_expr = tree_strip_any_location_wrapper (expr);
+  if (TREE_CODE (stripped_expr) == STRING_CST)
+    PAREN_STRING_LITERAL_P (stripped_expr) = 1;
 
   expr = cp_expr (force_paren_expr (expr), expr.get_location ());
 
@@ -1806,7 +1829,15 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
     {
       tree scope = qualifying_scope;
       if (scope == NULL_TREE)
-       scope = context_for_name_lookup (decl);
+       {
+         scope = context_for_name_lookup (decl);
+         if (!TYPE_P (scope))
+           {
+             /* Can happen during error recovery (c++/85014).  */
+             gcc_assert (seen_error ());
+             return error_mark_node;
+           }
+       }
       object = maybe_dummy_object (scope, NULL);
     }
 
@@ -1831,7 +1862,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
   if (current_class_ptr)
     TREE_USED (current_class_ptr) = 1;
-  if (processing_template_decl && !qualifying_scope)
+  if (processing_template_decl)
     {
       tree type = TREE_TYPE (decl);
 
@@ -1852,17 +1883,16 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
          type = cp_build_qualified_type (type, quals);
        }
 
-      ret = (convert_from_reference
-             (build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
+      if (qualifying_scope)
+       /* Wrap this in a SCOPE_REF for now.  */
+       ret = build_qualified_name (type, qualifying_scope, decl,
+                                   /*template_p=*/false);
+      else
+       ret = (convert_from_reference
+              (build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
     }
   /* If PROCESSING_TEMPLATE_DECL is nonzero here, then
-     QUALIFYING_SCOPE is also non-null.  Wrap this in a SCOPE_REF
-     for now.  */
-  else if (processing_template_decl)
-    ret = build_qualified_name (TREE_TYPE (decl),
-                               qualifying_scope,
-                               decl,
-                               /*template_p=*/false);
+     QUALIFYING_SCOPE is also non-null.  */
   else
     {
       tree access_type = TREE_TYPE (object);
@@ -2073,7 +2103,8 @@ finish_qualified_id_expr (tree qualifying_class,
     {
       /* See if any of the functions are non-static members.  */
       /* If so, the expression may be relative to 'this'.  */
-      if (!shared_member_p (expr)
+      if ((type_dependent_expression_p (expr)
+          || !shared_member_p (expr))
          && current_class_ptr
          && DERIVED_FROM_P (qualifying_class,
                             current_nonlambda_class_type ()))
@@ -2089,6 +2120,14 @@ finish_qualified_id_expr (tree qualifying_class,
        expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
                                 complain);
     }
+  else if (!template_p
+          && TREE_CODE (expr) == TEMPLATE_DECL
+          && !DECL_FUNCTION_TEMPLATE_P (expr))
+    {
+      if (complain & tf_error)
+       error ("%qE missing template arguments", expr);
+      return error_mark_node;
+    }
   else
     {
       /* In a template, return a SCOPE_REF for most qualified-ids
@@ -2098,10 +2137,14 @@ finish_qualified_id_expr (tree qualifying_class,
         non-type template argument handling.  */
       if (processing_template_decl
          && (!currently_open_class (qualifying_class)
+             || TREE_CODE (expr) == IDENTIFIER_NODE
+             || TREE_CODE (expr) == TEMPLATE_ID_EXPR
              || TREE_CODE (expr) == BIT_NOT_EXPR))
        expr = build_qualified_name (TREE_TYPE (expr),
                                     qualifying_class, expr,
                                     template_p);
+      else if (tree wrap = maybe_get_tls_wrapper_call (expr))
+       expr = wrap;
 
       expr = convert_from_reference (expr);
     }
@@ -2276,19 +2319,22 @@ empty_expr_stmt_p (tree expr_stmt)
   return false;
 }
 
-/* Perform Koenig lookup.  FN is the postfix-expression representing
+/* Perform Koenig lookup.  FN_EXPR is the postfix-expression representing
    the function (or functions) to call; ARGS are the arguments to the
    call.  Returns the functions to be considered by overload resolution.  */
 
 cp_expr
-perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
+perform_koenig_lookup (cp_expr fn_expr, vec<tree, va_gc> *args,
                       tsubst_flags_t complain)
 {
   tree identifier = NULL_TREE;
   tree functions = NULL_TREE;
   tree tmpl_args = NULL_TREE;
   bool template_id = false;
-  location_t loc = fn.get_location ();
+  location_t loc = fn_expr.get_location ();
+  tree fn = fn_expr.get_value ();
+
+  STRIP_ANY_LOCATION_WRAPPER (fn);
 
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
     {
@@ -2328,7 +2374,7 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
   if (fn && template_id && fn != error_mark_node)
     fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args);
   
-  return fn;
+  return cp_expr (fn, loc);
 }
 
 /* Generate an expression for `FN (ARGS)'.  This may change the
@@ -2348,7 +2394,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 {
   tree result;
   tree orig_fn;
-  vec<tree, va_gc> *orig_args = NULL;
+  vec<tree, va_gc> *orig_args = *args;
 
   if (fn == error_mark_node)
     return error_mark_node;
@@ -2359,6 +2405,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
      it so that we can tell this is a call to a known function.  */
   fn = maybe_undo_parenthesized_ref (fn);
 
+  STRIP_ANY_LOCATION_WRAPPER (fn);
+
   orig_fn = fn;
 
   if (processing_template_decl)
@@ -2380,13 +2428,10 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
          || any_type_dependent_arguments_p (*args))
        {
          result = build_min_nt_call_vec (orig_fn, *args);
-         SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
+         SET_EXPR_LOCATION (result, cp_expr_loc_or_loc (fn, input_location));
          KOENIG_LOOKUP_P (result) = koenig_p;
          if (is_overloaded_fn (fn))
-           {
-             fn = get_fns (fn);
-             lookup_keep (fn, true);
-           }
+           fn = get_fns (fn);
 
          if (cfun)
            {
@@ -2522,6 +2567,20 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
                 sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
            }
 
+         if ((complain & tf_warning)
+             && TREE_CODE (fn) == FUNCTION_DECL
+             && fndecl_built_in_p (fn, BUILT_IN_MEMSET)
+             && vec_safe_length (*args) == 3
+             && !any_type_dependent_arguments_p (*args))
+           {
+             tree arg0 = (*orig_args)[0];
+             tree arg1 = (*orig_args)[1];
+             tree arg2 = (*orig_args)[2];
+             int literal_mask = ((literal_integer_zerop (arg1) << 1)
+                                 | (literal_integer_zerop (arg2) << 2));
+             warn_for_memset (input_location, arg0, arg2, literal_mask);
+           }
+
          /* A call to a namespace-scope function.  */
          result = build_new_function_call (fn, args, complain);
        }
@@ -2557,10 +2616,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
       result = convert_from_reference (result);
     }
 
-  /* Free or retain OVERLOADs from lookup.  */
-  if (is_overloaded_fn (orig_fn))
-    lookup_keep (get_fns (orig_fn), processing_template_decl);
-
   return result;
 }
 
@@ -2693,13 +2748,14 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
   /* TODO: build_x_unary_op doesn't always honor the location.  */
   result.set_location (combined_loc);
 
-  tree result_ovl, expr_ovl;
+  if (result == error_mark_node)
+    return result;
 
   if (!(complain & tf_warning))
     return result;
 
-  result_ovl = result;
-  expr_ovl = expr;
+  tree result_ovl = result;
+  tree expr_ovl = expr;
 
   if (!processing_template_decl)
     expr_ovl = cp_fully_fold (expr_ovl);
@@ -2756,14 +2812,31 @@ finish_compound_literal (tree type, tree compound_literal,
          return error_mark_node;
       }
 
+  /* Used to hold a copy of the compound literal in a template.  */
+  tree orig_cl = NULL_TREE;
+
   if (processing_template_decl)
     {
-      TREE_TYPE (compound_literal) = type;
+      const bool dependent_p
+       = (instantiation_dependent_expression_p (compound_literal)
+          || dependent_type_p (type));
+      if (dependent_p)
+       /* We're about to return, no need to copy.  */
+       orig_cl = compound_literal;
+      else
+       /* We're going to need a copy.  */
+       orig_cl = unshare_constructor (compound_literal);
+      TREE_TYPE (orig_cl) = type;
       /* Mark the expression as a compound literal.  */
-      TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+      TREE_HAS_CONSTRUCTOR (orig_cl) = 1;
+      /* And as instantiation-dependent.  */
+      CONSTRUCTOR_IS_DEPENDENT (orig_cl) = dependent_p;
       if (fcl_context == fcl_c99)
-       CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
-      return compound_literal;
+       CONSTRUCTOR_C99_COMPOUND_LITERAL (orig_cl) = 1;
+      /* If the compound literal is dependent, we're done for now.  */
+      if (dependent_p)
+       return orig_cl;
+      /* Otherwise, do go on to e.g. check narrowing.  */
     }
 
   type = complete_type (type);
@@ -2784,9 +2857,13 @@ finish_compound_literal (tree type, tree compound_literal,
     return error_mark_node;
   compound_literal = reshape_init (type, compound_literal, complain);
   if (SCALAR_TYPE_P (type)
-      && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)
-      && !check_narrowing (type, compound_literal, complain))
-    return error_mark_node;
+      && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal))
+    {
+      tree t = instantiate_non_dependent_expr_sfinae (compound_literal,
+                                                     complain);
+      if (!check_narrowing (type, t, complain))
+       return error_mark_node;
+    }
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == NULL_TREE)
     {
@@ -2795,8 +2872,21 @@ finish_compound_literal (tree type, tree compound_literal,
       if (type == error_mark_node)
        return error_mark_node;
     }
-  compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL,
+  compound_literal = digest_init_flags (type, compound_literal,
+                                       LOOKUP_NORMAL | LOOKUP_NO_NARROWING,
                                        complain);
+  if (compound_literal == error_mark_node)
+    return error_mark_node;
+
+  /* If we're in a template, return the original compound literal.  */
+  if (orig_cl)
+    {
+      if (!VECTOR_TYPE_P (type))
+       return get_target_expr_sfinae (orig_cl, complain);
+      else
+       return orig_cl;
+    }
+
   if (TREE_CODE (compound_literal) == CONSTRUCTOR)
     {
       TREE_HAS_CONSTRUCTOR (compound_literal) = true;
@@ -2952,7 +3042,7 @@ begin_class_definition (tree t)
   if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
     return error_mark_node;
 
-  if (processing_template_parmlist)
+  if (processing_template_parmlist && !LAMBDA_TYPE_P (t))
     {
       error ("definition of %q#T inside template parameter list", t);
       return error_mark_node;
@@ -3404,11 +3494,12 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
        = decl_function_context (containing_function);
     }
 
-  /* In a lambda within a template, wait until instantiation
-     time to implicitly capture.  */
+  /* In a lambda within a template, wait until instantiation time to implicitly
+     capture a parameter pack.  We want to wait because we don't know if we're
+     capturing the whole pack or a single element, and it's OK to wait because
+     find_parameter_packs_r walks into the lambda body.  */
   if (context == containing_function
-      && DECL_TEMPLATE_INFO (containing_function)
-      && uses_template_parms (DECL_TI_ARGS (containing_function)))
+      && DECL_PACK_P (decl))
     return decl;
 
   if (lambda_expr && VAR_P (decl)
@@ -3497,20 +3588,20 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-cp_expr
-finish_id_expression (tree id_expression,
-                     tree decl,
-                     tree scope,
-                     cp_id_kind *idk,
-                     bool integral_constant_expression_p,
-                     bool allow_non_integral_constant_expression_p,
-                     bool *non_integral_constant_expression_p,
-                     bool template_p,
-                     bool done,
-                     bool address_p,
-                     bool template_arg_p,
-                     const char **error_msg,
-                     location_t location)
+static cp_expr
+finish_id_expression_1 (tree id_expression,
+                       tree decl,
+                       tree scope,
+                       cp_id_kind *idk,
+                       bool integral_constant_expression_p,
+                       bool allow_non_integral_constant_expression_p,
+                       bool *non_integral_constant_expression_p,
+                       bool template_p,
+                       bool done,
+                       bool address_p,
+                       bool template_arg_p,
+                       const char **error_msg,
+                       location_t location)
 {
   decl = strip_using_decl (decl);
 
@@ -3613,8 +3704,17 @@ finish_id_expression (tree id_expression,
       *idk = CP_ID_KIND_NONE;
       if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
        decl = TEMPLATE_PARM_DECL (decl);
-      r = convert_from_reference (DECL_INITIAL (decl));
-
+      r = DECL_INITIAL (decl);
+      if (CLASS_TYPE_P (TREE_TYPE (r)) && !CP_TYPE_CONST_P (TREE_TYPE (r)))
+       {
+         /* If the entity is a template parameter object for a template
+            parameter of type T, the type of the expression is const T.  */
+         tree ctype = TREE_TYPE (r);
+         ctype = cp_build_qualified_type (ctype, (cp_type_quals (ctype)
+                                                  | TYPE_QUAL_CONST));
+         r = build1 (VIEW_CONVERT_EXPR, ctype, r);
+       }
+      r = convert_from_reference (r);
       if (integral_constant_expression_p
          && !dependent_type_p (TREE_TYPE (decl))
          && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r))))
@@ -3695,18 +3795,10 @@ finish_id_expression (tree id_expression,
          *non_integral_constant_expression_p = true;
        }
 
-      tree wrap;
-      if (VAR_P (decl)
-         && !cp_unevaluated_operand
-         && !processing_template_decl
-         && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
-         && CP_DECL_THREAD_LOCAL_P (decl)
-         && (wrap = get_tls_wrapper_fn (decl)))
-       {
-         /* Replace an evaluated use of the thread_local variable with
-            a call to its wrapper.  */
-         decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
-       }
+      if (tree wrap = maybe_get_tls_wrapper_call (decl))
+       /* Replace an evaluated use of the thread_local variable with
+          a call to its wrapper.  */
+       decl = wrap;
       else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
               && !dependent_p
               && variable_template_p (TREE_OPERAND (decl, 0)))
@@ -3770,9 +3862,10 @@ finish_id_expression (tree id_expression,
            return error_mark_node;
 
          if (!template_arg_p
-             && TREE_CODE (first_fn) == FUNCTION_DECL
-             && DECL_FUNCTION_MEMBER_P (first_fn)
-             && !shared_member_p (decl))
+             && (TREE_CODE (first_fn) == USING_DECL
+                 || (TREE_CODE (first_fn) == FUNCTION_DECL
+                     && DECL_FUNCTION_MEMBER_P (first_fn)
+                     && !shared_member_p (decl))))
            {
              /* A set of member functions.  */
              decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
@@ -3805,6 +3898,34 @@ finish_id_expression (tree id_expression,
   return cp_expr (decl, location);
 }
 
+/* As per finish_id_expression_1, but adding a wrapper node
+   around the result if needed to express LOCATION.  */
+
+cp_expr
+finish_id_expression (tree id_expression,
+                     tree decl,
+                     tree scope,
+                     cp_id_kind *idk,
+                     bool integral_constant_expression_p,
+                     bool allow_non_integral_constant_expression_p,
+                     bool *non_integral_constant_expression_p,
+                     bool template_p,
+                     bool done,
+                     bool address_p,
+                     bool template_arg_p,
+                     const char **error_msg,
+                     location_t location)
+{
+  cp_expr result
+    = finish_id_expression_1 (id_expression, decl, scope, idk,
+                             integral_constant_expression_p,
+                             allow_non_integral_constant_expression_p,
+                             non_integral_constant_expression_p,
+                             template_p, done, address_p, template_arg_p,
+                             error_msg, location);
+  return result.maybe_add_location_wrapper ();
+}
+
 /* Implement the __typeof keyword: Return the type of EXPR, suitable for
    use as a type-specifier.  */
 
@@ -4023,6 +4144,9 @@ finish_offsetof (tree object_ptr, tree expr, location_t loc)
       return expr;
     }
 
+  if (expr == error_mark_node)
+    return error_mark_node;
+
   if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
     {
       error ("cannot apply %<offsetof%> to destructor %<~%T%>",
@@ -4214,7 +4338,7 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_INTERFACE_KNOWN (fn))
        /* We've already made a decision as to how this function will
           be handled.  */;
-      else if (!at_eof)
+      else if (!at_eof || DECL_OMP_DECLARE_REDUCTION_P (fn))
        tentative_decl_linkage (fn);
       else
        import_export_decl (fn);
@@ -4225,6 +4349,7 @@ expand_or_defer_fn_1 (tree fn)
         be emitted; there may be callers in other DLLs.  */
       if (DECL_DECLARED_INLINE_P (fn)
          && !DECL_REALLY_EXTERN (fn)
+         && !DECL_OMP_DECLARE_REDUCTION_P (fn)
          && (flag_keep_inline_functions
              || (flag_keep_inline_dllexport
                  && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4250,6 +4375,14 @@ expand_or_defer_fn_1 (tree fn)
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
+    {
+      /* Pretend that this function has been written out so that we don't try
+        to expand it again.  */
+      TREE_ASM_WRITTEN (fn) = 1;
+      return false;
+    }
+
+  if (DECL_OMP_DECLARE_REDUCTION_P (fn))
     return false;
 
   return true;
@@ -4565,7 +4698,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
          return error_mark_node;
        }
-      else if (TREE_CODE (t) == PARM_DECL
+      else if (ort == C_ORT_OMP
+              && TREE_CODE (t) == PARM_DECL
               && DECL_ARTIFICIAL (t)
               && DECL_NAME (t) == this_identifier)
        {
@@ -4589,7 +4723,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     }
 
   if (ort == C_ORT_OMP
-      && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+      && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+         || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
       && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
     TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
   ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
@@ -4648,7 +4784,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
       if (!integer_nonzerop (length))
        {
          if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            {
              if (integer_zerop (length))
                {
@@ -4714,7 +4852,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
              if (tree_int_cst_equal (size, low_bound))
                {
                  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    {
                      error_at (OMP_CLAUSE_LOCATION (c),
                                "zero length array section in %qs clause",
@@ -4733,7 +4873,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
          else if (length == NULL_TREE)
            {
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
                maybe_zero_len = true;
              if (first_non_one == types.length ())
                first_non_one++;
@@ -4769,7 +4911,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
       else if (length == NULL_TREE)
        {
          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
-             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+             && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
            maybe_zero_len = true;
          if (first_non_one == types.length ())
            first_non_one++;
@@ -4841,7 +4985,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
   bool maybe_zero_len = false;
   unsigned int first_non_one = 0;
   auto_vec<tree, 10> types;
-  tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+  tree *tp = &OMP_CLAUSE_DECL (c);
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+      && TREE_CODE (*tp) == TREE_LIST
+      && TREE_PURPOSE (*tp)
+      && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+    tp = &TREE_VALUE (*tp);
+  tree first = handle_omp_array_sections_1 (c, *tp, types,
                                            maybe_zero_len, first_non_one,
                                            ort);
   if (first == error_mark_node)
@@ -4850,7 +5000,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
     return false;
   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
     {
-      tree t = OMP_CLAUSE_DECL (c);
+      tree t = *tp;
       tree tem = NULL_TREE;
       if (processing_template_decl)
        return false;
@@ -4870,7 +5020,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
        }
       if (tem)
        first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
-      OMP_CLAUSE_DECL (c) = first;
+      *tp = first;
     }
   else
     {
@@ -4947,7 +5097,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
 
              if (i > first_non_one
                  && ((length && integer_nonzerop (length))
-                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION))
                continue;
              if (length)
                l = fold_convert (sizetype, length);
@@ -4975,7 +5127,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
                  tree eltype = TREE_TYPE (types[num - 1]);
                  while (TREE_CODE (eltype) == ARRAY_TYPE)
                    eltype = TREE_TYPE (eltype);
-                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
                    size = size_binop (EXACT_DIV_EXPR, size,
                                       size_in_bytes (eltype));
                  size = size_binop (MULT_EXPR, size, l);
@@ -4991,9 +5145,12 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
        {
          if (side_effects)
            size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
-         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+             || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
            {
              size = size_binop (MINUS_EXPR, size, size_one_node);
+             size = save_expr (size);
              tree index_type = build_index_type (size);
              tree eltype = TREE_TYPE (first);
              while (TREE_CODE (eltype) == ARRAY_TYPE)
@@ -5531,11 +5688,13 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
                                  TYPE_SIZE_UNIT (type));
          if (integer_zerop (size))
            {
-             error ("%qE in %<reduction%> clause is a zero size array",
-                    omp_clause_printable_decl (t));
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE in %<reduction%> clause is a zero size array",
+                       omp_clause_printable_decl (t));
              return true;
            }
          size = size_binop (MINUS_EXPR, size, size_one_node);
+         size = save_expr (size);
          tree index_type = build_index_type (size);
          tree atype = build_array_type (type, index_type);
          tree ptype = build_pointer_type (type);
@@ -5579,8 +5738,9 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
       }
   else if (TYPE_READONLY (type))
     {
-      error ("%qE has const type for %<reduction%>",
-            omp_clause_printable_decl (t));
+      error_at (OMP_CLAUSE_LOCATION (c),
+               "%qE has const type for %<reduction%>",
+               omp_clause_printable_decl (t));
       return true;
     }
   else if (!processing_template_decl)
@@ -5654,7 +5814,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
              if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0])))
                cxx_mark_addressable (placeholder);
              if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
-                 && !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
+                 && (decl_placeholder
+                     || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
                cxx_mark_addressable (decl_placeholder ? decl_placeholder
                                      : OMP_CLAUSE_DECL (c));
              tree omp_out = placeholder;
@@ -5680,7 +5841,9 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
            {
              gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
                          && TREE_CODE (stmts[4]) == DECL_EXPR);
-             if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
+             if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3]))
+                 && (decl_placeholder
+                     || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
                cxx_mark_addressable (decl_placeholder ? decl_placeholder
                                      : OMP_CLAUSE_DECL (c));
              if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
@@ -5741,8 +5904,9 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
     *need_dtor = true;
   else
     {
-      error ("user defined reduction not found for %qE",
-            omp_clause_printable_decl (t));
+      error_at (OMP_CLAUSE_LOCATION (c),
+               "user defined reduction not found for %qE",
+               omp_clause_printable_decl (t));
       return true;
     }
   if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
@@ -5763,7 +5927,8 @@ finish_omp_declare_simd_methods (tree t)
 
   for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
     {
-      if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
+      if (TREE_CODE (x) == USING_DECL
+         || !DECL_NONSTATIC_MEMBER_FUNCTION_P (x))
        continue;
       tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
       if (!ods || !TREE_VALUE (ods))
@@ -5823,6 +5988,155 @@ cp_finish_omp_clause_depend_sink (tree sink_clause)
   return false;
 }
 
+/* Finish OpenMP iterators ITER.  Return true if they are errorneous
+   and clauses containing them should be removed.  */
+
+static bool
+cp_omp_finish_iterators (tree iter)
+{
+  bool ret = false;
+  for (tree it = iter; it; it = TREE_CHAIN (it))
+    {
+      tree var = TREE_VEC_ELT (it, 0);
+      tree begin = TREE_VEC_ELT (it, 1);
+      tree end = TREE_VEC_ELT (it, 2);
+      tree step = TREE_VEC_ELT (it, 3);
+      tree orig_step;
+      tree type = TREE_TYPE (var);
+      location_t loc = DECL_SOURCE_LOCATION (var);
+      if (type == error_mark_node)
+       {
+         ret = true;
+         continue;
+       }
+      if (type_dependent_expression_p (var))
+       continue;
+      if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+       {
+         error_at (loc, "iterator %qD has neither integral nor pointer type",
+                   var);
+         ret = true;
+         continue;
+       }
+      else if (TYPE_READONLY (type))
+       {
+         error_at (loc, "iterator %qD has const qualified type", var);
+         ret = true;
+         continue;
+       }
+      if (type_dependent_expression_p (begin)
+         || type_dependent_expression_p (end)
+         || type_dependent_expression_p (step))
+       continue;
+      else if (error_operand_p (step))
+       {
+         ret = true;
+         continue;
+       }
+      else if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
+       {
+         error_at (EXPR_LOC_OR_LOC (step, loc),
+                   "iterator step with non-integral type");
+         ret = true;
+         continue;
+       }
+
+      begin = mark_rvalue_use (begin);
+      end = mark_rvalue_use (end);
+      step = mark_rvalue_use (step);
+      begin = cp_build_c_cast (type, begin, tf_warning_or_error);
+      end = cp_build_c_cast (type, end, tf_warning_or_error);
+      orig_step = step;
+      if (!processing_template_decl)
+       step = orig_step = save_expr (step);
+      tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+      step = cp_build_c_cast (stype, step, tf_warning_or_error);
+      if (POINTER_TYPE_P (type) && !processing_template_decl)
+       {
+         begin = save_expr (begin);
+         step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+         step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+                                 fold_convert (sizetype, step),
+                                 fold_convert (sizetype, begin));
+         step = fold_convert (ssizetype, step);
+       }
+      if (!processing_template_decl)
+       {
+         begin = maybe_constant_value (begin);
+         end = maybe_constant_value (end);
+         step = maybe_constant_value (step);
+         orig_step = maybe_constant_value (orig_step);
+       }
+      if (integer_zerop (step))
+       {
+         error_at (loc, "iterator %qD has zero step", var);
+         ret = true;
+         continue;
+       }
+
+      if (begin == error_mark_node
+         || end == error_mark_node
+         || step == error_mark_node
+         || orig_step == error_mark_node)
+       {
+         ret = true;
+         continue;
+       }
+
+      if (!processing_template_decl)
+       {
+         begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin);
+         end = fold_build_cleanup_point_expr (TREE_TYPE (end), end);
+         step = fold_build_cleanup_point_expr (TREE_TYPE (step), step);
+         orig_step = fold_build_cleanup_point_expr (TREE_TYPE (orig_step),
+                                                    orig_step);
+       }
+      hash_set<tree> pset;
+      tree it2;
+      for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+       {
+         tree var2 = TREE_VEC_ELT (it2, 0);
+         tree begin2 = TREE_VEC_ELT (it2, 1);
+         tree end2 = TREE_VEC_ELT (it2, 2);
+         tree step2 = TREE_VEC_ELT (it2, 3);
+         location_t loc2 = DECL_SOURCE_LOCATION (var2);
+         if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset))
+           {
+             error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+                       "begin expression refers to outer iterator %qD", var);
+             break;
+           }
+         else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset))
+           {
+             error_at (EXPR_LOC_OR_LOC (end2, loc2),
+                       "end expression refers to outer iterator %qD", var);
+             break;
+           }
+         else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset))
+           {
+             error_at (EXPR_LOC_OR_LOC (step2, loc2),
+                       "step expression refers to outer iterator %qD", var);
+             break;
+           }
+       }
+      if (it2)
+       {
+         ret = true;
+         continue;
+       }
+      TREE_VEC_ELT (it, 1) = begin;
+      TREE_VEC_ELT (it, 2) = end;
+      if (processing_template_decl)
+       TREE_VEC_ELT (it, 3) = orig_step;
+      else
+       {
+         TREE_VEC_ELT (it, 3) = step;
+         TREE_VEC_ELT (it, 4) = orig_step;
+       }
+    }
+  return ret;
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -5837,14 +6151,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool copyprivate_seen = false;
   bool ordered_seen = false;
   bool oacc_async = false;
+  tree last_iterators = NULL_TREE;
+  bool last_iterators_remove = false;
+  bool reduction_seen = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
   bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
   bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
   bitmap_initialize (&aligned_head, &bitmap_default_obstack);
+  /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead.  */
   bitmap_initialize (&map_head, &bitmap_default_obstack);
   bitmap_initialize (&map_field_head, &bitmap_default_obstack);
+  /* If ort == C_ORT_OMP used as nontemporal_head instead.  */
   bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
 
   if (ort & C_ORT_ACC)
@@ -5869,6 +6188,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
          goto check_dup_generic;
        case OMP_CLAUSE_REDUCTION:
+         reduction_seen = true;
+         /* FALLTHRU */
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
          t = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (t) == TREE_LIST)
@@ -5926,10 +6249,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                   || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL)
                  && !TYPE_REF_P (type))
                {
-                 error ("linear clause with %qs modifier applied to "
-                        "non-reference variable with %qT type",
-                        OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
-                        ? "ref" : "uval", TREE_TYPE (t));
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "linear clause with %qs modifier applied to "
+                           "non-reference variable with %qT type",
+                           OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
+                           ? "ref" : "uval", TREE_TYPE (t));
                  remove = true;
                  break;
                }
@@ -5940,8 +6264,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  if (!INTEGRAL_TYPE_P (type)
                      && !TYPE_PTR_P (type))
                    {
-                     error ("linear clause applied to non-integral non-pointer"
-                            " variable with %qT type", TREE_TYPE (t));
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "linear clause applied to non-integral "
+                               "non-pointer variable with %qT type",
+                               TREE_TYPE (t));
                      remove = true;
                      break;
                    }
@@ -5962,7 +6288,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                       || !TYPE_REF_P (TREE_TYPE (t))
                       || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (t)))))
            {
-             error ("linear step expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "linear step expression must be integral");
              remove = true;
              break;
            }
@@ -6054,8 +6381,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
                      && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
              remove = true;
              break;
            }
@@ -6065,11 +6393,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
-               error ("%qD is not a variable in clause %qs", t,
-                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in clause %qs", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              else
-               error ("%qE is not a variable in clause %qs", t,
-                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in clause %qs", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              remove = true;
            }
          else if (ort == C_ORT_ACC
@@ -6077,7 +6407,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            {
              if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
                {
-                 error ("%qD appears more than once in reduction clauses", t);
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qD appears more than once in reduction clauses",
+                           t);
                  remove = true;
                }
              else
@@ -6087,16 +6419,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                   || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
                   || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
            {
-             error ("%qD appears more than once in data clauses", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD appears more than once in data clauses", t);
              remove = true;
            }
          else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
                   && bitmap_bit_p (&map_head, DECL_UID (t)))
            {
              if (ort == C_ORT_ACC)
-               error ("%qD appears more than once in data clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in data clauses", t);
              else
-               error ("%qD appears both in data and map clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears both in data and map clauses", t);
              remove = true;
            }
          else
@@ -6125,8 +6460,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            t = OMP_CLAUSE_DECL (c);
          if (ort != C_ORT_ACC && t == current_class_ptr)
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
              remove = true;
              break;
            }
@@ -6137,23 +6473,30 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
-               error ("%qD is not a variable in clause %<firstprivate%>", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in clause %<firstprivate%>",
+                         t);
              else
-               error ("%qE is not a variable in clause %<firstprivate%>", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in clause %<firstprivate%>",
+                         t);
              remove = true;
            }
          else if (bitmap_bit_p (&generic_head, DECL_UID (t))
                   || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
            {
-             error ("%qD appears more than once in data clauses", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD appears more than once in data clauses", t);
              remove = true;
            }
          else if (bitmap_bit_p (&map_head, DECL_UID (t)))
            {
              if (ort == C_ORT_ACC)
-               error ("%qD appears more than once in data clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in data clauses", t);
              else
-               error ("%qD appears both in data and map clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears both in data and map clauses", t);
              remove = true;
            }
          else
@@ -6168,8 +6511,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            t = OMP_CLAUSE_DECL (c);
          if (t == current_class_ptr)
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
              remove = true;
              break;
            }
@@ -6180,15 +6524,20 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
-               error ("%qD is not a variable in clause %<lastprivate%>", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in clause %<lastprivate%>",
+                         t);
              else
-               error ("%qE is not a variable in clause %<lastprivate%>", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in clause %<lastprivate%>",
+                         t);
              remove = true;
            }
          else if (bitmap_bit_p (&generic_head, DECL_UID (t))
                   || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
            {
-             error ("%qD appears more than once in data clauses", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD appears more than once in data clauses", t);
              remove = true;
            }
          else
@@ -6225,7 +6574,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              else if (!type_dependent_expression_p (t)
                       && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
                {
-                 error ("%<gang%> static expression must be integral");
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%<gang%> static expression must be integral");
                  remove = true;
                }
              else
@@ -6329,30 +6679,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          break;
 
        case OMP_CLAUSE_SCHEDULE:
-         if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
-           {
-             const char *p = NULL;
-             switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
-               {
-               case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break;
-               case OMP_CLAUSE_SCHEDULE_DYNAMIC: break;
-               case OMP_CLAUSE_SCHEDULE_GUIDED: break;
-               case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break;
-               case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break;
-               default: gcc_unreachable ();
-               }
-             if (p)
-               {
-                 error_at (OMP_CLAUSE_LOCATION (c),
-                           "%<nonmonotonic%> modifier specified for %qs "
-                           "schedule kind", p);
-                 OMP_CLAUSE_SCHEDULE_KIND (c)
-                   = (enum omp_clause_schedule_kind)
-                     (OMP_CLAUSE_SCHEDULE_KIND (c)
-                      & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
-               }
-           }
-
          t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
          if (t == NULL)
            ;
@@ -6361,7 +6687,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("schedule chunk size expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "schedule chunk size expression must be integral");
              remove = true;
            }
          else
@@ -6391,8 +6718,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%qs length expression must be integral",
-                    omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qs length expression must be integral",
+                       omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              remove = true;
            }
          else
@@ -6404,9 +6732,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  if (TREE_CODE (t) != INTEGER_CST
                      || tree_int_cst_sgn (t) != 1)
                    {
-                     error ("%qs length expression must be positive constant"
-                            " integer expression",
-                            omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%qs length expression must be positive "
+                               "constant integer expression",
+                               omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
                      remove = true;
                    }
                }
@@ -6423,7 +6752,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<async%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<async%> expression must be integral");
              remove = true;
            }
          else
@@ -6451,7 +6781,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<thread_limit%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<thread_limit%> expression must be integral");
              remove = true;
            }
          else
@@ -6480,7 +6811,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<device%> id must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<device%> id must be integral");
              remove = true;
            }
          else
@@ -6501,14 +6833,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<dist_schedule%> chunk size expression must be "
-                    "integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<dist_schedule%> chunk size expression must be "
+                       "integral");
              remove = true;
            }
          else
            {
              t = mark_rvalue_use (t);
-             if (!processing_template_decl)
+             if (!processing_template_decl)
                t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
              OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
            }
@@ -6518,8 +6851,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          t = OMP_CLAUSE_DECL (c);
          if (t == current_class_ptr && ort != C_ORT_OMP_DECLARE_SIMD)
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
              remove = true;
              break;
            }
@@ -6528,9 +6862,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
                break;
              if (DECL_P (t))
-               error ("%qD is not a variable in %<aligned%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in %<aligned%> clause", t);
              else
-               error ("%qE is not a variable in %<aligned%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in %<aligned%> clause", t);
              remove = true;
            }
          else if (!type_dependent_expression_p (t)
@@ -6548,7 +6884,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
            {
-             error ("%qD appears more than once in %<aligned%> clauses", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD appears more than once in %<aligned%> clauses",
+                       t);
              remove = true;
            }
          else
@@ -6561,8 +6899,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<aligned%> clause alignment expression must "
-                    "be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<aligned%> clause alignment expression must "
+                       "be integral");
              remove = true;
            }
          else
@@ -6574,15 +6913,45 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  if (TREE_CODE (t) != INTEGER_CST
                      || tree_int_cst_sgn (t) != 1)
                    {
-                     error ("%<aligned%> clause alignment expression must be "
-                            "positive constant integer expression");
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%<aligned%> clause alignment expression must "
+                               "be positive constant integer expression");
                      remove = true;
                    }
+                 else
+                   t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
                }
              OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
            }
          break;
 
+       case OMP_CLAUSE_NONTEMPORAL:
+         t = OMP_CLAUSE_DECL (c);
+         if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+           {
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+               break;
+             if (DECL_P (t))
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in %<nontemporal%> clause",
+                         t);
+             else
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in %<nontemporal%> clause",
+                         t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD appears more than once in %<nontemporal%> "
+                       "clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
+         break;
+
        case OMP_CLAUSE_DEPEND:
          t = OMP_CLAUSE_DECL (c);
          if (t == NULL_TREE)
@@ -6597,33 +6966,108 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                remove = true;
              break;
            }
+         if (TREE_CODE (t) == TREE_LIST
+             && TREE_PURPOSE (t)
+             && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+           {
+             if (TREE_PURPOSE (t) != last_iterators)
+               last_iterators_remove
+                 = cp_omp_finish_iterators (TREE_PURPOSE (t));
+             last_iterators = TREE_PURPOSE (t);
+             t = TREE_VALUE (t);
+             if (last_iterators_remove)
+               t = error_mark_node;
+           }
+         else
+           last_iterators = NULL_TREE;
+
          if (TREE_CODE (t) == TREE_LIST)
            {
              if (handle_omp_array_sections (c, ort))
                remove = true;
+             else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%<depend%> clause with %<depobj%> dependence "
+                           "type on array section");
+                 remove = true;
+               }
              break;
            }
          if (t == error_mark_node)
            remove = true;
-         else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+         else if (t == current_class_ptr)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
+             remove = true;
+           }
+         else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+           break;
+         else if (!lvalue_p (t))
            {
-             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
-               break;
              if (DECL_P (t))
-               error ("%qD is not a variable in %<depend%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not lvalue expression nor array section "
+                         "in %<depend%> clause", t);
              else
-               error ("%qE is not a variable in %<depend%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not lvalue expression nor array section "
+                         "in %<depend%> clause", t);
              remove = true;
            }
-         else if (t == current_class_ptr)
+         else if (TREE_CODE (t) == COMPONENT_REF
+                  && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
+                  && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "bit-field %qE in %qs clause", t, "depend");
              remove = true;
            }
-         else if (!processing_template_decl
-                  && !cxx_mark_addressable (t))
-           remove = true;
+         else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+           {
+             if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+                                    ? TREE_TYPE (TREE_TYPE (t))
+                                    : TREE_TYPE (t)))
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qE does not have %<omp_depend_t%> type in "
+                           "%<depend%> clause with %<depobj%> dependence "
+                           "type", t);
+                 remove = true;
+               }
+           }
+         else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+                                    ? TREE_TYPE (TREE_TYPE (t))
+                                    : TREE_TYPE (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE should not have %<omp_depend_t%> type in "
+                       "%<depend%> clause with dependence type other than "
+                       "%<depobj%>", t);
+             remove = true;
+           }
+         if (!remove)
+           {
+             tree addr = cp_build_addr_expr (t, tf_warning_or_error);
+             if (addr == error_mark_node)
+               remove = true;
+             else
+               {
+                 t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+                                            tf_warning_or_error);
+                 if (t == error_mark_node)
+                   remove = true;
+                 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+                          && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+                          && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+                              == TREE_VEC))
+                   TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+                 else
+                   OMP_CLAUSE_DECL (c) = t;
+               }
+           }
          break;
 
        case OMP_CLAUSE_MAP:
@@ -6662,14 +7106,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                      if (bitmap_bit_p (&map_head, DECL_UID (t)))
                        {
                          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
-                           error ("%qD appears more than once in motion"
-                                  " clauses", t);
+                           error_at (OMP_CLAUSE_LOCATION (c),
+                                     "%qD appears more than once in motion"
+                                     " clauses", t);
                          else if (ort == C_ORT_ACC)
-                           error ("%qD appears more than once in data"
-                                  " clauses", t);
+                           error_at (OMP_CLAUSE_LOCATION (c),
+                                     "%qD appears more than once in data"
+                                     " clauses", t);
                          else
-                           error ("%qD appears more than once in map"
-                                  " clauses", t);
+                           error_at (OMP_CLAUSE_LOCATION (c),
+                                     "%qD appears more than once in map"
+                                     " clauses", t);
                          remove = true;
                        }
                      else
@@ -6745,23 +7192,27 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                      || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
                break;
              if (DECL_P (t))
-               error ("%qD is not a variable in %qs clause", t,
-                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in %qs clause", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              else
-               error ("%qE is not a variable in %qs clause", t,
-                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in %qs clause", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              remove = true;
            }
          else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
            {
-             error ("%qD is threadprivate variable in %qs clause", t,
-                    omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD is threadprivate variable in %qs clause", t,
+                       omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              remove = true;
            }
          else if (ort != C_ORT_ACC && t == current_class_ptr)
            {
-             error ("%<this%> allowed in OpenMP only in %<declare simd%>"
-                    " clauses");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
              remove = true;
              break;
            }
@@ -6792,7 +7243,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                   && !type_dependent_expression_p (t)
                   && !INDIRECT_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%qD is not a pointer variable", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qD is not a pointer variable", t);
              remove = true;
            }
          else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
@@ -6801,15 +7253,18 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (bitmap_bit_p (&generic_head, DECL_UID (t))
                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
                {
-                 error ("%qD appears more than once in data clauses", t);
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qD appears more than once in data clauses", t);
                  remove = true;
                }
              else if (bitmap_bit_p (&map_head, DECL_UID (t)))
                {
                  if (ort == C_ORT_ACC)
-                   error ("%qD appears more than once in data clauses", t);
+                   error_at (OMP_CLAUSE_LOCATION (c),
+                             "%qD appears more than once in data clauses", t);
                  else
-                   error ("%qD appears both in data and map clauses", t);
+                   error_at (OMP_CLAUSE_LOCATION (c),
+                             "%qD appears both in data and map clauses", t);
                  remove = true;
                }
              else
@@ -6818,20 +7273,25 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (bitmap_bit_p (&map_head, DECL_UID (t)))
            {
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
-               error ("%qD appears more than once in motion clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in motion clauses", t);
              if (ort == C_ORT_ACC)
-               error ("%qD appears more than once in data clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in data clauses", t);
              else
-               error ("%qD appears more than once in map clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in map clauses", t);
              remove = true;
            }
          else if (bitmap_bit_p (&generic_head, DECL_UID (t))
                   || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
            {
              if (ort == C_ORT_ACC)
-               error ("%qD appears more than once in data clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears more than once in data clauses", t);
              else
-               error ("%qD appears both in data and map clauses", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD appears both in data and map clauses", t);
              remove = true;
            }
          else
@@ -6844,7 +7304,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        handle_map_references:
          if (!remove
              && !processing_template_decl
-             && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+             && ort != C_ORT_DECLARE_SIMD
              && TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
            {
              t = OMP_CLAUSE_DECL (c);
@@ -6946,9 +7406,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              if (processing_template_decl)
                break;
              if (DECL_P (t))
-               error ("%qD is not an argument in %<uniform%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not an argument in %<uniform%> clause", t);
              else
-               error ("%qE is not an argument in %<uniform%> clause", t);
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not an argument in %<uniform%> clause", t);
              remove = true;
              break;
            }
@@ -6963,7 +7425,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<grainsize%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<grainsize%> expression must be integral");
              remove = true;
            }
          else
@@ -6992,7 +7455,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<priority%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<priority%> expression must be integral");
              remove = true;
            }
          else
@@ -7021,7 +7485,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%<num_tasks%> expression must be integral");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<hint%> expression must be integral");
              remove = true;
            }
          else
@@ -7031,6 +7496,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                {
                  t = maybe_constant_value (t);
                  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+                 if (TREE_CODE (t) != INTEGER_CST)
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%<hint%> expression must be constant integer "
+                               "expression");
+                     remove = true;
+                   }
                }
              OMP_CLAUSE_HINT_EXPR (c) = t;
            }
@@ -7075,6 +7547,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_INDEPENDENT:
        case OMP_CLAUSE_SEQ:
+       case OMP_CLAUSE_IF_PRESENT:
+       case OMP_CLAUSE_FINALIZE:
          break;
 
        case OMP_CLAUSE_TILE:
@@ -7125,8 +7599,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_NOTINBRANCH:
          if (branch_seen)
            {
-             error ("%<inbranch%> clause is incompatible with "
-                    "%<notinbranch%>");
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<inbranch%> clause is incompatible with "
+                       "%<notinbranch%>");
              remove = true;
            }
          branch_seen = true;
@@ -7177,6 +7652,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_LINEAR:
@@ -7229,6 +7706,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
+       case OMP_CLAUSE_NOGROUP:
+         if (reduction_seen)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<nogroup%> clause must not be used together with "
+                       "%<reduction%> clause");
+             *pc = OMP_CLAUSE_CHAIN (c);
+             continue;
+           }
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
        case OMP_CLAUSE_NOWAIT:
          if (copyprivate_seen)
            {
@@ -7263,6 +7751,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          break;
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
          if (finish_omp_reduction_clause (c, &need_default_ctor,
                                           &need_dtor))
            remove = true;
@@ -7273,7 +7763,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_COPYIN:
          if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
            {
-             error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE must be %<threadprivate%> for %<copyin%>", t);
              remove = true;
            }
          break;
@@ -7287,7 +7778,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          t = require_complete_type (t);
          if (t == error_mark_node)
            remove = true;
-         else if (TYPE_REF_P (TREE_TYPE (t))
+         else if (!processing_template_decl
+                  && TYPE_REF_P (TREE_TYPE (t))
                   && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
            remove = true;
        }
@@ -7302,10 +7794,24 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
              break;
            case OMP_CLAUSE_DEFAULT_SHARED:
-             /* const vars may be specified in firstprivate clause.  */
-             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
-                 && cxx_omp_const_qual_no_mutable (t))
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+                 && c_omp_predefined_variable (t))
+               /* The __func__ variable and similar function-local predefined
+                  variables may be listed in a shared or firstprivate
+                  clause.  */
                break;
+             if (VAR_P (t)
+                 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                 && TREE_STATIC (t)
+                 && cxx_omp_const_qual_no_mutable (t))
+               {
+                 tree ctx = CP_DECL_CONTEXT (t);
+                 /* const qualified static data members without mutable
+                    member may be specified in firstprivate clause.  */
+                 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
+                   break;
+               }
              share_name = "shared";
              break;
            case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -7316,9 +7822,20 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          if (share_name)
            {
-             error ("%qE is predetermined %qs for %qs",
-                    omp_clause_printable_decl (t), share_name,
-                    omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE is predetermined %qs for %qs",
+                       omp_clause_printable_decl (t), share_name,
+                       omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             remove = true;
+           }
+         else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED
+                  && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE
+                  && cxx_omp_const_qual_no_mutable (t))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<const%> qualified %qE without %<mutable%> member "
+                       "may appear only in %<shared%> or %<firstprivate%> "
+                       "clauses", omp_clause_printable_decl (t));
              remove = true;
            }
        }
@@ -7327,7 +7844,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
       inner_type = type = TREE_TYPE (t);
       if ((need_complete_type
           || need_copy_assignment
-          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+          || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
          && TYPE_REF_P (inner_type))
        inner_type = TREE_TYPE (inner_type);
       while (TREE_CODE (inner_type) == ARRAY_TYPE)
@@ -7528,14 +8047,7 @@ finish_omp_threadprivate (tree vars)
        {
          /* Allocate a LANG_SPECIFIC structure for V, if needed.  */
          if (DECL_LANG_SPECIFIC (v) == NULL)
-           {
-             retrofit_lang_decl (v);
-
-             /* Make sure that DECL_DISCRIMINATOR_P continues to be true
-                after the allocation of the lang_decl structure.  */
-             if (DECL_DISCRIMINATOR_P (v))
-               DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1;
-           }
+           retrofit_lang_decl (v);
 
          if (! CP_DECL_THREAD_LOCAL_P (v))
            {
@@ -7671,7 +8183,7 @@ static bool
 handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
                               tree declv, tree orig_declv, tree initv,
                               tree condv, tree incrv, tree *body,
-                              tree *pre_body, tree &clauses, tree *lastp,
+                              tree *pre_body, tree &clauses,
                               int collapse, int ordered)
 {
   tree diff, iter_init, iter_incr = NULL, last;
@@ -7686,7 +8198,6 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   if (init && EXPR_HAS_LOCATION (init))
     elocus = EXPR_LOCATION (init);
 
-  cond = cp_fully_fold (cond);
   switch (TREE_CODE (cond))
     {
     case GT_EXPR:
@@ -7836,6 +8347,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
     }
 
   incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+  incr = cp_fully_fold (incr);
   bool taskloop_iv_seen = false;
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -7971,11 +8483,22 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
        = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
     }
 
+  if (TREE_CODE (TREE_VEC_ELT (orig_declv, i)) == TREE_LIST)
+    {
+      tree t = TREE_VEC_ELT (orig_declv, i);
+      gcc_assert (TREE_PURPOSE (t) == NULL_TREE
+                 && TREE_VALUE (t) == NULL_TREE
+                 && TREE_CODE (TREE_CHAIN (t)) == TREE_VEC);
+      TREE_PURPOSE (t) = TREE_VEC_ELT (declv, i);
+      TREE_VALUE (t) = last;
+    }
+  else
+    TREE_VEC_ELT (orig_declv, i)
+      = tree_cons (TREE_VEC_ELT (declv, i), last, NULL_TREE);
   TREE_VEC_ELT (declv, i) = decl;
   TREE_VEC_ELT (initv, i) = init;
   TREE_VEC_ELT (condv, i) = cond;
   TREE_VEC_ELT (incrv, i) = incr;
-  *lastp = last;
 
   return false;
 }
@@ -7994,7 +8517,6 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
 {
   tree omp_for = NULL, orig_incr = NULL;
   tree decl = NULL, init, cond, incr;
-  tree last = NULL_TREE;
   location_t elocus;
   int i;
   int collapse = 1;
@@ -8058,6 +8580,9 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
       if (init && EXPR_HAS_LOCATION (init))
        elocus = EXPR_LOCATION (init);
 
+      if (cond == global_namespace)
+       continue;
+
       if (cond == NULL)
        {
          error_at (elocus, "missing controlling predicate");
@@ -8080,7 +8605,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
       tree orig_init;
       FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
        if (orig_init
-           && !c_omp_check_loop_iv_exprs (locus, declv,
+           && !c_omp_check_loop_iv_exprs (locus, orig_declv
+                                                 ? orig_declv : declv,
                                           TREE_VEC_ELT (declv, i), orig_init,
                                           NULL_TREE, cp_walk_subtrees))
          fail = true;
@@ -8161,7 +8687,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
            }
          if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv,
                                             initv, condv, incrv, &body,
-                                            &pre_body, clauses, &last,
+                                            &pre_body, clauses,
                                             collapse, ordered))
            return NULL;
          continue;
@@ -8213,11 +8739,12 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
       i++;
     }
 
-  if (IS_EMPTY_STMT (pre_body))
+  if (pre_body && IS_EMPTY_STMT (pre_body))
     pre_body = NULL;
 
   omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
-                             incrv, body, pre_body);
+                             incrv, body, pre_body,
+                             !processing_template_decl);
 
   /* Check for iterators appearing in lb, b or incr expressions.  */
   if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees))
@@ -8329,9 +8856,55 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
   return omp_for;
 }
 
+/* Fix up range for decls.  Those decls were pushed into BIND's BIND_EXPR_VARS
+   and need to be moved into the BIND_EXPR inside of the OMP_FOR's body.  */
+
+tree
+finish_omp_for_block (tree bind, tree omp_for)
+{
+  if (omp_for == NULL_TREE
+      || !OMP_FOR_ORIG_DECLS (omp_for)
+      || bind == NULL_TREE
+      || TREE_CODE (bind) != BIND_EXPR)
+    return bind;
+  tree b = NULL_TREE;
+  for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (omp_for)); i++)
+    if (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) == TREE_LIST
+       && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)))
+      {
+       tree v = TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i));
+       gcc_assert (BIND_EXPR_BLOCK (bind)
+                   && (BIND_EXPR_VARS (bind)
+                       == BLOCK_VARS (BIND_EXPR_BLOCK (bind))));
+       for (int j = 2; j < TREE_VEC_LENGTH (v); j++)
+         for (tree *p = &BIND_EXPR_VARS (bind); *p; p = &DECL_CHAIN (*p))
+           {
+             if (*p == TREE_VEC_ELT (v, j))
+               {
+                 tree var = *p;
+                 *p = DECL_CHAIN (*p);
+                 if (b == NULL_TREE)
+                   {
+                     b = make_node (BLOCK);
+                     b = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+                                 OMP_FOR_BODY (omp_for), b);
+                     TREE_SIDE_EFFECTS (b) = 1;
+                     OMP_FOR_BODY (omp_for) = b;
+                   }
+                 DECL_CHAIN (var) = BIND_EXPR_VARS (b);
+                 BIND_EXPR_VARS (b) = var;
+                 BLOCK_VARS (BIND_EXPR_BLOCK (b)) = var;
+               }
+           }
+       BLOCK_VARS (BIND_EXPR_BLOCK (bind)) = BIND_EXPR_VARS (bind);
+      }
+  return bind;
+}
+
 void
-finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
-                  tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
+finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
+                  tree lhs, tree rhs, tree v, tree lhs1, tree rhs1,
+                  tree clauses, enum omp_memory_order mo)
 {
   tree orig_lhs;
   tree orig_rhs;
@@ -8358,6 +8931,15 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
                     || (v && type_dependent_expression_p (v))
                     || (lhs1 && type_dependent_expression_p (lhs1))
                     || (rhs1 && type_dependent_expression_p (rhs1)));
+      if (clauses)
+       {
+         gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE
+                     && OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT
+                     && OMP_CLAUSE_CHAIN (clauses) == NULL_TREE);
+         if (type_dependent_expression_p (OMP_CLAUSE_HINT_EXPR (clauses))
+             || TREE_CODE (OMP_CLAUSE_HINT_EXPR (clauses)) != INTEGER_CST)
+           dependent_p = true;
+       }
       if (!dependent_p)
        {
          lhs = build_non_dependent_expr (lhs);
@@ -8399,8 +8981,8 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
                   "expressions for memory");
          return;
        }
-      stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
-                                 v, lhs1, rhs1, swapped, seq_cst,
+      stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs,
+                                 v, lhs1, rhs1, swapped, mo,
                                  processing_template_decl != 0);
       if (stmt == error_mark_node)
        return;
@@ -8409,9 +8991,8 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
     {
       if (code == OMP_ATOMIC_READ)
        {
-         stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
-                                  OMP_ATOMIC_READ, orig_lhs);
-         OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+         stmt = build_min_nt_loc (loc, OMP_ATOMIC_READ, orig_lhs);
+         OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
          stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
        }
       else
@@ -8425,15 +9006,21 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
                                     COMPOUND_EXPR, orig_rhs1, stmt);
          if (code != OMP_ATOMIC)
            {
-             stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
-                                      code, orig_lhs1, stmt);
-             OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+             stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt);
+             OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
              stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
            }
        }
-      stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
-      OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+      stmt = build2 (OMP_ATOMIC, void_type_node,
+                    clauses ? clauses : integer_zero_node, stmt);
+      OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+      SET_EXPR_LOCATION (stmt, loc);
     }
+
+  /* Avoid -Wunused-value warnings here, the whole construct has side-effects
+     and even if it might be wrapped from fold-const.c or c-omp.c wrapped
+     in some tree that appears to be unused, the value is not unused.  */
+  warning_sentinel w (warn_unused_value);
   finish_expr_stmt (stmt);
 }
 
@@ -8448,10 +9035,50 @@ finish_omp_barrier (void)
 }
 
 void
-finish_omp_flush (void)
+finish_omp_depobj (location_t loc, tree depobj,
+                  enum omp_clause_depend_kind kind, tree clause)
+{
+  if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj))
+    {
+      if (!lvalue_p (depobj))
+       {
+         error_at (EXPR_LOC_OR_LOC (depobj, loc),
+                   "%<depobj%> expression is not lvalue expression");
+         depobj = error_mark_node;
+       }
+    }
+
+  if (processing_template_decl)
+    {
+      if (clause == NULL_TREE)
+       clause = build_int_cst (integer_type_node, kind);
+      add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause));
+      return;
+    }
+
+  if (!error_operand_p (depobj))
+    {
+      tree addr = cp_build_addr_expr (depobj, tf_warning_or_error);
+      if (addr == error_mark_node)
+       depobj = error_mark_node;
+      else
+       depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+                                       tf_warning_or_error);
+    }
+
+  c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+void
+finish_omp_flush (int mo)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   vec<tree, va_gc> *vec = make_tree_vector ();
+  if (mo != MEMMODEL_LAST)
+    {
+      fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
+      vec->quick_push (build_int_cst (integer_type_node, mo));
+    }
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
@@ -8500,10 +9127,30 @@ finish_omp_cancel (tree clauses)
   tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
   if (ifc != NULL_TREE)
     {
-      tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
-      ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
-                            boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc),
-                            build_zero_cst (type));
+      if (OMP_CLAUSE_IF_MODIFIER (ifc) != ERROR_MARK
+         && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST)
+       error_at (OMP_CLAUSE_LOCATION (ifc),
+                 "expected %<cancel%> %<if%> clause modifier");
+      else
+       {
+         tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF);
+         if (ifc2 != NULL_TREE)
+           {
+             gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST
+                         && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK
+                         && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST);
+             error_at (OMP_CLAUSE_LOCATION (ifc2),
+                       "expected %<cancel%> %<if%> clause modifier");
+           }
+       }
+
+      if (!processing_template_decl)
+       ifc = maybe_convert_cond (OMP_CLAUSE_IF_EXPR (ifc));
+      else
+       ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
+                                OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK,
+                                integer_zero_node, ERROR_MARK,
+                                NULL, tf_warning_or_error);
     }
   else
     ifc = boolean_true_node;
@@ -8668,7 +9315,8 @@ finish_static_assert (tree condition, tree message, location_t location,
   /* Fold the expression and convert it to a boolean value. */
   condition = perform_implicit_conversion_flags (boolean_type_node, condition,
                                                 complain, LOOKUP_NORMAL);
-  condition = fold_non_dependent_expr (condition);
+  condition = fold_non_dependent_expr (condition, complain,
+                                      /*manifestly_const_eval=*/true);
 
   if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
     /* Do nothing; the condition is satisfied. */
@@ -8771,7 +9419,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
       if (identifier_p (expr))
         expr = lookup_name (expr);
 
-      if (INDIRECT_REF_P (expr))
+      if (INDIRECT_REF_P (expr)
+         || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
         /* This can happen when the expression is, e.g., "a.b". Just
            look at the underlying operand.  */
         expr = TREE_OPERAND (expr, 0);
@@ -8913,8 +9562,8 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
       if (copy_fn_p (fn) > 0)
        {
          saw_copy = true;
-         maybe_instantiate_noexcept (fn);
-         if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
+         if (!maybe_instantiate_noexcept (fn)
+             || !TYPE_NOTHROW_P (TREE_TYPE (fn)))
            return false;
        }
     }
@@ -8956,8 +9605,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
       return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
              || (CLASS_TYPE_P (type1)
                  && (t = locate_ctor (type1))
-                 && (maybe_instantiate_noexcept (t),
-                     TYPE_NOTHROW_P (TREE_TYPE (t)))));
+                 && maybe_instantiate_noexcept (t)
+                 && TYPE_NOTHROW_P (TREE_TYPE (t))));
 
     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
       type1 = strip_array_types (type1);
@@ -9243,12 +9892,12 @@ static tree
 capture_decltype (tree decl)
 {
   tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
-  /* FIXME do lookup instead of list walk? */
-  tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam));
+  tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
+                              /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
   tree type;
 
-  if (cap)
-    type = TREE_TYPE (TREE_PURPOSE (cap));
+  if (cap && is_capture_proxy (cap))
+    type = TREE_TYPE (cap);
   else
     switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam))
       {
@@ -9374,4 +10023,27 @@ finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain)
                                       TREE_TYPE (arg), 1, arg);
 }
 
+/* Finish __builtin_convertvector (arg, type).  */
+
+tree
+cp_build_vec_convert (tree arg, location_t loc, tree type,
+                     tsubst_flags_t complain)
+{
+  if (error_operand_p (type))
+    return error_mark_node;
+  if (error_operand_p (arg))
+    return error_mark_node;
+
+  tree ret = NULL_TREE;
+  if (!type_dependent_expression_p (arg) && !dependent_type_p (type))
+    ret = c_build_vec_convert (cp_expr_loc_or_loc (arg, input_location),
+                              decay_conversion (arg, complain),
+                              loc, type, (complain & tf_error) != 0);
+
+  if (!processing_template_decl)
+    return ret;
+
+  return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg);
+}
+
 #include "gt-cp-semantics.h"
This page took 0.097084 seconds and 5 git commands to generate.