]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/decl.c
/cp
[thirdparty/gcc.git] / gcc / cp / decl.c
index e662f63bb0f07ffafecb8c9a3f7eb6c81e163755..0a3ef452536fa836c3b37e227304ebccd878ee41 100644 (file)
@@ -1,5 +1,5 @@
-/* Process declarations and variables for C++ compiler.
-   Copyright (C) 1988-2018 Free Software Foundation, Inc.
+/* Process declarations and variables for -*- C++ -*- compiler.
+   Copyright (C) 1988-2019 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -68,7 +68,7 @@ static int decl_jump_unsafe (tree);
 static void require_complete_types_for_parms (tree);
 static tree grok_reference_init (tree, tree, tree, int);
 static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
-                        int, int, int, bool, int, tree);
+                        int, int, int, bool, int, tree, location_t);
 static void check_static_variable_definition (tree, tree);
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (tree, tree, bool);
@@ -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);
@@ -1305,7 +1304,7 @@ check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl,
        auto_diagnostic_group d;
        if (permerror (DECL_SOURCE_LOCATION (newdecl),
                       "friend declaration of %q#D specifies default "
-                      "arguments and isn't the only declaration", newdecl))
+                      "arguments and isn%'t the only declaration", newdecl))
          inform (DECL_SOURCE_LOCATION (olddecl),
                  "previous declaration of %q#D", olddecl);
        return;
@@ -1476,7 +1475,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,
@@ -2026,9 +2025,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);
@@ -2132,13 +2132,33 @@ next_arg:;
          if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
            {
              tree remove = TREE_TYPE (newdecl);
-             for (tree t = TYPE_MAIN_VARIANT (remove); ;
-                  t = TYPE_NEXT_VARIANT (t))
-               if (TYPE_NEXT_VARIANT (t) == remove)
-                 {
-                   TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
-                   break;
-                 }
+             if (TYPE_MAIN_VARIANT (remove) == remove)
+               {
+                 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))
+                 if (TYPE_NEXT_VARIANT (t) == remove)
+                   {
+                     TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+                     break;
+                   }
            }
        }
       else if (merge_attr)
@@ -2366,9 +2386,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),
@@ -2378,10 +2399,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)
@@ -2457,9 +2480,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);
 
@@ -3206,32 +3229,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;
            }
@@ -3247,7 +3270,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);
        }
     }
 
@@ -3342,7 +3365,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)
@@ -3360,13 +3383,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)
@@ -3475,9 +3498,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.  */
@@ -3506,7 +3526,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;
@@ -3527,8 +3546,7 @@ pop_switch (void)
   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.  */
@@ -3643,9 +3661,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.  */
@@ -3816,7 +3832,9 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   gcc_assert (identifier_p (name));
   gcc_assert (TYPE_P (context));
 
-  if (!MAYBE_CLASS_TYPE_P (context))
+  if (TREE_CODE (context) == TYPE_PACK_EXPANSION)
+    /* This can happen for C++17 variadic using (c++/88986).  */;
+  else if (!MAYBE_CLASS_TYPE_P (context))
     {
       if (complain & tf_error)
        error ("%q#T is not a class", context);
@@ -4265,7 +4283,8 @@ cxx_init_decl_processing (void)
   if (aligned_new_threshold > 1
       && !pow2p_hwi (aligned_new_threshold))
     {
-      error ("-faligned-new=%d is not a power of two", aligned_new_threshold);
+      error ("%<-faligned-new=%d%> is not a power of two",
+            aligned_new_threshold);
       aligned_new_threshold = 1;
     }
   if (aligned_new_threshold == -1)
@@ -4536,11 +4555,9 @@ builtin_function_1 (tree decl, tree context, bool is_global)
     }
 
   if (is_global)
-    pushdecl_top_level (decl);
+    return pushdecl_top_level (decl);
   else
-    pushdecl (decl);
-
-  return decl;
+    return pushdecl (decl);
 }
 
 tree
@@ -4803,15 +4820,20 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
     declared_type = declspecs->type;
   else if (declspecs->type == error_mark_node)
     error_p = true;
-  if (declared_type == NULL_TREE && ! saw_friend && !error_p)
-    permerror (input_location, "declaration does not declare anything");
-  else if (declared_type != NULL_TREE && type_uses_auto (declared_type))
+
+  if (type_uses_auto (declared_type))
     {
       error_at (declspecs->locations[ds_type_spec],
                "%<auto%> can only be specified for variables "
                "or function declarations");
       return error_mark_node;
     }
