]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/semantics.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / semantics.c
index 8c893ed64b0098a7a262379610c37e636ac3f511..3669b247e3468d142b9acd2deb31a474ae06550b 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-2020 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
@@ -645,10 +646,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 +657,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_input_loc (cond),
+                    OPT_Wparentheses, "suggest parentheses around "
+                                      "assignment used as truth value"))
+    TREE_NO_WARNING (cond) = 1;
 
   return condition_conversion (cond);
 }
@@ -686,7 +686,7 @@ finish_expr_stmt (tree expr)
          expr = convert_to_void (expr, ICV_STATEMENT, tf_warning_or_error);
        }
       else if (!type_dependent_expression_p (expr))
-       convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT, 
+       convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT,
                          tf_warning_or_error);
 
       if (check_for_bare_parameter_packs (expr))
@@ -723,6 +723,28 @@ begin_if_stmt (void)
   return r;
 }
 
+/* Returns true if FN, a CALL_EXPR, is a call to
+   std::is_constant_evaluated or __builtin_is_constant_evaluated.  */
+
+static bool
+is_std_constant_evaluated_p (tree fn)
+{
+  /* std::is_constant_evaluated takes no arguments.  */
+  if (call_expr_nargs (fn) != 0)
+    return false;
+
+  tree fndecl = cp_get_callee_fndecl_nofold (fn);
+  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+                        BUILT_IN_FRONTEND))
+    return true;
+
+  if (!decl_in_std_namespace_p (fndecl))
+    return false;
+
+  tree name = DECL_NAME (fndecl);
+  return name && id_equal (name, "is_constant_evaluated");
+}
+
 /* Process the COND of an if-statement, which may be given by
    IF_STMT.  */
 
@@ -736,8 +758,22 @@ finish_if_stmt_cond (tree cond, tree if_stmt)
       && !instantiation_dependent_expression_p (cond)
       /* Wait until instantiation time, since only then COND has been
         converted to bool.  */
-      && TREE_TYPE (cond) == boolean_type_node)
+      && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node)
     {
+      /* if constexpr (std::is_constant_evaluated()) is always true,
+        so give the user a clue.  */
+      if (warn_tautological_compare)
+       {
+         tree t = cond;
+         if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
+           t = TREE_OPERAND (t, 0);
+         if (TREE_CODE (t) == CALL_EXPR
+             && is_std_constant_evaluated_p (t))
+           warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare,
+                       "%qs always evaluates to true in %<if constexpr%>",
+                       "std::is_constant_evaluated");
+       }
+
       cond = instantiate_non_dependent_expr (cond);
       cond = cxx_constant_value (cond, NULL_TREE);
     }
@@ -774,6 +810,18 @@ finish_else_clause (tree if_stmt)
   ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt));
 }
 
+/* Callback for cp_walk_tree to mark all {VAR,PARM}_DECLs in a tree as
+   read.  */
+
+static tree
+maybe_mark_exp_read_r (tree *tp, int *, void *)
+{
+  tree t = *tp;
+  if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+    mark_exp_read (t);
+  return NULL_TREE;
+}
+
 /* Finish an if-statement.  */
 
 void
@@ -781,6 +829,16 @@ finish_if_stmt (tree if_stmt)
 {
   tree scope = IF_SCOPE (if_stmt);
   IF_SCOPE (if_stmt) = NULL;
+  if (IF_STMT_CONSTEXPR_P (if_stmt))
+    {
+      /* Prevent various -Wunused warnings.  We might not instantiate
+        either of these branches, so we would not mark the variables
+        used in that branch as read.  */
+      cp_walk_tree_without_duplicates (&THEN_CLAUSE (if_stmt),
+                                      maybe_mark_exp_read_r, NULL);
+      cp_walk_tree_without_duplicates (&ELSE_CLAUSE (if_stmt),
+                                      maybe_mark_exp_read_r, NULL);
+    }
   add_stmt (do_poplevel (scope));
 }
 
@@ -906,7 +964,7 @@ finish_return_stmt (tree expr)
     {
       if (warn_sequence_point)
        verify_sequence_points (expr);
-      
+
       if (DECL_DESTRUCTOR_P (current_function_decl)
          || (DECL_CONSTRUCTOR_P (current_function_decl)
              && targetm.cxx.cdtor_returns_this ()))
@@ -934,9 +992,7 @@ finish_return_stmt (tree expr)
 tree
 begin_for_scope (tree *init)
 {
-  tree scope = NULL_TREE;
-  if (flag_new_for_scope)
-    scope = do_pushlevel (sk_for);
+  tree scope = do_pushlevel (sk_for);
 
   if (processing_template_decl)
     *init = push_stmt_list ();
@@ -960,10 +1016,10 @@ begin_for_stmt (tree scope, tree init)
 
   if (scope == NULL_TREE)
     {
-      gcc_assert (!init || !flag_new_for_scope);
-      if (!init)
-       scope = begin_for_scope (&init);
+      gcc_assert (!init);
+      scope = begin_for_scope (&init);
     }
+
   FOR_INIT_STMT (r) = init;
   FOR_SCOPE (r) = scope;
 
@@ -1057,16 +1113,40 @@ finish_for_stmt (tree for_stmt)
     FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt));
 
   /* Pop the scope for the body of the loop.  */
-  if (flag_new_for_scope)
-    {
-      tree scope;
-      tree *scope_ptr = (TREE_CODE (for_stmt) == RANGE_FOR_STMT
-                        ? &RANGE_FOR_SCOPE (for_stmt)
-                        : &FOR_SCOPE (for_stmt));
-      scope = *scope_ptr;
-      *scope_ptr = NULL;
-      add_stmt (do_poplevel (scope));
+  tree *scope_ptr = (TREE_CODE (for_stmt) == RANGE_FOR_STMT
+                    ? &RANGE_FOR_SCOPE (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.
@@ -1077,36 +1157,34 @@ finish_for_stmt (tree for_stmt)
 tree
 begin_range_for_stmt (tree scope, tree init)
 {
-  tree r;
-
   begin_maybe_infinite_loop (boolean_false_node);
 
-  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)
     {
-      gcc_assert (!init || !flag_new_for_scope);
-      if (!init)
-       scope = begin_for_scope (&init);
+      gcc_assert (!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);
@@ -1165,10 +1243,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
   if (!processing_template_decl)
     {
       /* Convert the condition to an integer or enumeration type.  */
+      tree orig_cond = cond;
       cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true);
       if (cond == NULL_TREE)
        {
-         error ("switch quantity not an integer");
+         error_at (cp_expr_loc_or_input_loc (orig_cond),
+                   "switch quantity not an integer");
          cond = error_mark_node;
        }
       /* We want unlowered type here to handle enum bit-fields.  */
@@ -1343,21 +1423,25 @@ finish_handler_parms (tree decl, tree handler)
       if (warn_catch_value
          && type != NULL_TREE
          && type != error_mark_node
-         && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE)
+         && !TYPE_REF_P (TREE_TYPE (decl)))
        {
          tree orig_type = TREE_TYPE (decl);
          if (CLASS_TYPE_P (orig_type))
            {
              if (TYPE_POLYMORPHIC_P (orig_type))
-               warning (OPT_Wcatch_value_,
-                        "catching polymorphic type %q#T by value", orig_type);
+               warning_at (DECL_SOURCE_LOCATION (decl),
+                           OPT_Wcatch_value_,
+                           "catching polymorphic type %q#T by value",
+                           orig_type);
              else if (warn_catch_value > 1)
-               warning (OPT_Wcatch_value_,
-                        "catching type %q#T by value", orig_type);
+               warning_at (DECL_SOURCE_LOCATION (decl),
+                           OPT_Wcatch_value_,
+                           "catching type %q#T by value", orig_type);
            }
          else if (warn_catch_value > 2)
-           warning (OPT_Wcatch_value_,
-                    "catching non-reference type %q#T", orig_type);
+           warning_at (DECL_SOURCE_LOCATION (decl),
+                       OPT_Wcatch_value_,
+                       "catching non-reference type %q#T", orig_type);
        }
     }
   HANDLER_TYPE (handler) = type;
@@ -1461,11 +1545,12 @@ 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)
+finish_asm_stmt (location_t loc, int volatile_p, tree string,
+                tree output_operands, tree input_operands, tree clobbers,
+                tree labels, bool inline_p)
 {
   tree r;
   tree t;
@@ -1507,13 +1592,12 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                  || CP_TYPE_CONST_P (TREE_TYPE (operand))
                  /* Functions are not modifiable, even though they are
                     lvalues.  */
-                 || TREE_CODE (TREE_TYPE (operand)) == FUNCTION_TYPE
-                 || TREE_CODE (TREE_TYPE (operand)) == METHOD_TYPE
+                 || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (operand))
                  /* If it's an aggregate and any field is const, then it is
                     effectively const.  */
                  || (CLASS_TYPE_P (TREE_TYPE (operand))
                      && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
-           cxx_readonly_error (operand, lv_asm);
+           cxx_readonly_error (loc, operand, lv_asm);
 
          tree *op = &operand;
          while (TREE_CODE (*op) == COMPOUND_EXPR)
@@ -1551,7 +1635,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
        {
          constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
          bool constraint_parsed
-           = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,   
+           = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
                                      oconstraints, &allows_mem, &allows_reg);
          /* If the operand is going to end up in memory, don't call
             decay_conversion.  */
@@ -1566,8 +1650,9 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
             resolve the overloading.  */
          if (TREE_TYPE (operand) == unknown_type_node)
            {
-             error ("type of asm operand %qE could not be determined",
-                    TREE_VALUE (t));
+             error_at (loc,
+                       "type of %<asm%> operand %qE could not be determined",
+                       TREE_VALUE (t));
              operand = error_mark_node;
            }
 
@@ -1615,10 +1700,11 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
        }
     }
 
