]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/pt.c
c++: alias_ctad_tweaks and constrained dguide [PR95486]
[gcc.git] / gcc / cp / pt.c
index f0cb7a2acb7d751d83ce3524b3dbaa5ce254b3d5..a7ab2bd28872737dd59f6ee58ae6795ec21265c6 100644 (file)
@@ -48,9 +48,9 @@ along with GCC; see the file COPYING3.  If not see
    returning an int.  */
 typedef int (*tree_fn_t) (tree, void*);
 
-/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
-   instantiations have been deferred, either because their definitions
-   were not yet available, or because we were putting off doing the work.  */
+/* The PENDING_TEMPLATES is a list of templates whose instantiations
+   have been deferred, either because their definitions were not yet
+   available, or because we were putting off doing the work.  */
 struct GTY ((chain_next ("%h.next"))) pending_template
 {
   struct pending_template *next;
@@ -116,9 +116,10 @@ struct spec_hasher : ggc_ptr_hash<spec_entry>
   static bool equal (spec_entry *, spec_entry *);
 };
 
-static GTY (()) hash_table<spec_hasher> *decl_specializations;
-
-static GTY (()) hash_table<spec_hasher> *type_specializations;
+/* The general template is not in these tables.  */
+typedef hash_table<spec_hasher> spec_hash_table;
+static GTY (()) spec_hash_table *decl_specializations;
+static GTY (()) spec_hash_table *type_specializations;
 
 /* Contains canonical template parameter types. The vector is indexed by
    the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
@@ -214,9 +215,7 @@ static bool any_template_arguments_need_structural_equality_p (tree);
 static bool dependent_type_p_r (tree);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_decl (tree, tree, tsubst_flags_t);
-static void perform_typedefs_access_check (tree tmpl, tree targs);
-static void append_type_to_template_for_access_check_1 (tree, tree, tree,
-                                                       location_t);
+static void perform_instantiation_time_access_checks (tree, tree);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
@@ -1278,7 +1277,7 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
     {
       spec_entry *found;
       spec_entry elt;
-      hash_table<spec_hasher> *specializations;
+      spec_hash_table *specializations;
 
       elt.tmpl = tmpl;
       elt.args = args;
@@ -1573,10 +1572,9 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
       if (hash == 0)
        hash = spec_hasher::hash (&elt);
 
-      slot =
-       decl_specializations->find_slot_with_hash (&elt, hash, INSERT);
+      slot = decl_specializations->find_slot_with_hash (&elt, hash, INSERT);
       if (*slot)
-       fn = ((spec_entry *) *slot)->spec;
+       fn = (*slot)->spec;
       else
        fn = NULL_TREE;
     }
@@ -4417,29 +4415,21 @@ build_template_parm_index (int index,
 static tree
 canonical_type_parameter (tree type)
 {
-  tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
 
   gcc_assert (TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM);
 
-  if (!canonical_template_parms)
-    vec_alloc (canonical_template_parms, idx + 1);
-
-  if (canonical_template_parms->length () <= (unsigned) idx)
+  if (vec_safe_length (canonical_template_parms) <= (unsigned) idx)
     vec_safe_grow_cleared (canonical_template_parms, idx + 1);
 
-  list = (*canonical_template_parms)[idx];
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  for (tree list = (*canonical_template_parms)[idx];
+       list; list = TREE_CHAIN (list))
+    if (comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+      return TREE_VALUE (list);
 
-  if (list)
-    return TREE_VALUE (list);
-  else
-    {
-      (*canonical_template_parms)[idx]
-       = tree_cons (NULL_TREE, type, (*canonical_template_parms)[idx]);
-      return type;
-    }
+  (*canonical_template_parms)[idx]
+    = tree_cons (NULL_TREE, type, (*canonical_template_parms)[idx]);
+  return type;
 }
 
 /* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
@@ -4463,6 +4453,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
                              type);
       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
       TREE_READONLY (decl) = TREE_READONLY (orig_decl);
+      DECL_VIRTUAL_P (decl) = DECL_VIRTUAL_P (orig_decl);
       DECL_ARTIFICIAL (decl) = 1;
       SET_DECL_TEMPLATE_PARM_P (decl);
 
@@ -4474,7 +4465,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
       TEMPLATE_PARM_PARAMETER_PACK (tpi)
        = TEMPLATE_PARM_PARAMETER_PACK (index);
 
-       /* Template template parameters need this.  */
+      /* Template template parameters need this.  */
       tree inner = decl;
       if (TREE_CODE (decl) == TEMPLATE_DECL)
        {
@@ -4583,7 +4574,16 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
          /* This is for distinguishing between real templates and template
             template parameters */
          TREE_TYPE (parm) = t;
-         TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;
+
+         /* any_template_parm_r expects to be able to get the targs of a
+            DECL_TEMPLATE_RESULT.  */
+         tree result = DECL_TEMPLATE_RESULT (parm);
+         TREE_TYPE (result) = t;
+         tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (parm));
+         tree tinfo = build_template_info (parm, args);
+         retrofit_lang_decl (result);
+         DECL_TEMPLATE_INFO (result) = tinfo;
+
          decl = parm;
        }
       else
@@ -4891,7 +4891,9 @@ build_template_decl (tree decl, tree parms, bool member_template_p)
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   SET_DECL_LANGUAGE (tmpl, DECL_LANGUAGE (decl));
   DECL_TEMPLATE_PARMS (tmpl) = parms;
