decl.c (cxx_maybe_build_cleanup): When clearing location of cleanup...
[gcc.git] / gcc / cp / decl.c
index 67d9244c450e3fb878064f243454461644c1ab4c..5e510c91aa30c0c35afe49669a60895203f0719c 100644 (file)
@@ -1,4 +1,4 @@
-/* Process declarations and variables for C++ compiler.
+/* Process declarations and variables for -*- C++ -*- compiler.
    Copyright (C) 1988-2019 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -80,7 +80,6 @@ static void maybe_deduce_size_from_array_init (tree, tree);
 static void layout_var_decl (tree);
 static tree check_initializer (tree, tree, int, vec<tree, va_gc> **);
 static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
-static void save_function_data (tree);
 static void copy_type_enum (tree , tree);
 static void check_function_type (tree, tree);
 static void finish_constructor_body (void);
@@ -101,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_code, tree, int);
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
+static location_t smallest_type_location (const cp_decl_specifier_seq*);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
    listed here individually for documentation purposes.
@@ -920,6 +920,31 @@ determine_local_discriminator (tree decl)
 }
 
 \f
+
+/* Returns true if functions FN1 and FN2 have equivalent trailing
+   requires clauses.  */
+
+static bool
+function_requirements_equivalent_p (tree newfn, tree oldfn)
+{
+  /* In the concepts TS, the combined constraints are compared.  */
+  if (cxx_dialect < cxx2a)
+    {
+      tree ci1 = get_constraints (oldfn);
+      tree ci2 = get_constraints (newfn);
+      tree req1 = ci1 ? CI_ASSOCIATED_CONSTRAINTS (ci1) : NULL_TREE;
+      tree req2 = ci2 ? CI_ASSOCIATED_CONSTRAINTS (ci2) : NULL_TREE;
+      return cp_tree_equal (req1, req2);
+    }
+
+  /* Compare only trailing requirements.  */
+  tree reqs1 = get_trailing_function_requirements (newfn);
+  tree reqs2 = get_trailing_function_requirements (oldfn);
+  if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE))
+    return false;
+  return cp_tree_equal (reqs1, reqs2);
+}
+
 /* Subroutine of duplicate_decls: return truthvalue of whether
    or not types of these decls match.
 
@@ -999,6 +1024,12 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
       else
        types_match = 0;
 
+      /* Two function declarations match if either has a requires-clause
+         then both have a requires-clause and their constraints-expressions
+         are equivalent.  */
+      if (types_match && flag_concepts)
+       types_match = function_requirements_equivalent_p (newdecl, olddecl);
+
       /* The decls dont match if they correspond to two different versions
         of the same function.   Disallow extern "C" functions to be
         versions for now.  */
@@ -1013,23 +1044,21 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
+      if (!template_heads_equivalent_p (newdecl, olddecl))
+       return 0;
+
       tree oldres = DECL_TEMPLATE_RESULT (olddecl);
       tree newres = DECL_TEMPLATE_RESULT (newdecl);
 
       if (TREE_CODE (newres) != TREE_CODE (oldres))
        return 0;
 
-      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-                               DECL_TEMPLATE_PARMS (olddecl)))
-       return 0;
-
-      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-       types_match = (same_type_p (TREE_TYPE (oldres), TREE_TYPE (newres))
-                      && equivalently_constrained (olddecl, newdecl));
+      /* Two template types match if they are the same. Otherwise, compare
+         the underlying declarations.  */
+      if (TREE_CODE (newres) == TYPE_DECL)
+        types_match = same_type_p (TREE_TYPE (newres), TREE_TYPE (oldres));
       else
-       // We don't need to check equivalently_constrained for variable and
-       // function templates because we check it on the results.
-       types_match = decls_match (oldres, newres);
+       types_match = decls_match (newres, oldres);
     }
   else
     {
@@ -1057,11 +1086,6 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
                                 COMPARE_REDECLARATION);
     }
 
-  // Normal functions can be constrained, as can variable partial
-  // specializations.
-  if (types_match && VAR_OR_FUNCTION_DECL_P (newdecl))
-    types_match = equivalently_constrained (newdecl, olddecl);
-
   return types_match;
 }
 
@@ -1336,6 +1360,46 @@ merge_attribute_bits (tree newdecl, tree olddecl)
                          && lookup_attribute ("gnu_inline",            \
                                               DECL_ATTRIBUTES (fn)))
 
+/* A subroutine of duplicate_decls. Emits a diagnostic when newdecl
+   ambiguates olddecl.  Returns true if an error occurs.  */
+
+static bool
+duplicate_function_template_decls (tree newdecl, tree olddecl)
+{
+
+  tree newres = DECL_TEMPLATE_RESULT (newdecl);
+  tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+  /* Function template declarations can be differentiated by parameter
+     and return type.  */
+  if (compparms (TYPE_ARG_TYPES (TREE_TYPE (oldres)),
+                TYPE_ARG_TYPES (TREE_TYPE (newres)))
+       && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+                      TREE_TYPE (TREE_TYPE (olddecl))))
+    {
+      /* ... and also by their template-heads and requires-clauses.  */
+      if (template_heads_equivalent_p (newdecl, olddecl)
+         && function_requirements_equivalent_p (newres, oldres))
+       {
+         error ("ambiguating new declaration %q+#D", newdecl);
+         inform (DECL_SOURCE_LOCATION (olddecl),
+                 "old declaration %q#D", olddecl);
+         return true;
+       }
+
+      /* FIXME: The types are the same but the are differences
+        in either the template heads or function requirements.
+        We should be able to diagnose a set of common errors
+        stemming from these declarations. For example:
+
+          template<typename T> requires C void f(...);
+          template<typename T> void f(...) requires C;
+
+        These are functionally equivalent but not equivalent.  */
+    }
+
+  return false;
+}
+
 /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
    If the redeclaration is invalid, a diagnostic is issued, and the
    error_mark_node is returned.  Otherwise, OLDDECL is returned.
@@ -1476,7 +1540,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
                  if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
                    break;
-next_arg:;
+               next_arg:;
                }
 
              warning_at (newdecl_loc,
@@ -1644,11 +1708,14 @@ next_arg:;
 
       if (TREE_CODE (newdecl) == TEMPLATE_DECL)
        {
+         tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+         tree newres = DECL_TEMPLATE_RESULT (newdecl);
+
          /* The name of a class template may not be declared to refer to
             any other template, class, function, object, namespace, value,
             or type in the same scope.  */
-         if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
-             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+         if (TREE_CODE (oldres) == TYPE_DECL
+             || TREE_CODE (newres) == TYPE_DECL)
            {
              error_at (newdecl_loc,
                        "conflicting declaration of template %q#D", newdecl);
@@ -1656,24 +1723,13 @@ next_arg:;
                      "previous declaration %q#D", olddecl);
              return error_mark_node;
            }
-         else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
-                  && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
-                  && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
-                                TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
-                  && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-                                          DECL_TEMPLATE_PARMS (olddecl))
-                  /* Template functions can be disambiguated by
-                     return type.  */
-                  && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
-                                  TREE_TYPE (TREE_TYPE (olddecl)))
-                   /* Template functions can also be disambiguated by
-                     constraints.  */
-                   && equivalently_constrained (olddecl, newdecl))
+
+         else if (TREE_CODE (oldres) == FUNCTION_DECL
+                  && TREE_CODE (newres) == FUNCTION_DECL)
            {
-             error_at (newdecl_loc, "ambiguating new declaration %q#D",
-                       newdecl);
-             inform (olddecl_loc,
-                     "old declaration %q#D", olddecl);
+             if (duplicate_function_template_decls (newdecl, olddecl))
+               return error_mark_node;
+             return NULL_TREE;
            }
           else if (check_concept_refinement (olddecl, newdecl))
            return error_mark_node;
@@ -1923,10 +1979,29 @@ next_arg:;
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
-      if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl))
-       inform (olddecl_loc, DECL_INITIAL (olddecl)
-               ? G_("previous definition of %qD here")
-               : G_("previous declaration of %qD here"), olddecl);
+      if (merge_attr)
+       {
+         if (diagnose_mismatched_attributes (olddecl, newdecl))
+           inform (olddecl_loc, DECL_INITIAL (olddecl)
+                   ? G_("previous definition of %qD here")
+                   : G_("previous declaration of %qD here"), olddecl);
+
+         /* [dcl.attr.noreturn]: The first declaration of a function shall
+            specify the noreturn attribute if any declaration of that function
+            specifies the noreturn attribute.  */
+         tree a;
+         if (TREE_THIS_VOLATILE (newdecl)
+             && !TREE_THIS_VOLATILE (olddecl)
+             /* This applies to [[noreturn]] only, not its GNU variants.  */
+             && (a = lookup_attribute ("noreturn", DECL_ATTRIBUTES (newdecl)))
+             && cxx11_attribute_p (a)
+             && get_attribute_namespace (a) == NULL_TREE)
+           {
+             error_at (newdecl_loc, "function %qD declared %<[[noreturn]]%> "
+                       "but its first declaration was not", newdecl);
+             inform (olddecl_loc, "previous declaration of %qD", olddecl);
+           }
+       }
 
       /* Now that functions must hold information normally held
         by field decls, there is extra work to do so that
@@ -2026,9 +2101,10 @@ next_arg:;
       tree old_result = DECL_TEMPLATE_RESULT (olddecl);
       tree new_result = DECL_TEMPLATE_RESULT (newdecl);
       TREE_TYPE (olddecl) = TREE_TYPE (old_result);
-      DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
-       = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
-                  DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+
+      /* The new decl should not already have gathered any
+        specializations.  */
+      gcc_assert (!DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
 
       DECL_ATTRIBUTES (old_result)
        = (*targetm.merge_decl_attributes) (old_result, new_result);
@@ -2133,7 +2209,24 @@ next_arg:;
            {
              tree remove = TREE_TYPE (newdecl);
              if (TYPE_MAIN_VARIANT (remove) == remove)
-               gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+               {
+                 gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+                 /* If remove is the main variant, no need to remove that
+                    from the list.  One of the DECL_ORIGINAL_TYPE
+                    variants, e.g. created for aligned attribute, might still
+                    refer to the newdecl TYPE_DECL though, so remove that one
+                    in that case.  */
+                 if (tree orig = DECL_ORIGINAL_TYPE (newdecl))
+                   if (orig != remove)
+                     for (tree t = TYPE_MAIN_VARIANT (orig); t;
+                          t = TYPE_MAIN_VARIANT (t))
+                       if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
+                         {
+                           TYPE_NEXT_VARIANT (t)
+                             = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
+                           break;
+                         }
+               }           
              else
                for (tree t = TYPE_MAIN_VARIANT (remove); ;
                     t = TYPE_NEXT_VARIANT (t))
@@ -2167,9 +2260,8 @@ next_arg:;
            SET_DECL_DEPENDENT_INIT_P (newdecl, true);
          DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
            |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
-          if (DECL_CLASS_SCOPE_P (olddecl))
-            DECL_DECLARED_CONSTEXPR_P (newdecl)
-             |= DECL_DECLARED_CONSTEXPR_P (olddecl);
+         DECL_DECLARED_CONSTEXPR_P (newdecl)
+           |= DECL_DECLARED_CONSTEXPR_P (olddecl);
 
          /* Merge the threadprivate attribute from OLDDECL into NEWDECL.  */
          if (DECL_LANG_SPECIFIC (olddecl)
@@ -2256,7 +2348,8 @@ next_arg:;
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
          DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
-         DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+         if (DECL_IS_OPERATOR_NEW_P (olddecl))
+           DECL_SET_IS_OPERATOR_NEW (newdecl, true);
          DECL_LOOPING_CONST_OR_PURE_P (newdecl)
            |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
 
@@ -2351,7 +2444,6 @@ next_arg:;
       /* Don't really know how much of the language-specific
         values we should copy from old to new.  */
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
-      DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
       DECL_INITIALIZED_IN_CLASS_P (newdecl)
        |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
 
@@ -2369,9 +2461,10 @@ next_arg:;
            }
          DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
        }
-      /* Only functions have these fields.  */
+
       if (DECL_DECLARES_FUNCTION_P (newdecl))
        {
+         /* Only functions have these fields.  */
          DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
          DECL_BEFRIENDING_CLASSES (newdecl)
            = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
@@ -2381,10 +2474,12 @@ next_arg:;
          if (DECL_VIRTUAL_P (newdecl))
            SET_DECL_THUNKS (newdecl, DECL_THUNKS (olddecl));
        }
-      /* Only variables have this field.  */
-      else if (VAR_P (newdecl)
-              && VAR_HAD_UNKNOWN_BOUND (olddecl))
-       SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
+      else if (VAR_P (newdecl))
+       {
+         /* Only variables have this field.  */
+         if (VAR_HAD_UNKNOWN_BOUND (olddecl))
+           SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
+       }
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2460,9 +2555,9 @@ next_arg:;
            }
          else if (DECL_PENDING_INLINE_P (newdecl))
            ;