+
+  if (declared_type && !OVERLOAD_TYPE_P (declared_type))
+    declared_type = NULL_TREE;
+
+  if (!declared_type && !saw_friend && !error_p)
+    permerror (input_location, "declaration does not declare anything");
   /* Check for an anonymous union.  */
   else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
           && TYPE_UNNAMED_P (declared_type))
@@ -5056,7 +5078,9 @@ start_decl (const cp_declarator *declarator,
   if (initialized
       && TREE_CODE (decl) == TYPE_DECL)
     {
-      error ("typedef %qD is initialized (use decltype instead)", decl);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "typedef %qD is initialized (use %qs instead)",
+               decl, "decltype");
       return error_mark_node;
     }
 
@@ -5093,7 +5117,8 @@ start_decl (const cp_declarator *declarator,
      a definition.  */
   if (initialized && DECL_DLLIMPORT_P (decl))
     {
-      error ("definition of %q#D is marked %<dllimport%>", decl);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "definition of %q#D is marked %<dllimport%>", decl);
       DECL_DLLIMPORT_P (decl) = 0;
     }
 
@@ -5106,7 +5131,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)))
     {
@@ -5199,7 +5224,8 @@ start_decl (const cp_declarator *declarator,
       if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)
          /* Aliases are definitions. */
          && !alias)
-       permerror (input_location, "declaration of %q#D outside of class is not definition",
+       permerror (declarator->id_loc,
+                  "declaration of %q#D outside of class is not definition",
                   decl);
     }
 
@@ -5232,10 +5258,12 @@ start_decl (const cp_declarator *declarator,
     {
       bool ok = false;
       if (CP_DECL_THREAD_LOCAL_P (decl))
-       error ("%qD declared %<thread_local%> in %<constexpr%> function",
-              decl);
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "%qD declared %<thread_local%> in %<constexpr%> function",
+                 decl);
       else if (TREE_STATIC (decl))
-       error ("%qD declared %<static%> in %<constexpr%> function", decl);
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "%qD declared %<static%> in %<constexpr%> function", decl);
       else
        ok = true;
       if (!ok)
@@ -5351,7 +5379,8 @@ grok_reference_init (tree decl, tree type, tree init, int flags)
       if ((DECL_LANG_SPECIFIC (decl) == 0
           || DECL_IN_AGGR_P (decl) == 0)
          && ! DECL_THIS_EXTERN (decl))
-       error ("%qD declared as reference but not initialized", decl);
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "%qD declared as reference but not initialized", decl);
       return NULL_TREE;
     }
 
@@ -5623,6 +5652,7 @@ maybe_commonize_var (tree decl)
                 be merged.  */
              TREE_PUBLIC (decl) = 0;
              DECL_COMMON (decl) = 0;
+             DECL_INTERFACE_KNOWN (decl) = 1;
              const char *msg;
              if (DECL_INLINE_VAR_P (decl))
                msg = G_("sorry: semantics of inline variable "
@@ -5665,13 +5695,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
            {
@@ -5680,6 +5712,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;
            }
        }
@@ -5688,7 +5722,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;
 
@@ -5786,6 +5820,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
        max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
     }
 
+  /* Set to the index of the last element with a non-zero initializer.
+     Zero initializers for elements past this one can be dropped.  */
+  unsigned HOST_WIDE_INT last_nonzero = -1;
   /* Loop until there are no more initializers.  */
   for (index = 0;
        d->cur != d->end && (!sized_array_p || index <= max_index_cst);
@@ -5804,11 +5841,32 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
       if (!TREE_CONSTANT (elt_init))
        TREE_CONSTANT (new_init) = false;
 
+      /* 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))
+       last_nonzero = index;
+
       /* This can happen with an invalid initializer (c++/54501).  */
       if (d->cur == old_cur && !sized_array_p)
        break;
     }
 
+  if (sized_array_p && trivial_type_p (elt_type))
+    {
+      /* Strip trailing zero-initializers from an array of a trivial
+        type of known size.  They are redundant and get in the way
+        of telling them apart from those with implicit zero value.  */
+      unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init);
+      if (last_nonzero > nelts)
+       nelts = 0;
+      else if (last_nonzero < nelts - 1)
+       nelts = last_nonzero + 1;
+
+      vec_safe_truncate (CONSTRUCTOR_ELTS (new_init), nelts);
+    }
+
   return new_init;
 }
 
@@ -5911,12 +5969,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)
@@ -6005,14 +6063,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
       && has_designator_problem (d, complain))
     return error_mark_node;
 
+  tree stripped_init = tree_strip_any_location_wrapper (init);
+
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
       /* A complex type can be initialized from one or two initializers,
         but braces are not elided.  */
       d->cur++;