+  DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+  TREE_TYPE (tmpl) = TREE_TYPE (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
 
@@ -5059,7 +5061,7 @@ process_partial_specialization (tree decl)
   if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
       && (!flag_concepts
          || !strictly_subsumes (current_template_constraints (),
-                                inner_args, maintmpl)))
+                                main_args, maintmpl)))
     {
       if (!flag_concepts)
         error ("partial specialization %q+D does not specialize "
@@ -5241,8 +5243,6 @@ process_partial_specialization (tree decl)
   // Build the template decl.
   tree tmpl = build_template_decl (decl, current_template_parms,
                                   DECL_MEMBER_TEMPLATE_P (maintmpl));
-  TREE_TYPE (tmpl) = type;
-  DECL_TEMPLATE_RESULT (tmpl) = decl;
   SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
   DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
   DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl;
@@ -5705,8 +5705,7 @@ push_template_decl_real (tree decl, bool is_friend)
          template <typename T> friend void A<T>::f();
        is not primary.  */
     is_primary = false;
-  else if (TREE_CODE (decl) == TYPE_DECL
-          && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+  else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
     is_primary = false;
   else
     is_primary = template_parm_scope_p ();
@@ -5845,8 +5844,7 @@ push_template_decl_real (tree decl, bool is_friend)
   if (!ctx
       || TREE_CODE (ctx) == FUNCTION_DECL
       || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
-      || (TREE_CODE (decl) == TYPE_DECL
-         && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+      || (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
       || (is_friend && !DECL_TEMPLATE_INFO (decl)))
     {
       if (DECL_LANG_SPECIFIC (decl)
@@ -5918,8 +5916,6 @@ push_template_decl_real (tree decl, bool is_friend)
          new_tmpl
            = build_template_decl (decl, current_template_parms,
                                   member_template_p);
-         DECL_TEMPLATE_RESULT (new_tmpl) = decl;
-         TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
          DECL_TI_TEMPLATE (decl) = new_tmpl;
          SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
          DECL_TEMPLATE_INFO (new_tmpl)
@@ -5989,27 +5985,33 @@ push_template_decl_real (tree decl, bool is_friend)
        }
     }
 
-  DECL_TEMPLATE_RESULT (tmpl) = decl;
-  TREE_TYPE (tmpl) = TREE_TYPE (decl);
+  gcc_checking_assert (DECL_TEMPLATE_RESULT (tmpl) == decl);
 
-  /* Push template declarations for global functions and types.  Note
-     that we do not try to push a global template friend declared in a
-     template class; such a thing may well depend on the template
-     parameters of the class.  */
-  if (new_template_p && !ctx
-      && !(is_friend && template_class_depth (current_class_type) > 0))
+  if (new_template_p)
     {
-      tmpl = pushdecl_namespace_level (tmpl, is_friend);
-      if (tmpl == error_mark_node)
-       return error_mark_node;
-
-      /* Hide template friend classes that haven't been declared yet.  */
-      if (is_friend && TREE_CODE (decl) == TYPE_DECL)
+      /* Push template declarations for global functions and types.
+        Note that we do not try to push a global template friend
+        declared in a template class; such a thing may well depend on
+        the template parameters of the class and we'll push it when
+        instantiating the befriending class.  */
+      if (!ctx
+         && !(is_friend && template_class_depth (current_class_type) > 0))
        {
-         DECL_ANTICIPATED (tmpl) = 1;
-         DECL_FRIEND_P (tmpl) = 1;
+         tmpl = pushdecl_namespace_level (tmpl, is_friend);
+         if (tmpl == error_mark_node)
+           return error_mark_node;
+
+         /* Hide template friend classes that haven't been declared yet.  */
+         if (is_friend && TREE_CODE (decl) == TYPE_DECL)
+           {
+             DECL_ANTICIPATED (tmpl) = 1;
+             DECL_FRIEND_P (tmpl) = 1;
+           }
        }
     }
+  else
+    /* The type may have been completed, or (erroneously) changed.  */
+    TREE_TYPE (tmpl) = TREE_TYPE (decl);
 
   if (is_primary)
     {
@@ -6095,8 +6097,6 @@ add_inherited_template_parms (tree fn, tree inherited)
   tree tmpl = build_template_decl (fn, parms, /*member*/true);
   tree args = template_parms_to_args (parms);
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
-  TREE_TYPE (tmpl) = TREE_TYPE (fn);
-  DECL_TEMPLATE_RESULT (tmpl) = fn;
   DECL_ARTIFICIAL (tmpl) = true;
   DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
   return tmpl;
@@ -6908,7 +6908,9 @@ template_parm_object_p (const_tree t)
 }
 
 /* Subroutine of convert_nontype_argument, to check whether EXPR, as an
-   argument for TYPE, points to an unsuitable object.  */
+   argument for TYPE, points to an unsuitable object.
+
+   Also adjust the type of the index in C++20 array subobject references.  */
 
 static bool
 invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
@@ -6936,6 +6938,19 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
       {
        tree decl = TREE_OPERAND (expr, 0);
 
+       if (cxx_dialect >= cxx20)
+         while (TREE_CODE (decl) == COMPONENT_REF
+                || TREE_CODE (decl) == ARRAY_REF)
+           {
+             tree &op = TREE_OPERAND (decl, 1);
+             if (TREE_CODE (decl) == ARRAY_REF
+                 && TREE_CODE (op) == INTEGER_CST)
+               /* Canonicalize array offsets to ptrdiff_t; how they were
+                  written doesn't matter for subobject identity.  */
+               op = fold_convert (ptrdiff_type_node, op);
+             decl = TREE_OPERAND (decl, 0);
+           }
+
        if (!VAR_P (decl))
          {
            if (complain & tf_error)
@@ -6977,9 +6992,10 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
                     decl);
            return true;
          }
-       else if (!same_type_ignoring_top_level_qualifiers_p
-                (strip_array_types (TREE_TYPE (type)),
-                 strip_array_types (TREE_TYPE (decl))))
+       else if (cxx_dialect < cxx20
+                && !(same_type_ignoring_top_level_qualifiers_p
+                     (strip_array_types (TREE_TYPE (type)),
+                      strip_array_types (TREE_TYPE (decl)))))
          {
            if (complain & tf_error)
              error ("the address of the %qT subobject of %qD is not a "
@@ -7257,7 +7273,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      For a non-type template-parameter of integral or enumeration type,
      integral promotions (_conv.prom_) and integral conversions
      (_conv.integral_) are applied.  */
-  if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+  if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+      || TREE_CODE (type) == REAL_TYPE)
     {
       if (cxx_dialect < cxx11)
        {
@@ -7272,7 +7289,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 
       /* Notice that there are constant expressions like '4 % 0' which
         do not fold into integer constants.  */
-      if (TREE_CODE (expr) != INTEGER_CST && !val_dep_p)
+      if (!CONSTANT_CLASS_P (expr) && !val_dep_p)
        {
          if (complain & tf_error)
            {
@@ -7287,7 +7304,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
                return NULL_TREE;
              /* else cxx_constant_value complained but gave us
                 a real constant, so go ahead.  */
-             if (TREE_CODE (expr) != INTEGER_CST)
+             if (!CONSTANT_CLASS_P (expr))
                {
                  /* Some assemble time constant expressions like
                     (intptr_t)&&lab1 - (intptr_t)&&lab2 or
@@ -7297,7 +7314,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
                     compile time.  Refuse them here.  */
                  gcc_checking_assert (reduced_constant_expression_p (expr));
                  error_at (loc, "template argument %qE for type %qT not "
-                                "a constant integer", expr, type);
+                                "a compile-time constant", expr, type);
                  return NULL_TREE;
                }
            }
@@ -9094,22 +9111,22 @@ template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
   if (class_nttp_const_wrapper_p (ot))
     ot = TREE_OPERAND (ot, 0);
 
-  if (TREE_CODE (nt) == TREE_VEC)
+  if (TREE_CODE (nt) == TREE_VEC || TREE_CODE (ot) == TREE_VEC)
     /* For member templates */
-    return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
-  else if (PACK_EXPANSION_P (ot))
-    return (PACK_EXPANSION_P (nt)
+    return TREE_CODE (ot) == TREE_CODE (nt) && comp_template_args (ot, nt);
+  else if (PACK_EXPANSION_P (ot) || PACK_EXPANSION_P (nt))
+    return (PACK_EXPANSION_P (ot) && PACK_EXPANSION_P (nt)
            && template_args_equal (PACK_EXPANSION_PATTERN (ot),
                                    PACK_EXPANSION_PATTERN (nt))
            && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
                                    PACK_EXPANSION_EXTRA_ARGS (nt)));
   else if (ARGUMENT_PACK_P (ot) || ARGUMENT_PACK_P (nt))
     return cp_tree_equal (ot, nt);
-  else if (ot && TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
+  else if (TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
     gcc_unreachable ();
-  else if (TYPE_P (nt))
+  else if (TYPE_P (nt) || TYPE_P (ot))
     {
-      if (!TYPE_P (ot))
+      if (!(TYPE_P (nt) && TYPE_P (ot)))
        return false;
       /* Don't treat an alias template specialization with dependent
         arguments as equivalent to its underlying type when used as a
@@ -9127,8 +9144,6 @@ template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
       else
        return same_type_p (ot, nt);
     }
-  else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
-    return 0;
   else
     {
       /* Try to treat a template non-type argument that has been converted
@@ -9138,6 +9153,7 @@ template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
             || code1 == NON_LVALUE_EXPR;
           code1 = TREE_CODE (ot))
        ot = TREE_OPERAND (ot, 0);
+
       for (enum tree_code code2 = TREE_CODE (nt);
           CONVERT_EXPR_CODE_P (code2)
             || code2 == NON_LVALUE_EXPR;
@@ -9927,7 +9943,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 
       /* If we called start_enum or pushtag above, this information
         will already be set up.  */
-      if (!TYPE_NAME (t))
+      type_decl = TYPE_NAME (t);
+      if (!type_decl)
        {
          TYPE_CONTEXT (t) = FROB_CONTEXT (context);
 
@@ -9936,8 +9953,6 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
          DECL_SOURCE_LOCATION (type_decl)
            = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
        }
-      else
-       type_decl = TYPE_NAME (t);
 
       if (CLASS_TYPE_P (template_type))
        {
@@ -10156,6 +10171,8 @@ finish_template_variable (tree var, tsubst_flags_t complain)
   arglist = coerce_innermost_template_parms (parms, arglist, templ, complain,
                                             /*req_all*/true,
                                             /*use_default*/true);
+  if (arglist == error_mark_node)
+    return error_mark_node;
 
   if (flag_concepts && !constraints_satisfied_p (templ, arglist))
     {
@@ -10909,6 +10926,8 @@ tsubst_friend_function (tree decl, tree args)
     }
 
   new_friend = tsubst (decl, args, tf_warning_or_error, NULL_TREE);
+  if (new_friend == error_mark_node)
+    return error_mark_node;
 
   /* The NEW_FRIEND will look like an instantiation, to the
      compiler, but is not an instantiation from the point of view of
@@ -10920,11 +10939,9 @@ tsubst_friend_function (tree decl, tree args)
 
      Then, in S<int>, template <class U> void f(int, U) is not an
      instantiation of anything.  */
-  if (new_friend == error_mark_node)
-    return error_mark_node;
 
   DECL_USE_TEMPLATE (new_friend) = 0;
-  if (TREE_CODE (decl) == TEMPLATE_DECL)
+  if (TREE_CODE (new_friend) == TEMPLATE_DECL)
     {
       DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
       DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
@@ -10951,29 +10968,27 @@ tsubst_friend_function (tree decl, tree args)
   if (DECL_NAMESPACE_SCOPE_P (new_friend))
     {
       tree old_decl;
-      tree new_friend_template_info;
-      tree new_friend_result_template_info;
       tree ns;
-      int  new_friend_is_defn;
 
       /* We must save some information from NEW_FRIEND before calling
         duplicate decls since that function will free NEW_FRIEND if
         possible.  */
-      new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
-      new_friend_is_defn =
-           (DECL_INITIAL (DECL_TEMPLATE_RESULT
-                          (template_for_substitution (new_friend)))
-            != NULL_TREE);
+      tree new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
+      tree new_friend_result_template_info = NULL_TREE;
+      bool new_friend_is_defn =
+       (DECL_INITIAL (DECL_TEMPLATE_RESULT
+                      (template_for_substitution (new_friend)))
+        != NULL_TREE);
+      tree not_tmpl = new_friend;
+
       if (TREE_CODE (new_friend) == TEMPLATE_DECL)
        {
          /* This declaration is a `primary' template.  */
          DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
 
-         new_friend_result_template_info
-           = DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
+         not_tmpl = DECL_TEMPLATE_RESULT (new_friend);
+         new_friend_result_template_info = DECL_TEMPLATE_INFO (not_tmpl);
        }
-      else
-       new_friend_result_template_info = NULL_TREE;
 
       /* Inside pushdecl_namespace_level, we will push into the
         current namespace. However, the friend function should go
@@ -11215,6 +11230,16 @@ tsubst_friend_class (tree friend_tmpl, tree args)
          DECL_ANTICIPATED (tmpl)
            = DECL_ANTICIPATED (DECL_TEMPLATE_RESULT (tmpl)) = true;
 
+         /* Substitute into and set the constraints on the new declaration.  */
+         if (tree ci = get_constraints (friend_tmpl))
+           {
+             ++processing_template_decl;
+             ci = tsubst_constraint_info (ci, args, tf_warning_or_error,
+                                          DECL_FRIEND_CONTEXT (friend_tmpl));
+             --processing_template_decl;
+             set_constraints (tmpl, ci);
+           }
+
          /* Inject this template into the enclosing namspace scope.  */
          tmpl = pushdecl_namespace_level (tmpl, true);
        }
@@ -11506,43 +11531,35 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
     }
 }
 
-/* Perform (or defer) access check for typedefs that were referenced
-   from within the template TMPL code.
-   This is a subroutine of instantiate_decl and instantiate_class_template.
-   TMPL is the template to consider and TARGS is the list of arguments of
-   that template.  */
+/* The template TMPL is being instantiated with the template arguments TARGS.
+   Perform the access checks that we deferred when parsing the template.  */
 
 static void
-perform_typedefs_access_check (tree tmpl, tree targs)
+perform_instantiation_time_access_checks (tree tmpl, tree targs)
 {
   unsigned i;
-  qualified_typedef_usage_t *iter;
+  deferred_access_check *chk;
 
-  if (!tmpl
-      || (!CLASS_TYPE_P (tmpl)
-         && TREE_CODE (tmpl) != FUNCTION_DECL))
+  if (!CLASS_TYPE_P (tmpl) && TREE_CODE (tmpl) != FUNCTION_DECL)
     return;
 
-  FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (tmpl), i, iter)
-    {
-      tree type_decl = iter->typedef_decl;
-      tree type_scope = iter->context;
-
-      if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
-       continue;
-
-      if (uses_template_parms (type_decl))
-       type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
-      if (uses_template_parms (type_scope))
-       type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
-
-      /* Make access check error messages point to the location
-         of the use of the typedef.  */
-      iloc_sentinel ils (iter->locus);
-      perform_or_defer_access_check (TYPE_BINFO (type_scope),
-                                    type_decl, type_decl,
-                                    tf_warning_or_error);
-    }
+  if (vec<deferred_access_check, va_gc> *access_checks
+      = TI_DEFERRED_ACCESS_CHECKS (get_template_info (tmpl)))
+    FOR_EACH_VEC_ELT (*access_checks, i, chk)
+      {
+       tree decl = chk->decl;
+       tree diag_decl = chk->diag_decl;
+       tree type_scope = TREE_TYPE (chk->binfo);
+
+       if (uses_template_parms (type_scope))
+         type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+
+       /* Make access check error messages point to the location
+          of the use of the typedef.  */
+       iloc_sentinel ils (chk->loc);
+       perform_or_defer_access_check (TYPE_BINFO (type_scope),
+                                      decl, diag_decl, tf_warning_or_error);
+      }
 }
 
 static tree
@@ -11752,13 +11769,10 @@ instantiate_class_template_1 (tree type)
                continue;
 
              /* Build new CLASSTYPE_NESTED_UTDS.  */
+             bool class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
+                                      && TYPE_LANG_SPECIFIC (t)
+                                      && CLASSTYPE_IS_TEMPLATE (t));
 
-             tree newtag;
-             bool class_template_p;
-
-             class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
-                                 && TYPE_LANG_SPECIFIC (t)
-                                 && CLASSTYPE_IS_TEMPLATE (t));
              /* If the member is a class template, then -- even after
                 substitution -- there may be dependent types in the
                 template argument list for the class.  We increment
@@ -11767,7 +11781,7 @@ instantiate_class_template_1 (tree type)
                 when outside of a template.  */
              if (class_template_p)
                ++processing_template_decl;
-             newtag = tsubst (t, args, tf_error, NULL_TREE);
+             tree newtag = tsubst (t, args, tf_error, NULL_TREE);
              if (class_template_p)
                --processing_template_decl;
              if (newtag == error_mark_node)
@@ -11834,6 +11848,7 @@ instantiate_class_template_1 (tree type)
                  tree vec = NULL_TREE;
                  int len = 1;
 
+                 gcc_checking_assert (TREE_CODE (t) != CONST_DECL);
                  /* The file and line for this declaration, to
                     assist in error message reporting.  Since we
                     called push_tinst_level above, we don't need to
@@ -12072,11 +12087,7 @@ instantiate_class_template_1 (tree type)
      definitions or default arguments, of the class member functions,
      member classes, static data members and member templates....  */
 
-  /* Some typedefs referenced from within the template code need to be access
-     checked at template instantiation time, i.e now. These types were
-     added to the template at parsing time. Let's get those and perform
-     the access checks then.  */
-  perform_typedefs_access_check (pattern, args);
+  perform_instantiation_time_access_checks (pattern, args);
   perform_deferred_access_checks (tf_warning_or_error);
   pop_nested_class ();
   maximum_field_alignment = saved_maximum_field_alignment;
@@ -12855,6 +12866,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
           template_parm_level_and_index (parm_pack, &level, &idx);
           if (level <= levels)
             arg_pack = TMPL_ARG (args, level, idx);
+
+         if (arg_pack && TREE_CODE (arg_pack) == TEMPLATE_TYPE_PARM
+             && TEMPLATE_TYPE_PARAMETER_PACK (arg_pack))
+           arg_pack = NULL_TREE;
         }
 
       orig_arg = arg_pack;
@@ -13067,8 +13082,8 @@ static tree
 make_argument_pack (tree vec)
 {
   tree pack;
-  tree elt = TREE_VEC_ELT (vec, 0);
-  if (TYPE_P (elt))
+
+  if (TYPE_P (TREE_VEC_ELT (vec, 0)))
     pack = cxx_make_type (TYPE_ARGUMENT_PACK);
   else
     {
@@ -13408,6 +13423,11 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
   if (TREE_CODE (arg) == DEFERRED_PARSE)
     return arg;
 
+  /* Shortcut {}.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (arg)
+      && CONSTRUCTOR_NELTS (arg) == 0)
+    return arg;
+
   tree parm = FUNCTION_FIRST_USER_PARM (fn);
   parm = chain_index (parmnum, parm);
   tree parmtype = TREE_TYPE (parm);
@@ -13856,7 +13876,10 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
      don't substitute through the constraints; that's only done when
      they are checked.  */
   if (tree ci = get_constraints (t))
-    set_constraints (r, ci);
+    /* Unless we're regenerating a lambda, in which case we'll set the
+       lambda's constraints in tsubst_lambda_expr.  */
+    if (!lambda_fntype)
+      set_constraints (r, ci);
 
   if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
     SET_DECL_FRIEND_CONTEXT (r,
@@ -13917,7 +13940,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
         If it isn't, that'll be handled by
         clone_constructors_and_destructors.  */
       if (PRIMARY_TEMPLATE_P (gen_tmpl))
-       clone_function_decl (r, /*update_methods=*/false);
+       clone_cdtor (r, /*update_methods=*/false);
     }
   else if ((complain & tf_error) != 0
           && IDENTIFIER_ANY_OP_P (DECL_NAME (r))
@@ -14042,52 +14065,50 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
     = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
                             complain);
 
-  if (TREE_CODE (decl) == TYPE_DECL
-      && !TYPE_DECL_ALIAS_P (decl))
+  bool class_p = false;
+  tree inner = decl;
+  ++processing_template_decl;
+  if (TREE_CODE (inner) == FUNCTION_DECL)
+    inner = tsubst_function_decl (inner, args, complain, lambda_fntype);
+  else
     {
-      tree new_type;
-      ++processing_template_decl;
-      new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-      --processing_template_decl;
-      if (new_type == error_mark_node)
-       return error_mark_node;
+      if (TREE_CODE (inner) == TYPE_DECL && !TYPE_DECL_ALIAS_P (inner))
+       {
+         class_p = true;
+         inner = TREE_TYPE (inner);
+       }
+      inner = tsubst (inner, args, complain, in_decl);
+    }
+  --processing_template_decl;
+  if (inner == error_mark_node)
+    return error_mark_node;
 
-      TREE_TYPE (r) = new_type;
+  if (class_p)
+    {
       /* For a partial specialization, we need to keep pointing to
         the primary template.  */
       if (!DECL_TEMPLATE_SPECIALIZATION (t))
-       CLASSTYPE_TI_TEMPLATE (new_type) = r;
-      DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
-      DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
-      DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);
+       CLASSTYPE_TI_TEMPLATE (inner) = r;
+
+      DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (inner);
+      inner = TYPE_MAIN_DECL (inner);
+    }
+  else if (lambda_fntype)
+    {
+      tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (r));
+      DECL_TEMPLATE_INFO (inner) = build_template_info (r, args);
     }
   else
     {
-      tree new_decl;
-      ++processing_template_decl;
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       new_decl = tsubst_function_decl (decl, args, complain, lambda_fntype);
-      else
-       new_decl = tsubst (decl, args, complain, in_decl);
-      --processing_template_decl;
-      if (new_decl == error_mark_node)
-       return error_mark_node;
-
-      DECL_TEMPLATE_RESULT (r) = new_decl;
-      TREE_TYPE (r) = TREE_TYPE (new_decl);
-      DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);
-      if (lambda_fntype)
-       {
-         tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (r));
-         DECL_TEMPLATE_INFO (new_decl) = build_template_info (r, args);
-       }
-      else
-       {
-         DECL_TI_TEMPLATE (new_decl) = r;
-         DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
-       }
+      if (TREE_CODE (decl) != TYPE_DECL || !TYPE_DECL_ALIAS_P (decl))
+       DECL_TI_TEMPLATE (inner) = r;
+      DECL_TI_ARGS (r) = DECL_TI_ARGS (inner);
     }
 
+  DECL_TEMPLATE_RESULT (r) = inner;
+  TREE_TYPE (r) = TREE_TYPE (inner);
+  DECL_CONTEXT (r) = DECL_CONTEXT (inner);
+
   DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
   DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
 
@@ -14634,7 +14655,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                         && DECL_BIT_FIELD_TYPE (TREE_OPERAND (ve, 1)) == type)
                  type = TREE_TYPE (ve);
                else
-                 gcc_checking_assert (TREE_TYPE (ve) == type);
+                 gcc_checking_assert (TYPE_MAIN_VARIANT (TREE_TYPE (ve))
+                                      == TYPE_MAIN_VARIANT (type));
                SET_DECL_VALUE_EXPR (r, ve);
              }
            if (CP_DECL_THREAD_LOCAL_P (r)
@@ -15057,6 +15079,94 @@ tsubst_exception_specification (tree fntype,
   return new_specs;
 }
 
+/* Substitute through a TREE_LIST of types or expressions, handling pack
+   expansions.  */
+
+tree
+tsubst_tree_list (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+  if (t == void_list_node)
+    return t;
+
+  tree purpose = TREE_PURPOSE (t);
+  tree purposevec = NULL_TREE;
+  if (!purpose)
+    ;
+  else if (PACK_EXPANSION_P (purpose))
+    {
+      purpose = tsubst_pack_expansion (purpose, args, complain, in_decl);
+      if (TREE_CODE (purpose) == TREE_VEC)
+       purposevec = purpose;
+    }
+  else if (TYPE_P (purpose))
+    purpose = tsubst (purpose, args, complain, in_decl);
+  else
+    purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
+  if (purpose == error_mark_node || purposevec == error_mark_node)
+    return error_mark_node;
+
+  tree value = TREE_VALUE (t);
+  tree valuevec = NULL_TREE;
+  if (!value)
+    ;
+  else if (PACK_EXPANSION_P (value))
+    {
+      value = tsubst_pack_expansion (value, args, complain, in_decl);
+      if (TREE_CODE (value) == TREE_VEC)
+       valuevec = value;
+    }
+  else if (TYPE_P (value))
+    value = tsubst (value, args, complain, in_decl);
+  else
+    value = tsubst_copy_and_build (value, args, complain, in_decl);
+  if (value == error_mark_node || valuevec == error_mark_node)
+    return error_mark_node;
+
+  tree chain = TREE_CHAIN (t);
+  if (!chain)
+    ;
+  else if (TREE_CODE (chain) == TREE_LIST)
+    chain = tsubst_tree_list (chain, args, complain, in_decl);
+  else if (TYPE_P (chain))
+    chain = tsubst (chain, args, complain, in_decl);
+  else
+    chain = tsubst_copy_and_build (chain, args, complain, in_decl);
+  if (chain == error_mark_node)
+    return error_mark_node;
+
+  if (purpose == TREE_PURPOSE (t)
+      && value == TREE_VALUE (t)
+      && chain == TREE_CHAIN (t))
+    return t;
+
+  int len;
+  /* Determine the number of arguments.  */
+  if (purposevec)
+    {
+      len = TREE_VEC_LENGTH (purposevec);
+      gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
+    }
+  else if (valuevec)
+    len = TREE_VEC_LENGTH (valuevec);
+  else
+    len = 1;
+
+  for (int i = len; i-- > 0; )
+    {
+      if (purposevec)
+       purpose = TREE_VEC_ELT (purposevec, i);
+      if (valuevec)
+       value = TREE_VEC_ELT (valuevec, i);
+
+      if (value && TYPE_P (value))
+       chain = hash_tree_cons (purpose, value, chain);
+      else
+       chain = tree_cons (purpose, value, chain);
+    }
+
+  return chain;
+}
+
 /* Take the tree structure T and replace template parameters used
    therein with the argument vector ARGS.  IN_DECL is an associated
    decl for diagnostics.  If an error occurs, returns ERROR_MARK_NODE.
@@ -15476,104 +15586,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       }
 
     case TREE_LIST:
-      {
-       tree purpose, value, chain;
-
-       if (t == void_list_node)
-         return t;
-
-       if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
-           || (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
-         {
-           /* We have pack expansions, so expand those and
-              create a new list out of it.  */
-
-           /* Expand the argument expressions.  */
-           tree purposevec = NULL_TREE;
-           if (TREE_PURPOSE (t))
-             purposevec = tsubst_pack_expansion (TREE_PURPOSE (t), args,
-                                                 complain, in_decl);
-           if (purposevec == error_mark_node)
-             return error_mark_node;
-
-           tree valuevec = NULL_TREE;
-           if (TREE_VALUE (t))
-             valuevec = tsubst_pack_expansion (TREE_VALUE (t), args,
-                                               complain, in_decl);
-           if (valuevec == error_mark_node)
-             return error_mark_node;
-
-           /* Build the rest of the list.  */
-           tree chain = TREE_CHAIN (t);
-           if (chain && chain != void_type_node)
-             chain = tsubst (chain, args, complain, in_decl);
-           if (chain == error_mark_node)
-             return error_mark_node;
-
-           /* Determine the number of arguments.  */
-           int len = -1;
-           if (purposevec && TREE_CODE (purposevec) == TREE_VEC)
-             {
-               len = TREE_VEC_LENGTH (purposevec);
-               gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
-             }
-           else if (TREE_CODE (valuevec) == TREE_VEC)
-             len = TREE_VEC_LENGTH (valuevec);
-           else
-             {
-               /* Since we only performed a partial substitution into
-                  the argument pack, we only RETURN (a single list
-                  node.  */
-               if (purposevec == TREE_PURPOSE (t)
-                   && valuevec == TREE_VALUE (t)
-                   && chain == TREE_CHAIN (t))
-                 return t;
-
-               return tree_cons (purposevec, valuevec, chain);
-             }
-
-           /* Convert the argument vectors into a TREE_LIST.  */
-           for (int i = len; i-- > 0; )
-             {
-               purpose = (purposevec ? TREE_VEC_ELT (purposevec, i)
-                          : NULL_TREE);
-               value = (valuevec ? TREE_VEC_ELT (valuevec, i)
-                        : NULL_TREE);
-
-               /* Build the list (backwards).  */
-               chain = hash_tree_cons (purpose, value, chain);
-             }
-
-           return chain;
-         }
-
-       purpose = TREE_PURPOSE (t);
-       if (purpose)
-         {
-           purpose = tsubst (purpose, args, complain, in_decl);
-           if (purpose == error_mark_node)
-             return error_mark_node;
-         }
-       value = TREE_VALUE (t);
-       if (value)
-         {
-           value = tsubst (value, args, complain, in_decl);
-           if (value == error_mark_node)
-             return error_mark_node;
-         }
-       chain = TREE_CHAIN (t);
-       if (chain && chain != void_type_node)
-         {
-           chain = tsubst (chain, args, complain, in_decl);
-           if (chain == error_mark_node)
-             return error_mark_node;
-         }
-       if (purpose == TREE_PURPOSE (t)
-           && value == TREE_VALUE (t)
-           && chain == TREE_CHAIN (t))
-         return t;
-       return hash_tree_cons (purpose, value, chain);
-      }
+      return tsubst_tree_list (t, args, complain, in_decl);
 
     case TREE_BINFO:
       /* We should never be tsubsting a binfo.  */
@@ -16035,7 +16048,8 @@ tsubst_baselink (tree baselink, tree object_type,
        /* Treat as-if non-dependent below.  */
        dependent_p = false;
 
-      baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
+      baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1,
+                                 complain);
       if (!baselink)
        {
          if ((complain & tf_error)
@@ -17463,7 +17477,16 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
       else
        decl = RECUR (decl);
     }
-  init = RECUR (init);
+  if (init && TREE_CODE (init) == TREE_VEC)
+    {
+      init = copy_node (init);
+      TREE_VEC_ELT (init, 0)
+       = tsubst_decl (TREE_VEC_ELT (init, 0), args, complain);
+      TREE_VEC_ELT (init, 1) = RECUR (TREE_VEC_ELT (init, 1));
+      TREE_VEC_ELT (init, 2) = RECUR (TREE_VEC_ELT (init, 2));
+    }
+  else
+    init = RECUR (init);
 
   if (orig_declv && OMP_FOR_ORIG_DECLS (t))
     {
@@ -17515,7 +17538,21 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
 
       if (!range_for)
        {
-         cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
+         cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
+         if (COMPARISON_CLASS_P (cond)
+             && TREE_CODE (TREE_OPERAND (cond, 1)) == TREE_VEC)
+           {
+             tree lhs = RECUR (TREE_OPERAND (cond, 0));
+             tree rhs = copy_node (TREE_OPERAND (cond, 1));
+             TREE_VEC_ELT (rhs, 0)
+               = tsubst_decl (TREE_VEC_ELT (rhs, 0), args, complain);
+             TREE_VEC_ELT (rhs, 1) = RECUR (TREE_VEC_ELT (rhs, 1));
+             TREE_VEC_ELT (rhs, 2) = RECUR (TREE_VEC_ELT (rhs, 2));
+             cond = build2 (TREE_CODE (cond), TREE_TYPE (cond),
+                            lhs, rhs);       
+           }
+         else
+           cond = RECUR (cond);
          incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
          if (TREE_CODE (incr) == MODIFY_EXPR)
            {
@@ -17998,6 +18035,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                    if (ndecl != error_mark_node)
                      cp_maybe_mangle_decomp (ndecl, first, cnt);
 
+                   /* In a non-template function, VLA type declarations are
+                      handled in grokdeclarator; for templates, handle them
+                      now.  */
+                   predeclare_vla (decl);
+
                    cp_finish_decl (decl, init, const_init, NULL_TREE,
                                    constinit_p ? LOOKUP_CONSTINIT : 0);
 
@@ -18490,6 +18532,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
          stmt = pop_stmt_list (stmt);
        }
 
+      if (TREE_CODE (t) == OMP_CRITICAL
+         && tmp != NULL_TREE
+         && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (tmp)))
+       {
+         error_at (OMP_CLAUSE_LOCATION (tmp),
+                   "%<#pragma omp critical%> with %<hint%> clause requires "
+                   "a name, except when %<omp_sync_hint_none%> is used");
+         RETURN (error_mark_node);
+       }
       t = copy_node (t);
       OMP_BODY (t) = stmt;
       OMP_CLAUSES (t) = tmp;
@@ -19041,6 +19092,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          finish_member_declaration (fn);
        }
 
+      if (tree ci = get_constraints (oldfn))
+       {
+         /* Substitute into the lambda's constraints.  */
+         if (oldtmpl)
+           ++processing_template_decl;
+         ci = tsubst_constraint_info (ci, args, complain, in_decl);
+         if (oldtmpl)
+           --processing_template_decl;
+         set_constraints (fn, ci);
+       }
+
       /* Let finish_function set this.  */
       DECL_DECLARED_CONSTEXPR_P (fn) = false;
 
@@ -19350,6 +19412,8 @@ tsubst_copy_and_build (tree t,
            break;
          case STATIC_CAST_EXPR:
            r = build_static_cast (input_location, type, op, complain);
+           if (IMPLICIT_RVALUE_P (t))
+             set_implicit_rvalue_p (r);
            break;
          default:
            gcc_unreachable ();
@@ -19608,6 +19672,8 @@ tsubst_copy_and_build (tree t,
 
        if (placement == NULL_TREE)
          placement_vec = NULL;
+       else if (placement == error_mark_node)
+         RETURN (error_mark_node);
        else
          {
            placement_vec = make_tree_vector ();
@@ -20090,90 +20156,7 @@ tsubst_copy_and_build (tree t,
       }
 
     case TREE_LIST:
-      {
-       tree purpose, value, chain;
-
-       if (t == void_list_node)
-         RETURN (t);
-
-        if ((TREE_PURPOSE (t) && PACK_EXPANSION_P (TREE_PURPOSE (t)))
-            || (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))))
-          {
-            /* We have pack expansions, so expand those and
-               create a new list out of it.  */
-            tree purposevec = NULL_TREE;
-            tree valuevec = NULL_TREE;
-            tree chain;
-            int i, len = -1;
-
-            /* Expand the argument expressions.  */
-            if (TREE_PURPOSE (t))
-              purposevec = tsubst_pack_expansion (TREE_PURPOSE (t), args,
-                                                 complain, in_decl);
-            if (TREE_VALUE (t))
-              valuevec = tsubst_pack_expansion (TREE_VALUE (t), args,
-                                               complain, in_decl);
-
-            /* Build the rest of the list.  */
-            chain = TREE_CHAIN (t);
-            if (chain && chain != void_type_node)
-              chain = RECUR (chain);
-
-            /* Determine the number of arguments.  */
-            if (purposevec && TREE_CODE (purposevec) == TREE_VEC)
-              {
-                len = TREE_VEC_LENGTH (purposevec);
-                gcc_assert (!valuevec || len == TREE_VEC_LENGTH (valuevec));
-              }
-            else if (TREE_CODE (valuevec) == TREE_VEC)
-              len = TREE_VEC_LENGTH (valuevec);
-            else
-              {
-                /* Since we only performed a partial substitution into
-                   the argument pack, we only RETURN (a single list
-                   node.  */
-                if (purposevec == TREE_PURPOSE (t)
-                    && valuevec == TREE_VALUE (t)
-                    && chain == TREE_CHAIN (t))
-                  RETURN (t);
-
-                RETURN (tree_cons (purposevec, valuevec, chain));
-              }
-
-            /* Convert the argument vectors into a TREE_LIST */
-            i = len;
-            while (i > 0)
-              {
-                /* Grab the Ith values.  */
-                i--;
-                purpose = purposevec ? TREE_VEC_ELT (purposevec, i) 
-                                    : NULL_TREE;
-                value 
-                 = valuevec ? convert_from_reference (TREE_VEC_ELT (valuevec, i))
-                             : NULL_TREE;
-
-                /* Build the list (backwards).  */
-                chain = tree_cons (purpose, value, chain);
-              }
-
-            RETURN (chain);
-          }
-
-       purpose = TREE_PURPOSE (t);
-       if (purpose)
-         purpose = RECUR (purpose);
-       value = TREE_VALUE (t);
-       if (value)
-         value = RECUR (value);
-       chain = TREE_CHAIN (t);
-       if (chain && chain != void_type_node)
-         chain = RECUR (chain);
-       if (purpose == TREE_PURPOSE (t)
-           && value == TREE_VALUE (t)
-           && chain == TREE_CHAIN (t))
-         RETURN (t);
-       RETURN (tree_cons (purpose, value, chain));
-      }
+      RETURN (tsubst_tree_list (t, args, complain, in_decl));
 
     case COMPONENT_REF:
       {
@@ -20714,10 +20697,11 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      but it doesn't seem to be on the hot path.  */
   spec = retrieve_specialization (gen_tmpl, targ_ptr, 0);
 
-  gcc_assert (tmpl == gen_tmpl
-             || ((fndecl = retrieve_specialization (tmpl, orig_args, 0))
-                 == spec)
-             || fndecl == NULL_TREE);
+  gcc_checking_assert (tmpl == gen_tmpl
+                      || ((fndecl
+                           = retrieve_specialization (tmpl, orig_args, 0))
+                          == spec)
+                      || fndecl == NULL_TREE);
 
   if (spec != NULL_TREE)
     {
@@ -20813,7 +20797,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      instantiating the template clones.  */
   if (tree chain = DECL_CHAIN (gen_tmpl))
     if (DECL_P (chain) && DECL_CLONED_FUNCTION_P (chain))
-      clone_function_decl (fndecl, /*update_methods=*/false);
+      clone_cdtor (fndecl, /*update_methods=*/false);
 
   if (!access_ok)
     {
@@ -21092,7 +21076,7 @@ fn_type_unification (tree fn,
       /* Adjust any explicit template arguments before entering the
         substitution context.  */
       explicit_targs
-       = (coerce_template_parms (tparms, explicit_targs, NULL_TREE,
+       = (coerce_template_parms (tparms, explicit_targs, fn,
                                  complain|tf_partial,
                                  /*require_all_args=*/false,
                                  /*use_default_args=*/false));
@@ -22794,7 +22778,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
               TREE_CONSTANT (result) = 1;
             }
           else
-            result = cxx_make_type (TYPE_ARGUMENT_PACK);
+           result = cxx_make_type (TYPE_ARGUMENT_PACK);
 
           SET_ARGUMENT_PACK_ARGS (result, new_args);
 
@@ -22818,7 +22802,15 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
        {
          tree bad_old_arg = NULL_TREE, bad_new_arg = NULL_TREE;
          tree old_args = ARGUMENT_PACK_ARGS (old_pack);
-
+         temp_override<int> ovl (TREE_VEC_LENGTH (old_args));
+         /* During template argument deduction for the aggregate deduction
+            candidate, the number of elements in a trailing parameter pack
+            is only deduced from the number of remaining function
+            arguments if it is not otherwise deduced.  */
+         if (cxx_dialect >= cxx20
+             && TREE_VEC_LENGTH (new_args) < TREE_VEC_LENGTH (old_args)
+             && builtin_guide_p (TPARMS_PRIMARY_TEMPLATE (tparms)))
+           TREE_VEC_LENGTH (old_args) = TREE_VEC_LENGTH (new_args);
          if (!comp_template_args (old_args, new_args,
                                   &bad_old_arg, &bad_new_arg))
            /* Inconsistent unification of this parameter pack.  */
@@ -24114,7 +24106,15 @@ more_specialized_fn (tree pat1, tree pat2, int len)
 
   /* If both deductions succeed, the partial ordering selects the more
      constrained template.  */
-  if (!lose1 && !lose2)
+  /* P2113: If the corresponding template-parameters of the
+     template-parameter-lists are not equivalent ([temp.over.link]) or if
+     the function parameters that positionally correspond between the two
+     templates are not of the same type, neither template is more
+     specialized than the other.  */
+  if (!lose1 && !lose2
+      && comp_template_parms (DECL_TEMPLATE_PARMS (pat1),
+                             DECL_TEMPLATE_PARMS (pat2))
+      && compparms (origs1, origs2))
     {
       int winner = more_constrained (decl1, decl2);
       if (winner > 0)
@@ -24562,21 +24562,22 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
 
   for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t))
     {
-      tree spec_args;
-      tree spec_tmpl = TREE_VALUE (t);
+      const tree ospec_tmpl = TREE_VALUE (t);
 
+      tree spec_tmpl;
       if (outer_args)
        {
          /* Substitute in the template args from the enclosing class.  */
          ++processing_template_decl;
-         spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE);
+         spec_tmpl = tsubst (ospec_tmpl, outer_args, tf_none, NULL_TREE);
          --processing_template_decl;
+         if (spec_tmpl == error_mark_node)
+           return error_mark_node;
        }
+      else
+       spec_tmpl = ospec_tmpl;
 
-      if (spec_tmpl == error_mark_node)
-       return error_mark_node;
-
-      spec_args = get_partial_spec_bindings (tmpl, spec_tmpl, args);
+      tree spec_args = get_partial_spec_bindings (tmpl, spec_tmpl, args);
       if (spec_args)
        {
          if (outer_args)
@@ -24585,9 +24586,9 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
           /* Keep the candidate only if the constraints are satisfied,
              or if we're not compiling with concepts.  */
           if (!flag_concepts
-              || constraints_satisfied_p (spec_tmpl, spec_args))
+             || constraints_satisfied_p (ospec_tmpl, spec_args))
             {
-              list = tree_cons (spec_args, TREE_VALUE (t), list);
+             list = tree_cons (spec_args, ospec_tmpl, list);
               TREE_TYPE (list) = TREE_TYPE (t);
             }
        }
@@ -24928,23 +24929,22 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
         [temp.explicit]
 
-        The explicit instantiation of a class template specialization
-        implies the instantiation of all of its members not
-        previously explicitly specialized in the translation unit
-        containing the explicit instantiation.
-
-     Of course, we can't instantiate member template classes, since we
-     don't have any arguments for them.  Note that the standard is
-     unclear on whether the instantiation of the members are
-     *explicit* instantiations or not.  However, the most natural
-     interpretation is that it should be an explicit
-     instantiation.  */
+        An explicit instantiation that names a class template
+        specialization is also an explicit instantiation of the same
+        kind (declaration or definition) of each of its members (not
+        including members inherited from base classes and members
+        that are templates) that has not been previously explicitly
+        specialized in the translation unit containing the explicit
+        instantiation, provided that the associated constraints, if
+        any, of that member are satisfied by the template arguments
+        of the explicit instantiation.  */
   for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld))
     if ((VAR_P (fld)
         || (TREE_CODE (fld) == FUNCTION_DECL
             && !static_p
             && user_provided_p (fld)))
-       && DECL_TEMPLATE_INSTANTIATION (fld))
+       && DECL_TEMPLATE_INSTANTIATION (fld)
+       && constraints_satisfied_p (fld))
       {
        mark_decl_instantiated (fld, extern_p);
        if (! extern_p)
@@ -25185,7 +25185,7 @@ always_instantiate_p (tree decl)
 bool
 maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 {
-  tree fntype, spec, noex, clone;
+  tree fntype, spec, noex;
 
   /* Don't instantiate a noexcept-specification from template context.  */
   if (processing_template_decl
@@ -25204,8 +25204,16 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
       return !DECL_MAYBE_DELETED (fn);
     }
 
-  if (DECL_CLONED_FUNCTION_P (fn))
-    fn = DECL_CLONED_FUNCTION (fn);
+  fntype = TREE_TYPE (fn);
+  spec = TYPE_RAISES_EXCEPTIONS (fntype);
+
+  if (!spec || !TREE_PURPOSE (spec))
+    return true;
+
+  noex = TREE_PURPOSE (spec);
+  if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
+      && TREE_CODE (noex) != DEFERRED_PARSE)
+    return true;
 
   tree orig_fn = NULL_TREE;
   /* For a member friend template we can get a TEMPLATE_DECL.  Let's use
@@ -25217,15 +25225,14 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
       fn = DECL_TEMPLATE_RESULT (fn);
     }
 
-  fntype = TREE_TYPE (fn);
-  spec = TYPE_RAISES_EXCEPTIONS (fntype);
-
-  if (!spec || !TREE_PURPOSE (spec))
-    return true;
-
-  noex = TREE_PURPOSE (spec);
-
-  if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
+  if (DECL_CLONED_FUNCTION_P (fn))
+    {
+      tree prime = DECL_CLONED_FUNCTION (fn);
+      if (!maybe_instantiate_noexcept (prime, complain))
+       return false;
+      spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (prime));
+    }
+  else if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
     {
       static hash_set<tree>* fns = new hash_set<tree>;
       bool added = false;
@@ -25295,27 +25302,19 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 
       if (added)
        fns->remove (fn);
-
-      if (spec == error_mark_node)
-       {
-         /* This failed with a hard error, so let's go with false.  */
-         gcc_assert (seen_error ());
-         spec = noexcept_false_spec;
-       }
-
-      TREE_TYPE (fn) = build_exception_variant (fntype, spec);
-      if (orig_fn)
-       TREE_TYPE (orig_fn) = TREE_TYPE (fn);
     }
 
-  FOR_EACH_CLONE (clone, fn)
+  if (spec == error_mark_node)
     {
-      if (TREE_TYPE (clone) == fntype)
-       TREE_TYPE (clone) = TREE_TYPE (fn);
-      else
-       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
+      /* This failed with a hard error, so let's go with false.  */
+      gcc_assert (seen_error ());
+      spec = noexcept_false_spec;
     }
 
+  TREE_TYPE (fn) = build_exception_variant (fntype, spec);
+  if (orig_fn)
+    TREE_TYPE (orig_fn) = TREE_TYPE (fn);
+
   return true;
 }
 
@@ -25397,6 +25396,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
     d = DECL_CLONED_FUNCTION (d);
 
   if (DECL_TEMPLATE_INSTANTIATED (d)
+      || TREE_TYPE (d) == error_mark_node
       || (TREE_CODE (d) == FUNCTION_DECL
          && DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
       || DECL_TEMPLATE_SPECIALIZATION (d))
@@ -25422,13 +25422,14 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
   gen_tmpl = most_general_template (tmpl);
   gen_args = DECL_TI_ARGS (d);
 
-  if (tmpl != gen_tmpl)
-    /* We should already have the extra args.  */
-    gcc_assert (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl))
-               == TMPL_ARGS_DEPTH (gen_args));
+  /* We should already have the extra args.  */
+  gcc_checking_assert (tmpl == gen_tmpl
+                      || (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl))
+                          == TMPL_ARGS_DEPTH (gen_args)));
   /* And what's in the hash table should match D.  */
