]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/pt.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / pt.c
index deaac576468052bfa94d1386fc48342e5ef8543d..5b12aa6996a89daad35e0a37c3794e42725b56f1 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle parameterized types (templates) for GNU -*- C++ -*-.
-   Copyright (C) 1992-2019 Free Software Foundation, Inc.
+   Copyright (C) 1992-2020 Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
 
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "gcc-rich-location.h"
 #include "selftest.h"
+#include "target.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -135,8 +136,6 @@ enum template_base_result {
   tbr_success
 };
 
-static void push_access_scope (tree);
-static void pop_access_scope (tree);
 static bool resolve_overloaded_unification (tree, tree, tree, tree,
                                            unification_kind_t, int,
                                            bool);
@@ -153,7 +152,6 @@ static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
                                              bool, bool);
 static void tsubst_enum        (tree, tree, tree);
 static tree add_to_template_args (tree, tree);
-static tree add_outermost_template_args (tree, tree);
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int check_non_deducible_conversion (tree, tree, int, int,
                                           struct conversion **, bool);
@@ -183,12 +181,9 @@ static int can_complete_type_without_circularity (tree);
 static tree get_bindings (tree, tree, tree, bool);
 static int template_decl_level (tree);
 static int check_cv_quals_for_unify (int, tree, tree);
-static void template_parm_level_and_index (tree, int*, int*);
 static int unify_pack_expansion (tree, tree, tree,
                                 tree, unification_kind_t, bool, bool);
 static tree copy_template_args (tree);
-static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
-static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
 static tree most_specialized_partial_spec (tree, tsubst_flags_t);
 static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
@@ -221,6 +216,7 @@ static tree listify_autos (tree, tree);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
 static bool complex_alias_template_p (const_tree tmpl);
+static tree get_underlying_template (tree);
 static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
 static tree canonicalize_expr_argument (tree, tsubst_flags_t);
 static tree make_argument_pack (tree);
@@ -232,7 +228,7 @@ static tree enclosing_instantiation_of (tree tctx);
    template, VAR_DECL for static member variable, or TYPE_DECL for
    alias template (needed by instantiate_decl).  */
 
-static void
+void
 push_access_scope (tree t)
 {
   gcc_assert (VAR_OR_FUNCTION_DECL_P (t)
@@ -255,7 +251,7 @@ push_access_scope (tree t)
 /* Restore the scope set up by push_access_scope.  T is the node we
    are processing.  */
 
-static void
+void
 pop_access_scope (tree t)
 {
   if (TREE_CODE (t) == FUNCTION_DECL)
@@ -298,7 +294,8 @@ finish_member_template_decl (tree decl)
       return NULL_TREE;
     }
   else if (TREE_CODE (decl) == FIELD_DECL)
-    error ("data member %qD cannot be a member template", decl);
+    error_at (DECL_SOURCE_LOCATION (decl),
+             "data member %qD cannot be a member template", decl);
   else if (DECL_TEMPLATE_INFO (decl))
     {
       if (!DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -310,7 +307,8 @@ finish_member_template_decl (tree decl)
        return decl;
     }
   else
-    error ("invalid member template declaration %qD", decl);
+    error_at (DECL_SOURCE_LOCATION (decl),
+             "invalid member template declaration %qD", decl);
 
   return error_mark_node;
 }
@@ -387,7 +385,7 @@ template_class_depth (tree type)
 
       if (DECL_P (type))
        type = CP_DECL_CONTEXT (type);
-      else if (LAMBDA_TYPE_P (type))
+      else if (LAMBDA_TYPE_P (type) && LAMBDA_TYPE_EXTRA_SCOPE (type))
        type = LAMBDA_TYPE_EXTRA_SCOPE (type);
       else
        type = CP_TYPE_CONTEXT (type);
@@ -580,7 +578,7 @@ add_to_template_args (tree args, tree extra_args)
    template arguments used to attain the full instantiation from the
    partial instantiation.  */
 
-static tree
+tree
 add_outermost_template_args (tree args, tree extra_args)
 {
   tree new_args;
@@ -852,58 +850,59 @@ check_explicit_instantiation_namespace (tree spec)
               spec, current_namespace, ns);
 }
 
-// Returns the type of a template specialization only if that
-// specialization needs to be defined. Otherwise (e.g., if the type has
-// already been defined), the function returns NULL_TREE.
+/* Returns the type of a template specialization only if that
+   specialization needs to be defined. Otherwise (e.g., if the type has
+   already been defined), the function returns NULL_TREE.  */
+
 static tree
 maybe_new_partial_specialization (tree type)
 {
-  // An implicit instantiation of an incomplete type implies
-  // the definition of a new class template.
-  //
-  //    template<typename T>
-  //      struct S;
-  //
-  //    template<typename T>
-  //      struct S<T*>;
-  //
-  // Here, S<T*> is an implicit instantiation of S whose type
-  // is incomplete.
+  /* An implicit instantiation of an incomplete type implies
+     the definition of a new class template.
+
+       template<typename T>
+         struct S;
+
+       template<typename T>
+         struct S<T*>;
+
+     Here, S<T*> is an implicit instantiation of S whose type
+     is incomplete.  */
   if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type))
     return type;
 
-  // It can also be the case that TYPE is a completed specialization.
-  // Continuing the previous example, suppose we also declare:
-  //
-  //    template<typename T>
-  //      requires Integral<T>
-  //        struct S<T*>;
-  //
-  // Here, S<T*> refers to the specialization S<T*> defined
-  // above. However, we need to differentiate definitions because
-  // we intend to define a new partial specialization. In this case,
-  // we rely on the fact that the constraints are different for
-  // this declaration than that above.
-  //
-  // Note that we also get here for injected class names and
-  // late-parsed template definitions. We must ensure that we
-  // do not create new type declarations for those cases.
+  /* It can also be the case that TYPE is a completed specialization.
+     Continuing the previous example, suppose we also declare:
+
+       template<typename T>
+         requires Integral<T>
+           struct S<T*>;
+
+     Here, S<T*> refers to the specialization S<T*> defined
+     above. However, we need to differentiate definitions because
+     we intend to define a new partial specialization. In this case,
+     we rely on the fact that the constraints are different for
+     this declaration than that above.
+
+     Note that we also get here for injected class names and
+     late-parsed template definitions. We must ensure that we
+     do not create new type declarations for those cases.  */
   if (flag_concepts && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
     {
       tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
       tree args = CLASSTYPE_TI_ARGS (type);
 
-      // If there are no template parameters, this cannot be a new
-      // partial template specializtion?
+      /* If there are no template parameters, this cannot be a new
+        partial template specialization?  */
       if (!current_template_parms)
         return NULL_TREE;
 
-      // The injected-class-name is not a new partial specialization.
+      /* The injected-class-name is not a new partial specialization.  */
       if (DECL_SELF_REFERENCE_P (TYPE_NAME (type)))
        return NULL_TREE;
 
-      // If the constraints are not the same as those of the primary
-      // then, we can probably create a new specialization.
+      /* If the constraints are not the same as those of the primary
+        then, we can probably create a new specialization.  */
       tree type_constr = current_template_constraints ();
 
       if (type == TREE_TYPE (tmpl))
@@ -913,8 +912,8 @@ maybe_new_partial_specialization (tree type)
            return NULL_TREE;
        }
 
-      // Also, if there's a pre-existing specialization with matching
-      // constraints, then this also isn't new.
+      /* Also, if there's a pre-existing specialization with matching
+        constraints, then this also isn't new.  */
       tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
       while (specs)
         {
@@ -927,8 +926,8 @@ maybe_new_partial_specialization (tree type)
           specs = TREE_CHAIN (specs);
         }
 
-      // Create a new type node (and corresponding type decl)
-      // for the newly declared specialization.
+      /* Create a new type node (and corresponding type decl)
+        for the newly declared specialization.  */
       tree t = make_class_type (TREE_CODE (type));
       CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
       SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
@@ -938,10 +937,12 @@ maybe_new_partial_specialization (tree type)
         equivalent.  So keep TYPE_CANONICAL the same.  */
       TYPE_CANONICAL (t) = TYPE_CANONICAL (type);
 
-      // Build the corresponding type decl.
+      /* Build the corresponding type decl.  */
       tree d = create_implicit_typedef (DECL_NAME (tmpl), t);
       DECL_CONTEXT (d) = TYPE_CONTEXT (t);
       DECL_SOURCE_LOCATION (d) = input_location;
+      TREE_PRIVATE (d) = (current_access_specifier == access_private_node);
+      TREE_PROTECTED (d) = (current_access_specifier == access_protected_node);
 
       return t;
     }
@@ -1883,7 +1884,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
   switch (tclass)
     {
     case tcc_type:
-      if (alias_template_specialization_p (arg))
+      if (tree ats = alias_template_specialization_p (arg, nt_transparent))
        {
          // We want an alias specialization that survived strip_typedefs
          // to hash differently from its TYPE_CANONICAL, to avoid hash
@@ -1892,7 +1893,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
          // left alone, or untouched specializations because
          // coerce_template_parms returns the unconverted template
          // arguments if it sees incomplete argument packs.
-         tree ti = TYPE_ALIAS_TEMPLATE_INFO (arg);
+         tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats);
          return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
        }
       if (TYPE_CANONICAL (arg))
@@ -2135,7 +2136,8 @@ determine_specialization (tree template_id,
 
   if (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns))
     {
-      error ("%qD is not a function template", fns);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "%qD is not a function template", fns);
       return error_mark_node;
     }
   else if (VAR_P (decl) && !variable_template_p (fns))
@@ -2414,7 +2416,8 @@ determine_specialization (tree template_id,
       error ("template-id %qD for %q+D does not match any template "
             "declaration", template_id, decl);
       if (header_count && header_count != template_count + 1)
-       inform (input_location, "saw %d %<template<>%>, need %d for "
+       inform (DECL_SOURCE_LOCATION (decl),
+               "saw %d %<template<>%>, need %d for "
                "specializing a member function template",
                header_count, template_count + 1);
       else
@@ -2438,7 +2441,7 @@ determine_specialization (tree template_id,
       tree fn = TREE_VALUE (candidates);
       *targs_out = copy_node (DECL_TI_ARGS (fn));
 
-      // Propagate the candidate's constraints to the declaration.
+      /* Propagate the candidate's constraints to the declaration.  */
       set_constraints (decl, get_constraints (fn));
 
       /* DECL is a re-declaration or partial instantiation of a template
@@ -2806,8 +2809,9 @@ check_explicit_specialization (tree declarator,
              /* This case handles bogus declarations like template <>
                 template <class T> void f<int>(); */
 
-             error ("template-id %qD in declaration of primary template",
-                    declarator);
+             error_at (cp_expr_loc_or_input_loc (declarator),
+                       "template-id %qE in declaration of primary template",
+                       declarator);
              return decl;
            }
        }
@@ -2865,8 +2869,9 @@ check_explicit_specialization (tree declarator,
             template <class T> void f<int>(); */
 
          if (!uses_template_parms (TREE_OPERAND (declarator, 1)))
-           error ("template-id %qD in declaration of primary template",
-                  declarator);
+           error_at (cp_expr_loc_or_input_loc (declarator),
+                     "template-id %qE in declaration of primary template",
+                     declarator);
          else if (variable_template_p (TREE_OPERAND (declarator, 0)))
            {
              /* Partial specialization of variable template.  */
@@ -2875,11 +2880,13 @@ check_explicit_specialization (tree declarator,
              goto ok;
            }
          else if (cxx_dialect < cxx14)
-           error ("non-type partial specialization %qD "
-                  "is not allowed", declarator);
+           error_at (cp_expr_loc_or_input_loc (declarator),
+                     "non-type partial specialization %qE "
+                     "is not allowed", declarator);
          else
-           error ("non-class, non-variable partial specialization %qD "
-                  "is not allowed", declarator);
+           error_at (cp_expr_loc_or_input_loc (declarator),
+                     "non-class, non-variable partial specialization %qE "
+                     "is not allowed", declarator);
          return decl;
        ok:;
        }
@@ -3297,6 +3304,153 @@ comp_template_parms (const_tree parms1, const_tree parms2)
   return 1;
 }
 
+/* Returns true if two template parameters are declared with
+   equivalent constraints.  */
+
+static bool
+template_parameter_constraints_equivalent_p (const_tree parm1, const_tree parm2)
+{
+  tree req1 = TREE_TYPE (parm1);
+  tree req2 = TREE_TYPE (parm2);
+  if (!req1 != !req2)
+    return false;
+  if (req1)
+    return cp_tree_equal (req1, req2);
+  return true;
+}
+
+/* Returns true when two template parameters are equivalent.  */
+
+static bool
+template_parameters_equivalent_p (const_tree parm1, const_tree parm2)
+{
+  tree decl1 = TREE_VALUE (parm1);
+  tree decl2 = TREE_VALUE (parm2);
+
+  /* If either of the template parameters are invalid, assume
+     they match for the sake of error recovery. */
+  if (error_operand_p (decl1) || error_operand_p (decl2))
+    return true;
+
+  /* ... they declare parameters of the same kind.  */
+  if (TREE_CODE (decl1) != TREE_CODE (decl2))
+    return false;
+
+  /* ... one parameter was introduced by a parameter declaration, then
+     both are. This case arises as a result of eagerly rewriting declarations
+     during parsing.  */
+  if (DECL_VIRTUAL_P (decl1) != DECL_VIRTUAL_P (decl2))
+    return false;
+
+  /* ... if either declares a pack, they both do.  */
+  if (template_parameter_pack_p (decl1) != template_parameter_pack_p (decl2))
+    return false;
+
+  if (TREE_CODE (decl1) == PARM_DECL)
+    {
+      /* ... if they declare non-type parameters, the types are equivalent.  */
+      if (!same_type_p (TREE_TYPE (decl1), TREE_TYPE (decl2)))
+       return false;
+    }
+  else if (TREE_CODE (decl2) == TEMPLATE_DECL)
+    {
+      /* ... if they declare template template parameters, their template
+        parameter lists are equivalent.  */
+      if (!template_heads_equivalent_p (decl1, decl2))
+       return false;
+    }
+
+  /* ... if they are declared with a qualified-concept name, they both
+     are, and those names are equivalent.  */
+  return template_parameter_constraints_equivalent_p (parm1, parm2);
+}
+
+/* Returns true if two template parameters lists are equivalent.
+   Two template parameter lists are equivalent if they have the
+   same length and their corresponding parameters are equivalent.
+
+   PARMS1 and PARMS2 are TREE_LISTs containing TREE_VECs: the
+   data structure returned by DECL_TEMPLATE_PARMS.
+
+   This is generally the same implementation as comp_template_parms
+   except that it also the concept names and arguments used to
+   introduce parameters.  */
+
+static bool
+template_parameter_lists_equivalent_p (const_tree parms1, const_tree parms2)
+{
+  if (parms1 == parms2)
+    return true;
+
+  const_tree p1 = parms1;
+  const_tree p2 = parms2;
+  while (p1 != NULL_TREE && p2 != NULL_TREE)
+    {
+      tree list1 = TREE_VALUE (p1);
+      tree list2 = TREE_VALUE (p2);
+
+      if (TREE_VEC_LENGTH (list1) != TREE_VEC_LENGTH (list2))
+       return 0;
+
+      for (int i = 0; i < TREE_VEC_LENGTH (list2); ++i)
+       {
+         tree parm1 = TREE_VEC_ELT (list1, i);
+         tree parm2 = TREE_VEC_ELT (list2, i);
+         if (!template_parameters_equivalent_p (parm1, parm2))
+           return false;
+       }
+
+      p1 = TREE_CHAIN (p1);
+      p2 = TREE_CHAIN (p2);
+    }
+
+  if ((p1 != NULL_TREE) != (p2 != NULL_TREE))
+    return false;
+
+  return true;
+}
+
+/* Return true if the requires-clause of the template parameter lists are
+   equivalent and false otherwise.  */
+static bool
+template_requirements_equivalent_p (const_tree parms1, const_tree parms2)
+{
+  tree req1 = TEMPLATE_PARMS_CONSTRAINTS (parms1);
+  tree req2 = TEMPLATE_PARMS_CONSTRAINTS (parms2);
+  if ((req1 != NULL_TREE) != (req2 != NULL_TREE))
+    return false;
+  if (!cp_tree_equal (req1, req2))
+    return false;
+  return true;
+}
+
+/* Returns true if two template heads are equivalent. 17.6.6.1p6:
+   Two template heads are equivalent if their template parameter
+   lists are equivalent and their requires clauses are equivalent.
+
+   In pre-C++20, this is equivalent to calling comp_template_parms
+   for the template parameters of TMPL1 and TMPL2.  */
+
+bool
+template_heads_equivalent_p (const_tree tmpl1, const_tree tmpl2)
+{
+  tree parms1 = DECL_TEMPLATE_PARMS (tmpl1);
+  tree parms2 = DECL_TEMPLATE_PARMS (tmpl2);
+
+  /* Don't change the matching rules for pre-C++20.  */
+  if (cxx_dialect < cxx2a)
+    return comp_template_parms (parms1, parms2);
+
+  /* ... have the same number of template parameters, and their
+     corresponding parameters are equivalent.  */
+  if (!template_parameter_lists_equivalent_p (parms1, parms2))
+    return false;
+
+  /* ... if either has a requires-clause, they both do and their
+     corresponding constraint-expressions are equivalent.  */
+  return template_requirements_equivalent_p (parms1, parms2);
+}
+
 /* Determine whether PARM is a parameter pack.  */
 
 bool
@@ -3423,7 +3577,7 @@ primary_template_specialization_p (const_tree t)
     return (CLASSTYPE_TEMPLATE_INFO (t)
            && CLASSTYPE_USE_TEMPLATE (t)
            && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
-  else if (alias_template_specialization_p (t))
+  else if (alias_template_specialization_p (t, nt_transparent))
     return true;
   return false;
 }
@@ -3872,7 +4026,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
 }
 
 /* Determines if the expression or type T uses any parameter packs.  */