-      if (BRACE_ENCLOSED_INITIALIZER_P (init))
+      if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init))
        {
-         if (CONSTRUCTOR_NELTS (init) > 2)
+         if (CONSTRUCTOR_NELTS (stripped_init) > 2)
            {
              if (complain & tf_error)
                error ("too many initializers for %qT", type);
@@ -6042,22 +6102,30 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
         We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
         of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
         a CONSTRUCTOR (with a record type).  */
-      if (TREE_CODE (init) == CONSTRUCTOR
+      if (TREE_CODE (stripped_init) == CONSTRUCTOR
          /* Don't complain about a capture-init.  */
-         && !CONSTRUCTOR_IS_DIRECT_INIT (init)
-         && BRACE_ENCLOSED_INITIALIZER_P (init))  /* p7626.C */
+         && !CONSTRUCTOR_IS_DIRECT_INIT (stripped_init)
+         && BRACE_ENCLOSED_INITIALIZER_P (stripped_init))  /* p7626.C */
        {
          if (SCALAR_TYPE_P (type))
            {
-             if (cxx_dialect < cxx11
-                 /* Isn't value-initialization.  */
-                 || CONSTRUCTOR_NELTS (init) > 0)
+             if (cxx_dialect < cxx11)
                {
                  if (complain & tf_error)
                    error ("braces around scalar initializer for type %qT",
                           type);
                  init = error_mark_node;
                }
+             else if (first_initializer_p
+                      || (CONSTRUCTOR_NELTS (stripped_init) > 0
+                          && (BRACE_ENCLOSED_INITIALIZER_P
+                              (CONSTRUCTOR_ELT (stripped_init,0)->value))))
+               {
+                 if (complain & tf_error)
+                   error ("too many braces around scalar initializer"
+                          "for type %qT", type);
+                 init = error_mark_node;
+               }
            }
          else
            maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
@@ -6111,20 +6179,22 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
       && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
     {
       tree str_init = init;
+      tree stripped_str_init = stripped_init;
 
       /* Strip one level of braces if and only if they enclose a single
         element (as allowed by [dcl.init.string]).  */
       if (!first_initializer_p
-         && TREE_CODE (str_init) == CONSTRUCTOR
-         && CONSTRUCTOR_NELTS (str_init) == 1)
+         && TREE_CODE (stripped_str_init) == CONSTRUCTOR
+         && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
        {
-         str_init = (*CONSTRUCTOR_ELTS (str_init))[0].value;
+         str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+         stripped_str_init = tree_strip_any_location_wrapper (str_init);
        }
 
       /* If it's a string literal, then it's the initializer for the array
         as a whole. Otherwise, continue with normal initialization for
         array types (one value per array element).  */
-      if (TREE_CODE (str_init) == STRING_CST)
+      if (TREE_CODE (stripped_str_init) == STRING_CST)
        {
          if (has_designator_problem (d, complain))
            return error_mark_node;
@@ -6139,24 +6209,33 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
      which reshape_init exists).  */
   if (!first_initializer_p)
     {
-      if (TREE_CODE (init) == CONSTRUCTOR)
+      if (TREE_CODE (stripped_init) == CONSTRUCTOR)
        {
-         if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
-           /* There is no need to reshape pointer-to-member function
-              initializers, as they are always constructed correctly
-              by the front end.  */
-           ;
-         else if (COMPOUND_LITERAL_P (init))
+         tree init_type = TREE_TYPE (init);
+         if (init_type && TYPE_PTRMEMFUNC_P (init_type))
+           /* There is no need to call reshape_init for pointer-to-member
+              function initializers, as they are always constructed correctly
+              by the front end.  Here we have e.g. {.__pfn=0B, .__delta=0},
+              which is missing outermost braces.  We should warn below, and
+              one of the routines below will wrap it in additional { }.  */;
          /* For a nested compound literal, there is no need to reshape since
-            brace elision is not allowed. Even if we decided to allow it,
-            we should add a call to reshape_init in finish_compound_literal,
-            before calling digest_init, so changing this code would still
-            not be necessary.  */
-           gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
+            we called reshape_init in finish_compound_literal, before calling
+            digest_init.  */
+         else if (COMPOUND_LITERAL_P (stripped_init)
+                  /* Similarly, a CONSTRUCTOR of the target's type is a
+                     previously digested initializer.  */
+                  || same_type_ignoring_top_level_qualifiers_p (type,
+                                                                init_type))
+           {
+             ++d->cur;
+             gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+             return init;
+           }
          else
            {
+             /* Something that hasn't been reshaped yet.  */
              ++d->cur;
-             gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
+             gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
              return reshape_init (type, init, complain);
            }
        }
@@ -6245,6 +6324,9 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
   if (CONSTRUCTOR_IS_DIRECT_INIT (init)
       && BRACE_ENCLOSED_INITIALIZER_P (new_init))
     CONSTRUCTOR_IS_DIRECT_INIT (new_init) = true;
+  if (CONSTRUCTOR_IS_DESIGNATED_INIT (init)
+      && BRACE_ENCLOSED_INITIALIZER_P (new_init))
+    CONSTRUCTOR_IS_DESIGNATED_INIT (new_init) = true;
 
   return new_init;
 }
@@ -6530,9 +6612,8 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
     }
 
   if (init_code
-      && (DECL_IN_AGGR_P (decl)
-         && DECL_INITIALIZED_IN_CLASS_P (decl)
-         && !DECL_VAR_DECLARED_INLINE_P (decl)))
+      && DECL_IN_AGGR_P (decl)
+      && DECL_INITIALIZED_IN_CLASS_P (decl))
     {
       static int explained = 0;
 
@@ -6600,8 +6681,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
         external; it is only a declaration, and not a definition.  */
       if (init == NULL_TREE)
        gcc_assert (DECL_EXTERNAL (decl)
-                   || !TREE_PUBLIC (decl)
-                   || DECL_INLINE_VAR_P (decl));
+                   || !TREE_PUBLIC (decl));
     }
 
   /* We don't create any RTL for local variables.  */
@@ -6942,8 +7022,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;
        }