-  gcc_assert ((spec = retrieve_specialization (gen_tmpl, gen_args, 0)) == d
-             || spec == NULL_TREE);
+  gcc_checking_assert ((spec = retrieve_specialization (gen_tmpl, gen_args, 0))
+                      == d
+                      || spec == NULL_TREE);
 
   /* This needs to happen before any tsubsting.  */
   if (! push_tinst_level (d))
@@ -25693,12 +25694,8 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
       else
        start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
 
-      /* Some typedefs referenced from within the template code need to be
-        access checked at template instantiation time, i.e now. These
-        types were added to the template at parsing time. Let's get those
-        and perform the access checks then.  */
-      perform_typedefs_access_check (DECL_TEMPLATE_RESULT (td),
-                                    args);
+      perform_instantiation_time_access_checks (DECL_TEMPLATE_RESULT (td),
+                                               args);
 
       /* Create substitution entries for the parameters.  */
       register_parameter_specializations (code_pattern, d);
@@ -26157,31 +26154,31 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
   else if (cxx_dialect >= cxx11
           && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
     return false;
-  else if (CLASS_TYPE_P (type))
+  else if (VOID_TYPE_P (type))
+    /* Fall through.  */;
+  else if (cxx_dialect >= cxx20)
     {
-      if (cxx_dialect < cxx20)
-       {
-         if (complain & tf_error)
-           error ("non-type template parameters of class type only available "
-                  "with %<-std=c++20%> or %<-std=gnu++20%>");
-         return true;
-       }
       if (dependent_type_p (type))
        return false;
-      if (!complete_type_or_else (type, NULL_TREE))
+      if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
        return true;
-      if (!structural_type_p (type))
+      if (structural_type_p (type))
+       return false;
+      if (complain & tf_error)
        {
-         if (complain & tf_error)
-           {
-             auto_diagnostic_group d;
-             error ("%qT is not a valid type for a template non-type "
-                    "parameter because it is not structural", type);
-             structural_type_p (type, true);
-           }
-         return true;
+         auto_diagnostic_group d;
+         error ("%qT is not a valid type for a template non-type "
+                "parameter because it is not structural", type);
+         structural_type_p (type, true);
        }
-      return false;
+      return true;
+    }
+  else if (CLASS_TYPE_P (type))
+    {
+      if (complain & tf_error)
+       error ("non-type template parameters of class type only available "
+              "with %<-std=c++20%> or %<-std=gnu++20%>");
+      return true;
     }
 
   if (complain & tf_error)
@@ -26743,8 +26740,7 @@ type_dependent_expression_p (tree expression)
     return true;
 
   /* Some expression forms are never type-dependent.  */
-  if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
-      || TREE_CODE (expression) == SIZEOF_EXPR
+  if (TREE_CODE (expression) == SIZEOF_EXPR
       || TREE_CODE (expression) == ALIGNOF_EXPR
       || TREE_CODE (expression) == AT_ENCODE_EXPR
       || TREE_CODE (expression) == NOEXCEPT_EXPR
@@ -27462,12 +27458,12 @@ resolve_typename_type (tree type, bool only_current_p)
   gcc_checking_assert (uses_template_parms (scope));
 
   /* Usually the non-qualified identifier of a TYPENAME_TYPE is
-     TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
-     a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
-     the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
-     identifier  of the TYPENAME_TYPE anymore.
-     So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
-     TYPENAME_TYPE instead, we avoid messing up with a possible
+     TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of a
+     TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL
+     representing the typedef. In that case TYPE_IDENTIFIER (type) is
+     not the non-qualified identifier of the TYPENAME_TYPE anymore.
+     So by getting the TYPE_IDENTIFIER of the _main declaration_ of
+     the TYPENAME_TYPE instead, we avoid messing up with a possible
      typedef variant case.  */
   name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
 
@@ -27816,7 +27812,7 @@ finish_concept_definition (cp_expr id, tree init)
       return error_mark_node;
     }
 
-  /* Initially build the concept declaration; it's type is bool.  */
+  /* Initially build the concept declaration; its type is bool.  */
   tree decl = build_lang_decl_loc (loc, CONCEPT_DECL, *id, boolean_type_node);
   DECL_CONTEXT (decl) = current_scope ();
   DECL_INITIAL (decl) = init;
@@ -28025,6 +28021,23 @@ template_guide_p (const_tree fn)
   return false;
 }
 