-         else if (DECL_SAVED_FUNCTION_DATA (newdecl) == NULL)
-           DECL_SAVED_FUNCTION_DATA (newdecl)
-             = DECL_SAVED_FUNCTION_DATA (olddecl);
+         else if (DECL_SAVED_AUTO_RETURN_TYPE (newdecl) == NULL)
+           DECL_SAVED_AUTO_RETURN_TYPE (newdecl)
+             = DECL_SAVED_AUTO_RETURN_TYPE (olddecl);
 
          DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
 
@@ -2503,8 +2598,7 @@ next_arg:;
       if (fndecl_built_in_p (olddecl)
          && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
        {
-         DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
-         DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+         copy_decl_built_in_function (newdecl, olddecl);
          /* If we're keeping the built-in definition, keep the rtl,
             regardless of declaration matches.  */
          COPY_DECL_RTL (olddecl, newdecl);
@@ -2525,9 +2619,9 @@ next_arg:;
                    set_builtin_decl_declared_p (fncode, true);
                  break;
                }
-           }
 
-         copy_attributes_to_builtin (newdecl);
+             copy_attributes_to_builtin (newdecl);
+           }
        }
       if (new_defines_function)
        /* If defining a function declared with other language
@@ -2878,6 +2972,9 @@ redeclaration_error_message (tree newdecl, tree olddecl)
          return NULL;
        }
 
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == CONCEPT_DECL)
+        return G_("redefinition of %q#D");
+
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
          || (DECL_TEMPLATE_RESULT (newdecl)
              == DECL_TEMPLATE_RESULT (olddecl)))
@@ -3209,32 +3306,32 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        {
        case sk_try:
          if (!saw_eh)
-           inf = N_("enters try block");
+           inf = G_("  enters %<try%> block");
          saw_eh = true;
          break;
 
        case sk_catch:
          if (!saw_eh)
-           inf = N_("enters catch block");
+           inf = G_("  enters %<catch%> block");
          saw_eh = true;
          break;
 
        case sk_omp:
          if (!saw_omp)
-           inf = N_("enters OpenMP structured block");
+           inf = G_("  enters OpenMP structured block");
          saw_omp = true;
          break;
 
        case sk_transaction:
          if (!saw_tm)
-           inf = N_("enters synchronized or atomic statement");
+           inf = G_("  enters synchronized or atomic statement");
          saw_tm = true;
          break;
 
        case sk_block:
          if (!saw_cxif && level_for_constexpr_if (b->level_chain))
            {
-             inf = N_("enters constexpr if statement");
+             inf = G_("  enters %<constexpr if%> statement");
              loc = EXPR_LOCATION (b->level_chain->this_entity);
              saw_cxif = true;
            }
@@ -3250,7 +3347,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
            complained = identify_goto (decl, input_location, locus, DK_ERROR);
          identified = 2;
          if (complained)
-           inform (loc, "  %s", inf);
+           inform (loc, inf);
        }
     }
 
@@ -3345,7 +3442,7 @@ check_goto (tree decl)
              identified = 2;
            }
          if (complained)
-           inform (DECL_SOURCE_LOCATION (bad), "  enters catch block");
+           inform (DECL_SOURCE_LOCATION (bad), "  enters %<catch%> block");
          saw_catch = true;
        }
       else if (complained)
@@ -3363,13 +3460,13 @@ check_goto (tree decl)
   if (complained)
     {
       if (ent->in_try_scope)
-       inform (input_location, "  enters try block");
+       inform (input_location, "  enters %<try%> block");
       else if (ent->in_catch_scope && !saw_catch)
-       inform (input_location, "  enters catch block");
+       inform (input_location, "  enters %<catch%> block");
       else if (ent->in_transaction_scope)
        inform (input_location, "  enters synchronized or atomic statement");
       else if (ent->in_constexpr_if)
-       inform (input_location, "  enters %<constexpr%> if statement");
+       inform (input_location, "  enters %<constexpr if%> statement");
     }
 
   if (ent->in_omp_scope)
@@ -3478,9 +3575,6 @@ struct cp_switch
      label.  We need a tree, rather than simply a hash table, because
      of the GNU case range extension.  */
   splay_tree cases;
-  /* Remember whether there was a case value that is outside the
-     range of the original type of the controlling expression.  */
-  bool outside_range_p;
   /* Remember whether a default: case label has been seen.  */
   bool has_default_p;
   /* Remember whether a BREAK_STMT has been seen in this SWITCH_STMT.  */
@@ -3509,7 +3603,6 @@ push_switch (tree switch_stmt)
   p->next = switch_stack;
   p->switch_stmt = switch_stmt;
   p->cases = splay_tree_new (case_compare, NULL, NULL);
-  p->outside_range_p = false;
   p->has_default_p = false;
   p->break_stmt_seen_p = false;
   p->in_loop_body_p = false;
@@ -3523,15 +3616,14 @@ pop_switch (void)
   location_t switch_location;
 
   /* Emit warnings as needed.  */
-  switch_location = cp_expr_loc_or_loc (cs->switch_stmt, input_location);
+  switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt);
   const bool bool_cond_p
     = (SWITCH_STMT_TYPE (cs->switch_stmt)
        && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
   if (!processing_template_decl)
     c_do_switch_warnings (cs->cases, switch_location,
                          SWITCH_STMT_TYPE (cs->switch_stmt),
-                         SWITCH_STMT_COND (cs->switch_stmt),
-                         bool_cond_p, cs->outside_range_p);
+                         SWITCH_STMT_COND (cs->switch_stmt), bool_cond_p);
 
   /* For the benefit of block_may_fallthru remember if the switch body
      case labels cover all possible values and if there are break; stmts.  */
@@ -3595,16 +3687,23 @@ case_conversion (tree type, tree value)
 
   value = mark_rvalue_use (value);
 
+  if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+    type = type_promotes_to (type);
+
+  tree ovalue = value;
+  /* The constant-expression VALUE shall be a converted constant expression
+     of the adjusted type of the switch condition, which doesn't allow
+     narrowing conversions.  */
+  value = build_converted_constant_expr (type, value, tf_warning_or_error);
+
   if (cxx_dialect >= cxx11
       && (SCOPED_ENUM_P (type)
-         || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))))
-    {
-      if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
-       type = type_promotes_to (type);
-      value = (perform_implicit_conversion_flags
-              (type, value, tf_warning_or_error,
-               LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL));
-    }
+         || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (ovalue))))
+    /* Use the converted value.  */;
+  else
+    /* The already integral case.  */
+    value = ovalue;
+
   return cxx_constant_value (value);
 }
 
@@ -3646,9 +3745,7 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
   low_value = case_conversion (type, low_value);
   high_value = case_conversion (type, high_value);
 
-  r = c_add_case_label (loc, switch_stack->cases, cond, type,
-                       low_value, high_value,
-                       &switch_stack->outside_range_p);
+  r = c_add_case_label (loc, switch_stack->cases, cond, low_value, high_value);
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
@@ -4108,6 +4205,9 @@ initialize_predefined_identifiers (void)
     {"value", &value_identifier, cik_normal},
     {"_FUN", &fun_identifier, cik_normal},
     {"__closure", &closure_identifier, cik_normal},
+    {"heap uninit", &heap_uninit_identifier, cik_normal},
+    {"heap ", &heap_identifier, cik_normal},
+    {"heap deleted", &heap_deleted_identifier, cik_normal},
     {NULL, NULL, cik_normal}
   };
 
@@ -4325,12 +4425,14 @@ cxx_init_decl_processing (void)
     deltype = build_exception_variant (deltype, empty_except_spec);
     tree opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
     DECL_IS_MALLOC (opnew) = 1;
-    DECL_IS_OPERATOR_NEW (opnew) = 1;
+    DECL_SET_IS_OPERATOR_NEW (opnew, true);
     opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
     DECL_IS_MALLOC (opnew) = 1;
-    DECL_IS_OPERATOR_NEW (opnew) = 1;
-    push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
-    push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+    DECL_SET_IS_OPERATOR_NEW (opnew, true);
+    tree opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+    DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+    opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+    DECL_SET_IS_OPERATOR_DELETE (opdel, true);
     if (flag_sized_deallocation)
       {
        /* Also push the sized deallocation variants:
@@ -4342,8 +4444,10 @@ cxx_init_decl_processing (void)
        deltype = cp_build_type_attribute_variant (void_ftype_ptr_size,
                                                   extvisattr);
        deltype = build_exception_variant (deltype, empty_except_spec);
-       push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
-       push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+       opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+       DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+       opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+       DECL_SET_IS_OPERATOR_DELETE (opdel, true);
       }
 
     if (aligned_new_threshold)
@@ -4361,18 +4465,20 @@ cxx_init_decl_processing (void)
        newtype = build_exception_variant (newtype, new_eh_spec);
        opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
        DECL_IS_MALLOC (opnew) = 1;
-       DECL_IS_OPERATOR_NEW (opnew) = 1;
+       DECL_SET_IS_OPERATOR_NEW (opnew, true);
        opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
        DECL_IS_MALLOC (opnew) = 1;
-       DECL_IS_OPERATOR_NEW (opnew) = 1;
+       DECL_SET_IS_OPERATOR_NEW (opnew, true);
 
        /* operator delete (void *, align_val_t); */
        deltype = build_function_type_list (void_type_node, ptr_type_node,
                                            align_type_node, NULL_TREE);
        deltype = cp_build_type_attribute_variant (deltype, extvisattr);
        deltype = build_exception_variant (deltype, empty_except_spec);
-       push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
-       push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+       opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+       DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+       opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+       DECL_SET_IS_OPERATOR_DELETE (opdel, true);
 
        if (flag_sized_deallocation)
          {
@@ -4382,8 +4488,10 @@ cxx_init_decl_processing (void)
                                                NULL_TREE);
            deltype = cp_build_type_attribute_variant (deltype, extvisattr);
            deltype = build_exception_variant (deltype, empty_except_spec);
-           push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
-           push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+           opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+           DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+           opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+           DECL_SET_IS_OPERATOR_DELETE (opdel, true);
          }
       }
 
@@ -4464,13 +4572,27 @@ cp_fname_init (const char* name, tree *type_p)
 static tree
 cp_make_fname_decl (location_t loc, tree id, int type_dep)
 {
-  const char *const name = (type_dep && in_template_function ()
-                           ? NULL : fname_as_string (type_dep));
+  const char * name = NULL;
+  bool release_name = false;
+  if (!(type_dep && in_template_function ()))
+    {
+      if (current_function_decl == NULL_TREE)
+       name = "top level";
+      else if (type_dep == 1) /* __PRETTY_FUNCTION__ */
+       name = cxx_printable_name (current_function_decl, 2);
+      else if (type_dep == 0) /* __FUNCTION__ */
+       {
+         name = fname_as_string (type_dep);
+         release_name = true;
+       }
+      else
+       gcc_unreachable ();
+    }
   tree type;
   tree init = cp_fname_init (name, &type);
   tree decl = build_decl (loc, VAR_DECL, id, type);
 
-  if (name)
+  if (release_name)
     free (CONST_CAST (char *, name));
 
   /* As we're using pushdecl_with_scope, we must set the context.  */
@@ -4770,6 +4892,24 @@ warn_misplaced_attr_for_class_type (location_t location,
            class_type, class_key_or_enum_as_string (class_type));
 }
 
+/* Returns the cv-qualifiers that apply to the type specified
+   by the DECLSPECS.  */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = TYPE_UNQUALIFIED;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+    type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+    type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+    type_quals |= TYPE_QUAL_RESTRICT;
+
+  return type_quals;
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
@@ -4789,7 +4929,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
   bool error_p = false;
 
   if (declspecs->multiple_types_p)