@@ -7281,7 +7361,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                    synthesize_method (decl);
                }
              else
-               error ("function %q#D is initialized like a variable", decl);
+               error_at (cp_expr_loc_or_loc (init,
+                                             DECL_SOURCE_LOCATION (decl)),
+                         "function %q#D is initialized like a variable",
+                         decl);
            }
          /* else no initialization required.  */
        }
@@ -7289,8 +7372,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))
@@ -7510,7 +7592,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,
@@ -7544,7 +7626,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);
@@ -7775,8 +7857,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
@@ -8246,18 +8347,18 @@ expand_static_init (tree decl, tree init)
   if (CP_DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
       && !DECL_FUNCTION_SCOPE_P (decl))
     {
+      location_t dloc = DECL_SOURCE_LOCATION (decl);
       if (init)
-       error ("non-local variable %qD declared %<__thread%> "
-              "needs dynamic initialization", decl);
+       error_at (dloc, "non-local variable %qD declared %<__thread%> "
+                 "needs dynamic initialization", decl);
       else
-       error ("non-local variable %qD declared %<__thread%> "
-              "has a non-trivial destructor", decl);
+       error_at (dloc, "non-local variable %qD declared %<__thread%> "
+                 "has a non-trivial destructor", decl);
       static bool informed;
       if (!informed)
        {
-         inform (DECL_SOURCE_LOCATION (decl),
-                 "C++11 %<thread_local%> allows dynamic initialization "
-                 "and destruction");
+         inform (dloc, "C++11 %<thread_local%> allows dynamic "
+                 "initialization and destruction");
          informed = true;
        }
       return;
@@ -8426,6 +8527,7 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
        {
          vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
          tree value = (*v)[0].value;
+         STRIP_ANY_LOCATION_WRAPPER (value);
 
          if (TREE_CODE (value) == STRING_CST
              && v->length () == 1)
@@ -8837,9 +8939,7 @@ 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))
@@ -8874,7 +8974,7 @@ grokfndecl (tree ctype,
          {
            permerror (DECL_SOURCE_LOCATION (decl),
                       "friend declaration of %qD specifies default "
-                      "arguments and isn't a definition", decl);
+                      "arguments and isn%'t a definition", decl);
            break;
          }
     }
@@ -9048,7 +9148,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  */
@@ -9282,7 +9382,8 @@ grokvardecl (tree type,
             int inlinep,
             bool conceptp,
             int template_count,
-            tree scope)
+            tree scope,
+            location_t location)
 {
   tree decl;
   tree explicit_scope;
@@ -9318,9 +9419,9 @@ grokvardecl (tree type,
          /* Similarly for explicit specializations.  */
          || (orig_declarator
              && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)))
-    decl = build_lang_decl (VAR_DECL, name, type);
+    decl = build_lang_decl_loc (location, VAR_DECL, name, type);
   else
-    decl = build_decl (input_location, VAR_DECL, name, type);
+    decl = build_decl (location, VAR_DECL, name, type);
 
   if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
     set_decl_namespace (decl, explicit_scope, 0);