+/* True if FN is an aggregate initialization guide or the copy deduction
+   guide.  */
+
+bool
+builtin_guide_p (const_tree fn)
+{
+  if (!deduction_guide_p (fn))
+    return false;
+  if (!DECL_ARTIFICIAL (fn))
+    /* Explicitly declared.  */
+    return false;
+  if (DECL_ABSTRACT_ORIGIN (fn))
+    /* Derived from a constructor.  */
+    return false;
+  return true;
+}
+
 /* OLDDECL is a _DECL for a template parameter.  Return a similar parameter at
    LEVEL:INDEX, using tsubst_args and complain for substitution into non-type
    template parameter types.  Note that the handling of template template
@@ -28323,8 +28336,6 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com
   DECL_NONCONVERTING_P (ded_fn) = explicit_p;
   tree ded_tmpl = build_template_decl (ded_fn, tparms, /*member*/false);
   DECL_ARTIFICIAL (ded_tmpl) = true;
-  DECL_TEMPLATE_RESULT (ded_tmpl) = ded_fn;
-  TREE_TYPE (ded_tmpl) = TREE_TYPE (ded_fn);
   DECL_TEMPLATE_INFO (ded_fn) = build_template_info (ded_tmpl, targs);
   DECL_PRIMARY_TEMPLATE (ded_tmpl) = ded_tmpl;
   if (DECL_P (ctor))
