diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 170dafd52c1..9d457e2a2f3 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -292,7 +292,7 @@ abi_check (int ver)
 static tree
 maybe_template_info (const tree decl)
 {
-  if (TREE_CODE (decl) == TYPE_DECL)
+  if (TREE_CODE (decl) == TYPE_DECL && !TYPE_DECL_ALIAS_P (decl))
     {
       /* TYPE_DECLs are handled specially.  Look at its type to decide
 	 if this is a template instantiation.  */
@@ -305,7 +305,7 @@ maybe_template_info (const tree decl)
     {
       /* Check if the template is a primary template.  */
       if (DECL_LANG_SPECIFIC (decl) != NULL
-	  && VAR_OR_FUNCTION_DECL_P (decl)
+	  && (VAR_OR_FUNCTION_DECL_P (decl) || TREE_CODE (decl) == TYPE_DECL)
 	  && DECL_TEMPLATE_INFO (decl)
 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
 	return DECL_TEMPLATE_INFO (decl);
@@ -402,8 +402,8 @@ write_exception_spec (tree spec)
 static inline tree
 canonicalize_for_substitution (tree node)
 {
-  /* For a TYPE_DECL, use the type instead.  */
-  if (TREE_CODE (node) == TYPE_DECL)
+  /* For a non-alias TYPE_DECL, use the type instead.  */
+  if (TREE_CODE (node) == TYPE_DECL && !TYPE_DECL_ALIAS_P (node))
     node = TREE_TYPE (node);
   if (TYPE_P (node)
       && TYPE_CANONICAL (node) != node
@@ -1044,6 +1044,7 @@ decl_mangling_context (tree decl)
     decl = DECL_TEMPLATE_RESULT (decl);
 
   if (TREE_CODE (decl) == TYPE_DECL
+      && !TYPE_DECL_ALIAS_P (decl)
       && LAMBDA_TYPE_P (TREE_TYPE (decl)))
     {
       tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl));
@@ -1588,7 +1589,9 @@ write_unqualified_name (tree decl)
       if (TREE_CODE (decl) == TYPE_DECL
           && TYPE_UNNAMED_P (type))
         write_unnamed_type_name (type);
-      else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (type))
+      else if (TREE_CODE (decl) == TYPE_DECL
+	       && !TYPE_DECL_ALIAS_P (decl)
+	       && LAMBDA_TYPE_P (type))
         write_closure_type_name (type);
       else
         write_source_name (DECL_NAME (decl));
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index cb234b53a55..cba7b97ef70 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15753,6 +15753,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
 	  }
 
 	/* Create a new node for the specialization we need.  */
+	r = copy_decl (t);
 	if (type == NULL_TREE)
 	  {
 	    if (is_typedef_decl (t))
@@ -15766,19 +15767,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
 	    tsubst_flags_t tcomplain = complain;
 	    if (VAR_P (t))
 	      tcomplain |= tf_tst_ok;
+	    bool is_alias
+	      = (is_typedef_decl (t)
+		 && alias_template_specialization_p (TREE_TYPE (t), nt_opaque));
+	    if (is_alias)
+	      start_lambda_scope (r);
 	    type = tsubst (type, args, tcomplain, in_decl);
-	    /* Substituting the type might have recursively instantiated this
-	       same alias (c++/86171).  */
-	    if (use_spec_table && gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl)
-		&& (spec = retrieve_specialization (gen_tmpl, argvec, hash)))
-	      {
-		r = spec;
-		break;
-	      }
+	    if (is_alias)
+	      finish_lambda_scope ();
 	  }
 	if (type == error_mark_node && !(complain & tf_error))
 	  RETURN (error_mark_node);
-	r = copy_decl (t);
 	if (VAR_P (r))
 	  {
 	    DECL_INITIALIZED_P (r) = 0;
@@ -22536,8 +22535,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
 	ctx = tsubst_entering_scope (DECL_CONTEXT (gen_tmpl), targ_ptr,
 				     complain, gen_tmpl);
       push_nested_class (ctx);
-      if (!DECL_ALIAS_TEMPLATE_P (gen_tmpl))
-	start_lambda_scope (TYPE_NAME (ctx));
+      start_lambda_scope (TYPE_NAME (ctx));
     }
 
   tree pattern = DECL_TEMPLATE_RESULT (gen_tmpl);
@@ -22568,8 +22566,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
     fndecl = tsubst_decl (pattern, targ_ptr, complain, /*use_spec_table=*/false);
   if (DECL_CLASS_SCOPE_P (gen_tmpl))
     {
-      if (!DECL_ALIAS_TEMPLATE_P (gen_tmpl))
-	finish_lambda_scope ();
+      finish_lambda_scope ();
       pop_nested_class ();
     }
   pop_from_top_level ();
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx4.C b/gcc/testsuite/g++.dg/abi/lambda-ctx4.C
index d6544a84652..809cace8574 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx4.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx4.C
@@ -1,5 +1,4 @@
 // { dg-do compile { target c++20 } }
-// { dg-additional-options "-fkeep-inline-functions" }
 
 struct S {
   template <int I>
@@ -9,14 +8,22 @@ struct S {
 S::T<0> a;
 S::T<1> b;
 
+template <int I>
+using L = decltype([]{ return I; });
+
+L<0> c;
+L<1> d;
+
 int main() {
   a();
   b();
+  c();
+  d();
 }
 
-// Currently we don't implement any special mangling rules for template aliases
-// (though we probably should; an alias template is a definable item by
-// [basic.def.odr] p1.5 and as such contained lambdas in different TUs should have
-// the same type, see [basic.def.odr] p15.6)
-// { scan_assembler {_ZNK1SUlvE_clEv:} }
-// { scan_assembler {_ZNK1SUlvE0_clEv:} }
+// { dg-final { scan-assembler {_ZNK1S1TILi0EEUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1S1TILi1EEUlvE_clEv:} } }
+
+// namespace-scope aliases don't have LAMBDA_EXPR_EXTRA_CONTEXT properly set
+// { dg-final { scan-assembler {_ZNK1LILi0EEUlvE_clEv:} { xfail *-*-* } } }
+// { dg-final { scan-assembler {_ZNK1LILi1EEUlvE_clEv:} { xfail *-*-* } } }
diff --git a/gcc/testsuite/g++.dg/modules/late-ret-3_a.H b/gcc/testsuite/g++.dg/modules/late-ret-3_a.H
index 54f95db0456..e64a6f340c0 100644
--- a/gcc/testsuite/g++.dg/modules/late-ret-3_a.H
+++ b/gcc/testsuite/g++.dg/modules/late-ret-3_a.H
@@ -17,4 +17,4 @@ auto Bar (const A& arg)
   -> TPL_3<typename TPL_1<decltype(arg)>::type>
   {return 3;}
 
-// { dg-final { scan-lang-dump { Cluster members:\n  \[0\]=decl definition '::template Foo'\n  \[1\]=specialization declaration '::TPL_1<#null#>'\n  \[2\]=specialization declaration '::TPL_3<::TPL_1<#null#>::type>'\n  \[3\]=specialization declaration '::TPL_2<::TPL_1<#null#>::type>'\n  \[4\]=binding '::Foo'\n} module } }
+// { dg-final { scan-lang-dump { Cluster members:\n  \[0\]=decl definition '::template Foo'\n  \[1\]=specialization declaration '::TPL_3<::TPL_1<#null#>::type>'\n  \[2\]=specialization declaration '::TPL_1<#null#>'\n  \[3\]=specialization declaration '::TPL_2<::TPL_1<#null#>::type>'\n  \[4\]=binding '::Foo'\n} module } }