-  r = build_stmt (input_location, ASM_EXPR, string,
+  r = build_stmt (loc, ASM_EXPR, string,
                  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);
 }
@@ -1647,7 +1733,7 @@ finish_label_decl (tree name)
 {
   if (!at_function_scope_p ())
     {
-      error ("__label__ declarations are only allowed in function scopes");
+      error ("%<__label__%> declarations are only allowed in function scopes");
       return;
     }
 
@@ -1706,10 +1792,10 @@ finish_mem_initializers (tree mem_inits)
 
 /* Obfuscate EXPR if it looks like an id-expression or member access so
    that the call to finish_decltype in do_auto_deduction will give the
-   right result.  */
+   right result.  If EVEN_UNEVAL, do this even in unevaluated context.  */
 
 tree
-force_paren_expr (tree expr)
+force_paren_expr (tree expr, bool even_uneval)
 {
   /* This is only needed for decltype(auto) in C++14.  */
   if (cxx_dialect < cxx14)
@@ -1717,35 +1803,25 @@ force_paren_expr (tree expr)
 
   /* If we're in unevaluated context, we can't be deducing a
      return/initializer type, so we don't need to mess with this.  */
-  if (cp_unevaluated_operand)
+  if (cp_unevaluated_operand && !even_uneval)
     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;
 
+  location_t loc = cp_expr_location (expr);
+
   if (TREE_CODE (expr) == COMPONENT_REF
       || TREE_CODE (expr) == SCOPE_REF)
     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.  */;
+    expr = build1_loc (loc, PAREN_EXPR, TREE_TYPE (expr), expr);
   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_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+      REF_PARENTHESIZED_P (expr) = true;
     }
 
   return expr;
@@ -1774,6 +1850,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;
 }
@@ -1793,8 +1872,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 ());
 
@@ -1815,7 +1895,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);
     }
 
@@ -1840,11 +1928,11 @@ 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);
 
-      if (TREE_CODE (type) == REFERENCE_TYPE)
+      if (TYPE_REF_P (type))
        /* Quals on the object don't matter.  */;
       else if (PACK_EXPANSION_P (type))
        /* Don't bother trying to represent this.  */
@@ -1861,17 +1949,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);
@@ -2001,7 +2088,7 @@ check_accessibility_of_qualified_id (tree decl,
        its bases.  */
     qualifying_type = currently_open_derived_class (scope);
 
-  if (qualifying_type 
+  if (qualifying_type
       /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
         or similar in a default argument value.  */
       && CLASS_TYPE_P (qualifying_type)
@@ -2061,7 +2148,8 @@ finish_qualified_id_expr (tree qualifying_class,
     }
 
   /* No need to check access within an enum.  */
-  if (TREE_CODE (qualifying_class) == ENUMERAL_TYPE)
+  if (TREE_CODE (qualifying_class) == ENUMERAL_TYPE
+      && TREE_CODE (expr) != IDENTIFIER_NODE)
     return expr;
 
   /* Within the scope of a class, turn references to non-static
@@ -2081,7 +2169,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 ()))
@@ -2097,6 +2186,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
@@ -2106,10 +2203,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);
     }
@@ -2284,19 +2385,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)
     {
@@ -2336,7 +2440,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
@@ -2356,7 +2460,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;
@@ -2367,6 +2471,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)
@@ -2388,13 +2494,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_input_loc (fn));
          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)
            {
@@ -2490,6 +2593,23 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
                                      /*fn_p=*/NULL,
                                      complain);
     }
+  else if (concept_check_p (fn))
+    {
+      /* FN is actually a template-id referring to a concept definition.  */
+      tree id = unpack_concept_check (fn);
+      tree tmpl = TREE_OPERAND (id, 0);
+      tree args = TREE_OPERAND (id, 1);
+
+      if (!function_concept_p (tmpl))
+       {
+         error_at (EXPR_LOC_OR_LOC (fn, input_location),
+                   "cannot call a concept as a function");
+         return error_mark_node;
+       }
+
+      /* Ensure the result is wrapped as a call expression.  */
+      result = build_concept_check (tmpl, args, tf_warning_or_error);
+    }
   else if (is_overloaded_fn (fn))
     {
       /* If the function is an overloaded builtin, resolve it.  */
@@ -2530,6 +2650,21 @@ 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));
+             arg2 = instantiate_non_dependent_expr (arg2);
+             warn_for_memset (input_location, arg0, arg2, literal_mask);
+           }
+
          /* A call to a namespace-scope function.  */
          result = build_new_function_call (fn, args, complain);
        }
@@ -2565,10 +2700,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;
 }
 
@@ -2701,13 +2832,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);
@@ -2737,12 +2869,15 @@ finish_compound_literal (tree type, tree compound_literal,
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (type) == REFERENCE_TYPE)
+  if (TYPE_REF_P (type))
     {
       compound_literal
        = finish_compound_literal (TREE_TYPE (type), compound_literal,
                                   complain, fcl_context);
-      return cp_build_c_cast (type, compound_literal, complain);
+      /* The prvalue is then used to direct-initialize the reference.  */
+      tree r = (perform_implicit_conversion_flags
+               (type, compound_literal, complain, LOOKUP_NORMAL));
+      return convert_from_reference (r);
     }
 
   if (!TYPE_OBJ_P (type))
@@ -2761,14 +2896,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);
@@ -2781,7 +2933,8 @@ finish_compound_literal (tree type, tree compound_literal,
         that it came from T{} rather than T({}).  */
       CONSTRUCTOR_IS_DIRECT_INIT (compound_literal) = 1;
       compound_literal = build_tree_list (NULL_TREE, compound_literal);
-      return build_functional_cast (type, compound_literal, complain);
+      return build_functional_cast (input_location, type,
+                                   compound_literal, complain);
     }
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -2789,9 +2942,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)
     {
@@ -2800,8 +2957,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;
@@ -2879,6 +3049,14 @@ finish_translation_unit (void)
 
   /* Do file scope __FUNCTION__ et al.  */
   finish_fname_decls ();
+
+  if (scope_chain->omp_declare_target_attribute)
+    {
+      if (!errorcount)
+       error ("%<#pragma omp declare target%> without corresponding "
+              "%<#pragma omp end declare target%>");
+      scope_chain->omp_declare_target_attribute = 0;
+    }
 }
 
 /* Finish a template type parameter, specified as AGGR IDENTIFIER.
@@ -2910,8 +3088,8 @@ finish_template_template_parm (tree aggr, tree identifier)
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_ARTIFICIAL (decl) = 1;
 
-  // Associate the constraints with the underlying declaration,
-  // not the template.
+  /* Associate the constraints with the underlying declaration,
+     not the template.  */
   tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
   tree constr = build_constraints (reqs, NULL_TREE);
   set_constraints (decl, constr);