-    error ("multiple types in one declaration");
+    error_at (smallest_type_location (declspecs),
+             "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
     {
       if (!in_system_header_at (input_location))
@@ -4849,9 +4990,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
       /* Anonymous unions are objects, so they can have specifiers.  */;
       SET_ANON_AGGR_TYPE_P (declared_type);
 
-      if (TREE_CODE (declared_type) != UNION_TYPE
-         && !in_system_header_at (input_location))
-       pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
+      if (TREE_CODE (declared_type) != UNION_TYPE)
+       pedwarn (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (declared_type)),
+                OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
     }
 
   else
@@ -4896,6 +5037,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
       else if (decl_spec_seq_has_spec_p (declspecs,  ds_constexpr))
         error_at (declspecs->locations[ds_constexpr],
                  "%<constexpr%> cannot be used for type declarations");
+      else if (decl_spec_seq_has_spec_p (declspecs,  ds_constinit))
+       error_at (declspecs->locations[ds_constinit],
+                 "%<constinit%> cannot be used for type declarations");
     }
 
   if (declspecs->attributes && warn_attributes && declared_type)
@@ -5066,7 +5210,8 @@ start_decl (const cp_declarator *declarator,
       && TREE_CODE (decl) == TYPE_DECL)
     {
       error_at (DECL_SOURCE_LOCATION (decl),
-               "typedef %qD is initialized (use decltype instead)", decl);
+               "typedef %qD is initialized (use %qs instead)",
+               decl, "decltype");
       return error_mark_node;
     }
 
@@ -5117,7 +5262,7 @@ start_decl (const cp_declarator *declarator,
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
     warning_at (DECL_SOURCE_LOCATION (decl), 0,
-               "inline function %qD given attribute noinline", decl);
+               "inline function %qD given attribute %qs", decl, "noinline");
 
   if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
     {
@@ -5224,7 +5369,14 @@ start_decl (const cp_declarator *declarator,
     decl = maybe_push_decl (decl);
 
   if (processing_template_decl)
-    decl = push_template_decl (decl);
+    {
+      /* Make sure that for a `constinit' decl push_template_decl creates
+        a DECL_TEMPLATE_INFO info for us, so that cp_finish_decl can then set
+        TINFO_VAR_DECLARED_CONSTINIT.  */
+      if (decl_spec_seq_has_spec_p (declspecs, ds_constinit))
+       retrofit_lang_decl (decl);
+      decl = push_template_decl (decl);
+    }
   if (decl == error_mark_node)
     return error_mark_node;
 
@@ -5451,8 +5603,9 @@ check_array_designated_initializer (constructor_elt *ce,
            sorry ("non-trivial designated initializers not supported");
        }
       else
-       error ("C99 designator %qE is not an integral constant-expression",
-              ce->index);
+       error_at (cp_expr_loc_or_input_loc (ce->index),
+                 "C99 designator %qE is not an integral constant-expression",
+                 ce->index);
 
       return false;
     }
@@ -5681,13 +5834,15 @@ check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
       if (!field)
        return true;
 
+      bool show_notes = true;
+
       if (!constexpr_context_p)
        {
          if (CP_TYPE_CONST_P (type))
            {
              if (complain & tf_error)
-               permerror (DECL_SOURCE_LOCATION (decl),
-                          "uninitialized const %qD", decl);
+               show_notes = permerror (DECL_SOURCE_LOCATION (decl),
+                                       "uninitialized %<const %D%>", decl);
            }
          else
            {
@@ -5696,6 +5851,8 @@ check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
                error_at (DECL_SOURCE_LOCATION (decl),
                          "uninitialized variable %qD in %<constexpr%> "
                          "function", decl);
+             else
+               show_notes = false;
              cp_function_chain->invalid_constexpr = true;
            }
        }
@@ -5704,7 +5861,7 @@ check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
                  "uninitialized variable %qD in %<constexpr%> context",
                  decl);
 
-      if (CLASS_TYPE_P (type) && (complain & tf_error))
+      if (show_notes && CLASS_TYPE_P (type) && (complain & tf_error))
        {
          tree defaulted_ctor;
 
@@ -5826,8 +5983,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
       /* Pointers initialized to strings must be treated as non-zero
         even if the string is empty.  */
       tree init_type = TREE_TYPE (elt_init);
-      if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type))
-         || !initializer_zerop (elt_init))
+      if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)))
+       last_nonzero = index;
+      else if (!type_initializer_zero_p (elt_type, elt_init))
        last_nonzero = index;
 
       /* This can happen with an invalid initializer (c++/54501).  */
@@ -5951,12 +6109,12 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
                  tree id = DECL_NAME (d->cur->index);
                  gcc_assert (id);
                  gcc_checking_assert (d->cur->index
-                                      == get_class_binding (type, id, false));
+                                      == get_class_binding (type, id));
                  field = d->cur->index;
                }
            }
          else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
-           field = get_class_binding (type, d->cur->index, false);
+           field = get_class_binding (type, d->cur->index);
          else
            {
              if (complain & tf_error)
@@ -6018,8 +6176,9 @@ has_designator_problem (reshape_iter *d, tsubst_flags_t complain)
   if (d->cur->index)
     {
       if (complain & tf_error)
-       error ("C99 designator %qE outside aggregate initializer",
-              d->cur->index);
+       error_at (cp_expr_loc_or_input_loc (d->cur->index),
+                 "C99 designator %qE outside aggregate initializer",
+                 d->cur->index);
       else
        return true;
     }
@@ -6364,7 +6523,7 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
 static tree
 check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
 {
-  tree type = TREE_TYPE (decl);
+  tree type;
   tree init_code = NULL;
   tree core_type;
 
@@ -6522,11 +6681,12 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
                 about aggregate initialization of non-aggregate classes.  */
              flags |= LOOKUP_ALREADY_DIGESTED;
            }
-         else if (DECL_DECLARED_CONSTEXPR_P (decl))
+         else if (DECL_DECLARED_CONSTEXPR_P (decl)
+                  || (flags & LOOKUP_CONSTINIT))
            {
-             /* Declared constexpr, but no suitable initializer; massage
-                init appropriately so we can pass it into store_init_value
-                for the error.  */
+             /* Declared constexpr or constinit, but no suitable initializer;
+                massage init appropriately so we can pass it into
+                store_init_value for the error.  */
              if (CLASS_TYPE_P (type)
                  && (!init || TREE_CODE (init) == TREE_LIST))
                {
@@ -6908,6 +7068,19 @@ notice_forced_label_r (tree *tp, int *walk_subtrees, void *)
   return NULL_TREE;
 }
 
+/* Return true if DECL has either a trivial destructor, or for C++2A
+   is constexpr and has a constexpr destructor.  */
+
+static bool
+decl_maybe_constant_destruction (tree decl, tree type)
+{
+  return (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+         || (cxx_dialect >= cxx2a
+             && VAR_P (decl)
+             && DECL_DECLARED_CONSTEXPR_P (decl)
+             && type_has_constexpr_destructor (strip_array_types (type))));
+}
+
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
@@ -7004,8 +7177,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
        return;
       if (TREE_CODE (type) == FUNCTION_TYPE)
        {
-         error ("initializer for %<decltype(auto) %D%> has function type "
-                "(did you forget the %<()%> ?)", decl);
+         error ("initializer for %<decltype(auto) %D%> has function type; "
+                "did you forget the %<()%>?", decl);
          TREE_TYPE (decl) = error_mark_node;
          return;
        }
@@ -7089,6 +7262,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          DECL_INITIAL (decl) = NULL_TREE;
        }
 
+      /* Handle `constinit' on variable templates.  */
+      if (flags & LOOKUP_CONSTINIT)
+       TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (decl)) = true;
+
       /* Generally, initializers in templates are expanded when the
         template is instantiated.  But, if DECL is a variable constant
         then it can be used in future constant expressions, so its value
@@ -7180,6 +7357,19 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 
   if (VAR_P (decl))
     {
+      duration_kind dk = decl_storage_duration (decl);
+      /* [dcl.constinit]/1 "The constinit specifier shall be applied
+        only to a declaration of a variable with static or thread storage
+        duration."  */
+      if ((flags & LOOKUP_CONSTINIT)
+         && !(dk == dk_thread || dk == dk_static))
+       {
+         error_at (DECL_SOURCE_LOCATION (decl),
+                   "%<constinit%> can only be applied to a variable with "
+                   "static or thread storage duration");
+         return;
+       }
+
       /* If this is a local variable that will need a mangled name,
         register it now.  We must do this before processing the
         initializer for the variable, since the initialization might
@@ -7315,7 +7505,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            TREE_READONLY (decl) = 1;
 
          /* Likewise if it needs destruction.  */
-         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+         if (!decl_maybe_constant_destruction (decl, type))
            TREE_READONLY (decl) = 0;
        }
 
@@ -7354,8 +7544,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
               && ! (DECL_LANG_SPECIFIC (decl)
                     && DECL_NOT_REALLY_EXTERN (decl)))
        {
-         if (init)
-           DECL_INITIAL (decl) = init;
+         /* check_initializer will have done any constant initialization.  */
        }
       /* A variable definition.  */
       else if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
@@ -7397,8 +7586,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                            DECL_ATTRIBUTES (decl));
       complete_type (TREE_TYPE (decl));
       if (!cp_omp_mappable_type (TREE_TYPE (decl)))