@@ -28338,22 +28349,48 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com
 /* Add to LIST the member types for the reshaped initializer CTOR.  */
 
 static tree
-collect_ctor_idx_types (tree ctor, tree list)
+collect_ctor_idx_types (tree ctor, tree list, tree elt = NULL_TREE)
 {
   vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (ctor);
   tree idx, val; unsigned i;
   FOR_EACH_CONSTRUCTOR_ELT (v, i, idx, val)
     {
+      tree ftype = elt ? elt : TREE_TYPE (idx);
       if (BRACE_ENCLOSED_INITIALIZER_P (val)
-         && CONSTRUCTOR_NELTS (val))
-       if (tree subidx = CONSTRUCTOR_ELT (val, 0)->index)
-         if (TREE_CODE (subidx) == FIELD_DECL)
-           {
-             list = collect_ctor_idx_types (val, list);
-             continue;
-           }
-      tree ftype = finish_decltype_type (idx, true, tf_none);
-      list = tree_cons (NULL_TREE, ftype, list);
+         && CONSTRUCTOR_NELTS (val)
+         /* As in reshape_init_r, a non-aggregate or array-of-dependent-bound
+            type gets a single initializer.  */
+         && CP_AGGREGATE_TYPE_P (ftype)
+         && !(TREE_CODE (ftype) == ARRAY_TYPE
+              && uses_template_parms (TYPE_DOMAIN (ftype))))
+       {
+         tree subelt = NULL_TREE;
+         if (TREE_CODE (ftype) == ARRAY_TYPE)
+           subelt = TREE_TYPE (ftype);
+         list = collect_ctor_idx_types (val, list, subelt);
+         continue;
+       }
+      tree arg = NULL_TREE;
+      if (i == v->length() - 1
+         && PACK_EXPANSION_P (ftype))
+       /* Give the trailing pack expansion parameter a default argument to
+          match aggregate initialization behavior, even if we deduce the
+          length of the pack separately to more than we have initializers. */
+       arg = build_constructor (init_list_type_node, NULL);
+      /* if ei is of array type and xi is a braced-init-list or string literal,
+        Ti is an rvalue reference to the declared type of ei */
+      STRIP_ANY_LOCATION_WRAPPER (val);
+      if (TREE_CODE (ftype) == ARRAY_TYPE
+         && (BRACE_ENCLOSED_INITIALIZER_P (val)
+             || TREE_CODE (val) == STRING_CST))
+       {
+         if (TREE_CODE (val) == STRING_CST)
+           ftype = cp_build_qualified_type
+             (ftype, cp_type_quals (ftype) | TYPE_QUAL_CONST);
+         ftype = (cp_build_reference_type
+                  (ftype, BRACE_ENCLOSED_INITIALIZER_P (val)));
+       }
+      list = tree_cons (arg, ftype, list);
     }
 
   return list;