@@ -9395,7 +9496,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.  */
@@ -9625,17 +9727,21 @@ static tree
 compute_array_index_type_loc (location_t name_loc, tree name, tree size,
                              tsubst_flags_t complain)
 {
-  tree itype;
-  tree osize = size;
-
   if (error_operand_p (size))
     return error_mark_node;
 
+  /* The type of the index being computed.  */
+  tree itype;
+
+  /* The original numeric size as seen in the source code before
+     conversion to size_t.  */
+  tree origsize = size;
+
   location_t loc = cp_expr_loc_or_loc (size, name ? name_loc : input_location);
 
   if (!type_dependent_expression_p (size))
     {
-      osize = size = mark_rvalue_use (size);
+      origsize = size = mark_rvalue_use (size);
 
       if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR
          && TREE_SIDE_EFFECTS (size))
@@ -9645,10 +9751,14 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
        {
          size = instantiate_non_dependent_expr_sfinae (size, complain);
          size = build_converted_constant_expr (size_type_node, size, complain);
-         size = maybe_constant_value (size);
+         /* Pedantically a constant expression is required here and so
+            __builtin_is_constant_evaluated () should fold to true if it
+            is successfully folded into a constant.  */
+         size = maybe_constant_value (size, NULL_TREE,
+                                      /*manifestly_const_eval=*/true);
 
          if (!TREE_CONSTANT (size))
-           size = osize;
+           size = origsize;
        }
 
       if (error_operand_p (size))
@@ -9709,16 +9819,30 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
-      /* An array must have a positive number of elements.  */
-      if (!valid_constant_size_p (size))
+      /* The size to use in diagnostics that reflects the constant
+        size used in the source, rather than SIZE massaged above.  */
+      tree diagsize = size;
+
+      /* If the original size before conversion to size_t was signed
+        and negative, convert it to ssizetype to restore the sign.  */
+      if (!TYPE_UNSIGNED (TREE_TYPE (origsize))
+         && TREE_CODE (size) == INTEGER_CST
+         && tree_int_cst_sign_bit (size))
+       {
+         diagsize = fold_convert (ssizetype, size);
+
+         /* Clear the overflow bit that may have been set as a result
+            of the conversion from the sizetype of the new size to
+            ssizetype.  */
+         TREE_OVERFLOW (diagsize) = false;
+       }
+
+      /* Verify that the array has a positive number of elements
+        and issue the appropriate diagnostic if it doesn't.  */
+      if (!valid_array_size_p (loc, diagsize, name, (complain & tf_error)))
        {
          if (!(complain & tf_error))
            return error_mark_node;
-
-         if (name)
-           error_at (loc, "size of array %qD is negative", name);
-         else
-           error_at (loc, "size of array is negative");
          size = integer_one_node;
        }
       /* As an extension we allow zero-sized arrays.  */
@@ -9987,6 +10111,15 @@ 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]);
+}
+
 /* 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
@@ -10005,7 +10138,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");
@@ -10018,7 +10152,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");
@@ -10033,7 +10168,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 "
@@ -10044,7 +10180,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 "
@@ -10060,7 +10197,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:
@@ -10109,7 +10246,7 @@ mark_inline_variable (tree decl, location_t loc)
     }
   else if (cxx_dialect < cxx17)
     pedwarn (loc, 0, "inline variables are only available "
-            "with -std=c++17 or -std=gnu++17");
+            "with %<-std=c++17%> or %<-std=gnu++17%>");
   if (inlinep)
     {
       retrofit_lang_decl (decl);
@@ -10129,15 +10266,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;
@@ -10317,13 +10451,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;
@@ -10488,7 +10624,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;
     }
 
@@ -10496,7 +10632,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;
     }
 
@@ -10505,7 +10641,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;
        }
 
@@ -10513,12 +10649,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;
            }
        }
@@ -10568,13 +10704,16 @@ grokdeclarator (const cp_declarator *declarator,
      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;
     }
 
@@ -10749,7 +10888,9 @@ grokdeclarator (const cp_declarator *declarator,
          error_at (&richloc, "%<long%> and %<short%> specified together");
        }
       else if (TREE_CODE (type) != INTEGER_TYPE
-              || type == char16_type_node || type == char32_type_node
+              || type == char8_type_node
+              || type == char16_type_node
+              || type == char32_type_node
               || ((long_p || short_p)
                   && (explicit_char || explicit_intN)))
        error_at (loc, "%qs specified with %qT", key, type);
@@ -10873,6 +11014,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;
@@ -10900,8 +11042,8 @@ grokdeclarator (const cp_declarator *declarator,
          gcc_rich_location richloc (declspecs->locations[ds_virtual]);
          richloc.add_range (declspecs->locations[ds_constexpr]);
          pedwarn (&richloc, OPT_Wpedantic, "member %qD can be declared both "
-                  "%<virtual%> and %<constexpr%> only in -std=c++2a or "
-                  "-std=gnu++2a", dname);
+                  "%<virtual%> and %<constexpr%> only in %<-std=c++2a%> or "
+                  "%<-std=gnu++2a%>", dname);
        }
     }
   friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
@@ -10962,40 +11104,43 @@ 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");
       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 "
@@ -11021,12 +11166,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.  */
@@ -11263,35 +11408,37 @@ grokdeclarator (const cp_declarator *declarator,
                          /* OK for C++11 lambdas.  */;
                        else if (cxx_dialect < cxx14)
                          {
-                           error ("%qs function uses "
-                                  "%<auto%> type specifier without trailing "
-                                  "return type", name);
-                           inform (input_location, "deduced return type "
-                                   "only available with -std=c++14 or "
-                                   "-std=gnu++14");
+                           error_at (typespec_loc, "%qs function uses "
+                                     "%<auto%> type specifier without "
+                                     "trailing return type", name);
+                           inform (typespec_loc,
+                                   "deduced return type only available "
+                                   "with %<-std=c++14%> or %<-std=gnu++14%>");
                          }
                        else if (virtualp)
                          {
-                           error ("virtual function cannot "
-                                  "have deduced return type");
+                           error_at (typespec_loc, "virtual function "
+                                     "cannot have deduced return type");
                            virtualp = false;
                          }
                      }
                    else if (!is_auto (type) && sfk != sfk_conversion)
                      {
-                       error ("%qs function with trailing return type has"
-                              " %qT as its type rather than plain %<auto%>",
-                              name, type);
+                       error_at (typespec_loc, "%qs function with trailing "
+                                 "return type has %qT as its type rather "
+                                 "than plain %<auto%>", name, type);
                        return error_mark_node;
                      }
                    else if (is_auto (type) && AUTO_IS_DECLTYPE (type))
                      {
                        if (funcdecl_p)
-                         error ("%qs function with trailing return type has "
-                                "%<decltype(auto)%> as its type rather than "
-                                "plain %<auto%>", name);
+                         error_at (typespec_loc,
+                                   "%qs function with trailing return type "
+                                   "has %<decltype(auto)%> as its type "
+                                   "rather than plain %<auto%>", name);
                        else
-                         error ("invalid use of %<decltype(auto)%>");
+                         error_at (typespec_loc,
+                                   "invalid use of %<decltype(auto)%>");
                        return error_mark_node;
                      }
                    tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node);