-       error ("%q+D in declare target directive does not have mappable type",
-              decl);
+       {
+         error ("%q+D in declare target directive does not have mappable"
+                " type", decl);
+         cp_omp_emit_unmappable_type_notes (TREE_TYPE (decl));
+       }
       else if (!lookup_attribute ("omp declare target",
                                  DECL_ATTRIBUTES (decl))
               && !lookup_attribute ("omp declare target link",
@@ -7575,7 +7767,7 @@ get_tuple_decomp_init (tree decl, unsigned i)
     }
   else
     {
-      vec<tree,va_gc> *args = make_tree_vector_single (e);
+      releasing_vec args (make_tree_vector_single (e));
       fns = lookup_template_function (get__identifier, targs);
       fns = perform_koenig_lookup (fns, args, tf_warning_or_error);
       return finish_call_expr (fns, &args, /*novirt*/false,
@@ -7587,13 +7779,6 @@ get_tuple_decomp_init (tree decl, unsigned i)
    based on the actual type of the variable, so store it in a hash table.  */
 
 static GTY((cache)) tree_cache_map *decomp_type_table;
-static void
-store_decomp_type (tree v, tree t)
-{
-  if (!decomp_type_table)
-    decomp_type_table = tree_cache_map::create_ggc (13);
-  decomp_type_table->put (v, t);
-}
 
 tree
 lookup_decomp_type (tree v)
@@ -7609,7 +7794,7 @@ cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
 {
   if (!processing_template_decl
       && !error_operand_p (decl)
-      && DECL_NAMESPACE_SCOPE_P (decl))
+      && TREE_STATIC (decl))
     {
       auto_vec<tree, 16> v;
       v.safe_grow (count);
@@ -7829,7 +8014,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
              goto error_out;
            }
          /* Save the decltype away before reference collapse.  */
-         store_decomp_type (v[i], eltype);
+         hash_map_safe_put<hm_ggc> (decomp_type_table, v[i], eltype);
          eltype = cp_build_reference_type (eltype, !lvalue_p (init));
          TREE_TYPE (v[i]) = eltype;
          layout_decl (v[i], 0);
@@ -7840,8 +8025,27 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
              DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
            }
          if (!processing_template_decl)
-           cp_finish_decl (v[i], init, /*constexpr*/false,
-                           /*asm*/NULL_TREE, LOOKUP_NORMAL);
+           {
+             TREE_PUBLIC (v[i]) = TREE_PUBLIC (decl);
+             TREE_STATIC (v[i]) = TREE_STATIC (decl);
+             DECL_COMMON (v[i]) = DECL_COMMON (decl);
+             DECL_COMDAT (v[i]) = DECL_COMDAT (decl);
+             if (TREE_STATIC (v[i]))
+               {
+                 CP_DECL_THREAD_LOCAL_P (v[i])
+                   = CP_DECL_THREAD_LOCAL_P (decl);
+                 set_decl_tls_model (v[i], DECL_TLS_MODEL (decl));
+                 if (DECL_ONE_ONLY (decl))
+                   make_decl_one_only (v[i], cxx_comdat_group (v[i]));
+                 if (TREE_PUBLIC (decl))
+                   DECL_WEAK (v[i]) = DECL_WEAK (decl);
+                 DECL_VISIBILITY (v[i]) = DECL_VISIBILITY (decl);
+                 DECL_VISIBILITY_SPECIFIED (v[i])
+                   = DECL_VISIBILITY_SPECIFIED (decl);
+               }
+             cp_finish_decl (v[i], init, /*constexpr*/false,
+                             /*asm*/NULL_TREE, LOOKUP_NORMAL);
+           }
        }
       /* Ignore reads from the underlying decl performed during initialization
         of the individual variables.  If those will be read, we'll mark
@@ -8183,6 +8387,13 @@ register_dtor_fn (tree decl)
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     return void_node;
 
+  if (decl_maybe_constant_destruction (decl, type)
+      && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+    {
+      cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+      return void_node;
+    }
+
   /* If we're using "__cxa_atexit" (or "__cxa_thread_atexit" or
      "__aeabi_atexit"), and DECL is a class object, we can just pass the
      destructor to "__cxa_atexit"; we don't have to build a temporary
@@ -8300,7 +8511,7 @@ expand_static_init (tree decl, tree init)
   gcc_assert (TREE_STATIC (decl));
 
   /* Some variables require no dynamic initialization.  */
-  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+  if (decl_maybe_constant_destruction (decl, TREE_TYPE (decl)))
     {
       /* Make sure the destructor is callable.  */
       cxx_maybe_build_cleanup (decl, tf_warning_or_error);
@@ -8813,10 +9024,10 @@ grokfndecl (tree ctype,
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
-  // Was the concept specifier present?
+  /* Was the concept specifier present?  */
   bool concept_p = inlinep & 4;
 
-  // Concept declarations must have a corresponding definition.
+  /* Concept declarations must have a corresponding definition.  */
   if (concept_p && !funcdef_flag)
     {
       error_at (location, "concept %qD has no definition", declarator);
@@ -8833,12 +9044,12 @@ grokfndecl (tree ctype,
       tree tmpl_reqs = NULL_TREE;
       if (processing_template_decl > template_class_depth (ctype))
         tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
-
-      /* Adjust the required expression into a constraint. */
-      if (decl_reqs)
-        decl_reqs = normalize_expression (decl_reqs);
-
       tree ci = build_constraints (tmpl_reqs, decl_reqs);
+      if (concept_p && ci)
+        {
+          error_at (location, "a function concept cannot be constrained");
+          ci = NULL_TREE;
+        }
       set_constraints (decl, ci);
     }
 
@@ -8903,16 +9114,14 @@ grokfndecl (tree ctype,
             the information in the TEMPLATE_ID_EXPR.  */
          SET_DECL_IMPLICIT_INSTANTIATION (decl);
 
-         gcc_assert (identifier_p (fns)
-                     || TREE_CODE (fns) == OVERLOAD
-                     || TREE_CODE (fns) == FUNCTION_DECL);
+         gcc_assert (identifier_p (fns) || OVL_P (fns));
          DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
 
          for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
            if (TREE_PURPOSE (t)
-               && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+               && TREE_CODE (TREE_PURPOSE (t)) == DEFERRED_PARSE)
            {
-             error_at (defarg_location (TREE_PURPOSE (t)),
+             error_at (defparse_location (TREE_PURPOSE (t)),
                        "default arguments are not allowed in declaration "
                        "of friend template specialization %qD",
                        decl);
@@ -9114,7 +9323,7 @@ grokfndecl (tree ctype,
          else if (long_double_p)
            {
              if (cpp_interpret_float_suffix (parse_in, suffix, strlen (suffix)))
-               warning_at (location, 0, "floating point suffix %qs"
+               warning_at (location, 0, "floating-point suffix %qs"
                            " shadowed by implementation", suffix);
            }
          /* 17.6.3.3.5  */
@@ -9462,7 +9671,8 @@ grokvardecl (tree type,
   if (DECL_NAME (decl)
       && MAIN_NAME_P (DECL_NAME (decl))
       && scope == global_namespace)
-    error ("cannot declare %<::main%> to be a global variable");
+    error_at (DECL_SOURCE_LOCATION (decl),
+             "cannot declare %<::main%> to be a global variable");
 
   /* Check that the variable can be safely declared as a concept.
      Note that this also forbids explicit specializations.  */
@@ -9479,12 +9689,18 @@ grokvardecl (tree type,
       if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node))
        error_at (declspecs->locations[ds_type_spec],
                  "concept must have type %<bool%>");
+      if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
+        {
+          error_at (location, "a variable concept cannot be constrained");
+          TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = NULL_TREE;
+        }
     }
   else if (flag_concepts
           && processing_template_decl > template_class_depth (scope))
     {
       tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
       tree ci = build_constraints (reqs, NULL_TREE);
+
       set_constraints (decl, ci);
     }
 
@@ -9530,10 +9746,12 @@ build_ptrmemfunc_type (tree type)
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
 
   field = build_decl (input_location, FIELD_DECL, pfn_identifier, type);
+  DECL_NONADDRESSABLE_P (field) = 1;
   fields = field;
 
   field = build_decl (input_location, FIELD_DECL, delta_identifier, 
                      delta_type_node);
+  DECL_NONADDRESSABLE_P (field) = 1;
   DECL_CHAIN (field) = fields;
   fields = field;
 
@@ -10076,6 +10294,22 @@ smallest_type_quals_location (int type_quals, const location_t* locations)
   return loc;
 }
 
+/* Returns the smallest among the latter and locations[ds_type_spec].  */
+
+static location_t
+smallest_type_location (int type_quals, const location_t* locations)
+{
+  location_t loc = smallest_type_quals_location (type_quals, locations);
+  return min_location (loc, locations[ds_type_spec]);
+}
+
+static location_t
+smallest_type_location (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = get_type_quals (declspecs);
+  return smallest_type_location (type_quals, declspecs->locations);
+}
+
 /* Check that it's OK to declare a function with the indicated TYPE
    and TYPE_QUALS.  SFK indicates the kind of special function (if any)
    that this function is.  OPTYPE is the type given in a conversion
@@ -10094,7 +10328,8 @@ check_special_function_return_type (special_function_kind sfk,
     {
     case sfk_constructor:
       if (type)
-       error ("return type specification for constructor invalid");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specification for constructor invalid");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on constructor declaration");
@@ -10107,7 +10342,8 @@ check_special_function_return_type (special_function_kind sfk,
 
     case sfk_destructor:
       if (type)
-       error ("return type specification for destructor invalid");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specification for destructor invalid");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on destructor declaration");
@@ -10122,7 +10358,8 @@ check_special_function_return_type (special_function_kind sfk,
 
     case sfk_conversion:
       if (type)
-       error ("return type specified for %<operator %T%>", optype);
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specified for %<operator %T%>", optype);
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on declaration of "
@@ -10133,7 +10370,8 @@ check_special_function_return_type (special_function_kind sfk,
 
     case sfk_deduction_guide:
       if (type)
-       error ("return type specified for deduction guide");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specified for deduction guide");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on declaration of "
@@ -10149,7 +10387,7 @@ check_special_function_return_type (special_function_kind sfk,
       for (int i = 0; i < ds_last; ++i)
        if (i != ds_explicit && locations[i])
          error_at (locations[i],
-                   "decl-specifier in declaration of deduction guide");
+                   "%<decl-specifier%> in declaration of deduction guide");
       break;
 
     default:
@@ -10165,19 +10403,20 @@ check_special_function_return_type (special_function_kind sfk,
    error-recovery purposes.  */
 
 tree
-check_var_type (tree identifier, tree type)
+check_var_type (tree identifier, tree type, location_t loc)
 {
   if (VOID_TYPE_P (type))
     {
       if (!identifier)
-       error ("unnamed variable or field declared void");
+       error_at (loc, "unnamed variable or field declared void");
       else if (identifier_p (identifier))
        {
          gcc_assert (!IDENTIFIER_ANY_OP_P (identifier));
-         error ("variable or field %qE declared void", identifier);
+         error_at (loc, "variable or field %qE declared void",
+                   identifier);
        }
       else
-       error ("variable or field declared void");
+       error_at (loc, "variable or field declared void");
       type = error_mark_node;
     }
 
@@ -10218,15 +10457,12 @@ name_unnamed_type (tree type, tree decl)
 
   /* Replace the anonymous name with the real name everywhere.  */
   for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-    {
-      if (anon_aggrname_p (TYPE_IDENTIFIER (t)))
-       /* We do not rename the debug info representing the
-          unnamed tagged type because the standard says in
-          [dcl.typedef] that the naming applies only for
-          linkage purposes.  */
-       /*debug_hooks->set_name (t, decl);*/
-       TYPE_NAME (t) = decl;
-    }
+    if (IDENTIFIER_ANON_P (TYPE_IDENTIFIER (t)))
+      /* We do not rename the debug info representing the unnamed
+        tagged type because the standard says in [dcl.typedef] that
+        the naming applies only for linkage purposes.  */
+      /*debug_hooks->set_name (t, decl);*/
+      TYPE_NAME (t) = decl;
 
   if (TYPE_LANG_SPECIFIC (type))
     TYPE_WAS_UNNAMED (type) = 1;
@@ -10304,6 +10540,7 @@ grokdeclarator (const cp_declarator *declarator,
   tree type = NULL_TREE;
   int longlong = 0;
   int explicit_intN = 0;
+  int int_n_alt = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
@@ -10339,7 +10576,7 @@ grokdeclarator (const cp_declarator *declarator,
      a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals = TYPE_UNQUALIFIED;
+  int type_quals = get_type_quals (declspecs);
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -10366,9 +10603,9 @@ grokdeclarator (const cp_declarator *declarator,
   bool template_parm_flag = false;
   bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
   bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
+  bool constinit_p = decl_spec_seq_has_spec_p (declspecs, ds_constinit);
   bool late_return_type_p = false;
   bool array_parameter_p = false;
-  location_t saved_loc = input_location;
   tree reqs = NULL_TREE;
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
@@ -10377,6 +10614,7 @@ grokdeclarator (const cp_declarator *declarator,
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
   explicit_intN = declspecs->explicit_intN_p;
+  int_n_alt = declspecs->int_n_alt;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   // Was concept_p specified? Note that ds_concept
@@ -10385,13 +10623,6 @@ grokdeclarator (const cp_declarator *declarator,
   if (concept_p)
     constexpr_p = true;
 
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-    type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-    type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-    type_quals |= TYPE_QUAL_RESTRICT;
-
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -10406,13 +10637,15 @@ grokdeclarator (const cp_declarator *declarator,
   if (initialized > 1)
     funcdef_flag = true;
 
-  location_t typespec_loc = smallest_type_quals_location (type_quals,
-                                                     declspecs->locations);
-  if (typespec_loc == UNKNOWN_LOCATION)
-    typespec_loc = declspecs->locations[ds_type_spec];
+  location_t typespec_loc = smallest_type_location (type_quals,
+                                                   declspecs->locations);
   if (typespec_loc == UNKNOWN_LOCATION)
     typespec_loc = input_location;
 
+  location_t id_loc = declarator ? declarator->id_loc : input_location;
+  if (id_loc == UNKNOWN_LOCATION)
+    id_loc = input_location;
+
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -10470,7 +10703,8 @@ grokdeclarator (const cp_declarator *declarator,
                    ctype = qualifying_scope;
                    if (!MAYBE_CLASS_TYPE_P (ctype))
                      {
-                       error ("%q#T is not a class or a namespace", ctype);
+                       error_at (id_declarator->id_loc,
+                                 "%q#T is not a class or namespace", ctype);
                        ctype = NULL_TREE;
                      }
                    else if (innermost_code != cdk_function
@@ -10478,8 +10712,9 @@ grokdeclarator (const cp_declarator *declarator,
                             && !uniquely_derived_from_p (ctype,
                                                          current_class_type))
                      {
-                       error ("invalid use of qualified-name %<%T::%D%>",
-                              qualifying_scope, decl);
+                       error_at (id_declarator->id_loc,
+                                 "invalid use of qualified-name %<%T::%D%>",
+                                 qualifying_scope, decl);
                        return error_mark_node;
                      }
                  }
@@ -10492,13 +10727,15 @@ grokdeclarator (const cp_declarator *declarator,
                {
                  if (innermost_code != cdk_function)
                    {
-                     error ("declaration of %qD as non-function", decl);
+                     error_at (EXPR_LOCATION (decl),
+                               "declaration of %qE as non-function", decl);
                      return error_mark_node;
                    }
                  else if (!qualifying_scope
                           && !(current_class_type && at_class_scope_p ()))
                    {
-                     error ("declaration of %qD as non-member", decl);
+                     error_at (EXPR_LOCATION (decl),
+                               "declaration of %qE as non-member", decl);
                      return error_mark_node;
                    }
 
@@ -10577,7 +10814,7 @@ grokdeclarator (const cp_declarator *declarator,
      D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
     {
-      error ("function definition does not declare parameters");
+      error_at (id_loc, "function definition does not declare parameters");
       return error_mark_node;
     }
 
@@ -10585,7 +10822,7 @@ grokdeclarator (const cp_declarator *declarator,
       && innermost_code != cdk_function
       && ! (ctype && !declspecs->any_specifiers_p))
     {
-      error ("declaration of %qD as non-function", dname);
+      error_at (id_loc, "declaration of %qD as non-function", dname);
       return error_mark_node;
     }
 
@@ -10594,7 +10831,7 @@ grokdeclarator (const cp_declarator *declarator,
       if (UDLIT_OPER_P (dname)
          && innermost_code != cdk_function)
        {
-         error ("declaration of %qD as non-function", dname);
+         error_at (id_loc, "declaration of %qD as non-function", dname);
          return error_mark_node;
        }
 
@@ -10602,12 +10839,12 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (typedef_p)
            {
-             error ("declaration of %qD as %<typedef%>", dname);
+             error_at (id_loc, "declaration of %qD as %<typedef%>", dname);
              return error_mark_node;
            }
          else if (decl_context == PARM || decl_context == CATCHPARM)
            {
-             error ("declaration of %qD as parameter", dname);
+             error_at (id_loc, "declaration of %qD as parameter", dname);
              return error_mark_node;
            }
        }
@@ -10653,17 +10890,39 @@ grokdeclarator (const cp_declarator *declarator,
       return error_mark_node;
     }
 
+  if (constinit_p && typedef_p)
+    {
+      error_at (declspecs->locations[ds_constinit],
+               "%<constinit%> cannot appear in a typedef declaration");
+      return error_mark_node;
+    }
+
+  /* [dcl.spec]/2 "At most one of the constexpr, consteval, and constinit
+     keywords shall appear in a decl-specifier-seq."  */
+  if (constinit_p && constexpr_p)
+    {
+      gcc_rich_location richloc (declspecs->locations[ds_constinit]);
+      richloc.add_range (declspecs->locations[ds_constexpr]);
+      error_at (&richloc,
+               "can use at most one of the %<constinit%> and %<constexpr%> "
+               "specifiers");
+      return error_mark_node;
+    }
+
   /* If there were multiple types specified in the decl-specifier-seq,
      issue an error message.  */
   if (declspecs->multiple_types_p)
     {
-      error ("two or more data types in declaration of %qs", name);
+      error_at (typespec_loc,
+               "two or more data types in declaration of %qs", name);
       return error_mark_node;
     }
 
   if (declspecs->conflicting_specifiers_p)
     {
-      error ("conflicting specifiers in declaration of %qs", name);
+      error_at (min_location (declspecs->locations[ds_typedef],
+                             declspecs->locations[ds_storage_class]),
+               "conflicting specifiers in declaration of %qs", name);
       return error_mark_node;
     }
 
@@ -10677,6 +10936,7 @@ grokdeclarator (const cp_declarator *declarator,
   cp_warn_deprecated_use (type);
   if (type && TREE_CODE (type) == TYPE_DECL)
     {
+      cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type));
       typedef_decl = type;
       type = TREE_TYPE (typedef_decl);
       if (DECL_ARTIFICIAL (typedef_decl))
@@ -10747,13 +11007,14 @@ grokdeclarator (const cp_declarator *declarator,
       else if (in_system_header_at (input_location) || flag_ms_extensions)
        /* Allow it, sigh.  */;
       else if (! is_main)
-       permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name);
+       permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
+                  name);
       else if (pedantic)
-       pedwarn (input_location, OPT_Wpedantic,
+       pedwarn (id_loc, OPT_Wpedantic,
                 "ISO C++ forbids declaration of %qs with no type", name);
       else
-       warning (OPT_Wreturn_type,
-                "ISO C++ forbids declaration of %qs with no type", name);
+       warning_at (id_loc, OPT_Wreturn_type,
+                   "ISO C++ forbids declaration of %qs with no type", name);
 
       if (type_was_error_mark_node && template_parm_flag)
        /* FIXME we should be able to propagate the error_mark_node as is
@@ -10769,12 +11030,15 @@ grokdeclarator (const cp_declarator *declarator,
     {
       if (! int_n_enabled_p[declspecs->int_n_idx])
        {
-         error ("%<__int%d%> is not supported by this target",
-                int_n_data[declspecs->int_n_idx].bitsize);
+         error_at (declspecs->locations[ds_type_spec],
+                   "%<__int%d%> is not supported by this target",
+                   int_n_data[declspecs->int_n_idx].bitsize);
          explicit_intN = false;
        }
-      else if (pedantic && ! in_system_header_at (input_location))
-       pedwarn (input_location, OPT_Wpedantic,
+      /* Don't pedwarn if the alternate "__intN__" form has been used instead
+        of "__intN".  */
+      else if (!int_n_alt && pedantic && ! in_system_header_at (input_location))
+       pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
                 "ISO C++ does not support %<__int%d%> for %qs",
                 int_n_data[declspecs->int_n_idx].bitsize, name);
     }
@@ -10922,7 +11186,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (decl_spec_seq_has_spec_p (declspecs, ds_complex))
     {
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
-       error ("complex invalid for %qs", name);
+       error_at (declspecs->locations[ds_complex],
+                 "complex invalid for %qs", name);
       /* If a modifier is specified, the resulting complex is the complex
         form of TYPE.  E.g, "complex short" is "complex short int".  */
       else if (type == integer_type_node)
@@ -10964,6 +11229,7 @@ grokdeclarator (const cp_declarator *declarator,
       error_at (typespec_loc, "template placeholder type %qT must be followed "
                "by a simple declarator-id", type);
       inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here", tmpl);
+      type = error_mark_node;
     }
 
   staticp = 0;
@@ -11036,6 +11302,12 @@ grokdeclarator (const cp_declarator *declarator,
                    "a parameter cannot be declared %<constexpr%>");
           constexpr_p = 0;
         }
+      else if (constinit_p)
+       {
+         error_at (declspecs->locations[ds_constinit],
+                   "a parameter cannot be declared %<constinit%>");
+         constexpr_p = 0;
+       }
     }
 
   /* Give error if `virtual' is used outside of class declaration.  */
@@ -11053,40 +11325,47 @@ grokdeclarator (const cp_declarator *declarator,
                        ? declarator->declarator->id_loc : declarator->id_loc);
       if (inlinep)
        error_at (declspecs->locations[ds_inline],
-                 "structured binding declaration cannot be %<inline%>");
+                 "structured binding declaration cannot be %qs", "inline");
       if (typedef_p)
        error_at (declspecs->locations[ds_typedef],
-                 "structured binding declaration cannot be %<typedef%>");
+                 "structured binding declaration cannot be %qs", "typedef");
       if (constexpr_p)
        error_at (declspecs->locations[ds_constexpr], "structured "
-                 "binding declaration cannot be %<constexpr%>");
-      if (thread_p)
-       error_at (declspecs->locations[ds_thread],
-                 "structured binding declaration cannot be %qs",
-                 declspecs->gnu_thread_keyword_p
-                 ? "__thread" : "thread_local");
+                 "binding declaration cannot be %qs", "constexpr");
+      if (thread_p && cxx_dialect < cxx2a)
+       pedwarn (declspecs->locations[ds_thread], 0,
+                "structured binding declaration can be %qs only in "
+                "%<-std=c++2a%> or %<-std=gnu++2a%>",
+                declspecs->gnu_thread_keyword_p
+                ? "__thread" : "thread_local");
       if (concept_p)
        error_at (declspecs->locations[ds_concept],
-                 "structured binding declaration cannot be %<concept%>");
+                 "structured binding declaration cannot be %qs", "concept");
+      /* [dcl.struct.bind] "A cv that includes volatile is deprecated."  */
+      if (type_quals & TYPE_QUAL_VOLATILE)
+       warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile,
+                   "%<volatile%>-qualified structured binding is deprecated");
       switch (storage_class)
        {
        case sc_none:
          break;
        case sc_register:
-         error_at (loc, "structured binding declaration cannot be "
-                   "%<register%>");
+         error_at (loc, "structured binding declaration cannot be %qs",
+                   "register");
          break;
        case sc_static:
-         error_at (loc, "structured binding declaration cannot be "
-                   "%<static%>");
+         if (cxx_dialect < cxx2a)
+           pedwarn (loc, 0,
+                    "structured binding declaration can be %qs only in "
+                    "%<-std=c++2a%> or %<-std=gnu++2a%>", "static");
          break;
        case sc_extern:
-         error_at (loc, "structured binding declaration cannot be "
-                   "%<extern%>");
+         error_at (loc, "structured binding declaration cannot be %qs",
+                   "extern");
          break;
        case sc_mutable:
-         error_at (loc, "structured binding declaration cannot be "
-                   "%<mutable%>");
+         error_at (loc, "structured binding declaration cannot be %qs",
+                   "mutable");
          break;
        case sc_auto:
          error_at (loc, "structured binding declaration cannot be "
@@ -11112,12 +11391,12 @@ grokdeclarator (const cp_declarator *declarator,
       inlinep = 0;
       typedef_p = 0;
       constexpr_p = 0;
-      thread_p = 0;
       concept_p = 0;
-      storage_class = sc_none;
-      staticp = 0;
-      declspecs->storage_class = sc_none;
-      declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
+      if (storage_class != sc_static)
+       {
+         storage_class = sc_none;
+         declspecs->storage_class = sc_none;
+       }
     }
 
   /* Static anonymous unions are dealt with here.  */
@@ -11134,7 +11413,10 @@ grokdeclarator (const cp_declarator *declarator,
           && storage_class != sc_static)
          || typedef_p))
     {
-      error ("multiple storage classes in declaration of %qs", name);
+      location_t loc
+       = min_location (declspecs->locations[ds_thread],
+                       declspecs->locations[ds_storage_class]);
+      error_at (loc, "multiple storage classes in declaration of %qs", name);
       thread_p = false;
     }
   if (decl_context != NORMAL
@@ -11178,7 +11460,8 @@ grokdeclarator (const cp_declarator *declarator,
   else if (toplevel_bindings_p ())
     {
       if (storage_class == sc_auto)
-       error ("top-level declaration of %qs specifies %<auto%>", name);
+       error_at (declspecs->locations[ds_storage_class],
+                 "top-level declaration of %qs specifies %<auto%>", name);
     }
   else if (thread_p
           && storage_class != sc_extern
@@ -11292,7 +11575,9 @@ grokdeclarator (const cp_declarator *declarator,
          type = create_array_type_for_decl (dname, type,
                                             declarator->u.array.bounds,
                                             declarator->id_loc);
-         if (!valid_array_size_p (input_location, type, dname))
+         if (!valid_array_size_p (dname
+                                  ? declarator->id_loc : input_location,
+                                  type, dname))
            type = error_mark_node;
 
          if (declarator->std_attributes)
@@ -11311,9 +11596,10 @@ grokdeclarator (const cp_declarator *declarator,
 
            /* Declaring a function type.  */
 
-           input_location = declspecs->locations[ds_type_spec];
-           abstract_virtuals_error (ACU_RETURN, type);
-           input_location = saved_loc;
+           {
+             iloc_sentinel ils (declspecs->locations[ds_type_spec]);
+             abstract_virtuals_error (ACU_RETURN, type);
+           }
 
            /* Pick up type qualifiers which should be applied to `this'.  */
            memfn_quals = declarator->u.function.qualifiers;
@@ -11425,6 +11711,8 @@ grokdeclarator (const cp_declarator *declarator,
                else if (late_return_type
                         && sfk != sfk_conversion)
                  {
+                   if (late_return_type == error_mark_node)
+                     return error_mark_node;
                    if (cxx_dialect < cxx11)
                      /* Not using maybe_warn_cpp0x because this should
                         always be an error.  */
@@ -11453,6 +11741,13 @@ grokdeclarator (const cp_declarator *declarator,
                if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
                  warning_at (typespec_loc, OPT_Wignored_qualifiers, "type "
                              "qualifiers ignored on function return type");
+               /* [dcl.fct] "A volatile-qualified return type is
+                  deprecated."  */
+               if (type_quals & TYPE_QUAL_VOLATILE)
+                 warning_at (typespec_loc, OPT_Wvolatile,
+                             "%<volatile%>-qualified return type is "
+                             "deprecated");
+
                /* We now know that the TYPE_QUALS don't apply to the
                   decl, but to its return type.  */
                type_quals = TYPE_UNQUALIFIED;
@@ -11472,6 +11767,23 @@ grokdeclarator (const cp_declarator *declarator,
                          "an array", name);
                return error_mark_node;
              }
+           if (constinit_p)
+             {
+               error_at (declspecs->locations[ds_constinit],
+                         "%<constinit%> on function return type is not "
+                         "allowed");
+               return error_mark_node;
+             }
+           /* Only plain decltype(auto) is allowed.  */
+           if (tree a = type_uses_auto (type))
+             {
+               if (AUTO_IS_DECLTYPE (a) && a != type)
+                 {
+                   error_at (typespec_loc, "%qT as type rather than "
+                             "plain %<decltype(auto)%>", type);
+                   return error_mark_node;
+                 }
+             }
 
            if (ctype == NULL_TREE
                && decl_context == FIELD
@@ -11496,9 +11808,12 @@ grokdeclarator (const cp_declarator *declarator,
                   virtual.  A constructor may not be static.
                   A constructor may not be declared with ref-qualifier. */
                if (staticp == 2)
-                 error ((flags == DTOR_FLAG)
-                        ? G_("destructor cannot be static member function")
-                        : G_("constructor cannot be static member function"));
+                 error_at (declspecs->locations[ds_storage_class],
+                           (flags == DTOR_FLAG)
+                           ? G_("destructor cannot be static member "
+                                "function")
+                           : G_("constructor cannot be static member "
+                                "function"));
                if (memfn_quals)
                  {
                    error ((flags == DTOR_FLAG)
@@ -11551,13 +11866,29 @@ grokdeclarator (const cp_declarator *declarator,
                    friendp = 0;
                  }
                if (decl_context == NORMAL)
-                 error ("friend declaration not in class definition");
+                 error_at (declarator->id_loc,
+                           "friend declaration not in class definition");
                if (current_function_decl && funcdef_flag)
                  {
-                   error ("can%'t define friend function %qs in a local "
-                          "class definition", name);
+                   error_at (declarator->id_loc,
+                             "cannot define friend function %qs in a local "
+                             "class definition", name);
                    friendp = 0;
                  }
+               /* [class.friend]/6: A function can be defined in a friend
+                  declaration if the function name is unqualified.  */
+               if (funcdef_flag && in_namespace)
+                 {
+                   if (in_namespace == global_namespace)
+                     error_at (declarator->id_loc,
+                               "friend function definition %qs cannot have "
+                               "a name qualified with %<::%>", name);
+                   else
+                     error_at (declarator->id_loc,
+                               "friend function definition %qs cannot have "
+                               "a name qualified with %<%D::%>", name,
+                               in_namespace);
+                 }
              }
            else if (ctype && sfk == sfk_conversion)
              {
@@ -11593,7 +11924,8 @@ grokdeclarator (const cp_declarator *declarator,
                && inner_declarator->u.id.sfk == sfk_destructor
                && arg_types != void_list_node)
              {
-               error ("destructors may not have parameters");
+               error_at (declarator->id_loc,
+                         "destructors may not have parameters");
                arg_types = void_list_node;
                parms = NULL_TREE;
              }
@@ -11809,6 +12141,8 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
+  id_loc = declarator ? declarator->id_loc : input_location;
+
   /* A `constexpr' specifier used in an object declaration declares
      the object as `const'.  */
   if (constexpr_p && innermost_code != cdk_function)
@@ -11824,8 +12158,7 @@ grokdeclarator (const cp_declarator *declarator,
     }
 
   if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
-      && TREE_CODE (type) != FUNCTION_TYPE
-      && TREE_CODE (type) != METHOD_TYPE
+      && !FUNC_OR_METHOD_TYPE_P (type)
       && !variable_template_p (TREE_OPERAND (unqualified_id, 0)))
     {
       error ("template-id %qD used as a declarator",
@@ -11853,13 +12186,13 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (friendp)
            {
-             permerror (input_location, "member functions are implicitly "
-                                        "friends of their class");
+             permerror (declspecs->locations[ds_friend],
+                        "member functions are implicitly "
+                        "friends of their class");
              friendp = 0;
            }
          else
-           permerror (declarator->id_loc, 
-                      "extra qualification %<%T::%> on member %qs",
+           permerror (id_loc, "extra qualification %<%T::%> on member %qs",
                       ctype, name);
        }
       else if (/* If the qualifying type is already complete, then we
@@ -11888,19 +12221,19 @@ grokdeclarator (const cp_declarator *declarator,
          if (current_class_type
              && (!friendp || funcdef_flag || initialized))
            {
-             error (funcdef_flag || initialized
-                    ? G_("cannot define member function %<%T::%s%> "
-                         "within %qT")
-                    : G_("cannot declare member function %<%T::%s%> "
-                         "within %qT"),
-                    ctype, name, current_class_type);
+             error_at (id_loc, funcdef_flag || initialized
+                       ? G_("cannot define member function %<%T::%s%> "
+                            "within %qT")
+                       : G_("cannot declare member function %<%T::%s%> "
+                            "within %qT"),
+                       ctype, name, current_class_type);
              return error_mark_node;
            }
        }
       else if (typedef_p && current_class_type)
        {
-         error ("cannot declare member %<%T::%s%> within %qT",
-                ctype, name, current_class_type);
+         error_at (id_loc, "cannot declare member %<%T::%s%> within %qT",
+                   ctype, name, current_class_type);
          return error_mark_node;
        }
     }
@@ -11947,9 +12280,11 @@ grokdeclarator (const cp_declarator *declarator,
       && variably_modified_type_p (type, NULL_TREE))
     {
       if (decl_context == FIELD)
-       error ("data member may not have variably modified type %qT", type);
+       error_at (id_loc,
+                 "data member may not have variably modified type %qT", type);
       else
-       error ("parameter may not have variably modified type %qT", type);
+       error_at (id_loc,
+                 "parameter may not have variably modified type %qT", type);
       type = error_mark_node;
     }
 
@@ -11987,8 +12322,7 @@ grokdeclarator (const cp_declarator *declarator,
                    name);
          storage_class = sc_none;
        }
-      else if (TREE_CODE (type) == FUNCTION_TYPE
-              || TREE_CODE (type) == METHOD_TYPE)
+      else if (FUNC_OR_METHOD_TYPE_P (type))
        {
          error_at (sloc, "function %qs cannot be declared %<mutable%>",
                    name);
@@ -12014,14 +12348,23 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
-  location_t loc = declarator ? declarator->id_loc : input_location;
-
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
   if (typedef_p && decl_context != TYPENAME)
     {
       bool alias_p = decl_spec_seq_has_spec_p (declspecs, ds_alias);
       tree decl;
 
+      if (funcdef_flag)
+       {
+         if (decl_context == NORMAL)
+           error_at (id_loc,
+                     "typedef may not be a function definition");
+         else
+           error_at (id_loc,
+                     "typedef may not be a member function definition");
+         return error_mark_node;
+       }
+
       /* This declaration:
 
           typedef void f(int) const;
@@ -12056,14 +12399,14 @@ grokdeclarator (const cp_declarator *declarator,
 
       if (id_declarator && declarator->u.id.qualifying_scope)
        {
-         error ("typedef name may not be a nested-name-specifier");
+         error_at (id_loc, "typedef name may not be a nested-name-specifier");
          type = error_mark_node;
        }
 
       if (decl_context == FIELD)
-       decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type);
+       decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
       else
-       decl = build_decl (loc, TYPE_DECL, unqualified_id, type);
+       decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
 
       if (decl_context != FIELD)
        {
@@ -12080,7 +12423,7 @@ grokdeclarator (const cp_declarator *declarator,
        }
       else if (current_class_type
               && constructor_name_p (unqualified_id, current_class_type))
-       permerror (input_location, "ISO C++ forbids nested type %qD with same name "
+       permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
                   "as enclosing class",
                   unqualified_id);
 
@@ -12238,7 +12581,7 @@ grokdeclarator (const cp_declarator *declarator,
       /* Only functions may be declared using an operator-function-id.  */
       if (dname && IDENTIFIER_ANY_OP_P (dname))
        {
-         error ("declaration of %qD as non-function", dname);
+         error_at (id_loc, "declaration of %qD as non-function", dname);
          return error_mark_node;
        }
 
@@ -12252,7 +12595,7 @@ grokdeclarator (const cp_declarator *declarator,
      error message later.  */
   if (decl_context != PARM)
     {
-      type = check_var_type (unqualified_id, type);
+      type = check_var_type (unqualified_id, type, id_loc);
       if (type == error_mark_node)
         return error_mark_node;
     }
@@ -12265,13 +12608,20 @@ grokdeclarator (const cp_declarator *declarator,
       if (ctype || in_namespace)
        error ("cannot use %<::%> in parameter declaration");
 
-      if (type_uses_auto (type)
-         && !(cxx_dialect >= cxx17 && template_parm_flag))
+      tree auto_node = type_uses_auto (type);
+      if (auto_node && !(cxx_dialect >= cxx17 && template_parm_flag))
        {
          if (cxx_dialect >= cxx14)
-           error ("%<auto%> parameter not permitted in this context");
+           {
+             if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node))
+               error_at (typespec_loc,
+                         "cannot declare a parameter with %<decltype(auto)%>");
+             else
+               error_at (typespec_loc,
+                         "%<auto%> parameter not permitted in this context");
+           }
          else
-           error ("parameter declared %<auto%>");
+           error_at (typespec_loc, "parameter declared %<auto%>");
          type = error_mark_node;
        }
 
@@ -12339,7 +12689,7 @@ grokdeclarator (const cp_declarator *declarator,
                && (TREE_CODE (ctype) == UNION_TYPE
                    || TREE_CODE (ctype) == QUAL_UNION_TYPE))
              {
-               error ("flexible array member in union");
+               error_at (id_loc, "flexible array member in union");
                type = error_mark_node;
              }
            else
@@ -12348,8 +12698,8 @@ grokdeclarator (const cp_declarator *declarator,
                if (in_system_header_at (input_location))
                  /* Do not warn on flexible array members in system
                     headers because glibc uses them.  */;
-               else if (name && declarator)
-                 pedwarn (declarator->id_loc, OPT_Wpedantic,
+               else if (name)
+                 pedwarn (id_loc, OPT_Wpedantic,
                           "ISO C++ forbids flexible array member %qs", name);
                else
                  pedwarn (input_location, OPT_Wpedantic,
@@ -12369,7 +12719,7 @@ grokdeclarator (const cp_declarator *declarator,
        else if (in_namespace && !friendp)
          {
            /* Something like struct S { int N::j; };  */
-           error ("invalid use of %<::%>");
+           error_at (id_loc, "invalid use of %<::%>");
            return error_mark_node;
          }
        else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)
@@ -12424,15 +12774,15 @@ grokdeclarator (const cp_declarator *declarator,
                if (!ctype)
                  {
                    gcc_assert (friendp);
-                   error ("expected qualified name in friend declaration "
-                          "for destructor %qD", uqname);
+                   error_at (id_loc, "expected qualified name in friend "
+                             "declaration for destructor %qD", uqname);
                    return error_mark_node;
                  }
 
                if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
                  {
-                   error ("declaration of %qD as member of %qT",
-                          uqname, ctype);
+                   error_at (id_loc, "declaration of %qD as member of %qT",
+                             uqname, ctype);
                    return error_mark_node;
                  }
                 if (concept_p)
@@ -12441,12 +12791,13 @@ grokdeclarator (const cp_declarator *declarator,
                              "a destructor cannot be %<concept%>");
                     return error_mark_node;
                   }
-                if (constexpr_p)
-                  {
-                    error_at (declspecs->locations[ds_constexpr],
-                             "a destructor cannot be %<constexpr%>");
-                    return error_mark_node;
-                  }
+               if (constexpr_p && cxx_dialect < cxx2a)
+                 {
+                   error_at (declspecs->locations[ds_constexpr],
+                             "%<constexpr%> destructors only available"
+                             " with %<-std=c++2a%> or %<-std=gnu++2a%>");
+                   return error_mark_node;
+                 }
              }
            else if (sfk == sfk_constructor && friendp && !ctype)
              {
@@ -12474,8 +12825,8 @@ grokdeclarator (const cp_declarator *declarator,
                tree tmpl = TREE_OPERAND (unqualified_id, 0);
                if (variable_template_p (tmpl))
                  {
-                   error ("specialization of variable template %qD "
-                          "declared as function", tmpl);
+                   error_at (id_loc, "specialization of variable template "
+                             "%qD declared as function", tmpl);
                    inform (DECL_SOURCE_LOCATION (tmpl),
                            "variable template declared here");
                    return error_mark_node;
@@ -12483,10 +12834,11 @@ grokdeclarator (const cp_declarator *declarator,
              }
 
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
-           function_context = (ctype != NULL_TREE) ?
-             decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
-           publicp = (! friendp || ! staticp)
-             && function_context == NULL_TREE;
+           function_context
+             = (ctype != NULL_TREE
+                ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE);
+           publicp = ((! friendp || ! staticp)
+                      && function_context == NULL_TREE);
 
            decl = grokfndecl (ctype, type,
                               TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
@@ -12501,7 +12853,7 @@ grokdeclarator (const cp_declarator *declarator,
                               initialized == SD_DELETED, sfk,
                               funcdef_flag, late_return_type_p,
                               template_count, in_namespace,
-                              attrlist, declarator->id_loc);
+                              attrlist, id_loc);
             decl = set_virt_specifiers (decl, virt_specifiers);
            if (decl == NULL_TREE)
              return error_mark_node;
@@ -12534,8 +12886,7 @@ grokdeclarator (const cp_declarator *declarator,
              {
                if (unqualified_id)
                  {
-                   error_at (declarator->id_loc,
-                             "field %qD has incomplete type %qT",
+                   error_at (id_loc, "field %qD has incomplete type %qT",
                              unqualified_id, type);
                    cxx_incomplete_type_inform (strip_array_types (type));
                  }
@@ -12550,8 +12901,8 @@ grokdeclarator (const cp_declarator *declarator,
          {
            if (friendp)
              {
-               if (unqualified_id && declarator)
-                 error_at (declarator->id_loc,
+               if (unqualified_id)
+                 error_at (id_loc,
                            "%qE is neither function nor member function; "
                            "cannot be declared friend", unqualified_id);
                else
@@ -12595,7 +12946,7 @@ grokdeclarator (const cp_declarator *declarator,
              {
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
-               decl = build_lang_decl_loc (loc, VAR_DECL,
+               decl = build_lang_decl_loc (id_loc, VAR_DECL,
                                            unqualified_id, type);
                set_linkage_for_static_data_member (decl);
                if (concept_p)
@@ -12639,11 +12990,18 @@ grokdeclarator (const cp_declarator *declarator,
                 else if (constexpr_p)
                  {
                    error_at (declspecs->locations[ds_constexpr],
-                             "non-static data member %qE declared %<constexpr%>",
-                             unqualified_id);
+                             "non-static data member %qE declared "
+                             "%<constexpr%>", unqualified_id);
                    constexpr_p = false;
                  }
-               decl = build_decl (loc, FIELD_DECL, unqualified_id, type);
+               else if (constinit_p)
+                 {
+                   error_at (declspecs->locations[ds_constinit],
+                             "non-static data member %qE declared "
+                             "%<constinit%>", unqualified_id);
+                   constinit_p = false;
+                 }
+               decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
                if (bitfield && !unqualified_id)
                  {
@@ -12678,8 +13036,7 @@ grokdeclarator (const cp_declarator *declarator,
                            declspecs->locations);
          }
       }
-    else if (TREE_CODE (type) == FUNCTION_TYPE
-            || TREE_CODE (type) == METHOD_TYPE)
+    else if (FUNC_OR_METHOD_TYPE_P (type))
       {
        tree original_name;
        int publicp = 0;
@@ -12694,9 +13051,12 @@ grokdeclarator (const cp_declarator *declarator,
        // FIXME:gcc_assert (original_name == dname);
 
        if (storage_class == sc_auto)
-         error ("storage class %<auto%> invalid for function %qs", name);
+         error_at (declspecs->locations[ds_storage_class],
+                   "storage class %<auto%> invalid for function %qs", name);
        else if (storage_class == sc_register)
-         error ("storage class %<register%> invalid for function %qs", name);
+         error_at (declspecs->locations[ds_storage_class],
+                   "storage class %<register%> invalid for function %qs",
+                   name);
        else if (thread_p)
          {
            if (declspecs->gnu_thread_keyword_p)
@@ -12762,7 +13122,7 @@ grokdeclarator (const cp_declarator *declarator,
                            funcdef_flag,
                           late_return_type_p,
                           template_count, in_namespace, attrlist,
-                          declarator->id_loc);
+                          id_loc);
        if (decl == NULL_TREE)
          return error_mark_node;
 
@@ -12809,7 +13169,7 @@ grokdeclarator (const cp_declarator *declarator,
                            concept_p,
                            template_count,
                            ctype ? ctype : in_namespace,
-                           loc);
+                           id_loc);
        if (decl == NULL_TREE)
          return error_mark_node;
 
@@ -12855,7 +13215,7 @@ grokdeclarator (const cp_declarator *declarator,
        if (innermost_code == cdk_decomp)
          {
            gcc_assert (declarator && declarator->kind == cdk_decomp);
-           DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+           DECL_SOURCE_LOCATION (decl) = id_loc;
            DECL_ARTIFICIAL (decl) = 1;
            fit_decomposition_lang_decl (decl, NULL_TREE);
          }
@@ -12996,8 +13356,8 @@ check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
   tree var;
   tree decl_type;
 
-  if (TREE_CODE (arg) == DEFAULT_ARG)
-    /* We get a DEFAULT_ARG when looking at an in-class declaration
+  if (TREE_CODE (arg) == DEFERRED_PARSE)
+    /* We get a DEFERRED_PARSE when looking at an in-class declaration
        with a default argument.  Ignore the argument for now; we'll
        deal with it after the class is complete.  */
     return arg;
@@ -13032,7 +13392,9 @@ check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
   /* Avoid redundant -Wzero-as-null-pointer-constant warnings at
      the call sites.  */
   if (TYPE_PTR_OR_PTRMEM_P (decl_type)
-      && null_ptr_cst_p (arg))
+      && null_ptr_cst_p (arg)
+      /* Don't lose side-effects as in PR90473.  */
+      && !TREE_SIDE_EFFECTS (arg))
     return nullptr_node;
 
   /* [dcl.fct.default]
@@ -13073,7 +13435,10 @@ type_is_deprecated (tree type)
       if (TREE_DEPRECATED (TYPE_NAME (type)))
        return type;
       else
-       return NULL_TREE;
+       {
+         cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type)));
+         return NULL_TREE;
+       }
     }
 
   /* Do warn about using typedefs to a deprecated class.  */
@@ -13157,6 +13522,13 @@ grokparms (tree parmlist, tree *parms)
                cp_warn_deprecated_use (deptype);
            }
 
+         /* [dcl.fct] "A parameter with volatile-qualified type is
+            deprecated."  */
+         if (CP_TYPE_VOLATILE_P (type))
+           warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wvolatile,
+                       "%<volatile%>-qualified parameter is "
+                       "deprecated");
+
          /* Top-level qualifiers on the parameters are
             ignored for function types.  */
          type = cp_build_qualified_type (type, 0);
@@ -13377,15 +13749,11 @@ grok_special_member_properties (tree decl)
             are no other parameters or else all other parameters have
             default arguments.  */
          TYPE_HAS_COPY_CTOR (class_type) = 1;
-         if (user_provided_p (decl))
-           TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1;
          if (ctor > 1)
            TYPE_HAS_CONST_COPY_CTOR (class_type) = 1;
        }
       else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
        TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
-      else if (move_fn_p (decl) && user_provided_p (decl))
-       TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1;
       else if (is_list_ctor (decl))
        TYPE_HAS_LIST_CTOR (class_type) = 1;
 
@@ -13406,13 +13774,9 @@ grok_special_member_properties (tree decl)
       if (assop)
        {
          TYPE_HAS_COPY_ASSIGN (class_type) = 1;
-         if (user_provided_p (decl))
-           TYPE_HAS_COMPLEX_COPY_ASSIGN (class_type) = 1;
          if (assop != 1)
            TYPE_HAS_CONST_COPY_ASSIGN (class_type) = 1;
        }
-      else if (move_fn_p (decl) && user_provided_p (decl))
-       TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1;
     }
   else if (IDENTIFIER_CONV_OP_P (DECL_NAME (decl)))
     TYPE_HAS_CONVERSION (class_type) = true;
@@ -13445,7 +13809,8 @@ grok_ctor_properties (const_tree ctype, const_tree decl)
         or implicitly defined), there's no need to worry about their
         existence.  Theoretically, they should never even be
         instantiated, but that's hard to forestall.  */
-      error ("invalid constructor; you probably meant %<%T (const %T&)%>",
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "invalid constructor; you probably meant %<%T (const %T&)%>",
                ctype, ctype);
       return false;
     }
@@ -13537,10 +13902,13 @@ grok_op_properties (tree decl, bool complain)
        }
 
       if (op_flags & OVL_OP_FLAG_DELETE)
-       coerce_delete_type (decl, loc);
+       {
+         DECL_SET_IS_OPERATOR_DELETE (decl, true);
+         coerce_delete_type (decl, loc);
+       }
       else
        {
-         DECL_IS_OPERATOR_NEW (decl) = 1;
+         DECL_SET_IS_OPERATOR_NEW (decl, true);
          TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl), loc);
        }
 
@@ -13600,7 +13968,7 @@ grok_op_properties (tree decl, bool complain)
   if (operator_code == COND_EXPR)
     {
       /* 13.4.0.3 */
-      error_at (loc, "ISO C++ prohibits overloading operator ?:");
+      error_at (loc, "ISO C++ prohibits overloading %<operator ?:%>");
       return false;
     }
 
@@ -14048,7 +14416,7 @@ xref_tag_1 (enum tag_types tag_code, tree name,
   /* In case of anonymous name, xref_tag is only called to
      make type node and push name.  Name lookup is not required.  */
   tree t = NULL_TREE;
-  if (scope != ts_lambda && !anon_aggrname_p (name))
+  if (scope != ts_lambda && !IDENTIFIER_ANON_P (name))
     t = lookup_and_check_tag  (tag_code, name, scope, template_header_p);
   
   if (t == error_mark_node)
@@ -14710,7 +15078,7 @@ finish_enum_value_list (tree enumtype)
       if (TYPE_PRECISION (enumtype))
        {
          if (precision > TYPE_PRECISION (enumtype))
-           error ("specified mode too small for enumeral values");
+           error ("specified mode too small for enumerated values");
          else
            {
              use_short_enum = true;
@@ -14785,11 +15153,8 @@ finish_enum_value_list (tree enumtype)
      type of the enumeration.  */
   for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
     {
-      location_t saved_location;
-
       decl = TREE_VALUE (values);
-      saved_location = input_location;
-      input_location = DECL_SOURCE_LOCATION (decl);
+      iloc_sentinel ils (DECL_SOURCE_LOCATION (decl));
       if (fixed_underlying_type_p)
         /* If the enumeration type has a fixed underlying type, we
            already checked all of the enumerator values.  */
@@ -14798,8 +15163,6 @@ finish_enum_value_list (tree enumtype)
         value = perform_implicit_conversion (underlying_type,
                                              DECL_INITIAL (decl),
                                              tf_warning_or_error);
-      input_location = saved_location;
-
       /* Do not clobber shared ints.  */
       if (value != error_mark_node)
        {
@@ -14906,8 +15269,9 @@ build_enumerator (tree name, tree value, tree enumtype, tree attributes,
              if (! INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P
                  (TREE_TYPE (value)))
                {
-                 error ("enumerator value for %qD must have integral or "
-                        "unscoped enumeration type", name);
+                 error_at (cp_expr_loc_or_input_loc (value),
+                           "enumerator value for %qD must have integral or "
+                           "unscoped enumeration type", name);
                  value = NULL_TREE;
                }
              else
@@ -15239,7 +15603,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
     warning_at (DECL_SOURCE_LOCATION (decl1), 0,
-               "inline function %qD given attribute noinline", decl1);
+               "inline function %qD given attribute %qs", decl1, "noinline");
 
   /* Handle gnu_inline attribute.  */
   if (GNU_INLINE_P (decl1))
@@ -15432,20 +15796,21 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
   current_binding_level = bl;
 
+  /* If we are (erroneously) defining a function that we have already
+     defined before, wipe out what we knew before.  */
+  gcc_checking_assert (!DECL_PENDING_INLINE_P (decl1));
+  FNDECL_USED_AUTO (decl1) = false;
+  DECL_SAVED_AUTO_RETURN_TYPE (decl1) = NULL;
+
   if (!processing_template_decl && type_uses_auto (restype))
     {
       FNDECL_USED_AUTO (decl1) = true;
-      current_function_auto_return_pattern = restype;
+      DECL_SAVED_AUTO_RETURN_TYPE (decl1) = restype;
     }
 
   /* Start the statement-tree, start the tree now.  */
   DECL_SAVED_TREE (decl1) = push_stmt_list ();
 
-  /* If we are (erroneously) defining a function that we have already
-     defined before, wipe out what we knew before.  */
-  if (!DECL_PENDING_INLINE_P (decl1))
-    DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
-
   if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
     {
       /* We know that this was set up by `grokclassfn'.  We do not
@@ -15626,13 +15991,6 @@ start_function (cp_decl_specifier_seq *declspecs,
   invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
   if (decl1 == error_mark_node)
     return false;
-  /* If the declarator is not suitable for a function definition,
-     cause a syntax error.  */
-  if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
-    {
-      error ("invalid function declaration");
-      return false;
-    }
 
   if (DECL_MAIN_P (decl1))
     /* main must return int.  grokfndecl should have corrected it
@@ -15667,6 +16025,39 @@ use_eh_spec_block (tree fn)
          && !DECL_DEFAULTED_FN (fn));
 }
 
+/* Helper function to push ARGS into the current lexical scope.  DECL
+   is the function declaration.  NONPARMS is used to handle enum
+   constants.  */
+
+void
+do_push_parm_decls (tree decl, tree args, tree *nonparms)
+{
+  /* If we're doing semantic analysis, then we'll call pushdecl
+     for each of these.  We must do them in reverse order so that
+     they end in the correct forward order.  */
+  args = nreverse (args);
+
+  tree next;
+  for (tree parm = args; parm; parm = next)
+    {
+      next = DECL_CHAIN (parm);
+      if (TREE_CODE (parm) == PARM_DECL)
+       pushdecl (parm);
+      else if (nonparms)
+       {
+         /* If we find an enum constant or a type tag, put it aside for
+            the moment.  */
+         TREE_CHAIN (parm) = NULL_TREE;
+         *nonparms = chainon (*nonparms, parm);
+       }
+    }
+
+  /* Get the decls in their original chain order and record in the
+     function.  This is all and only the PARM_DECLs that were
+     pushed into scope by the loop above.  */
+  DECL_ARGUMENTS (decl) = get_local_decls ();
+}
+
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
    digesting the body of the function.
@@ -15677,7 +16068,6 @@ static void
 store_parm_decls (tree current_function_parms)
 {
   tree fndecl = current_function_decl;
-  tree parm;
 
   /* This is a chain of any other decls that came in among the parm
      declarations.  If a parm is declared with  enum {foo, bar} x;
@@ -15692,35 +16082,12 @@ store_parm_decls (tree current_function_parms)
         and complain if any redundant old-style parm decls were written.  */
 
       tree specparms = current_function_parms;
-      tree next;
 
       /* Must clear this because it might contain TYPE_DECLs declared
             at class level.  */
       current_binding_level->names = NULL;
 
-      /* If we're doing semantic analysis, then we'll call pushdecl
-            for each of these.  We must do them in reverse order so that
-            they end in the correct forward order.  */
-      specparms = nreverse (specparms);
-
-      for (parm = specparms; parm; parm = next)
-       {
-         next = DECL_CHAIN (parm);
-         if (TREE_CODE (parm) == PARM_DECL)
-           pushdecl (parm);
-         else
-           {
-             /* If we find an enum constant or a type tag,
-                put it aside for the moment.  */
-             TREE_CHAIN (parm) = NULL_TREE;
-             nonparms = chainon (nonparms, parm);
-           }
-       }
-
-      /* Get the decls in their original chain order and record in the
-        function.  This is all and only the PARM_DECLs that were
-        pushed into scope by the loop above.  */
-      DECL_ARGUMENTS (fndecl) = get_local_decls ();
+      do_push_parm_decls (fndecl, specparms, &nonparms);
     }
   else
     DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -15736,31 +16103,6 @@ store_parm_decls (tree current_function_parms)
 }
 
 \f
-/* We have finished doing semantic analysis on DECL, but have not yet
-   generated RTL for its body.  Save away our current state, so that
-   when we want to generate RTL later we know what to do.  */
-
-static void
-save_function_data (tree decl)
-{
-  struct language_function *f;
-
-  /* Save the language-specific per-function data so that we can
-     get it back when we really expand this function.  */
-  gcc_assert (!DECL_PENDING_INLINE_P (decl));
-
-  /* Make a copy.  */
-  f = ggc_alloc<language_function> ();
-  memcpy (f, cp_function_chain, sizeof (struct language_function));
-  DECL_SAVED_FUNCTION_DATA (decl) = f;
-
-  /* Clear out the bits we don't need.  */
-  f->base.x_stmt_tree.x_cur_stmt_list = NULL;
-  f->bindings = NULL;
-  f->base.local_typedefs = NULL;
-}
-
-
 /* Set the return value of the constructor (if present).  */
 
 static void
@@ -16089,10 +16431,19 @@ finish_function (bool inline_p)
      the return type is void.  But if the declared type is something like
      auto*, this is an error.  */
   if (!processing_template_decl && FNDECL_USED_AUTO (fndecl)
-      && TREE_TYPE (fntype) == current_function_auto_return_pattern)
+      && TREE_TYPE (fntype) == DECL_SAVED_AUTO_RETURN_TYPE (fndecl))
     {
-      if (is_auto (current_function_auto_return_pattern))
+      if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl))
+          && !current_function_returns_value
+          && !current_function_returns_null)
        {
+         /* We haven't applied return type deduction because we haven't
+             seen any return statements. Do that now.  */
+         tree node = type_uses_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
+         do_auto_deduction (DECL_SAVED_AUTO_RETURN_TYPE (fndecl),
+                            void_node, node, tf_warning_or_error,
+                             adc_return_type);
+
          apply_deduced_return_type (fndecl, void_type_node);
          fntype = TREE_TYPE (fndecl);
        }
@@ -16100,7 +16451,7 @@ finish_function (bool inline_p)
               && !current_function_returns_null)
        {
          error ("no return statements in function returning %qT",
-                current_function_auto_return_pattern);
+                DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
          inform (input_location, "only plain %<auto%> return type can be "
                  "deduced to %<void%>");
        }
@@ -16163,10 +16514,6 @@ finish_function (bool inline_p)
      to the FUNCTION_DECL node itself.  */
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
-  /* Save away current state, if appropriate.  */
-  if (!processing_template_decl)
-    save_function_data (fndecl);
-
   /* Complain if there's just no return statement.  */
   if (warn_return_type
       && !VOID_TYPE_P (TREE_TYPE (fntype))
@@ -16196,6 +16543,7 @@ finish_function (bool inline_p)
              && same_type_ignoring_top_level_qualifiers_p
                  (TREE_TYPE (valtype), TREE_TYPE (current_class_ref))
              && global_dc->option_enabled (OPT_Wreturn_type,
+                                           global_dc->lang_mask,
                                            global_dc->option_state))
            add_return_star_this_fixit (&richloc, fndecl);
        }
@@ -16248,20 +16596,7 @@ finish_function (bool inline_p)
 
   /* Genericize before inlining.  */
   if (!processing_template_decl)
-    {
-      struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
-      cp_genericize (fndecl);
-      /* Clear out the bits we don't need.  */
-      f->x_current_class_ptr = NULL;
-      f->x_current_class_ref = NULL;
-      f->x_eh_spec_block = NULL;
-      f->x_in_charge_parm = NULL;
-      f->x_vtt_parm = NULL;
-      f->x_return_value = NULL;
-      f->bindings = NULL;
-      f->extern_decl_map = NULL;
-      f->infinite_loops = NULL;
-    }
+    cp_genericize (fndecl);
 
   /* We're leaving the context of this function, so zap cfun.  It's still in
      DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation.  */
@@ -16319,12 +16654,6 @@ grokmethod (cp_decl_specifier_seq *declspecs,
   if (fndecl == error_mark_node)
     return error_mark_node;
 
-  if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
-    {
-      error ("invalid member function declaration");
-      return error_mark_node;
-    }
-
   if (attrlist)
     cplus_decl_attributes (&fndecl, attrlist, 0);
 
@@ -16519,6 +16848,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
        cleanup = error_mark_node;
       else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
        /* Discard the call.  */;
+      else if (decl_maybe_constant_destruction (decl, type)
+              && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+       cxx_constant_dtor (call, decl);
       else if (cleanup)
        cleanup = cp_build_compound_expr (cleanup, call, complain);
       else
@@ -16532,6 +16864,8 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
      the end of the block.  So let's unset the location of the
      destructor call instead.  */
   protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
+  if (cleanup && CONVERT_EXPR_P (cleanup))
+    protected_set_expr_location (TREE_OPERAND (cleanup, 0), UNKNOWN_LOCATION);
 
   if (cleanup
       && DECL_P (decl)
@@ -16600,20 +16934,20 @@ cp_tree_node_structure (union lang_tree_node * t)
 {
   switch (TREE_CODE (&t->generic))
     {
-    case DEFAULT_ARG:          return TS_CP_DEFAULT_ARG;
+    case ARGUMENT_PACK_SELECT:  return TS_CP_ARGUMENT_PACK_SELECT;
+    case BASELINK:             return TS_CP_BASELINK;
+    case CONSTRAINT_INFO:       return TS_CP_CONSTRAINT_INFO;
     case DEFERRED_NOEXCEPT:    return TS_CP_DEFERRED_NOEXCEPT;
+    case DEFERRED_PARSE:       return TS_CP_DEFERRED_PARSE;
     case IDENTIFIER_NODE:      return TS_CP_IDENTIFIER;
+    case LAMBDA_EXPR:          return TS_CP_LAMBDA_EXPR;
     case OVERLOAD:             return TS_CP_OVERLOAD;
-    case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
     case PTRMEM_CST:           return TS_CP_PTRMEM;
-    case BASELINK:             return TS_CP_BASELINK;
-    case TEMPLATE_DECL:                return TS_CP_TEMPLATE_DECL;
     case STATIC_ASSERT:                return TS_CP_STATIC_ASSERT;
-    case ARGUMENT_PACK_SELECT:  return TS_CP_ARGUMENT_PACK_SELECT;
-    case TRAIT_EXPR:           return TS_CP_TRAIT_EXPR;
-    case LAMBDA_EXPR:          return TS_CP_LAMBDA_EXPR;
+    case TEMPLATE_DECL:                return TS_CP_TEMPLATE_DECL;
     case TEMPLATE_INFO:                return TS_CP_TEMPLATE_INFO;
-    case CONSTRAINT_INFO:       return TS_CP_CONSTRAINT_INFO;
+    case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
+    case TRAIT_EXPR:           return TS_CP_TRAIT_EXPR;
     case USERDEF_LITERAL:      return TS_CP_USERDEF_LITERAL;
     default:                   return TS_CP_GENERIC;
     }
@@ -16675,14 +17009,8 @@ fndecl_declared_return_type (tree fn)
 {
   fn = STRIP_TEMPLATE (fn);
   if (FNDECL_USED_AUTO (fn))
-    {
-      struct language_function *f = NULL;
-      if (DECL_STRUCT_FUNCTION (fn))
-       f = DECL_STRUCT_FUNCTION (fn)->language;
-      if (f == NULL)
-       f = DECL_SAVED_FUNCTION_DATA (fn);
-      return f->x_auto_return_pattern;
-    }
+    return DECL_SAVED_AUTO_RETURN_TYPE (fn);
+
   return TREE_TYPE (TREE_TYPE (fn));
 }
 
@@ -16707,7 +17035,9 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
 {
   if (undeduced_auto_decl (decl))
     {
-      if (complain & tf_error)
+      if (TREE_NO_WARNING (decl) && seen_error ())
+       /* We probably already complained about deduction failure.  */;
+      else if (complain & tf_error)
        error ("use of %qD before deduction of %<auto%>", decl);
       return false;
     }