-bool
+tree
 uses_parameter_packs (tree t)
 {
   tree parameter_packs = NULL_TREE;
@@ -3882,7 +4036,7 @@ uses_parameter_packs (tree t)
   ppd.type_pack_expansion_p = false;
   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
   delete ppd.visited;
-  return parameter_packs != NULL_TREE;
+  return parameter_packs;
 }
 
 /* Turn ARG, which may be an expression, type, or a TREE_LIST
@@ -4059,7 +4213,7 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
   if (parameter_packs)
     {
       if (loc == UNKNOWN_LOCATION)
-       loc = cp_expr_loc_or_loc (t, input_location);
+       loc = cp_expr_loc_or_input_loc (t);
       error_at (loc, "parameter packs not expanded with %<...%>:");
       while (parameter_packs)
         {
@@ -4280,33 +4434,40 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
       || !same_type_p (type, TREE_TYPE (TEMPLATE_PARM_DESCENDANTS (index))))
     {
       tree orig_decl = TEMPLATE_PARM_DECL (index);
-      tree decl, t;
 
-      decl = build_decl (DECL_SOURCE_LOCATION (orig_decl),
-                        TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
+      tree decl = build_decl (DECL_SOURCE_LOCATION (orig_decl),
+                             TREE_CODE (orig_decl), DECL_NAME (orig_decl),
+                             type);
       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
       TREE_READONLY (decl) = TREE_READONLY (orig_decl);
       DECL_ARTIFICIAL (decl) = 1;
       SET_DECL_TEMPLATE_PARM_P (decl);
 
-      t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
-                                    TEMPLATE_PARM_LEVEL (index) - levels,
-                                    TEMPLATE_PARM_ORIG_LEVEL (index),
-                                    decl, type);
-      TEMPLATE_PARM_DESCENDANTS (index) = t;
-      TEMPLATE_PARM_PARAMETER_PACK (t)
+      tree tpi = build_template_parm_index (TEMPLATE_PARM_IDX (index),
+                                           TEMPLATE_PARM_LEVEL (index) - levels,
+                                           TEMPLATE_PARM_ORIG_LEVEL (index),
+                                           decl, type);
+      TEMPLATE_PARM_DESCENDANTS (index) = tpi;
+      TEMPLATE_PARM_PARAMETER_PACK (tpi)
        = TEMPLATE_PARM_PARAMETER_PACK (index);
 
        /* Template template parameters need this.  */
+      tree inner = decl;
       if (TREE_CODE (decl) == TEMPLATE_DECL)
        {
-         DECL_TEMPLATE_RESULT (decl)
-           = build_decl (DECL_SOURCE_LOCATION (decl),
-                         TYPE_DECL, DECL_NAME (decl), type);
-         DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (decl)) = true;
+         inner = build_decl (DECL_SOURCE_LOCATION (decl),
+                             TYPE_DECL, DECL_NAME (decl), type);
+         DECL_TEMPLATE_RESULT (decl) = inner;
+         DECL_ARTIFICIAL (inner) = true;
          DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
            (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
        }
+
+      /* Attach the TPI to the decl.  */
+      if (TREE_CODE (inner) == TYPE_DECL)
+       TEMPLATE_TYPE_PARM_INDEX (type) = tpi;
+      else
+       DECL_INITIAL (decl) = tpi;
     }
 
   return TEMPLATE_PARM_DESCENDANTS (index);
@@ -4564,7 +4725,7 @@ template_parm_to_arg (tree t)
 /* Given a single level of template parameters (a TREE_VEC), return it
    as a set of template arguments.  */
 
-static tree
+tree
 template_parms_level_to_args (tree parms)
 {
   tree a = copy_node (parms);
@@ -4582,7 +4743,7 @@ template_parms_level_to_args (tree parms)
    arguments.  The template parameters are represented as a TREE_VEC, in
    the form documented in cp-tree.h for template arguments.  */
 
-static tree
+tree
 template_parms_to_args (tree parms)
 {
   tree header;
@@ -4618,6 +4779,26 @@ current_template_args (void)
   return template_parms_to_args (current_template_parms);
 }
 
+/* Return the fully generic arguments for of TMPL, i.e. what
+   current_template_args would be while parsing it.  */
+
+tree
+generic_targs_for (tree tmpl)
+{
+  if (tmpl == NULL_TREE)
+    return NULL_TREE;
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
+      || DECL_TEMPLATE_SPECIALIZATION (tmpl))
+    /* DECL_TEMPLATE_RESULT doesn't have the arguments we want.  For a template
+       template parameter, it has no TEMPLATE_INFO; for a partial
+       specialization, it has the arguments for the primary template, and we
+       want the arguments for the partial specialization.  */;
+  else if (tree result = DECL_TEMPLATE_RESULT (tmpl))
+    if (tree ti = get_template_info (result))
+      return TI_ARGS (ti);
+  return template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl));
+}
+
 /* Update the declared TYPE by doing any lookups which were thought to be
    dependent, but are not now that we know the SCOPE of the declarator.  */
 
@@ -4847,7 +5028,7 @@ process_partial_specialization (tree decl)
   if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
       && (!flag_concepts
          || !strictly_subsumes (current_template_constraints (),
-                                get_constraints (maintmpl))))
+                                inner_args, maintmpl)))
     {
       if (!flag_concepts)
         error ("partial specialization %q+D does not specialize "
@@ -4956,8 +5137,9 @@ process_partial_specialization (tree decl)
             {
               if ((!packed_args && tpd.arg_uses_template_parms[i])
                   || (packed_args && uses_template_parms (arg)))
-                error ("template argument %qE involves template parameter(s)",
-                       arg);
+               error_at (cp_expr_loc_or_input_loc (arg),
+                         "template argument %qE involves template "
+                         "parameter(s)", arg);
               else 
                 {
                   /* Look at the corresponding template parameter,
@@ -5515,7 +5697,8 @@ push_template_decl_real (tree decl, bool is_friend)
              /* [temp.mem]
 
                 A destructor shall not be a member template.  */
-             error ("destructor %qD declared as member template", decl);
+             error_at (DECL_SOURCE_LOCATION (decl),
+                       "destructor %qD declared as member template", decl);
              return error_mark_node;
            }
          if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl))
@@ -5554,6 +5737,8 @@ push_template_decl_real (tree decl, bool is_friend)
        gcc_assert (!DECL_ARTIFICIAL (decl));
       else if (VAR_P (decl))
        /* C++14 variable template. */;
+      else if (TREE_CODE (decl) == CONCEPT_DECL)
+       /* C++2a concept definitions.  */;
       else
        {
          error ("template declaration of %q#D", decl);
@@ -5806,9 +5991,18 @@ push_template_decl_real (tree decl, bool is_friend)
        }
 
       if (TREE_CODE (decl) == TYPE_DECL
-         && TYPE_DECL_ALIAS_P (decl)
-         && complex_alias_template_p (tmpl))
-       TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+         && TYPE_DECL_ALIAS_P (decl))
+       {
+         if (tree constr
+             = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+           {
+             /* ??? Why don't we do this here for all templates?  */
+             constr = build_constraints (constr, NULL_TREE);
+             set_constraints (decl, constr);
+           }
+         if (complex_alias_template_p (tmpl))
+           TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+       }
     }
 
   /* The DECL_TI_ARGS of DECL contains full set of arguments referring
@@ -5835,7 +6029,7 @@ push_template_decl_real (tree decl, bool is_friend)
       && TREE_PUBLIC (decl)
       && VAR_OR_FUNCTION_DECL_P (decl))
     /* Set DECL_COMDAT on template instantiations; if we force
-       them to be emitted by explicit instantiation or -frepo,
+       them to be emitted by explicit instantiation,
        mark_needed will tell cgraph to do the right thing.  */
     DECL_COMDAT (decl) = true;
 
@@ -5956,6 +6150,19 @@ redeclare_class_template (tree type, tree parms, tree cons)
          return false;
        }
 
+      /* The parameters can be declared to introduce different
+        constraints.  */
+      tree p1 = TREE_VEC_ELT (tmpl_parms, i);
+      tree p2 = TREE_VEC_ELT (parms, i);
+      if (!template_parameter_constraints_equivalent_p (p1, p2))
+       {
+         error ("declaration of template parameter %q+#D with different "
+                "constraints", parm);
+         inform (DECL_SOURCE_LOCATION (tmpl_parm),
+                 "original declaration appeared here");
+         return false;
+       }
+
       if (tmpl_default != NULL_TREE && parm_default != NULL_TREE)
        {
          /* We have in [temp.param]:
@@ -5989,13 +6196,18 @@ redeclare_class_template (tree type, tree parms, tree cons)
        TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (parm)) = true;
     }
 
-  // Cannot redeclare a class template with a different set of constraints.
-  if (!equivalent_constraints (get_constraints (tmpl), cons))
+  tree ci = get_constraints (tmpl);
+  tree req1 = ci ? CI_TEMPLATE_REQS (ci) : NULL_TREE;
+  tree req2 = cons ? CI_TEMPLATE_REQS (cons) : NULL_TREE;
+
+  /* Two classes with different constraints declare different entities.  */
+  if (!cp_tree_equal (req1, req2))
     {
       error_at (input_location, "redeclaration %q#D with different "
                                 "constraints", tmpl);
       inform (DECL_SOURCE_LOCATION (tmpl),
               "original declaration appeared here");
+      return false;
     }
 
     return true;
@@ -6097,18 +6309,30 @@ alias_type_or_template_p (tree t)
          || DECL_ALIAS_TEMPLATE_P (t));
 }
 
-/* Return TRUE iff T is a specialization of an alias template.  */
+/* If T is a specialization of an alias template, return it; otherwise return
+   NULL_TREE.  If TRANSPARENT_TYPEDEFS is true, look through other aliases.  */
 
-bool
-alias_template_specialization_p (const_tree t)
+tree
+alias_template_specialization_p (const_tree t,
+                                bool transparent_typedefs)
 {
+  if (!TYPE_P (t))
+    return NULL_TREE;
+
   /* It's an alias template specialization if it's an alias and its
      TYPE_NAME is a specialization of a primary template.  */
-  if (TYPE_ALIAS_P (t))
-    if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
-      return PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo));
+  if (typedef_variant_p (t))
+    {
+      if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+       if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)))
+         return CONST_CAST_TREE (t);
+      if (transparent_typedefs)
+       return alias_template_specialization_p (DECL_ORIGINAL_TYPE
+                                               (TYPE_NAME (t)),
+                                               transparent_typedefs);
+    }
 
-  return false;
+  return NULL_TREE;
 }
 
 /* An alias template is complex from a SFINAE perspective if a template-id
@@ -6137,6 +6361,14 @@ uses_all_template_parms_r (tree t, void *data_)
 static bool
 complex_alias_template_p (const_tree tmpl)
 {
+  /* A renaming alias isn't complex.  */
+  if (get_underlying_template (CONST_CAST_TREE (tmpl)) != tmpl)
+    return false;
+
+  /* Any other constrained alias is complex.  */
+  if (get_constraints (tmpl))
+    return true;
+
   struct uses_all_template_parms_data data;
   tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
   tree parms = DECL_TEMPLATE_PARMS (tmpl);
@@ -6153,30 +6385,36 @@ complex_alias_template_p (const_tree tmpl)
   return false;
 }
 
-/* Return TRUE iff T is a specialization of a complex alias template with
-   dependent template-arguments.  */
+/* If T is a specialization of a complex alias template with dependent
+   template-arguments, return it; otherwise return NULL_TREE.  If T is a
+   typedef to such a specialization, return the specialization.  */
 
-bool
-dependent_alias_template_spec_p (const_tree t)
+tree
+dependent_alias_template_spec_p (const_tree t, bool transparent_typedefs)
 {
-  if (!alias_template_specialization_p (t))
-    return false;
+  if (!TYPE_P (t) || !typedef_variant_p (t))
+    return NULL_TREE;
 
   tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
-  if (!TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo)))
-    return false;
+  if (tinfo
+      && TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo))
+      && (any_dependent_template_arguments_p
+         (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)))))
+    return CONST_CAST_TREE (t);
 
-  tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));
-  if (!any_dependent_template_arguments_p (args))
-    return false;
+  if (transparent_typedefs)
+    {
+      tree utype = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
+      return dependent_alias_template_spec_p (utype, transparent_typedefs);
+    }
 
-  return true;
+  return NULL_TREE;
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
 
 static int
-num_innermost_template_parms (tree tmpl)
+num_innermost_template_parms (const_tree tmpl)
 {
   tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
   return TREE_VEC_LENGTH (parms);
@@ -6194,6 +6432,9 @@ get_underlying_template (tree tmpl)
     {
       /* Determine if the alias is equivalent to an underlying template.  */
       tree orig_type = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+      /* The underlying type may have been ill-formed. Don't proceed.  */
+      if (!orig_type)
+       break;
       tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (orig_type);
       if (!tinfo)
        break;
@@ -6204,11 +6445,15 @@ get_underlying_template (tree tmpl)
              != num_innermost_template_parms (underlying)))
        break;
 
-      tree alias_args = INNERMOST_TEMPLATE_ARGS
-       (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
+      tree alias_args = INNERMOST_TEMPLATE_ARGS (generic_targs_for (tmpl));
       if (!comp_template_args (TI_ARGS (tinfo), alias_args))
        break;
 
+      /* If TMPL adds or changes any constraints, it isn't equivalent.  I think
+        it's appropriate to treat a less-constrained alias as equivalent.  */
+      if (!at_least_as_constrained (underlying, tmpl))
+       break;
+
       /* Alias is equivalent.  Strip it and repeat.  */
       tmpl = underlying;
     }