@@ -28583,7 +28620,10 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
            }
 
          if (ci)
-           set_constraints (fprime, ci);
+           {
+             remove_constraints (fprime);
+             set_constraints (fprime, ci);
+           }
        }
       else
        {
@@ -28987,6 +29027,12 @@ do_auto_deduction (tree type, tree init, tree auto_node,
            error ("%qT as type rather than plain %<decltype(auto)%>", type);
          return error_mark_node;
        }
+      else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
+       {
+         if (complain & tf_error)
+           error ("%<decltype(auto)%> cannot be cv-qualified");
+         return error_mark_node;
+       }
     }
   else
     {
@@ -29218,126 +29264,6 @@ check_auto_in_tmpl_args (tree tmpl, tree args)
   return errors;
 }
 
-/* For a given template T, return the vector of typedefs referenced
-   in T for which access check is needed at T instantiation time.
-   T is either  a FUNCTION_DECL or a RECORD_TYPE.
-   Those typedefs were added to T by the function
-   append_type_to_template_for_access_check.  */
-
-vec<qualified_typedef_usage_t, va_gc> *
-get_types_needing_access_check (tree t)
-{
-  tree ti;
-  vec<qualified_typedef_usage_t, va_gc> *result = NULL;
-
-  if (!t || t == error_mark_node)
-    return NULL;
-
-  if (!(ti = get_template_info (t)))
-    return NULL;
-
-  if (CLASS_TYPE_P (t)
-      || TREE_CODE (t) == FUNCTION_DECL)
-    {
-      if (!TI_TEMPLATE (ti))
-       return NULL;
-
-      result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
-    }
-
-  return result;
-}
-
-/* Append the typedef TYPE_DECL used in template T to a list of typedefs
-   tied to T. That list of typedefs will be access checked at
-   T instantiation time.
-   T is either a FUNCTION_DECL or a RECORD_TYPE.
-   TYPE_DECL is a TYPE_DECL node representing a typedef.
-   SCOPE is the scope through which TYPE_DECL is accessed.
-   LOCATION is the location of the usage point of TYPE_DECL.
-
-   This function is a subroutine of
-   append_type_to_template_for_access_check.  */
-
-static void
-append_type_to_template_for_access_check_1 (tree t,
-                                           tree type_decl,
-                                           tree scope,
-                                           location_t location)
-{
-  qualified_typedef_usage_t typedef_usage;
-  tree ti;
-
-  if (!t || t == error_mark_node)
-    return;
-
-  gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
-              || CLASS_TYPE_P (t))
-             && type_decl
-             && TREE_CODE (type_decl) == TYPE_DECL
-             && scope);
-
-  if (!(ti = get_template_info (t)))
-    return;
-
-  gcc_assert (TI_TEMPLATE (ti));
-
-  typedef_usage.typedef_decl = type_decl;
-  typedef_usage.context = scope;
-  typedef_usage.locus = location;
-
-  vec_safe_push (TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti), typedef_usage);
-}
-
-/* Append TYPE_DECL to the template TEMPL.
-   TEMPL is either a class type, a FUNCTION_DECL or a TEMPLATE_DECL.
-   At TEMPL instanciation time, TYPE_DECL will be checked to see
-   if it can be accessed through SCOPE.
-   LOCATION is the location of the usage point of TYPE_DECL.
-
-   e.g. consider the following code snippet:
-
-     class C
-     {
-       typedef int myint;
-     };
-
-     template<class U> struct S
-     {
-       C::myint mi; // <-- usage point of the typedef C::myint
-     };
-
-     S<char> s;
-
-   At S<char> instantiation time, we need to check the access of C::myint
-   In other words, we need to check the access of the myint typedef through
-   the C scope. For that purpose, this function will add the myint typedef
-   and the scope C through which its being accessed to a list of typedefs
-   tied to the template S. That list will be walked at template instantiation
-   time and access check performed on each typedefs it contains.
-   Note that this particular code snippet should yield an error because
-   myint is private to C.  */
-
-void
-append_type_to_template_for_access_check (tree templ,
-                                          tree type_decl,
-                                         tree scope,
-                                         location_t location)
-{
-  qualified_typedef_usage_t *iter;
-  unsigned i;
-
-  gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
-
-  /* Make sure we don't append the type to the template twice.  */
-  FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (templ), i, iter)
-    if (iter->typedef_decl == type_decl && scope == iter->context)
-      return;
-
-  append_type_to_template_for_access_check_1 (templ, type_decl,
-                                             scope, location);
-}
-
 /* Recursively walk over && expressions searching for EXPR. Return a reference
    to that expression.  */
 
@@ -29445,9 +29371,8 @@ declare_integer_pack (void)
 void
 init_template_processing (void)
 {
-  /* FIXME: enable sanitization (PR87847) */
-  decl_specializations = hash_table<spec_hasher>::create_ggc (37, false);
-  type_specializations = hash_table<spec_hasher>::create_ggc (37, false);
+  decl_specializations = hash_table<spec_hasher>::create_ggc (37);
+  type_specializations = hash_table<spec_hasher>::create_ggc (37);
 
   if (cxx_dialect >= cxx11)
     declare_integer_pack ();
This page took 0.103031 seconds and 5 git commands to generate.