@@ -11335,11 +11482,13 @@ grokdeclarator (const cp_declarator *declarator,
                    if (cxx_dialect < cxx11)
                      /* Not using maybe_warn_cpp0x because this should
                         always be an error.  */
-                     error ("trailing return type only available with "
-                            "-std=c++11 or -std=gnu++11");
+                     error_at (typespec_loc,
+                               "trailing return type only available "
+                               "with %<-std=c++11%> or %<-std=gnu++11%>");
                    else
-                     error ("%qs function with trailing return type not "
-                            "declared with %<auto%> type specifier", name);
+                     error_at (typespec_loc, "%qs function with trailing "
+                               "return type not declared with %<auto%> "
+                               "type specifier", name);
                    return error_mark_node;
                  }
              }
@@ -11459,7 +11608,7 @@ grokdeclarator (const cp_declarator *declarator,
                  error ("friend declaration not in class definition");
                if (current_function_decl && funcdef_flag)
                  {
-                   error ("can%'t define friend function %qs in a local "
+                   error ("cannot define friend function %qs in a local "
                           "class definition", name);
                    friendp = 0;
                  }
@@ -11714,6 +11863,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)
@@ -11729,8 +11880,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",
@@ -11758,13 +11908,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
@@ -11793,19 +11943,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;
        }
     }
@@ -11852,9 +12002,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;
     }
 