@@ -2920,7 +3098,7 @@ finish_template_template_parm (tree aggr, tree identifier)
 
   gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
 
-  check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl), 
+  check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl),
                           /*is_primary=*/true, /*is_partial=*/false,
                           /*is_friend=*/0);
 
@@ -2957,7 +3135,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;
@@ -3295,7 +3473,7 @@ baselink_for_fns (tree fns)
   tree scope;
   tree cl;
 
-  if (BASELINK_P (fns) 
+  if (BASELINK_P (fns)
       || error_operand_p (fns))
     return fns;
 
@@ -3397,27 +3575,23 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
        /* A lambda in an NSDMI (c++/64496).  */
        break;
 
-      if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
-         == CPLD_NONE)
+      if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE)
        break;
 
-      lambda_stack = tree_cons (NULL_TREE,
-                               lambda_expr,
-                               lambda_stack);
+      lambda_stack = tree_cons (NULL_TREE, lambda_expr, lambda_stack);
 
-      containing_function
-       = decl_function_context (containing_function);
+      containing_function = 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)
-      && DECL_ANON_UNION_VAR_P (decl))
+  if (lambda_expr && VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl))
     {
       if (complain & tf_error)
        error ("cannot capture member %qD of anonymous union", decl);
@@ -3426,11 +3600,8 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
   /* Do lambda capture when processing the id-expression, not when
      odr-using a variable.  */
   if (!odr_use && context == containing_function)
-    {
-      decl = add_default_capture (lambda_stack,
-                                 /*id=*/DECL_NAME (decl),
-                                 initializer);
-    }
+    decl = add_default_capture (lambda_stack,
+                               /*id=*/DECL_NAME (decl), initializer);
   /* Only an odr-use of an outer automatic variable causes an
      error, and a constant variable can decay to a prvalue
      constant without odr-use.  So don't complain yet.  */
@@ -3442,8 +3613,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
        {
          error ("%qD is not captured", decl);
          tree closure = LAMBDA_EXPR_CLOSURE (lambda_expr);
-         if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
-             == CPLD_NONE)
+         if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE)
            inform (location_of (closure),
                    "the lambda has no capture-default");
          else if (TYPE_CLASS_SCOPE_P (closure))
@@ -3502,20 +3672,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);
 
@@ -3559,11 +3729,6 @@ finish_id_expression (tree id_expression,
          else
            decl = id_expression;
        }
-      /* If DECL is a variable that would be out of scope under
-        ANSI/ISO rules, but in scope in the ARM, name lookup
-        will succeed.  Issue a diagnostic here.  */
-      else
-       decl = check_for_out_of_scope_variable (decl);
 
       /* Remember that the name was used in the definition of
         the current class so that we can check later to see if
@@ -3623,8 +3788,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))))
@@ -3659,17 +3833,13 @@ finish_id_expression (tree id_expression,
           wrong, so just return the identifier.  */
        return id_expression;
 
-      if (TREE_CODE (decl) == NAMESPACE_DECL)
-       {
-         error ("use of namespace %qD as expression", decl);
-         return error_mark_node;
-       }
-      else if (DECL_CLASS_TEMPLATE_P (decl))
+      if (DECL_CLASS_TEMPLATE_P (decl))
        {
          error ("use of class template %qT as expression", decl);
          return error_mark_node;
        }
-      else if (TREE_CODE (decl) == TREE_LIST)
+
+      if (TREE_CODE (decl) == TREE_LIST)
        {
          /* Ambiguous reference to base members.  */
          error ("request for member %qD is ambiguous in "
@@ -3693,9 +3863,10 @@ finish_id_expression (tree id_expression,
       if (! error_operand_p (decl)
          && !dependent_p
          && integral_constant_expression_p
-         && ! decl_constant_var_p (decl)
+         && !decl_constant_var_p (decl)
          && TREE_CODE (decl) != CONST_DECL
-         && ! builtin_valid_in_constant_expr_p (decl))
+         && !builtin_valid_in_constant_expr_p (decl)
+         && !concept_check_p (decl))
        {
          if (!allow_non_integral_constant_expression_p)
            {
@@ -3705,26 +3876,24 @@ 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)))
+              && variable_template_p (TREE_OPERAND (decl, 0))
+              && !concept_check_p (decl))
        {
          decl = finish_template_variable (decl);
          mark_used (decl);
          decl = convert_from_reference (decl);
        }
+      else if (concept_check_p (decl))
+       {
+         /* Nothing more to do. All of the analysis for concept checks
+            is done by build_conept_id, called from the parser.  */
+       }
       else if (scope)
        {
          if (TREE_CODE (decl) == SCOPE_REF)
@@ -3739,6 +3908,8 @@ finish_id_expression (tree id_expression,
          if (TREE_CODE (decl) == FUNCTION_DECL)
            mark_used (decl);
 
+         cp_warn_deprecated_use_scopes (scope);
+
          if (TYPE_P (scope))
            decl = finish_qualified_id_expr (scope,
                                             decl,
@@ -3762,10 +3933,11 @@ finish_id_expression (tree id_expression,
        }
       else if (is_overloaded_fn (decl))
        {
+         /* We only need to look at the first function,
+            because all the fns share the attribute we're
+            concerned with (all member fns or all non-members).  */
          tree first_fn = get_first_fn (decl);
-
-         if (TREE_CODE (first_fn) == TEMPLATE_DECL)
-           first_fn = DECL_TEMPLATE_RESULT (first_fn);
+         first_fn = STRIP_TEMPLATE (first_fn);
 
          /* [basic.def.odr]: "A function whose name appears as a
             potentially-evaluated expression is odr-used if it is the unique
@@ -3780,9 +3952,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);
@@ -3798,7 +3971,7 @@ finish_id_expression (tree id_expression,
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
              && DECL_CLASS_SCOPE_P (decl))
            {
-             tree context = context_for_name_lookup (decl); 
+             tree context = context_for_name_lookup (decl);
              if (context != current_class_type)
                {
                  tree path = currently_open_derived_class (context);
@@ -3815,6 +3988,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.  */
 
@@ -3894,7 +4095,7 @@ calculate_direct_bases (tree type, tsubst_flags_t complain)
       || !NON_UNION_CLASS_TYPE_P (type))
     return make_tree_vec (0);
 
-  vec<tree, va_gc> *vector = make_tree_vector ();
+  releasing_vec vector;
   vec<tree, va_gc> *base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
   tree binfo;
   unsigned i;
@@ -3914,7 +4115,6 @@ calculate_direct_bases (tree type, tsubst_flags_t complain)
   for (i = 0; i < vector->length (); ++i)
     TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE ((*vector)[i]);
 
-  release_tree_vector (vector);
   return bases_vec;
 }
 
@@ -3960,27 +4160,24 @@ calculate_bases (tree type, tsubst_flags_t complain)
       || !NON_UNION_CLASS_TYPE_P (type))
     return make_tree_vec (0);
 
-  vec<tree, va_gc> *vector = make_tree_vector ();
+  releasing_vec vector;
   tree bases_vec = NULL_TREE;
   unsigned i;
   vec<tree, va_gc> *vbases;
-  vec<tree, va_gc> *nonvbases;
   tree binfo;
 
   /* First go through virtual base classes */
   for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
        vec_safe_iterate (vbases, i, &binfo); i++)
     {
-      vec<tree, va_gc> *vbase_bases
+      releasing_vec vbase_bases
        = calculate_bases_helper (BINFO_TYPE (binfo));
       vec_safe_splice (vector, vbase_bases);
-      release_tree_vector (vbase_bases);
     }
 
   /* Now for the non-virtual bases */