@@ -6255,13 +6500,14 @@ convert_nontype_argument_function (tree type, tree expr,
     {
       if (complain & tf_error)
        {
-         error ("%qE is not a valid template argument for type %qT",
-                expr, type);
+         location_t loc = cp_expr_loc_or_input_loc (expr);
+         error_at (loc, "%qE is not a valid template argument for type %qT",
+                   expr, type);
          if (TYPE_PTR_P (type))
-           inform (input_location, "it must be the address of a function "
+           inform (loc, "it must be the address of a function "
                    "with external linkage");
          else
-           inform (input_location, "it must be the name of a function with "
+           inform (loc, "it must be the name of a function with "
                    "external linkage");
        }
       return NULL_TREE;
@@ -6272,14 +6518,15 @@ convert_nontype_argument_function (tree type, tree expr,
     {
       if (complain & tf_error)
        {
+         location_t loc = cp_expr_loc_or_input_loc (expr);
          if (cxx_dialect >= cxx11)
-           error ("%qE is not a valid template argument for type %qT "
-                  "because %qD has no linkage",
-                  expr, type, fn_no_ptr);
+           error_at (loc, "%qE is not a valid template argument for type "
+                     "%qT because %qD has no linkage",
+                     expr, type, fn_no_ptr);
          else
-           error ("%qE is not a valid template argument for type %qT "
-                  "because %qD does not have external linkage",
-                  expr, type, fn_no_ptr);
+           error_at (loc, "%qE is not a valid template argument for type "
+                     "%qT because %qD does not have external linkage",
+                     expr, type, fn_no_ptr);
        }
       return NULL_TREE;
     }
@@ -6306,7 +6553,6 @@ static bool
 check_valid_ptrmem_cst_expr (tree type, tree expr,
                             tsubst_flags_t complain)
 {
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
   tree orig_expr = expr;
   STRIP_NOPS (expr);
   if (null_ptr_cst_p (expr))
@@ -6323,6 +6569,7 @@ check_valid_ptrmem_cst_expr (tree type, tree expr,
     return true;
   if (complain & tf_error)
     {
+      location_t loc = cp_expr_loc_or_input_loc (orig_expr);
       error_at (loc, "%qE is not a valid template argument for type %qT",
                orig_expr, type);
       if (TREE_CODE (expr) != PTRMEM_CST)
@@ -6350,6 +6597,8 @@ check_valid_ptrmem_cst_expr (tree type, tree expr,
 static bool
 has_value_dependent_address (tree op)
 {
+  STRIP_ANY_LOCATION_WRAPPER (op);
+
   /* We could use get_inner_reference here, but there's no need;
      this is only relevant for template non-type arguments, which
      can only be expressed as &id-expression.  */
@@ -6525,7 +6774,7 @@ unify_arg_conversion (bool explain_p, tree to_type,
                      tree from_type, tree arg)
 {
   if (explain_p)
-    inform (cp_expr_loc_or_loc (arg, input_location),
+    inform (cp_expr_loc_or_input_loc (arg),
            "  cannot convert %qE (type %qT) to type %qT",
            arg, from_type, to_type);
   return unify_invalid (explain_p);
@@ -6620,24 +6869,27 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
        if (!VAR_P (decl))
          {
            if (complain & tf_error)
-             error ("%qE is not a valid template argument of type %qT "
-                    "because %qE is not a variable", expr, type, decl);
+             error_at (cp_expr_loc_or_input_loc (expr),
+                       "%qE is not a valid template argument of type %qT "
+                       "because %qE is not a variable", expr, type, decl);
            return true;
          }
        else if (cxx_dialect < cxx11 && !DECL_EXTERNAL_LINKAGE_P (decl))
          {
            if (complain & tf_error)
-             error ("%qE is not a valid template argument of type %qT "
-                    "in C++98 because %qD does not have external linkage",
-                    expr, type, decl);
+             error_at (cp_expr_loc_or_input_loc (expr),
+                       "%qE is not a valid template argument of type %qT "
+                       "in C++98 because %qD does not have external linkage",
+                       expr, type, decl);
            return true;
          }
        else if ((cxx_dialect >= cxx11 && cxx_dialect < cxx17)
                 && decl_linkage (decl) == lk_none)
          {
            if (complain & tf_error)
-             error ("%qE is not a valid template argument of type %qT "
-                    "because %qD has no linkage", expr, type, decl);
+             error_at (cp_expr_loc_or_input_loc (expr),
+                       "%qE is not a valid template argument of type %qT "
+                       "because %qD has no linkage", expr, type, decl);
            return true;
          }
        /* C++17: For a non-type template-parameter of reference or pointer
@@ -6765,7 +7017,7 @@ static tree
 convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 {
   tree expr_type;
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
 
   /* Detect immediately string literals as invalid non-type argument.
      This special-case is not needed for correctness (we would easily
@@ -7307,14 +7559,7 @@ coerce_template_args_for_ttp (tree templ, tree arglist,
 
   tree outer = DECL_CONTEXT (templ);
   if (outer)
-    {
-      if (DECL_TEMPLATE_SPECIALIZATION (outer))
-       /* We want arguments for the partial specialization, not arguments for
-          the primary template.  */
-       outer = template_parms_to_args (DECL_TEMPLATE_PARMS (outer));
-      else
-       outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
-    }
+    outer = generic_targs_for (outer);
   else if (current_template_parms)
     {
       /* This is an argument of the current template, so we haven't set
@@ -7344,21 +7589,6 @@ coerce_template_args_for_ttp (tree templ, tree arglist,
 /* A cache of template template parameters with match-all default
    arguments.  */
 static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
-static void
-store_defaulted_ttp (tree v, tree t)
-{
-  if (!defaulted_ttp_cache)
-    defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
-  defaulted_ttp_cache->put (v, t);
-}
-static tree
-lookup_defaulted_ttp (tree v)
-{
-  if (defaulted_ttp_cache)
-    if (tree *p = defaulted_ttp_cache->get (v))
-      return *p;
-  return NULL_TREE;
-}
 
 /* T is a bound template template-parameter.  Copy its arguments into default
    arguments of the template template-parameter's template parameters.  */
@@ -7366,8 +7596,8 @@ lookup_defaulted_ttp (tree v)
 static tree
 add_defaults_to_ttp (tree otmpl)
 {
-  if (tree c = lookup_defaulted_ttp (otmpl))
-    return c;
+  if (tree *c = hash_map_safe_get (defaulted_ttp_cache, otmpl))
+    return *c;
 
   tree ntmpl = copy_node (otmpl);
 
@@ -7397,7 +7627,7 @@ add_defaults_to_ttp (tree otmpl)
        }
     }
 
-  store_defaulted_ttp (otmpl, ntmpl);
+  hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
   return ntmpl;
 }
 
@@ -7787,26 +8017,25 @@ is_compatible_template_arg (tree parm, tree arg)
   if (parm_cons == NULL_TREE)
     return true;
 
-  tree arg_cons = get_constraints (arg);
+  /* If the template parameter is constrained, we need to rewrite its
+     constraints in terms of the ARG's template parameters. This ensures
+     that all of the template parameter types will have the same depth.
 
-  // If the template parameter is constrained, we need to rewrite its
-  // constraints in terms of the ARG's template parameters. This ensures
-  // that all of the template parameter types will have the same depth.
-  //
-  // Note that this is only valid when coerce_template_template_parm is
-  // true for the innermost template parameters of PARM and ARG. In other
-  // words, because coercion is successful, this conversion will be valid.
+     Note that this is only valid when coerce_template_template_parm is
+     true for the innermost template parameters of PARM and ARG. In other
+     words, because coercion is successful, this conversion will be valid.  */
+  tree new_args = NULL_TREE;
   if (parm_cons)
     {
-      tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (arg));
-      parm_cons = tsubst_constraint_info (parm_cons,
-                                         INNERMOST_TEMPLATE_ARGS (args),
+      tree aparms = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+      new_args = template_parms_level_to_args (aparms);
+      parm_cons = tsubst_constraint_info (parm_cons, new_args,
                                          tf_none, NULL_TREE);
       if (parm_cons == error_mark_node)
         return false;
     }
 
-  return subsumes (parm_cons, arg_cons);
+  return weakly_subsumes (parm_cons, new_args, arg);
 }
 
 // Convert a placeholder argument into a binding to the original
@@ -8126,8 +8355,9 @@ convert_template_argument (tree parm,
       if (val == NULL_TREE)
        val = error_mark_node;
       else if (val == error_mark_node && (complain & tf_error))
-       error ("could not convert template argument %qE from %qT to %qT",
-              orig_arg, TREE_TYPE (orig_arg), t);
+       error_at (cp_expr_loc_or_input_loc (orig_arg),
+                 "could not convert template argument %qE from %qT to %qT",
+                 orig_arg, TREE_TYPE (orig_arg), t);
 
       if (INDIRECT_REF_P (val))
         {
@@ -8425,7 +8655,7 @@ coerce_template_parms (tree parms,
      template (DR 1430).  */
   else if (in_decl
           && (DECL_ALIAS_TEMPLATE_P (in_decl)
-              || concept_template_p (in_decl))
+              || concept_definition_p (in_decl))
           && variadic_args_p
           && nargs - variadic_args_p < nparms - variadic_p)
     {
@@ -8599,6 +8829,7 @@ coerce_template_parms (tree parms,
 
       if (arg == error_mark_node)
        lost++;
+
       TREE_VEC_ELT (new_inner_args, arg_idx - pack_adjust) = arg;
     }
 
@@ -8616,6 +8847,32 @@ coerce_template_parms (tree parms,
       /* We had some pack expansion arguments that will only work if the packs
         are empty, but wait until instantiation time to complain.
         See variadic-ttp3.C.  */
+
+      /* Except that we can't provide empty packs to alias templates or
+         concepts when there are no corresponding parameters. Basically,
+         we can get here with this:
+
+             template<typename T> concept C = true;
+
+             template<typename... Args>
+              requires C<Args...>
+             void f();
+
+         When parsing C<Args...>, we try to form a concept check of
+         C<?, Args...>. Without the extra check for substituting an empty
+         pack past the last parameter, we can accept the check as valid.
+
+         FIXME: This may be valid for alias templates (but I doubt it).
+
+         FIXME: The error could be better also.   */
+      if (in_decl && concept_definition_p (in_decl))
+       {
+         if (complain & tf_error)
+           error_at (location_of (TREE_VEC_ELT (args, arg_idx)),
+                     "too many arguments");
+         return error_mark_node;
+       }
+
       int len = nparms + (nargs - arg_idx);
       tree args = make_tree_vec (len);
       int i = 0;
@@ -9446,12 +9703,14 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
          Note that the check is deferred until after the hash
          lookup. This prevents redundant checks on previously
          instantiated specializations. */
-      if (flag_concepts && !constraints_satisfied_p (gen_tmpl, arglist))
+      if (flag_concepts
+         && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)
+         && !constraints_satisfied_p (gen_tmpl, arglist))
         {
           if (complain & tf_error)
             {
              auto_diagnostic_group d;
-              error ("template constraint failure");
+              error ("template constraint failure for %qD", gen_tmpl);
               diagnose_constraints (input_location, gen_tmpl, arglist);
             }
           return error_mark_node;
@@ -9784,13 +10043,12 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context,
 tree
 lookup_template_variable (tree templ, tree arglist)
 {
+  if (flag_concepts && variable_concept_p (templ))
+    return build_concept_check (templ, arglist, tf_none);
+
   /* The type of the expression is NULL_TREE since the template-id could refer
      to an explicit or partial specialization. */
-  tree type = NULL_TREE;
-  if (flag_concepts && variable_concept_p (templ))
-    /* Except that concepts are always bool.  */
-    type = boolean_type_node;
-  return build2 (TEMPLATE_ID_EXPR, type, templ, arglist);
+  return build2 (TEMPLATE_ID_EXPR, NULL_TREE, templ, arglist);
 }
 
 /* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */
@@ -9801,12 +10059,6 @@ finish_template_variable (tree var, tsubst_flags_t complain)
   tree templ = TREE_OPERAND (var, 0);
   tree arglist = TREE_OPERAND (var, 1);
 
-  /* We never want to return a VAR_DECL for a variable concept, since they
-     aren't instantiated.  In a template, leave the TEMPLATE_ID_EXPR alone.  */
-  bool concept_p = flag_concepts && variable_concept_p (templ);
-  if (concept_p && processing_template_decl)
-    return var;
-
   tree tmpl_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (templ));
   arglist = add_outermost_template_args (tmpl_args, arglist);
 
@@ -9827,19 +10079,6 @@ finish_template_variable (tree var, tsubst_flags_t complain)
       return error_mark_node;
     }
 
-  /* If a template-id refers to a specialization of a variable
-     concept, then the expression is true if and only if the
-     concept's constraints are satisfied by the given template
-     arguments.
-
-     NOTE: This is an extension of Concepts Lite TS that
-     allows constraints to be used in expressions. */
-  if (concept_p)
-    {
-      tree decl = DECL_TEMPLATE_RESULT (templ);
-      return evaluate_variable_concept (decl, arglist);
-    }
-
   return instantiate_template (templ, arglist, complain);
 }
 
@@ -10040,6 +10279,26 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
        return error_mark_node;
       break;
 
+    case SCOPE_REF:
+      if (pfd->include_nondeduced_p)
+       WALK_SUBTREE (TREE_OPERAND (t, 0));
+      break;
+
+    case REQUIRES_EXPR:
+      {
+       if (!fn)
+         return error_mark_node;
+
+       /* Recursively walk the type of each constraint variable.  */
+       tree p = TREE_OPERAND (t, 0);
+       while (p)
+         {
+           WALK_SUBTREE (TREE_TYPE (p));
+           p = TREE_CHAIN (p);
+         }
+      }
+      break;
+
     default:
       break;
     }
@@ -10103,6 +10362,126 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
   return result;
 }
 
+struct find_template_parameter_info
+{
+  explicit find_template_parameter_info (int d)
+    : max_depth (d)
+  {}
+
+  hash_set<tree> visited;
+  hash_set<tree> parms;
+  int max_depth;
+};
+
+/* Appends the declaration of T to the list in DATA.  */
+
+static int
+keep_template_parm (tree t, void* data)
+{
+  find_template_parameter_info *ftpi = (find_template_parameter_info*)data;
+
+  /* Template parameters declared within the expression are not part of
+     the parameter mapping. For example, in this concept:
+
+       template<typename T>
+       concept C = requires { <expr> } -> same_as<int>;
+
+     the return specifier same_as<int> declares a new decltype parameter
+     that must not be part of the parameter mapping. The same is true
+     for generic lambda parameters, lambda template parameters, etc.  */
+  int level;
+  int index;
+  template_parm_level_and_index (t, &level, &index);
+  if (level > ftpi->max_depth)
+    return 0;
+
+  /* Arguments like const T yield parameters like const T. This means that
+     a template-id like X<T, const T> would yield two distinct parameters:
+     T and const T. Adjust types to their unqualified versions.  */
+  if (TYPE_P (t))
+    t = TYPE_MAIN_VARIANT (t);
+  ftpi->parms.add (t);
+
+  return 0;
+}
+
+/* Ensure that we recursively examine certain terms that are not normally
+   visited in for_each_template_parm_r.  */
+
+static int
+any_template_parm_r (tree t, void *data)
+{
+  find_template_parameter_info *ftpi = (find_template_parameter_info*)data;
+
+#define WALK_SUBTREE(NODE)                                             \
+  do                                                                   \
+    {                                                                  \
+      for_each_template_parm (NODE, keep_template_parm, data,          \
+                             &ftpi->visited, true,                     \
+                             any_template_parm_r);                     \
+    }                                                                  \
+  while (0)
+
+  switch (TREE_CODE (t))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+      /* Search for template parameters in type aliases.  */
+      if (tree ats = alias_template_specialization_p (t, nt_opaque))
+       {
+         tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (ats);
+         WALK_SUBTREE (TI_ARGS (tinfo));
+        }
+      break;
+
+    case TEMPLATE_TYPE_PARM:
+      /* Type constraints of a placeholder type may contain parameters.  */
+      if (is_auto (t))
+       if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (t))
+         WALK_SUBTREE (constr);
+      break;
+
+    case TEMPLATE_ID_EXPR:
+      /* Search through references to variable templates.  */
+      WALK_SUBTREE (TREE_OPERAND (t, 0));
+      WALK_SUBTREE (TREE_OPERAND (t, 1));
+      break;
+
+    case CONSTRUCTOR:
+      if (TREE_TYPE (t))
+        WALK_SUBTREE (TREE_TYPE (t));
+      break;
+
+    case PARM_DECL:
+      /* A parameter or constraint variable may also depend on a template
+        parameter without explicitly naming it.  */
+      WALK_SUBTREE (TREE_TYPE (t));
+      break;
+
+    default:
+      break;
+    }
+
+  /* Keep walking.  */
+  return 0;
+}
+
+/* Returns a list of unique template parameters found within T.  */
+
+tree
+find_template_parameters (tree t, int depth)
+{
+  find_template_parameter_info ftpi (depth);
+  for_each_template_parm (t, keep_template_parm, &ftpi, &ftpi.visited,
+                         /*include_nondeduced*/true, any_template_parm_r);
+  tree list = NULL_TREE;
+  for (hash_set<tree>::iterator iter = ftpi.parms.begin();
+       iter != ftpi.parms.end(); ++iter)
+    list = tree_cons (NULL_TREE, *iter, list);
+  return list;
+}
+
 /* Returns true if T depends on any template parameter.  */
 
 int
@@ -10261,7 +10640,12 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
      anything else.  Do allow deduction substitution and decls usable in
      constant expressions.  */
   if (!targs && limit_bad_template_recursion (tldcl))
-    return false;
+    {
+      /* Avoid no_linkage_errors and unused function warnings for this
+        decl.  */
+      TREE_NO_WARNING (tldcl) = 1;
+      return false;
+    }
 
   /* When not -quiet, dump template instantiations other than functions, since
      announce_function will take care of those.  */
@@ -10430,7 +10814,31 @@ tsubst_friend_function (tree decl, tree args)
       DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
       DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
        = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
-    }
+
+      /* Attach the template requirements to the new declaration
+         for declaration matching. We need to rebuild the requirements
+         so that parameter levels match.  */
+      if (tree ci = get_constraints (decl))
+       {
+         tree parms = DECL_TEMPLATE_PARMS (new_friend);
+         tree args = generic_targs_for (new_friend);
+         tree treqs = tsubst_constraint (CI_TEMPLATE_REQS (ci), args,
+                                         tf_warning_or_error, NULL_TREE);
+         tree freqs = tsubst_constraint (CI_DECLARATOR_REQS (ci), args,
+                                         tf_warning_or_error, NULL_TREE);
+
+         /* Update the constraints -- these won't really be valid for
+            checking, but that's not what we need them for. These ensure
+            that the declared function can find the friend during
+            declaration matching.  */
+         tree new_ci = get_constraints (new_friend);
+         CI_TEMPLATE_REQS (new_ci) = treqs;
+         CI_DECLARATOR_REQS (new_ci) = freqs;
+
+         /* Also update the template parameter list.  */
+         TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
+       }
+    }
 
   /* The mangled name for the NEW_FRIEND is incorrect.  The function
      is not a template instantiation and should not be mangled like
@@ -10773,6 +11181,88 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
       else
        val = NULL_TREE;
     }
+  else if (flag_openmp
+          && is_attribute_p ("omp declare variant base",
+                             get_attribute_name (t)))
+    {
+      ++cp_unevaluated_operand;
+      tree varid
+       = tsubst_expr (TREE_PURPOSE (val), args, complain,
+                      in_decl, /*integral_constant_expression_p=*/false);
+      --cp_unevaluated_operand;
+      tree chain = TREE_CHAIN (val);
+      location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
+      tree ctx = copy_list (TREE_VALUE (val));
+      tree simd = get_identifier ("simd");
+      tree score = get_identifier (" score");
+      tree condition = get_identifier ("condition");
+      for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+       {
+         const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
+         TREE_VALUE (t1) = copy_list (TREE_VALUE (t1));
+         for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+           {
+             if (TREE_PURPOSE (t2) == simd && set[0] == 'c')
+               {
+                 tree clauses = TREE_VALUE (t2);
+                 clauses = tsubst_omp_clauses (clauses,
+                                               C_ORT_OMP_DECLARE_SIMD, args,
+                                               complain, in_decl);
+                 c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+                 clauses = finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
+                 TREE_VALUE (t2) = clauses;
+               }
+             else
+               {
+                 TREE_VALUE (t2) = copy_list (TREE_VALUE (t2));
+                 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+                   if (TREE_VALUE (t3))
+                     {
+                       bool allow_string
+                         = ((TREE_PURPOSE (t2) != condition || set[0] != 'u')
+                            && TREE_PURPOSE (t3) != score);
+                       tree v = TREE_VALUE (t3);
+                       if (TREE_CODE (v) == STRING_CST && allow_string)
+                         continue;
+                       v = tsubst_expr (v, args, complain, in_decl, true);
+                       v = fold_non_dependent_expr (v);
+                       if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
+                           || (TREE_PURPOSE (t3) == score
+                               ? TREE_CODE (v) != INTEGER_CST
+                               : !tree_fits_shwi_p (v)))
+                         {
+                           location_t loc
+                             = cp_expr_loc_or_loc (TREE_VALUE (t3),
+                                                   match_loc);
+                           if (TREE_PURPOSE (t3) == score)
+                             error_at (loc, "score argument must be "
+                                            "constant integer expression");
+                           else if (allow_string)
+                             error_at (loc, "property must be constant "
+                                            "integer expression or string "
+                                            "literal");
+                           else
+                             error_at (loc, "property must be constant "
+                                            "integer expression");
+                           return NULL_TREE;
+                         }
+                       else if (TREE_PURPOSE (t3) == score
+                                && tree_int_cst_sgn (v) < 0)
+                         {
+                           location_t loc
+                             = cp_expr_loc_or_loc (TREE_VALUE (t3),
+                                                   match_loc);
+                           error_at (loc, "score argument must be "
+                                          "non-negative");
+                           return NULL_TREE;
+                         }
+                       TREE_VALUE (t3) = v;
+                     }
+               }
+           }
+       }
+      val = tree_cons (varid, ctx, chain);
+    }
   /* If the first attribute argument is an identifier, don't
      pass it through tsubst.  Attributes like mode, format,
      cleanup and several target specific attributes expect it
@@ -10927,7 +11417,6 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
 static void
 perform_typedefs_access_check (tree tmpl, tree targs)
 {
-  location_t saved_location;
   unsigned i;
   qualified_typedef_usage_t *iter;
 
@@ -10936,7 +11425,6 @@ perform_typedefs_access_check (tree tmpl, tree targs)
          && TREE_CODE (tmpl) != FUNCTION_DECL))
     return;
 
-  saved_location = input_location;
   FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (tmpl), i, iter)
     {
       tree type_decl = iter->typedef_decl;
@@ -10952,12 +11440,11 @@ perform_typedefs_access_check (tree tmpl, tree targs)
 
       /* Make access check error messages point to the location
          of the use of the typedef.  */
-      input_location = iter->locus;
+      iloc_sentinel ils (iter->locus);
       perform_or_defer_access_check (TYPE_BINFO (type_scope),
                                     type_decl, type_decl,
                                     tf_warning_or_error);
     }