@@ -11878,36 +12030,42 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (storage_class == sc_mutable)
     {
+      location_t sloc = declspecs->locations[ds_storage_class];
       if (decl_context != FIELD || friendp)
        {
-         error ("non-member %qs cannot be declared %<mutable%>", name);
+         error_at (sloc, "non-member %qs cannot be declared %<mutable%>",
+                   name);
          storage_class = sc_none;
        }
       else if (decl_context == TYPENAME || typedef_p)
        {
-         error ("non-object member %qs cannot be declared %<mutable%>", name);
+         error_at (sloc,
+                   "non-object member %qs cannot be declared %<mutable%>",
+                   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 ("function %qs cannot be declared %<mutable%>", name);
+         error_at (sloc, "function %qs cannot be declared %<mutable%>",
+                   name);
          storage_class = sc_none;
        }
       else if (staticp)
        {
-         error ("static %qs cannot be declared %<mutable%>", name);
+         error_at (sloc, "%<static%> %qs cannot be declared %<mutable%>",
+                   name);
          storage_class = sc_none;
        }
       else if (type_quals & TYPE_QUAL_CONST)
        {
-         error ("const %qs cannot be declared %<mutable%>", name);
+         error_at (sloc, "%<const%> %qs cannot be declared %<mutable%>",
+                   name);
          storage_class = sc_none;
        }
       else if (TYPE_REF_P (type))
        {
-         permerror (input_location, "reference %qs cannot be declared "
-                    "%<mutable%>", name);
+         permerror (sloc, "reference %qs cannot be declared %<mutable%>",
+                    name);
          storage_class = sc_none;
        }
     }
@@ -11952,14 +12110,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 (TYPE_DECL, unqualified_id, type);
+       decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
       else
-       decl = build_decl (input_location, TYPE_DECL, unqualified_id, type);
+       decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
 
       if (decl_context != FIELD)
        {
@@ -11976,7 +12134,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);
 
@@ -12134,7 +12292,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;
        }
 
@@ -12216,13 +12374,13 @@ grokdeclarator (const cp_declarator *declarator,
        if (!staticp && !friendp && TREE_CODE (type) != METHOD_TYPE)
          if (tree auto_node = type_uses_auto (type))
            {
-             location_t loc = declspecs->locations[ds_type_spec];
+             location_t tloc = declspecs->locations[ds_type_spec];
              if (CLASS_PLACEHOLDER_TEMPLATE (auto_node))
-               error_at (loc, "invalid use of template-name %qE without an "
+               error_at (tloc, "invalid use of template-name %qE without an "
                          "argument list",
                          CLASS_PLACEHOLDER_TEMPLATE (auto_node));
              else
-               error_at (loc, "non-static data member declared with "
+               error_at (tloc, "non-static data member declared with "
                          "placeholder %qT", auto_node);
              type = error_mark_node;
            }
@@ -12244,8 +12402,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,
@@ -12397,7 +12555,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;
@@ -12430,8 +12588,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));
                  }
@@ -12446,9 +12603,13 @@ grokdeclarator (const cp_declarator *declarator,
          {
            if (friendp)
              {
-               error_at (declarator->id_loc,
-                         "%qE is neither function nor member function; "
-                         "cannot be declared friend", unqualified_id);
+               if (unqualified_id)
+                 error_at (id_loc,
+                           "%qE is neither function nor member function; "
+                           "cannot be declared friend", unqualified_id);
+               else
+                 error ("unnamed field is neither function nor member "
+                        "function; cannot be declared friend");
                return error_mark_node;
              }
            decl = NULL_TREE;
@@ -12487,10 +12648,8 @@ grokdeclarator (const cp_declarator *declarator,
              {
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
-               decl = build_lang_decl_loc (declarator
-                                           ? declarator->id_loc
-                                           : input_location,
-                                           VAR_DECL, unqualified_id, type);
+               decl = build_lang_decl_loc (id_loc, VAR_DECL,
+                                           unqualified_id, type);
                set_linkage_for_static_data_member (decl);
                if (concept_p)
                  error_at (declspecs->locations[ds_concept],
@@ -12498,8 +12657,9 @@ grokdeclarator (const cp_declarator *declarator,
                            unqualified_id);
                else if (constexpr_p && !initialized)
                  {
-                   error ("%<constexpr%> static data member %qD must have an "
-                          "initializer", decl);
+                   error_at (DECL_SOURCE_LOCATION (decl),
+                             "%<constexpr%> static data member %qD must "
+                             "have an initializer", decl);
                    constexpr_p = false;
                  }
 
@@ -12536,8 +12696,7 @@ grokdeclarator (const cp_declarator *declarator,
                              unqualified_id);
                    constexpr_p = false;
                  }
-               decl = build_decl (input_location,
-                                  FIELD_DECL, unqualified_id, type);
+               decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
                if (bitfield && !unqualified_id)
                  {
@@ -12572,8 +12731,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;
@@ -12656,7 +12814,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;
 
@@ -12702,7 +12860,8 @@ grokdeclarator (const cp_declarator *declarator,
                            inlinep,
                            concept_p,
                            template_count,
-                           ctype ? ctype : in_namespace);
+                           ctype ? ctype : in_namespace,
+                           id_loc);
        if (decl == NULL_TREE)
          return error_mark_node;
 
@@ -12716,7 +12875,8 @@ grokdeclarator (const cp_declarator *declarator,
            DECL_CONTEXT (decl) = ctype;
            if (staticp == 1)
              {
-               permerror (input_location, "%<static%> may not be used when defining "
+               permerror (declspecs->locations[ds_storage_class],
+                          "%<static%> may not be used when defining "
                           "(as opposed to declaring) a static data member");
                staticp = 0;
                storage_class = sc_none;
@@ -12736,8 +12896,9 @@ grokdeclarator (const cp_declarator *declarator,
          }
        else if (constexpr_p && DECL_EXTERNAL (decl))
          {
-           error ("declaration of %<constexpr%> variable %qD "
-                  "is not a definition", decl);
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "declaration of %<constexpr%> variable %qD "
+                     "is not a definition", decl);
            constexpr_p = false;
          }
 
@@ -12746,7 +12907,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);
          }
@@ -12768,11 +12929,13 @@ grokdeclarator (const cp_declarator *declarator,
            /* It's common practice (and completely valid) to have a const
               be initialized and declared extern.  */
            if (!(type_quals & TYPE_QUAL_CONST))
-             warning (0, "%qs initialized and declared %<extern%>", name);
+             warning_at (DECL_SOURCE_LOCATION (decl), 0,
+                         "%qs initialized and declared %<extern%>", name);
          }
        else
          {
-           error ("%qs has both %<extern%> and initializer", name);
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "%qs has both %<extern%> and initializer", name);
            return error_mark_node;
          }
       }
@@ -13244,7 +13407,8 @@ grok_special_member_properties (tree decl)
 {
   tree class_type;
 
-  if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+  if (TREE_CODE (decl) == USING_DECL
+      || !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
     return;
 
   class_type = DECL_CONTEXT (decl);
@@ -13488,7 +13652,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;
     }
 
@@ -13936,7 +14100,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)
@@ -14598,7 +14762,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;
@@ -15127,7 +15291,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))
@@ -15320,20 +15484,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
@@ -15469,6 +15634,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   store_parm_decls (current_function_parms);
 