-  nonvbases = calculate_bases_helper (type);
+  releasing_vec nonvbases = calculate_bases_helper (type);
   vec_safe_splice (vector, nonvbases);
-  release_tree_vector (nonvbases);
 
   /* Note that during error recovery vector->length can even be zero.  */
   if (vector->length () > 1)
@@ -3994,7 +4191,6 @@ calculate_bases (tree type, tsubst_flags_t complain)
   else
     bases_vec = make_tree_vec (0);
 
-  release_tree_vector (vector);
   return bases_vec;
 }
 
@@ -4006,7 +4202,7 @@ finish_bases (tree type, bool direct)
   if (!processing_template_decl)
     {
       /* Parameter packs can only be used in templates */
-      error ("Parameter pack __bases only valid in template declaration");
+      error ("parameter pack %<__bases%> only valid in template declaration");
       return error_mark_node;
     }
 
@@ -4033,14 +4229,16 @@ 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%>",
              TREE_OPERAND (expr, 2));
       return error_mark_node;
     }
-  if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
-      || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
+  if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr))
       || TREE_TYPE (expr) == unknown_type_node)
     {
       while (TREE_CODE (expr) == COMPONENT_REF
@@ -4069,7 +4267,7 @@ finish_offsetof (tree object_ptr, tree expr, location_t loc)
       && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr)))
       && CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr)))
       && cp_unevaluated_operand == 0)
-    warning_at (loc, OPT_Winvalid_offsetof, "offsetof within "
+    warning_at (loc, OPT_Winvalid_offsetof, "%<offsetof%> within "
                "non-standard-layout type %qT is conditionally-supported",
                TREE_TYPE (TREE_TYPE (object_ptr)));
   return fold_offsetof (expr);
@@ -4224,7 +4422,9 @@ 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_IMMEDIATE_FUNCTION_P (fn)
+              || DECL_OMP_DECLARE_REDUCTION_P (fn))
        tentative_decl_linkage (fn);
       else
        import_export_decl (fn);
@@ -4235,6 +4435,8 @@ 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_IMMEDIATE_FUNCTION_P (fn)
+         && !DECL_OMP_DECLARE_REDUCTION_P (fn)
          && (flag_keep_inline_functions
              || (flag_keep_inline_dllexport
                  && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4260,6 +4462,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;
@@ -4280,8 +4490,9 @@ expand_or_defer_fn (tree fn)
     }
 }
 
-struct nrv_data
+class nrv_data
 {
+public:
   nrv_data () : visited (37) {}
 
   tree var;
@@ -4294,7 +4505,7 @@ struct nrv_data
 static tree
 finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
 {
-  struct nrv_data *dp = (struct nrv_data *)data;
+  class nrv_data *dp = (class nrv_data *)data;
   tree_node **slot;
 
   /* No need to walk into types.  There wouldn't be any need to walk into
@@ -4352,7 +4563,7 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
 void
 finalize_nrv (tree *tp, tree var, tree result)
 {
-  struct nrv_data data;
+  class nrv_data data;
 
   /* Copy name from VAR to RESULT.  */
   DECL_NAME (result) = DECL_NAME (var);
@@ -4478,7 +4689,7 @@ omp_privatize_field (tree t, bool shared)
     return error_mark_node;
   if (!omp_private_member_map && !shared)
     omp_private_member_map = new hash_map<tree, tree>;
-  if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+  if (TYPE_REF_P (TREE_TYPE (t)))
     {
       gcc_assert (INDIRECT_REF_P (m));
       m = TREE_OPERAND (m, 0);
@@ -4533,7 +4744,6 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
        t = TREE_OPERAND (t, 0);
       ret = t;
       if (TREE_CODE (t) == COMPONENT_REF
-         && ort == C_ORT_OMP
          && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
@@ -4557,6 +4767,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
                  return error_mark_node;
                }
              t = TREE_OPERAND (t, 0);
+             if (ort == C_ORT_ACC && TREE_CODE (t) == INDIRECT_REF)
+               t = TREE_OPERAND (t, 0);
            }
          if (REFERENCE_REF_P (t))
            t = TREE_OPERAND (t, 0);
@@ -4575,7 +4787,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)
        {
@@ -4599,7 +4812,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,
@@ -4653,12 +4868,26 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
   if (low_bound == NULL_TREE)
     low_bound = integer_zero_node;
 
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+      && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+         || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+    {
+      if (length != integer_one_node)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c),
+                   "expected single pointer in %qs clause",
+                   c_omp_map_clause_name (c, ort == C_ORT_ACC));
+         return error_mark_node;
+       }
+    }
   if (length != NULL_TREE)
     {
       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))
                {
@@ -4724,7 +4953,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",
@@ -4743,7 +4974,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++;
@@ -4779,7 +5012,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++;
@@ -4796,7 +5031,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
            }
        }
     }
-  else if (TREE_CODE (type) == POINTER_TYPE)
+  else if (TYPE_PTR_P (type))
     {
       if (length == NULL_TREE)
        {
@@ -4839,6 +5074,17 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
       TREE_PURPOSE (t) = lb;
       low_bound = lb;
     }
+  /* Temporarily disable -fstrong-eval-order for array reductions.
+     The SAVE_EXPR and COMPOUND_EXPR added if low_bound has side-effects
+     is something the middle-end can't cope with and more importantly,
+     it needs to be the actual base variable that is privatized, not some
+     temporary assigned previous value of it.  That, together with OpenMP
+     saying how many times the side-effects are evaluated is unspecified,
+     makes int *a, *b; ... reduction(+:a[a = b, 3:10]) really unspecified.  */
+  warning_sentinel s (flag_strong_eval_order,
+                     OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION);
   ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, false);
   return ret;
 }
@@ -4851,7 +5097,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)
@@ -4860,7 +5112,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;
@@ -4880,7 +5132,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
     {
@@ -4957,7 +5209,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);
@@ -4985,7 +5239,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);
@@ -5001,17 +5257,20 @@ 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)
                eltype = TREE_TYPE (eltype);
              tree type = build_array_type (eltype, index_type);
              tree ptype = build_pointer_type (eltype);
-             if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
-                 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
+             if (TYPE_REF_P (TREE_TYPE (t))
+                 && INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
                t = convert_from_reference (t);
              else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
                t = build_fold_addr_expr (t);
@@ -5046,6 +5305,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
            switch (OMP_CLAUSE_MAP_KIND (c))
              {
              case GOMP_MAP_ALLOC:
+             case GOMP_MAP_IF_PRESENT:
              case GOMP_MAP_TO:
              case GOMP_MAP_FROM:
              case GOMP_MAP_TOFROM:
@@ -5068,12 +5328,18 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
          if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
            OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
          else if (TREE_CODE (t) == COMPONENT_REF)
-           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+           {
+             gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                                  : GOMP_MAP_ALWAYS_POINTER;
+             OMP_CLAUSE_SET_MAP_KIND (c2, k);
+           }
          else if (REFERENCE_REF_P (t)
                   && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
            {
              t = TREE_OPERAND (t, 0);
-             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+             gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                                  : GOMP_MAP_ALWAYS_POINTER;
+             OMP_CLAUSE_SET_MAP_KIND (c2, k);
            }
          else
            OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
@@ -5086,7 +5352,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
                                ptrdiff_type_node, t);
          tree ptr = OMP_CLAUSE_DECL (c2);
          ptr = convert_from_reference (ptr);
-         if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
+         if (!INDIRECT_TYPE_P (TREE_TYPE (ptr)))
            ptr = build_fold_addr_expr (ptr);
          t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
                               ptrdiff_type_node, t,
@@ -5097,8 +5363,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
          OMP_CLAUSE_CHAIN (c) = c2;
          ptr = OMP_CLAUSE_DECL (c2);
          if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
-             && TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
-             && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
+             && TYPE_REF_P (TREE_TYPE (ptr))
+             && INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
            {
              tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
                                          OMP_CLAUSE_MAP);
@@ -5364,7 +5630,7 @@ void
 cp_check_omp_declare_reduction (tree udr)
 {
   tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (udr)));
-  gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+  gcc_assert (TYPE_REF_P (type));
   type = TREE_TYPE (type);
   int i;
   location_t loc = DECL_SOURCE_LOCATION (udr);
@@ -5407,15 +5673,14 @@ cp_check_omp_declare_reduction (tree udr)
          return;
        }
     }