-    input_location = saved_location;
 }
 
 static tree
@@ -11334,6 +11821,9 @@ instantiate_class_template_1 (tree type)
                              error ("flexible array member %qD in union", r);
                              TREE_TYPE (r) = error_mark_node;
                            }
+                         else if (!verify_type_context (input_location,
+                                                        TCTX_FIELD, rtype))
+                           TREE_TYPE (r) = error_mark_node;
                        }
 
                      /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
@@ -11531,7 +12021,7 @@ instantiate_class_template (tree type)
   return ret;
 }
 
-static tree
+tree
 tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   tree r;
@@ -11549,6 +12039,7 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (!(complain & tf_warning))
        --c_inhibit_evaluation_warnings;
     }
+
   return r;
 }
 
@@ -11657,7 +12148,23 @@ use_pack_expansion_extra_args_p (tree parm_packs,
   if (parm_packs == NULL_TREE)
     return false;
   else if (has_empty_arg)
-    return true;
+    {
+      /* If all the actual packs are pack expansions, we can still
+        subsitute directly.  */
+      for (tree p = parm_packs; p; p = TREE_CHAIN (p))
+       {
+         tree a = TREE_VALUE (p);
+         if (TREE_CODE (a) == ARGUMENT_PACK_SELECT)
+           a = ARGUMENT_PACK_SELECT_FROM_PACK (a);
+         a = ARGUMENT_PACK_ARGS (a);
+         if (TREE_VEC_LENGTH (a) == 1)
+           a = TREE_VEC_ELT (a, 0);
+         if (PACK_EXPANSION_P (a))
+           continue;
+         return true;
+       }
+      return false;
+    }
 
   bool has_expansion_arg = false;
   for (int i = 0 ; i < arg_pack_len; ++i)
@@ -11764,10 +12271,6 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
       ARGUMENT_PACK_SELECT_INDEX (aps) = index;
     }
 
-  // Any local specialization bindings arising from this substitution
-  // cannot be reused for a different INDEX.
-  local_specialization_stack lss (lss_copy);
-
   /* Substitute into the PATTERN with the (possibly altered)
      arguments.  */
   if (pattern == in_decl)
@@ -11776,14 +12279,6 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
     t = tsubst_decl (pattern, args, complain);
   else if (pattern == error_mark_node)
     t = error_mark_node;
-  else if (constraint_p (pattern))
-    {
-      if (processing_template_decl)
-       t = tsubst_constraint (pattern, args, complain, in_decl);
-      else
-       t = (constraints_satisfied_p (pattern, args)
-            ? boolean_true_node : boolean_false_node);
-    }
   else if (!TYPE_P (pattern))
     t = tsubst_expr (pattern, args, complain, in_decl,
                     /*integral_constant_expression_p=*/false);
@@ -12149,7 +12644,22 @@ add_extra_args (tree extra, tree args)
       gcc_assert (!TREE_PURPOSE (extra));
       extra = TREE_VALUE (extra);
     }
-  return add_to_template_args (extra, args);
+#if 1
+  /* I think we should always be able to substitute dependent args into the
+     pattern.  If that turns out to be incorrect in some cases, enable the
+     alternate code (and add complain/in_decl parms to this function).  */
+  gcc_checking_assert (!uses_template_parms (extra));
+#else
+  if (!uses_template_parms (extra))
+    {
+      gcc_unreachable ();
+      extra = tsubst_template_args (extra, args, complain, in_decl);
+      args = add_outermost_template_args (args, extra);
+    }
+  else
+#endif
+    args = add_to_template_args (extra, args);
+  return args;
 }
 
 /* Substitute ARGS into T, which is an pack expansion
@@ -12263,7 +12773,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         {
          int idx;
           template_parm_level_and_index (parm_pack, &level, &idx);
-
           if (level <= levels)
             arg_pack = TMPL_ARG (args, level, idx);
         }
@@ -12317,6 +12826,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
          /* We can't substitute for this parameter pack.  We use a flag as
             well as the missing_level counter because function parameter
             packs don't have a level.  */
+          if (!(processing_template_decl || is_auto (parm_pack)))
+           {
+             gcc_unreachable ();
+           }
          gcc_assert (processing_template_decl || is_auto (parm_pack));
          unsubstituted_packs = true;
        }
@@ -12525,9 +13038,33 @@ copy_template_args (tree t)
   return new_vec;
 }
 
+/* Substitute ARGS into the *_ARGUMENT_PACK orig_arg.  */
+
+tree
+tsubst_argument_pack (tree orig_arg, tree args, tsubst_flags_t complain,
+                     tree in_decl)
+{
+  /* Substitute into each of the arguments.  */
+  tree new_arg = TYPE_P (orig_arg)
+    ? cxx_make_type (TREE_CODE (orig_arg))
+    : make_node (TREE_CODE (orig_arg));
+
+  tree pack_args = tsubst_template_args (ARGUMENT_PACK_ARGS (orig_arg),
+                                        args, complain, in_decl);
+  if (pack_args == error_mark_node)
+    new_arg = error_mark_node;
+  else
+    SET_ARGUMENT_PACK_ARGS (new_arg, pack_args);
+
+  if (TREE_CODE (new_arg) == NONTYPE_ARGUMENT_PACK)
+    TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg);
+
+  return new_arg;
+}
+
 /* Substitute ARGS into the vector or list of template arguments T.  */
 
-static tree
+tree
 tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   tree orig_t = t;
@@ -12562,22 +13099,7 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
             expanded_len_adjust += TREE_VEC_LENGTH (new_arg) - 1;
         }
       else if (ARGUMENT_PACK_P (orig_arg))
-        {
-          /* Substitute into each of the arguments.  */
-          new_arg = TYPE_P (orig_arg)
-            ? cxx_make_type (TREE_CODE (orig_arg))
-            : make_node (TREE_CODE (orig_arg));
-
-         tree pack_args = tsubst_template_args (ARGUMENT_PACK_ARGS (orig_arg),
-                                                args, complain, in_decl);
-          if (pack_args == error_mark_node)
-            new_arg = error_mark_node;
-         else
-           SET_ARGUMENT_PACK_ARGS (new_arg, pack_args);
-
-          if (TREE_CODE (new_arg) == NONTYPE_ARGUMENT_PACK)
-           TREE_CONSTANT (new_arg) = TREE_CONSTANT (orig_arg);
-        }
+       new_arg = tsubst_argument_pack (orig_arg, args, complain, in_decl);
       else
        new_arg = tsubst_template_arg (orig_arg, args, complain, in_decl);
 
@@ -12710,6 +13232,7 @@ tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
 
   default_value = TREE_PURPOSE (t);
   parm_decl = TREE_VALUE (t);
+  tree constraint = TEMPLATE_PARM_CONSTRAINTS (t);
 
   parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
   if (TREE_CODE (parm_decl) == PARM_DECL
@@ -12717,8 +13240,11 @@ tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
     parm_decl = error_mark_node;
   default_value = tsubst_template_arg (default_value, args,
                                       complain, NULL_TREE);
+  constraint = tsubst_constraint (constraint, args, complain, NULL_TREE);
 
-  return build_tree_list (default_value, parm_decl);
+  tree r = build_tree_list (default_value, parm_decl);
+  TEMPLATE_PARM_CONSTRAINTS (r) = constraint;
+  return r;
 }
 
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
@@ -12798,7 +13324,7 @@ tsubst_aggr_type (tree t,
     }
 }
 
-static GTY((cache)) tree_cache_map *defarg_inst;
+static GTY((cache)) decl_tree_cache_map *defarg_inst;
 
 /* Substitute into the default argument ARG (a default argument for
    FN), which has the indicated TYPE.  */
@@ -12872,7 +13398,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
   if (arg != error_mark_node && !cp_unevaluated_operand)
     {
       if (!defarg_inst)
-       defarg_inst = tree_cache_map::create_ggc (37);
+       defarg_inst = decl_tree_cache_map::create_ggc (37);
       defarg_inst->put (parm, arg);
     }
 
@@ -12909,7 +13435,7 @@ tsubst_default_arguments (tree fn, tsubst_flags_t complain)
 }
 
 /* Hash table mapping a FUNCTION_DECL to its dependent explicit-specifier.  */
-static GTY((cache)) tree_cache_map *explicit_specifier_map;
+static GTY((cache)) decl_tree_cache_map *explicit_specifier_map;
 
 /* Store a pair to EXPLICIT_SPECIFIER_MAP.  */
 
@@ -12917,7 +13443,7 @@ void
 store_explicit_specifier (tree v, tree t)
 {
   if (!explicit_specifier_map)
-    explicit_specifier_map = tree_cache_map::create_ggc (37);
+    explicit_specifier_map = decl_tree_cache_map::create_ggc (37);
   DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (v) = true;
   explicit_specifier_map->put (v, t);
 }
@@ -13144,14 +13670,11 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
       && !grok_op_properties (r, /*complain=*/false))
     return error_mark_node;
 
-  /* When instantiating a constrained member, substitute
-     into the constraints to create a new constraint.  */
+  /* Associate the constraints directly with the instantiation. We
+     don't substitute through the constraints; that's only done when
+     they are checked.  */
   if (tree ci = get_constraints (t))
-    if (member)
-      {
-       ci = tsubst_constraint_info (ci, argvec, complain, NULL_TREE);
-       set_constraints (r, ci);
-      }
+    set_constraints (r, ci);
 
   if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
     SET_DECL_FRIEND_CONTEXT (r,
@@ -13234,6 +13757,11 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
 
   apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
                                  args, complain, in_decl);
+  if (flag_openmp)
+    if (tree attr = lookup_attribute ("omp declare variant base",
+                                     DECL_ATTRIBUTES (r)))
+      omp_declare_variant_finalize (r, attr);
+
   return r;
 }
 
@@ -13898,8 +14426,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            /* Wait until cp_finish_decl to set this again, to handle
               circular dependency (template/instantiate6.C). */
            DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) = 0;
-           type = check_var_type (DECL_NAME (r), type);
-
+           type = check_var_type (DECL_NAME (r), type,
+                                  DECL_SOURCE_LOCATION (r));
            if (DECL_HAS_VALUE_EXPR_P (t))
              {
                tree ve = DECL_VALUE_EXPR (t);
@@ -13959,6 +14487,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 
            DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
            SET_DECL_IMPLICIT_INSTANTIATION (r);
+           /* Remember whether we require constant initialization of
+              a non-constant template variable.  */
+           TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (r))
+             = TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (t));
            if (!error_operand_p (r) || (complain & tf_error))
              register_specialization (r, gen_tmpl, argvec, false, hash);
          }
@@ -14003,6 +14535,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Substitute into the complete parameter type list PARMS.  */
+
+tree
+tsubst_function_parms (tree parms,
+                      tree args,
+                      tsubst_flags_t complain,
+                      tree in_decl)
+{
+  return tsubst_arg_types (parms, args, NULL_TREE, complain, in_decl);
+}
+
 /* Substitute into the ARG_TYPES of a function type.
    If END is a TREE_CHAIN, leave it and any following types
    un-substituted.  */
@@ -14405,7 +14948,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     {
       tree decl = TYPE_NAME (t);
 
-      if (alias_template_specialization_p (t))
+      if (alias_template_specialization_p (t, nt_opaque))
        {
          /* DECL represents an alias template and we want to
             instantiate it.  */
@@ -14567,6 +15110,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            if (code == TEMPLATE_TYPE_PARM)
              {
                int quals;
+
+               /* When building concept checks for the purpose of
+                  deducing placeholders, we can end up with wildcards
+                  where types are expected. Adjust this to the deduced
+                  value.  */
+               if (TREE_CODE (arg) == WILDCARD_DECL)
+                 arg = TREE_TYPE (TREE_TYPE (arg));
+
                gcc_assert (TYPE_P (arg));
 
                quals = cp_type_quals (arg) | cp_type_quals (t);
@@ -14698,10 +15249,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
                 if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
                  {
-                   /* Propagate constraints on placeholders.  */
+                   /* Propagate constraints on placeholders since they are
+                      only instantiated during satisfaction.  */
                    if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (t))
-                     PLACEHOLDER_TYPE_CONSTRAINTS (r)
-                       = tsubst_constraint (constr, args, complain, in_decl);
+                     PLACEHOLDER_TYPE_CONSTRAINTS (r) = constr;
                    else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t))
                      {
                        pl = tsubst_copy (pl, args, complain, in_decl);
@@ -15139,24 +15690,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                                      /*function_p*/false,
                                      /*integral_constant_expression*/false);
 
-       if (DECLTYPE_FOR_INIT_CAPTURE (t))
-         {
-           if (type == NULL_TREE)
-             {
-               if (complain & tf_error)
-                 error ("empty initializer in lambda init-capture");
-               type = error_mark_node;
-             }
-           else if (TREE_CODE (type) == TREE_LIST)
-             type = build_x_compound_expr_from_list (type, ELK_INIT, complain);
-         }
-
        --cp_unevaluated_operand;
        --c_inhibit_evaluation_warnings;
 
        if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
          type = lambda_capture_field_type (type,
-                                           DECLTYPE_FOR_INIT_CAPTURE (t),
+                                           false /*explicit_init*/,
                                            DECLTYPE_FOR_REF_CAPTURE (t));
        else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
          type = lambda_proxy_type (type);
@@ -15861,11 +16400,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                expanded = make_argument_pack (expanded);
 
              if (TYPE_P (expanded))
-               return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+               return cxx_sizeof_or_alignof_type (input_location,
+                                                  expanded, SIZEOF_EXPR,
                                                   false,
                                                   complain & tf_error);
              else
-               return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+               return cxx_sizeof_or_alignof_expr (input_location,
+                                                  expanded, SIZEOF_EXPR,
                                                    complain & tf_error);
            }
          else
@@ -15961,8 +16502,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case TRUTH_OR_EXPR:
     case RSHIFT_EXPR:
     case LSHIFT_EXPR:
-    case RROTATE_EXPR:
-    case LROTATE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
     case MAX_EXPR:
@@ -16319,6 +16858,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
        case OMP_CLAUSE_MAP:
        case OMP_CLAUSE_NONTEMPORAL:
        case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
        case OMP_CLAUSE_INCLUSIVE:
        case OMP_CLAUSE_EXCLUSIVE:
@@ -16420,6 +16960,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
        case OMP_CLAUSE_SIMD:
        case OMP_CLAUSE_DEFAULTMAP:
        case OMP_CLAUSE_ORDER:
+       case OMP_CLAUSE_BIND:
        case OMP_CLAUSE_INDEPENDENT:
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_SEQ:
@@ -16442,6 +16983,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
          case OMP_CLAUSE_IN_REDUCTION:
          case OMP_CLAUSE_TASK_REDUCTION:
          case OMP_CLAUSE_USE_DEVICE_PTR:
+         case OMP_CLAUSE_USE_DEVICE_ADDR:
          case OMP_CLAUSE_IS_DEVICE_PTR:
          case OMP_CLAUSE_INCLUSIVE:
          case OMP_CLAUSE_EXCLUSIVE:
@@ -16748,7 +17290,8 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
     {
       tree *pc;
       int j;
-      for (j = (omp_parallel_combined_clauses == NULL ? 1 : 0); j < 2; j++)
+      for (j = ((omp_parallel_combined_clauses == NULL
+               || TREE_CODE (t) == OMP_LOOP) ? 1 : 0); j < 2; j++)
        {
          for (pc = j ? clauses : omp_parallel_combined_clauses; *pc; )
            {
@@ -16788,7 +17331,10 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
        }
       if (*pc == NULL_TREE)
        {
-         tree c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+         tree c = build_omp_clause (input_location,
+                                    TREE_CODE (t) == OMP_LOOP
+                                    ? OMP_CLAUSE_LASTPRIVATE
+                                    : OMP_CLAUSE_PRIVATE);
          OMP_CLAUSE_DECL (c) = decl;
          c = finish_omp_clauses (c, C_ORT_OMP);
          if (c)
@@ -17113,6 +17659,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
        else
          {
            init = DECL_INITIAL (decl);
+           /* The following tsubst call will clear the DECL_TEMPLATE_INFO
+              for local variables, so save if DECL was declared constinit.  */
+           const bool constinit_p
+             = (VAR_P (decl)
+                && DECL_LANG_SPECIFIC (decl)
+                && DECL_TEMPLATE_INFO (decl)
+                && TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (decl)));
            decl = tsubst (decl, args, complain, in_decl);
            if (decl != error_mark_node)
              {
@@ -17151,7 +17704,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                  }
                else
                  {
-                   int const_init = false;
+                   bool const_init = false;
                    unsigned int cnt = 0;
                    tree first = NULL_TREE, ndecl = error_mark_node;
                    maybe_push_decl (decl);
@@ -17172,7 +17725,8 @@ 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);
 
-                   cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+                   cp_finish_decl (decl, init, const_init, NULL_TREE,
+                                   constinit_p ? LOOKUP_CONSTINIT : 0);
 
                    if (ndecl != error_mark_node)
                      cp_finish_decomp (ndecl, first, cnt);
@@ -17405,8 +17959,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                                                  complain, in_decl);
        tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
                                                complain, in_decl);
-       tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
-                              clobbers, labels, ASM_INLINE_P (t));
+       tmp = finish_asm_stmt (EXPR_LOCATION (t), ASM_VOLATILE_P (t), string,
+                              outputs, inputs, clobbers, labels,
+                              ASM_INLINE_P (t));
        tree asm_expr = tmp;
        if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
          asm_expr = TREE_OPERAND (asm_expr, 0);
@@ -17508,6 +18063,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 
     case OACC_KERNELS:
     case OACC_PARALLEL:
+    case OACC_SERIAL:
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_ACC, args, complain,
                                in_decl);
       stmt = begin_omp_parallel ();
@@ -18023,6 +18579,33 @@ tsubst_non_call_postfix_expression (tree t, tree args,
   return t;
 }
 
+/* Subroutine of tsubst_lambda_expr: add the FIELD/INIT capture pair to the
+   LAMBDA_EXPR_CAPTURE_LIST passed in LIST.  Do deduction for a previously
+   dependent init-capture.  */
+
+static void
+prepend_one_capture (tree field, tree init, tree &list,
+                    tsubst_flags_t complain)
+{
+  if (tree auto_node = type_uses_auto (TREE_TYPE (field)))
+    {
+      tree type = NULL_TREE;
+      if (!init)
+       {
+         if (complain & tf_error)
+           error ("empty initializer in lambda init-capture");
+         init = error_mark_node;
+       }
+      else if (TREE_CODE (init) == TREE_LIST)
+       init = build_x_compound_expr_from_list (init, ELK_INIT, complain);
+      if (!type)
+       type = do_auto_deduction (TREE_TYPE (field), init, auto_node, complain);
+      TREE_TYPE (field) = type;
+      cp_apply_type_quals_to_decl (cp_type_quals (type), field);
+    }
+  list = tree_cons (field, init, list);
+}
+
 /* T is a LAMBDA_EXPR.  Generate a new LAMBDA_EXPR for the current
    instantiation context.  Instantiating a pack expansion containing a lambda
    might result in multiple lambdas all based on the same lambda in the
@@ -18034,17 +18617,8 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   tree oldfn = lambda_function (t);
   in_decl = oldfn;
 
-  /* If we have already specialized this lambda expr, reuse it.  See
-     PR c++/87322.  */
-  if (local_specializations)
-    if (tree r = retrieve_local_specialization (t))
-      return r;
-
   tree r = build_lambda_expr ();
 
-  if (local_specializations)
-    register_local_specialization (r, t);
-
   LAMBDA_EXPR_LOCATION (r)
     = LAMBDA_EXPR_LOCATION (t);
   LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
@@ -18097,15 +18671,15 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          gcc_assert (TREE_CODE (init) == TREE_VEC
                      && TREE_VEC_LENGTH (init) == len);
          for (int i = 0; i < len; ++i)