+  push_operator_bindings ();
+
   if (!processing_template_decl
       && (flag_lifetime_dse > 1)
       && DECL_CONSTRUCTOR_P (decl1)
@@ -15622,31 +15789,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
@@ -15975,9 +16117,9 @@ 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)))
        {
          apply_deduced_return_type (fndecl, void_type_node);
          fntype = TREE_TYPE (fndecl);
@@ -15986,7 +16128,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%>");
        }
@@ -16049,10 +16191,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))
@@ -16078,15 +16216,16 @@ finish_function (bool inline_p)
        {
          tree valtype = TREE_TYPE (DECL_RESULT (fndecl));
          if (TREE_CODE (valtype) == REFERENCE_TYPE
+             && current_class_ref
              && same_type_ignoring_top_level_qualifiers_p
-                 (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
-           if (global_dc->option_enabled (OPT_Wreturn_type,
-                                          global_dc->option_state))
-             add_return_star_this_fixit (&richloc, fndecl);
+                 (TREE_TYPE (valtype), TREE_TYPE (current_class_ref))
+             && global_dc->option_enabled (OPT_Wreturn_type,
+                                           global_dc->option_state))
+           add_return_star_this_fixit (&richloc, fndecl);
        }
-      warning_at (&richloc, OPT_Wreturn_type,
-                 "no return statement in function returning non-void");
-      TREE_NO_WARNING (fndecl) = 1;
+      if (warning_at (&richloc, OPT_Wreturn_type,
+         "no return statement in function returning non-void"))
+       TREE_NO_WARNING (fndecl) = 1;
     }
 
   /* Store the end of the function, so that we get good line number
@@ -16133,20 +16272,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.  */
@@ -16560,14 +16686,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));
 }
 
@@ -16579,6 +16699,7 @@ undeduced_auto_decl (tree decl)
 {
   if (cxx_dialect < cxx11)
     return false;
+  STRIP_ANY_LOCATION_WRAPPER (decl);
   return ((VAR_OR_FUNCTION_DECL_P (decl)
           || TREE_CODE (decl) == TEMPLATE_DECL)
          && type_uses_auto (TREE_TYPE (decl)));
@@ -16604,12 +16725,14 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
 tree
 build_explicit_specifier (tree expr, tsubst_flags_t complain)
 {
-  if (processing_template_decl && value_dependent_expression_p (expr))
+  if (instantiation_dependent_expression_p (expr))
     /* Wait for instantiation, tsubst_function_decl will handle it.  */
     return expr;
 
-  expr = build_converted_constant_expr (boolean_type_node, expr, complain);
-  expr = instantiate_non_dependent_expr (expr);
+  expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+  /* Don't let convert_like_real create more template codes.  */
+  processing_template_decl_sentinel s;
+  expr = build_converted_constant_bool_expr (expr, complain);
   expr = cxx_constant_value (expr);
   return expr;
 }