-  else if (TREE_CODE (type) == FUNCTION_TYPE
-          || TREE_CODE (type) == METHOD_TYPE
+  else if (FUNC_OR_METHOD_TYPE_P (type)
           || TREE_CODE (type) == ARRAY_TYPE)
     {
       error_at (loc, "function or array type %qT in "
                     "%<#pragma omp declare reduction%>", type);
       return;
     }
-  else if (TREE_CODE (type) == REFERENCE_TYPE)
+  else if (TYPE_REF_P (type))
     {
       error_at (loc, "reference type %qT in %<#pragma omp declare reduction%>",
                type);
@@ -5423,8 +5688,8 @@ cp_check_omp_declare_reduction (tree udr)
     }
   else if (TYPE_QUALS_NO_ADDR_SPACE (type))
     {
-      error_at (loc, "const, volatile or __restrict qualified type %qT in "
-                    "%<#pragma omp declare reduction%>", type);
+      error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified "
+               "type %qT in %<#pragma omp declare reduction%>", type);
       return;
     }
 
@@ -5524,7 +5789,7 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
   tree type = TREE_TYPE (t);
   if (TREE_CODE (t) == MEM_REF)
     type = TREE_TYPE (type);
-  if (TREE_CODE (type) == REFERENCE_TYPE)
+  if (TYPE_REF_P (type))
     type = TREE_TYPE (type);
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -5541,11 +5806,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);
@@ -5589,8 +5856,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)
@@ -5664,8 +5932,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]))
-                 && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
-                    != REFERENCE_TYPE)
+                 && (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;
@@ -5674,9 +5942,11 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
              if (need_static_cast)
                {
                  tree rtype = build_reference_type (atype);
-                 omp_out = build_static_cast (rtype, omp_out,
+                 omp_out = build_static_cast (input_location,
+                                              rtype, omp_out,
                                               tf_warning_or_error);
-                 omp_in = build_static_cast (rtype, omp_in,
+                 omp_in = build_static_cast (input_location,
+                                             rtype, omp_in,
                                              tf_warning_or_error);
                  if (omp_out == error_mark_node || omp_in == error_mark_node)
                    return true;
@@ -5691,7 +5961,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])))
@@ -5709,9 +5981,11 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
                      return true;
                    }
                  tree rtype = build_reference_type (atype);
-                 omp_priv = build_static_cast (rtype, omp_priv,
+                 omp_priv = build_static_cast (input_location,
+                                               rtype, omp_priv,
                                                tf_warning_or_error);
-                 omp_orig = build_static_cast (rtype, omp_orig,
+                 omp_orig = build_static_cast (input_location,
+                                               rtype, omp_orig,
                                                tf_warning_or_error);
                  if (omp_priv == error_mark_node
                      || omp_orig == error_mark_node)
@@ -5752,8 +6026,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)
@@ -5774,7 +6049,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))
@@ -5783,8 +6059,7 @@ finish_omp_declare_simd_methods (tree t)
        if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
            && integer_zerop (OMP_CLAUSE_DECL (c))
            && OMP_CLAUSE_LINEAR_STEP (c)
-           && TREE_CODE (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))
-              == POINTER_TYPE)
+           && TYPE_PTR_P (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c))))
          {
            tree s = OMP_CLAUSE_LINEAR_STEP (c);
            s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s);
@@ -5813,7 +6088,7 @@ cp_finish_omp_clause_depend_sink (tree sink_clause)
   for (; t; t = TREE_CHAIN (t))
     {
       tree decl = TREE_VALUE (t);
-      if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+      if (TYPE_PTR_P (TREE_TYPE (decl)))
        {
          tree offset = TREE_PURPOSE (t);
          bool neg = wi::neg_p (wi::to_wide (offset));
@@ -5835,6 +6110,193 @@ 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 (input_location, type, begin,
+                              tf_warning_or_error);
+      end = cp_build_c_cast (input_location, 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 (input_location, 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;
+}
+
+/* Ensure that pointers are used in OpenACC attach and detach clauses.
+   Return true if an error has been detected.  */
+
+static bool
+cp_oacc_check_attachments (tree c)
+{
+  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+    return false;
+
+  /* OpenACC attach / detach clauses must be pointers.  */
+  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+      || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+    {
+      tree t = OMP_CLAUSE_DECL (c);
+      tree type;
+
+      while (TREE_CODE (t) == TREE_LIST)
+       t = TREE_CHAIN (t);
+
+      type = TREE_TYPE (t);
+
+      if (TREE_CODE (type) == REFERENCE_TYPE)
+       type = TREE_TYPE (type);
+
+      if (TREE_CODE (type) != POINTER_TYPE)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause",
+                   c_omp_map_clause_name (c, true));
+         return true;
+       }
+    }
+
+  return false;
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -5848,15 +6310,25 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool branch_seen = false;
   bool copyprivate_seen = false;
   bool ordered_seen = false;
+  bool order_seen = false;
+  bool schedule_seen = false;
   bool oacc_async = false;
+  tree last_iterators = NULL_TREE;
+  bool last_iterators_remove = false;
+  /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+     has been seen, -2 if mixed inscan/normal reduction diagnosed.  */
+  int reduction_seen = 0;
 
   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 or use_device_xxx_head
+     instead.  */
   bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
 
   if (ort & C_ORT_ACC)
@@ -5881,6 +6353,20 @@ 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:
+         if (reduction_seen == 0)
+           reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+         else if (reduction_seen != -2
+                  && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+                                        ? -1 : 1))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+                       "on the same construct");
+             reduction_seen = -2;
+           }
+         /* 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)
@@ -5890,6 +6376,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  remove = true;
                  break;
                }
+             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_REDUCTION_INSCAN (c))
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%<inscan%> %<reduction%> clause with array "
+                           "section");
+                 remove = true;
+                 break;
+               }
              if (TREE_CODE (t) == TREE_LIST)
                {
                  while (TREE_CODE (t) == TREE_LIST)
@@ -5936,24 +6431,27 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              tree type = TREE_TYPE (t);
              if ((OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
                   || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL)
-                 && TREE_CODE (type) != REFERENCE_TYPE)
+                 && !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;
                }
-             if (TREE_CODE (type) == REFERENCE_TYPE)
+             if (TYPE_REF_P (type))
                type = TREE_TYPE (type);
              if (OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_REF)
                {
                  if (!INTEGRAL_TYPE_P (type)
-                     && TREE_CODE (type) != POINTER_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;
                    }
@@ -5971,10 +6469,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t))
                   && (ort != C_ORT_OMP_DECLARE_SIMD
                       || TREE_CODE (t) != PARM_DECL
-                      || TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
+                      || !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;
            }
@@ -6004,7 +6503,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                    }
                  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
                  tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
-                 if (TREE_CODE (type) == REFERENCE_TYPE)
+                 if (TYPE_REF_P (type))
                    type = TREE_TYPE (type);
                  if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF)
                    {
@@ -6022,7 +6521,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                          break;
                        }
                    }
-                 else if (TREE_CODE (type) == POINTER_TYPE
+                 else if (TYPE_PTR_P (type)
                           /* Can't multiply the step yet if *this
                              is still incomplete type.  */
                           && (ort != C_ORT_OMP_DECLARE_SIMD
@@ -6062,12 +6561,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            t = OMP_CLAUSE_DECL (c);
        check_dup_generic_t:
          if (t == current_class_ptr
-             && (ort != C_ORT_OMP_DECLARE_SIMD
+             && ((ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_ACC)
                  || (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;
            }
@@ -6077,19 +6577,29 @@ 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
-                  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+         else if ((ort == C_ORT_ACC
+                   && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                  || (ort == C_ORT_OMP
+                      && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
+                          || (OMP_CLAUSE_CODE (c)
+                              == OMP_CLAUSE_USE_DEVICE_ADDR))))
            {
              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),
+                           ort == C_ORT_ACC
+                           ? "%qD appears more than once in reduction clauses"
+                           : "%qD appears more than once in data clauses",
+                           t);
                  remove = true;
                }
              else
@@ -6099,16 +6609,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
@@ -6118,8 +6631,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        handle_field_decl:
          if (!remove
              && TREE_CODE (t) == FIELD_DECL
-             && t == OMP_CLAUSE_DECL (c)
-             && ort != C_ORT_ACC)
+             && t == OMP_CLAUSE_DECL (c))
            {
              OMP_CLAUSE_DECL (c)
                = omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
@@ -6137,8 +6649,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;
            }
@@ -6149,23 +6662,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
@@ -6178,10 +6698,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
          else
            t = OMP_CLAUSE_DECL (c);
-         if (t == current_class_ptr)
+         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;
            }