-           LAMBDA_EXPR_CAPTURE_LIST (r)
-             = tree_cons (TREE_VEC_ELT (field, i),
-                          TREE_VEC_ELT (init, i),
-                          LAMBDA_EXPR_CAPTURE_LIST (r));
+           prepend_one_capture (TREE_VEC_ELT (field, i),
+                                TREE_VEC_ELT (init, i),
+                                LAMBDA_EXPR_CAPTURE_LIST (r),
+                                complain);
        }
       else
        {
-         LAMBDA_EXPR_CAPTURE_LIST (r)
-           = tree_cons (field, init, LAMBDA_EXPR_CAPTURE_LIST (r));
+         prepend_one_capture (field, init, LAMBDA_EXPR_CAPTURE_LIST (r),
+                              complain);
 
          if (id_equal (DECL_NAME (field), "__this"))
            LAMBDA_EXPR_THIS_CAPTURE (r) = field;
@@ -18327,8 +18901,29 @@ tsubst_copy_and_build (tree t,
            RETURN (templ);
          }
 
+       if (concept_definition_p (templ))
+         {
+           tree check = build_concept_check (templ, targs, complain);
+           if (check == error_mark_node)
+             RETURN (error_mark_node);
+
+           tree id = unpack_concept_check (check);
+
+           /* If we built a function concept check, return the underlying
+              template-id. So we can evaluate it as a function call.  */
+           if (function_concept_p (TREE_OPERAND (id, 0)))
+             RETURN (id);
+
+           RETURN (check);
+         }
+
        if (variable_template_p (templ))
-         RETURN (lookup_and_finish_template_variable (templ, targs, complain));
+         {
+           tree r = lookup_and_finish_template_variable (templ, targs,
+                                                         complain);
+           r = maybe_wrap_with_location (r, EXPR_LOCATION (t));
+           RETURN (r);
+         }
 
        if (TREE_CODE (templ) == COMPONENT_REF)
          {
@@ -18433,19 +19028,19 @@ tsubst_copy_and_build (tree t,
        switch (TREE_CODE (t))
          {
          case CAST_EXPR:
-           r = build_functional_cast (type, op, complain);
+           r = build_functional_cast (input_location, type, op, complain);
            break;
          case REINTERPRET_CAST_EXPR:
-           r = build_reinterpret_cast (type, op, complain);
+           r = build_reinterpret_cast (input_location, type, op, complain);
            break;
          case CONST_CAST_EXPR:
-           r = build_const_cast (type, op, complain);
+           r = build_const_cast (input_location, type, op, complain);
            break;
          case DYNAMIC_CAST_EXPR:
-           r = build_dynamic_cast (type, op, complain);
+           r = build_dynamic_cast (input_location, type, op, complain);
            break;
          case STATIC_CAST_EXPR:
-           r = build_static_cast (type, op, complain);
+           r = build_static_cast (input_location, type, op, complain);
            break;
          default:
            gcc_unreachable ();
@@ -18510,8 +19105,6 @@ tsubst_copy_and_build (tree t,
     case TRUTH_OR_EXPR:
     case RSHIFT_EXPR:
     case LSHIFT_EXPR:
-    case RROTATE_EXPR:
-    case LROTATE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
     case MAX_EXPR:
@@ -18520,6 +19113,7 @@ tsubst_copy_and_build (tree t,
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+    case SPACESHIP_EXPR:
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       {
@@ -18602,10 +19196,12 @@ tsubst_copy_and_build (tree t,
            --c_inhibit_evaluation_warnings;
          }
         if (TYPE_P (op1))
-         r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), std_alignof,
+         r = cxx_sizeof_or_alignof_type (input_location,
+                                         op1, TREE_CODE (t), std_alignof,
                                          complain & tf_error);
        else
-         r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+         r = cxx_sizeof_or_alignof_expr (input_location,
+                                         op1, TREE_CODE (t),
                                          complain & tf_error);
        if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
          {
@@ -18740,7 +19336,7 @@ tsubst_copy_and_build (tree t,
       {
        tree op0 = RECUR (TREE_OPERAND (t, 0));
        tree op1 = RECUR (TREE_OPERAND (t, 1));
-       RETURN (delete_sanity (op0, op1,
+       RETURN (delete_sanity (input_location, op0, op1,
                               DELETE_EXPR_USE_VEC (t),
                               DELETE_EXPR_USE_GLOBAL (t),
                               complain));
@@ -18963,10 +19559,10 @@ tsubst_copy_and_build (tree t,
 
                    bool diag = true;
                    if (in_lambda)
-                     error_at (cp_expr_loc_or_loc (t, input_location),
+                     error_at (cp_expr_loc_or_input_loc (t),
                                msg, function);
                    else
-                     diag = permerror (cp_expr_loc_or_loc (t, input_location),
+                     diag = permerror (cp_expr_loc_or_input_loc (t),
                                        msg, function);
                    if (diag)
                      {
@@ -18981,8 +19577,7 @@ tsubst_copy_and_build (tree t,
                          /* Can't say anything more.  */;
                        else if (DECL_CLASS_SCOPE_P (fn))
                          {
-                           location_t loc = cp_expr_loc_or_loc (t,
-                                                             input_location);
+                           location_t loc = cp_expr_loc_or_input_loc (t);
                            inform (loc,
                                    "declarations in dependent base %qT are "
                                    "not found by unqualified lookup",
@@ -19030,14 +19625,13 @@ tsubst_copy_and_build (tree t,
              gcc_assert (nargs == 1);
              if (vec_safe_length (call_args) != 1)
                {
-                 error_at (cp_expr_loc_or_loc (t, input_location),
+                 error_at (cp_expr_loc_or_input_loc (t),
                            "wrong number of arguments to "
                            "%<__builtin_launder%>");
                  ret = error_mark_node;
                }
              else
-               ret = finish_builtin_launder (cp_expr_loc_or_loc (t,
-                                                              input_location),
+               ret = finish_builtin_launder (cp_expr_loc_or_input_loc (t),
                                              (*call_args)[0], complain);
              break;
 
@@ -19045,7 +19639,7 @@ tsubst_copy_and_build (tree t,
              gcc_assert (nargs == 1);
              if (vec_safe_length (call_args) != 1)
                {
-                 error_at (cp_expr_loc_or_loc (t, input_location),
+                 error_at (cp_expr_loc_or_input_loc (t),
                            "wrong number of arguments to "
                            "%<__builtin_convertvector%>");
                  ret = error_mark_node;
@@ -19093,6 +19687,20 @@ tsubst_copy_and_build (tree t,
                       /*fn_p=*/NULL,
                       complain));
          }
+       else if (concept_check_p (function))
+         {
+           /* FUNCTION is a template-id referring to a concept definition.  */
+           tree id = unpack_concept_check (function);
+           tree tmpl = TREE_OPERAND (id, 0);
+           tree args = TREE_OPERAND (id, 1);
+
+           /* Calls to standard and variable concepts should have been
+              previously diagnosed.  */
+           gcc_assert (function_concept_p (tmpl));
+
+           /* Ensure the result is wrapped as a call expression.  */
+           ret = build_concept_check (tmpl, args, tf_warning_or_error);
+         }
        else
          ret = finish_call_expr (function, &call_args,
                                  /*disallow_virtual=*/qualified_p,
@@ -19355,7 +19963,7 @@ tsubst_copy_and_build (tree t,
 
     case THROW_EXPR:
       RETURN (build_throw
-       (RECUR (TREE_OPERAND (t, 0))));
+       (input_location, RECUR (TREE_OPERAND (t, 0))));
 
     case CONSTRUCTOR:
       {
@@ -19524,7 +20132,8 @@ tsubst_copy_and_build (tree t,
        else if (type2)
          type2 = tsubst (type2, args, complain, in_decl);
 
-       RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2));
+       RETURN (finish_trait_expr (TRAIT_EXPR_LOCATION (t),
+                                  TRAIT_EXPR_KIND (t), type1, type2));
       }
 
     case STMT_EXPR:
@@ -19586,7 +20195,12 @@ tsubst_copy_and_build (tree t,
       }
 
     case REQUIRES_EXPR:
-      RETURN (tsubst_requires_expr (t, args, complain, in_decl));
+      {
+       tree r = tsubst_requires_expr (t, args, tf_none, in_decl);
+       if (r == error_mark_node && (complain & tf_error))
+         tsubst_requires_expr (t, args, complain, in_decl);
+       RETURN (r);
+      }
 
     case RANGE_EXPR:
       /* No need to substitute further, a RANGE_EXPR will always be built
@@ -19884,8 +20498,9 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      instantiate all the alternate entry points as well.  We do this
      by cloning the instantiation of the main entry point, not by
      instantiating the template clones.  */
-  if (DECL_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (gen_tmpl)))
-    clone_function_decl (fndecl, /*update_methods=*/false);
+  if (tree chain = DECL_CHAIN (gen_tmpl))
+    if (DECL_P (chain) && DECL_CLONED_FUNCTION_P (chain))
+      clone_function_decl (fndecl, /*update_methods=*/false);
 
   if (!access_ok)
     {
@@ -19922,8 +20537,6 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
 {
   if (tmpl == error_mark_node || args == error_mark_node)
     return error_mark_node;
-  if (!push_tinst_level (tmpl, args))
-    return error_mark_node;
 
   args =
     coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
@@ -19931,6 +20544,22 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
                                     /*require_all_args=*/true,
                                     /*use_default_args=*/true);
 
+  /* FIXME check for satisfaction in check_instantiated_args.  */
+  if (flag_concepts
+      && !any_dependent_template_arguments_p (args)
+      && !constraints_satisfied_p (tmpl, args))
+    {
+      if (complain & tf_error)
+       {
+         auto_diagnostic_group d;
+         error ("template constraint failure for %qD", tmpl);
+         diagnose_constraints (input_location, tmpl, args);
+       }
+      return error_mark_node;
+    }
+
+  if (!push_tinst_level (tmpl, args))
+    return error_mark_node;
   tree r = instantiate_template (tmpl, args, complain);
   pop_tinst_level ();
 
@@ -20563,7 +21192,7 @@ static bool
 deducible_expression (tree expr)
 {
   /* Strip implicit conversions.  */
-  while (CONVERT_EXPR_P (expr))
+  while (CONVERT_EXPR_P (expr) || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
     expr = TREE_OPERAND (expr, 0);
   return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX);
 }
@@ -22030,8 +22659,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
   /* I don't think this will do the right thing with respect to types.
      But the only case I've seen it in so far has been array bounds, where
      signedness is the only information lost, and I think that will be
-     okay.  */
-  while (CONVERT_EXPR_P (parm))
+     okay.  VIEW_CONVERT_EXPR can appear with class NTTP, thanks to
+     finish_id_expression_1, and are also OK.  */
+  while (CONVERT_EXPR_P (parm) || TREE_CODE (parm) == VIEW_CONVERT_EXPR)
     parm = TREE_OPERAND (parm, 0);
 
   if (arg == error_mark_node)
@@ -22060,11 +22690,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
       unsigned i;
       tree orig_parm = parm;
 
-      /* Replace T with std::initializer_list<T> for deduction.  */
-      if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
-         && flag_deduce_init_list)
-       parm = listify (parm);
-
       if (!is_std_init_list (parm)
          && TREE_CODE (parm) != ARRAY_TYPE)
        /* We can only deduce from an initializer list argument if the
@@ -23187,10 +23812,11 @@ more_specialized_fn (tree pat1, tree pat2, int len)
      constrained template.  */
   if (!lose1 && !lose2)
     {
-      tree c1 = get_constraints (DECL_TEMPLATE_RESULT (pat1));
-      tree c2 = get_constraints (DECL_TEMPLATE_RESULT (pat2));
-      lose1 = !subsumes_constraints (c1, c2);
-      lose2 = !subsumes_constraints (c2, c1);
+      int winner = more_constrained (decl1, decl2);
+      if (winner > 0)
+       lose2 = true;
+      else if (winner < 0)
+       lose1 = true;
     }
 
   /* All things being equal, if the next argument is a pack expansion
@@ -23262,7 +23888,7 @@ more_specialized_partial_spec (tree tmpl, tree pat1, tree pat2)
   /* If both deductions succeed, the partial ordering selects the more
      constrained template.  */
   if (!winner && any_deductions)
-    return more_constrained (tmpl1, tmpl2);
+    winner = more_constrained (tmpl1, tmpl2);
 
   /* In the case of a tie where at least one of the templates
      has a parameter pack at the end, the template with the most
@@ -23843,7 +24469,7 @@ do_decl_instantiation (tree decl, tree storage)
     ;
   else if (storage == ridpointers[(int) RID_EXTERN])
     {
-      if (!in_system_header_at (input_location) && (cxx_dialect == cxx98))
+      if (cxx_dialect == cxx98)
        pedwarn (input_location, OPT_Wpedantic,
                 "ISO C++ 1998 forbids the use of %<extern%> on explicit "
                 "instantiations");
@@ -23925,20 +24551,17 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   if (storage != NULL_TREE)
     {
-      if (!in_system_header_at (input_location))
+      if (storage == ridpointers[(int) RID_EXTERN])
        {
-         if (storage == ridpointers[(int) RID_EXTERN])
-           {
-             if (cxx_dialect == cxx98)
-               pedwarn (input_location, OPT_Wpedantic,
-                        "ISO C++ 1998 forbids the use of %<extern%> on "
-                        "explicit instantiations");
-           }
-         else
+         if (cxx_dialect == cxx98)
            pedwarn (input_location, OPT_Wpedantic,
-                    "ISO C++ forbids the use of %qE"
-                    " on explicit instantiations", storage);
+                    "ISO C++ 1998 forbids the use of %<extern%> on "
+                    "explicit instantiations");
        }
+      else
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ forbids the use of %qE"
+                " on explicit instantiations", storage);
 
       if (storage == ridpointers[(int) RID_INLINE])
        nomem_p = 1;
@@ -24310,12 +24933,11 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
        }
       else if (push_tinst_level (fn))
        {
+         push_to_top_level ();
          push_access_scope (fn);
          push_deferring_access_checks (dk_no_deferred);
          input_location = DECL_SOURCE_LOCATION (fn);
 
-         tree save_ccp = current_class_ptr;
-         tree save_ccr = current_class_ref;
          /* If needed, set current_class_ptr for the benefit of
             tsubst_copy/PARM_DECL.  */
          tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
@@ -24341,9 +24963,6 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
                                        /*function_p=*/false,
                                        /*i_c_e_p=*/true);
 
-         current_class_ptr = save_ccp;
-         current_class_ref = save_ccr;
-
          /* Build up the noexcept-specification.  */
          spec = build_noexcept_spec (noex, tf_warning_or_error);
 
@@ -24353,6 +24972,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
          pop_deferring_access_checks ();
          pop_access_scope (fn);
          pop_tinst_level ();
+         pop_from_top_level ();
        }
       else
        spec = noexcept_false_spec;
@@ -24370,14 +24990,14 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
       TREE_TYPE (fn) = build_exception_variant (fntype, spec);
       if (orig_fn)
        TREE_TYPE (orig_fn) = TREE_TYPE (fn);
-    }
 
-  FOR_EACH_CLONE (clone, fn)
-    {
-      if (TREE_TYPE (clone) == fntype)
-       TREE_TYPE (clone) = TREE_TYPE (fn);
-      else
-       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
+      FOR_EACH_CLONE (clone, fn)
+       {
+         if (TREE_TYPE (clone) == fntype)
+           TREE_TYPE (clone) = TREE_TYPE (fn);
+         else
+           TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
+       }
     }
 
   return true;
@@ -24658,22 +25278,6 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
        add_pending_template (d);
       goto out;
     }
-  /* Tell the repository that D is available in this translation unit
-     -- and see if it is supposed to be instantiated here.  */
-  if (TREE_PUBLIC (d) && !DECL_REALLY_EXTERN (d) && !repo_emit_p (d))
-    {
-      /* In a PCH file, despite the fact that the repository hasn't
-        requested instantiation in the PCH it is still possible that
-        an instantiation will be required in a file that includes the
-        PCH.  */
-      if (pch_file)
-       add_pending_template (d);
-      /* Instantiate inline functions so that the inliner can do its
-        job, even though we'll not be emitting a copy of this
-        function.  */
-      if (!(TREE_CODE (d) == FUNCTION_DECL && possibly_inlined_p (d)))
-       goto out;
-    }
 
   bool push_to_top, nested;
   tree fn_context;
@@ -24739,7 +25343,9 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
         push_nested_class (DECL_CONTEXT (d));
 
       const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
-      cp_finish_decl (d, init, const_init, NULL_TREE, 0);
+      int flags = (TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (d))
+                  ? LOOKUP_CONSTINIT : 0);
+      cp_finish_decl (d, init, const_init, NULL_TREE, flags);
 
       if (enter_context)
         pop_nested_class ();
@@ -25221,29 +25827,26 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
     {
       if (cxx_dialect < cxx2a)
        {
-         error ("non-type template parameters of class type only available "
-                "with %<-std=c++2a%> or %<-std=gnu++2a%>");
+         if (complain & tf_error)
+           error ("non-type template parameters of class type only available "
+                  "with %<-std=c++2a%> or %<-std=gnu++2a%>");
          return true;
        }
       if (dependent_type_p (type))
        return false;
       if (!complete_type_or_else (type, NULL_TREE))
        return true;
-      if (!literal_type_p (type))
-       {
-         error ("%qT is not a valid type for a template non-type parameter "
-                "because it is not literal", type);
-         explain_non_literal_class (type);
-         return true;
-       }
-      if (cp_has_mutable_p (type))
+      if (!structural_type_p (type))
        {
-         error ("%qT is not a valid type for a template non-type parameter "
-                "because it has a mutable member", type);
+         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;
        }
-      /* FIXME check op<=> and strong structural equality once spaceship is
-        implemented.  */
       return false;
     }
 
@@ -25284,7 +25887,7 @@ dependent_type_p_r (tree type)
 
   /* An alias template specialization can be dependent even if the
      resulting type is not.  */
-  if (dependent_alias_template_spec_p (type))
+  if (dependent_alias_template_spec_p (type, nt_transparent))
     return true;
 
   /* -- a cv-qualified type where the cv-unqualified type is
@@ -25551,7 +26154,14 @@ value_dependent_expression_p (tree expression)
       if (DECL_HAS_VALUE_EXPR_P (expression))
        {
          tree value_expr = DECL_VALUE_EXPR (expression);
-         if (value_dependent_expression_p (value_expr))
+         if (value_dependent_expression_p (value_expr)
+             /* __PRETTY_FUNCTION__ inside a template function is dependent
+                on the name of the function.  */
+             || (DECL_PRETTY_FUNCTION_P (expression)
+                 /* It might be used in a template, but not a template
+                    function, in which case its DECL_VALUE_EXPR will be
+                    "top level".  */
+                 && value_expr == error_mark_node))
            return true;
        }
       return false;
@@ -25706,7 +26316,7 @@ value_dependent_expression_p (tree expression)
       }
 
     case TEMPLATE_ID_EXPR:
-      return variable_concept_p (TREE_OPERAND (expression, 0));
+      return concept_definition_p (TREE_OPERAND (expression, 0));
 
     case CONSTRUCTOR:
       {
@@ -26106,14 +26716,14 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
       return *tp;
 
     case CALL_EXPR:
-      /* Treat calls to function concepts as dependent. */
-      if (function_concept_check_p (*tp))
+      /* Treat concept checks as dependent. */
+      if (concept_check_p (*tp))
         return *tp;
       break;
 
     case TEMPLATE_ID_EXPR:
-      /* And variable concepts.  */
-      if (variable_concept_p (TREE_OPERAND (*tp, 0)))
+      /* Treat concept checks as dependent.  */
+      if (concept_check_p (*tp))
        return *tp;
       break;
 
@@ -26593,7 +27203,7 @@ resolve_typename_type (tree type, bool only_current_p)
 
             [temp.names]: In a qualified-id of a declarator-id, the keyword
             template shall not appear at the top level.  */
-         pedwarn (cp_expr_loc_or_loc (fullname, input_location), OPT_Wpedantic,
+         pedwarn (cp_expr_loc_or_input_loc (fullname), OPT_Wpedantic,
                   "keyword %<template%> not allowed in declarator-id");
          tmpl = decl;
        }
@@ -26651,9 +27261,9 @@ build_non_dependent_expr (tree expr)
       /* Don't do this during nsdmi parsing as it can lead to
         unexpected recursive instantiations.  */
       && !parsing_nsdmi ()
-      /* Don't do this during concept expansion either and for
+      /* Don't do this during concept processing either and for
          the same reason.  */
-      && !expanding_concept ())
+      && !processing_constraint_expression_p ())
     fold_non_dependent_expr (expr, tf_none);
 
   STRIP_ANY_LOCATION_WRAPPER (expr);
@@ -26703,7 +27313,7 @@ build_non_dependent_expr (tree expr)
   if (TREE_CODE (expr) == COND_EXPR)
     return build3 (COND_EXPR,
                   TREE_TYPE (expr),
-                  TREE_OPERAND (expr, 0),
+                  build_non_dependent_expr (TREE_OPERAND (expr, 0)),
                   (TREE_OPERAND (expr, 1)
                    ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
                    : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
@@ -26749,8 +27359,7 @@ static tree
 make_auto_1 (tree name, bool set_canonical)
 {
   tree au = cxx_make_type (TEMPLATE_TYPE_PARM);
-  TYPE_NAME (au) = build_decl (input_location,
-                              TYPE_DECL, name, au);
+  TYPE_NAME (au) = build_decl (input_location, TYPE_DECL, name, au);
   TYPE_STUB_DECL (au) = TYPE_NAME (au);
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
@@ -26795,31 +27404,87 @@ template_placeholder_p (tree t)
   return is_auto (t) && CLASS_PLACEHOLDER_TEMPLATE (t);
 }
 
-/* Make a "constrained auto" type-specifier. This is an
-   auto type with constraints that must be associated after
-   deduction.  The constraint is formed from the given
-   CONC and its optional sequence of arguments, which are
-   non-null if written as partial-concept-id.  */
+/* Make a "constrained auto" type-specifier. This is an auto or
+  decltype(auto) type with constraints that must be associated after
+  deduction.  The constraint is formed from the given concept CON
+  and its optional sequence of template arguments ARGS.
 
-tree
-make_constrained_auto (tree con, tree args)
-{
-  tree type = make_auto_1 (auto_identifier, false);
+  TYPE must be the result of make_auto_type or make_decltype_auto_type. */
 
+static tree
+make_constrained_placeholder_type (tree type, tree con, tree args)
+{
   /* Build the constraint. */
   tree tmpl = DECL_TI_TEMPLATE (con);
-  tree expr = VAR_P (con) ? tmpl : ovl_make (tmpl);
-  expr = build_concept_check (expr, type, args);
+  tree expr = tmpl;
+  if (TREE_CODE (con) == FUNCTION_DECL)
+    expr = ovl_make (tmpl);
+  expr = build_concept_check (expr, type, args, tf_warning_or_error);
 
-  tree constr = normalize_expression (expr);
-  PLACEHOLDER_TYPE_CONSTRAINTS (type) = constr;
+  PLACEHOLDER_TYPE_CONSTRAINTS (type) = expr;
 
   /* Our canonical type depends on the constraint.  */
   TYPE_CANONICAL (type) = canonical_type_parameter (type);
 
   /* Attach the constraint to the type declaration. */
-  tree decl = TYPE_NAME (type);
-  return decl;
+  return TYPE_NAME (type);
+}
+
+/* Make a "constrained auto" type-specifier.  */
+
+tree
+make_constrained_auto (tree con, tree args)
+{
+  tree type = make_auto_1 (auto_identifier, false);
+  return make_constrained_placeholder_type (type, con, args);
+}
+
+/* Make a "constrained decltype(auto)" type-specifier.  */
+
+tree
+make_constrained_decltype_auto (tree con, tree args)
+{
+  tree type = make_auto_1 (decltype_auto_identifier, false);
+  /* FIXME: I don't know why this isn't done in make_auto_1.  */
+  AUTO_IS_DECLTYPE (type) = true;
+  return make_constrained_placeholder_type (type, con, args);
+}
+
+/* Build and return a concept definition. Like other templates, the
+   CONCEPT_DECL node is wrapped by a TEMPLATE_DECL.  This returns the
+   the TEMPLATE_DECL. */
+
+tree
+finish_concept_definition (cp_expr id, tree init)
+{
+  gcc_assert (identifier_p (id));
+  gcc_assert (processing_template_decl);
+
+  location_t loc = id.get_location();
+
+  /* A concept-definition shall not have associated constraints.  */
+  if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
+    {
+      error_at (loc, "a concept cannot be constrained");
+      TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = NULL_TREE;
+    }
+
+  /* A concept-definition shall appear in namespace scope.  Templates
+     aren't allowed in block scope, so we only need to check for class
+     scope.  */
+  if (TYPE_P (current_scope()) || !DECL_NAMESPACE_SCOPE_P (current_scope ()))
+    {
+      error_at (loc, "concept %qE not in namespace scope", *id);
+      return error_mark_node;
+    }
+
+  /* Initially build the concept declaration; it's 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;
+
+  /* Push the enclosing template.  */
+  return push_template_decl (decl);
 }
 
 /* Given type ARG, return std::initializer_list<ARG>.  */
@@ -27134,30 +27799,64 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
   return newdecl;
 }
 
+/* As rewrite_template_parm, but for the whole TREE_LIST representing a
+   template parameter.  */
+
+static tree
+rewrite_tparm_list (tree oldelt, unsigned index, unsigned level,
+                   tree targs, unsigned targs_index, tsubst_flags_t complain)
+{
+  tree olddecl = TREE_VALUE (oldelt);
+  tree newdecl = rewrite_template_parm (olddecl, index, level,
+                                       targs, complain);
+  if (newdecl == error_mark_node)
+    return error_mark_node;
+  tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
+                                    targs, complain, NULL_TREE);
+  tree list = build_tree_list (newdef, newdecl);
+  TEMPLATE_PARM_CONSTRAINTS (list)
+    = tsubst_constraint_info (TEMPLATE_PARM_CONSTRAINTS (oldelt),
+                             targs, complain, NULL_TREE);
+  int depth = TMPL_ARGS_DEPTH (targs);
+  TMPL_ARG (targs, depth, targs_index) = template_parm_to_arg (list);
+  return list;
+}
+
 /* Returns a C++17 class deduction guide template based on the constructor
    CTOR.  As a special case, CTOR can be a RECORD_TYPE for an implicit default
-   guide, or REFERENCE_TYPE for an implicit copy/move guide.  */
+   guide, REFERENCE_TYPE for an implicit copy/move guide, or TREE_LIST for an
+   aggregate initialization guide.  */
 
 static tree
-build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
+build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t complain)
 {
-  tree type, tparms, targs, fparms, fargs, ci;
+  tree tparms, targs, fparms, fargs, ci;
   bool memtmpl = false;
   bool explicit_p;
   location_t loc;
   tree fn_tmpl = NULL_TREE;
 
-  if (TYPE_P (ctor))
+  if (outer_args)
+    {
+      ++processing_template_decl;
+      type = tsubst (type, outer_args, complain, CLASSTYPE_TI_TEMPLATE (type));
+      --processing_template_decl;
+    }
+
+  if (!DECL_DECLARES_FUNCTION_P (ctor))
     {
-      type = ctor;
-      bool copy_p = TYPE_REF_P (type);
-      if (copy_p)
+      if (TYPE_P (ctor))
        {
-         type = TREE_TYPE (type);
-         fparms = tree_cons (NULL_TREE, type, void_list_node);
+         bool copy_p = TYPE_REF_P (ctor);
+         if (copy_p)
+           fparms = tree_cons (NULL_TREE, type, void_list_node);
+         else
+           fparms = void_list_node;
        }
+      else if (TREE_CODE (ctor) == TREE_LIST)
+       fparms = ctor;
       else
-       fparms = void_list_node;
+       gcc_unreachable ();
 
       tree ctmpl = CLASSTYPE_TI_TEMPLATE (type);
       tparms = DECL_TEMPLATE_PARMS (ctmpl);
@@ -27179,8 +27878,6 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
        fn_tmpl = tsubst (fn_tmpl, outer_args, complain, ctor);
       ctor = DECL_TEMPLATE_RESULT (fn_tmpl);
 
-      type = DECL_CONTEXT (ctor);
-
       tparms = DECL_TEMPLATE_PARMS (fn_tmpl);
       /* If type is a member class template, DECL_TI_ARGS (ctor) will have
         fully specialized args for the enclosing class.  Strip those off, as
@@ -27238,19 +27935,12 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
              unsigned index = i + clen;
              unsigned level = 1;
              tree oldelt = TREE_VEC_ELT (ftparms, i);
-             tree olddecl = TREE_VALUE (oldelt);
-             tree newdecl = rewrite_template_parm (olddecl, index, level,
-                                                   tsubst_args, complain);
-             if (newdecl == error_mark_node)
+             tree newelt
+               = rewrite_tparm_list (oldelt, index, level,
+                                     tsubst_args, i, complain);
+             if (newelt == error_mark_node)
                ok = false;
-             tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
-                                                tsubst_args, complain, ctor);
-             tree list = build_tree_list (newdef, newdecl);
-             TEMPLATE_PARM_CONSTRAINTS (list)
-               = tsubst_constraint_info (TEMPLATE_PARM_CONSTRAINTS (oldelt),
-                                         tsubst_args, complain, ctor);
-             TREE_VEC_ELT (new_vec, index) = list;
-             TMPL_ARG (tsubst_args, depth, i) = template_parm_to_arg (list);
+             TREE_VEC_ELT (new_vec, index) = newelt;
            }
 
          /* Now we have a final set of template parms to substitute into the
@@ -27301,77 +27991,476 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
   return ded_tmpl;
 }
 
-/* Deduce template arguments for the class template placeholder PTYPE for
-   template TMPL based on the initializer INIT, and return the resulting
-   type.  */
+/* Add to LIST the member types for the reshaped initializer CTOR.  */
 
 static tree
-do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
-                   tsubst_flags_t complain)
+collect_ctor_idx_types (tree ctor, tree list)
 {
-  if (!DECL_CLASS_TEMPLATE_P (tmpl))
+  vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (ctor);
+  tree idx, val; unsigned i;
+  FOR_EACH_CONSTRUCTOR_ELT (v, i, idx, val)
     {
-      /* We should have handled this in the caller.  */
-      if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
-       return ptype;
-      if (complain & tf_error)
-       error ("non-class template %qT used without template arguments", tmpl);
-      return error_mark_node;
+      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);
     }
-  if (init && TREE_TYPE (init) == ptype)
-    /* Using the template parm as its own argument.  */
-    return ptype;
+
+  return list;
+}
+
+/* Return whether ETYPE is, or is derived from, a specialization of TMPL.  */
+
+static bool
+is_spec_or_derived (tree etype, tree tmpl)
+{
+  if (!etype || !CLASS_TYPE_P (etype))
+    return false;
 
   tree type = TREE_TYPE (tmpl);
+  tree tparms = (INNERMOST_TEMPLATE_PARMS
+                (DECL_TEMPLATE_PARMS (tmpl)));
+  tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
+  int err = unify (tparms, targs, type, etype,
+                  UNIFY_ALLOW_DERIVED, /*explain*/false);
+  ggc_free (targs);
+  return !err;
+}
 
-  bool try_list_ctor = false;
+/* Return a C++20 aggregate deduction candidate for TYPE initialized from
+   INIT.  */
 
-  releasing_vec rv_args = NULL;
-  vec<tree,va_gc> *&args = *&rv_args;
-  if (init == NULL_TREE
-      || TREE_CODE (init) == TREE_LIST)
-    args = make_tree_vector_from_list (init);
-  else if (BRACE_ENCLOSED_INITIALIZER_P (init))
+static tree
+maybe_aggr_guide (tree tmpl, tree init, vec<tree,va_gc> *args)
+{
+  if (cxx_dialect < cxx2a)
+    return NULL_TREE;
+
+  if (init == NULL_TREE)
+    return NULL_TREE;
+
+  tree type = TREE_TYPE (tmpl);
+  if (!CP_AGGREGATE_TYPE_P (type))
+    return NULL_TREE;
+
+  /* No aggregate candidate for copy-initialization.  */
+  if (args->length() == 1)
     {
-      try_list_ctor = TYPE_HAS_LIST_CTOR (type);
-      if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
-       {
-         /* As an exception, the first phase in 16.3.1.7 (considering the
-            initializer list as a single argument) is omitted if the
-            initializer list consists of a single expression of type cv U,
-            where U is a specialization of C or a class derived from a
-            specialization of C.  */
-         tree elt = CONSTRUCTOR_ELT (init, 0)->value;
-         if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+      tree val = (*args)[0];
+      if (is_spec_or_derived (tmpl, TREE_TYPE (val)))
+       return NULL_TREE;
+    }
+
+  /* If we encounter a problem, we just won't add the candidate.  */
+  tsubst_flags_t complain = tf_none;
+
+  tree parms = NULL_TREE;
+  if (TREE_CODE (init) == CONSTRUCTOR)
+    {
+      init = reshape_init (type, init, complain);
+      if (init == error_mark_node)
+       return NULL_TREE;
+      parms = collect_ctor_idx_types (init, parms);
+    }
+  else if (TREE_CODE (init) == TREE_LIST)
+    {
+      int len = list_length (init);
+      for (tree field = TYPE_FIELDS (type);
+          len;
+          --len, field = DECL_CHAIN (field))
+       {
+         field = next_initializable_field (field);
+         if (!field)
+           return NULL_TREE;
+         tree ftype = finish_decltype_type (field, true, complain);
+         parms = tree_cons (NULL_TREE, ftype, parms);
+       }
+    }
+  else
+    /* Aggregate initialization doesn't apply to an initializer expression.  */
+    return NULL_TREE;
+
+  if (parms)
+    {
+      tree last = parms;
+      parms = nreverse (parms);
+      TREE_CHAIN (last) = void_list_node;
+      tree guide = build_deduction_guide (type, parms, NULL_TREE, complain);
+      return guide;
+    }
+
+  return NULL_TREE;
+}
+
+/* UGUIDES are the deduction guides for the underlying template of alias
+   template TMPL; adjust them to be deduction guides for TMPL.  */
+
+static tree
+alias_ctad_tweaks (tree tmpl, tree uguides)
+{
+  /* [over.match.class.deduct]: When resolving a placeholder for a deduced
+     class type (9.2.8.2) where the template-name names an alias template A,
+     the defining-type-id of A must be of the form
+
+     typename(opt) nested-name-specifier(opt) template(opt) simple-template-id
+
+     as specified in 9.2.8.2. The guides of A are the set of functions or
+     function templates formed as follows. For each function or function
+     template f in the guides of the template named by the simple-template-id
+     of the defining-type-id, the template arguments of the return type of f
+     are deduced from the defining-type-id of A according to the process in
+     13.10.2.5 with the exception that deduction does not fail if not all
+     template arguments are deduced. Let g denote the result of substituting
+     these deductions into f. If substitution succeeds, form a function or
+     function template f' with the following properties and add it to the set
+     of guides of A:
+
+     * The function type of f' is the function type of g.
+
+     * If f is a function template, f' is a function template whose template
+     parameter list consists of all the template parameters of A (including
+     their default template arguments) that appear in the above deductions or
+     (recursively) in their default template arguments, followed by the
+     template parameters of f that were not deduced (including their default
+     template arguments), otherwise f' is not a function template.
+
+     * The associated constraints (13.5.2) are the conjunction of the
+     associated constraints of g and a constraint that is satisfied if and only
+     if the arguments of A are deducible (see below) from the return type.
+
+     * If f is a copy deduction candidate (12.4.1.8), then f' is considered to
+     be so as well.
+
+     * If f was generated from a deduction-guide (12.4.1.8), then f' is
+     considered to be so as well.
+
+     * The explicit-specifier of f' is the explicit-specifier of g (if
+     any).  */
+
+  /* This implementation differs from the above in two significant ways:
+
+     1) We include all template parameters of A, not just some.
+     2) The added constraint is same_type instead of deducible.
+
+     I believe that while it's probably possible to construct a testcase that
+     behaves differently with this simplification, it should have the same
+     effect for real uses.  Including all template parameters means that we
+     deduce all parameters of A when resolving the call, so when we're in the
+     constraint we don't need to deduce them again, we can just check whether
+     the deduction produced the desired result.  */
+
+  tsubst_flags_t complain = tf_warning_or_error;
+  tree atype = TREE_TYPE (tmpl);
+  tree aguides = NULL_TREE;
+  tree atparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+  unsigned natparms = TREE_VEC_LENGTH (atparms);
+  tree utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+  for (ovl_iterator iter (uguides); iter; ++iter)
+    {
+      tree f = *iter;
+      tree in_decl = f;
+      location_t loc = DECL_SOURCE_LOCATION (f);
+      tree ret = TREE_TYPE (TREE_TYPE (f));
+      tree fprime = f;
+      if (TREE_CODE (f) == TEMPLATE_DECL)
+       {
+         processing_template_decl_sentinel ptds (/*reset*/false);
+         ++processing_template_decl;
+
+         /* Deduce template arguments for f from the type-id of A.  */
+         tree ftparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (f));
+         unsigned len = TREE_VEC_LENGTH (ftparms);
+         tree targs = make_tree_vec (len);
+         int err = unify (ftparms, targs, ret, utype, UNIFY_ALLOW_NONE, false);
+         gcc_assert (!err);
+
+         /* The number of parms for f' is the number of parms for A plus
+            non-deduced parms of f.  */
+         unsigned ndlen = 0;
+         unsigned j;
+         for (unsigned i = 0; i < len; ++i)
+           if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+             ++ndlen;
+         tree gtparms = make_tree_vec (natparms + ndlen);
+
+         /* First copy over the parms of A.  */
+         for (j = 0; j < natparms; ++j)
+           TREE_VEC_ELT (gtparms, j) = TREE_VEC_ELT (atparms, j);
+         /* Now rewrite the non-deduced parms of f.  */
+         for (unsigned i = 0; ndlen && i < len; ++i)
+           if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+             {
+               --ndlen;
+               unsigned index = j++;
+               unsigned level = 1;
+               tree oldlist = TREE_VEC_ELT (ftparms, i);
+               tree list = rewrite_tparm_list (oldlist, index, level,
+                                               targs, i, complain);
+               TREE_VEC_ELT (gtparms, index) = list;
+             }
+         gtparms = build_tree_list (size_one_node, gtparms);
+
+         /* Substitute the deduced arguments plus the rewritten template
+            parameters into f to get g.  This covers the type, copyness,
+            guideness, and explicit-specifier.  */
+         tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain);
+         if (g == error_mark_node)
+           return error_mark_node;
+         DECL_USE_TEMPLATE (g) = 0;
+         fprime = build_template_decl (g, gtparms, false);
+         DECL_TEMPLATE_RESULT (fprime) = g;
+         TREE_TYPE (fprime) = TREE_TYPE (g);
+         tree gtargs = template_parms_to_args (gtparms);
+         DECL_TEMPLATE_INFO (g) = build_template_info (fprime, gtargs);
+         DECL_PRIMARY_TEMPLATE (fprime) = fprime;
+
+         /* Substitute the associated constraints.  */
+         tree ci = get_constraints (f);
+         if (ci)
+           ci = tsubst_constraint_info (ci, targs, complain, in_decl);
+         if (ci == error_mark_node)
+           return error_mark_node;
+
+         /* Add a constraint that the return type matches the instantiation of
+            A with the same template arguments.  */
+         ret = TREE_TYPE (TREE_TYPE (fprime));
+         if (!same_type_p (atype, ret)
+             /* FIXME this should mean they don't compare as equivalent.  */
+             || dependent_alias_template_spec_p (atype, nt_opaque))
            {
-             tree etype = TREE_TYPE (elt);
-             tree tparms = (INNERMOST_TEMPLATE_PARMS
-                            (DECL_TEMPLATE_PARMS (tmpl)));
-             tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
-             int err = unify (tparms, targs, type, etype,
-                              UNIFY_ALLOW_DERIVED, /*explain*/false);
-             if (err == 0)
-               try_list_ctor = false;
-             ggc_free (targs);
+             tree same = finish_trait_expr (loc, CPTK_IS_SAME_AS, atype, ret);
+             ci = append_constraint (ci, same);
            }
+
+         if (ci)
+           set_constraints (fprime, ci);
+       }
+      else
+       {
+         /* For a non-template deduction guide, if the arguments of A aren't
+            deducible from the return type, don't add the candidate.  */
+         tree targs = make_tree_vec (natparms);
+         int err = unify (atparms, targs, utype, ret, UNIFY_ALLOW_NONE, false);
+         for (unsigned i = 0; !err && i < natparms; ++i)
+           if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+             err = true;
+         if (err)
+           continue;
+       }
+
+      aguides = lookup_add (fprime, aguides);
+    }
+
+  return aguides;
+}
+
+/* Return artificial deduction guides built from the constructors of class
+   template TMPL.  */
+
+static tree
+ctor_deduction_guides_for (tree tmpl, tsubst_flags_t complain)
+{
+  tree type = TREE_TYPE (tmpl);
+  tree outer_args = NULL_TREE;
+  if (DECL_CLASS_SCOPE_P (tmpl)
+      && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl)))
+    {
+      outer_args = CLASSTYPE_TI_ARGS (DECL_CONTEXT (tmpl));
+      type = TREE_TYPE (most_general_template (tmpl));
+    }
+
+  tree cands = NULL_TREE;
+
+  for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
+    {
+      /* Skip inherited constructors.  */
+      if (iter.using_p ())
+       continue;
+
+      tree guide = build_deduction_guide (type, *iter, outer_args, complain);
+      cands = lookup_add (guide, cands);
+    }
+
+  /* Add implicit default constructor deduction guide.  */
+  if (!TYPE_HAS_USER_CONSTRUCTOR (type))
+    {
+      tree guide = build_deduction_guide (type, type, outer_args,
+                                         complain);
+      cands = lookup_add (guide, cands);
+    }
+
+  /* Add copy guide.  */
+  {
+    tree gtype = build_reference_type (type);
+    tree guide = build_deduction_guide (type, gtype, outer_args,
+                                       complain);
+    cands = lookup_add (guide, cands);
+  }
+
+  return cands;
+}
+
+static GTY((deletable)) hash_map<tree, tree_pair_p> *dguide_cache;
+
+/* Return the non-aggregate deduction guides for deducible template TMPL.  The
+   aggregate candidate is added separately because it depends on the
+   initializer.  */
+
+static tree
+deduction_guides_for (tree tmpl, tsubst_flags_t complain)
+{
+  tree guides = NULL_TREE;
+  if (DECL_ALIAS_TEMPLATE_P (tmpl))
+    {
+      tree under = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+      tree tinfo = get_template_info (under);
+      guides = deduction_guides_for (TI_TEMPLATE (tinfo), complain);
+    }
+  else
+    {
+      guides = lookup_qualified_name (CP_DECL_CONTEXT (tmpl),
+                                     dguide_name (tmpl),
+                                     /*type*/false, /*complain*/false,
+                                     /*hidden*/false);
+      if (guides == error_mark_node)
+       guides = NULL_TREE;
+    }
+
+  /* Cache the deduction guides for a template.  We also remember the result of
+     lookup, and rebuild everything if it changes; should be very rare.  */
+  tree_pair_p cache = NULL;
+  if (tree_pair_p &r
+      = hash_map_safe_get_or_insert<hm_ggc> (dguide_cache, tmpl))
+    {
+      cache = r;
+      if (cache->purpose == guides)
+       return cache->value;
+    }
+  else
+    {
+      r = cache = ggc_cleared_alloc<tree_pair_s> ();
+      cache->purpose = guides;
+    }
+
+  tree cands = NULL_TREE;
+  if (DECL_ALIAS_TEMPLATE_P (tmpl))
+    cands = alias_ctad_tweaks (tmpl, guides);
+  else
+    {
+      cands = ctor_deduction_guides_for (tmpl, complain);
+      for (ovl_iterator it (guides); it; ++it)
+       cands = lookup_add (*it, cands);
+    }
+
+  cache->value = cands;
+  return cands;
+}
+
+/* Return whether TMPL is a (class template argument-) deducible template.  */
+
+bool
+ctad_template_p (tree tmpl)
+{
+  /* A deducible template is either a class template or is an alias template
+     whose defining-type-id is of the form
+
+      typename(opt) nested-name-specifier(opt) template(opt) simple-template-id
+
+     where the nested-name-specifier (if any) is non-dependent and the
+     template-name of the simple-template-id names a deducible template.  */
+
+  if (DECL_CLASS_TEMPLATE_P (tmpl)
+      || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
+    return true;
+  if (!DECL_ALIAS_TEMPLATE_P (tmpl))
+    return false;
+  tree orig = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+  if (tree tinfo = get_template_info (orig))
+    return ctad_template_p (TI_TEMPLATE (tinfo));
+  return false;
+}
+
+/* Deduce template arguments for the class template placeholder PTYPE for
+   template TMPL based on the initializer INIT, and return the resulting
+   type.  */
+
+static tree
+do_class_deduction (tree ptype, tree tmpl, tree init,
+                   int flags, tsubst_flags_t complain)
+{
+  /* We should have handled this in the caller.  */
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
+    return ptype;
+
+  /* Look through alias templates that just rename another template.  */
+  tmpl = get_underlying_template (tmpl);
+  if (!ctad_template_p (tmpl))
+    {
+      if (complain & tf_error)
+       error ("non-deducible template %qT used without template arguments", tmpl);
+      return error_mark_node;
+    }
+  else if (cxx_dialect < cxx2a && DECL_ALIAS_TEMPLATE_P (tmpl))
+    {
+      /* This doesn't affect conforming C++17 code, so just pedwarn.  */
+      if (complain & tf_warning_or_error)
+       pedwarn (input_location, 0, "alias template deduction only available "
+                "with %<-std=c++2a%> or %<-std=gnu++2a%>");
+    }
+
+  if (init && TREE_TYPE (init) == ptype)
+    /* Using the template parm as its own argument.  */
+    return ptype;
+
+  tree type = TREE_TYPE (tmpl);
+
+  bool try_list_ctor = false;
+
+  releasing_vec rv_args = NULL;
+  vec<tree,va_gc> *&args = *&rv_args;
+  if (init == NULL_TREE)
+    args = make_tree_vector ();
+  else if (BRACE_ENCLOSED_INITIALIZER_P (init))
+    {
+      try_list_ctor = TYPE_HAS_LIST_CTOR (type);
+      if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
+       {
+         /* As an exception, the first phase in 16.3.1.7 (considering the
+            initializer list as a single argument) is omitted if the
+            initializer list consists of a single expression of type cv U,
+            where U is a specialization of C or a class derived from a
+            specialization of C.  */
+         tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+         if (is_spec_or_derived (TREE_TYPE (elt), tmpl))
+           try_list_ctor = false;
        }
       if (try_list_ctor || is_std_init_list (type))
        args = make_tree_vector_single (init);
       else
        args = make_tree_vector_from_ctor (init);
     }
+  else if (TREE_CODE (init) == TREE_LIST)
+    args = make_tree_vector_from_list (init);
   else
     args = make_tree_vector_single (init);
 
-  tree dname = dguide_name (tmpl);
-  tree cands = lookup_qualified_name (CP_DECL_CONTEXT (tmpl), dname,
-                                     /*type*/false, /*complain*/false,
-                                     /*hidden*/false);
-  bool elided = false;
+  /* Do this now to avoid problems with erroneous args later on.  */
+  args = resolve_args (args, complain);
+  if (args == NULL)
+    return error_mark_node;
+
+  tree cands = deduction_guides_for (tmpl, complain);
   if (cands == error_mark_node)
-    cands = NULL_TREE;
+    return error_mark_node;
 
   /* Prune explicit deduction guides in copy-initialization context.  */
+  bool elided = false;
   if (flags & LOOKUP_ONLYCONVERTING)
     {
       for (lkp_iterator iter (cands); !elided && iter; ++iter)
@@ -27390,33 +28479,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
        }
     }
 
-  tree outer_args = NULL_TREE;
-  if (DECL_CLASS_SCOPE_P (tmpl)
-      && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl)))
-    {
-      outer_args = CLASSTYPE_TI_ARGS (DECL_CONTEXT (tmpl));
-      type = TREE_TYPE (most_general_template (tmpl));
-    }
-
-  bool saw_ctor = false;
-  // FIXME cache artificial deduction guides
-  for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
-    {
-      /* Skip inherited constructors.  */
-      if (iter.using_p ())
-       continue;
-
-      tree guide = build_deduction_guide (*iter, outer_args, complain);
-      if (guide == error_mark_node)
-       return error_mark_node;
-      if ((flags & LOOKUP_ONLYCONVERTING)
-         && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
-       elided = true;
-      else
-       cands = lookup_add (guide, cands);
-
-      saw_ctor = true;
-    }
+  if (tree guide = maybe_aggr_guide (tmpl, init, args))
+    cands = lookup_add (guide, cands);
 
   tree call = error_mark_node;
 
@@ -27445,27 +28509,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
        }
     }
 
-  /* Maybe generate an implicit deduction guide.  */
-  if (call == error_mark_node && args->length () < 2)
-    {
-      tree gtype = NULL_TREE;
-
-      if (args->length () == 1)
-       /* Generate a copy guide.  */
-       gtype = build_reference_type (type);
-      else if (!saw_ctor)
-       /* Generate a default guide.  */
-       gtype = type;
-
-      if (gtype)
-       {
-         tree guide = build_deduction_guide (gtype, outer_args, complain);
-         if (guide == error_mark_node)
-           return error_mark_node;
-         cands = lookup_add (guide, cands);
-       }
-    }
-
   if (elided && !cands)
     {
       error ("cannot deduce template arguments for copy-initialization"
@@ -27487,7 +28530,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
       --cp_unevaluated_operand;
     }
 
-  if (call == error_mark_node && (complain & tf_warning_or_error))
+  if (call == error_mark_node
+      && (complain & tf_warning_or_error))
     {
       error ("class template argument deduction failed:");
 
@@ -27602,6 +28646,9 @@ do_auto_deduction (tree type, tree init, tree auto_node,
     }
   else
     {
+      if (error_operand_p (init))
+       return error_mark_node;
+
       tree parms = build_tree_list (NULL_TREE, type);
       tree tparms;
 
@@ -27647,13 +28694,17 @@ do_auto_deduction (tree type, tree init, tree auto_node,
 
   /* Check any placeholder constraints against the deduced type. */
   if (flag_concepts && !processing_template_decl)
-    if (tree constr = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (auto_node)))
+    if (tree check = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (auto_node)))
       {
         /* Use the deduced type to check the associated constraints. If we
            have a partial-concept-id, rebuild the argument list so that
            we check using the extra arguments. */
-        gcc_assert (TREE_CODE (constr) == CHECK_CONSTR);
-        tree cargs = CHECK_CONSTR_ARGS (constr);
+       check = unpack_concept_check (check);
+       gcc_assert (TREE_CODE (check) == TEMPLATE_ID_EXPR);
+       tree cdecl = TREE_OPERAND (check, 0);
+       if (OVL_P (cdecl))
+         cdecl = OVL_FIRST (cdecl);
+        tree cargs = TREE_OPERAND (check, 1);
         if (TREE_VEC_LENGTH (cargs) > 1)
           {
             cargs = copy_node (cargs);
@@ -27661,7 +28712,11 @@ do_auto_deduction (tree type, tree init, tree auto_node,
           }
         else
           cargs = targs;
-        if (!constraints_satisfied_p (constr, cargs))
+
+       /* Rebuild the check using the deduced arguments.  */
+       check = build_concept_check (cdecl, cargs, tf_none);
+
+       if (!constraints_satisfied_p (check))
           {
             if (complain & tf_warning_or_error)
               {
@@ -27686,7 +28741,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
                            "placeholder constraints");
                     break;
                   }
-                diagnose_constraints (input_location, constr, targs);
+               diagnose_constraints (input_location, check, targs);
               }
             return error_mark_node;
           }
@@ -27927,6 +28982,23 @@ append_type_to_template_for_access_check (tree templ,
                                              scope, location);
 }
 
+/* Recursively walk over && expressions searching for EXPR. Return a reference
+   to that expression.  */
+
+static tree *find_template_requirement (tree *t, tree key)
+{
+  if (*t == key)
+    return t;
+  if (TREE_CODE (*t) == TRUTH_ANDIF_EXPR)
+    {
+      if (tree *p = find_template_requirement (&TREE_OPERAND (*t, 0), key))
+       return p;
+      if (tree *p = find_template_requirement (&TREE_OPERAND (*t, 1), key))
+       return p;
+    }
+  return 0;
+}
+
 /* Convert the generic type parameters in PARM that match the types given in the
    range [START_IDX, END_IDX) from the current_template_parms into generic type
    packs.  */
@@ -27948,20 +29020,38 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
       /* Create a distinct parameter pack type from the current parm and add it
         to the replacement args to tsubst below into the generic function
         parameter.  */
-
-      tree o = TREE_TYPE (TREE_VALUE
-                         (TREE_VEC_ELT (current, i)));
+      tree node = TREE_VEC_ELT (current, i);
+      tree o = TREE_TYPE (TREE_VALUE (node));
       tree t = copy_type (o);
       TEMPLATE_TYPE_PARM_INDEX (t)
        = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (o),
-                                     o, 0, 0, tf_none);
+                                     t, 0, 0, tf_none);
       TREE_TYPE (TEMPLATE_TYPE_DECL (t)) = t;
       TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);
       TYPE_MAIN_VARIANT (t) = t;
       TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
       TYPE_CANONICAL (t) = canonical_type_parameter (t);
       TREE_VEC_ELT (replacement, i) = t;
-      TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);
+
+      /* Replace the current template parameter with new pack.  */
+      TREE_VALUE (node) = TREE_CHAIN (t);
+
+      /* Surgically adjust the associated constraint of adjusted parameter
+         and it's corresponding contribution to the current template
+         requirements.  */
+      if (tree constr = TEMPLATE_PARM_CONSTRAINTS (node))
+       {
+         tree id = unpack_concept_check (constr);
+         TREE_VEC_ELT (TREE_OPERAND (id, 1), 0) = template_parm_to_arg (t);
+         tree fold = finish_left_unary_fold_expr (constr, TRUTH_ANDIF_EXPR);
+         TEMPLATE_PARM_CONSTRAINTS (node) = fold;
+
+         /* If there was a constraint, we also need to replace that in
+            the template requirements, which we've already built.  */
+         tree *reqs = &TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
+         reqs = find_template_requirement (reqs, constr);
+         *reqs = fold;
+       }
     }
 
   for (int i = end_idx, e = TREE_VEC_LENGTH (current); i < e; ++i)
@@ -27978,332 +29068,6 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
   return tsubst (parm, replacement, tf_none, NULL_TREE);
 }
 
-/* Entries in the decl_constraint hash table. */
-struct GTY((for_user)) constr_entry
-{
-  tree decl;
-  tree ci;
-};
-
-/* Hashing function and equality for constraint entries. */
-struct constr_hasher : ggc_ptr_hash<constr_entry>
-{
-  static hashval_t hash (constr_entry *e)
-  {
-    return (hashval_t)DECL_UID (e->decl);
-  }
-
-  static bool equal (constr_entry *e1, constr_entry *e2)
-  {
-    return e1->decl == e2->decl;
-  }
-};
-
-/* A mapping from declarations to constraint information. Note that
-   both templates and their underlying declarations are mapped to the
-   same constraint information.
-
-   FIXME: This is defined in pt.c because garbage collection
-   code is not being generated for constraint.cc. */
-
-static GTY (()) hash_table<constr_hasher> *decl_constraints;
-
-/* Returns the template constraints of declaration T. If T is not
-   constrained, return NULL_TREE. Note that T must be non-null. */
-
-tree
-get_constraints (tree t)
-{
-  if (!flag_concepts)
-    return NULL_TREE;
-
-  gcc_assert (DECL_P (t));
-  if (TREE_CODE (t) == TEMPLATE_DECL)
-    t = DECL_TEMPLATE_RESULT (t);
-  constr_entry elt = { t, NULL_TREE };
-  constr_entry* found = decl_constraints->find (&elt);
-  if (found)
-    return found->ci;
-  else
-    return NULL_TREE;
-}
-
-/* Associate the given constraint information CI with the declaration
-   T. If T is a template, then the constraints are associated with
-   its underlying declaration. Don't build associations if CI is
-   NULL_TREE.  */
-
-void
-set_constraints (tree t, tree ci)
-{
-  if (!ci)
-    return;
-  gcc_assert (t && flag_concepts);
-  if (TREE_CODE (t) == TEMPLATE_DECL)
-    t = DECL_TEMPLATE_RESULT (t);
-  gcc_assert (!get_constraints (t));
-  constr_entry elt = {t, ci};
-  constr_entry** slot = decl_constraints->find_slot (&elt, INSERT);
-  constr_entry* entry = ggc_alloc<constr_entry> ();
-  *entry = elt;
-  *slot = entry;
-}
-
-/* Remove the associated constraints of the declaration T.  */
-
-void
-remove_constraints (tree t)
-{
-  gcc_assert (DECL_P (t));
-  if (TREE_CODE (t) == TEMPLATE_DECL)
-    t = DECL_TEMPLATE_RESULT (t);
-
-  constr_entry elt = {t, NULL_TREE};
-  constr_entry** slot = decl_constraints->find_slot (&elt, NO_INSERT);
-  if (slot)
-    decl_constraints->clear_slot (slot);
-}
-
-/* Memoized satisfaction results for declarations. This
-   maps the pair (constraint_info, arguments) to the result computed
-   by constraints_satisfied_p.  */
-
-struct GTY((for_user)) constraint_sat_entry
-{
-  tree ci;
-  tree args;
-  tree result;
-};
-
-/* Hashing function and equality for constraint entries. */
-
-struct constraint_sat_hasher : ggc_ptr_hash<constraint_sat_entry>
-{
-  static hashval_t hash (constraint_sat_entry *e)
-  {
-    hashval_t val = iterative_hash_object(e->ci, 0);
-    return iterative_hash_template_arg (e->args, val);
-  }
-
-  static bool equal (constraint_sat_entry *e1, constraint_sat_entry *e2)
-  {
-    return e1->ci == e2->ci && comp_template_args (e1->args, e2->args);
-  }
-};
-
-/* Memoized satisfaction results for concept checks. */
-
-struct GTY((for_user)) concept_spec_entry
-{
-  tree tmpl;
-  tree args;
-  tree result;
-};
-
-/* Hashing function and equality for constraint entries.  */
-
-struct concept_spec_hasher : ggc_ptr_hash<concept_spec_entry>
-{
-  static hashval_t hash (concept_spec_entry *e)
-  {
-    return hash_tmpl_and_args (e->tmpl, e->args);
-  }
-
-  static bool equal (concept_spec_entry *e1, concept_spec_entry *e2)
-  {
-    ++comparing_specializations;
-    bool eq = e1->tmpl == e2->tmpl && comp_template_args (e1->args, e2->args);
-    --comparing_specializations;
-    return eq;
-  }
-};
-
-static GTY (()) hash_table<constraint_sat_hasher> *constraint_memos;
-static GTY (()) hash_table<concept_spec_hasher> *concept_memos;
-
-/* Search for a memoized satisfaction result. Returns one of the
-   truth value nodes if previously memoized, or NULL_TREE otherwise.   */
-
-tree
-lookup_constraint_satisfaction (tree ci, tree args)
-{
-  constraint_sat_entry elt = { ci, args, NULL_TREE };
-  constraint_sat_entry* found = constraint_memos->find (&elt);
-  if (found)
-    return found->result;
-  else
-    return NULL_TREE;
-}
-
-/* Memoize the result of a satisfication test. Returns the saved result.  */
-
-tree
-memoize_constraint_satisfaction (tree ci, tree args, tree result)
-{
-  constraint_sat_entry elt = {ci, args, result};
-  constraint_sat_entry** slot = constraint_memos->find_slot (&elt, INSERT);
-  constraint_sat_entry* entry = ggc_alloc<constraint_sat_entry> ();
-  *entry = elt;
-  *slot = entry;
-  return result;
-}
-
-/* Search for a memoized satisfaction result for a concept. */
-
-tree
-lookup_concept_satisfaction (tree tmpl, tree args)
-{
-  concept_spec_entry elt = { tmpl, args, NULL_TREE };
-  concept_spec_entry* found = concept_memos->find (&elt);
-  if (found)
-    return found->result;
-  else
-    return NULL_TREE;
-}
-
-/* Memoize the result of a concept check. Returns the saved result.  */
-
-tree
-memoize_concept_satisfaction (tree tmpl, tree args, tree result)
-{
-  concept_spec_entry elt = {tmpl, args, result};
-  concept_spec_entry** slot = concept_memos->find_slot (&elt, INSERT);
-  concept_spec_entry* entry = ggc_alloc<concept_spec_entry> ();
-  *entry = elt;
-  *slot = entry;
-  return result;
-}
-
-static GTY (()) hash_table<concept_spec_hasher> *concept_expansions;
-
-/* Returns a prior concept specialization. This returns the substituted
-   and normalized constraints defined by the concept.  */
-
-tree
-get_concept_expansion (tree tmpl, tree args)
-{
-  concept_spec_entry elt = { tmpl, args, NULL_TREE };
-  concept_spec_entry* found = concept_expansions->find (&elt);
-  if (found)
-    return found->result;
-  else
-    return NULL_TREE;
-}
-
-/* Save a concept expansion for later.  */
-
-tree
-save_concept_expansion (tree tmpl, tree args, tree def)
-{
-  concept_spec_entry elt = {tmpl, args, def};
-  concept_spec_entry** slot = concept_expansions->find_slot (&elt, INSERT);
-  concept_spec_entry* entry = ggc_alloc<concept_spec_entry> ();
-  *entry = elt;
-  *slot = entry;
-  return def;
-}
-
-static hashval_t
-hash_subsumption_args (tree t1, tree t2)
-{
-  gcc_assert (TREE_CODE (t1) == CHECK_CONSTR);
-  gcc_assert (TREE_CODE (t2) == CHECK_CONSTR);
-  int val = 0;
-  val = iterative_hash_object (CHECK_CONSTR_CONCEPT (t1), val);
-  val = iterative_hash_template_arg (CHECK_CONSTR_ARGS (t1), val);
-  val = iterative_hash_object (CHECK_CONSTR_CONCEPT (t2), val);
-  val = iterative_hash_template_arg (CHECK_CONSTR_ARGS (t2), val);
-  return val;
-}
-
-/* Compare the constraints of two subsumption entries.  The LEFT1 and
-   LEFT2 arguments comprise the first subsumption pair and the RIGHT1
-   and RIGHT2 arguments comprise the second. These are all CHECK_CONSTRs. */
-
-static bool
-comp_subsumption_args (tree left1, tree left2, tree right1, tree right2)
-{
-  if (CHECK_CONSTR_CONCEPT (left1) == CHECK_CONSTR_CONCEPT (right1))
-    if (CHECK_CONSTR_CONCEPT (left2) == CHECK_CONSTR_CONCEPT (right2))
-      if (comp_template_args (CHECK_CONSTR_ARGS (left1),
-                             CHECK_CONSTR_ARGS (right1)))
-        return comp_template_args (CHECK_CONSTR_ARGS (left2),
-                                  CHECK_CONSTR_ARGS (right2));
-  return false;
-}
-
-/* Key/value pair for learning and memoizing subsumption results. This
-   associates a pair of check constraints (including arguments) with
-   a boolean value indicating the result.  */
-
-struct GTY((for_user)) subsumption_entry
-{
-  tree t1;
-  tree t2;
-  bool result;
-};
-
-/* Hashing function and equality for constraint entries.  */
-
-struct subsumption_hasher : ggc_ptr_hash<subsumption_entry>
-{
-  static hashval_t hash (subsumption_entry *e)
-  {
-    return hash_subsumption_args (e->t1, e->t2);
-  }
-
-  static bool equal (subsumption_entry *e1, subsumption_entry *e2)
-  {
-    ++comparing_specializations;
-    bool eq = comp_subsumption_args(e1->t1, e1->t2, e2->t1, e2->t2);
-    --comparing_specializations;
-    return eq;
-  }
-};
-
-static GTY (()) hash_table<subsumption_hasher> *subsumption_table;
-
-/* Search for a previously cached subsumption result. */
-
-bool*
-lookup_subsumption_result (tree t1, tree t2)
-{
-  subsumption_entry elt = { t1, t2, false };
-  subsumption_entry* found = subsumption_table->find (&elt);
-  if (found)
-    return &found->result;
-  else
-    return 0;
-}
-
-/* Save a subsumption result. */
-
-bool
-save_subsumption_result (tree t1, tree t2, bool result)
-{
-  subsumption_entry elt = {t1, t2, result};
-  subsumption_entry** slot = subsumption_table->find_slot (&elt, INSERT);
-  subsumption_entry* entry = ggc_alloc<subsumption_entry> ();
-  *entry = elt;
-  *slot = entry;
-  return result;
-}
-
-/* Set up the hash table for constraint association. */
-
-void
-init_constraint_processing (void)
-{
-  if (!flag_concepts)
-    return;
-
-  decl_constraints = hash_table<constr_hasher>::create_ggc(37);
-  constraint_memos = hash_table<constraint_sat_hasher>::create_ggc(37);
-  concept_memos = hash_table<concept_spec_hasher>::create_ggc(37);
-  concept_expansions = hash_table<concept_spec_hasher>::create_ggc(37);
-  subsumption_table = hash_table<subsumption_hasher>::create_ggc(37);
-}
-
 /* __integer_pack(N) in a pack expansion expands to a sequence of numbers from
    0..N-1.  */
 
@@ -28316,9 +29080,8 @@ declare_integer_pack (void)
                                                         NULL_TREE),
                               NULL_TREE, ECF_CONST);
   DECL_DECLARED_CONSTEXPR_P (ipfn) = true;
-  DECL_BUILT_IN_CLASS (ipfn) = BUILT_IN_FRONTEND;
-  DECL_FUNCTION_CODE (ipfn)
-    = (enum built_in_function) (int) CP_BUILT_IN_INTEGER_PACK;
+  set_decl_built_in_function (ipfn, BUILT_IN_FRONTEND,
+                             CP_BUILT_IN_INTEGER_PACK);
 }
 
 /* Set up the hash tables for template instantiations.  */