@@ -6192,15 +6713,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
@@ -6237,7 +6763,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
@@ -6341,30 +6868,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)
            ;
@@ -6373,7 +6876,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
@@ -6393,6 +6897,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                }
              OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
            }
+         if (!remove)
+           schedule_seen = true;
          break;
 
        case OMP_CLAUSE_SIMDLEN:
@@ -6403,8 +6909,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
@@ -6416,9 +6923,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;
                    }
                }
@@ -6435,7 +6943,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
@@ -6463,7 +6972,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
@@ -6492,7 +7002,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
@@ -6513,14 +7024,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;
            }
@@ -6530,8 +7042,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;
            }
@@ -6540,16 +7053,18 @@ 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)
-                  && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
+                  && !TYPE_PTR_P (TREE_TYPE (t))
                   && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE
-                  && (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
-                      || (!POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t)))
+                  && (!TYPE_REF_P (TREE_TYPE (t))
+                      || (!INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (t)))
                           && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
                               != ARRAY_TYPE))))
            {
@@ -6560,7 +7075,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
@@ -6573,8 +7090,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
@@ -6586,15 +7104,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)
@@ -6609,33 +7157,109 @@ 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 (ort != C_ORT_ACC && 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 (OMP_CLAUSE_LOCATION (c),
+                                            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:
@@ -6658,6 +7282,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                                "array section does not have mappable type "
                                "in %qs clause",
                                omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     cp_omp_emit_unmappable_type_notes (TREE_TYPE (t));
                      remove = true;
                    }
                  while (TREE_CODE (t) == ARRAY_REF)
@@ -6674,14 +7299,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
@@ -6691,6 +7319,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                        }
                    }
                }
+             if (cp_oacc_check_attachments (c))
+               remove = true;
              break;
            }
          if (t == error_mark_node)
@@ -6698,14 +7328,25 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              remove = true;
              break;
            }
+         /* OpenACC attach / detach clauses must be pointers.  */
+         if (cp_oacc_check_attachments (c))
+           {
+             remove = true;
+             break;
+           }
          if (REFERENCE_REF_P (t)
              && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
            {
              t = TREE_OPERAND (t, 0);
              OMP_CLAUSE_DECL (c) = t;
            }
+         if (ort == C_ORT_ACC
+             && TREE_CODE (t) == COMPONENT_REF
+             && TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
+           t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
          if (TREE_CODE (t) == COMPONENT_REF
-             && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+             && ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+                 || ort == C_ORT_ACC)
              && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
            {
              if (type_dependent_expression_p (t))
@@ -6723,6 +7364,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  error_at (OMP_CLAUSE_LOCATION (c),
                            "%qE does not have a mappable type in %qs clause",
                            t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                 cp_omp_emit_unmappable_type_notes (TREE_TYPE (t));
                  remove = true;
                }
              while (TREE_CODE (t) == COMPONENT_REF)
@@ -6754,31 +7396,36 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                break;
              if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
                  && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
-                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
+                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
+                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH))
                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;
            }
          else if (!processing_template_decl
-                  && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
+                  && !TYPE_REF_P (TREE_TYPE (t))
                   && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
                       || (OMP_CLAUSE_MAP_KIND (c)
                           != GOMP_MAP_FIRSTPRIVATE_POINTER))
@@ -6790,22 +7437,23 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                             == GOMP_MAP_FIRSTPRIVATE_POINTER)))
                   && t == OMP_CLAUSE_DECL (c)
                   && !type_dependent_expression_p (t)
-                  && !cp_omp_mappable_type ((TREE_CODE (TREE_TYPE (t))
-                                             == REFERENCE_TYPE)
+                  && !cp_omp_mappable_type (TYPE_REF_P (TREE_TYPE (t))
                                             ? TREE_TYPE (TREE_TYPE (t))
                                             : TREE_TYPE (t)))
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%qD does not have a mappable type in %qs clause", t,
                        omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             cp_omp_emit_unmappable_type_notes (TREE_TYPE (t));
              remove = true;
            }
          else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
                   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR
                   && !type_dependent_expression_p (t)
-                  && !POINTER_TYPE_P (TREE_TYPE (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
@@ -6814,37 +7462,47 @@ 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
                bitmap_set_bit (&generic_head, DECL_UID (t));
            }
-         else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+         else if (bitmap_bit_p (&map_head, DECL_UID (t))
+                  && (ort != C_ORT_ACC
+                      || !bitmap_bit_p (&map_field_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
@@ -6857,8 +7515,8 @@ 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
-             && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == REFERENCE_TYPE)
+             && ort != C_ORT_DECLARE_SIMD
+             && TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
            {
              t = OMP_CLAUSE_DECL (c);
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
@@ -6878,7 +7536,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
                                              OMP_CLAUSE_MAP);
                  if (TREE_CODE (t) == COMPONENT_REF)
-                   OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+                   {
+                     gomp_map_kind k
+                       = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                            : GOMP_MAP_ALWAYS_POINTER;
+                     OMP_CLAUSE_SET_MAP_KIND (c2, k);
+                   }
                  else
                    OMP_CLAUSE_SET_MAP_KIND (c2,
                                             GOMP_MAP_FIRSTPRIVATE_REFERENCE);
@@ -6937,6 +7600,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%qD does not have a mappable type in %qs clause", t,
                        omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             cp_omp_emit_unmappable_type_notes (TREE_TYPE (t));
              remove = true;
            }
          if (remove)
@@ -6959,9 +7623,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;
            }
@@ -6976,7 +7642,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
@@ -7005,7 +7672,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
@@ -7034,7 +7702,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
@@ -7044,6 +7713,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;
            }
@@ -7056,21 +7732,42 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          if (!type_dependent_expression_p (t))
            {
              tree type = TREE_TYPE (t);
-             if (TREE_CODE (type) != POINTER_TYPE
-                 && TREE_CODE (type) != ARRAY_TYPE
-                 && (TREE_CODE (type) != REFERENCE_TYPE
-                     || (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
-                         && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)))
+             if (!TYPE_PTR_P (type)
+                 && (!TYPE_REF_P (type) || !TYPE_PTR_P (TREE_TYPE (type))))
                {
-                 error_at (OMP_CLAUSE_LOCATION (c),
-                           "%qs variable is neither a pointer, nor an array "
-                           "nor reference to pointer or array",
-                           omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
-                 remove = true;
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
+                     && ort == C_ORT_OMP)
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%qs variable is neither a pointer "
+                               "nor reference to pointer",
+                               omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     remove = true;
+                   }
+                 else if (TREE_CODE (type) != ARRAY_TYPE
+                          && (!TYPE_REF_P (type)
+                              || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%qs variable is neither a pointer, nor an "
+                               "array nor reference to pointer or array",
+                               omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     remove = true;
+                   }
                }
            }
          goto check_dup_generic;
 
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
+         field_ok = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (!processing_template_decl
+             && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+             && !TYPE_REF_P (TREE_TYPE (t))
+             && !cxx_mark_addressable (t))
+           remove = true;
+         goto check_dup_generic;
+
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
@@ -7081,13 +7778,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_SECTIONS:
        case OMP_CLAUSE_TASKGROUP:
        case OMP_CLAUSE_PROC_BIND:
+       case OMP_CLAUSE_DEVICE_TYPE:
        case OMP_CLAUSE_NOGROUP:
        case OMP_CLAUSE_THREADS:
        case OMP_CLAUSE_SIMD:
        case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_BIND:
        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:
@@ -7134,17 +7835,56 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          ordered_seen = true;
          break;
 
+       case OMP_CLAUSE_ORDER:
+         if (order_seen)
+           remove = true;
+         else
+           order_seen = true;
+         break;
+
        case OMP_CLAUSE_INBRANCH:
        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;
          break;
 
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
+         t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+         if (!t)
+           t = OMP_CLAUSE_DECL (c);
+         if (t == current_class_ptr)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
+             remove = true;
+             break;
+           }
+         if (!VAR_P (t)
+             && TREE_CODE (t) != PARM_DECL
+             && TREE_CODE (t) != FIELD_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 clause %qs", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             else
+               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;
+           }
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -7155,6 +7895,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        pc = &OMP_CLAUSE_CHAIN (c);
     }
 
+  if (reduction_seen < 0 && (ordered_seen || schedule_seen))
+    reduction_seen = -2;
+
   for (pc = &clauses, c = clauses; c ; c = *pc)
     {
       enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
@@ -7190,6 +7933,16 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_REDUCTION:
+         if (reduction_seen == -2)
+           OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+         if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+           need_copy_assignment = true;
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_IN_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_LINEAR:
@@ -7240,6 +7993,39 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  (OMP_CLAUSE_SCHEDULE_KIND (c)
                   & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
            }
+         if (reduction_seen == -2)
+           error_at (OMP_CLAUSE_LOCATION (c),
+                     "%qs clause specified together with %<inscan%> "
+                     "%<reduction%> clause", "schedule");
+         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_ORDERED:
+         if (reduction_seen == -2)
+           error_at (OMP_CLAUSE_LOCATION (c),
+                     "%qs clause specified together with %<inscan%> "
+                     "%<reduction%> clause", "ordered");
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+       case OMP_CLAUSE_ORDER:
+         if (ordered_seen)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<order%> clause must not be used together "
+                       "with %<ordered%>");
+             *pc = OMP_CLAUSE_CHAIN (c);
+             continue;
+           }
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
        case OMP_CLAUSE_NOWAIT:
@@ -7276,6 +8062,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;
@@ -7286,7 +8074,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;
@@ -7300,7 +8089,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 (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
+         else if (!processing_template_decl
+                  && TYPE_REF_P (TREE_TYPE (t))
                   && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
            remove = true;
        }
@@ -7310,15 +8100,29 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 
          if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
            share_name = "threadprivate";
-         else switch (cxx_omp_predetermined_sharing (t))
+         else switch (cxx_omp_predetermined_sharing_1 (t))
            {
            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:
@@ -7329,9 +8133,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;
            }
        }
@@ -7340,8 +8155,10 @@ 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)
-         && TREE_CODE (inner_type) == REFERENCE_TYPE)
+          || 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)
        inner_type = TREE_TYPE (inner_type);
@@ -7480,7 +8297,7 @@ restore_omp_privatization_clauses (vec<tree> &save)
       save.release ();
       return;
     }
-    
+
   omp_private_member_map = new hash_map <tree, tree>;
   while (!save.is_empty ())
     {
@@ -7541,14 +8358,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))
            {
@@ -7684,7 +8494,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;
@@ -7699,7 +8509,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:
@@ -7849,24 +8658,26 @@ 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);
-  bool taskloop_iv_seen = false;
+  incr = cp_fully_fold (incr);
+  tree loop_iv_seen = NULL_TREE;
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
        && OMP_CLAUSE_DECL (c) == iter)
       {
-       if (code == OMP_TASKLOOP)
+       if (code == OMP_TASKLOOP || code == OMP_LOOP)
          {
-           taskloop_iv_seen = true;
-           OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c) = 1;
+           loop_iv_seen = c;
+           OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) = 1;
          }
        break;
       }
-    else if (code == OMP_TASKLOOP
+    else if ((code == OMP_TASKLOOP || code == OMP_LOOP)
             && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
             && OMP_CLAUSE_DECL (c) == iter)
       {
-       taskloop_iv_seen = true;
-       OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
+       loop_iv_seen = c;
+       if (code == OMP_TASKLOOP)
+         OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
       }
 
   decl = create_temporary_var (TREE_TYPE (diff));
@@ -7886,7 +8697,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   tree diffvar = NULL_TREE;
   if (code == OMP_TASKLOOP)
     {
-      if (!taskloop_iv_seen)
+      if (!loop_iv_seen)
        {
          tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
          OMP_CLAUSE_DECL (ivc) = iter;
@@ -7902,6 +8713,28 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
       pushdecl (diffvar);
       add_decl_expr (diffvar);
     }
+  else if (code == OMP_LOOP)
+    {
+      if (!loop_iv_seen)
+       {
+         /* While iterators on the loop construct are predetermined
+            lastprivate, if the decl is not declared inside of the
+            loop, OMP_CLAUSE_LASTPRIVATE should have been added
+            already.  */
+         loop_iv_seen = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+         OMP_CLAUSE_DECL (loop_iv_seen) = iter;
+         OMP_CLAUSE_CHAIN (loop_iv_seen) = clauses;
+         clauses = loop_iv_seen;
+       }
+      else if (OMP_CLAUSE_CODE (loop_iv_seen) == OMP_CLAUSE_PRIVATE)
+       {
+         OMP_CLAUSE_PRIVATE_DEBUG (loop_iv_seen) = 0;
+         OMP_CLAUSE_PRIVATE_OUTER_REF (loop_iv_seen) = 0;
+         OMP_CLAUSE_CODE (loop_iv_seen) = OMP_CLAUSE_FIRSTPRIVATE;
+       }
+      if (OMP_CLAUSE_CODE (loop_iv_seen) == OMP_CLAUSE_FIRSTPRIVATE)
+       cxx_omp_finish_clause (loop_iv_seen, NULL);
+    }
 
   orig_pre_body = *pre_body;
   *pre_body = push_stmt_list ();
@@ -7984,11 +8817,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;
 }
@@ -8007,7 +8851,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;
@@ -8071,6 +8914,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");
@@ -8093,7 +8939,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;
@@ -8174,7 +9021,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;
@@ -8226,20 +9073,19 @@ 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))
     omp_for = NULL_TREE;
 
   if (omp_for == NULL)
-    {
-      return NULL;
-    }
+    return NULL;
 
   add_stmt (omp_for);
 
@@ -8296,14 +9142,14 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
            case POSTINCREMENT_EXPR:
              /* c_omp_for_incr_canonicalize_ptr() should have been
                 called to massage things appropriately.  */
-             gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+             gcc_assert (!INDIRECT_TYPE_P (TREE_TYPE (decl)));
              OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1);
              break;
            case PREDECREMENT_EXPR:
            case POSTDECREMENT_EXPR:
              /* c_omp_for_incr_canonicalize_ptr() should have been
                 called to massage things appropriately.  */
-             gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+             gcc_assert (!INDIRECT_TYPE_P (TREE_TYPE (decl)));
              OMP_CLAUSE_LINEAR_STEP (c)
                = build_int_cst (TREE_TYPE (decl), -1);
              break;
@@ -8327,7 +9173,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
                  gcc_unreachable ();
                }
              stept = TREE_TYPE (decl);
-             if (POINTER_TYPE_P (stept))
+             if (INDIRECT_TYPE_P (stept))
                stept = sizetype;
              step = fold_convert (stept, step);
              if (TREE_CODE (incr) == MINUS_EXPR)
@@ -8338,13 +9184,69 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
              gcc_unreachable ();
            }
        }
+  /* Override saved methods on OMP_LOOP's OMP_CLAUSE_LASTPRIVATE_LOOP_IV
+     clauses, we need copy ctor for those rather than default ctor,
+     plus as for other lastprivates assignment op and dtor.  */
+  if (code == OMP_LOOP && !processing_template_decl)
+    for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+         && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)
+         && cxx_omp_create_clause_info (c, TREE_TYPE (OMP_CLAUSE_DECL (c)),
+                                        false, true, true, true))
+       CP_OMP_CLAUSE_INFO (c) = NULL_TREE;
 
   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;
@@ -8371,6 +9273,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);
@@ -8412,8 +9323,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;
@@ -8422,31 +9333,36 @@ 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
        {
          if (opcode == NOP_EXPR)
            stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
-         else 
+         else
            stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
          if (orig_rhs1)
            stmt = build_min_nt_loc (EXPR_LOCATION (orig_rhs1),
                                     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);
 }
 
@@ -8454,19 +9370,57 @@ void
 finish_omp_barrier (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
 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 (loc, 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 ();
+  releasing_vec vec;
+  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);
 }
 
@@ -8474,9 +9428,8 @@ void
 finish_omp_taskwait (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -8484,9 +9437,8 @@ void
 finish_omp_taskyield (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -8509,21 +9461,40 @@ finish_omp_cancel (tree clauses)
             "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
       return;
     }
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   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;
   vec->quick_push (build_int_cst (integer_type_node, mask));
   vec->quick_push (ifc);
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -8546,10 +9517,9 @@ finish_omp_cancellation_point (tree clauses)
             "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
       return;
     }
-  vec<tree, va_gc> *vec
+  releasing_vec vec
     = make_tree_vector_single (build_int_cst (integer_type_node, mask));
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 \f
@@ -8642,8 +9612,8 @@ init_cp_semantics (void)
    CONDITION and the message text MESSAGE.  LOCATION is the location
    of the static assertion in the source code.  When MEMBER_P, this
    static assertion is a member of a class.  */
-void 
-finish_static_assert (tree condition, tree message, location_t location, 
+void
+finish_static_assert (tree condition, tree message, location_t location,
                       bool member_p)
 {
   tsubst_flags_t complain = tf_warning_or_error;
@@ -8669,7 +9639,7 @@ finish_static_assert (tree condition, tree message, location_t location,
       STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
 
       if (member_p)
-        maybe_add_class_template_decl_list (current_class_type, 
+        maybe_add_class_template_decl_list (current_class_type,
                                             assertion,
                                             /*friend_p=*/0);
       else
@@ -8678,20 +9648,24 @@ finish_static_assert (tree condition, tree message, location_t location,
       return;
     }
 
+  /* Save the condition in case it was a concept check.  */
+  tree orig_condition = condition;
+
   /* 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. */
     ;
-  else 
+  else
     {
       location_t saved_loc = input_location;
 
       input_location = location;
-      if (TREE_CODE (condition) == INTEGER_CST 
+      if (TREE_CODE (condition) == INTEGER_CST
           && integer_zerop (condition))
        {
          int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
@@ -8703,6 +9677,10 @@ finish_static_assert (tree condition, tree message, location_t location,
          else
             error ("static assertion failed: %s",
                   TREE_STRING_POINTER (message));
+
+         /* Actually explain the failure if this is a concept check.  */
+         if (concept_check_p (orig_condition))
+           diagnose_constraints (location, orig_condition, NULL_TREE);
        }
       else if (condition && condition != error_mark_node)
        {
@@ -8736,7 +9714,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
          && TYPE_P (TREE_OPERAND (expr, 0))))
     {
       if (complain & tf_error)
-       error ("argument to decltype must be an expression");
+       error ("argument to %<decltype%> must be an expression");
       return error_mark_node;
     }
 
@@ -8764,7 +9742,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
   if (type_unknown_p (expr))
     {
       if (complain & tf_error)
-       error ("decltype cannot resolve address of overloaded function");
+       error ("%<decltype%> cannot resolve address of overloaded function");
       return error_mark_node;
     }
 
@@ -8784,7 +9762,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);
@@ -8891,7 +9870,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
             decltype(e) is defined as T&; if an xvalue, T&&; otherwise, T. */
          cp_lvalue_kind clk = lvalue_kind (expr);
          type = unlowered_expr_type (expr);
-         gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
+         gcc_assert (!TYPE_REF_P (type));
 
          /* For vector types, pick a non-opaque variant.  */
          if (VECTOR_TYPE_P (type))
@@ -8905,7 +9884,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
   return type;
 }
 
-/* Called from trait_expr_value to evaluate either __has_nothrow_assign or 
+/* Called from trait_expr_value to evaluate either __has_nothrow_assign or
    __has_nothrow_copy, depending on assign_p.  Returns true iff all
    the copy {ctor,assign} fns are nothrow.  */
 
@@ -8926,8 +9905,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;
        }
     }
@@ -8966,11 +9945,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
 
     case CPTK_HAS_NOTHROW_CONSTRUCTOR:
       type1 = strip_array_types (type1);
-      return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, 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);
@@ -9093,7 +10072,7 @@ check_trait_type (tree type)
 /* Process a trait expression.  */
 
 tree
-finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
+finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
 {
   if (type1 == error_mark_node
       || type2 == error_mark_node)
@@ -9106,6 +10085,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       TRAIT_EXPR_TYPE1 (trait_expr) = type1;
       TRAIT_EXPR_TYPE2 (trait_expr) = type2;
       TRAIT_EXPR_KIND (trait_expr) = kind;
+      TRAIT_EXPR_LOCATION (trait_expr) = loc;
       return trait_expr;
     }
 
@@ -9163,8 +10143,9 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       gcc_unreachable ();
     }
 
-  return (trait_expr_value (kind, type1, type2)
-         ? boolean_true_node : boolean_false_node);
+tree val = (trait_expr_value (kind, type1, type2)
+           ? boolean_true_node : boolean_false_node);
+ return maybe_wrap_with_location (val, loc);
 }
 
 /* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64,
@@ -9245,7 +10226,6 @@ apply_deduced_return_type (tree fco, tree return_type)
 #endif
       cfun->returns_struct = aggr;
     }
-
 }
 
 /* DECL is a local variable or parameter from the surrounding scope of a
@@ -9256,12 +10236,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))
       {
@@ -9271,14 +10251,14 @@ capture_decltype (tree decl)
 
       case CPLD_COPY:
        type = TREE_TYPE (decl);
-       if (TREE_CODE (type) == REFERENCE_TYPE
+       if (TYPE_REF_P (type)
            && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
          type = TREE_TYPE (type);
        break;
 
       case CPLD_REFERENCE:
        type = TREE_TYPE (decl);
-       if (TREE_CODE (type) != REFERENCE_TYPE)
+       if (!TYPE_REF_P (type))
          type = build_reference_type (TREE_TYPE (decl));
        break;
 
@@ -9286,7 +10266,7 @@ capture_decltype (tree decl)
        gcc_unreachable ();
       }
 
-  if (TREE_CODE (type) != REFERENCE_TYPE)
+  if (!TYPE_REF_P (type))
     {
       if (!LAMBDA_EXPR_MUTABLE_P (lam))
        type = cp_build_qualified_type (type, (cp_type_quals (type)
@@ -9302,7 +10282,7 @@ capture_decltype (tree decl)
 static tree
 finish_unary_fold_expr (tree expr, int op, tree_code dir)
 {
-  // Build a pack expansion (assuming expr has pack type).
+  /* Build a pack expansion (assuming expr has pack type).  */
   if (!uses_parameter_packs (expr))
     {
       error_at (location_of (expr), "operand of fold expression has no "
@@ -9311,7 +10291,7 @@ finish_unary_fold_expr (tree expr, int op, tree_code dir)
     }
   tree pack = make_pack_expansion (expr);
 
-  // Build the fold expression.
+  /* Build the fold expression.  */
   tree code = build_int_cstu (integer_type_node, abs (op));
   tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack);
   FOLD_EXPR_MODIFY_P (fold) = (op < 0);
@@ -9376,7 +10356,7 @@ finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain)
   if (error_operand_p (arg))
     return error_mark_node;
   if (!type_dependent_expression_p (arg)
-      && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
+      && !TYPE_PTR_P (TREE_TYPE (arg)))
     {
       error_at (loc, "non-pointer argument to %<__builtin_launder%>");
       return error_mark_node;
@@ -9387,4 +10367,26 @@ 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_input_loc (arg), arg,
+                              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"